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