summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-03-02 10:28:31 +0000
committerMartin Peres <martin.peres@linux.intel.com>2015-08-18 12:59:27 +0300
commitcadf5b541eb57798c1c4fe83d6cfb42ca998d7bd (patch)
tree69e9a23327535a504d5d7968c3da9e60670b77a7
parentbd3067436150de4b85554081413fd5c8a4762a9e (diff)
dri2: Add SwapBuffersWithDamagedri2-swapbuffers
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--glx/glxdri2.c3
-rw-r--r--hw/xfree86/dri2/dri2.c57
-rw-r--r--hw/xfree86/dri2/dri2.h1
-rw-r--r--hw/xfree86/dri2/dri2ext.c78
4 files changed, 123 insertions, 16 deletions
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index af050b744..64038e5d1 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -211,7 +211,8 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
(*screen->flush->invalidate) (priv->driDrawable);
}
- status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+ status = DRI2SwapBuffers(client, drawable->pDraw, NULL, NULL,
+ 0, 0, 0, &unused,
__glXdriSwapEvent, drawable);
if (cx != lastGLContext) {
lastGLContext = cx;
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index cbdafe588..f91fe62df 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -1096,14 +1096,16 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
int
-DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- CARD64 divisor, CARD64 remainder, CARD64 * swap_target,
- DRI2SwapEventPtr func, void *data)
+DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw,
+ RegionPtr valid, RegionPtr update,
+ CARD64 target_msc, CARD64 divisor, CARD64 remainder,
+ CARD64 *swap_target, DRI2SwapEventPtr func, void *data)
{
ScreenPtr pScreen = pDraw->pScreen;
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv;
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
+ RegionRec region;
int ret, i;
CARD64 ust, current_msc;
@@ -1135,24 +1137,25 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
}
if (ds->bufferAge)
- pSrcBuffer->flags = *swap_target;
+ pSrcBuffer->flags = valid ? 0 : *swap_target;
/* Old DDX or PRIME, just blit */
- if (!ds->ScheduleSwap ||
+ if (valid ||
+ !ds->ScheduleSwap ||
(pPriv->swap_interval == 0 && !ds->scheduleSwap0) ||
pPriv->prime_id) {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pDraw->width;
- box.y2 = pDraw->height;
- RegionInit(&region, &box, 0);
+ if (valid == NULL) {
+ region.extents.x1 = 0;
+ region.extents.y1 = 0;
+ region.extents.x2 = pDraw->width;
+ region.extents.y2 = pDraw->height;
+ region.data = NULL;
+ valid = &region;
+ }
pPriv->swapsPending++;
- dri2_copy_region(pDraw, &region, pDestBuffer, pSrcBuffer);
+ dri2_copy_region(pDraw, valid, pDestBuffer, pSrcBuffer);
DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
func, data);
return Success;
@@ -1189,6 +1192,28 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
target_msc = pPriv->last_swap_target + pPriv->swap_interval;
}
+ if (update == NULL) {
+ if (pDraw->type != DRAWABLE_WINDOW) {
+ region.extents.x1 = 0;
+ region.extents.y1 = 0;
+ region.extents.x2 = pDraw->width;
+ region.extents.y2 = pDraw->height;
+ region.data = NULL;
+ update = &region;
+ } else
+ update = &((WindowPtr)pDraw)->clipList;
+ DamageRegionAppend(pDraw, update);
+ } else if (RegionNotEmpty(update)) {
+ RegionNull(&region);
+ RegionCopy(&region, update);
+ if (pDraw->x | pDraw->y)
+ RegionTranslate(&region, pDraw->x, pDraw->y);
+ if (pDraw->type == DRAWABLE_WINDOW)
+ RegionIntersect(&region, &region, &((WindowPtr)pDraw)->clipList);
+ DamageRegionAppend(pDraw, &region);
+ RegionUninit(&region);
+ }
+
pPriv->swapsPending++;
ret = (*ds->ScheduleSwap) (client, pDraw, pDestBuffer, pSrcBuffer,
&target_msc, divisor, remainder, func, data);
@@ -1201,6 +1226,9 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
pPriv->last_swap_target = target_msc;
+ if (RegionNotEmpty(update))
+ DamageRegionProcessPending(pDraw);
+
DRI2InvalidateDrawableAll(pDraw);
return Success;
@@ -1584,6 +1612,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
if (info->version >= 10) {
ds->scheduleSwap0 = info->scheduleSwap0;
ds->bufferAge = info->bufferAge;
+ cur_minor = 5;
}
/*
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 7a89de2fd..27bd48e30 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -321,6 +321,7 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
extern _X_EXPORT Bool DRI2SwapLimit(DrawablePtr pDraw, int swap_limit);
extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
+ RegionPtr valid, RegionPtr update,
CARD64 target_msc, CARD64 divisor,
CARD64 remainder, CARD64 * swap_target,
DRI2SwapEventPtr func, void *data);
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 7c9bc63b8..ae7c2c5fd 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -413,7 +413,81 @@ ProcDRI2SwapBuffers(ClientPtr client)
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,
+ status = DRI2SwapBuffers(client, pDrawable, NULL, NULL,
+ target_msc, divisor, remainder,
+ &swap_target, DRI2SwapEvent, pDrawable);
+ if (status != Success)
+ return BadDrawable;
+
+ load_swap_reply(&rep, swap_target);
+
+ WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
+
+ return Success;
+}
+
+static int region_subsumes_drawable(RegionPtr region, DrawablePtr drawable)
+{
+ if (region == NULL)
+ return 0;
+
+ if (region->data)
+ return 0;
+
+ if (region->extents.x1 > drawable->x)
+ return 0;
+ if (region->extents.x2 < drawable->x + drawable->width)
+ return 0;
+
+ if (region->extents.y1 > drawable->y)
+ return 0;
+ if (region->extents.y2 < drawable->y + drawable->height)
+ return 0;
+
+ return 1;
+}
+
+static int
+ProcDRI2SwapBuffersWithDamage(ClientPtr client)
+{
+ REQUEST(xDRI2SwapBuffersWithDamageReq);
+ xDRI2SwapBuffersReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ .length = 0
+ };
+ DrawablePtr pDrawable;
+ RegionPtr valid, update;
+ CARD64 target_msc, divisor, remainder, swap_target;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2SwapBuffersWithDamageReq);
+
+ if (!validDrawable(client, stuff->drawable,
+ DixReadAccess | DixWriteAccess, &pDrawable, &status))
+ return status;
+
+ VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
+ VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
+
+ if (region_subsumes_drawable(valid, pDrawable))
+ valid = NULL;
+ if (region_subsumes_drawable(update, pDrawable))
+ update = NULL;
+
+ /*
+ * Ensures an out of control client can't exhaust our swap queue, and
+ * also orders swaps.
+ */
+ if (DRI2ThrottleClient(client, pDrawable))
+ return Success;
+
+ 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, valid, update,
+ target_msc, divisor, remainder,
&swap_target, DRI2SwapEvent, pDrawable);
if (status != Success)
return BadDrawable;
@@ -621,6 +695,8 @@ ProcDRI2Dispatch(ClientPtr client)
return ProcDRI2SwapInterval(client);
case X_DRI2GetParam:
return ProcDRI2GetParam(client);
+ case X_DRI2SwapBuffersWithDamage:
+ return ProcDRI2SwapBuffersWithDamage(client);
default:
return BadRequest;
}