Merge branch 'gallium-polygon-stipple'
[mesa.git] / src / glx / glxext.c
index 5930d7d5a8fe3b2a3d201d67243f786b857d65c6..8254544d1c01473e3cebfd129ee6400a0c9584ee 100644 (file)
@@ -41,7 +41,6 @@
 #include "glxclient.h"
 #include <X11/extensions/Xext.h>
 #include <X11/extensions/extutil.h>
-#include <X11/extensions/dri2proto.h>
 #ifdef GLX_USE_APPLEGL
 #include "apple_glx.h"
 #include "apple_visual.h"
@@ -131,28 +130,25 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
       aevent->count = awire->count;
       return True;
    }
-   /* No easy symbol to test for this, as GLX_BufferSwapComplete is
-    * defined in the local glx.h header, but the
-    * xGLXBufferSwapComplete typedef is only available in new versions
-    * of the external glxproto.h header, which doesn't have any
-    * testable versioning define.
-    *
-    * I'll use the related DRI2 define, in the hope that we won't
-    * receive these events unless we know how to ask for them:
-    */
-#ifdef X_DRI2SwapBuffers
    case GLX_BufferSwapComplete:
    {
       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
-      xGLXBufferSwapComplete *awire = (xGLXBufferSwapComplete *)wire;
+      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
+      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
       aevent->event_type = awire->event_type;
       aevent->drawable = awire->drawable;
       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
-      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
+
+      if (!glxDraw)
+        return False;
+
+      if (awire->sbc < glxDraw->lastEventSbc)
+        glxDraw->eventSbcWrap += 0x100000000;
+      glxDraw->lastEventSbc = awire->sbc;
+      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
       return True;
    }
-#endif
    default:
       /* client doesn't support server event */
       break;
@@ -197,7 +193,7 @@ __glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
 ** __glXScreenConfigs.
 */
 static void
-  FreeScreenConfigs(struct glx_display * priv)
+FreeScreenConfigs(struct glx_display * priv)
 {
    struct glx_screen *psc;
    GLint i, screens;
@@ -206,17 +202,7 @@ static void
    screens = ScreenCount(priv->dpy);
    for (i = 0; i < screens; i++) {
       psc = priv->screens[i];
-      if (psc->configs) {
-        glx_config_destroy_list(psc->configs);
-         if (psc->effectiveGLXexts)
-            Xfree(psc->effectiveGLXexts);
-         psc->configs = NULL;   /* NOTE: just for paranoia */
-      }
-      if (psc->visuals) {
-        glx_config_destroy_list(psc->visuals);
-        psc->visuals = NULL;   /* NOTE: just for paranoia */
-      }
-      Xfree((char *) psc->serverGLXexts);
+      glx_screen_cleanup(psc);
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
       if (psc->driScreen) {
@@ -232,28 +218,13 @@ static void
    priv->screens = NULL;
 }
 
-/*
-** Release the private memory referred to in a display private
-** structure.  The caller will free the extension structure.
-*/
-static int
-__glXCloseDisplay(Display * dpy, XExtCodes * codes)
+static void
+glx_display_free(struct glx_display *priv)
 {
-     struct glx_display *priv, **prev;
-     struct glx_context *gc;
-
-   _XLockMutex(_Xglobal_lock);
-   prev = &glx_displays;
-   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
-      if (priv->dpy == dpy) {
-        (*prev)->next = priv->next;
-        break;
-      }
-   }
-   _XUnlockMutex(_Xglobal_lock);
+   struct glx_context *gc;
 
    gc = __glXGetCurrentContext();
-   if (dpy == gc->currentDpy) {
+   if (priv->dpy == gc->currentDpy) {
       gc->vtable->destroy(gc);
       __glXSetCurrentContextNull();
    }
@@ -264,9 +235,11 @@ __glXCloseDisplay(Display * dpy, XExtCodes * codes)
    if (priv->serverGLXversion)
       Xfree((char *) priv->serverGLXversion);
 
-   __glxHashDestroy(priv->drawHash);
+   __glxHashDestroy(priv->glXDrawHash);
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+   __glxHashDestroy(priv->drawHash);
+
    /* Free the direct rendering per display data */
    if (priv->driswDisplay)
       (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
@@ -282,6 +255,24 @@ __glXCloseDisplay(Display * dpy, XExtCodes * codes)
 #endif
 
    Xfree((char *) priv);
+}
+
+static int
+__glXCloseDisplay(Display * dpy, XExtCodes * codes)
+{
+   struct glx_display *priv, **prev;
+
+   _XLockMutex(_Xglobal_lock);
+   prev = &glx_displays;
+   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
+      if (priv->dpy == dpy) {
+         *prev = priv->next;
+        break;
+      }
+   }
+   _XUnlockMutex(_Xglobal_lock);
+
+   glx_display_free(priv);
 
    return 1;
 }
@@ -565,6 +556,10 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
          config->yInverted = *bp++;
          break;
 #endif
+      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
+         config->sRGBCapable = *bp++;
+         break;
+
       case GLX_USE_GL:
          if (fbconfig_style_tags)
             bp++;
@@ -697,7 +692,7 @@ static GLboolean
    }
    else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
       GetReqExtra(GLXVendorPrivateWithReply,
-                  sz_xGLXGetFBConfigsSGIXReq +
+                  sz_xGLXGetFBConfigsSGIXReq -
                   sz_xGLXVendorPrivateWithReplyReq, vpreq);
       sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
       sgi_req->reqType = priv->majorOpcode;
@@ -737,12 +732,28 @@ glx_screen_init(struct glx_screen *psc,
    return GL_TRUE;
 }
 
+_X_HIDDEN void
+glx_screen_cleanup(struct glx_screen *psc)
+{
+   if (psc->configs) {
+      glx_config_destroy_list(psc->configs);
+      if (psc->effectiveGLXexts)
+          Xfree(psc->effectiveGLXexts);
+      psc->configs = NULL;   /* NOTE: just for paranoia */
+   }
+   if (psc->visuals) {
+      glx_config_destroy_list(psc->visuals);
+      psc->visuals = NULL;   /* NOTE: just for paranoia */
+   }
+   Xfree((char *) psc->serverGLXexts);
+}
+
 /*
 ** Allocate the memory for the per screen configs for each screen.
 ** If that works then fetch the per screen configs data.
 */
 static Bool
- AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
+AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
 {
    struct glx_screen *psc;
    GLint i, screens;
@@ -772,8 +783,13 @@ static Bool
       if (psc == NULL && priv->driswDisplay)
         psc = (*priv->driswDisplay->createScreen) (i, priv);
 #endif
+#if defined(GLX_USE_APPLEGL)
+      if (psc == NULL)
+         psc = applegl_create_screen(i, priv);
+#else
       if (psc == NULL)
         psc = indirect_create_screen(i, priv);
+#endif
       priv->screens[i] = psc;
    }
    SyncHandle();
@@ -786,7 +802,7 @@ static Bool
  _X_HIDDEN struct glx_display *
 __glXInitialize(Display * dpy)
 {
-    struct glx_display *dpyPriv;
+   struct glx_display *dpyPriv, *d;
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    Bool glx_direct, glx_accel;
 #endif
@@ -801,6 +817,9 @@ __glXInitialize(Display * dpy)
       }
    }
 
+   /* Drop the lock while we create the display private. */
+   _XUnlockMutex(_Xglobal_lock);
+
    dpyPriv = Xcalloc(1, sizeof *dpyPriv);
    if (!dpyPriv)
       return NULL;
@@ -833,6 +852,8 @@ __glXInitialize(Display * dpy)
    XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
    XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
 
+   dpyPriv->glXDrawHash = __glxHashCreate();
+
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
    glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
@@ -853,7 +874,7 @@ __glXInitialize(Display * dpy)
 #endif
 
 #ifdef GLX_USE_APPLEGL
-   if (apple_init_glx(dpy)) {
+   if (!applegl_create_display(dpyPriv)) {
       Xfree(dpyPriv);
       return NULL;
    }
@@ -866,6 +887,18 @@ __glXInitialize(Display * dpy)
    if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1)
       __glXClientInfo(dpy, dpyPriv->majorOpcode);
 
+   /* Grab the lock again and add the dispay private, unless somebody
+    * beat us to initializing on this display in the meantime. */
+   _XLockMutex(_Xglobal_lock);
+
+   for (d = glx_displays; d; d = d->next) {
+      if (d->dpy == dpy) {
+        _XUnlockMutex(_Xglobal_lock);
+        glx_display_free(dpyPriv);
+        return d;
+      }
+   }
+
    dpyPriv->next = glx_displays;
    glx_displays = dpyPriv;