diff options
Diffstat (limited to 'src/egl')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 19 | ||||
-rw-r--r-- | src/egl/main/eglcontext.c | 85 |
2 files changed, 75 insertions, 29 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 15b3529cd2..8b6f78cdc9 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -54,6 +54,8 @@ struct dri2_egl_driver { _EGLDriver base; + + void (*glFlush)(void); }; struct dri2_egl_display @@ -760,6 +762,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, disp->Extensions.KHR_image_base = EGL_TRUE; disp->Extensions.KHR_image_pixmap = EGL_TRUE; disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; /* we're supporting EGL 1.4 */ *major = 1; @@ -873,6 +876,7 @@ static EGLBoolean dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf, _EGLContext *ctx) { + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); @@ -884,6 +888,10 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, if (!_eglBindContext(&ctx, &dsurf, &rsurf)) return EGL_FALSE; + /* flush before context switch */ + if (ctx && dri2_drv->glFlush) + dri2_drv->glFlush(); + ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; @@ -1011,10 +1019,18 @@ dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + _EGLContext *ctx; xcb_dri2_copy_region_cookie_t cookie; + if (dri2_drv->glFlush) { + ctx = _eglGetCurrentContext(); + if (ctx && ctx->DrawSurface == &dri2_surf->base) + dri2_drv->glFlush(); + } + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); #if 0 @@ -1352,5 +1368,8 @@ _eglMain(const char *args) dri2_drv->base.Name = "DRI2"; dri2_drv->base.Unload = dri2_unload; + dri2_drv->glFlush = + (void (*)(void)) dri2_get_proc_address(&dri2_drv->base, "glFlush"); + return &dri2_drv->base; } diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 012d8dfe1f..d5a1e79a99 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -208,25 +208,56 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, * bound to; when the context is NULL, the same surfaces are returned. */ static void -_eglBindContextToSurfaces(_EGLContext *ctx, +_eglBindContextToSurfaces(_EGLContext *newCtx, _EGLSurface **draw, _EGLSurface **read) { _EGLSurface *newDraw = *draw, *newRead = *read; + _EGLContext *oldCtx; + + /* + * The goal is to bind a newCtx to newDraw. Since newDraw may already have + * a binding context (oldCtx), and newCtx may already be bound to another + * surface (oldDraw), the old bindings are broken first and the new one is + * created. + */ + oldCtx = newDraw->CurrentContext; + if (newCtx != oldCtx) { + if (oldCtx) { + assert(oldCtx->DrawSurface == newDraw); + oldCtx->DrawSurface = NULL; + } + + if (newCtx) { + _EGLSurface *oldDraw = newCtx->DrawSurface; + if (oldDraw) + oldDraw->CurrentContext = NULL; + + newCtx->DrawSurface = newDraw; + *draw = oldDraw; + } + + newDraw->CurrentContext = newCtx; + } - if (newDraw->CurrentContext) - newDraw->CurrentContext->DrawSurface = NULL; - newDraw->CurrentContext = ctx; + /* likewise */ + if (newRead != newDraw) + oldCtx = newRead->CurrentContext; + if (newCtx != oldCtx) { + if (oldCtx) { + assert(oldCtx->ReadSurface == newRead); + oldCtx->ReadSurface = NULL; + } - if (newRead->CurrentContext) - newRead->CurrentContext->ReadSurface = NULL; - newRead->CurrentContext = ctx; + if (newCtx) { + _EGLSurface *oldRead = newCtx->ReadSurface; + if (oldRead) + oldRead->CurrentContext = NULL; - if (ctx) { - *draw = ctx->DrawSurface; - ctx->DrawSurface = newDraw; + newCtx->ReadSurface = newRead; + *read = oldRead; + } - *read = ctx->ReadSurface; - ctx->ReadSurface = newRead; + newRead->CurrentContext = newCtx; } } @@ -246,15 +277,14 @@ _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex; oldCtx = t->CurrentContexts[apiIndex]; - if (ctx == oldCtx) - return NULL; + if (ctx != oldCtx) { + if (oldCtx) + oldCtx->Binding = NULL; + if (ctx) + ctx->Binding = t; - if (oldCtx) - oldCtx->Binding = NULL; - if (ctx) - ctx->Binding = t; - - t->CurrentContexts[apiIndex] = ctx; + t->CurrentContexts[apiIndex] = ctx; + } return oldCtx; } @@ -347,19 +377,13 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read) /* bind the new context */ oldCtx = _eglBindContextToThread(newCtx, t); - *ctx = oldCtx; + if (newCtx) _eglBindContextToSurfaces(newCtx, draw, read); /* unbind the old context from its binding surfaces */ - if (oldCtx) { - /* - * If the new context replaces some old context, the new one should not - * be current before the replacement and it should not be bound to any - * surface. - */ - if (newCtx) - assert(!*draw && !*read); + if (oldCtx && oldCtx != newCtx) { + assert(!*draw && !*read); *draw = oldCtx->DrawSurface; *read = oldCtx->ReadSurface; @@ -368,6 +392,9 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read) _eglBindContextToSurfaces(NULL, draw, read); } + *ctx = oldCtx; + /* draw and read have been updated in _eglBindContextToSurfaces */ + return EGL_TRUE; } |