diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-03-02 10:28:31 +0000 |
---|---|---|
committer | Martin Peres <martin.peres@linux.intel.com> | 2015-08-18 12:59:27 +0300 |
commit | cadf5b541eb57798c1c4fe83d6cfb42ca998d7bd (patch) | |
tree | 69e9a23327535a504d5d7968c3da9e60670b77a7 | |
parent | bd3067436150de4b85554081413fd5c8a4762a9e (diff) |
dri2: Add SwapBuffersWithDamagedri2-swapbuffers
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | glx/glxdri2.c | 3 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.c | 57 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2.h | 1 | ||||
-rw-r--r-- | hw/xfree86/dri2/dri2ext.c | 78 |
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(®ion, &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 = ®ion; + } pPriv->swapsPending++; - dri2_copy_region(pDraw, ®ion, 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 = ®ion; + } else + update = &((WindowPtr)pDraw)->clipList; + DamageRegionAppend(pDraw, update); + } else if (RegionNotEmpty(update)) { + RegionNull(®ion); + RegionCopy(®ion, update); + if (pDraw->x | pDraw->y) + RegionTranslate(®ion, pDraw->x, pDraw->y); + if (pDraw->type == DRAWABLE_WINDOW) + RegionIntersect(®ion, ®ion, &((WindowPtr)pDraw)->clipList); + DamageRegionAppend(pDraw, ®ion); + RegionUninit(®ion); + } + 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; } |