egl_g3d.c revision 37213ceacc2d7b309de7641da501282f8f24c8c2
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); 130 131 for (j = 0; j < num_modes; j++) { 132 const struct native_mode *nmode = native_modes[j]; 133 _EGLMode *mode; 134 135 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height, 136 nmode->refresh_rate, nmode->desc); 137 if (!mode) 138 break; 139 /* gscr->native_modes and gscr->base.Modes should be consistent */ 140 assert(mode == &gscr->base.Modes[j]); 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{ 161 uint rgba[4], depth_stencil[2], buffer_size; 162 EGLint surface_type; 163 EGLint i; 164 165 /* get the color and depth/stencil component sizes */ 166 assert(nconf->color_format != PIPE_FORMAT_NONE); 167 buffer_size = 0; 168 for (i = 0; i < 4; i++) { 169 rgba[i] = util_format_get_component_bits(nconf->color_format, 170 UTIL_FORMAT_COLORSPACE_RGB, i); 171 buffer_size += rgba[i]; 172 } 173 for (i = 0; i < 2; i++) { 174 if (depth_stencil_format != PIPE_FORMAT_NONE) { 175 depth_stencil[i] = 176 util_format_get_component_bits(depth_stencil_format, 177 UTIL_FORMAT_COLORSPACE_ZS, i); 178 } 179 else { 180 depth_stencil[i] = 0; 181 } 182 } 183 184 surface_type = 0x0; 185 if (nconf->window_bit) 186 surface_type |= EGL_WINDOW_BIT; 187 if (nconf->pixmap_bit) 188 surface_type |= EGL_PIXMAP_BIT; 189#ifdef EGL_MESA_screen_surface 190 if (nconf->scanout_bit) 191 surface_type |= EGL_SCREEN_BIT_MESA; 192#endif 193 194 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 195 surface_type |= EGL_PBUFFER_BIT; 196 197 conf->Conformant = api_mask; 198 conf->RenderableType = api_mask; 199 200 conf->RedSize = rgba[0]; 201 conf->GreenSize = rgba[1]; 202 conf->BlueSize = rgba[2]; 203 conf->AlphaSize = rgba[3]; 204 conf->BufferSize = buffer_size; 205 206 conf->DepthSize = depth_stencil[0]; 207 conf->StencilSize = depth_stencil[1]; 208 209 conf->SurfaceType = surface_type; 210 211 conf->NativeRenderable = EGL_TRUE; 212 if (surface_type & EGL_WINDOW_BIT) { 213 conf->NativeVisualID = nconf->native_visual_id; 214 conf->NativeVisualType = nconf->native_visual_type; 215 } 216 217 if (surface_type & EGL_PBUFFER_BIT) { 218 conf->BindToTextureRGB = EGL_TRUE; 219 if (rgba[3]) 220 conf->BindToTextureRGBA = EGL_TRUE; 221 222 conf->MaxPbufferWidth = 4096; 223 conf->MaxPbufferHeight = 4096; 224 conf->MaxPbufferPixels = 4096 * 4096; 225 } 226 227 conf->Level = nconf->level; 228 conf->Samples = nconf->samples; 229 conf->SampleBuffers = 0; 230 231 if (nconf->slow_config) 232 conf->ConfigCaveat = EGL_SLOW_CONFIG; 233 234 if (nconf->transparent_rgb) { 235 conf->TransparentType = EGL_TRANSPARENT_RGB; 236 conf->TransparentRedValue = nconf->transparent_rgb_values[0]; 237 conf->TransparentGreenValue = nconf->transparent_rgb_values[1]; 238 conf->TransparentBlueValue = nconf->transparent_rgb_values[2]; 239 } 240 241 return _eglValidateConfig(conf, EGL_FALSE); 242} 243 244/** 245 * Initialize an EGL config from the native config. 246 */ 247static EGLBoolean 248egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, 249 _EGLConfig *conf, const struct native_config *nconf, 250 enum pipe_format depth_stencil_format) 251{ 252 struct egl_g3d_config *gconf = egl_g3d_config(conf); 253 EGLint buffer_mask, api_mask; 254 EGLBoolean valid; 255 256 /* skip single-buffered configs */ 257 if (!(nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))) 258 return EGL_FALSE; 259 260 buffer_mask = 0x0; 261 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) 262 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 263 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 264 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 265 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) 266 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 267 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) 268 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 269 270 gconf->stvis.buffer_mask = buffer_mask; 271 gconf->stvis.color_format = nconf->color_format; 272 gconf->stvis.depth_stencil_format = depth_stencil_format; 273 gconf->stvis.accum_format = PIPE_FORMAT_NONE; 274 gconf->stvis.samples = nconf->samples; 275 276 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? 277 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; 278 279 api_mask = dpy->ClientAPIsMask; 280 /* this is required by EGL, not by OpenGL ES */ 281 if (nconf->window_bit && 282 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) 283 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); 284 285 if (!api_mask) { 286 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", 287 nconf->native_visual_id); 288 } 289 290 valid = init_config_attributes(&gconf->base, 291 nconf, api_mask, depth_stencil_format); 292 if (!valid) { 293 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); 294 return EGL_FALSE; 295 } 296 297 gconf->native = nconf; 298 299 return EGL_TRUE; 300} 301 302/** 303 * Get all interested depth/stencil formats of a display. 304 */ 305static EGLint 306egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, 307 enum pipe_format formats[8]) 308{ 309 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 310 struct pipe_screen *screen = gdpy->native->screen; 311 const EGLint candidates[] = { 312 1, PIPE_FORMAT_Z16_UNORM, 313 1, PIPE_FORMAT_Z32_UNORM, 314 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 315 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, 316 0 317 }; 318 const EGLint *fmt = candidates; 319 EGLint count; 320 321 count = 0; 322 formats[count++] = PIPE_FORMAT_NONE; 323 324 while (*fmt) { 325 EGLint i, n = *fmt++; 326 327 /* pick the first supported format */ 328 for (i = 0; i < n; i++) { 329 if (screen->is_format_supported(screen, fmt[i], 330 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) { 331 formats[count++] = fmt[i]; 332 break; 333 } 334 } 335 336 fmt += n; 337 } 338 339 return count; 340} 341 342/** 343 * Add configs to display and return the next config ID. 344 */ 345static EGLint 346egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) 347{ 348 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 349 const struct native_config **native_configs; 350 enum pipe_format depth_stencil_formats[8]; 351 int num_formats, num_configs, i, j; 352 353 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); 354 if (!num_configs) { 355 if (native_configs) 356 FREE(native_configs); 357 return id; 358 } 359 360 num_formats = egl_g3d_fill_depth_stencil_formats(dpy, 361 depth_stencil_formats); 362 363 for (i = 0; i < num_configs; i++) { 364 for (j = 0; j < num_formats; j++) { 365 struct egl_g3d_config *gconf; 366 367 gconf = CALLOC_STRUCT(egl_g3d_config); 368 if (gconf) { 369 _eglInitConfig(&gconf->base, dpy, id); 370 if (!egl_g3d_init_config(drv, dpy, &gconf->base, 371 native_configs[i], depth_stencil_formats[j])) { 372 FREE(gconf); 373 break; 374 } 375 376 _eglLinkConfig(&gconf->base); 377 id++; 378 } 379 } 380 } 381 382 FREE(native_configs); 383 return id; 384} 385 386static void 387egl_g3d_invalid_surface(struct native_display *ndpy, 388 struct native_surface *nsurf, 389 unsigned int seq_num) 390{ 391 /* XXX not thread safe? */ 392 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); 393 struct egl_g3d_context *gctx; 394 395 /* 396 * Some functions such as egl_g3d_copy_buffers create a temporary native 397 * surface. There is no gsurf associated with it. 398 */ 399 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; 400 if (gctx) 401 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); 402} 403 404static struct pipe_screen * 405egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) 406{ 407 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 408 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 409 return gdpy->loader->create_drm_screen(name, fd); 410} 411 412static struct pipe_screen * 413egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) 414{ 415 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 416 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 417 return gdpy->loader->create_sw_screen(ws); 418} 419 420static struct native_event_handler egl_g3d_native_event_handler = { 421 egl_g3d_invalid_surface, 422 egl_g3d_new_drm_screen, 423 egl_g3d_new_sw_screen 424}; 425 426static void 427egl_g3d_free_config(void *conf) 428{ 429 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf); 430 FREE(gconf); 431} 432 433static void 434egl_g3d_free_screen(void *scr) 435{ 436#ifdef EGL_MESA_screen_surface 437 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr); 438 FREE(gscr->native_modes); 439 FREE(gscr); 440#endif 441} 442 443static EGLBoolean 444egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) 445{ 446 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 447 448 _eglReleaseDisplayResources(drv, dpy); 449 450 if (gdpy->pipe) 451 gdpy->pipe->destroy(gdpy->pipe); 452 453 if (dpy->Configs) { 454 _eglDestroyArray(dpy->Configs, egl_g3d_free_config); 455 dpy->Configs = NULL; 456 } 457 if (dpy->Screens) { 458 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen); 459 dpy->Screens = NULL; 460 } 461 462 _eglCleanupDisplay(dpy); 463 464 if (gdpy->smapi) 465 egl_g3d_destroy_st_manager(gdpy->smapi); 466 467 if (gdpy->native) 468 gdpy->native->destroy(gdpy->native); 469 470 FREE(gdpy); 471 dpy->DriverData = NULL; 472 473 return EGL_TRUE; 474} 475 476static EGLBoolean 477egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, 478 EGLint *major, EGLint *minor) 479{ 480 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 481 struct egl_g3d_display *gdpy; 482 const struct native_platform *nplat; 483 484 nplat = egl_g3d_get_platform(drv, dpy->Platform); 485 if (!nplat) 486 return EGL_FALSE; 487 488 gdpy = CALLOC_STRUCT(egl_g3d_display); 489 if (!gdpy) { 490 _eglError(EGL_BAD_ALLOC, "eglInitialize"); 491 goto fail; 492 } 493 gdpy->loader = gdrv->loader; 494 dpy->DriverData = gdpy; 495 496 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); 497 gdpy->native = nplat->create_display(dpy->PlatformDisplay, 498 &egl_g3d_native_event_handler, (void *) dpy); 499 if (!gdpy->native) { 500 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); 501 goto fail; 502 } 503 504 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) 505 dpy->ClientAPIsMask |= EGL_OPENGL_BIT; 506 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK) 507 dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT; 508 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK) 509 dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; 510 if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK) 511 dpy->ClientAPIsMask |= EGL_OPENVG_BIT; 512 513 gdpy->smapi = egl_g3d_create_st_manager(dpy); 514 if (!gdpy->smapi) { 515 _eglError(EGL_NOT_INITIALIZED, 516 "eglInitialize(failed to create st manager)"); 517 goto fail; 518 } 519 520#ifdef EGL_MESA_screen_surface 521 /* enable MESA_screen_surface before adding (and validating) configs */ 522 if (gdpy->native->modeset) { 523 dpy->Extensions.MESA_screen_surface = EGL_TRUE; 524 egl_g3d_add_screens(drv, dpy); 525 } 526#endif 527 528 dpy->Extensions.KHR_image_base = EGL_TRUE; 529 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) 530 dpy->Extensions.KHR_image_pixmap = EGL_TRUE; 531 532 dpy->Extensions.KHR_reusable_sync = EGL_TRUE; 533 dpy->Extensions.KHR_fence_sync = EGL_TRUE; 534 535 dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; 536 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; 537 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE; 538 539 if (dpy->Platform == _EGL_PLATFORM_DRM) { 540 dpy->Extensions.MESA_drm_display = EGL_TRUE; 541 dpy->Extensions.MESA_drm_image = EGL_TRUE; 542 } 543 544 if (egl_g3d_add_configs(drv, dpy, 1) == 1) { 545 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); 546 goto fail; 547 } 548 549 *major = 1; 550 *minor = 4; 551 552 return EGL_TRUE; 553 554fail: 555 if (gdpy) 556 egl_g3d_terminate(drv, dpy); 557 return EGL_FALSE; 558} 559 560static _EGLProc 561egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) 562{ 563 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 564 struct st_api *stapi = NULL; 565 566 if (procname && procname[0] == 'v' && procname[1] == 'g') 567 stapi = gdrv->loader->get_st_api(ST_API_OPENVG); 568 else if (procname && procname[0] == 'g' && procname[1] == 'l') 569 stapi = gdrv->loader->get_st_api(ST_API_OPENGL); 570 571 return (_EGLProc) ((stapi) ? 572 stapi->get_proc_address(stapi, procname) : NULL); 573} 574 575static EGLint 576egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) 577{ 578 return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0; 579} 580 581_EGLDriver * 582egl_g3d_create_driver(const struct egl_g3d_loader *loader) 583{ 584 struct egl_g3d_driver *gdrv; 585 586 gdrv = CALLOC_STRUCT(egl_g3d_driver); 587 if (!gdrv) 588 return NULL; 589 590 gdrv->loader = loader; 591 592 egl_g3d_init_driver_api(&gdrv->base); 593 gdrv->base.API.Initialize = egl_g3d_initialize; 594 gdrv->base.API.Terminate = egl_g3d_terminate; 595 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; 596 597 gdrv->base.Probe = egl_g3d_probe; 598 599 /* to be filled by the caller */ 600 gdrv->base.Name = NULL; 601 gdrv->base.Unload = NULL; 602 603 return &gdrv->base; 604} 605 606void 607egl_g3d_destroy_driver(_EGLDriver *drv) 608{ 609 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 610 FREE(gdrv); 611} 612