egl_g3d.c revision ea05299ce54ea0463626277907cab8e849884740
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 "native.h" 39 40/** 41 * Initialize the state trackers. 42 */ 43static void 44egl_g3d_init_st(_EGLDriver *drv) 45{ 46 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 47 EGLint i; 48 49 /* already initialized */ 50 if (gdrv->api_mask) 51 return; 52 53 egl_g3d_init_st_apis(gdrv->stapis); 54 for (i = 0; i < ST_API_COUNT; i++) { 55 if (gdrv->stapis[i]) 56 gdrv->api_mask |= egl_g3d_st_api_bit(i); 57 } 58 59 if (gdrv->api_mask) 60 _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); 61 else 62 _eglLog(_EGL_WARNING, "No supported client API"); 63} 64 65/** 66 * Get the native platform. 67 */ 68static const struct native_platform * 69egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) 70{ 71 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 72 73 if (!gdrv->platforms[plat]) { 74 const char *plat_name = NULL; 75 const struct native_platform *nplat = NULL; 76 77 switch (plat) { 78 case _EGL_PLATFORM_WINDOWS: 79 plat_name = "Windows"; 80#ifdef HAVE_GDI_BACKEND 81 nplat = native_get_gdi_platform(); 82#endif 83 break; 84 case _EGL_PLATFORM_X11: 85 plat_name = "X11"; 86#ifdef HAVE_X11_BACKEND 87 nplat = native_get_x11_platform(); 88#endif 89 break; 90 case _EGL_PLATFORM_DRM: 91 plat_name = "DRM"; 92#ifdef HAVE_KMS_BACKEND 93 nplat = native_get_kms_platform(); 94#endif 95 break; 96 case _EGL_PLATFORM_FBDEV: 97 plat_name = "FBDEV"; 98#ifdef HAVE_FBDEV_BACKEND 99 nplat = native_get_fbdev_platform(); 100#endif 101 break; 102 default: 103 break; 104 } 105 106 if (!nplat) 107 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); 108 109 gdrv->platforms[plat] = nplat; 110 } 111 112 return gdrv->platforms[plat]; 113} 114 115/** 116 * Get the probe result of the display. 117 * 118 * Note that this function may be called before the display is initialized. 119 */ 120static enum native_probe_result 121egl_g3d_get_probe_result(_EGLDriver *drv, _EGLDisplay *dpy) 122{ 123 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 124 struct native_probe *nprobe; 125 const struct native_platform *nplat; 126 127 nplat = egl_g3d_get_platform(drv, dpy->Platform); 128 if (!nplat || !nplat->create_probe) 129 return NATIVE_PROBE_UNKNOWN; 130 131 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); 132 if (!nprobe || nprobe->display != dpy->PlatformDisplay) { 133 if (nprobe) 134 nprobe->destroy(nprobe); 135 nprobe = nplat->create_probe(dpy->PlatformDisplay); 136 _eglSetProbeCache(gdrv->probe_key, (void *) nprobe); 137 } 138 139 return nplat->get_probe_result(nprobe); 140} 141 142/** 143 * Destroy the probe object of the display. The display may be NULL. 144 * 145 * Note that this function may be called before the display is initialized. 146 */ 147static void 148egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) 149{ 150 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 151 struct native_probe *nprobe; 152 153 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); 154 if (nprobe && (!dpy || nprobe->display == dpy->PlatformDisplay)) { 155 nprobe->destroy(nprobe); 156 _eglSetProbeCache(gdrv->probe_key, NULL); 157 } 158} 159 160#ifdef EGL_MESA_screen_surface 161 162static void 163egl_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); 199 200 for (j = 0; j < num_modes; j++) { 201 const struct native_mode *nmode = native_modes[j]; 202 _EGLMode *mode; 203 204 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height, 205 nmode->refresh_rate, nmode->desc); 206 if (!mode) 207 break; 208 /* gscr->native_modes and gscr->base.Modes should be consistent */ 209 assert(mode == &gscr->base.Modes[j]); 210 } 211 212 gscr->native = nconn; 213 gscr->native_modes = native_modes; 214 215 _eglAddScreen(dpy, &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 */ 226static EGLBoolean 227init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, 228 EGLint api_mask, enum pipe_format depth_stencil_format) 229{ 230 uint rgba[4], depth_stencil[2], buffer_size; 231 EGLint surface_type; 232 EGLint i; 233 234 /* get the color and depth/stencil component sizes */ 235 assert(nconf->color_format != PIPE_FORMAT_NONE); 236 buffer_size = 0; 237 for (i = 0; i < 4; i++) { 238 rgba[i] = util_format_get_component_bits(nconf->color_format, 239 UTIL_FORMAT_COLORSPACE_RGB, i); 240 buffer_size += rgba[i]; 241 } 242 for (i = 0; i < 2; i++) { 243 if (depth_stencil_format != PIPE_FORMAT_NONE) { 244 depth_stencil[i] = 245 util_format_get_component_bits(depth_stencil_format, 246 UTIL_FORMAT_COLORSPACE_ZS, i); 247 } 248 else { 249 depth_stencil[i] = 0; 250 } 251 } 252 253 surface_type = 0x0; 254 if (nconf->window_bit) 255 surface_type |= EGL_WINDOW_BIT; 256 if (nconf->pixmap_bit) 257 surface_type |= EGL_PIXMAP_BIT; 258#ifdef EGL_MESA_screen_surface 259 if (nconf->scanout_bit) 260 surface_type |= EGL_SCREEN_BIT_MESA; 261#endif 262 263 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 264 surface_type |= EGL_PBUFFER_BIT; 265 266 SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask); 267 SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask); 268 269 SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]); 270 SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]); 271 SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]); 272 SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]); 273 SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size); 274 275 SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]); 276 SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]); 277 278 SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type); 279 280 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE); 281 if (surface_type & EGL_WINDOW_BIT) { 282 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id); 283 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, 284 nconf->native_visual_type); 285 } 286 287 if (surface_type & EGL_PBUFFER_BIT) { 288 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); 289 if (rgba[3]) 290 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); 291 292 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096); 293 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096); 294 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096); 295 } 296 297 SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level); 298 SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples); 299 SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1); 300 301 if (nconf->slow_config) 302 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG); 303 304 if (nconf->transparent_rgb) { 305 rgba[0] = nconf->transparent_rgb_values[0]; 306 rgba[1] = nconf->transparent_rgb_values[1]; 307 rgba[2] = nconf->transparent_rgb_values[2]; 308 309 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB); 310 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]); 311 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]); 312 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]); 313 } 314 315 return _eglValidateConfig(conf, EGL_FALSE); 316} 317 318/** 319 * Initialize an EGL config from the native config. 320 */ 321static EGLBoolean 322egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, 323 _EGLConfig *conf, const struct native_config *nconf, 324 enum pipe_format depth_stencil_format) 325{ 326 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 327 struct egl_g3d_config *gconf = egl_g3d_config(conf); 328 EGLint buffer_mask, api_mask; 329 EGLBoolean valid; 330 331 buffer_mask = 0x0; 332 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) 333 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 334 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) 335 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 336 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) 337 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 338 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) 339 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 340 341 gconf->stvis.buffer_mask = buffer_mask; 342 gconf->stvis.color_format = nconf->color_format; 343 gconf->stvis.depth_stencil_format = depth_stencil_format; 344 gconf->stvis.accum_format = PIPE_FORMAT_NONE; 345 gconf->stvis.samples = nconf->samples; 346 347 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? 348 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; 349 350 api_mask = gdrv->api_mask;; 351 /* this is required by EGL, not by OpenGL ES */ 352 if (nconf->window_bit && 353 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) 354 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); 355 356 if (!api_mask) { 357 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", 358 nconf->native_visual_id); 359 } 360 361 valid = init_config_attributes(&gconf->base, 362 nconf, api_mask, depth_stencil_format); 363 if (!valid) { 364 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); 365 return EGL_FALSE; 366 } 367 368 gconf->native = nconf; 369 370 return EGL_TRUE; 371} 372 373/** 374 * Get all interested depth/stencil formats of a display. 375 */ 376static EGLint 377egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, 378 enum pipe_format formats[8]) 379{ 380 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 381 struct pipe_screen *screen = gdpy->native->screen; 382 const EGLint candidates[] = { 383 1, PIPE_FORMAT_Z16_UNORM, 384 1, PIPE_FORMAT_Z32_UNORM, 385 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 386 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, 387 0 388 }; 389 const EGLint *fmt = candidates; 390 EGLint count; 391 392 count = 0; 393 formats[count++] = PIPE_FORMAT_NONE; 394 395 while (*fmt) { 396 EGLint i, n = *fmt++; 397 398 /* pick the first supported format */ 399 for (i = 0; i < n; i++) { 400 if (screen->is_format_supported(screen, fmt[i], 401 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) { 402 formats[count++] = fmt[i]; 403 break; 404 } 405 } 406 407 fmt += n; 408 } 409 410 return count; 411} 412 413/** 414 * Add configs to display and return the next config ID. 415 */ 416static EGLint 417egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) 418{ 419 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 420 const struct native_config **native_configs; 421 enum pipe_format depth_stencil_formats[8]; 422 int num_formats, num_configs, i, j; 423 424 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); 425 if (!num_configs) { 426 if (native_configs) 427 FREE(native_configs); 428 return id; 429 } 430 431 num_formats = egl_g3d_fill_depth_stencil_formats(dpy, 432 depth_stencil_formats); 433 434 for (i = 0; i < num_configs; i++) { 435 for (j = 0; j < num_formats; j++) { 436 struct egl_g3d_config *gconf; 437 438 gconf = CALLOC_STRUCT(egl_g3d_config); 439 if (gconf) { 440 _eglInitConfig(&gconf->base, dpy, id); 441 if (!egl_g3d_init_config(drv, dpy, &gconf->base, 442 native_configs[i], depth_stencil_formats[j])) { 443 FREE(gconf); 444 break; 445 } 446 447 _eglAddConfig(dpy, &gconf->base); 448 id++; 449 } 450 } 451 } 452 453 FREE(native_configs); 454 return id; 455} 456 457static void 458egl_g3d_invalid_surface(struct native_display *ndpy, 459 struct native_surface *nsurf, 460 unsigned int seq_num) 461{ 462 /* XXX not thread safe? */ 463 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); 464 struct egl_g3d_context *gctx; 465 466 /* 467 * Some functions such as egl_g3d_copy_buffers create a temporary native 468 * surface. There is no gsurf associated with it. 469 */ 470 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; 471 if (gctx) 472 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); 473} 474 475static struct native_event_handler egl_g3d_native_event_handler = { 476 egl_g3d_invalid_surface 477}; 478 479static EGLBoolean 480egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) 481{ 482 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 483 EGLint i; 484 485 _eglReleaseDisplayResources(drv, dpy); 486 _eglCleanupDisplay(dpy); 487 488 if (gdpy->pipe) 489 gdpy->pipe->destroy(gdpy->pipe); 490 491 if (dpy->Screens) { 492 for (i = 0; i < dpy->NumScreens; i++) { 493 struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); 494 FREE(gscr->native_modes); 495 FREE(gscr); 496 } 497 FREE(dpy->Screens); 498 } 499 500 if (gdpy->smapi) 501 egl_g3d_destroy_st_manager(gdpy->smapi); 502 503 if (gdpy->native) 504 gdpy->native->destroy(gdpy->native); 505 506 FREE(gdpy); 507 dpy->DriverData = NULL; 508 509 return EGL_TRUE; 510} 511 512static EGLBoolean 513egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, 514 EGLint *major, EGLint *minor) 515{ 516 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 517 struct egl_g3d_display *gdpy; 518 const struct native_platform *nplat; 519 520 /* the probe object is unlikely to be needed again */ 521 egl_g3d_destroy_probe(drv, dpy); 522 523 nplat = egl_g3d_get_platform(drv, dpy->Platform); 524 if (!nplat) 525 return EGL_FALSE; 526 527 gdpy = CALLOC_STRUCT(egl_g3d_display); 528 if (!gdpy) { 529 _eglError(EGL_BAD_ALLOC, "eglInitialize"); 530 goto fail; 531 } 532 dpy->DriverData = gdpy; 533 534 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); 535 gdpy->native = nplat->create_display(dpy->PlatformDisplay, 536 &egl_g3d_native_event_handler); 537 if (!gdpy->native) { 538 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); 539 goto fail; 540 } 541 542 gdpy->native->user_data = (void *) dpy; 543 544 egl_g3d_init_st(&gdrv->base); 545 dpy->ClientAPIsMask = gdrv->api_mask; 546 547 gdpy->smapi = egl_g3d_create_st_manager(dpy); 548 if (!gdpy->smapi) { 549 _eglError(EGL_NOT_INITIALIZED, 550 "eglInitialize(failed to create st manager)"); 551 goto fail; 552 } 553 554#ifdef EGL_MESA_screen_surface 555 /* enable MESA_screen_surface before adding (and validating) configs */ 556 if (gdpy->native->modeset) { 557 dpy->Extensions.MESA_screen_surface = EGL_TRUE; 558 egl_g3d_add_screens(drv, dpy); 559 } 560#endif 561 562 dpy->Extensions.KHR_image_base = EGL_TRUE; 563 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) 564 dpy->Extensions.KHR_image_pixmap = EGL_TRUE; 565 566 if (egl_g3d_add_configs(drv, dpy, 1) == 1) { 567 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); 568 goto fail; 569 } 570 571 *major = 1; 572 *minor = 4; 573 574 return EGL_TRUE; 575 576fail: 577 if (gdpy) 578 egl_g3d_terminate(drv, dpy); 579 return EGL_FALSE; 580} 581 582static _EGLProc 583egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) 584{ 585 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 586 _EGLProc proc; 587 EGLint i; 588 589 /* in case this is called before a display is initialized */ 590 egl_g3d_init_st(&gdrv->base); 591 592 for (i = 0; i < ST_API_COUNT; i++) { 593 struct st_api *stapi = gdrv->stapis[i]; 594 if (stapi) { 595 proc = (_EGLProc) stapi->get_proc_address(stapi, procname); 596 if (proc) 597 return proc; 598 } 599 } 600 601 return (_EGLProc) NULL; 602} 603 604static EGLint 605egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) 606{ 607 enum native_probe_result res; 608 EGLint score; 609 610 res = egl_g3d_get_probe_result(drv, dpy); 611 612 switch (res) { 613 case NATIVE_PROBE_UNKNOWN: 614 default: 615 score = 0; 616 break; 617 case NATIVE_PROBE_FALLBACK: 618 score = 40; 619 break; 620 case NATIVE_PROBE_SUPPORTED: 621 score = 50; 622 break; 623 case NATIVE_PROBE_EXACT: 624 score = 100; 625 break; 626 } 627 628 return score; 629} 630 631static void 632egl_g3d_unload(_EGLDriver *drv) 633{ 634 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 635 636 egl_g3d_destroy_st_apis(); 637 egl_g3d_destroy_probe(drv, NULL); 638 FREE(gdrv); 639} 640 641_EGLDriver * 642_eglMain(const char *args) 643{ 644 struct egl_g3d_driver *gdrv; 645 646 gdrv = CALLOC_STRUCT(egl_g3d_driver); 647 if (!gdrv) 648 return NULL; 649 650 egl_g3d_init_driver_api(&gdrv->base); 651 gdrv->base.API.Initialize = egl_g3d_initialize; 652 gdrv->base.API.Terminate = egl_g3d_terminate; 653 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; 654 655 gdrv->base.Name = "Gallium"; 656 gdrv->base.Probe = egl_g3d_probe; 657 gdrv->base.Unload = egl_g3d_unload; 658 659 /* the key is " EGL G3D" */ 660 gdrv->probe_key = 0x0E61063D; 661 662 return &gdrv->base; 663} 664