glx: Send DestroyContext protocol at the correct times
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 7 Dec 2011 21:31:27 +0000 (13:31 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 19 Dec 2011 22:55:31 +0000 (14:55 -0800)
Send the DestroyContext protocol immediately when glXDestroyContext is
called, and never call it when glXFreeContextEXT is called.  In both
cases, either destroy the client-side structures or, if the context is
current, set xid to None so that the client-side structures will be
destroyed later.

I believe this restores the behavior of the original SGI code.  See
src/glx/x11 around commit 5df82c8.  The spec doesn't say anything
about glXDestroyContext not really destroying imported contexts (it
acts like glXFreeContextEXT instead), but that's what the original
code did.  Note that glXFreeContextEXT on a non-imported context does
not destroy it either.

Fixes the piglit test glx-free-context.

NOTE: This is a candidate for the 7.11 branch.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/glx/dri2_glx.c
src/glx/dri_glx.c
src/glx/drisw_glx.c
src/glx/glxclient.h
src/glx/glxcmds.c
src/glx/indirect_glx.c

index f929fddcf65c4ead3f83b9cce56b96e845f89eee..a9bcebf9b5d2fa6aa6c754da6c8c8e0d09dd63b3 100644 (file)
@@ -120,9 +120,6 @@ dri2_destroy_context(struct glx_context *context)
 
    driReleaseDrawables(&pcp->base);
 
-   if (context->xid)
-      glx_send_destroy_context(psc->base.dpy, context->xid);
-
    if (context->extensions)
       XFree((char *) context->extensions);
 
index 9365224a69643e34791fddbc38f22f68e0346a54..3c14ef05fff89f1f5bfbeb1cbec8132b2291e032 100644 (file)
@@ -516,9 +516,6 @@ dri_destroy_context(struct glx_context * context)
 
    driReleaseDrawables(&pcp->base);
 
-   if (context->xid)
-      glx_send_destroy_context(psc->base.dpy, context->xid);
-
    if (context->extensions)
       XFree((char *) context->extensions);
 
index 801ac7d470bc19559f82b010e6f41beb0d996084..204879efeca7e0485e51bb19fcab8fda26258c9e 100644 (file)
@@ -253,9 +253,6 @@ drisw_destroy_context(struct glx_context *context)
 
    driReleaseDrawables(&pcp->base);
 
-   if (context->xid)
-      glx_send_destroy_context(psc->base.dpy, context->xid);
-
    if (context->extensions)
       XFree((char *) context->extensions);
 
index f91542661016eb9ff9f8ba0f7a90007a55a44e64..109206f6ba03fe12e9df7ae09c02b965be18c641 100644 (file)
@@ -227,9 +227,6 @@ struct glx_context_vtable {
    void * (*get_proc_address)(const char *symbol);
 };
 
-extern void
-glx_send_destroy_context(Display *dpy, XID xid);
-
 /**
  * GLX state that needs to be kept on the client.  One of these records
  * exist for each context that has been made current by this client.
index f2c1884b8a5ce953be72b737bfbf57c2b41eba55..4f99023172da81a3c1dd1ce4cd505a485083792a 100644 (file)
@@ -381,7 +381,7 @@ glXCreateContext(Display * dpy, XVisualInfo * vis,
                         X_GLXCreateContext, renderType, vis->screen);
 }
 
-_X_HIDDEN void
+static void
 glx_send_destroy_context(Display *dpy, XID xid)
 {
    CARD8 opcode = __glXSetupForCommand(dpy);
@@ -405,25 +405,24 @@ glXDestroyContext(Display * dpy, GLXContext ctx)
 {
    struct glx_context *gc = (struct glx_context *) ctx;
 
-   if (!gc)
+   if (gc == NULL || gc->xid == None)
       return;
 
    __glXLock();
+   if (!gc->imported)
+      glx_send_destroy_context(dpy, gc->xid);
+
    if (gc->currentDpy) {
       /* This context is bound to some thread.  According to the man page,
        * we should not actually delete the context until it's unbound.
        * Note that we set gc->xid = None above.  In MakeContextCurrent()
        * we check for that and delete the context there.
        */
-      if (!gc->imported)
-        glx_send_destroy_context(dpy, gc->xid);
       gc->xid = None;
-      __glXUnlock();
-      return;
+   } else {
+      gc->vtable->destroy(gc);
    }
    __glXUnlock();
-
-   gc->vtable->destroy(gc);
 }
 
 /*
@@ -1566,9 +1565,30 @@ _X_EXPORT GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
    return (ctx == NULL) ? None : ctx->xid;
 }
 
-_X_EXPORT
-GLX_ALIAS_VOID(glXFreeContextEXT, (Display *dpy, GLXContext ctx), (dpy, ctx),
-              glXDestroyContext);
+_X_EXPORT void
+glXFreeContextEXT(Display *dpy, GLXContext ctx)
+{
+   struct glx_context *gc = (struct glx_context *) ctx;
+
+   if (gc == NULL || gc->xid == None)
+      return;
+
+   /* The GLX_EXT_import_context spec says:
+    *
+    *     "glXFreeContext does not free the server-side context information or
+    *     the XID associated with the server-side context."
+    *
+    * Don't send any protocol.  Just destroy the client-side tracking of the
+    * context.  Also, only release the context structure if it's not current.
+    */
+   __glXLock();
+   if (gc->currentDpy) {
+      gc->xid = None;
+   } else {
+      gc->vtable->destroy(gc);
+   }
+   __glXUnlock();
+}
 
 _X_EXPORT GLXFBConfig *
 glXChooseFBConfig(Display * dpy, int screen,
index 7b542dd159c6696dde58b6cee43f7a9f82d994f6..17689d45f2304801eab5ddc5ac788902b2b71646 100644 (file)
@@ -43,9 +43,6 @@ static struct _glapi_table *IndirectAPI = NULL;
 static void
 indirect_destroy_context(struct glx_context *gc)
 {
-   if (!gc->imported && gc->xid)
-      glx_send_destroy_context(gc->psc->dpy, gc->xid);
-
    __glXFreeVertexArrayState(gc);
 
    if (gc->vendor)