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