diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-03 14:23:52 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-10-29 14:05:10 -0700 |
commit | 94d2897c95da1b129158e91391b96a26a1612bcd (patch) | |
tree | 5e6684e0595f26f0ac0815a5dc1aae3e08e5a401 | |
parent | ecf7439af402de218a3874a6ac9ebd83b50c970e (diff) |
DRI2: initial MSC support
Add support for MSC queries and waits along the same lines as asynchronous
swapbuffers.
-rw-r--r-- | glx/glxcmds.c | 2 | ||||
-rw-r--r-- | glx/glxdrawable.h | 2 | ||||
-rw-r--r-- | glx/glxdri.c | 2 | ||||
-rw-r--r-- | glx/glxdri2.c | 17 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.c | 294 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.h | 37 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2ext.c | 154 |
7 files changed, 436 insertions, 72 deletions
diff --git a/glx/glxcmds.c b/glx/glxcmds.c index eedab652f..77afbf4b1 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -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; diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h index 3f165ed4f..2a365c505 100644 --- a/glx/glxdrawable.h +++ b/glx/glxdrawable.h @@ -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 *); diff --git a/glx/glxdri.c b/glx/glxdri.c index 6122653b0..21e44d12d 100644 --- a/glx/glxdri.c +++ b/glx/glxdri.c @@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) } static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate) +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; __GLXDRIscreen *screen = diff --git a/glx/glxdri2.c b/glx/glxdri2.c index 0a3720e45..b8a960531 100644 --- a/glx/glxdri2.c +++ b/glx/glxdri2.c @@ -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; } diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index fe3888558..082dcb568 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -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; + list_del(&event->link); + xfree(event); +} - while (cur) { - if (cur == swap) { - cur->next = swap->next; - xfree(swap); - } - cur = cur->next; - } +static void +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(DRI2SwapDataPtr swap) +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; + + if (list_is_empty(&ds->swaps)) { + ErrorF("tried to dequeue non-existent swap\n"); + return; + } - while (cur) { - if (cur->frame == frame) { - DRI2SwapSubmit(cur); - DRI2RemoveSwap(cur); + 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 */ + } + + switch (swap->type) { + case DRI2_SWAP: + DRI2SwapSubmit(swap); + break; + case DRI2_WAITMSC: + DRI2WaitMSCComplete(swap, frame, tv_sec, tv_usec); + break; + default: + /* Unknown type */ + break; } - cur = cur->next; + 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); diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index e8f12d1d9..57f34bfa2 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -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 diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index 9fc033ab7..35297a49e 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -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; } |