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