glx: MakeCurrent fixes.
authorThomas Hellstrom <thellstrom-at-vmware-dot-com>
Thu, 2 Apr 2009 09:00:41 +0000 (11:00 +0200)
committerThomas Hellstrom <thellstrom-at-vmware-dot-com>
Thu, 2 Apr 2009 09:33:20 +0000 (11:33 +0200)
1) If MakeContextCurrent is called with (NULL, None, None), Don't
   send the request to the X server if the current context is direct.
2) Return BadMatch in some error cases according to the glx spec.
3) If MakeContextCurrent is called for a context which is current in
   another thread, return BadAccess according to the glx spec.

Signed-off-by: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
src/glx/x11/glxclient.h
src/glx/x11/glxcurrent.c

index fa3ec26e60a663eddf5e8d1edd50d6706414fb66..bf68d0f8910dfafd77a2988c1ae14d0f26e220e1 100644 (file)
@@ -426,6 +426,11 @@ struct __GLXcontextRec {
    int server_minor;        /**< Minor version number. */
     /*@}*/
 
+   /**
+    * Thread ID we're currently current in. Zero if none.
+    */
+   unsigned long thread_id;
+
     char gl_extension_bits[ __GL_EXT_BYTES ];
 };
 
index 4d0a7c65eba56ebe3d54332bef74d408c165ec72..01f42332413ea0efb323f33a828e85ffe14ba1c6 100644 (file)
@@ -339,6 +339,20 @@ FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc)
 }
 #endif /* GLX_DIRECT_RENDERING */
 
+static void
+__glXGenerateError(Display *dpy, GLXContext gc, XID resource,
+                  BYTE errorCode, CARD16 minorCode)
+{
+   xError error;
+
+   error.errorCode = errorCode;
+   error.resourceID = resource;
+   error.sequenceNumber = dpy->request;
+   error.type = X_Error;
+   error.majorCode = gc->majorOpcode;
+   error.minorCode = minorCode;
+   _XError(dpy, &error);
+}
 
 /**
  * Make a particular context current.
@@ -369,8 +383,26 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
       return GL_FALSE;
    }
 
+   if (gc == NULL && (draw != None || read != None)) {
+      __glXGenerateError(dpy, gc, (draw != None) ? draw : read,
+                        BadMatch, X_GLXMakeContextCurrent);
+      return False;
+   }
+   if (gc != NULL && (draw == None || read == None)) {
+      __glXGenerateError(dpy, gc, None,
+                        BadMatch, X_GLXMakeContextCurrent);
+      return False;
+   }
+
    _glapi_check_multithread();
 
+   if (gc != NULL && gc->thread_id != 0 &&
+       gc->thread_id != _glthread_GetID()) {
+      __glXGenerateError(dpy, gc, gc->xid,
+                        BadAccess, X_GLXMakeContextCurrent);
+      return False;
+   }
+
 #ifdef GLX_DIRECT_RENDERING
    /* Bind the direct rendering context to the drawable */
    if (gc && gc->driContext) {
@@ -378,21 +410,17 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
       __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc);
 
       if ((pdraw == NULL) || (pread == NULL)) {
-         xError error;
-
-         error.errorCode = GLXBadDrawable;
-         error.resourceID = (pdraw == NULL) ? draw : read;
-         error.sequenceNumber = dpy->request;
-         error.type = X_Error;
-         error.majorCode = gc->majorOpcode;
-         error.minorCode = X_GLXMakeContextCurrent;
-         _XError(dpy, &error);
+         __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read,
+                           GLXBadDrawable, X_GLXMakeContextCurrent);
          return False;
       }
 
       bindReturnValue =
          (gc->driContext->bindContext) (gc->driContext, pdraw, pread);
    }
+   else if (!gc && oldGC && oldGC->driContext) {
+      bindReturnValue = True;
+   }
    else
 #endif
    {
@@ -453,6 +481,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
          oldGC->currentDrawable = None;
          oldGC->currentReadable = None;
          oldGC->currentContextTag = 0;
+         oldGC->thread_id = 0;
 
          if (oldGC->xid == None) {
             /* We are switching away from a context that was
@@ -477,6 +506,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
          gc->currentDpy = dpy;
          gc->currentDrawable = draw;
          gc->currentReadable = read;
+         gc->thread_id = _glthread_GetID();
 
 #ifdef GLX_DIRECT_RENDERING
          if (!gc->driContext) {