summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2009-07-17 11:26:37 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-10-29 14:05:09 -0700
commit219729033efb2d970bc8c6b3f98006b6ebddcdfe (patch)
tree0cb00af6f81badd096cf823d13cacc2600015ed1
parent01a443b3b85cf5013f969126a57358c9f9704175 (diff)
downloadxserver-219729033efb2d970bc8c6b3f98006b6ebddcdfe.tar.gz
Only block swapping client not entire server in DRI2SwapBuffers
-rw-r--r--glx/glxdri2.c2
-rw-r--r--hw/xfree86/dri2/dri2.c92
-rw-r--r--hw/xfree86/dri2/dri2.h4
-rw-r--r--hw/xfree86/dri2/dri2ext.c11
4 files changed, 88 insertions, 21 deletions
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 1d51ce6f8..63462a54c 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -175,7 +175,7 @@ __glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
(*screen->flush->flushInvalidate)(priv->driDrawable);
- if (!DRI2SwapBuffers(drawable->pDraw))
+ if (DRI2SwapBuffers(drawable->pDraw) != Success)
return FALSE;
return TRUE;
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 22ac9a5e7..fc1d25603 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -38,6 +38,7 @@
#include "xf86Module.h"
#include "scrnintstr.h"
#include "windowstr.h"
+#include "dixstruct.h"
#include "dri2.h"
#include "xf86VGAarbiter.h"
@@ -56,7 +57,8 @@ typedef struct _DRI2Drawable {
int height;
DRI2BufferPtr *buffers;
int bufferCount;
- unsigned int pendingSequence;
+ unsigned int swapPending;
+ ClientPtr blockedClient;
} DRI2DrawableRec, *DRI2DrawablePtr;
typedef struct _DRI2Screen {
@@ -120,6 +122,8 @@ DRI2CreateDrawable(DrawablePtr pDraw)
pPriv->height = pDraw->height;
pPriv->buffers = NULL;
pPriv->bufferCount = 0;
+ pPriv->swapPending = FALSE;
+ pPriv->blockedClient = NULL;
if (pDraw->type == DRAWABLE_WINDOW)
{
@@ -339,17 +343,43 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
return Success;
}
-Bool
+static Bool
+DRI2FlipCheck(DrawablePtr pDraw)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ WindowPtr pWin;
+ PixmapPtr pWinPixmap;
+
+ if (pDraw->type == DRAWABLE_PIXMAP)
+ return TRUE;
+
+ pWin = (WindowPtr) pDraw;
+ pWinPixmap = pScreen->GetWindowPixmap(pWin);
+ if (pDraw->width != pWinPixmap->drawable.width)
+ return FALSE;
+ if (pDraw->height != pWinPixmap->drawable.height)
+ return FALSE;
+ if (pDraw->depth != pWinPixmap->drawable.depth)
+ return FALSE;
+ if (!REGION_EQUAL(pScreen, &pWin->clipList, &pWin->winSize))
+ return FALSE;
+
+ return TRUE;
+}
+
+int
DRI2SwapBuffers(DrawablePtr pDraw)
{
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv;
DRI2BufferPtr pDestBuffer, pSrcBuffer;
int i;
+ BoxRec box;
+ RegionRec region;
pPriv = DRI2GetDrawable(pDraw);
if (pPriv == NULL)
- return FALSE;
+ return BadDrawable;
pDestBuffer = NULL;
pSrcBuffer = NULL;
@@ -361,22 +391,54 @@ DRI2SwapBuffers(DrawablePtr pDraw)
pSrcBuffer = pPriv->buffers[i];
}
if (pSrcBuffer == NULL || pDestBuffer == NULL)
- return FALSE;
+ return BadValue;
- if (!(*ds->SwapBuffers)(pDraw, pDestBuffer, pSrcBuffer)) {
- BoxRec box;
- RegionRec region;
+ if (DRI2FlipCheck(pDraw) &&
+ (*ds->SwapBuffers)(pDraw, pDestBuffer, pSrcBuffer))
+ {
+ pPriv->swapPending = TRUE;
+ return Success;
+ }
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pDraw->width;
- box.y2 = pDraw->height;
- REGION_INIT(drawable->pDraw->pScreen, &region, &box, 0);
- if (DRI2CopyRegion(pDraw, &region, DRI2BufferFrontLeft, DRI2BufferBackLeft) != Success)
- return FALSE;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDraw->width;
+ box.y2 = pDraw->height;
+ REGION_INIT(drawable->pDraw->pScreen, &region, &box, 0);
+
+ return DRI2CopyRegion(pDraw, &region,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+}
+
+Bool
+DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ /* If we're currently waiting for a swap on this drawable, reset
+ * the request and suspend the client. We only support one
+ * blocked client per drawable. */
+ if (pPriv->swapPending && pPriv->blockedClient == NULL) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ return TRUE;
}
- return TRUE;
+ return FALSE;
+}
+
+void
+DRI2SwapComplete(DrawablePtr pDrawable)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ if (pPriv->blockedClient)
+ AttendClient(pPriv->blockedClient);
+
+ pPriv->swapPending = FALSE;
+ pPriv->blockedClient = NULL;
}
void
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index e330fe930..8cf23085e 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -140,6 +140,8 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
int *width, int *height, unsigned int *attachments, int count,
int *out_count);
-extern _X_EXPORT Bool DRI2SwapBuffers(DrawablePtr pDraw);
+extern _X_EXPORT int DRI2SwapBuffers(DrawablePtr pDraw);
+extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
+extern _X_EXPORT void DRI2SwapComplete(DrawablePtr pDrawable);
#endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index b2bb5d0a6..666fe729c 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -259,6 +259,9 @@ ProcDRI2GetBuffers(ClientPtr client)
&pDrawable, &status))
return status;
+ if (DRI2WaitSwap(client, pDrawable))
+ return client->noClientException;
+
attachments = (unsigned int *) &stuff[1];
buffers = DRI2GetBuffers(pDrawable, &width, &height,
attachments, stuff->count, &count);
@@ -283,6 +286,9 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
&pDrawable, &status))
return status;
+ if (DRI2WaitSwap(client, pDrawable))
+ return client->noClientException;
+
attachments = (unsigned int *) &stuff[1];
buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
attachments, stuff->count, &count);
@@ -341,10 +347,7 @@ ProcDRI2SwapBuffers(ClientPtr client)
if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
return status;
- if (!DRI2SwapBuffers(pDrawable))
- return BadAlloc;
-
- return client->noClientException;
+ return DRI2SwapBuffers(pDrawable);
}
static int