aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glx
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/glx')
-rw-r--r--xorg-server/glx/extension_string.c1
-rw-r--r--xorg-server/glx/extension_string.h1
-rw-r--r--xorg-server/glx/glxcmds.c2
-rw-r--r--xorg-server/glx/glxcontext.h4
-rw-r--r--xorg-server/glx/glxdrawable.h2
-rw-r--r--xorg-server/glx/glxdri.c2
-rw-r--r--xorg-server/glx/glxdri2.c102
-rw-r--r--xorg-server/glx/glxdriswrast.c2
-rw-r--r--xorg-server/glx/glxext.c5
-rw-r--r--xorg-server/glx/glxscreens.c1
-rw-r--r--xorg-server/glx/glxserver.h20
-rw-r--r--xorg-server/glx/swap_interval.c7
12 files changed, 121 insertions, 28 deletions
diff --git a/xorg-server/glx/extension_string.c b/xorg-server/glx/extension_string.c
index 9d110cf98..7721cb056 100644
--- a/xorg-server/glx/extension_string.c
+++ b/xorg-server/glx/extension_string.c
@@ -82,6 +82,7 @@ static const struct extension_info known_glx_extensions[] = {
{ GLX(SGIX_fbconfig), VER(1,3), Y, },
{ GLX(SGIX_pbuffer), VER(1,3), Y, },
{ GLX(SGIX_visual_select_group), VER(0,0), Y, },
+ { GLX(INTEL_swap_event), VER(1,4), N, },
{ NULL }
};
diff --git a/xorg-server/glx/extension_string.h b/xorg-server/glx/extension_string.h
index 98e91bc18..912534a04 100644
--- a/xorg-server/glx/extension_string.h
+++ b/xorg-server/glx/extension_string.h
@@ -50,6 +50,7 @@ enum {
SGIX_fbconfig_bit,
SGIX_pbuffer_bit,
SGIX_visual_select_group_bit,
+ INTEL_swap_event_bit,
__NUM_GLX_EXTS,
};
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index eedab652f..77afbf4b1 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/glx/glxcmds.c
@@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
return error;
if (pGlxDraw->type == DRAWABLE_WINDOW &&
- (*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE)
+ (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
return __glXError(GLXBadDrawable);
return Success;
diff --git a/xorg-server/glx/glxcontext.h b/xorg-server/glx/glxcontext.h
index 70a14115d..79bc083a8 100644
--- a/xorg-server/glx/glxcontext.h
+++ b/xorg-server/glx/glxcontext.h
@@ -55,6 +55,10 @@ struct __GLXcontext {
unsigned long mask);
int (*forceCurrent) (__GLXcontext *context);
+ Bool (*wait) (__GLXcontext *context,
+ __GLXclientState *cl,
+ int *error);
+
__GLXtextureFromPixmap *textureFromPixmap;
/*
diff --git a/xorg-server/glx/glxdrawable.h b/xorg-server/glx/glxdrawable.h
index 3f165ed4f..2a365c505 100644
--- a/xorg-server/glx/glxdrawable.h
+++ b/xorg-server/glx/glxdrawable.h
@@ -45,7 +45,7 @@ enum {
struct __GLXdrawable {
void (*destroy)(__GLXdrawable *private);
- GLboolean (*swapBuffers)(__GLXdrawable *);
+ GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *);
void (*copySubBuffer)(__GLXdrawable *drawable,
int x, int y, int w, int h);
void (*waitX)(__GLXdrawable *);
diff --git a/xorg-server/glx/glxdri.c b/xorg-server/glx/glxdri.c
index 6122653b0..21e44d12d 100644
--- a/xorg-server/glx/glxdri.c
+++ b/xorg-server/glx/glxdri.c
@@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
}
static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
{
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
__GLXDRIscreen *screen =
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index ed7dc80ba..69fd39b3b 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -70,6 +70,7 @@ struct __GLXDRIscreen {
const __DRIcoreExtension *core;
const __DRIdri2Extension *dri2;
+ const __DRI2flushExtension *flush;
const __DRIcopySubBufferExtension *copySubBuffer;
const __DRIswapControlExtension *swapControl;
const __DRItexBufferExtension *texBuffer;
@@ -132,17 +133,6 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
DRI2BufferFrontLeft, DRI2BufferBackLeft);
}
-static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-
- __glXDRIdrawableCopySubBuffer(drawable, 0, 0,
- private->width, private->height);
-
- return TRUE;
-}
-
static void
__glXDRIdrawableWaitX(__GLXdrawable *drawable)
{
@@ -177,9 +167,74 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
}
+static void
+__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
+ CARD64 msc, CARD64 sbc)
+{
+ __GLXdrawable *drawable = data;
+ xGLXBufferSwapComplete wire;
+
+ if (!drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)
+ return;
+
+ wire.type = __glXEventBase + GLX_BufferSwapComplete;
+ switch (type) {
+ case DRI2_EXCHANGE_COMPLETE:
+ wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+ break;
+ case DRI2_BLIT_COMPLETE:
+ wire.event_type = GLX_BLIT_COMPLETE_INTEL;
+ break;
+ case DRI2_FLIP_COMPLETE:
+ wire.event_type = GLX_FLIP_COMPLETE_INTEL;
+ break;
+ default:
+ /* unknown swap completion type */
+ break;
+ }
+ wire.sequenceNumber = client->sequence;
+ wire.drawable = drawable->drawId;
+ wire.ust_hi = ust >> 32;
+ wire.ust_lo = ust & 0xffffffff;
+ wire.msc_hi = msc >> 32;
+ wire.msc_lo = msc & 0xffffffff;
+ wire.sbc_hi = sbc >> 32;
+ wire.sbc_lo = sbc & 0xffffffff;
+
+ WriteEventsToClient(client, 1, (xEvent *) &wire);
+}
+
+/*
+ * Copy or flip back to front, honoring the swap interval if possible.
+ *
+ * If the kernel supports it, we request an event for the frame when the
+ * swap should happen, then perform the copy when we receive it.
+ */
+static GLboolean
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
+ __GLXDRIscreen *screen = priv->screen;
+ CARD64 unused;
+
+ if (screen->flush)
+ (*screen->flush->flushInvalidate)(priv->driDrawable);
+
+ if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+ __glXdriSwapEvent, drawable->pDraw) != Success)
+ return FALSE;
+
+ return TRUE;
+}
+
static int
__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
{
+ if (interval <= 0) /* || interval > BIGNUM? */
+ return GLX_BAD_VALUE;
+
+ DRI2SwapInterval(drawable->pDraw, interval);
+
return 0;
}
@@ -241,6 +296,18 @@ __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
read->driDrawable);
}
+static Bool
+__glXDRIcontextWait(__GLXcontext *baseContext,
+ __GLXclientState *cl, int *error)
+{
+ if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+ *error = cl->client->noClientException;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
#ifdef __DRI_TEX_BUFFER
static int
@@ -346,6 +413,7 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
context->base.copy = __glXDRIcontextCopy;
context->base.forceCurrent = __glXDRIcontextForceCurrent;
context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
+ context->base.wait = __glXDRIcontextWait;
context->driContext =
(*screen->dri2->createNewContext)(screen->driScreen,
@@ -550,6 +618,10 @@ initializeExtensions(__GLXDRIscreen *screen)
"GLX_MESA_copy_sub_buffer");
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
+ /* FIXME: only if DDX supports it */
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
+
for (i = 0; extensions[i]; i++) {
#ifdef __DRI_READ_DRAWABLE
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
@@ -581,6 +653,14 @@ initializeExtensions(__GLXDRIscreen *screen)
LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
}
#endif
+
+#ifdef __DRI2_FLUSH
+ if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
+ extensions[i]->version >= __DRI2_FLUSH_VERSION) {
+ screen->flush = (__DRI2flushExtension *) extensions[i];
+ }
+#endif
+
/* Ignore unknown extensions */
}
}
diff --git a/xorg-server/glx/glxdriswrast.c b/xorg-server/glx/glxdriswrast.c
index 20f9f90d6..c647d83ca 100644
--- a/xorg-server/glx/glxdriswrast.c
+++ b/xorg-server/glx/glxdriswrast.c
@@ -108,7 +108,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
}
static GLboolean
-__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
{
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
const __DRIcoreExtension *core = private->screen->core;
diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c
index 751ea7297..59bcfbed2 100644
--- a/xorg-server/glx/glxext.c
+++ b/xorg-server/glx/glxext.c
@@ -267,6 +267,7 @@ GLboolean __glXErrorOccured(void)
}
static int __glXErrorBase;
+int __glXEventBase;
int __glXError(int error)
{
@@ -403,6 +404,7 @@ void GlxExtensionInit(void)
}
__glXErrorBase = extEntry->errorBase;
+ __glXEventBase = extEntry->eventBase;
}
/************************************************************************/
@@ -446,6 +448,9 @@ __GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
}
}
+ if (cx->wait && (*cx->wait)(cx, cl, error))
+ return NULL;
+
if (cx == __glXLastContext) {
/* No need to re-bind */
return cx;
diff --git a/xorg-server/glx/glxscreens.c b/xorg-server/glx/glxscreens.c
index 674e2c681..58d8ee0b4 100644
--- a/xorg-server/glx/glxscreens.c
+++ b/xorg-server/glx/glxscreens.c
@@ -181,6 +181,7 @@ static char GLXServerExtensions[] =
"GLX_SGIX_fbconfig "
"GLX_SGIX_pbuffer "
"GLX_MESA_copy_sub_buffer "
+ "GLX_INTEL_swap_event"
;
/*
diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h
index 80f1b28f9..1daf97758 100644
--- a/xorg-server/glx/glxserver.h
+++ b/xorg-server/glx/glxserver.h
@@ -56,7 +56,14 @@
#include <GL/gl.h>
#include <GL/glxproto.h>
-/* For glxscreens.h */
+/*
+** GLX resources.
+*/
+typedef XID GLXContextID;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+
+typedef struct __GLXclientStateRec __GLXclientState;
typedef struct __GLXdrawable __GLXdrawable;
typedef struct __GLXcontext __GLXcontext;
@@ -71,15 +78,6 @@ typedef struct __GLXcontext __GLXcontext;
#define False 0
#endif
-/*
-** GLX resources.
-*/
-typedef XID GLXContextID;
-typedef XID GLXPixmap;
-typedef XID GLXDrawable;
-
-typedef struct __GLXclientStateRec __GLXclientState;
-
extern __GLXscreen *glxGetScreen(ScreenPtr pScreen);
extern __GLXclientState *glxGetClient(ClientPtr pClient);
@@ -251,4 +249,6 @@ extern int __glXImageSize(GLenum format, GLenum type,
extern unsigned glxMajorVersion;
extern unsigned glxMinorVersion;
+extern int __glXEventBase;
+
#endif /* !__GLX_server_h__ */
diff --git a/xorg-server/glx/swap_interval.c b/xorg-server/glx/swap_interval.c
index 3a5242022..0bae3247e 100644
--- a/xorg-server/glx/swap_interval.c
+++ b/xorg-server/glx/swap_interval.c
@@ -53,8 +53,6 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
cx = __glXLookupContextByTag(cl, tag);
- LogMessage(X_ERROR, "%s: cx = %p, GLX screen = %p\n", __func__,
- cx, (cx == NULL) ? NULL : cx->pGlxScreen);
if ((cx == NULL) || (cx->pGlxScreen == NULL)) {
client->errorValue = tag;
return __glXError(GLXBadContext);
@@ -68,7 +66,7 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
if (cx->drawPriv == NULL) {
client->errorValue = tag;
- return __glXError(GLXBadDrawable);
+ return BadValue;
}
pc += __GLX_VENDPRIV_HDR_SIZE;
@@ -76,6 +74,9 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
? bswap_32(*(int *)(pc + 0))
: *(int *)(pc + 0);
+ if (interval <= 0)
+ return BadValue;
+
(void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval);
return Success;
}