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