1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.8 4 * 5 * Copyright (C) 2009-2010 Chia-I Wu <olv (at) 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 #include "util/u_atomic.h" 35 36 #include "egl_g3d.h" 37 #include "egl_g3d_api.h" 38 #include "egl_g3d_st.h" 39 #include "egl_g3d_loader.h" 40 #include "native.h" 41 42 static void 43 egl_g3d_invalid_surface(struct native_display *ndpy, 44 struct native_surface *nsurf, 45 unsigned int seq_num) 46 { 47 /* XXX not thread safe? */ 48 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); 49 50 if (gsurf && gsurf->stfbi) 51 p_atomic_inc(&gsurf->stfbi->stamp); 52 } 53 54 static struct pipe_screen * 55 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd) 56 { 57 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 58 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 59 return gdpy->loader->create_drm_screen(name, fd); 60 } 61 62 static struct pipe_screen * 63 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) 64 { 65 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 66 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 67 return gdpy->loader->create_sw_screen(ws); 68 } 69 70 static struct pipe_resource * 71 egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image) 72 { 73 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; 74 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 75 struct st_egl_image img; 76 struct pipe_resource *resource = NULL; 77 78 memset(&img, 0, sizeof(img)); 79 if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img)) 80 resource = img.texture; 81 82 return resource; 83 } 84 85 static const struct native_event_handler egl_g3d_native_event_handler = { 86 egl_g3d_invalid_surface, 87 egl_g3d_new_drm_screen, 88 egl_g3d_new_sw_screen, 89 egl_g3d_lookup_egl_image 90 }; 91 92 /** 93 * Get the native platform. 94 */ 95 static const struct native_platform * 96 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) 97 { 98 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 99 100 if (!gdrv->platforms[plat]) { 101 const char *plat_name = NULL; 102 const struct native_platform *nplat = NULL; 103 104 switch (plat) { 105 case _EGL_PLATFORM_WINDOWS: 106 plat_name = "Windows"; 107 #ifdef HAVE_GDI_BACKEND 108 nplat = native_get_gdi_platform(&egl_g3d_native_event_handler); 109 #endif 110 break; 111 case _EGL_PLATFORM_X11: 112 plat_name = "X11"; 113 #ifdef HAVE_X11_BACKEND 114 nplat = native_get_x11_platform(&egl_g3d_native_event_handler); 115 #endif 116 break; 117 case _EGL_PLATFORM_WAYLAND: 118 plat_name = "wayland"; 119 #ifdef HAVE_WAYLAND_BACKEND 120 nplat = native_get_wayland_platform(&egl_g3d_native_event_handler); 121 #endif 122 break; 123 case _EGL_PLATFORM_DRM: 124 plat_name = "DRM"; 125 #ifdef HAVE_DRM_BACKEND 126 nplat = native_get_drm_platform(&egl_g3d_native_event_handler); 127 #endif 128 break; 129 case _EGL_PLATFORM_FBDEV: 130 plat_name = "FBDEV"; 131 #ifdef HAVE_FBDEV_BACKEND 132 nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler); 133 #endif 134 break; 135 case _EGL_PLATFORM_NULL: 136 plat_name = "NULL"; 137 #ifdef HAVE_NULL_BACKEND 138 nplat = native_get_null_platform(&egl_g3d_native_event_handler); 139 #endif 140 break; 141 case _EGL_PLATFORM_ANDROID: 142 plat_name = "Android"; 143 #ifdef HAVE_ANDROID_BACKEND 144 nplat = native_get_android_platform(&egl_g3d_native_event_handler); 145 #endif 146 break; 147 default: 148 break; 149 } 150 151 if (!nplat) 152 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); 153 154 gdrv->platforms[plat] = nplat; 155 } 156 157 return gdrv->platforms[plat]; 158 } 159 160 #ifdef EGL_MESA_screen_surface 161 162 static void 163 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) 164 { 165 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 166 const struct native_connector **native_connectors; 167 EGLint num_connectors, i; 168 169 native_connectors = 170 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL); 171 if (!num_connectors) { 172 if (native_connectors) 173 FREE(native_connectors); 174 return; 175 } 176 177 for (i = 0; i < num_connectors; i++) { 178 const struct native_connector *nconn = native_connectors[i]; 179 struct egl_g3d_screen *gscr; 180 const struct native_mode **native_modes; 181 EGLint num_modes, j; 182 183 /* TODO support for hotplug */ 184 native_modes = 185 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes); 186 if (!num_modes) { 187 if (native_modes) 188 FREE(native_modes); 189 continue; 190 } 191 192 gscr = CALLOC_STRUCT(egl_g3d_screen); 193 if (!gscr) { 194 FREE(native_modes); 195 continue; 196 } 197 198 _eglInitScreen(&gscr->base, dpy, num_modes); 199 for (j = 0; j < gscr->base.NumModes; j++) { 200 const struct native_mode *nmode = native_modes[j]; 201 _EGLMode *mode = &gscr->base.Modes[j]; 202 203 mode->Width = nmode->width; 204 mode->Height = nmode->height; 205 mode->RefreshRate = nmode->refresh_rate; 206 mode->Optimal = EGL_FALSE; 207 mode->Interlaced = EGL_FALSE; 208 /* no need to strdup() */ 209 mode->Name = nmode->desc; 210 } 211 212 gscr->native = nconn; 213 gscr->native_modes = native_modes; 214 215 _eglLinkScreen(&gscr->base); 216 } 217 218 FREE(native_connectors); 219 } 220 221 #endif /* EGL_MESA_screen_surface */ 222 223 /** 224 * Initialize and validate the EGL config attributes. 225 */ 226 static EGLBoolean 227 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, 228 EGLint api_mask, enum pipe_format depth_stencil_format, 229 EGLint preserve_buffer, EGLint max_swap_interval, 230 EGLBoolean pre_alpha) 231 { 232 uint rgba[4], depth_stencil[2], buffer_size; 233 EGLint surface_type; 234 EGLint i; 235 236 /* get the color and depth/stencil component sizes */ 237 assert(nconf->color_format != PIPE_FORMAT_NONE); 238 buffer_size = 0; 239 for (i = 0; i < 4; i++) { 240 rgba[i] = util_format_get_component_bits(nconf->color_format, 241 UTIL_FORMAT_COLORSPACE_RGB, i); 242 buffer_size += rgba[i]; 243 } 244 for (i = 0; i < 2; i++) { 245 if (depth_stencil_format != PIPE_FORMAT_NONE) { 246 depth_stencil[i] = 247 util_format_get_component_bits(depth_stencil_format, 248 UTIL_FORMAT_COLORSPACE_ZS, i); 249 } 250 else { 251 depth_stencil[i] = 0; 252 } 253 } 254 255 surface_type = 0x0; 256 /* pixmap surfaces should be EGL_SINGLE_BUFFER */ 257 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) { 258 if (nconf->pixmap_bit) 259 surface_type |= EGL_PIXMAP_BIT; 260 } 261 /* the others surfaces should be EGL_BACK_BUFFER (or settable) */ 262 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) { 263 if (nconf->window_bit) 264 surface_type |= EGL_WINDOW_BIT; 265 #ifdef EGL_MESA_screen_surface 266 if (nconf->scanout_bit) 267 surface_type |= EGL_SCREEN_BIT_MESA; 268 #endif 269 surface_type |= EGL_PBUFFER_BIT; 270 } 271 272 if (preserve_buffer) 273 surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 274 275 if (pre_alpha && rgba[3]) { 276 surface_type |= EGL_VG_ALPHA_FORMAT_PRE_BIT; 277 /* st/vega does not support premultiplied alpha yet */ 278 api_mask &= ~EGL_OPENVG_BIT; 279 } 280 281 conf->Conformant = api_mask; 282 conf->RenderableType = api_mask; 283 284 conf->RedSize = rgba[0]; 285 conf->GreenSize = rgba[1]; 286 conf->BlueSize = rgba[2]; 287 conf->AlphaSize = rgba[3]; 288 conf->BufferSize = buffer_size; 289 290 conf->DepthSize = depth_stencil[0]; 291 conf->StencilSize = depth_stencil[1]; 292 293 /* st/vega will allocate the mask on demand */ 294 if (api_mask & EGL_OPENVG_BIT) 295 conf->AlphaMaskSize = 8; 296 297 conf->SurfaceType = surface_type; 298 299 conf->NativeRenderable = EGL_TRUE; 300 if (surface_type & EGL_WINDOW_BIT) { 301 conf->NativeVisualID = nconf->native_visual_id; 302 conf->NativeVisualType = nconf->native_visual_type; 303 } 304 305 if (surface_type & EGL_PBUFFER_BIT) { 306 conf->BindToTextureRGB = EGL_TRUE; 307 if (rgba[3]) 308 conf->BindToTextureRGBA = EGL_TRUE; 309 310 conf->MaxPbufferWidth = 4096; 311 conf->MaxPbufferHeight = 4096; 312 conf->MaxPbufferPixels = 4096 * 4096; 313 } 314 315 conf->Level = nconf->level; 316 317 if (nconf->transparent_rgb) { 318 conf->TransparentType = EGL_TRANSPARENT_RGB; 319 conf->TransparentRedValue = nconf->transparent_rgb_values[0]; 320 conf->TransparentGreenValue = nconf->transparent_rgb_values[1]; 321 conf->TransparentBlueValue = nconf->transparent_rgb_values[2]; 322 } 323 324 conf->MinSwapInterval = 0; 325 conf->MaxSwapInterval = max_swap_interval; 326 327 return _eglValidateConfig(conf, EGL_FALSE); 328 } 329 330 /** 331 * Initialize an EGL config from the native config. 332 */ 333 static EGLBoolean 334 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, 335 _EGLConfig *conf, const struct native_config *nconf, 336 enum pipe_format depth_stencil_format, 337 int preserve_buffer, int max_swap_interval, 338 int pre_alpha) 339 { 340 struct egl_g3d_config *gconf = egl_g3d_config(conf); 341 EGLint buffer_mask; 342 EGLBoolean valid; 343 344 buffer_mask = 0x0; 345 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) 346 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 347 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 348 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 349 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) 350 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 351 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) 352 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 353 354 gconf->stvis.buffer_mask = buffer_mask; 355 gconf->stvis.color_format = nconf->color_format; 356 gconf->stvis.depth_stencil_format = depth_stencil_format; 357 gconf->stvis.accum_format = PIPE_FORMAT_NONE; 358 gconf->stvis.samples = 0; 359 360 /* will be overridden per surface */ 361 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? 362 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; 363 364 valid = init_config_attributes(&gconf->base, 365 nconf, dpy->ClientAPIs, depth_stencil_format, 366 preserve_buffer, max_swap_interval, pre_alpha); 367 if (!valid) { 368 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); 369 return EGL_FALSE; 370 } 371 372 gconf->native = nconf; 373 374 return EGL_TRUE; 375 } 376 377 /** 378 * Get all interested depth/stencil formats of a display. 379 */ 380 static EGLint 381 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, 382 enum pipe_format formats[8]) 383 { 384 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 385 struct pipe_screen *screen = gdpy->native->screen; 386 const EGLint candidates[] = { 387 1, PIPE_FORMAT_Z16_UNORM, 388 1, PIPE_FORMAT_Z32_UNORM, 389 2, PIPE_FORMAT_Z24_UNORM_S8_UINT, PIPE_FORMAT_S8_UINT_Z24_UNORM, 390 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, 391 0 392 }; 393 const EGLint *fmt = candidates; 394 EGLint count; 395 396 count = 0; 397 formats[count++] = PIPE_FORMAT_NONE; 398 399 while (*fmt) { 400 EGLint i, n = *fmt++; 401 402 /* pick the first supported format */ 403 for (i = 0; i < n; i++) { 404 if (screen->is_format_supported(screen, fmt[i], 405 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) { 406 formats[count++] = fmt[i]; 407 break; 408 } 409 } 410 411 fmt += n; 412 } 413 414 return count; 415 } 416 417 /** 418 * Add configs to display and return the next config ID. 419 */ 420 static EGLint 421 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) 422 { 423 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 424 const struct native_config **native_configs; 425 enum pipe_format depth_stencil_formats[8]; 426 int num_formats, num_configs, i, j; 427 int preserve_buffer, max_swap_interval, premultiplied_alpha; 428 429 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); 430 if (!num_configs) { 431 if (native_configs) 432 FREE(native_configs); 433 return id; 434 } 435 436 preserve_buffer = 437 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER); 438 max_swap_interval = 439 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL); 440 premultiplied_alpha = 441 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PREMULTIPLIED_ALPHA); 442 443 num_formats = egl_g3d_fill_depth_stencil_formats(dpy, 444 depth_stencil_formats); 445 446 for (i = 0; i < num_configs; i++) { 447 for (j = 0; j < num_formats; j++) { 448 struct egl_g3d_config *gconf; 449 450 gconf = CALLOC_STRUCT(egl_g3d_config); 451 if (gconf) { 452 _eglInitConfig(&gconf->base, dpy, id); 453 if (!egl_g3d_init_config(drv, dpy, &gconf->base, 454 native_configs[i], depth_stencil_formats[j], 455 preserve_buffer, max_swap_interval, 456 premultiplied_alpha)) { 457 FREE(gconf); 458 break; 459 } 460 461 _eglLinkConfig(&gconf->base); 462 id++; 463 } 464 } 465 } 466 467 FREE(native_configs); 468 return id; 469 } 470 471 static void 472 egl_g3d_free_config(void *conf) 473 { 474 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf); 475 FREE(gconf); 476 } 477 478 static void 479 egl_g3d_free_screen(void *scr) 480 { 481 #ifdef EGL_MESA_screen_surface 482 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr); 483 FREE(gscr->native_modes); 484 FREE(gscr); 485 #endif 486 } 487 488 static EGLBoolean 489 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) 490 { 491 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 492 493 _eglReleaseDisplayResources(drv, dpy); 494 495 if (dpy->Configs) { 496 _eglDestroyArray(dpy->Configs, egl_g3d_free_config); 497 dpy->Configs = NULL; 498 } 499 if (dpy->Screens) { 500 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen); 501 dpy->Screens = NULL; 502 } 503 504 _eglCleanupDisplay(dpy); 505 506 if (gdpy->smapi) 507 egl_g3d_destroy_st_manager(gdpy->smapi); 508 509 if (gdpy->native) 510 gdpy->native->destroy(gdpy->native); 511 512 FREE(gdpy); 513 dpy->DriverData = NULL; 514 515 return EGL_TRUE; 516 } 517 518 static EGLBoolean 519 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) 520 { 521 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 522 struct egl_g3d_display *gdpy; 523 const struct native_platform *nplat; 524 525 nplat = egl_g3d_get_platform(drv, dpy->Platform); 526 if (!nplat) 527 return EGL_FALSE; 528 529 if (dpy->Options.TestOnly) 530 return EGL_TRUE; 531 532 gdpy = CALLOC_STRUCT(egl_g3d_display); 533 if (!gdpy) { 534 _eglError(EGL_BAD_ALLOC, "eglInitialize"); 535 goto fail; 536 } 537 gdpy->loader = gdrv->loader; 538 dpy->DriverData = gdpy; 539 540 _eglLog(_EGL_INFO, "use %s for display %p", 541 nplat->name, dpy->PlatformDisplay); 542 gdpy->native = 543 nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback); 544 if (!gdpy->native) { 545 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); 546 goto fail; 547 } 548 gdpy->native->user_data = (void *) dpy; 549 if (!gdpy->native->init_screen(gdpy->native)) { 550 _eglError(EGL_NOT_INITIALIZED, 551 "eglInitialize(failed to initialize screen)"); 552 goto fail; 553 } 554 555 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) 556 dpy->ClientAPIs |= EGL_OPENGL_BIT; 557 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK) 558 dpy->ClientAPIs |= EGL_OPENGL_ES_BIT; 559 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK) 560 dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT; 561 if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK) 562 dpy->ClientAPIs |= EGL_OPENVG_BIT; 563 564 gdpy->smapi = egl_g3d_create_st_manager(dpy); 565 if (!gdpy->smapi) { 566 _eglError(EGL_NOT_INITIALIZED, 567 "eglInitialize(failed to create st manager)"); 568 goto fail; 569 } 570 571 #ifdef EGL_MESA_screen_surface 572 /* enable MESA_screen_surface before adding (and validating) configs */ 573 if (gdpy->native->modeset) { 574 dpy->Extensions.MESA_screen_surface = EGL_TRUE; 575 egl_g3d_add_screens(drv, dpy); 576 } 577 #endif 578 579 dpy->Extensions.KHR_image_base = EGL_TRUE; 580 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) 581 dpy->Extensions.KHR_image_pixmap = EGL_TRUE; 582 583 dpy->Extensions.KHR_reusable_sync = EGL_TRUE; 584 dpy->Extensions.KHR_fence_sync = EGL_TRUE; 585 586 dpy->Extensions.KHR_surfaceless_context = EGL_TRUE; 587 588 if (dpy->Platform == _EGL_PLATFORM_DRM) { 589 dpy->Extensions.MESA_drm_display = EGL_TRUE; 590 if (gdpy->native->buffer) 591 dpy->Extensions.MESA_drm_image = EGL_TRUE; 592 } 593 594 if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer) 595 dpy->Extensions.MESA_drm_image = EGL_TRUE; 596 597 #ifdef EGL_ANDROID_image_native_buffer 598 if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer) 599 dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; 600 #endif 601 602 #ifdef EGL_WL_bind_wayland_display 603 if (gdpy->native->wayland_bufmgr) 604 dpy->Extensions.WL_bind_wayland_display = EGL_TRUE; 605 #endif 606 607 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) && 608 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) { 609 #ifdef EGL_NOK_swap_region 610 dpy->Extensions.NOK_swap_region = EGL_TRUE; 611 #endif 612 dpy->Extensions.NV_post_sub_buffer = EGL_TRUE; 613 } 614 615 if (egl_g3d_add_configs(drv, dpy, 1) == 1) { 616 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); 617 goto fail; 618 } 619 620 dpy->VersionMajor = 1; 621 dpy->VersionMinor = 4; 622 623 return EGL_TRUE; 624 625 fail: 626 if (gdpy) 627 egl_g3d_terminate(drv, dpy); 628 return EGL_FALSE; 629 } 630 631 static _EGLProc 632 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) 633 { 634 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 635 struct st_api *stapi = NULL; 636 637 if (procname && procname[0] == 'v' && procname[1] == 'g') 638 stapi = gdrv->loader->get_st_api(ST_API_OPENVG); 639 else if (procname && procname[0] == 'g' && procname[1] == 'l') 640 stapi = gdrv->loader->get_st_api(ST_API_OPENGL); 641 642 return (_EGLProc) ((stapi) ? 643 stapi->get_proc_address(stapi, procname) : NULL); 644 } 645 646 _EGLDriver * 647 egl_g3d_create_driver(const struct egl_g3d_loader *loader) 648 { 649 struct egl_g3d_driver *gdrv; 650 651 gdrv = CALLOC_STRUCT(egl_g3d_driver); 652 if (!gdrv) 653 return NULL; 654 655 gdrv->loader = loader; 656 657 egl_g3d_init_driver_api(&gdrv->base); 658 gdrv->base.API.Initialize = egl_g3d_initialize; 659 gdrv->base.API.Terminate = egl_g3d_terminate; 660 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; 661 662 /* to be filled by the caller */ 663 gdrv->base.Name = NULL; 664 gdrv->base.Unload = NULL; 665 666 return &gdrv->base; 667 } 668 669 void 670 egl_g3d_destroy_driver(_EGLDriver *drv) 671 { 672 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 673 FREE(gdrv); 674 } 675