egl: eglMakeCurrent should accept an uninitialized display.
authorChia-I Wu <olvaffe@gmail.com>
Wed, 27 Jan 2010 15:51:54 +0000 (23:51 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Thu, 28 Jan 2010 09:28:47 +0000 (17:28 +0800)
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.

src/egl/drivers/glx/egl_glx.c
src/egl/drivers/xdri/egl_xdri.c
src/egl/main/eglapi.c
src/egl/main/eglapi.h
src/egl/main/eglcontext.c
src/gallium/state_trackers/egl/common/egl_g3d.c

index 89a4353f8a8b19195eefbc9e7dad38a95819d862..5efb72e875416a543f5bce4ad242bc160fc8c5e2 100644 (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;
 }
index e13d884e71573e6141e9062d82567050c8ba9ae8..26fe95b043107667b86165de838ce124260fde68 100644 (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;
 }
 
index 2c26dfada8e7ad9fbe6ddd50795b831f9fbe945d..d0f9749f84f553e6d090b55fcd9ef95dc5cdede6 100644 (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);
          }
       }
    }
index db31c7cf937cbe3fcebb3dead8744efcf0539339..a7600820f3f75a20099cb674cdb670229d727f45 100644 (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);
 
index 4a9a47204cd538653781a8ecad449412082b19cd..60d2efd44b9015d806140a13b89737b3131e67e7 100644 (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;
-
-   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);
+   /* 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);
+   }
 
    return EGL_TRUE;
 }
index aa4f01221694fc6247b5a51435a8b82189e6ad13..657c771a6b150629d1753d5bc430367bd0a3623f 100644 (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;
 }