mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-05-01 19:38:09 +02:00
DRI2: initial MSC support
Add support for MSC queries and waits along the same lines as asynchronous swapbuffers.
This commit is contained in:
parent
ecf7439af4
commit
94d2897c95
7 changed files with 437 additions and 73 deletions
|
|
@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
|
|||
return error;
|
||||
|
||||
if (pGlxDraw->type == DRAWABLE_WINDOW &&
|
||||
(*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE)
|
||||
(*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
|
||||
return __glXError(GLXBadDrawable);
|
||||
|
||||
return Success;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ enum {
|
|||
|
||||
struct __GLXdrawable {
|
||||
void (*destroy)(__GLXdrawable *private);
|
||||
GLboolean (*swapBuffers)(__GLXdrawable *);
|
||||
GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *);
|
||||
void (*copySubBuffer)(__GLXdrawable *drawable,
|
||||
int x, int y, int w, int h);
|
||||
void (*waitX)(__GLXdrawable *);
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
|||
}
|
||||
|
||||
static GLboolean
|
||||
__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
|
||||
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
|
||||
{
|
||||
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
|
||||
__GLXDRIscreen *screen =
|
||||
|
|
|
|||
|
|
@ -174,18 +174,15 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
|
|||
* swap should happen, then perform the copy when we receive it.
|
||||
*/
|
||||
static GLboolean
|
||||
__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
|
||||
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
|
||||
{
|
||||
__GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
|
||||
__GLXDRIscreen *screen = priv->screen;
|
||||
int interval = 1;
|
||||
|
||||
if (screen->swapControl)
|
||||
interval = screen->swapControl->getSwapInterval(priv->driDrawable);
|
||||
CARD64 unused;
|
||||
|
||||
(*screen->flush->flushInvalidate)(priv->driDrawable);
|
||||
|
||||
if (DRI2SwapBuffers(drawable->pDraw, interval) != Success)
|
||||
if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused) != Success)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -194,12 +191,10 @@ __glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
|
|||
static int
|
||||
__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
|
||||
{
|
||||
__GLXDRIdrawable *draw = (__GLXDRIdrawable *) drawable;
|
||||
__GLXDRIscreen *screen =
|
||||
(__GLXDRIscreen *) glxGetScreen(drawable->pDraw->pScreen);
|
||||
if (interval <= 0) /* || interval > BIGNUM? */
|
||||
return GLX_BAD_VALUE;
|
||||
|
||||
if (screen->swapControl)
|
||||
screen->swapControl->setSwapInterval(draw->driDrawable, interval);
|
||||
DRI2SwapInterval(drawable->pDraw, interval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <xf86drm.h>
|
||||
#include "xf86Module.h"
|
||||
#include "scrnintstr.h"
|
||||
|
|
@ -60,17 +61,75 @@ typedef struct _DRI2Drawable {
|
|||
unsigned int swapsPending;
|
||||
unsigned int flipsPending;
|
||||
ClientPtr blockedClient;
|
||||
int swap_interval;
|
||||
CARD64 swap_count;
|
||||
CARD64 last_swap_target; /* most recently queued swap target */
|
||||
} DRI2DrawableRec, *DRI2DrawablePtr;
|
||||
|
||||
typedef struct _DRI2Screen *DRI2ScreenPtr;
|
||||
typedef struct _DRI2SwapData *DRI2SwapDataPtr;
|
||||
typedef struct _DRI2FrameEvent *DRI2FrameEventPtr;
|
||||
|
||||
typedef struct _DRI2SwapData {
|
||||
#define container_of(ptr,type,mem) ((type *)((char *)(ptr) - offsetof(type, \
|
||||
mem)))
|
||||
|
||||
struct list {
|
||||
struct list *prev, *next;
|
||||
};
|
||||
|
||||
static inline void list_init(struct list *l)
|
||||
{
|
||||
l->prev = l;
|
||||
l->next = l;
|
||||
}
|
||||
|
||||
static inline void __list_add(struct list *l, struct list *prev,
|
||||
struct list *next)
|
||||
{
|
||||
prev->next = l;
|
||||
l->prev = prev;
|
||||
l->next = next;
|
||||
next->prev = l;
|
||||
}
|
||||
|
||||
static inline void list_add(struct list *l, struct list *head)
|
||||
{
|
||||
__list_add(l, head, head->next);
|
||||
}
|
||||
|
||||
static inline void list_add_tail(struct list *l, struct list *head)
|
||||
{
|
||||
__list_add(l, head->prev, head);
|
||||
}
|
||||
|
||||
static inline void list_del(struct list *l)
|
||||
{
|
||||
l->prev->next = l->next;
|
||||
l->next->prev = l->prev;
|
||||
list_init(l);
|
||||
}
|
||||
|
||||
static inline Bool list_is_empty(struct list *l)
|
||||
{
|
||||
return l->next == l;
|
||||
}
|
||||
|
||||
#define list_foreach_safe(cur, tmp, head) \
|
||||
for (cur = (head)->next, tmp = cur->next; cur != (head); \
|
||||
cur = tmp, tmp = cur->next)
|
||||
|
||||
enum DRI2FrameEventType {
|
||||
DRI2_SWAP,
|
||||
DRI2_WAITMSC,
|
||||
};
|
||||
|
||||
typedef struct _DRI2FrameEvent {
|
||||
DrawablePtr pDraw;
|
||||
ScreenPtr pScreen;
|
||||
ClientPtr client;
|
||||
enum DRI2FrameEventType type;
|
||||
int frame;
|
||||
DRI2SwapDataPtr next;
|
||||
} DRI2SwapDataRec;
|
||||
struct list link;
|
||||
} DRI2FrameEventRec;
|
||||
|
||||
typedef struct _DRI2Screen {
|
||||
const char *driverName;
|
||||
|
|
@ -78,12 +137,15 @@ typedef struct _DRI2Screen {
|
|||
int fd;
|
||||
unsigned int lastSequence;
|
||||
drmEventContext event_context;
|
||||
DRI2SwapDataPtr swaps; /* Pending swap list */
|
||||
struct list swaps;
|
||||
|
||||
DRI2CreateBufferProcPtr CreateBuffer;
|
||||
DRI2DestroyBufferProcPtr DestroyBuffer;
|
||||
DRI2CopyRegionProcPtr CopyRegion;
|
||||
DRI2SetupSwapProcPtr SetupSwap;
|
||||
DRI2SwapBuffersProcPtr SwapBuffers;
|
||||
DRI2GetMSCProcPtr GetMSC;
|
||||
DRI2SetupWaitMSCProcPtr SetupWaitMSC;
|
||||
|
||||
HandleExposuresProcPtr HandleExposures;
|
||||
} DRI2ScreenRec;
|
||||
|
|
@ -141,6 +203,9 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|||
pPriv->swapsPending = 0;
|
||||
pPriv->flipsPending = 0;
|
||||
pPriv->blockedClient = NULL;
|
||||
pPriv->swap_count = 0;
|
||||
pPriv->swap_interval = 1;
|
||||
pPriv->last_swap_target = 0;
|
||||
|
||||
if (pDraw->type == DRAWABLE_WINDOW)
|
||||
{
|
||||
|
|
@ -383,46 +448,66 @@ DRI2FlipCheck(DrawablePtr pDraw)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool DRI2AddSwap(DrawablePtr pDraw, int frame)
|
||||
static Bool DRI2AddFrameEvent(DrawablePtr pDraw, ClientPtr client,
|
||||
enum DRI2FrameEventType type, int frame)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
DRI2DrawablePtr pPriv;
|
||||
DRI2SwapDataPtr new;
|
||||
DRI2FrameEventPtr new;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return FALSE;
|
||||
|
||||
new = xcalloc(1, sizeof(DRI2SwapDataRec));
|
||||
new = xcalloc(1, sizeof(DRI2FrameEventRec));
|
||||
if (!new)
|
||||
return FALSE;
|
||||
|
||||
new->pScreen = pDraw->pScreen;
|
||||
new->pDraw = pDraw;
|
||||
new->client = client;
|
||||
new->frame = frame;
|
||||
new->next = ds->swaps;
|
||||
ds->swaps = new;
|
||||
new->type = type;
|
||||
|
||||
list_add_tail(&new->link, &ds->swaps);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void DRI2RemoveSwap(DRI2SwapDataPtr swap)
|
||||
static void DRI2RemoveFrameEvent(DRI2FrameEventPtr event)
|
||||
{
|
||||
ScreenPtr pScreen = swap->pScreen;
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
|
||||
DRI2SwapDataPtr cur = ds->swaps;
|
||||
|
||||
while (cur) {
|
||||
if (cur == swap) {
|
||||
cur->next = swap->next;
|
||||
xfree(swap);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
list_del(&event->link);
|
||||
xfree(event);
|
||||
}
|
||||
|
||||
static void
|
||||
DRI2SwapSubmit(DRI2SwapDataPtr swap)
|
||||
DRI2WaitMSCComplete(DRI2FrameEventPtr swap, unsigned int sequence,
|
||||
unsigned int tv_sec, unsigned int tv_usec)
|
||||
{
|
||||
DrawablePtr pDraw = swap->pDraw;
|
||||
DRI2DrawablePtr pPriv;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return;
|
||||
|
||||
ProcDRI2WaitMSCReply(swap->client, ((CARD64)tv_sec * 1000000) + tv_usec,
|
||||
sequence, pPriv->swap_count);
|
||||
|
||||
if (pPriv->blockedClient)
|
||||
AttendClient(pPriv->blockedClient);
|
||||
|
||||
pPriv->blockedClient = NULL;
|
||||
}
|
||||
|
||||
/* Wake up clients waiting for flip/swap completion */
|
||||
static void DRI2SwapComplete(DRI2DrawablePtr pPriv)
|
||||
{
|
||||
pPriv->swap_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
DRI2SwapSubmit(DRI2FrameEventPtr swap)
|
||||
{
|
||||
DrawablePtr pDraw = swap->pDraw;
|
||||
ScreenPtr pScreen = swap->pScreen;
|
||||
|
|
@ -472,8 +557,7 @@ DRI2SwapSubmit(DRI2SwapDataPtr swap)
|
|||
box.y2 = pPriv->height;
|
||||
REGION_INIT(pScreen, ®ion, &box, 0);
|
||||
|
||||
DRI2CopyRegion(pDraw, ®ion,
|
||||
DRI2BufferFrontLeft, DRI2BufferBackLeft);
|
||||
DRI2CopyRegion(pDraw, ®ion, DRI2BufferFrontLeft, DRI2BufferBackLeft);
|
||||
pPriv->swapsPending--;
|
||||
|
||||
DRI2SwapComplete(pPriv);
|
||||
|
|
@ -483,14 +567,39 @@ static void drm_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
|
|||
unsigned int tv_usec, void *user_data)
|
||||
{
|
||||
DRI2ScreenPtr ds = user_data;
|
||||
DRI2SwapDataPtr cur = ds->swaps;
|
||||
DRI2DrawablePtr pPriv;
|
||||
struct list *cur, *tmp;
|
||||
|
||||
while (cur) {
|
||||
if (cur->frame == frame) {
|
||||
DRI2SwapSubmit(cur);
|
||||
DRI2RemoveSwap(cur);
|
||||
if (list_is_empty(&ds->swaps)) {
|
||||
ErrorF("tried to dequeue non-existent swap\n");
|
||||
return;
|
||||
}
|
||||
|
||||
list_foreach_safe(cur, tmp, &ds->swaps) {
|
||||
DRI2FrameEventPtr swap = container_of(cur, DRI2FrameEventRec, link);
|
||||
|
||||
if (swap->frame != frame)
|
||||
continue;
|
||||
|
||||
pPriv = DRI2GetDrawable(swap->pDraw);
|
||||
if (pPriv == NULL) {
|
||||
DRI2RemoveFrameEvent(swap);
|
||||
ErrorF("no dri2priv??\n");
|
||||
continue; /* FIXME: check priv refcounting */
|
||||
}
|
||||
cur = cur->next;
|
||||
|
||||
switch (swap->type) {
|
||||
case DRI2_SWAP:
|
||||
DRI2SwapSubmit(swap);
|
||||
break;
|
||||
case DRI2_WAITMSC:
|
||||
DRI2WaitMSCComplete(swap, frame, tv_sec, tv_usec);
|
||||
break;
|
||||
default:
|
||||
/* Unknown type */
|
||||
break;
|
||||
}
|
||||
DRI2RemoveFrameEvent(swap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -505,17 +614,24 @@ drm_wakeup_handler(pointer data, int err, pointer p)
|
|||
}
|
||||
|
||||
int
|
||||
DRI2SwapBuffers(DrawablePtr pDraw, int interval)
|
||||
DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||
CARD64 divisor, CARD64 remainder, CARD64 *swap_target)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
DRI2DrawablePtr pPriv;
|
||||
drmVBlank vbl;
|
||||
CARD64 event_frame;
|
||||
int ret;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return BadDrawable;
|
||||
|
||||
vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (DRI2FlipCheck(pDraw)) {
|
||||
/*
|
||||
|
|
@ -523,25 +639,28 @@ DRI2SwapBuffers(DrawablePtr pDraw, int interval)
|
|||
* frame - 1 to honor the swap interval.
|
||||
*/
|
||||
pPriv->flipsPending++;
|
||||
if (interval > 1) {
|
||||
vbl.request.sequence = interval - 1;
|
||||
if (pPriv->swap_interval > 1) {
|
||||
*swap_target = *swap_target - 1;
|
||||
/* fixme: prevent cliprect changes between now and the flip */
|
||||
} else {
|
||||
/* FIXME: perform immediate page flip */
|
||||
DRI2SwapComplete(pPriv);
|
||||
return Success;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pPriv->swapsPending++;
|
||||
vbl.request.sequence = interval;
|
||||
}
|
||||
|
||||
/* fixme: get correct crtc for this drawable */
|
||||
drmWaitVBlank(ds->fd, &vbl);
|
||||
ret = (*ds->SetupSwap)(pDraw, *swap_target, divisor, remainder, ds,
|
||||
&event_frame);
|
||||
if (!ret)
|
||||
return BadDrawable;
|
||||
|
||||
/* Request an event for the requested frame */
|
||||
if (!DRI2AddSwap(pDraw, vbl.reply.sequence))
|
||||
if (!DRI2AddFrameEvent(pDraw, client, DRI2_SWAP, event_frame))
|
||||
return BadValue;
|
||||
|
||||
pPriv->last_swap_target = *swap_target;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
@ -565,15 +684,88 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Wake up clients waiting for flip/swap completion */
|
||||
void DRI2SwapComplete(void *data)
|
||||
void
|
||||
DRI2SwapInterval(DrawablePtr pDrawable, int interval)
|
||||
{
|
||||
DRI2DrawablePtr pPriv = data;
|
||||
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
|
||||
|
||||
if (pPriv->blockedClient)
|
||||
AttendClient(pPriv->blockedClient);
|
||||
/* fixme: check against arbitrary max? */
|
||||
|
||||
pPriv->blockedClient = NULL;
|
||||
pPriv->swap_interval = interval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
DRI2DrawablePtr pPriv;
|
||||
Bool ret;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return BadDrawable;
|
||||
|
||||
if (!ds->GetMSC)
|
||||
FatalError("advertised MSC support w/o driver hook\n");
|
||||
|
||||
ret = (*ds->GetMSC)(pDraw, ust, msc);
|
||||
if (!ret)
|
||||
return BadDrawable;
|
||||
|
||||
*sbc = pPriv->swap_count;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||
CARD64 divisor, CARD64 remainder)
|
||||
{
|
||||
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
||||
DRI2DrawablePtr pPriv;
|
||||
CARD64 event_frame;
|
||||
Bool ret;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return BadDrawable;
|
||||
|
||||
ret = (*ds->SetupWaitMSC)(pDraw, target_msc, divisor, remainder, ds,
|
||||
&event_frame);
|
||||
if (!ret) {
|
||||
ErrorF("setupmsc failed: %d\n", ret);
|
||||
return BadDrawable;
|
||||
}
|
||||
|
||||
ret = DRI2AddFrameEvent(pDraw, client, DRI2_WAITMSC, event_frame);
|
||||
if (!ret)
|
||||
return BadDrawable;
|
||||
|
||||
/* DDX returned > 0, block the client until its wait completes */
|
||||
|
||||
if (pPriv->blockedClient == NULL) {
|
||||
IgnoreClient(client);
|
||||
pPriv->blockedClient = client;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
DRI2WaitSBC(DrawablePtr pDraw, CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
|
||||
CARD64 *sbc)
|
||||
{
|
||||
DRI2DrawablePtr pPriv;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL)
|
||||
return BadDrawable;
|
||||
|
||||
/* fixme: put client to sleep until swap count hits target */
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -675,12 +867,18 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|||
ds->DestroyBuffer = info->DestroyBuffer;
|
||||
ds->CopyRegion = info->CopyRegion;
|
||||
|
||||
if (info->version >= 4)
|
||||
if (info->version >= 4) {
|
||||
ds->SetupSwap = info->SetupSwap;
|
||||
ds->SwapBuffers = info->SwapBuffers;
|
||||
ds->SetupWaitMSC = info->SetupWaitMSC;
|
||||
ds->GetMSC = info->GetMSC;
|
||||
}
|
||||
|
||||
ds->event_context.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
ds->event_context.vblank_handler = drm_vblank_handler;
|
||||
|
||||
list_init(&ds->swaps);
|
||||
|
||||
AddGeneralSocket(ds->fd);
|
||||
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
|
||||
drm_wakeup_handler, ds);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
|
|||
RegionPtr pRegion,
|
||||
DRI2BufferPtr pDestBuffer,
|
||||
DRI2BufferPtr pSrcBuffer);
|
||||
typedef int (*DRI2SetupSwapProcPtr)(DrawablePtr pDraw,
|
||||
CARD64 target_msc,
|
||||
CARD64 divisor,
|
||||
CARD64 remainder,
|
||||
void *data,
|
||||
CARD64 *event_frame);
|
||||
typedef Bool (*DRI2SwapBuffersProcPtr)(ScreenPtr pScreen,
|
||||
DRI2BufferPtr pFrontBuffer,
|
||||
DRI2BufferPtr pBackBuffer,
|
||||
|
|
@ -71,6 +77,14 @@ typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
|
|||
unsigned int format);
|
||||
typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
|
||||
DRI2BufferPtr buffer);
|
||||
typedef int (*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
|
||||
CARD64 *msc);
|
||||
typedef int (*DRI2SetupWaitMSCProcPtr)(DrawablePtr pDraw,
|
||||
CARD64 target_msc,
|
||||
CARD64 divisor,
|
||||
CARD64 remainder,
|
||||
void *data,
|
||||
CARD64 *event_frame);
|
||||
|
||||
/**
|
||||
* Version of the DRI2InfoRec structure defined in this header
|
||||
|
|
@ -86,8 +100,10 @@ typedef struct {
|
|||
DRI2CreateBufferProcPtr CreateBuffer;
|
||||
DRI2DestroyBufferProcPtr DestroyBuffer;
|
||||
DRI2CopyRegionProcPtr CopyRegion;
|
||||
DRI2SetupSwapProcPtr SetupSwap;
|
||||
DRI2SwapBuffersProcPtr SwapBuffers;
|
||||
|
||||
DRI2GetMSCProcPtr GetMSC;
|
||||
DRI2SetupWaitMSCProcPtr SetupWaitMSC;
|
||||
} DRI2InfoRec, *DRI2InfoPtr;
|
||||
|
||||
extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
|
||||
|
|
@ -141,8 +157,23 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
|
|||
int *width, int *height, unsigned int *attachments, int count,
|
||||
int *out_count);
|
||||
|
||||
extern _X_EXPORT int DRI2SwapBuffers(DrawablePtr pDrawable, int interval);
|
||||
extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
|
||||
extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
|
||||
CARD64 target_msc, CARD64 divisor,
|
||||
CARD64 remainder, CARD64 *swap_target);
|
||||
extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
|
||||
extern _X_EXPORT void DRI2SwapComplete(void *data);
|
||||
|
||||
extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
|
||||
CARD64 *msc, CARD64 *sbc);
|
||||
extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
|
||||
CARD64 target_msc, CARD64 divisor,
|
||||
CARD64 remainder);
|
||||
extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
|
||||
CARD64 msc, CARD64 sbc);
|
||||
extern _X_EXPORT int DRI2WaitSBC(DrawablePtr pDraw, CARD64 target_sbc,
|
||||
CARD64 *ust, CARD64 *msc, CARD64 *sbc);
|
||||
#define DRI2_WAITMSC_ERROR -1
|
||||
#define DRI2_WAITMSC_DONE 0
|
||||
#define DRI2_WAITMSC_BLOCK 1
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -259,9 +259,6 @@ ProcDRI2GetBuffers(ClientPtr client)
|
|||
&pDrawable, &status))
|
||||
return status;
|
||||
|
||||
if (DRI2WaitSwap(client, pDrawable))
|
||||
return client->noClientException;
|
||||
|
||||
attachments = (unsigned int *) &stuff[1];
|
||||
buffers = DRI2GetBuffers(pDrawable, &width, &height,
|
||||
attachments, stuff->count, &count);
|
||||
|
|
@ -286,9 +283,6 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
|
|||
&pDrawable, &status))
|
||||
return status;
|
||||
|
||||
if (DRI2WaitSwap(client, pDrawable))
|
||||
return client->noClientException;
|
||||
|
||||
attachments = (unsigned int *) &stuff[1];
|
||||
buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
|
||||
attachments, stuff->count, &count);
|
||||
|
|
@ -335,11 +329,26 @@ ProcDRI2CopyRegion(ClientPtr client)
|
|||
return client->noClientException;
|
||||
}
|
||||
|
||||
static void
|
||||
load_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc)
|
||||
{
|
||||
rep->swap_hi = sbc >> 32;
|
||||
rep->swap_lo = sbc & 0xffffffff;
|
||||
}
|
||||
|
||||
static CARD64
|
||||
vals_to_card64(CARD32 lo, CARD32 hi)
|
||||
{
|
||||
return (CARD64)hi << 32 | lo;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcDRI2SwapBuffers(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI2SwapBuffersReq);
|
||||
xDRI2SwapBuffersReply rep;
|
||||
DrawablePtr pDrawable;
|
||||
CARD64 target_msc, divisor, remainder, swap_target;
|
||||
int status;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
|
||||
|
|
@ -347,7 +356,132 @@ ProcDRI2SwapBuffers(ClientPtr client)
|
|||
if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
|
||||
return status;
|
||||
|
||||
return DRI2SwapBuffers(pDrawable, 0); /* get swap interval... */
|
||||
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);
|
||||
|
||||
status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
|
||||
&swap_target);
|
||||
if (status != Success)
|
||||
return BadDrawable;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
load_swap_reply(&rep, swap_target);
|
||||
|
||||
WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
static void
|
||||
load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
|
||||
{
|
||||
rep->ust_hi = ust >> 32;
|
||||
rep->ust_lo = ust & 0xffffffff;
|
||||
rep->msc_hi = msc >> 32;
|
||||
rep->msc_lo = msc & 0xffffffff;
|
||||
rep->sbc_hi = sbc >> 32;
|
||||
rep->sbc_lo = sbc & 0xffffffff;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcDRI2GetMSC(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI2GetMSCReq);
|
||||
xDRI2MSCReply rep;
|
||||
DrawablePtr pDrawable;
|
||||
CARD64 ust, msc, sbc;
|
||||
int status;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
|
||||
|
||||
if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
|
||||
return status;
|
||||
|
||||
status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
load_msc_reply(&rep, ust, msc, sbc);
|
||||
|
||||
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcDRI2WaitMSC(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI2WaitMSCReq);
|
||||
DrawablePtr pDrawable;
|
||||
CARD64 target, divisor, remainder;
|
||||
int status;
|
||||
|
||||
/* FIXME: in restart case, client may be gone at this point */
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
|
||||
|
||||
if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
|
||||
return status;
|
||||
|
||||
target = 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);
|
||||
|
||||
status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
int
|
||||
ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
|
||||
{
|
||||
xDRI2MSCReply rep;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
load_msc_reply(&rep, ust, msc, sbc);
|
||||
|
||||
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcDRI2WaitSBC(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI2WaitSBCReq);
|
||||
xDRI2MSCReply rep;
|
||||
DrawablePtr pDrawable;
|
||||
CARD64 target, ust, msc, sbc;
|
||||
int status;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
|
||||
|
||||
if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
|
||||
return status;
|
||||
|
||||
target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
|
||||
status = DRI2WaitSBC(pDrawable, target, &ust, &msc, &sbc);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
load_msc_reply(&rep, ust, msc, sbc);
|
||||
|
||||
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -380,6 +514,12 @@ ProcDRI2Dispatch (ClientPtr client)
|
|||
return ProcDRI2GetBuffersWithFormat(client);
|
||||
case X_DRI2SwapBuffers:
|
||||
return ProcDRI2SwapBuffers(client);
|
||||
case X_DRI2GetMSC:
|
||||
return ProcDRI2GetMSC(client);
|
||||
case X_DRI2WaitMSC:
|
||||
return ProcDRI2WaitMSC(client);
|
||||
case X_DRI2WaitSBC:
|
||||
return ProcDRI2WaitSBC(client);
|
||||
default:
|
||||
return BadRequest;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue