diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-08 15:10:47 -0800 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-29 10:02:57 -0700 |
commit | 5933b0abc6a76aaea84aa534df89900cd795c888 (patch) | |
tree | f1aef8423ce48bed302794a1a469c784ac4e7be2 | |
parent | b00d435ddf2e9817e33bfd5f7e9b905442dc23c7 (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.c | 37 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.h | 1 |
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, |