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