summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-09-03 14:23:52 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-10-29 14:05:10 -0700
commit94d2897c95da1b129158e91391b96a26a1612bcd (patch)
tree5e6684e0595f26f0ac0815a5dc1aae3e08e5a401
parentecf7439af402de218a3874a6ac9ebd83b50c970e (diff)
DRI2: initial MSC support
Add support for MSC queries and waits along the same lines as asynchronous swapbuffers.
-rw-r--r--glx/glxcmds.c2
-rw-r--r--glx/glxdrawable.h2
-rw-r--r--glx/glxdri.c2
-rw-r--r--glx/glxdri2.c17
-rw-r--r--hw/xfree86/dri2/dri2.c294
-rw-r--r--hw/xfree86/dri2/dri2.h37
-rw-r--r--hw/xfree86/dri2/dri2ext.c154
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, &region, &box, 0);
- DRI2CopyRegion(pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
+ DRI2CopyRegion(pDraw, &region, 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;
}