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:
parent
b00d435ddf
commit
5933b0abc6
|
@ -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,10 +541,11 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue