[PATCH 3/5] glx: Implement GLX_EXT_swap_control

Adam Jackson ajax at redhat.com
Tue Jun 2 10:41:06 PDT 2015


This is incomplete, as it does not update the generated code to include
the dispatch code.

Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 glx/extension_string.c  |  1 +
 glx/extension_string.h  |  1 +
 glx/glxcmds.c           | 21 +++++++++++++--
 glx/glxdrawable.h       |  4 +--
 glx/glxdri2.c           |  5 +---
 glx/glxdricommon.c      |  2 ++
 glx/glxscreens.h        |  4 +++
 glx/glxserver.h         |  4 +++
 glx/indirect_dispatch.h |  7 +++++
 glx/swap_interval.c     | 69 ++++++++++++++++++++++++++++++++++++-------------
 10 files changed, 91 insertions(+), 27 deletions(-)

diff --git a/glx/extension_string.c b/glx/extension_string.c
index e881d21..d2c942b 100644
--- a/glx/extension_string.c
+++ b/glx/extension_string.c
@@ -83,6 +83,7 @@ static const struct extension_info known_glx_extensions[] = {
     { GLX(EXT_create_context_es2_profile), VER(0,0), N, },
     { GLX(EXT_framebuffer_sRGB),        VER(0,0), N, },
     { GLX(EXT_import_context),          VER(0,0), Y, },
+    { GLX(EXT_swap_control),            VER(0,0), N, },
     { GLX(EXT_texture_from_pixmap),     VER(0,0), Y, },
     { GLX(EXT_visual_info),             VER(0,0), Y, },
     { GLX(EXT_visual_rating),           VER(0,0), Y, },
diff --git a/glx/extension_string.h b/glx/extension_string.h
index bac7b06..99eb2f7 100644
--- a/glx/extension_string.h
+++ b/glx/extension_string.h
@@ -45,6 +45,7 @@ enum {
     ARB_multisample_bit,
     EXT_create_context_es2_profile_bit,
     EXT_import_context_bit,
+    EXT_swap_control_bit,
     EXT_texture_from_pixmap_bit,
     EXT_visual_info_bit,
     EXT_visual_rating_bit,
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index cbd4ede..8139149 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -486,7 +486,7 @@ StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc)
  * resource ID, look up the GLX drawable if available, otherwise, make
  * sure it's an X window and create a GLX drawable one the fly.
  */
-static __GLXdrawable *
+__GLXdrawable *
 __glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client,
                  int *error)
 {
@@ -1214,6 +1214,7 @@ __glXDrawableInit(__GLXdrawable * drawable,
     drawable->drawId = drawId;
     drawable->config = config;
     drawable->eventMask = 0;
+    drawable->swap_interval = 0;
 
     return GL_TRUE;
 }
@@ -1926,6 +1927,14 @@ __glXDisp_CopySubBufferMESA(__GLXclientState * cl, GLbyte * pc)
     return Success;
 }
 
+/* hack for old glxext.h */
+#ifndef GLX_SWAP_INTERVAL_EXT
+#define GLX_SWAP_INTERVAL_EXT               0x20F1
+#endif
+#ifndef GLX_MAX_SWAP_INTERVAL_EXT
+#define GLX_MAX_SWAP_INTERVAL_EXT           0x20F2
+#endif
+
 /*
 ** Get drawable attributes
 */
@@ -1936,7 +1945,7 @@ DoGetDrawableAttributes(__GLXclientState * cl, XID drawId)
     xGLXGetDrawableAttributesReply reply;
     __GLXdrawable *pGlxDraw = NULL;
     DrawablePtr pDraw;
-    CARD32 attributes[14];
+    CARD32 attributes[16];
     int num = 0, error;
 
     if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
@@ -1976,6 +1985,14 @@ DoGetDrawableAttributes(__GLXclientState * cl, XID drawId)
             attributes[2*num+1] = GL_TRUE;
             num++;
         }
+        if (pGlxDraw->type == GLX_DRAWABLE_WINDOW) {
+            attributes[2*num] = GLX_SWAP_INTERVAL_EXT;
+            attributes[2*num+1] = pGlxDraw->swap_interval;
+            num++;
+            attributes[2*num] = GLX_MAX_SWAP_INTERVAL_EXT;
+            attributes[2*num+1] = pGlxDraw->config->maxSwapInterval;
+            num++;
+        }
     }
 
     reply = (xGLXGetDrawableAttributesReply) {
diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h
index 0076589..3947658 100644
--- a/glx/glxdrawable.h
+++ b/glx/glxdrawable.h
@@ -68,10 +68,8 @@ struct __GLXdrawable {
     GLenum target;
     GLenum format;
 
-    /*
-     ** Event mask
-     */
     unsigned long eventMask;
+    uint32_t swap_interval;
 };
 
 #endif                          /* !__GLX_drawable_h__ */
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 6fb3d92..d5f47ab 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -226,16 +226,13 @@ __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
 {
     __GLXcontext *cx = lastGLContext;
 
-    if (interval <= 0)          /* || interval > BIGNUM? */
-        return GLX_BAD_VALUE;
-
     DRI2SwapInterval(drawable->pDraw, interval);
     if (cx != lastGLContext) {
         lastGLContext = cx;
         cx->makeCurrent(cx);
     }
 
-    return 0;
+    return Success;
 }
 
 static void
diff --git a/glx/glxdricommon.c b/glx/glxdricommon.c
index 62cce13..a14fdef 100644
--- a/glx/glxdricommon.c
+++ b/glx/glxdricommon.c
@@ -103,6 +103,8 @@ __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
         __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
         __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
         __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
+        __ATTRIB(__DRI_ATTRIB_MAX_SWAP_INTERVAL, maxSwapInterval),
+        __ATTRIB(__DRI_ATTRIB_MIN_SWAP_INTERVAL, minSwapInterval),
         __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
         __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
         __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
diff --git a/glx/glxscreens.h b/glx/glxscreens.h
index a905877..bfd862d 100644
--- a/glx/glxscreens.h
+++ b/glx/glxscreens.h
@@ -92,6 +92,10 @@ struct __GLXconfig {
     /* OML_swap_method */
     GLint swapMethod;
 
+    /* EXT_swap_control */
+    GLint maxSwapInterval;
+    GLint minSwapInterval;
+
     /* EXT_texture_from_pixmap */
     GLint bindToTextureRgb;
     GLint bindToTextureRgba;
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 9088ec4..753805b 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -280,4 +280,8 @@ extern unsigned glxMinorVersion;
 
 extern int __glXEventBase;
 
+extern __GLXdrawable *
+__glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client,
+                 int *error);
+
 #endif                          /* !__GLX_server_h__ */
diff --git a/glx/indirect_dispatch.h b/glx/indirect_dispatch.h
index 536be60..72c48f6 100644
--- a/glx/indirect_dispatch.h
+++ b/glx/indirect_dispatch.h
@@ -1356,4 +1356,11 @@ extern _X_HIDDEN void __glXDispSwap_SecondaryColor3sv(GLbyte * pc);
 extern _X_HIDDEN void __glXDisp_MultiTexCoord2sv(GLbyte * pc);
 extern _X_HIDDEN void __glXDispSwap_MultiTexCoord2sv(GLbyte * pc);
 
+/* XXX should be autogenerated */
+
+extern _X_HIDDEN int __glXDisp_SwapIntervalEXT(struct __GLXclientStateRec *,
+                                               GLbyte *);
+extern _X_HIDDEN int __glXDispSwap_SwapIntervalEXT(struct __GLXclientStateRec *,
+                                                   GLbyte *);
+
 #endif                          /* !defined( _INDIRECT_DISPATCH_H_ ) */
diff --git a/glx/swap_interval.c b/glx/swap_interval.c
index 2320550..c59840d 100644
--- a/glx/swap_interval.c
+++ b/glx/swap_interval.c
@@ -35,18 +35,18 @@
 #include "indirect_dispatch.h"
 #include "glxbyteorder.h"
 
-static int DoSwapInterval(__GLXclientState * cl, GLbyte * pc, int do_swap);
-
-int
-DoSwapInterval(__GLXclientState * cl, GLbyte * pc, int do_swap)
+static int
+DoSwapInterval(__GLXclientState * cl, GLbyte * pc, int do_swap, int ext)
 {
     xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc;
     ClientPtr client = cl->client;
     const GLXContextTag tag = req->contextTag;
     __GLXcontext *cx;
+    __GLXdrawable *draw;
     GLint interval;
+    int ret;
 
-    REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 4);
+    REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 4 + (ext * 4));
 
     cx = __glXLookupContextByTag(cl, tag);
 
@@ -61,31 +61,64 @@ DoSwapInterval(__GLXclientState * cl, GLbyte * pc, int do_swap)
         return __glXError(GLXUnsupportedPrivateRequest);
     }
 
-    if (cx->drawPriv == NULL) {
-        client->errorValue = tag;
-        return BadValue;
-    }
-
     pc += __GLX_VENDPRIV_HDR_SIZE;
-    interval = (do_swap)
-        ? bswap_32(*(int *) (pc + 0))
-        : *(int *) (pc + 0);
 
-    if (interval <= 0)
+    if (ext) {
+        int error;
+        XID drawable = (do_swap)
+            ? bswap_32(*(int *) (pc + 0))
+            : *(int *) (pc + 0);
+
+        interval = (do_swap)
+            ? bswap_32(*(int *) (pc + 4))
+            : *(int *) (pc + 4);
+
+        draw = __glXGetDrawable(cx, drawable, cl->client, &error);
+        if (!draw || draw->type != GLX_DRAWABLE_WINDOW)
+            return BadWindow;
+
+    } else {
+        interval = (do_swap)
+            ? bswap_32(*(int *) (pc + 0))
+            : *(int *) (pc + 0);
+        draw = cx->drawPriv;
+    }
+
+    if (draw == NULL) {
+        client->errorValue = tag;
         return BadValue;
+    }
+
+    if (interval < 0 || (!ext && !interval))
+        return BadValue;
+
+    ret = (*cx->pGlxScreen->swapInterval) (draw, interval);
+    if (ret == Success)
+        draw->swap_interval = interval;
 
-    (void) (*cx->pGlxScreen->swapInterval) (cx->drawPriv, interval);
-    return Success;
+    return ret;
 }
 
 int
 __glXDisp_SwapIntervalSGI(__GLXclientState * cl, GLbyte * pc)
 {
-    return DoSwapInterval(cl, pc, 0);
+    return DoSwapInterval(cl, pc, 0, 0);
 }
 
 int
 __glXDispSwap_SwapIntervalSGI(__GLXclientState * cl, GLbyte * pc)
 {
-    return DoSwapInterval(cl, pc, 1);
+    return DoSwapInterval(cl, pc, 1, 0);
+}
+
+int
+__glXDisp_SwapIntervalEXT(__GLXclientState *cl, GLbyte *pc)
+{
+    return DoSwapInterval(cl, pc, 0, 1);
+}
+
+int
+__glXDispSwap_SwapIntervalEXT(__GLXclientState *cl, GLbyte *pc)
+{
+    return DoSwapInterval(cl, pc, 1, 1);
 }
-- 
2.4.1



More information about the xorg-devel mailing list