egl_g3d.c revision b8cb14209a3a694eaaa6451e19d79e5b2f789a30
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.8 4 * 5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#include "egldriver.h" 27#include "eglcurrent.h" 28#include "egllog.h" 29 30#include "pipe/p_screen.h" 31#include "util/u_memory.h" 32#include "util/u_format.h" 33#include "util/u_string.h" 34 35#include "egl_g3d.h" 36#include "egl_g3d_api.h" 37#include "egl_g3d_st.h" 38#include "egl_g3d_loader.h" 39#include "native.h" 40 41/** 42 * Get the native platform. 43 */ 44static const struct native_platform * 45egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) 46{ 47 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 48 49 if (!gdrv->platforms[plat]) { 50 const char *plat_name = NULL; 51 const struct native_platform *nplat = NULL; 52 53 switch (plat) { 54 case _EGL_PLATFORM_WINDOWS: 55 plat_name = "Windows"; 56#ifdef HAVE_GDI_BACKEND 57 nplat = native_get_gdi_platform(); 58#endif 59 break; 60 case _EGL_PLATFORM_X11: 61 plat_name = "X11"; 62#ifdef HAVE_X11_BACKEND 63 nplat = native_get_x11_platform(); 64#endif 65 break; 66 case _EGL_PLATFORM_DRM: 67 plat_name = "DRM"; 68#ifdef HAVE_DRM_BACKEND 69 nplat = native_get_drm_platform(); 70#endif 71 break; 72 case _EGL_PLATFORM_FBDEV: 73 plat_name = "FBDEV"; 74#ifdef HAVE_FBDEV_BACKEND 75 nplat = native_get_fbdev_platform(); 76#endif 77 break; 78 default: 79 break; 80 } 81 82 if (!nplat) 83 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); 84 85 gdrv->platforms[plat] = nplat; 86 } 87 88 return gdrv->platforms[plat]; 89} 90 91#ifdef EGL_MESA_screen_surface 92 93static void 94egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) 95{ 96 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 97 const struct native_connector **native_connectors; 98 EGLint num_connectors, i; 99 100 native_connectors = 101 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL); 102 if (!num_connectors) { 103 if (native_connectors) 104 FREE(native_connectors); 105 return; 106 } 107 108 for (i = 0; i < num_connectors; i++) { 109 const struct native_connector *nconn = native_connectors[i]; 110 struct egl_g3d_screen *gscr; 111 const struct native_mode **native_modes; 112 EGLint num_modes, j; 113 114 /* TODO support for hotplug */ 115 native_modes = 116 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes); 117 if (!num_modes) { 118 if (native_modes) 119 FREE(native_modes); 120 continue; 121 } 122 123 gscr = CALLOC_STRUCT(egl_g3d_screen); 124 if (!gscr) { 125 FREE(native_modes); 126 continue; 127 } 128 129 _eglInitScreen(&gscr->base, dpy, num_modes); 130 for (j = 0; j < gscr->base.NumModes; j++) { 131 const struct native_mode *nmode = native_modes[j]; 132 _EGLMode *mode = &gscr->base.Modes[j]; 133 134 mode->Width = nmode->width; 135 mode->Height = nmode->height; 136 mode->RefreshRate = nmode->refresh_rate; 137 mode->Optimal = EGL_FALSE; 138 mode->Interlaced = EGL_FALSE; 139 /* no need to strdup() */ 140 mode->Name = nmode->desc; 141 } 142 143 gscr->native = nconn; 144 gscr->native_modes = native_modes; 145 146 _eglLinkScreen(&gscr->base); 147 } 148 149 FREE(native_connectors); 150} 151 152#endif /* EGL_MESA_screen_surface */ 153 154/** 155 * Initialize and validate the EGL config attributes. 156 */ 157static EGLBoolean 158init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, 159 EGLint api_mask, enum pipe_format depth_stencil_format, 160 EGLBoolean preserve_buffer, EGLint max_swap_interval) 161{ 162 uint rgba[4], depth_stencil[2], buffer_size; 163 EGLint surface_type; 164 EGLint i; 165 166 /* get the color and depth/stencil component sizes */ 167 assert(nconf->color_format != PIPE_FORMAT_NONE); 168 buffer_size = 0; 169 for (i = 0; i < 4; i++) { 170 rgba[i] = util_format_get_component_bits(nconf->color_format, 171 UTIL_FORMAT_COLORSPACE_RGB, i); 172 buffer_size += rgba[i]; 173 } 174 for (i = 0; i < 2; i++) { 175 if (depth_stencil_format != PIPE_FORMAT_NONE) { 176 depth_stencil[i] = 177 util_format_get_component_bits(depth_stencil_format, 178 UTIL_FORMAT_COLORSPACE_ZS, i); 179 } 180 else { 181 depth_stencil[i] = 0; 182 } 183 } 184 185 surface_type = 0x0; 186 if (nconf->window_bit) 187 surface_type |= EGL_WINDOW_BIT; 188 if (nconf->pixmap_bit) 189 surface_type |= EGL_PIXMAP_BIT; 190#ifdef EGL_MESA_screen_surface 191 if (nconf->scanout_bit) 192 surface_type |= EGL_SCREEN_BIT_MESA; 193#endif 194 195 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 196 surface_type |= EGL_PBUFFER_BIT; 197 198 conf->Conformant = api_mask; 199 conf->RenderableType = api_mask; 200 201 conf->RedSize = rgba[0]; 202 conf->GreenSize = rgba[1]; 203 conf->BlueSize = rgba[2]; 204 conf->AlphaSize = rgba[3]; 205 conf->BufferSize = buffer_size; 206 207 conf->DepthSize = depth_stencil[0]; 208 conf->StencilSize = depth_stencil[1]; 209 210 conf->SurfaceType = surface_type; 211 212 conf->NativeRenderable = EGL_TRUE; 213 if (surface_type & EGL_WINDOW_BIT) { 214 conf->NativeVisualID = nconf->native_visual_id; 215 conf->NativeVisualType = nconf->native_visual_type; 216 } 217 218 if (surface_type & EGL_PBUFFER_BIT) { 219 conf->BindToTextureRGB = EGL_TRUE; 220 if (rgba[3]) 221 conf->BindToTextureRGBA = EGL_TRUE; 222 223 conf->MaxPbufferWidth = 4096; 224 conf->MaxPbufferHeight = 4096; 225 conf->MaxPbufferPixels = 4096 * 4096; 226 } 227 228 conf->Level = nconf->level; 229 conf->Samples = nconf->samples; 230 conf->SampleBuffers = 0; 231 232 if (nconf->slow_config) 233 conf->ConfigCaveat = EGL_SLOW_CONFIG; 234 235 if (nconf->transparent_rgb) { 236 conf->TransparentType = EGL_TRANSPARENT_RGB; 237 conf->TransparentRedValue = nconf->transparent_rgb_values[0]; 238 conf->TransparentGreenValue = nconf->transparent_rgb_values[1]; 239 conf->TransparentBlueValue = nconf->transparent_rgb_values[2]; 240 } 241 242 conf->MinSwapInterval = 0; 243 conf->MaxSwapInterval = max_swap_interval; 244 if (preserve_buffer) 245 conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 246 247 return _eglValidateConfig(conf, EGL_FALSE); 248} 249 250/** 251 * Initialize an EGL config from the native config. 252 */ 253static EGLBoolean 254egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, 255 _EGLConfig *conf, const struct native_config *nconf, 256 enum pipe_format depth_stencil_format, 257 int preserve_buffer, int max_swap_interval) 258{ 259 struct egl_g3d_config *gconf = egl_g3d_config(conf); 260 EGLint buffer_mask, api_mask; 261 EGLBoolean valid; 262 263 /* skip single-buffered configs */ 264 if (!(nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))) 265 return EGL_FALSE; 266 267 buffer_mask = 0x0; 268 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) 269 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 270 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 271 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 272 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) 273 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 274 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) 275 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 276 277 gconf->stvis.buffer_mask = buffer_mask; 278 gconf->stvis.color_format = nconf->color_format; 279 gconf->stvis.depth_stencil_format = depth_stencil_format; 280 gconf->stvis.accum_format = PIPE_FORMAT_NONE; 281 gconf->stvis.samples = nconf->samples; 282 283 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? 284 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; 285 286 api_mask = dpy->ClientAPIsMask; 287 /* this is required by EGL, not by OpenGL ES */ 288 if (nconf->window_bit && 289 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) 290 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); 291 292 if (!api_mask) { 293 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", 294 nconf->native_visual_id); 295 } 296 297 valid = init_config_attributes(&gconf->base, 298 nconf, api_mask, depth_stencil_format, 299 preserve_buffer, max_swap_interval); 300 if (!valid) { 301 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); 302 return EGL_FALSE; 303 } 304 305 gconf->native = nconf; 306 307 return EGL_TRUE; 308} 309 310/** 311 * Get all interested depth/stencil formats of a display. 312 */ 313static EGLint 314egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, 315 enum pipe_format formats[8]) 316{ 317 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 318 struct pipe_screen *screen = gdpy->native->screen; 319 const EGLint candidates[] = { 320 1, PIPE_FORMAT_Z16_UNORM, 321 1, PIPE_FORMAT_Z32_UNORM, 322 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 323 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, 324 0 325 }; 326 const EGLint *fmt = candidates; 327 EGLint count; 328 329 count = 0; 330 formats[count++] = PIPE_FORMAT_NONE; 331 332 while (*fmt) { 333 EGLint i, n = *fmt++; 334 335 /* pick the first supported format */ 336 for (i = 0; i < n; i++) { 337 if (screen->is_format_supported(screen, fmt[i], 338 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) { 339 formats[count++] = fmt[i]; 340 break; 341 } 342 } 343 344 fmt += n; 345 } 346 347 return count; 348} 349 350/** 351 * Add configs to display and return the next config ID. 352 */ 353static EGLint 354egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) 355{ 356 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 357 const struct native_config **native_configs; 358 enum pipe_format depth_stencil_formats[8]; 359 int num_formats, num_configs, i, j; 360 int preserve_buffer, max_swap_interval; 361 362 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); 363 if (!num_configs) { 364 if (native_configs) 365 FREE(native_configs); 366 return id; 367 } 368 369 preserve_buffer = 370 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER); 371 max_swap_interval = 372 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL); 373 374 num_formats = egl_g3d_fill_depth_stencil_formats(dpy, 375 depth_stencil_formats); 376 377 for (i = 0; i < num_configs; i++) { 378 for (j = 0; j < num_formats; j++) { 379 struct egl_g3d_config *gconf; 380 381 gconf = CALLOC_STRUCT(egl_g3d_config); 382 if (gconf) { 383 _eglInitConfig(&gconf->base, dpy, id); 384 if (!egl_g3d_init_config(drv, dpy, &gconf->base, 385 native_configs[i], depth_stencil_formats[j], 386 preserve_buffer, max_swap_interval)) { 387 FREE(gconf); 388 break; 389 } 390 391 _eglLinkConfig(&gconf->base); 392 id++; 393 } 394 } 395 } 396 397 FREE(native_configs); 398 return id; 399} 400 401static void 402egl_g3d_invalid_surface(struct native_display *ndpy, 403 struct native_surface *nsurf, 404 unsigned int seq_num) 405{ 406 /* XXX not thread safe? */ 407 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); 408 struct egl_g3d_context *gctx; 409 410 /* 411 * Some functions such as egl_g3d_copy_buffers create a temporary native 412 * surface. There is no gsurf associated with it. 413 */ 414 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; 415 if (gctx) 416 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); 417} 418 419static struct pipe_screen * 420egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) 421{ 422 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 423 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 424 return gdpy->loader->create_drm_screen(name, fd); 425} 426 427static struct pipe_screen * 428egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) 429{ 430 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 431 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 432 return gdpy->loader->create_sw_screen(ws); 433} 434 435static struct native_event_handler egl_g3d_native_event_handler = { 436 egl_g3d_invalid_surface, 437 egl_g3d_new_drm_screen, 438 egl_g3d_new_sw_screen 439}; 440 441static void 442egl_g3d_free_config(void *conf) 443{ 444 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf); 445 FREE(gconf); 446} 447 448static void 449egl_g3d_free_screen(void *scr) 450{ 451#ifdef EGL_MESA_screen_surface 452 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr); 453 FREE(gscr->native_modes); 454 FREE(gscr); 455#endif 456} 457 458static EGLBoolean 459egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) 460{ 461 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 462 463 _eglReleaseDisplayResources(drv, dpy); 464 465 if (gdpy->pipe) 466 gdpy->pipe->destroy(gdpy->pipe); 467 468 if (dpy->Configs) { 469 _eglDestroyArray(dpy->Configs, egl_g3d_free_config); 470 dpy->Configs = NULL; 471 } 472 if (dpy->Screens) { 473 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen); 474 dpy->Screens = NULL; 475 } 476 477 _eglCleanupDisplay(dpy); 478 479 if (gdpy->smapi) 480 egl_g3d_destroy_st_manager(gdpy->smapi); 481 482 if (gdpy->native) 483 gdpy->native->destroy(gdpy->native); 484 485 FREE(gdpy); 486 dpy->DriverData = NULL; 487 488 return EGL_TRUE; 489} 490 491static EGLBoolean 492egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, 493 EGLint *major, EGLint *minor) 494{ 495 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 496 struct egl_g3d_display *gdpy; 497 const struct native_platform *nplat; 498 499 nplat = egl_g3d_get_platform(drv, dpy->Platform); 500 if (!nplat) 501 return EGL_FALSE; 502 503 gdpy = CALLOC_STRUCT(egl_g3d_display); 504 if (!gdpy) { 505 _eglError(EGL_BAD_ALLOC, "eglInitialize"); 506 goto fail; 507 } 508 gdpy->loader = gdrv->loader; 509 dpy->DriverData = gdpy; 510 511 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); 512 gdpy->native = nplat->create_display(dpy->PlatformDisplay, 513 &egl_g3d_native_event_handler, (void *) dpy); 514 if (!gdpy->native) { 515 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); 516 goto fail; 517 } 518 519 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) 520 dpy->ClientAPIsMask |= EGL_OPENGL_BIT; 521 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK) 522 dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT; 523 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK) 524 dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; 525 if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK) 526 dpy->ClientAPIsMask |= EGL_OPENVG_BIT; 527 528 gdpy->smapi = egl_g3d_create_st_manager(dpy); 529 if (!gdpy->smapi) { 530 _eglError(EGL_NOT_INITIALIZED, 531 "eglInitialize(failed to create st manager)"); 532 goto fail; 533 } 534 535#ifdef EGL_MESA_screen_surface 536 /* enable MESA_screen_surface before adding (and validating) configs */ 537 if (gdpy->native->modeset) { 538 dpy->Extensions.MESA_screen_surface = EGL_TRUE; 539 egl_g3d_add_screens(drv, dpy); 540 } 541#endif 542 543 dpy->Extensions.KHR_image_base = EGL_TRUE; 544 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) 545 dpy->Extensions.KHR_image_pixmap = EGL_TRUE; 546 547 dpy->Extensions.KHR_reusable_sync = EGL_TRUE; 548 dpy->Extensions.KHR_fence_sync = EGL_TRUE; 549 550 dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; 551 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; 552 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE; 553 554 if (dpy->Platform == _EGL_PLATFORM_DRM) { 555 dpy->Extensions.MESA_drm_display = EGL_TRUE; 556 dpy->Extensions.MESA_drm_image = EGL_TRUE; 557 } 558 559 if (egl_g3d_add_configs(drv, dpy, 1) == 1) { 560 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); 561 goto fail; 562 } 563 564 *major = 1; 565 *minor = 4; 566 567 return EGL_TRUE; 568 569fail: 570 if (gdpy) 571 egl_g3d_terminate(drv, dpy); 572 return EGL_FALSE; 573} 574 575static _EGLProc 576egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) 577{ 578 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 579 struct st_api *stapi = NULL; 580 581 if (procname && procname[0] == 'v' && procname[1] == 'g') 582 stapi = gdrv->loader->get_st_api(ST_API_OPENVG); 583 else if (procname && procname[0] == 'g' && procname[1] == 'l') 584 stapi = gdrv->loader->get_st_api(ST_API_OPENGL); 585 586 return (_EGLProc) ((stapi) ? 587 stapi->get_proc_address(stapi, procname) : NULL); 588} 589 590static EGLint 591egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) 592{ 593 return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0; 594} 595 596_EGLDriver * 597egl_g3d_create_driver(const struct egl_g3d_loader *loader) 598{ 599 struct egl_g3d_driver *gdrv; 600 601 gdrv = CALLOC_STRUCT(egl_g3d_driver); 602 if (!gdrv) 603 return NULL; 604 605 gdrv->loader = loader; 606 607 egl_g3d_init_driver_api(&gdrv->base); 608 gdrv->base.API.Initialize = egl_g3d_initialize; 609 gdrv->base.API.Terminate = egl_g3d_terminate; 610 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; 611 612 gdrv->base.Probe = egl_g3d_probe; 613 614 /* to be filled by the caller */ 615 gdrv->base.Name = NULL; 616 gdrv->base.Unload = NULL; 617 618 return &gdrv->base; 619} 620 621void 622egl_g3d_destroy_driver(_EGLDriver *drv) 623{ 624 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 625 FREE(gdrv); 626} 627