egl_g3d.c revision 0b99303d1c6244094c24844f86f4e7677ee69f18
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 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include <assert.h> 26#include <stdio.h> 27#include <string.h> 28#include "pipe/p_screen.h" 29#include "util/u_memory.h" 30#include "util/u_rect.h" 31#include "util/u_inlines.h" 32#include "egldriver.h" 33#include "eglcurrent.h" 34#include "eglconfigutil.h" 35#include "egllog.h" 36 37#include "native.h" 38#include "egl_g3d.h" 39#include "egl_st.h" 40 41/** 42 * Validate the draw/read surfaces of the context. 43 */ 44static void 45egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) 46{ 47 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 48 struct pipe_screen *screen = gdpy->native->screen; 49 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 50 const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { 51 ST_SURFACE_FRONT_LEFT, 52 ST_SURFACE_BACK_LEFT, 53 ST_SURFACE_FRONT_RIGHT, 54 ST_SURFACE_BACK_RIGHT, 55 }; 56 EGLint num_surfaces, s; 57 58 /* validate draw and/or read buffers */ 59 num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; 60 for (s = 0; s < num_surfaces; s++) { 61 struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; 62 struct egl_g3d_surface *gsurf; 63 struct egl_g3d_buffer *gbuf; 64 EGLint att; 65 66 if (s == 0) { 67 gsurf = egl_g3d_surface(gctx->base.DrawSurface); 68 gbuf = &gctx->draw; 69 } 70 else { 71 gsurf = egl_g3d_surface(gctx->base.ReadSurface); 72 gbuf = &gctx->read; 73 } 74 75 if (!gctx->force_validate) { 76 unsigned int seq_num; 77 78 gsurf->native->validate(gsurf->native, gbuf->attachment_mask, 79 &seq_num, NULL, NULL, NULL); 80 /* skip validation */ 81 if (gsurf->sequence_number == seq_num) 82 continue; 83 } 84 85 pipe_surface_reference(&gsurf->render_surface, NULL); 86 memset(textures, 0, sizeof(textures)); 87 88 gsurf->native->validate(gsurf->native, gbuf->attachment_mask, 89 &gsurf->sequence_number, textures, 90 &gsurf->base.Width, &gsurf->base.Height); 91 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 92 struct pipe_texture *pt = textures[att]; 93 struct pipe_surface *ps; 94 95 if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { 96 ps = screen->get_tex_surface(screen, pt, 0, 0, 0, 97 PIPE_BUFFER_USAGE_GPU_READ | 98 PIPE_BUFFER_USAGE_GPU_WRITE); 99 gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, 100 st_att_map[att], ps); 101 102 if (gsurf->render_att == att) 103 pipe_surface_reference(&gsurf->render_surface, ps); 104 105 pipe_surface_reference(&ps, NULL); 106 pipe_texture_reference(&pt, NULL); 107 } 108 } 109 110 gctx->stapi->st_resize_framebuffer(gbuf->st_fb, 111 gsurf->base.Width, gsurf->base.Height); 112 } 113 114 gctx->force_validate = EGL_FALSE; 115 116} 117 118/** 119 * Create a st_framebuffer. 120 */ 121static struct st_framebuffer * 122create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) 123{ 124 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 125 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 126 struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); 127 128 return gctx->stapi->st_create_framebuffer(&gconf->native->mode, 129 gconf->native->color_format, gconf->native->depth_format, 130 gconf->native->stencil_format, 131 gsurf->base.Width, gsurf->base.Height, &gsurf->base); 132} 133 134/** 135 * Update the attachments of draw/read surfaces. 136 */ 137static void 138egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) 139{ 140 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 141 EGLint s; 142 143 /* route draw and read buffers' attachments */ 144 for (s = 0; s < 2; s++) { 145 struct egl_g3d_surface *gsurf; 146 struct egl_g3d_buffer *gbuf; 147 148 if (s == 0) { 149 gsurf = egl_g3d_surface(gctx->base.DrawSurface); 150 gbuf = &gctx->draw; 151 } 152 else { 153 gsurf = egl_g3d_surface(gctx->base.ReadSurface); 154 gbuf = &gctx->read; 155 } 156 157 gbuf->attachment_mask = (1 << gsurf->render_att); 158 159 /* FIXME OpenGL defaults to draw the front or back buffer when the 160 * context is single-buffered or double-buffered respectively. In EGL, 161 * however, the buffer to be drawn is determined by the surface, instead 162 * of the context. As a result, rendering to a pixmap surface with a 163 * double-buffered context does not work as expected. 164 * 165 * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == 166 * NATIVE_ATTACHMENT_FRONT_LEFT); 167 */ 168 169 /* 170 * FIXME If the back buffer is asked for here, and the front buffer is 171 * later needed by the client API (e.g. glDrawBuffer is called to draw 172 * the front buffer), it will create a new pipe texture and draw there. 173 * One fix is to ask for both buffers here, but it would be a waste if 174 * the front buffer is never used. A better fix is to add a callback to 175 * the pipe screen with context private (just like flush_frontbuffer). 176 */ 177 } 178} 179 180/** 181 * Reallocate the context's framebuffers after draw/read surfaces change. 182 */ 183static EGLBoolean 184egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) 185{ 186 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 187 struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); 188 struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); 189 190 /* unreference the old framebuffers */ 191 if (gctx->draw.st_fb) { 192 EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); 193 void *priv; 194 195 priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); 196 if (!gdraw || priv != (void *) &gdraw->base) { 197 gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); 198 gctx->draw.st_fb = NULL; 199 gctx->draw.attachment_mask = 0x0; 200 } 201 202 if (is_equal) { 203 gctx->read.st_fb = NULL; 204 gctx->draw.attachment_mask = 0x0; 205 } 206 else { 207 priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); 208 if (!gread || priv != (void *) &gread->base) { 209 gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); 210 gctx->read.st_fb = NULL; 211 gctx->draw.attachment_mask = 0x0; 212 } 213 } 214 } 215 216 if (!gdraw) 217 return EGL_TRUE; 218 219 /* create the draw fb */ 220 if (!gctx->draw.st_fb) { 221 gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); 222 if (!gctx->draw.st_fb) 223 return EGL_FALSE; 224 } 225 226 /* create the read fb */ 227 if (!gctx->read.st_fb) { 228 if (gread != gdraw) { 229 gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); 230 if (!gctx->read.st_fb) { 231 gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); 232 gctx->draw.st_fb = NULL; 233 return EGL_FALSE; 234 } 235 } 236 else { 237 /* there is no st_reference_framebuffer... */ 238 gctx->read.st_fb = gctx->draw.st_fb; 239 } 240 } 241 242 egl_g3d_route_context(dpy, &gctx->base); 243 gctx->force_validate = EGL_TRUE; 244 245 return EGL_TRUE; 246} 247 248/** 249 * Return the state tracker for the given context. 250 */ 251static const struct egl_g3d_st * 252egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) 253{ 254 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 255 const struct egl_g3d_st *stapi; 256 EGLint idx = -1; 257 258 switch (ctx->ClientAPI) { 259 case EGL_OPENGL_ES_API: 260 switch (ctx->ClientVersion) { 261 case 1: 262 idx = EGL_G3D_ST_OPENGL_ES; 263 break; 264 case 2: 265 idx = EGL_G3D_ST_OPENGL_ES2; 266 break; 267 default: 268 _eglLog(_EGL_WARNING, "unknown client version %d", 269 ctx->ClientVersion); 270 break; 271 } 272 break; 273 case EGL_OPENVG_API: 274 idx = EGL_G3D_ST_OPENVG; 275 break; 276 case EGL_OPENGL_API: 277 idx = EGL_G3D_ST_OPENGL; 278 break; 279 default: 280 _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); 281 break; 282 } 283 284 stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; 285 return stapi; 286} 287 288/** 289 * Initialize the state trackers. 290 */ 291static void 292egl_g3d_init_st(_EGLDriver *drv) 293{ 294 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 295 EGLint i; 296 297 /* already initialized */ 298 if (gdrv->api_mask) 299 return; 300 301 for (i = 0; i < NUM_EGL_G3D_STS; i++) { 302 gdrv->stapis[i] = egl_g3d_get_st(i); 303 if (gdrv->stapis[i]) 304 gdrv->api_mask |= gdrv->stapis[i]->api_bit; 305 } 306 307 if (gdrv->api_mask) 308 _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); 309 else 310 _eglLog(_EGL_WARNING, "No supported client API"); 311} 312 313/** 314 * Get the probe object of the display. 315 * 316 * Note that this function may be called before the display is initialized. 317 */ 318static struct native_probe * 319egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy) 320{ 321 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 322 struct native_probe *nprobe; 323 324 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); 325 if (!nprobe || nprobe->display != dpy->NativeDisplay) { 326 if (nprobe) 327 nprobe->destroy(nprobe); 328 nprobe = native_create_probe(dpy->NativeDisplay); 329 _eglSetProbeCache(gdrv->probe_key, (void *) nprobe); 330 } 331 332 return nprobe; 333} 334 335/** 336 * Destroy the probe object of the display. The display may be NULL. 337 * 338 * Note that this function may be called before the display is initialized. 339 */ 340static void 341egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) 342{ 343 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 344 struct native_probe *nprobe; 345 346 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key); 347 if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) { 348 nprobe->destroy(nprobe); 349 _eglSetProbeCache(gdrv->probe_key, NULL); 350 } 351} 352 353/** 354 * Return an API mask that consists of the state trackers that supports the 355 * given mode. 356 * 357 * FIXME add st_is_mode_supported()? 358 */ 359static EGLint 360get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) 361{ 362 EGLint check; 363 364 /* OpenGL ES 1.x and 2.x are checked together */ 365 check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; 366 if (api_mask & check) { 367 /* this is required by EGL, not by OpenGL ES */ 368 if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) 369 api_mask &= ~check; 370 } 371 372 check = EGL_OPENVG_BIT; 373 if (api_mask & check) { 374 /* vega st needs the depth/stencil rb */ 375 if (!mode->depthBits && !mode->stencilBits) 376 api_mask &= ~check; 377 } 378 379 return api_mask; 380} 381 382#ifdef EGL_MESA_screen_surface 383 384static void 385egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) 386{ 387 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 388 const struct native_connector **native_connectors; 389 EGLint num_connectors, i; 390 391 native_connectors = 392 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL); 393 if (!num_connectors) { 394 if (native_connectors) 395 free(native_connectors); 396 return; 397 } 398 399 for (i = 0; i < num_connectors; i++) { 400 const struct native_connector *nconn = native_connectors[i]; 401 struct egl_g3d_screen *gscr; 402 const struct native_mode **native_modes; 403 EGLint num_modes, j; 404 405 /* TODO support for hotplug */ 406 native_modes = 407 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes); 408 if (!num_modes) { 409 if (native_modes) 410 free(native_modes); 411 continue; 412 } 413 414 gscr = CALLOC_STRUCT(egl_g3d_screen); 415 if (!gscr) { 416 free(native_modes); 417 continue; 418 } 419 420 _eglInitScreen(&gscr->base); 421 422 for (j = 0; j < num_modes; j++) { 423 const struct native_mode *nmode = native_modes[j]; 424 _EGLMode *mode; 425 426 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height, 427 nmode->refresh_rate, nmode->desc); 428 if (!mode) 429 break; 430 /* gscr->native_modes and gscr->base.Modes should be consistent */ 431 assert(mode == &gscr->base.Modes[j]); 432 } 433 434 gscr->native = nconn; 435 gscr->native_modes = native_modes; 436 437 _eglAddScreen(dpy, &gscr->base); 438 } 439 440 free(native_connectors); 441} 442 443#endif /* EGL_MESA_screen_surface */ 444 445/** 446 * Add configs to display and return the next config ID. 447 */ 448static EGLint 449egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) 450{ 451 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 452 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 453 const struct native_config **native_configs; 454 int num_configs, i; 455 456 native_configs = gdpy->native->get_configs(gdpy->native, 457 &num_configs); 458 if (!num_configs) { 459 if (native_configs) 460 free(native_configs); 461 return id; 462 } 463 464 for (i = 0; i < num_configs; i++) { 465 EGLint api_mask; 466 struct egl_g3d_config *gconf; 467 EGLBoolean valid; 468 469 gconf = CALLOC_STRUCT(egl_g3d_config); 470 if (!gconf) 471 continue; 472 473 _eglInitConfig(&gconf->base, dpy, id); 474 475 api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); 476 if (!api_mask) { 477 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", 478 native_configs[i]->mode.visualID); 479 } 480 481 valid = _eglConfigFromContextModesRec(&gconf->base, 482 &native_configs[i]->mode, api_mask, api_mask); 483 if (valid) { 484#ifdef EGL_MESA_screen_surface 485 /* check if scanout surface bit is set */ 486 if (native_configs[i]->scanout_bit) { 487 EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); 488 val |= EGL_SCREEN_BIT_MESA; 489 SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); 490 } 491#endif 492 valid = _eglValidateConfig(&gconf->base, EGL_FALSE); 493 } 494 if (!valid) { 495 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", 496 native_configs[i]->mode.visualID); 497 free(gconf); 498 continue; 499 } 500 501 gconf->native = native_configs[i]; 502 _eglAddConfig(dpy, &gconf->base); 503 id++; 504 } 505 506 free(native_configs); 507 return id; 508} 509 510/** 511 * Flush the front buffer of the context's draw surface. 512 */ 513static void 514egl_g3d_flush_frontbuffer(struct pipe_screen *screen, 515 struct pipe_surface *surf, void *context_private) 516{ 517 struct egl_g3d_context *gctx = egl_g3d_context(context_private); 518 struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface); 519 520 if (gsurf) 521 gsurf->native->flush_frontbuffer(gsurf->native); 522} 523 524/** 525 * Re-validate the context. 526 */ 527static void 528egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) 529{ 530 struct egl_g3d_context *gctx = egl_g3d_context(context_private); 531 532 /** 533 * It is likely that the surface has changed when this function is called. 534 * Set force_validate to skip an unnecessary check. 535 */ 536 gctx->force_validate = EGL_TRUE; 537 egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); 538} 539 540static EGLBoolean 541egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) 542{ 543 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 544 EGLint i; 545 546 _eglReleaseDisplayResources(drv, dpy); 547 _eglCleanupDisplay(dpy); 548 549 if (dpy->Screens) { 550 for (i = 0; i < dpy->NumScreens; i++) { 551 struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); 552 free(gscr->native_modes); 553 free(gscr); 554 } 555 free(dpy->Screens); 556 } 557 558 if (gdpy->native) 559 gdpy->native->destroy(gdpy->native); 560 561 free(gdpy); 562 dpy->DriverData = NULL; 563 564 return EGL_TRUE; 565} 566 567static EGLBoolean 568egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, 569 EGLint *major, EGLint *minor) 570{ 571 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 572 struct egl_g3d_display *gdpy; 573 574 /* the probe object is unlikely to be needed again */ 575 egl_g3d_destroy_probe(drv, dpy); 576 577 gdpy = CALLOC_STRUCT(egl_g3d_display); 578 if (!gdpy) { 579 _eglError(EGL_BAD_ALLOC, "eglInitialize"); 580 goto fail; 581 } 582 dpy->DriverData = gdpy; 583 584 gdpy->native = native_create_display(dpy->NativeDisplay); 585 if (!gdpy->native) { 586 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); 587 goto fail; 588 } 589 590 gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; 591 gdpy->native->screen->update_buffer = egl_g3d_update_buffer; 592 593 egl_g3d_init_st(&gdrv->base); 594 dpy->ClientAPIsMask = gdrv->api_mask; 595 596 if (egl_g3d_add_configs(drv, dpy, 1) == 1) { 597 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); 598 goto fail; 599 } 600 601#ifdef EGL_MESA_screen_surface 602 /* enable MESA_screen_surface */ 603 if (gdpy->native->modeset) { 604 dpy->Extensions.MESA_screen_surface = EGL_TRUE; 605 egl_g3d_add_screens(drv, dpy); 606 } 607#endif 608 609 *major = 1; 610 *minor = 4; 611 612 return EGL_TRUE; 613 614fail: 615 if (gdpy) 616 egl_g3d_terminate(drv, dpy); 617 return EGL_FALSE; 618} 619 620static _EGLContext * 621egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 622 _EGLContext *share, const EGLint *attribs) 623{ 624 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 625 struct egl_g3d_context *gshare = egl_g3d_context(share); 626 struct egl_g3d_config *gconf = egl_g3d_config(conf); 627 struct egl_g3d_context *gctx; 628 const __GLcontextModes *mode; 629 630 gctx = CALLOC_STRUCT(egl_g3d_context); 631 if (!gctx) { 632 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 633 return NULL; 634 } 635 636 if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { 637 free(gctx); 638 return NULL; 639 } 640 641 gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); 642 if (!gctx->stapi) { 643 free(gctx); 644 return NULL; 645 } 646 647 mode = &gconf->native->mode; 648 649 gctx->pipe = gdpy->native->screen->context_create( 650 gdpy->native->screen, 651 (void *) &gctx->base); 652 653 if (!gctx->pipe) { 654 free(gctx); 655 return NULL; 656 } 657 658 gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, 659 (gshare) ? gshare->st_ctx : NULL); 660 if (!gctx->st_ctx) { 661 gctx->pipe->destroy(gctx->pipe); 662 free(gctx); 663 return NULL; 664 } 665 666 return &gctx->base; 667} 668 669/** 670 * Destroy a context. 671 */ 672static void 673destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) 674{ 675 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 676 677 /* FIXME a context might live longer than its display */ 678 if (!dpy->Initialized) 679 _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); 680 681 egl_g3d_realloc_context(dpy, &gctx->base); 682 /* it will destroy the associated pipe context */ 683 gctx->stapi->st_destroy_context(gctx->st_ctx); 684 685 free(gctx); 686} 687 688static EGLBoolean 689egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 690{ 691 if (!_eglIsContextBound(ctx)) 692 destroy_context(dpy, ctx); 693 return EGL_TRUE; 694} 695 696static EGLBoolean 697init_surface_geometry(_EGLSurface *surf) 698{ 699 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 700 701 return gsurf->native->validate(gsurf->native, 0x0, 702 &gsurf->sequence_number, NULL, 703 &gsurf->base.Width, &gsurf->base.Height); 704} 705 706static _EGLSurface * 707egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, 708 _EGLConfig *conf, EGLNativeWindowType win, 709 const EGLint *attribs) 710{ 711 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 712 struct egl_g3d_config *gconf = egl_g3d_config(conf); 713 struct egl_g3d_surface *gsurf; 714 715 gsurf = CALLOC_STRUCT(egl_g3d_surface); 716 if (!gsurf) { 717 _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); 718 return NULL; 719 } 720 721 if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) { 722 free(gsurf); 723 return NULL; 724 } 725 726 gsurf->native = 727 gdpy->native->create_window_surface(gdpy->native, win, gconf->native); 728 if (!gsurf->native) { 729 free(gsurf); 730 return NULL; 731 } 732 733 if (!init_surface_geometry(&gsurf->base)) { 734 gsurf->native->destroy(gsurf->native); 735 free(gsurf); 736 return NULL; 737 } 738 739 gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER || 740 !gconf->native->mode.doubleBufferMode) ? 741 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; 742 743 return &gsurf->base; 744} 745 746static _EGLSurface * 747egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, 748 _EGLConfig *conf, EGLNativePixmapType pix, 749 const EGLint *attribs) 750{ 751 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 752 struct egl_g3d_config *gconf = egl_g3d_config(conf); 753 struct egl_g3d_surface *gsurf; 754 755 gsurf = CALLOC_STRUCT(egl_g3d_surface); 756 if (!gsurf) { 757 _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); 758 return NULL; 759 } 760 761 if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) { 762 free(gsurf); 763 return NULL; 764 } 765 766 gsurf->native = 767 gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native); 768 if (!gsurf->native) { 769 free(gsurf); 770 return NULL; 771 } 772 773 if (!init_surface_geometry(&gsurf->base)) { 774 gsurf->native->destroy(gsurf->native); 775 free(gsurf); 776 return NULL; 777 } 778 779 gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; 780 781 return &gsurf->base; 782} 783 784static _EGLSurface * 785egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, 786 _EGLConfig *conf, const EGLint *attribs) 787{ 788 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 789 struct egl_g3d_config *gconf = egl_g3d_config(conf); 790 struct egl_g3d_surface *gsurf; 791 792 gsurf = CALLOC_STRUCT(egl_g3d_surface); 793 if (!gsurf) { 794 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); 795 return NULL; 796 } 797 798 if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { 799 free(gsurf); 800 return NULL; 801 } 802 803 gsurf->native = 804 gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native, 805 gsurf->base.Width, gsurf->base.Height); 806 if (!gsurf->native) { 807 free(gsurf); 808 return NULL; 809 } 810 811 if (!init_surface_geometry(&gsurf->base)) { 812 gsurf->native->destroy(gsurf->native); 813 free(gsurf); 814 return NULL; 815 } 816 817 gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? 818 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; 819 820 return &gsurf->base; 821} 822 823/** 824 * Destroy a surface. 825 */ 826static void 827destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) 828{ 829 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 830 831 /* FIXME a surface might live longer than its display */ 832 if (!dpy->Initialized) 833 _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); 834 835 pipe_surface_reference(&gsurf->render_surface, NULL); 836 gsurf->native->destroy(gsurf->native); 837 free(gsurf); 838} 839 840static EGLBoolean 841egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 842{ 843 if (!_eglIsSurfaceBound(surf)) 844 destroy_surface(dpy, surf); 845 return EGL_TRUE; 846} 847 848static EGLBoolean 849egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, 850 _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) 851{ 852 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 853 struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); 854 struct egl_g3d_context *old_gctx; 855 EGLBoolean ok = EGL_TRUE; 856 857 /* bind the new context and return the "orphaned" one */ 858 if (!_eglBindContext(&ctx, &draw, &read)) 859 return EGL_FALSE; 860 old_gctx = egl_g3d_context(ctx); 861 862 if (old_gctx) { 863 /* flush old context */ 864 old_gctx->stapi->st_flush(old_gctx->st_ctx, 865 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 866 867 /* 868 * The old context is no longer current, and egl_g3d_realloc_context() 869 * should be called to destroy the framebuffers. However, it is possible 870 * that it will be made current again with the same draw/read surfaces. 871 * It might be better to keep it around. 872 */ 873 } 874 875 if (gctx) { 876 ok = egl_g3d_realloc_context(dpy, &gctx->base); 877 if (ok) { 878 ok = gctx->stapi->st_make_current(gctx->st_ctx, 879 gctx->draw.st_fb, gctx->read.st_fb); 880 if (ok) { 881 egl_g3d_validate_context(dpy, &gctx->base); 882 if (gdraw->base.Type == EGL_WINDOW_BIT) { 883 gctx->base.WindowRenderBuffer = 884 (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? 885 EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; 886 } 887 } 888 } 889 } 890 else if (old_gctx) { 891 ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL); 892 old_gctx->base.WindowRenderBuffer = EGL_NONE; 893 } 894 895 if (ctx && !_eglIsContextLinked(ctx)) 896 destroy_context(dpy, ctx); 897 if (draw && !_eglIsSurfaceLinked(draw)) 898 destroy_surface(dpy, draw); 899 if (read && read != draw && !_eglIsSurfaceLinked(read)) 900 destroy_surface(dpy, read); 901 902 return ok; 903} 904 905static EGLBoolean 906egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 907{ 908 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 909 _EGLContext *ctx = _eglGetCurrentContext(); 910 struct egl_g3d_context *gctx = NULL; 911 912 /* no-op for pixmap or pbuffer surface */ 913 if (gsurf->base.Type == EGL_PIXMAP_BIT || 914 gsurf->base.Type == EGL_PBUFFER_BIT) 915 return EGL_TRUE; 916 917 /* or when the surface is single-buffered */ 918 if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) 919 return EGL_TRUE; 920 921 if (ctx && ctx->DrawSurface == surf) 922 gctx = egl_g3d_context(ctx); 923 924 /* flush if the surface is current */ 925 if (gctx) 926 gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); 927 928 /* 929 * We drew on the back buffer, unless there was no back buffer. 930 * In that case, we drew on the front buffer. Either case, we call 931 * swap_buffers. 932 */ 933 if (!gsurf->native->swap_buffers(gsurf->native)) 934 return EGL_FALSE; 935 936 if (gctx) { 937 struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); 938 939 /* force validation if the swap method is not copy */ 940 if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) { 941 gctx->force_validate = EGL_TRUE; 942 egl_g3d_validate_context(dpy, &gctx->base); 943 } 944 } 945 946 return EGL_TRUE; 947} 948 949/** 950 * Find a config that supports the pixmap. 951 */ 952static _EGLConfig * 953find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) 954{ 955 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 956 struct egl_g3d_config *gconf; 957 EGLint i; 958 959 for (i = 0; i < dpy->NumConfigs; i++) { 960 gconf = egl_g3d_config(dpy->Configs[i]); 961 if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) 962 break; 963 } 964 965 return (i < dpy->NumConfigs) ? &gconf->base : NULL; 966} 967 968/** 969 * Get the pipe surface of the given attachment of the native surface. 970 */ 971static struct pipe_surface * 972get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, 973 enum native_attachment natt) 974{ 975 struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; 976 struct pipe_surface *psurf; 977 978 textures[natt] = NULL; 979 nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); 980 if (!textures[natt]) 981 return NULL; 982 983 psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], 984 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); 985 pipe_texture_reference(&textures[natt], NULL); 986 987 return psurf; 988} 989 990static EGLBoolean 991egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 992 EGLNativePixmapType target) 993{ 994 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 995 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 996 _EGLContext *ctx = _eglGetCurrentContext(); 997 struct egl_g3d_config *gconf; 998 struct native_surface *nsurf; 999 struct pipe_screen *screen = gdpy->native->screen; 1000 struct pipe_surface *psurf; 1001 1002 if (!gsurf->render_surface) 1003 return EGL_TRUE; 1004 1005 gconf = egl_g3d_config(find_pixmap_config(dpy, target)); 1006 if (!gconf) 1007 return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); 1008 1009 nsurf = gdpy->native->create_pixmap_surface(gdpy->native, 1010 target, gconf->native); 1011 if (!nsurf) 1012 return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); 1013 1014 /* flush if the surface is current */ 1015 if (ctx && ctx->DrawSurface == &gsurf->base) { 1016 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 1017 gctx->stapi->st_flush(gctx->st_ctx, 1018 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 1019 } 1020 1021 psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); 1022 if (psurf) { 1023 struct pipe_context pipe; 1024 1025 /** 1026 * XXX This is hacky. If we might allow the EGLDisplay to create a pipe 1027 * context of its own and use the blitter context for this. 1028 */ 1029 memset(&pipe, 0, sizeof(pipe)); 1030 pipe.screen = screen; 1031 1032 util_surface_copy(&pipe, FALSE, psurf, 0, 0, 1033 gsurf->render_surface, 0, 0, psurf->width, psurf->height); 1034 1035 pipe_surface_reference(&psurf, NULL); 1036 nsurf->flush_frontbuffer(nsurf); 1037 } 1038 1039 nsurf->destroy(nsurf); 1040 1041 return EGL_TRUE; 1042} 1043 1044static EGLBoolean 1045egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 1046{ 1047 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 1048 gctx->stapi->st_finish(gctx->st_ctx); 1049 return EGL_TRUE; 1050} 1051 1052static EGLBoolean 1053egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) 1054{ 1055 _EGLContext *ctx = _eglGetCurrentContext(); 1056 1057 if (engine != EGL_CORE_NATIVE_ENGINE) 1058 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 1059 1060 if (ctx && ctx->DrawSurface) { 1061 struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); 1062 gsurf->native->wait(gsurf->native); 1063 } 1064 1065 return EGL_TRUE; 1066} 1067 1068static _EGLProc 1069egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) 1070{ 1071 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 1072 _EGLProc proc; 1073 EGLint i; 1074 1075 /* in case this is called before a display is initialized */ 1076 egl_g3d_init_st(&gdrv->base); 1077 1078 for (i = 0; i < NUM_EGL_G3D_STS; i++) { 1079 const struct egl_g3d_st *stapi = gdrv->stapis[i]; 1080 if (stapi) { 1081 proc = (_EGLProc) stapi->st_get_proc_address(procname); 1082 if (proc) 1083 return proc; 1084 } 1085 } 1086 1087 return (_EGLProc) NULL; 1088} 1089 1090static EGLBoolean 1091egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, 1092 _EGLSurface *surf, EGLint buffer) 1093{ 1094 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 1095 _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); 1096 struct egl_g3d_context *gctx; 1097 enum pipe_format target_format; 1098 int target; 1099 1100 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) 1101 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); 1102 if (buffer != EGL_BACK_BUFFER) 1103 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); 1104 if (gsurf->base.BoundToTexture) 1105 return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); 1106 1107 switch (gsurf->base.TextureFormat) { 1108 case EGL_TEXTURE_RGB: 1109 target_format = PIPE_FORMAT_R8G8B8_UNORM; 1110 break; 1111 case EGL_TEXTURE_RGBA: 1112 target_format = PIPE_FORMAT_A8R8G8B8_UNORM; 1113 break; 1114 default: 1115 return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); 1116 } 1117 1118 switch (gsurf->base.TextureTarget) { 1119 case EGL_TEXTURE_2D: 1120 target = ST_TEXTURE_2D; 1121 break; 1122 default: 1123 return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); 1124 } 1125 1126 if (!es1) 1127 return EGL_TRUE; 1128 if (!gsurf->render_surface) 1129 return EGL_FALSE; 1130 1131 /* flush properly if the surface is bound */ 1132 if (gsurf->base.CurrentContext) { 1133 gctx = egl_g3d_context(gsurf->base.CurrentContext); 1134 gctx->stapi->st_flush(gctx->st_ctx, 1135 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 1136 } 1137 1138 gctx = egl_g3d_context(es1); 1139 gctx->stapi->st_bind_texture_surface(gsurf->render_surface, 1140 target, gsurf->base.MipmapLevel, target_format); 1141 1142 gsurf->base.BoundToTexture = EGL_TRUE; 1143 1144 return EGL_TRUE; 1145} 1146 1147static EGLBoolean 1148egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, 1149 _EGLSurface *surf, EGLint buffer) 1150{ 1151 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 1152 1153 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || 1154 !gsurf->base.BoundToTexture) 1155 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); 1156 if (buffer != EGL_BACK_BUFFER) 1157 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); 1158 1159 if (gsurf->render_surface) { 1160 _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); 1161 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 1162 1163 /* what if the context the surface binds to is no longer current? */ 1164 if (gctx) 1165 gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, 1166 ST_TEXTURE_2D, gsurf->base.MipmapLevel); 1167 } 1168 1169 gsurf->base.BoundToTexture = EGL_FALSE; 1170 1171 return EGL_TRUE; 1172} 1173 1174#ifdef EGL_MESA_screen_surface 1175 1176static _EGLSurface * 1177egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, 1178 _EGLConfig *conf, const EGLint *attribs) 1179{ 1180 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 1181 struct egl_g3d_config *gconf = egl_g3d_config(conf); 1182 struct egl_g3d_surface *gsurf; 1183 1184 gsurf = CALLOC_STRUCT(egl_g3d_surface); 1185 if (!gsurf) { 1186 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); 1187 return NULL; 1188 } 1189 1190 if (!_eglInitSurface(&gsurf->base, dpy, 1191 EGL_SCREEN_BIT_MESA, conf, attribs)) { 1192 free(gsurf); 1193 return NULL; 1194 } 1195 1196 gsurf->native = 1197 gdpy->native->modeset->create_scanout_surface(gdpy->native, 1198 gconf->native, gsurf->base.Width, gsurf->base.Height); 1199 if (!gsurf->native) { 1200 free(gsurf); 1201 return NULL; 1202 } 1203 1204 gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? 1205 NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; 1206 1207 return &gsurf->base; 1208} 1209 1210static EGLBoolean 1211egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, 1212 _EGLScreen *scr, _EGLSurface *surf, 1213 _EGLMode *mode) 1214{ 1215 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 1216 struct egl_g3d_screen *gscr = egl_g3d_screen(scr); 1217 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 1218 struct native_surface *nsurf; 1219 const struct native_mode *nmode; 1220 EGLBoolean changed; 1221 1222 if (gsurf) { 1223 EGLint idx; 1224 1225 if (!mode) 1226 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); 1227 if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) 1228 return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); 1229 if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) 1230 return _eglError(EGL_BAD_MATCH, 1231 "eglShowSurfaceMESA(surface smaller than mode size)"); 1232 1233 /* find the index of the mode */ 1234 for (idx = 0; idx < gscr->base.NumModes; idx++) 1235 if (mode == &gscr->base.Modes[idx]) 1236 break; 1237 if (idx >= gscr->base.NumModes) { 1238 return _eglError(EGL_BAD_MODE_MESA, 1239 "eglShowSurfaceMESA(unknown mode)"); 1240 } 1241 1242 nsurf = gsurf->native; 1243 nmode = gscr->native_modes[idx]; 1244 } 1245 else { 1246 if (mode) 1247 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); 1248 1249 /* disable the screen */ 1250 nsurf = NULL; 1251 nmode = NULL; 1252 } 1253 1254 /* TODO surface panning by CRTC choosing */ 1255 changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, 1256 gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); 1257 if (changed) { 1258 gscr->base.CurrentSurface = &gsurf->base; 1259 gscr->base.CurrentMode = mode; 1260 } 1261 1262 return changed; 1263} 1264 1265#endif /* EGL_MESA_screen_surface */ 1266 1267static EGLint 1268egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) 1269{ 1270 struct native_probe *nprobe; 1271 enum native_probe_result res; 1272 EGLint score; 1273 1274 nprobe = egl_g3d_get_probe(drv, dpy); 1275 res = native_get_probe_result(nprobe); 1276 1277 switch (res) { 1278 case NATIVE_PROBE_UNKNOWN: 1279 default: 1280 score = 0; 1281 break; 1282 case NATIVE_PROBE_FALLBACK: 1283 score = 40; 1284 break; 1285 case NATIVE_PROBE_SUPPORTED: 1286 score = 50; 1287 break; 1288 case NATIVE_PROBE_EXACT: 1289 score = 100; 1290 break; 1291 } 1292 1293 return score; 1294} 1295 1296static void 1297egl_g3d_unload(_EGLDriver *drv) 1298{ 1299 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 1300 1301 egl_g3d_destroy_probe(drv, NULL); 1302 free(gdrv); 1303} 1304 1305_EGLDriver * 1306_eglMain(const char *args) 1307{ 1308 static char driver_name[64]; 1309 struct egl_g3d_driver *gdrv; 1310 1311 snprintf(driver_name, sizeof(driver_name), 1312 "Gallium/%s", native_get_name()); 1313 1314 gdrv = CALLOC_STRUCT(egl_g3d_driver); 1315 if (!gdrv) 1316 return NULL; 1317 1318 _eglInitDriverFallbacks(&gdrv->base); 1319 1320 gdrv->base.API.Initialize = egl_g3d_initialize; 1321 gdrv->base.API.Terminate = egl_g3d_terminate; 1322 gdrv->base.API.CreateContext = egl_g3d_create_context; 1323 gdrv->base.API.DestroyContext = egl_g3d_destroy_context; 1324 gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface; 1325 gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; 1326 gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; 1327 gdrv->base.API.DestroySurface = egl_g3d_destroy_surface; 1328 gdrv->base.API.MakeCurrent = egl_g3d_make_current; 1329 gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers; 1330 gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers; 1331 gdrv->base.API.WaitClient = egl_g3d_wait_client; 1332 gdrv->base.API.WaitNative = egl_g3d_wait_native; 1333 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; 1334 1335 gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image; 1336 gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image; 1337 1338#ifdef EGL_MESA_screen_surface 1339 gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; 1340 gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; 1341#endif 1342 1343 gdrv->base.Name = driver_name; 1344 gdrv->base.Probe = egl_g3d_probe; 1345 gdrv->base.Unload = egl_g3d_unload; 1346 1347 /* the key is " EGL G3D" */ 1348 gdrv->probe_key = 0x0E61063D; 1349 1350 return &gdrv->base; 1351} 1352