1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 2014 Adrián Arroyo Calle <adrian.arroyocalle@gmail.com> 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include <errno.h> 26bf215546Sopenharmony_ci#include <dlfcn.h> 27bf215546Sopenharmony_ci#include <stdint.h> 28bf215546Sopenharmony_ci#include <stdio.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "eglconfig.h" 31bf215546Sopenharmony_ci#include "eglcontext.h" 32bf215546Sopenharmony_ci#include "egldevice.h" 33bf215546Sopenharmony_ci#include "egldisplay.h" 34bf215546Sopenharmony_ci#include "egldriver.h" 35bf215546Sopenharmony_ci#include "eglcurrent.h" 36bf215546Sopenharmony_ci#include "egllog.h" 37bf215546Sopenharmony_ci#include "eglsurface.h" 38bf215546Sopenharmony_ci#include "eglimage.h" 39bf215546Sopenharmony_ci#include "egltypedefs.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include <InterfaceKit.h> 42bf215546Sopenharmony_ci#include <OpenGLKit.h> 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#ifdef DEBUG 46bf215546Sopenharmony_ci# define TRACE(x...) printf("egl_haiku: " x) 47bf215546Sopenharmony_ci# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) 48bf215546Sopenharmony_ci#else 49bf215546Sopenharmony_ci# define TRACE(x...) 50bf215546Sopenharmony_ci# define CALLED() 51bf215546Sopenharmony_ci#endif 52bf215546Sopenharmony_ci#define ERROR(x...) printf("egl_haiku: " x) 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci_EGL_DRIVER_STANDARD_TYPECASTS(haiku_egl) 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_cistruct haiku_egl_config 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci _EGLConfig base; 61bf215546Sopenharmony_ci}; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistruct haiku_egl_context 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci _EGLContext ctx; 66bf215546Sopenharmony_ci}; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistruct haiku_egl_surface 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci _EGLSurface surf; 71bf215546Sopenharmony_ci BGLView* gl; 72bf215546Sopenharmony_ci}; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci/** 76bf215546Sopenharmony_ci * Called via eglCreateWindowSurface(), drv->CreateWindowSurface(). 77bf215546Sopenharmony_ci */ 78bf215546Sopenharmony_cistatic _EGLSurface * 79bf215546Sopenharmony_cihaiku_create_window_surface(_EGLDisplay *disp, 80bf215546Sopenharmony_ci _EGLConfig *conf, void *native_window, const EGLint *attrib_list) 81bf215546Sopenharmony_ci{ 82bf215546Sopenharmony_ci CALLED(); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci struct haiku_egl_surface* surface; 85bf215546Sopenharmony_ci surface = (struct haiku_egl_surface*) calloc(1, sizeof (*surface)); 86bf215546Sopenharmony_ci if (!surface) { 87bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "haiku_create_window_surface"); 88bf215546Sopenharmony_ci return NULL; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci if (!_eglInitSurface(&surface->surf, disp, EGL_WINDOW_BIT, 92bf215546Sopenharmony_ci conf, attrib_list, native_window)) { 93bf215546Sopenharmony_ci free(surface); 94bf215546Sopenharmony_ci return NULL; 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci (&surface->surf)->SwapInterval = 1; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci TRACE("Creating window\n"); 100bf215546Sopenharmony_ci BWindow* win = (BWindow*)native_window; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci TRACE("Creating GL view\n"); 103bf215546Sopenharmony_ci surface->gl = new BGLView(win->Bounds(), "OpenGL", B_FOLLOW_ALL_SIDES, 0, 104bf215546Sopenharmony_ci BGL_RGB | BGL_DOUBLE | BGL_ALPHA); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci TRACE("Adding GL\n"); 107bf215546Sopenharmony_ci win->AddChild(surface->gl); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci TRACE("Showing window\n"); 110bf215546Sopenharmony_ci win->Show(); 111bf215546Sopenharmony_ci return &surface->surf; 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_cistatic _EGLSurface * 116bf215546Sopenharmony_cihaiku_create_pixmap_surface(_EGLDisplay *disp, 117bf215546Sopenharmony_ci _EGLConfig *conf, void *native_pixmap, const EGLint *attrib_list) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci return NULL; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic _EGLSurface * 124bf215546Sopenharmony_cihaiku_create_pbuffer_surface(_EGLDisplay *disp, 125bf215546Sopenharmony_ci _EGLConfig *conf, const EGLint *attrib_list) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci return NULL; 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic EGLBoolean 132bf215546Sopenharmony_cihaiku_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci if (_eglPutSurface(surf)) { 135bf215546Sopenharmony_ci // XXX: detach haiku_egl_surface::gl from the native window and destroy it 136bf215546Sopenharmony_ci free(surf); 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci return EGL_TRUE; 139bf215546Sopenharmony_ci} 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_cistatic EGLBoolean 143bf215546Sopenharmony_cihaiku_add_configs_for_visuals(_EGLDisplay *disp) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci CALLED(); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci struct haiku_egl_config* conf; 148bf215546Sopenharmony_ci conf = (struct haiku_egl_config*) calloc(1, sizeof (*conf)); 149bf215546Sopenharmony_ci if (!conf) 150bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "haiku_add_configs_for_visuals"); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci _eglInitConfig(&conf->base, disp, 1); 153bf215546Sopenharmony_ci TRACE("Config inited\n"); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci conf->base.RedSize = 8; 156bf215546Sopenharmony_ci conf->base.BlueSize = 8; 157bf215546Sopenharmony_ci conf->base.GreenSize = 8; 158bf215546Sopenharmony_ci conf->base.LuminanceSize = 0; 159bf215546Sopenharmony_ci conf->base.AlphaSize = 8; 160bf215546Sopenharmony_ci conf->base.ColorBufferType = EGL_RGB_BUFFER; 161bf215546Sopenharmony_ci conf->base.BufferSize = conf->base.RedSize 162bf215546Sopenharmony_ci + conf->base.GreenSize 163bf215546Sopenharmony_ci + conf->base.BlueSize 164bf215546Sopenharmony_ci + conf->base.AlphaSize; 165bf215546Sopenharmony_ci conf->base.ConfigCaveat = EGL_NONE; 166bf215546Sopenharmony_ci conf->base.ConfigID = 1; 167bf215546Sopenharmony_ci conf->base.BindToTextureRGB = EGL_FALSE; 168bf215546Sopenharmony_ci conf->base.BindToTextureRGBA = EGL_FALSE; 169bf215546Sopenharmony_ci conf->base.StencilSize = 0; 170bf215546Sopenharmony_ci conf->base.TransparentType = EGL_NONE; 171bf215546Sopenharmony_ci conf->base.NativeRenderable = EGL_TRUE; // Let's say yes 172bf215546Sopenharmony_ci conf->base.NativeVisualID = 0; // No visual 173bf215546Sopenharmony_ci conf->base.NativeVisualType = EGL_NONE; // No visual 174bf215546Sopenharmony_ci conf->base.RenderableType = 0x8; 175bf215546Sopenharmony_ci conf->base.SampleBuffers = 0; // TODO: How to get the right value ? 176bf215546Sopenharmony_ci conf->base.Samples = conf->base.SampleBuffers == 0 ? 0 : 0; 177bf215546Sopenharmony_ci conf->base.DepthSize = 24; // TODO: How to get the right value ? 178bf215546Sopenharmony_ci conf->base.Level = 0; 179bf215546Sopenharmony_ci conf->base.MaxPbufferWidth = 0; // TODO: How to get the right value ? 180bf215546Sopenharmony_ci conf->base.MaxPbufferHeight = 0; // TODO: How to get the right value ? 181bf215546Sopenharmony_ci conf->base.MaxPbufferPixels = 0; // TODO: How to get the right value ? 182bf215546Sopenharmony_ci conf->base.SurfaceType = EGL_WINDOW_BIT /*| EGL_PIXMAP_BIT | EGL_PBUFFER_BIT*/; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci TRACE("Config configuated\n"); 185bf215546Sopenharmony_ci if (!_eglValidateConfig(&conf->base, EGL_FALSE)) { 186bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "Haiku: failed to validate config"); 187bf215546Sopenharmony_ci goto cleanup; 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci TRACE("Validated config\n"); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci _eglLinkConfig(&conf->base); 192bf215546Sopenharmony_ci if (!_eglGetArraySize(disp->Configs)) { 193bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "Haiku: failed to create any config"); 194bf215546Sopenharmony_ci goto cleanup; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci TRACE("Config successfull\n"); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci return EGL_TRUE; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cicleanup: 201bf215546Sopenharmony_ci free(conf); 202bf215546Sopenharmony_ci return EGL_FALSE; 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ciextern "C" 207bf215546Sopenharmony_ciEGLBoolean 208bf215546Sopenharmony_ciinit_haiku(_EGLDisplay *disp) 209bf215546Sopenharmony_ci{ 210bf215546Sopenharmony_ci _EGLDevice *dev; 211bf215546Sopenharmony_ci CALLED(); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci dev = _eglAddDevice(-1, true); 214bf215546Sopenharmony_ci if (!dev) { 215bf215546Sopenharmony_ci _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); 216bf215546Sopenharmony_ci return EGL_FALSE; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci disp->Device = dev; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci TRACE("Add configs\n"); 221bf215546Sopenharmony_ci if (!haiku_add_configs_for_visuals(disp)) 222bf215546Sopenharmony_ci return EGL_FALSE; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci TRACE("Initialization finished\n"); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci return EGL_TRUE; 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ciextern "C" 231bf215546Sopenharmony_ciEGLBoolean 232bf215546Sopenharmony_cihaiku_terminate(_EGLDisplay *disp) 233bf215546Sopenharmony_ci{ 234bf215546Sopenharmony_ci return EGL_TRUE; 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ciextern "C" 239bf215546Sopenharmony_ci_EGLContext* 240bf215546Sopenharmony_cihaiku_create_context(_EGLDisplay *disp, _EGLConfig *conf, 241bf215546Sopenharmony_ci _EGLContext *share_list, const EGLint *attrib_list) 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci CALLED(); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci struct haiku_egl_context* context; 246bf215546Sopenharmony_ci context = (struct haiku_egl_context*) calloc(1, sizeof (*context)); 247bf215546Sopenharmony_ci if (!context) { 248bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "haiku_create_context"); 249bf215546Sopenharmony_ci return NULL; 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci if (!_eglInitContext(&context->ctx, disp, conf, attrib_list)) 253bf215546Sopenharmony_ci goto cleanup; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci TRACE("Context created\n"); 256bf215546Sopenharmony_ci return &context->ctx; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_cicleanup: 259bf215546Sopenharmony_ci free(context); 260bf215546Sopenharmony_ci return NULL; 261bf215546Sopenharmony_ci} 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ciextern "C" 265bf215546Sopenharmony_ciEGLBoolean 266bf215546Sopenharmony_cihaiku_destroy_context(_EGLDisplay *disp, _EGLContext* ctx) 267bf215546Sopenharmony_ci{ 268bf215546Sopenharmony_ci struct haiku_egl_context* context = haiku_egl_context(ctx); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci if (_eglPutContext(ctx)) { 271bf215546Sopenharmony_ci // XXX: teardown the context ? 272bf215546Sopenharmony_ci free(context); 273bf215546Sopenharmony_ci ctx = NULL; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci return EGL_TRUE; 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ciextern "C" 280bf215546Sopenharmony_ciEGLBoolean 281bf215546Sopenharmony_cihaiku_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, 282bf215546Sopenharmony_ci _EGLSurface *rsurf, _EGLContext *ctx) 283bf215546Sopenharmony_ci{ 284bf215546Sopenharmony_ci CALLED(); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci struct haiku_egl_context* cont = haiku_egl_context(ctx); 287bf215546Sopenharmony_ci struct haiku_egl_surface* surf = haiku_egl_surface(dsurf); 288bf215546Sopenharmony_ci _EGLContext *old_ctx; 289bf215546Sopenharmony_ci _EGLSurface *old_dsurf, *old_rsurf; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 292bf215546Sopenharmony_ci return EGL_FALSE; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci //cont->ctx.DrawSurface=&surf->surf; 295bf215546Sopenharmony_ci surf->gl->LockGL(); 296bf215546Sopenharmony_ci return EGL_TRUE; 297bf215546Sopenharmony_ci} 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ciextern "C" 301bf215546Sopenharmony_ciEGLBoolean 302bf215546Sopenharmony_cihaiku_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci struct haiku_egl_surface* surface = haiku_egl_surface(surf); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci surface->gl->SwapBuffers(); 307bf215546Sopenharmony_ci //gl->Render(); 308bf215546Sopenharmony_ci return EGL_TRUE; 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ciextern "C" 313bf215546Sopenharmony_ciconst _EGLDriver _eglDriver = { 314bf215546Sopenharmony_ci .Initialize = init_haiku, 315bf215546Sopenharmony_ci .Terminate = haiku_terminate, 316bf215546Sopenharmony_ci .CreateContext = haiku_create_context, 317bf215546Sopenharmony_ci .DestroyContext = haiku_destroy_context, 318bf215546Sopenharmony_ci .MakeCurrent = haiku_make_current, 319bf215546Sopenharmony_ci .CreateWindowSurface = haiku_create_window_surface, 320bf215546Sopenharmony_ci .CreatePixmapSurface = haiku_create_pixmap_surface, 321bf215546Sopenharmony_ci .CreatePbufferSurface = haiku_create_pbuffer_surface, 322bf215546Sopenharmony_ci .DestroySurface = haiku_destroy_surface, 323bf215546Sopenharmony_ci .SwapBuffers = haiku_swap_buffers, 324bf215546Sopenharmony_ci}; 325