Mesa (master): egl: eglMakeCurrent should accept an uninitialized display.

Chia-I Wu olv at kemper.freedesktop.org
Thu Jan 28 09:31:13 UTC 2010


Module: Mesa
Branch: master
Commit: 17330479b39409a63a06ec9e6b0f8e28b585db12
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=17330479b39409a63a06ec9e6b0f8e28b585db12

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Wed Jan 27 23:51:54 2010 +0800

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.

---

 src/egl/drivers/glx/egl_glx.c                   |   64 ++++++++++------------
 src/egl/drivers/xdri/egl_xdri.c                 |   53 +++++++++++++-----
 src/egl/main/eglapi.c                           |   18 +++++--
 src/egl/main/eglapi.h                           |    1 +
 src/egl/main/eglcontext.c                       |   23 +++++----
 src/gallium/state_trackers/egl/common/egl_g3d.c |   40 +++++++++++----
 6 files changed, 124 insertions(+), 75 deletions(-)

diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index 89a4353..5efb72e 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -103,6 +103,8 @@ struct GLX_egl_surface
 
    Drawable drawable;
    GLXDrawable glx_drawable;
+
+   void (*destroy)(Display *, GLXDrawable);
 };
 
 
@@ -631,6 +633,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().
  */
 static EGLBoolean
@@ -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;
 }
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
index e13d884..26fe95b 100644
--- a/src/egl/drivers/xdri/egl_xdri.c
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -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;
 }
 
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 2c26dfa..d0f9749 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -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);
          }
       }
    }
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index db31c7c..a760082 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -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);
 
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 4a9a472..60d2efd 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -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;
 }
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index aa4f012..657c771 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -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;
 }
 




More information about the mesa-commit mailing list