egl_g3d_api.c revision 4531356817ec8383ac35932903773de67af92e37
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#include "egldriver.h" 27#include "eglcurrent.h" 28#include "egllog.h" 29 30#include "pipe/p_screen.h" 31#include "util/u_memory.h" 32#include "util/u_inlines.h" 33 34#include "egl_g3d.h" 35#include "egl_g3d_api.h" 36#include "egl_g3d_image.h" 37#include "egl_g3d_sync.h" 38#include "egl_g3d_st.h" 39#include "egl_g3d_loader.h" 40#include "native.h" 41 42/** 43 * Return the state tracker for the given context. 44 */ 45static struct st_api * 46egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, 47 enum st_profile_type *profile) 48{ 49 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); 50 EGLint idx = -1; 51 52 switch (ctx->ClientAPI) { 53 case EGL_OPENGL_ES_API: 54 switch (ctx->ClientVersion) { 55 case 1: 56 idx = ST_API_OPENGL_ES1; 57 break; 58 case 2: 59 idx = ST_API_OPENGL_ES2; 60 break; 61 default: 62 _eglLog(_EGL_WARNING, "unknown client version %d", 63 ctx->ClientVersion); 64 break; 65 } 66 break; 67 case EGL_OPENVG_API: 68 idx = ST_API_OPENVG; 69 break; 70 case EGL_OPENGL_API: 71 idx = ST_API_OPENGL; 72 break; 73 default: 74 _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); 75 break; 76 } 77 78 switch (idx) { 79 case ST_API_OPENGL_ES1: 80 *profile = ST_PROFILE_OPENGL_ES1; 81 break; 82 case ST_API_OPENGL_ES2: 83 *profile = ST_PROFILE_OPENGL_ES2; 84 break; 85 default: 86 *profile = ST_PROFILE_DEFAULT; 87 break; 88 } 89 90 return (idx >= 0) ? gdrv->loader->get_st_api(idx) : NULL; 91} 92 93static _EGLContext * 94egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 95 _EGLContext *share, const EGLint *attribs) 96{ 97 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 98 struct egl_g3d_context *gshare = egl_g3d_context(share); 99 struct egl_g3d_config *gconf = egl_g3d_config(conf); 100 struct egl_g3d_context *gctx; 101 struct st_context_attribs stattribs; 102 103 gctx = CALLOC_STRUCT(egl_g3d_context); 104 if (!gctx) { 105 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 106 return NULL; 107 } 108 109 if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { 110 FREE(gctx); 111 return NULL; 112 } 113 114 memset(&stattribs, 0, sizeof(stattribs)); 115 if (gconf) 116 stattribs.visual = gconf->stvis; 117 118 gctx->stapi = egl_g3d_choose_st(drv, &gctx->base, &stattribs.profile); 119 if (!gctx->stapi) { 120 FREE(gctx); 121 return NULL; 122 } 123 124 gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, 125 &stattribs, (gshare) ? gshare->stctxi : NULL); 126 if (!gctx->stctxi) { 127 FREE(gctx); 128 return NULL; 129 } 130 131 gctx->stctxi->st_manager_private = (void *) &gctx->base; 132 133 return &gctx->base; 134} 135 136/** 137 * Destroy a context. 138 */ 139static void 140destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) 141{ 142 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 143 144 /* FIXME a context might live longer than its display */ 145 if (!dpy->Initialized) 146 _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); 147 148 gctx->stctxi->destroy(gctx->stctxi); 149 150 FREE(gctx); 151} 152 153static EGLBoolean 154egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 155{ 156 if (!_eglIsContextBound(ctx)) 157 destroy_context(dpy, ctx); 158 return EGL_TRUE; 159} 160 161struct egl_g3d_create_surface_arg { 162 EGLint type; 163 union { 164 EGLNativeWindowType win; 165 EGLNativePixmapType pix; 166 } u; 167}; 168 169static _EGLSurface * 170egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 171 struct egl_g3d_create_surface_arg *arg, 172 const EGLint *attribs) 173{ 174 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 175 struct egl_g3d_config *gconf = egl_g3d_config(conf); 176 struct egl_g3d_surface *gsurf; 177 struct native_surface *nsurf; 178 const char *err; 179 180 switch (arg->type) { 181 case EGL_WINDOW_BIT: 182 err = "eglCreateWindowSurface"; 183 break; 184 case EGL_PIXMAP_BIT: 185 err = "eglCreatePixmapSurface"; 186 break; 187#ifdef EGL_MESA_screen_surface 188 case EGL_SCREEN_BIT_MESA: 189 err = "eglCreateScreenSurface"; 190 break; 191#endif 192 default: 193 err = "eglCreateUnknownSurface"; 194 break; 195 } 196 197 gsurf = CALLOC_STRUCT(egl_g3d_surface); 198 if (!gsurf) { 199 _eglError(EGL_BAD_ALLOC, err); 200 return NULL; 201 } 202 203 if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { 204 FREE(gsurf); 205 return NULL; 206 } 207 208 /* create the native surface */ 209 switch (arg->type) { 210 case EGL_WINDOW_BIT: 211 nsurf = gdpy->native->create_window_surface(gdpy->native, 212 arg->u.win, gconf->native); 213 break; 214 case EGL_PIXMAP_BIT: 215 nsurf = gdpy->native->create_pixmap_surface(gdpy->native, 216 arg->u.pix, gconf->native); 217 break; 218#ifdef EGL_MESA_screen_surface 219 case EGL_SCREEN_BIT_MESA: 220 /* prefer back buffer (move to _eglInitSurface?) */ 221 gsurf->base.RenderBuffer = EGL_BACK_BUFFER; 222 nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, 223 gconf->native, gsurf->base.Width, gsurf->base.Height); 224 break; 225#endif 226 default: 227 nsurf = NULL; 228 break; 229 } 230 231 if (!nsurf) { 232 FREE(gsurf); 233 return NULL; 234 } 235 /* initialize the geometry */ 236 if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, 237 &gsurf->base.Width, &gsurf->base.Height)) { 238 nsurf->destroy(nsurf); 239 FREE(gsurf); 240 return NULL; 241 } 242 243 gsurf->stvis = gconf->stvis; 244 if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) 245 gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; 246 247 gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); 248 if (!gsurf->stfbi) { 249 nsurf->destroy(nsurf); 250 FREE(gsurf); 251 return NULL; 252 } 253 254 nsurf->user_data = &gsurf->base; 255 gsurf->native = nsurf; 256 257 return &gsurf->base; 258} 259 260static _EGLSurface * 261egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, 262 _EGLConfig *conf, EGLNativeWindowType win, 263 const EGLint *attribs) 264{ 265 struct egl_g3d_create_surface_arg arg; 266 267 memset(&arg, 0, sizeof(arg)); 268 arg.type = EGL_WINDOW_BIT; 269 arg.u.win = win; 270 271 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); 272} 273 274static _EGLSurface * 275egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, 276 _EGLConfig *conf, EGLNativePixmapType pix, 277 const EGLint *attribs) 278{ 279 struct egl_g3d_create_surface_arg arg; 280 281 memset(&arg, 0, sizeof(arg)); 282 arg.type = EGL_PIXMAP_BIT; 283 arg.u.pix = pix; 284 285 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); 286} 287 288static struct egl_g3d_surface * 289create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *conf, 290 const EGLint *attribs, const char *func) 291{ 292 struct egl_g3d_config *gconf = egl_g3d_config(conf); 293 struct egl_g3d_surface *gsurf; 294 295 gsurf = CALLOC_STRUCT(egl_g3d_surface); 296 if (!gsurf) { 297 _eglError(EGL_BAD_ALLOC, func); 298 return NULL; 299 } 300 301 if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { 302 FREE(gsurf); 303 return NULL; 304 } 305 306 gsurf->stvis = gconf->stvis; 307 308 gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); 309 if (!gsurf->stfbi) { 310 FREE(gsurf); 311 return NULL; 312 } 313 314 return gsurf; 315} 316 317static _EGLSurface * 318egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, 319 _EGLConfig *conf, const EGLint *attribs) 320{ 321 struct egl_g3d_surface *gsurf; 322 struct pipe_resource *ptex = NULL; 323 324 gsurf = create_pbuffer_surface(dpy, conf, attribs, 325 "eglCreatePbufferSurface"); 326 if (!gsurf) 327 return NULL; 328 329 gsurf->client_buffer_type = EGL_NONE; 330 331 if (!gsurf->stfbi->validate(gsurf->stfbi, 332 &gsurf->stvis.render_buffer, 1, &ptex)) { 333 egl_g3d_destroy_st_framebuffer(gsurf->stfbi); 334 FREE(gsurf); 335 return NULL; 336 } 337 338 return &gsurf->base; 339} 340 341static _EGLSurface * 342egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver *drv, _EGLDisplay *dpy, 343 EGLenum buftype, 344 EGLClientBuffer buffer, 345 _EGLConfig *conf, 346 const EGLint *attribs) 347{ 348 struct egl_g3d_surface *gsurf; 349 struct pipe_resource *ptex = NULL; 350 EGLint pbuffer_attribs[32]; 351 EGLint count, i; 352 353 switch (buftype) { 354 case EGL_OPENVG_IMAGE: 355 break; 356 default: 357 _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer"); 358 return NULL; 359 break; 360 } 361 362 /* parse the attributes first */ 363 count = 0; 364 for (i = 0; attribs && attribs[i] != EGL_NONE; i++) { 365 EGLint attr = attribs[i++]; 366 EGLint val = attribs[i]; 367 EGLint err = EGL_SUCCESS; 368 369 switch (attr) { 370 case EGL_TEXTURE_FORMAT: 371 case EGL_TEXTURE_TARGET: 372 case EGL_MIPMAP_TEXTURE: 373 pbuffer_attribs[count++] = attr; 374 pbuffer_attribs[count++] = val; 375 break; 376 default: 377 err = EGL_BAD_ATTRIBUTE; 378 break; 379 } 380 /* bail out */ 381 if (err != EGL_SUCCESS) { 382 _eglError(err, "eglCreatePbufferFromClientBuffer"); 383 return NULL; 384 } 385 } 386 387 pbuffer_attribs[count++] = EGL_NONE; 388 389 gsurf = create_pbuffer_surface(dpy, conf, pbuffer_attribs, 390 "eglCreatePbufferFromClientBuffer"); 391 if (!gsurf) 392 return NULL; 393 394 gsurf->client_buffer_type = buftype; 395 gsurf->client_buffer = buffer; 396 397 if (!gsurf->stfbi->validate(gsurf->stfbi, 398 &gsurf->stvis.render_buffer, 1, &ptex)) { 399 egl_g3d_destroy_st_framebuffer(gsurf->stfbi); 400 FREE(gsurf); 401 return NULL; 402 } 403 404 return &gsurf->base; 405} 406 407/** 408 * Destroy a surface. 409 */ 410static void 411destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) 412{ 413 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 414 415 /* FIXME a surface might live longer than its display */ 416 if (!dpy->Initialized) 417 _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); 418 419 pipe_resource_reference(&gsurf->render_texture, NULL); 420 egl_g3d_destroy_st_framebuffer(gsurf->stfbi); 421 if (gsurf->native) 422 gsurf->native->destroy(gsurf->native); 423 FREE(gsurf); 424} 425 426static EGLBoolean 427egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 428{ 429 if (!_eglIsSurfaceBound(surf)) 430 destroy_surface(dpy, surf); 431 return EGL_TRUE; 432} 433 434static EGLBoolean 435egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, 436 _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) 437{ 438 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 439 struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); 440 struct egl_g3d_surface *gread = egl_g3d_surface(read); 441 struct egl_g3d_context *old_gctx; 442 EGLBoolean ok = EGL_TRUE; 443 444 /* bind the new context and return the "orphaned" one */ 445 if (!_eglBindContext(&ctx, &draw, &read)) 446 return EGL_FALSE; 447 old_gctx = egl_g3d_context(ctx); 448 449 if (old_gctx) { 450 /* flush old context */ 451 old_gctx->stctxi->flush(old_gctx->stctxi, 452 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 453 } 454 455 if (gctx) { 456 ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi, 457 (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); 458 if (ok) { 459 if (gdraw) { 460 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, 461 gdraw->stfbi); 462 463 if (gdraw->base.Type == EGL_WINDOW_BIT) { 464 gctx->base.WindowRenderBuffer = 465 (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? 466 EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; 467 } 468 } 469 if (gread && gread != gdraw) { 470 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, 471 gread->stfbi); 472 } 473 } 474 } 475 else if (old_gctx) { 476 ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); 477 old_gctx->base.WindowRenderBuffer = EGL_NONE; 478 } 479 480 if (ctx && !_eglIsContextLinked(ctx)) 481 destroy_context(dpy, ctx); 482 if (draw && !_eglIsSurfaceLinked(draw)) 483 destroy_surface(dpy, draw); 484 if (read && read != draw && !_eglIsSurfaceLinked(read)) 485 destroy_surface(dpy, read); 486 487 return ok; 488} 489 490static EGLBoolean 491egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 492{ 493 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 494 _EGLContext *ctx = _eglGetCurrentContext(); 495 struct egl_g3d_context *gctx = NULL; 496 497 /* no-op for pixmap or pbuffer surface */ 498 if (gsurf->base.Type == EGL_PIXMAP_BIT || 499 gsurf->base.Type == EGL_PBUFFER_BIT) 500 return EGL_TRUE; 501 502 /* or when the surface is single-buffered */ 503 if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) 504 return EGL_TRUE; 505 506 if (ctx && ctx->DrawSurface == surf) 507 gctx = egl_g3d_context(ctx); 508 509 /* flush if the surface is current */ 510 if (gctx) { 511 gctx->stctxi->flush(gctx->stctxi, 512 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 513 } 514 515 return gsurf->native->swap_buffers(gsurf->native); 516} 517 518/** 519 * Get the pipe surface of the given attachment of the native surface. 520 */ 521static struct pipe_resource * 522get_pipe_resource(struct native_display *ndpy, struct native_surface *nsurf, 523 enum native_attachment natt) 524{ 525 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 526 527 textures[natt] = NULL; 528 nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); 529 530 return textures[natt]; 531} 532 533static EGLBoolean 534egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 535 EGLNativePixmapType target) 536{ 537 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 538 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 539 _EGLContext *ctx = _eglGetCurrentContext(); 540 struct egl_g3d_config *gconf; 541 struct native_surface *nsurf; 542 struct pipe_resource *ptex; 543 544 if (!gsurf->render_texture) 545 return EGL_TRUE; 546 547 gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); 548 if (!gconf) 549 return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); 550 551 nsurf = gdpy->native->create_pixmap_surface(gdpy->native, 552 target, gconf->native); 553 if (!nsurf) 554 return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); 555 556 /* flush if the surface is current */ 557 if (ctx && ctx->DrawSurface == &gsurf->base) { 558 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 559 gctx->stctxi->flush(gctx->stctxi, 560 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 561 } 562 563 /* create a pipe context to copy surfaces */ 564 if (!gdpy->pipe) { 565 gdpy->pipe = 566 gdpy->native->screen->context_create(gdpy->native->screen, NULL); 567 if (!gdpy->pipe) 568 return EGL_FALSE; 569 } 570 571 ptex = get_pipe_resource(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); 572 if (ptex) { 573 struct pipe_resource *psrc = gsurf->render_texture; 574 struct pipe_subresource subsrc, subdst; 575 subsrc.face = 0; 576 subsrc.level = 0; 577 subdst.face = 0; 578 subdst.level = 0; 579 580 if (psrc) { 581 gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, subdst, 0, 0, 0, 582 gsurf->render_texture, subsrc, 0, 0, 0, ptex->width0, ptex->height0); 583 584 nsurf->flush_frontbuffer(nsurf); 585 } 586 587 pipe_resource_reference(&ptex, NULL); 588 } 589 590 nsurf->destroy(nsurf); 591 592 return EGL_TRUE; 593} 594 595static EGLBoolean 596egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) 597{ 598 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 599 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 600 struct pipe_screen *screen = gdpy->native->screen; 601 struct pipe_fence_handle *fence = NULL; 602 603 gctx->stctxi->flush(gctx->stctxi, 604 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); 605 screen->fence_finish(screen, fence, 0); 606 screen->fence_reference(screen, &fence, NULL); 607 608 return EGL_TRUE; 609} 610 611static EGLBoolean 612egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) 613{ 614 _EGLContext *ctx = _eglGetCurrentContext(); 615 616 if (engine != EGL_CORE_NATIVE_ENGINE) 617 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 618 619 if (ctx && ctx->DrawSurface) { 620 struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); 621 622 if (gsurf->native) 623 gsurf->native->wait(gsurf->native); 624 } 625 626 return EGL_TRUE; 627} 628 629static EGLBoolean 630egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, 631 _EGLSurface *surf, EGLint buffer) 632{ 633 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 634 _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); 635 struct egl_g3d_context *gctx; 636 enum pipe_format internal_format; 637 enum st_texture_type target; 638 639 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) 640 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); 641 if (buffer != EGL_BACK_BUFFER) 642 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); 643 if (gsurf->base.BoundToTexture) 644 return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); 645 646 switch (gsurf->base.TextureFormat) { 647 case EGL_TEXTURE_RGB: 648 internal_format = PIPE_FORMAT_R8G8B8_UNORM; 649 break; 650 case EGL_TEXTURE_RGBA: 651 internal_format = PIPE_FORMAT_B8G8R8A8_UNORM; 652 break; 653 default: 654 return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); 655 } 656 657 switch (gsurf->base.TextureTarget) { 658 case EGL_TEXTURE_2D: 659 target = ST_TEXTURE_2D; 660 break; 661 default: 662 return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); 663 } 664 665 if (!es1) 666 return EGL_TRUE; 667 if (!gsurf->render_texture) 668 return EGL_FALSE; 669 670 /* flush properly if the surface is bound */ 671 if (gsurf->base.CurrentContext) { 672 gctx = egl_g3d_context(gsurf->base.CurrentContext); 673 gctx->stctxi->flush(gctx->stctxi, 674 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); 675 } 676 677 gctx = egl_g3d_context(es1); 678 if (gctx->stctxi->teximage) { 679 if (!gctx->stctxi->teximage(gctx->stctxi, target, 680 gsurf->base.MipmapLevel, internal_format, 681 gsurf->render_texture, gsurf->base.MipmapTexture)) 682 return EGL_FALSE; 683 gsurf->base.BoundToTexture = EGL_TRUE; 684 } 685 686 return EGL_TRUE; 687} 688 689static EGLBoolean 690egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, 691 _EGLSurface *surf, EGLint buffer) 692{ 693 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 694 695 if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || 696 !gsurf->base.BoundToTexture) 697 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); 698 if (buffer != EGL_BACK_BUFFER) 699 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); 700 701 if (gsurf->render_texture) { 702 _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); 703 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 704 705 /* what if the context the surface binds to is no longer current? */ 706 if (gctx) { 707 gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D, 708 gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE); 709 } 710 } 711 712 gsurf->base.BoundToTexture = EGL_FALSE; 713 714 return EGL_TRUE; 715} 716 717#ifdef EGL_MESA_screen_surface 718 719static _EGLSurface * 720egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, 721 _EGLConfig *conf, const EGLint *attribs) 722{ 723 struct egl_g3d_create_surface_arg arg; 724 725 memset(&arg, 0, sizeof(arg)); 726 arg.type = EGL_SCREEN_BIT_MESA; 727 728 return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); 729} 730 731static EGLBoolean 732egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, 733 _EGLScreen *scr, _EGLSurface *surf, 734 _EGLMode *mode) 735{ 736 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 737 struct egl_g3d_screen *gscr = egl_g3d_screen(scr); 738 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 739 struct native_surface *nsurf; 740 const struct native_mode *nmode; 741 EGLBoolean changed; 742 743 if (gsurf) { 744 EGLint idx; 745 746 if (!mode) 747 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); 748 if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) 749 return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); 750 if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) 751 return _eglError(EGL_BAD_MATCH, 752 "eglShowSurfaceMESA(surface smaller than mode size)"); 753 754 /* find the index of the mode */ 755 for (idx = 0; idx < gscr->base.NumModes; idx++) 756 if (mode == &gscr->base.Modes[idx]) 757 break; 758 if (idx >= gscr->base.NumModes) { 759 return _eglError(EGL_BAD_MODE_MESA, 760 "eglShowSurfaceMESA(unknown mode)"); 761 } 762 763 nsurf = gsurf->native; 764 nmode = gscr->native_modes[idx]; 765 } 766 else { 767 if (mode) 768 return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); 769 770 /* disable the screen */ 771 nsurf = NULL; 772 nmode = NULL; 773 } 774 775 /* TODO surface panning by CRTC choosing */ 776 changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, 777 gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); 778 if (changed) { 779 gscr->base.CurrentSurface = &gsurf->base; 780 gscr->base.CurrentMode = mode; 781 } 782 783 return changed; 784} 785 786#endif /* EGL_MESA_screen_surface */ 787 788/** 789 * Find a config that supports the pixmap. 790 */ 791_EGLConfig * 792egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) 793{ 794 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 795 struct egl_g3d_config *gconf; 796 EGLint i; 797 798 for (i = 0; i < dpy->Configs->Size; i++) { 799 gconf = egl_g3d_config((_EGLConfig *) dpy->Configs->Elements[i]); 800 if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) 801 break; 802 } 803 804 return (i < dpy->Configs->Size) ? &gconf->base : NULL; 805} 806 807void 808egl_g3d_init_driver_api(_EGLDriver *drv) 809{ 810 _eglInitDriverFallbacks(drv); 811 812 drv->API.CreateContext = egl_g3d_create_context; 813 drv->API.DestroyContext = egl_g3d_destroy_context; 814 drv->API.CreateWindowSurface = egl_g3d_create_window_surface; 815 drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; 816 drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; 817 drv->API.CreatePbufferFromClientBuffer = egl_g3d_create_pbuffer_from_client_buffer; 818 drv->API.DestroySurface = egl_g3d_destroy_surface; 819 drv->API.MakeCurrent = egl_g3d_make_current; 820 drv->API.SwapBuffers = egl_g3d_swap_buffers; 821 drv->API.CopyBuffers = egl_g3d_copy_buffers; 822 drv->API.WaitClient = egl_g3d_wait_client; 823 drv->API.WaitNative = egl_g3d_wait_native; 824 825 drv->API.BindTexImage = egl_g3d_bind_tex_image; 826 drv->API.ReleaseTexImage = egl_g3d_release_tex_image; 827 828 drv->API.CreateImageKHR = egl_g3d_create_image; 829 drv->API.DestroyImageKHR = egl_g3d_destroy_image; 830#ifdef EGL_MESA_drm_image 831 drv->API.CreateDRMImageMESA = egl_g3d_create_drm_image; 832 drv->API.ExportDRMImageMESA = egl_g3d_export_drm_image; 833#endif 834 835#ifdef EGL_KHR_reusable_sync 836 drv->API.CreateSyncKHR = egl_g3d_create_sync; 837 drv->API.DestroySyncKHR = egl_g3d_destroy_sync; 838 drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync; 839 drv->API.SignalSyncKHR = egl_g3d_signal_sync; 840#endif 841 842#ifdef EGL_MESA_screen_surface 843 drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; 844 drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; 845#endif 846} 847