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>
This commit is contained in:
Jesse Barnes 2010-03-08 15:10:47 -08:00
parent b00d435ddf
commit 5933b0abc6
2 changed files with 27 additions and 11 deletions

View File

@ -63,6 +63,7 @@ typedef struct _DRI2Drawable {
int bufferCount; int bufferCount;
unsigned int swapsPending; unsigned int swapsPending;
ClientPtr blockedClient; ClientPtr blockedClient;
Bool blockedOnMsc;
int swap_interval; int swap_interval;
CARD64 swap_count; CARD64 swap_count;
int64_t target_sbc; /* -1 means no SBC wait outstanding */ int64_t target_sbc; /* -1 means no SBC wait outstanding */
@ -145,6 +146,7 @@ DRI2CreateDrawable(DrawablePtr pDraw)
pPriv->bufferCount = 0; pPriv->bufferCount = 0;
pPriv->swapsPending = 0; pPriv->swapsPending = 0;
pPriv->blockedClient = NULL; pPriv->blockedClient = NULL;
pPriv->blockedOnMsc = FALSE;
pPriv->swap_count = 0; pPriv->swap_count = 0;
pPriv->target_sbc = -1; pPriv->target_sbc = -1;
pPriv->swap_interval = 1; pPriv->swap_interval = 1;
@ -402,6 +404,15 @@ DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
return FALSE; return FALSE;
} }
static void
__DRI2BlockClient(ClientPtr client, DRI2DrawablePtr pPriv)
{
if (pPriv->blockedClient == NULL) {
IgnoreClient(client);
pPriv->blockedClient = client;
}
}
void void
DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
{ {
@ -411,10 +422,8 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
if (pPriv == NULL) if (pPriv == NULL)
return; return;
if (pPriv->blockedClient == NULL) { __DRI2BlockClient(client, pPriv);
IgnoreClient(client); pPriv->blockedOnMsc = TRUE;
pPriv->blockedClient = client;
}
} }
int int
@ -495,6 +504,7 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
AttendClient(pPriv->blockedClient); AttendClient(pPriv->blockedClient);
pPriv->blockedClient = NULL; pPriv->blockedClient = NULL;
pPriv->blockedOnMsc = FALSE;
/* If there's still a swap pending, let DRI2SwapComplete free it */ /* If there's still a swap pending, let DRI2SwapComplete free it */
if (pPriv->refCount == 0 && pPriv->swapsPending == 0) 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 * Swap completed.
* blocked due to GLX activity during a swap. * 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 && if (pPriv->target_sbc != -1 &&
pPriv->target_sbc <= pPriv->swap_count) { pPriv->target_sbc <= pPriv->swap_count) {
@ -527,12 +541,13 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
AttendClient(pPriv->blockedClient); AttendClient(pPriv->blockedClient);
pPriv->blockedClient = NULL; pPriv->blockedClient = NULL;
} else if (pPriv->target_sbc == -1) { } else if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
if (pPriv->blockedClient) if (pPriv->blockedClient) {
AttendClient(pPriv->blockedClient); AttendClient(pPriv->blockedClient);
pPriv->blockedClient = NULL; pPriv->blockedClient = NULL;
} }
} }
}
void void
DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
@ -582,7 +597,7 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
pPriv->blockedClient == NULL) { pPriv->blockedClient == NULL) {
ResetCurrentRequest(client); ResetCurrentRequest(client);
client->sequence--; client->sequence--;
DRI2BlockClient(client, pDrawable); __DRI2BlockClient(client, pPriv);
return TRUE; return TRUE;
} }
@ -780,7 +795,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
} }
pPriv->target_sbc = target_sbc; pPriv->target_sbc = target_sbc;
DRI2BlockClient(client, pDraw); __DRI2BlockClient(client, pPriv);
return Success; return Success;
} }

View File

@ -257,6 +257,7 @@ extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
extern _X_EXPORT Bool DRI2CanExchange(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 DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,