summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-03-08 15:10:47 -0800
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-03-29 10:02:57 -0700
commit5933b0abc6a76aaea84aa534df89900cd795c888 (patch)
treef1aef8423ce48bed302794a1a469c784ac4e7be2
parentb00d435ddf2e9817e33bfd5f7e9b905442dc23c7 (diff)
DRI2: prevent swap wakes from waking MSC waiters
If a few swaps were queued leading to a throttle related block on the client, and then the client submitted an MSC wait, one of the previous swap wakeups could have caused the MSC wait to complete early. Add a flag for this to prevent a swap wake from prematurely waking an MSC waiter. Reported-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--hw/xfree86/dri2/dri2.c37
-rw-r--r--hw/xfree86/dri2/dri2.h1
2 files changed, 27 insertions, 11 deletions
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 8a671226f..8b4c36f49 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -63,6 +63,7 @@ typedef struct _DRI2Drawable {
int bufferCount;
unsigned int swapsPending;
ClientPtr blockedClient;
+ Bool blockedOnMsc;
int swap_interval;
CARD64 swap_count;
int64_t target_sbc; /* -1 means no SBC wait outstanding */
@@ -145,6 +146,7 @@ DRI2CreateDrawable(DrawablePtr pDraw)
pPriv->bufferCount = 0;
pPriv->swapsPending = 0;
pPriv->blockedClient = NULL;
+ pPriv->blockedOnMsc = FALSE;
pPriv->swap_count = 0;
pPriv->target_sbc = -1;
pPriv->swap_interval = 1;
@@ -402,6 +404,15 @@ DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
return FALSE;
}
+static void
+__DRI2BlockClient(ClientPtr client, DRI2DrawablePtr pPriv)
+{
+ if (pPriv->blockedClient == NULL) {
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ }
+}
+
void
DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
{
@@ -411,10 +422,8 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
if (pPriv == NULL)
return;
- if (pPriv->blockedClient == NULL) {
- IgnoreClient(client);
- pPriv->blockedClient = client;
- }
+ __DRI2BlockClient(client, pPriv);
+ pPriv->blockedOnMsc = TRUE;
}
int
@@ -495,6 +504,7 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
AttendClient(pPriv->blockedClient);
pPriv->blockedClient = NULL;
+ pPriv->blockedOnMsc = FALSE;
/* If there's still a swap pending, let DRI2SwapComplete free it */
if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
@@ -516,8 +526,12 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
}
/*
- * Swap completed. Either wake up an SBC waiter or a client that was
- * blocked due to GLX activity during a swap.
+ * Swap completed.
+ * Wake the client iff:
+ * - it was waiting on SBC
+ * - was blocked due to GLX make current
+ * - was blocked due to swap throttling
+ * - is not blocked due to an MSC wait
*/
if (pPriv->target_sbc != -1 &&
pPriv->target_sbc <= pPriv->swap_count) {
@@ -527,10 +541,11 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
AttendClient(pPriv->blockedClient);
pPriv->blockedClient = NULL;
- } else if (pPriv->target_sbc == -1) {
- if (pPriv->blockedClient)
+ } else if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
+ if (pPriv->blockedClient) {
AttendClient(pPriv->blockedClient);
- pPriv->blockedClient = NULL;
+ pPriv->blockedClient = NULL;
+ }
}
}
@@ -582,7 +597,7 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
pPriv->blockedClient == NULL) {
ResetCurrentRequest(client);
client->sequence--;
- DRI2BlockClient(client, pDrawable);
+ __DRI2BlockClient(client, pPriv);
return TRUE;
}
@@ -780,7 +795,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
}
pPriv->target_sbc = target_sbc;
- DRI2BlockClient(client, pDraw);
+ __DRI2BlockClient(client, pPriv);
return Success;
}
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 066cc3947..e1881baa9 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -257,6 +257,7 @@ extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
+/* Note: use *only* for MSC related waits */
extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,