egl: eglMakeCurrent should accept an uninitialized display.

When no context or surface are given, the display is allowed to be
uninitialized.  Most drivers cannot handle an uninitialized display.
But they are updated to at least throw a fatal message.
This commit is contained in:
Chia-I Wu 2010-01-27 23:51:54 +08:00
parent 959481ad70
commit 17330479b3
6 changed files with 123 additions and 74 deletions

View file

@ -103,6 +103,8 @@ struct GLX_egl_surface
Drawable drawable;
GLXDrawable glx_drawable;
void (*destroy)(Display *, GLXDrawable);
};
@ -630,6 +632,21 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
}
/**
* Destroy a surface. The display is allowed to be uninitialized.
*/
static void
destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
{
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
if (GLX_surf->destroy)
GLX_surf->destroy(disp->NativeDisplay, GLX_surf->glx_drawable);
free(GLX_surf);
}
/**
* Called via eglMakeCurrent(), drv->API.MakeCurrent().
*/
@ -712,6 +729,9 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
return NULL;
}
if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
GLX_surf->destroy = glXDestroyWindow;
get_drawable_size(GLX_dpy->dpy, window, &width, &height);
GLX_surf->Base.Width = width;
GLX_surf->Base.Height = height;
@ -769,6 +789,9 @@ GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp,
return NULL;
}
GLX_surf->destroy = (GLX_dpy->have_1_3) ?
glXDestroyPixmap : glXDestroyGLXPixmap;
get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
GLX_surf->Base.Width = width;
GLX_surf->Base.Height = height;
@ -833,47 +856,18 @@ GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
return NULL;
}
GLX_surf->destroy = (GLX_dpy->have_1_3) ?
glXDestroyPbuffer : GLX_dpy->glXDestroyGLXPbufferSGIX;
return &GLX_surf->Base;
}
static EGLBoolean
GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
{
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
if (!_eglIsSurfaceBound(surf)) {
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
if (GLX_dpy->have_1_3) {
switch (surf->Type) {
case EGL_WINDOW_BIT:
if (!GLX_dpy->glx_window_quirk)
glXDestroyWindow(GLX_dpy->dpy, GLX_surf->glx_drawable);
break;
case EGL_PBUFFER_BIT:
glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->glx_drawable);
break;
case EGL_PIXMAP_BIT:
glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
break;
default:
break;
}
}
else {
switch (surf->Type) {
case EGL_PBUFFER_BIT:
GLX_dpy->glXDestroyGLXPbufferSGIX(GLX_dpy->dpy,
GLX_surf->glx_drawable);
break;
case EGL_PIXMAP_BIT:
glXDestroyGLXPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
break;
default:
break;
}
}
free(surf);
}
if (!_eglIsSurfaceBound(surf))
destroy_surface(disp, surf);
return EGL_TRUE;
}

View file

@ -419,19 +419,47 @@ xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
}
static EGLBoolean
xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
/**
* Destroy a context.
*/
static void
destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
{
struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
struct xdri_egl_context *xdri_ctx = lookup_context(ctx);
if (!_eglIsContextBound(ctx)) {
xdri_ctx->driContext->destroyContext(xdri_ctx->driContext,
xdri_dpy->psc, xdri_dpy->dpy);
free(xdri_ctx->dummy_gc);
free(xdri_ctx);
}
/* FIXME a context might live longer than its display */
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
xdri_ctx->driContext->destroyContext(xdri_ctx->driContext,
xdri_dpy->psc, xdri_dpy->dpy);
free(xdri_ctx->dummy_gc);
free(xdri_ctx);
}
/**
* Destroy a surface.
*/
static void
destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
{
struct xdri_egl_surface *xdri_surf = lookup_surface(surf);
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable);
free(xdri_surf);
}
static EGLBoolean
xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
if (!_eglIsContextBound(ctx))
destroy_context(dpy, ctx);
return EGL_TRUE;
}
@ -539,13 +567,8 @@ xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf
static EGLBoolean
xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
{
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
if (!_eglIsSurfaceBound(&xdri_surf->Base)) {
xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable);
free(xdri_surf);
}
if (!_eglIsSurfaceBound(surface))
destroy_surface(dpy, surface);
return EGL_TRUE;
}

View file

@ -394,9 +394,19 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
_EGLSurface *read_surf = _eglLookupSurface(read, disp);
_EGLDriver *drv;
drv = _eglCheckDisplay(disp, __FUNCTION__);
if (!disp)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
drv = disp->Driver;
/* display is allowed to be uninitialized under certain condition */
if (!disp->Initialized) {
if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
ctx != EGL_NO_CONTEXT)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
}
if (!drv)
return EGL_FALSE;
return EGL_TRUE;
if (!context && ctx != EGL_NO_CONTEXT)
return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
if ((!draw_surf && draw != EGL_NO_SURFACE) ||
@ -994,9 +1004,7 @@ eglReleaseThread(void)
if (ctx) {
_EGLDisplay *disp = ctx->Resource.Display;
_EGLDriver *drv = disp->Driver;
/* what if display is not initialized? */
if (disp->Initialized)
(void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
(void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
}
}
}

View file

@ -23,6 +23,7 @@ typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLC
/* context funcs */
typedef _EGLContext *(*CreateContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, _EGLContext *share_list, const EGLint *attrib_list);
typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
/* this is the only function (other than Initialize) that may be called with an uninitialized display */
typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx);
typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value);

View file

@ -321,16 +321,19 @@ _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
if (!_eglBindContext(&ctx, &draw, &read))
return EGL_FALSE;
/* avoid double destroy */
if (read && read == draw)
read = NULL;
/* nothing we can do if the display is uninitialized */
if (dpy->Initialized) {
/* avoid double destroy */
if (read && read == draw)
read = NULL;
if (ctx && !_eglIsContextLinked(ctx))
drv->API.DestroyContext(drv, dpy, ctx);
if (draw && !_eglIsSurfaceLinked(draw))
drv->API.DestroySurface(drv, dpy, draw);
if (read && !_eglIsSurfaceLinked(read))
drv->API.DestroySurface(drv, dpy, read);
if (ctx && !_eglIsContextLinked(ctx))
drv->API.DestroyContext(drv, dpy, ctx);
if (draw && !_eglIsSurfaceLinked(draw))
drv->API.DestroySurface(drv, dpy, draw);
if (read && !_eglIsSurfaceLinked(read))
drv->API.DestroySurface(drv, dpy, read);
}
return EGL_TRUE;
}

View file

@ -672,21 +672,30 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
return &gctx->base;
}
static EGLBoolean
egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
/**
* Destroy a context.
*/
static void
destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
{
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
if (_eglIsContextBound(&gctx->base))
return EGL_TRUE;
/* FIXME a context might live longer than its display */
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
egl_g3d_realloc_context(dpy, &gctx->base);
/* it will destroy pipe context */
/* it will destroy the associated pipe context */
gctx->stapi->st_destroy_context(gctx->st_ctx);
free(gctx);
}
static EGLBoolean
egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
if (!_eglIsContextBound(ctx))
destroy_context(dpy, ctx);
return EGL_TRUE;
}
@ -817,17 +826,28 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
return &gsurf->base;
}
static EGLBoolean
egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
/**
* Destroy a surface.
*/
static void
destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
if (_eglIsSurfaceBound(&gsurf->base))
return EGL_TRUE;
/* FIXME a surface might live longer than its display */
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
pipe_surface_reference(&gsurf->render_surface, NULL);
gsurf->native->destroy(gsurf->native);
free(gsurf);
}
static EGLBoolean
egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
if (!_eglIsSurfaceBound(surf))
destroy_surface(dpy, surf);
return EGL_TRUE;
}