Merge remote branch 'jbarnes/master'
This commit is contained in:
commit
a7698a6776
|
@ -616,6 +616,7 @@ glxDRILeaveVT (int index, int flags)
|
|||
static void
|
||||
initializeExtensions(__GLXDRIscreen *screen)
|
||||
{
|
||||
ScreenPtr pScreen = screen->base.pScreen;
|
||||
const __DRIextension **extensions;
|
||||
int i;
|
||||
|
||||
|
@ -625,10 +626,17 @@ initializeExtensions(__GLXDRIscreen *screen)
|
|||
"GLX_MESA_copy_sub_buffer");
|
||||
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
|
||||
|
||||
/* FIXME: only if DDX supports it */
|
||||
__glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
|
||||
LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
|
||||
|
||||
if (DRI2HasSwapControl(pScreen)) {
|
||||
__glXEnableExtension(screen->glx_enable_bits,
|
||||
"GLX_SGI_swap_control");
|
||||
__glXEnableExtension(screen->glx_enable_bits,
|
||||
"GLX_MESA_swap_control");
|
||||
LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
|
||||
}
|
||||
|
||||
for (i = 0; extensions[i]; i++) {
|
||||
#ifdef __DRI_READ_DRAWABLE
|
||||
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
|
||||
|
@ -639,19 +647,6 @@ initializeExtensions(__GLXDRIscreen *screen)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_SWAP_CONTROL
|
||||
if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
|
||||
screen->swapControl =
|
||||
(const __DRIswapControlExtension *) extensions[i];
|
||||
__glXEnableExtension(screen->glx_enable_bits,
|
||||
"GLX_SGI_swap_control");
|
||||
__glXEnableExtension(screen->glx_enable_bits,
|
||||
"GLX_MESA_swap_control");
|
||||
|
||||
LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __DRI_TEX_BUFFER
|
||||
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
|
||||
screen->texBuffer =
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
|
||||
#include "xf86.h"
|
||||
|
||||
CARD8 dri2_major; /* version of DRI2 supported by DDX */
|
||||
CARD8 dri2_minor;
|
||||
|
||||
static int dri2ScreenPrivateKeyIndex;
|
||||
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
||||
static int dri2WindowPrivateKeyIndex;
|
||||
|
@ -60,10 +63,13 @@ typedef struct _DRI2Drawable {
|
|||
int bufferCount;
|
||||
unsigned int swapsPending;
|
||||
ClientPtr blockedClient;
|
||||
Bool blockedOnMsc;
|
||||
int swap_interval;
|
||||
CARD64 swap_count;
|
||||
CARD64 target_sbc; /* -1 means no SBC wait outstanding */
|
||||
int64_t target_sbc; /* -1 means no SBC wait outstanding */
|
||||
CARD64 last_swap_target; /* most recently queued swap target */
|
||||
CARD64 last_swap_msc; /* msc at completion of most recent swap */
|
||||
CARD64 last_swap_ust; /* ust at completion of most recent swap */
|
||||
int swap_limit; /* for N-buffering */
|
||||
} DRI2DrawableRec, *DRI2DrawablePtr;
|
||||
|
||||
|
@ -116,9 +122,11 @@ DRI2GetDrawable(DrawablePtr pDraw)
|
|||
int
|
||||
DRI2CreateDrawable(DrawablePtr pDraw)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
WindowPtr pWin;
|
||||
PixmapPtr pPixmap;
|
||||
DRI2DrawablePtr pPriv;
|
||||
CARD64 ust;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv != NULL)
|
||||
|
@ -138,11 +146,17 @@ 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;
|
||||
pPriv->last_swap_target = -1;
|
||||
/* Initialize last swap target from DDX if possible */
|
||||
if (!ds->GetMSC || !(*ds->GetMSC)(pDraw, &ust, &pPriv->last_swap_target))
|
||||
pPriv->last_swap_target = 0;
|
||||
|
||||
pPriv->swap_limit = 1; /* default to double buffering */
|
||||
pPriv->last_swap_msc = 0;
|
||||
pPriv->last_swap_ust = 0;
|
||||
|
||||
if (pDraw->type == DRAWABLE_WINDOW)
|
||||
{
|
||||
|
@ -390,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)
|
||||
{
|
||||
|
@ -399,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
|
||||
|
@ -483,6 +504,11 @@ 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)
|
||||
DRI2FreeDrawable(pDraw);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -500,22 +526,27 @@ 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) {
|
||||
pPriv->target_sbc <= pPriv->swap_count) {
|
||||
ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
|
||||
frame, pPriv->swap_count);
|
||||
pPriv->target_sbc = -1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -534,21 +565,24 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|||
return;
|
||||
}
|
||||
|
||||
if (pPriv->refCount == 0) {
|
||||
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
||||
"[DRI2] %s: bad drawable refcount\n", __func__);
|
||||
DRI2FreeDrawable(pDraw);
|
||||
return;
|
||||
}
|
||||
pPriv->swapsPending--;
|
||||
pPriv->swap_count++;
|
||||
|
||||
ust = ((CARD64)tv_sec * 1000000) + tv_usec;
|
||||
if (swap_complete)
|
||||
swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
|
||||
|
||||
pPriv->swapsPending--;
|
||||
pPriv->swap_count++;
|
||||
pPriv->last_swap_msc = frame;
|
||||
pPriv->last_swap_ust = ust;
|
||||
|
||||
DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
|
||||
|
||||
/*
|
||||
* It's normal for the app to have exited with a swap outstanding, but
|
||||
* don't free the drawable until they're all complete.
|
||||
*/
|
||||
if (pPriv->swapsPending == 0 && pPriv->refCount == 0)
|
||||
DRI2FreeDrawable(pDraw);
|
||||
}
|
||||
|
||||
Bool
|
||||
|
@ -563,7 +597,7 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
|
|||
pPriv->blockedClient == NULL) {
|
||||
ResetCurrentRequest(client);
|
||||
client->sequence--;
|
||||
DRI2BlockClient(client, pDrawable);
|
||||
__DRI2BlockClient(client, pPriv);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -579,7 +613,6 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
DRI2DrawablePtr pPriv;
|
||||
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
||||
CARD64 ust;
|
||||
int ret, i;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
|
@ -601,8 +634,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|||
return BadDrawable;
|
||||
}
|
||||
|
||||
/* Old DDX, just blit */
|
||||
if (!ds->ScheduleSwap) {
|
||||
/* Old DDX or no swap interval, just blit */
|
||||
if (!ds->ScheduleSwap || !pPriv->swap_interval) {
|
||||
BoxRec box;
|
||||
RegionRec region;
|
||||
|
||||
|
@ -623,52 +656,52 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|||
/*
|
||||
* In the simple glXSwapBuffers case, all params will be 0, and we just
|
||||
* need to schedule a swap for the last swap target + the swap interval.
|
||||
* If the last swap target hasn't been set yet, call into the driver
|
||||
* to get the current count.
|
||||
*/
|
||||
if (target_msc == 0 && divisor == 0 && remainder == 0 &&
|
||||
pPriv->last_swap_target < 0) {
|
||||
ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
|
||||
if (!ret) {
|
||||
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
||||
"[DRI2] %s: driver failed to return current MSC\n",
|
||||
__func__);
|
||||
return BadDrawable;
|
||||
}
|
||||
}
|
||||
|
||||
/* First swap needs to initialize last_swap_target */
|
||||
if (pPriv->last_swap_target < 0)
|
||||
pPriv->last_swap_target = target_msc;
|
||||
|
||||
if (target_msc == 0 && divisor == 0 && remainder == 0) {
|
||||
/*
|
||||
* Swap target for this swap is last swap target + swap interval since
|
||||
* we have to account for the current swap count, interval, and the
|
||||
* number of pending swaps.
|
||||
*/
|
||||
*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
||||
} else {
|
||||
/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
||||
*swap_target = target_msc;
|
||||
}
|
||||
|
||||
pPriv->swapsPending++;
|
||||
ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
|
||||
swap_target, divisor, remainder, func, data);
|
||||
if (!ret) {
|
||||
pPriv->swapsPending--; /* didn't schedule */
|
||||
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
||||
"[DRI2] %s: driver failed to schedule swap\n", __func__);
|
||||
return BadDrawable;
|
||||
}
|
||||
|
||||
pPriv->swapsPending++;
|
||||
pPriv->last_swap_target = *swap_target;
|
||||
|
||||
/* According to spec, return expected swapbuffers count SBC after this swap
|
||||
* will complete.
|
||||
*/
|
||||
*swap_target = pPriv->swap_count + pPriv->swapsPending;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
DRI2SwapInterval(DrawablePtr pDrawable, int interval)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
|
||||
|
||||
/* fixme: check against arbitrary max? */
|
||||
if (pPriv == NULL) {
|
||||
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
||||
"[DRI2] %s: bad drawable\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fixme: check against arbitrary max? */
|
||||
pPriv->swap_interval = interval;
|
||||
}
|
||||
|
||||
|
@ -717,7 +750,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|||
Bool ret;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
if (pPriv == NULL || pPriv->refCount == 0)
|
||||
return BadDrawable;
|
||||
|
||||
/* Old DDX just completes immediately */
|
||||
|
@ -741,14 +774,28 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|||
DRI2DrawablePtr pPriv;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
if (pPriv == NULL || pPriv->refCount == 0)
|
||||
return BadDrawable;
|
||||
|
||||
if (pPriv->swap_count >= target_sbc)
|
||||
/* target_sbc == 0 means to block until all pending swaps are
|
||||
* finished. Recalculate target_sbc to get that behaviour.
|
||||
*/
|
||||
if (target_sbc == 0)
|
||||
target_sbc = pPriv->swap_count + pPriv->swapsPending;
|
||||
|
||||
/* If current swap count already >= target_sbc,
|
||||
* return immediately with (ust, msc, sbc) triplet of
|
||||
* most recent completed swap.
|
||||
*/
|
||||
if (pPriv->swap_count >= target_sbc) {
|
||||
*sbc = pPriv->swap_count;
|
||||
*msc = pPriv->last_swap_msc;
|
||||
*ust = pPriv->last_swap_ust;
|
||||
return Success;
|
||||
}
|
||||
|
||||
pPriv->target_sbc = target_sbc;
|
||||
DRI2BlockClient(client, pDraw);
|
||||
__DRI2BlockClient(client, pPriv);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
@ -776,13 +823,21 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
|
|||
xfree(pPriv->buffers);
|
||||
}
|
||||
|
||||
/* If the window is destroyed while we have a swap pending, don't
|
||||
/* If the window is destroyed while we have a swap or wait pending, don't
|
||||
* actually free the priv yet. We'll need it in the DRI2SwapComplete()
|
||||
* callback and we'll free it there once we're done. */
|
||||
if (!pPriv->swapsPending)
|
||||
if (!pPriv->swapsPending && !pPriv->blockedClient)
|
||||
DRI2FreeDrawable(pDraw);
|
||||
}
|
||||
|
||||
Bool
|
||||
DRI2HasSwapControl(ScreenPtr pScreen)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
|
||||
|
||||
return (ds->ScheduleSwap && ds->GetMSC);
|
||||
}
|
||||
|
||||
Bool
|
||||
DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
|
||||
const char **driverName, const char **deviceName)
|
||||
|
@ -820,6 +875,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|||
"VDPAU", /* DRI2DriverVDPAU */
|
||||
};
|
||||
unsigned int i;
|
||||
CARD8 cur_minor;
|
||||
|
||||
if (info->version < 3)
|
||||
return FALSE;
|
||||
|
@ -836,6 +892,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|||
|
||||
ds->fd = info->fd;
|
||||
ds->deviceName = info->deviceName;
|
||||
dri2_major = 1;
|
||||
|
||||
ds->CreateBuffer = info->CreateBuffer;
|
||||
ds->DestroyBuffer = info->DestroyBuffer;
|
||||
|
@ -845,8 +902,15 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|||
ds->ScheduleSwap = info->ScheduleSwap;
|
||||
ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
|
||||
ds->GetMSC = info->GetMSC;
|
||||
cur_minor = 2;
|
||||
} else {
|
||||
cur_minor = 1;
|
||||
}
|
||||
|
||||
/* Initialize minor if needed and set to minimum provied by DDX */
|
||||
if (!dri2_minor || dri2_minor > cur_minor)
|
||||
dri2_minor = cur_minor;
|
||||
|
||||
if (info->version == 3 || info->numDrivers == 0) {
|
||||
/* Driver too old: use the old-style driverName field */
|
||||
ds->numDrivers = 1;
|
||||
|
|
|
@ -46,6 +46,9 @@ typedef struct {
|
|||
void *driverPrivate;
|
||||
} DRI2BufferRec, *DRI2BufferPtr;
|
||||
|
||||
extern CARD8 dri2_major; /* version of DRI2 supported by DDX */
|
||||
extern CARD8 dri2_minor;
|
||||
|
||||
typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
|
||||
typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
|
||||
CARD64 ust, CARD64 msc, CARD64 sbc);
|
||||
|
@ -185,6 +188,8 @@ extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
|
|||
|
||||
extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT Bool DRI2HasSwapControl(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
|
||||
unsigned int driverType,
|
||||
int *fd,
|
||||
|
@ -254,6 +259,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,
|
||||
|
|
|
@ -80,8 +80,8 @@ ProcDRI2QueryVersion(ClientPtr client)
|
|||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.majorVersion = SERVER_DRI2_MAJOR_VERSION;
|
||||
rep.minorVersion = SERVER_DRI2_MINOR_VERSION;
|
||||
rep.majorVersion = dri2_major;
|
||||
rep.minorVersion = dri2_minor;
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
|
@ -384,6 +384,13 @@ ProcDRI2SwapBuffers(ClientPtr client)
|
|||
DixReadAccess | DixWriteAccess, &pDrawable, &status))
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Ensures an out of control client can't exhaust our swap queue, and
|
||||
* also orders swaps.
|
||||
*/
|
||||
if (DRI2ThrottleClient(client, pDrawable))
|
||||
return client->noClientException;
|
||||
|
||||
target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
|
||||
divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
|
||||
remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
|
||||
|
|
|
@ -51,10 +51,6 @@
|
|||
#define SERVER_DMX_MINOR_VERSION 2
|
||||
#define SERVER_DMX_PATCH_VERSION 20040604
|
||||
|
||||
/* DRI2 */
|
||||
#define SERVER_DRI2_MAJOR_VERSION 1
|
||||
#define SERVER_DRI2_MINOR_VERSION 2
|
||||
|
||||
/* Generic event extension */
|
||||
#define SERVER_GE_MAJOR_VERSION 1
|
||||
#define SERVER_GE_MINOR_VERSION 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user