summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-25 16:34:15 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-25 16:34:15 +0100
commitb460b9645451af84136c5daebbc00c7545de67f4 (patch)
tree993f7cea56ec4a4207fefc10b30cdf83f17e4297
parent28fffbd1d07890c8b4d697369159f6a30f267675 (diff)
sna/dri: Fix composited copy-swaps
The secret is not to cheat and render directly to the front buffer, but remember to mark the Window as damaged. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri.c157
1 files changed, 73 insertions, 84 deletions
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 3a8a753e..510ddd16 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -324,52 +324,24 @@ static void sna_dri_reference_buffer(DRI2Buffer2Ptr buffer)
static void damage(DrawablePtr drawable, PixmapPtr pixmap, RegionPtr region)
{
struct sna_pixmap *priv;
- int16_t dx, dy;
-
- get_drawable_deltas(drawable, pixmap, &dx, &dy);
+ BoxPtr box;
priv = sna_pixmap(pixmap);
if (priv->gpu_only)
return;
- if (region) {
- BoxPtr box;
-
- RegionTranslate(region, dx, dy);
- box = RegionExtents(region);
- if (RegionNumRects(region) == 1 &&
- box->x1 <= 0 && box->y1 <= 0 &&
- box->x2 >= pixmap->drawable.width &&
- box->y2 >= pixmap->drawable.height) {
- sna_damage_all(&priv->gpu_damage,
- pixmap->drawable.width,
- pixmap->drawable.height);
- sna_damage_destroy(&priv->cpu_damage);
- } else {
- sna_damage_add(&priv->gpu_damage, region);
- sna_damage_subtract(&priv->cpu_damage, region);
- }
-
- RegionTranslate(region, -dx, -dy);
+ box = RegionExtents(region);
+ if (RegionNumRects(region) == 1 &&
+ box->x1 <= 0 && box->y1 <= 0 &&
+ box->x2 >= pixmap->drawable.width &&
+ box->y2 >= pixmap->drawable.height) {
+ sna_damage_all(&priv->gpu_damage,
+ pixmap->drawable.width,
+ pixmap->drawable.height);
+ sna_damage_destroy(&priv->cpu_damage);
} else {
- BoxRec box;
-
- box.x1 = drawable->x + dx;
- box.x2 = box.x1 + drawable->width;
-
- box.y1 = drawable->y + dy;
- box.y2 = box.y1 + drawable->height;
- if (box.x1 == 0 && box.y1 == 0 &&
- box.x2 == pixmap->drawable.width &&
- box.y2 == pixmap->drawable.height) {
- sna_damage_all(&priv->gpu_damage,
- pixmap->drawable.width,
- pixmap->drawable.height);
- sna_damage_destroy(&priv->cpu_damage);
- } else {
- sna_damage_add_box(&priv->gpu_damage, &box);
- sna_damage_subtract_box(&priv->gpu_damage, &box);
- }
+ sna_damage_add(&priv->gpu_damage, region);
+ sna_damage_subtract(&priv->cpu_damage, region);
}
}
@@ -386,7 +358,7 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
pixman_region16_t clip;
bool flush = false;
BoxRec box, *boxes;
- int16_t dx, dy;
+ int16_t dx, dy, sx, sy;
int n;
DBG(("%s: dst -- attachment=%d, name=%d, handle=%d [screen=%d]\n",
@@ -400,58 +372,71 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
src_buffer->attachment,
src_buffer->name,
src_priv->bo->handle));
+ if (region) {
+ DBG(("%s: clip (%d, %d), (%d, %d) x %d\n",
+ __FUNCTION__,
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2,
+ REGION_NUM_RECTS(region)));
+ }
- if (draw->type == DRAWABLE_PIXMAP) {
- if (region) {
- boxes = REGION_RECTS(region);
- n = REGION_NUM_RECTS(region);
- if (n == 0)
- return;
- } else {
- box.x1 = box.y1 = 0;
- box.x2 = draw->width;
- box.y2 = draw->height;
+ box.x1 = draw->x;
+ box.y1 = draw->y;
+ box.x2 = draw->x + draw->width;
+ box.y2 = draw->y + draw->height;
+
+ get_drawable_deltas(draw, src, &sx, &sy);
+ sx -= draw->x;
+ sy -= draw->y;
+
+ if (region) {
+ pixman_region_translate(region, draw->x, draw->y);
+ pixman_region_init_rects(&clip, &box, 1);
+ pixman_region_intersect(&clip, &clip, region);
+ region = &clip;
- boxes = &box;
- n = 1;
+ if (!pixman_region_not_empty(region)) {
+ DBG(("%s: all clipped\n", __FUNCTION__));
+ return;
}
- dx = dy = 0;
- } else {
+ }
+
+ dx = dy = 0;
+ if (draw->type != DRAWABLE_PIXMAP) {
WindowPtr win = (WindowPtr)draw;
- DBG(("%s: draw=(%d, %d), delta=(%d, %d)\n",
+ DBG(("%s: draw=(%d, %d), delta=(%d, %d), clip.extents=(%d, %d), (%d, %d)\n",
__FUNCTION__, draw->x, draw->y,
- get_drawable_dx(draw), get_drawable_dy(draw)));
- if (region) {
- pixman_region_translate(region, draw->x, draw->y);
-
- pixman_region_init(&clip);
- pixman_region_intersect(&clip, &win->clipList, region);
- if (!pixman_region_not_empty(&clip)) {
- DBG(("%s: all clipped\n", __FUNCTION__));
- return;
- }
- region = &clip;
+ get_drawable_dx(draw), get_drawable_dy(draw),
+ win->clipList.extents.x1, win->clipList.extents.y1,
+ win->clipList.extents.x2, win->clipList.extents.y2));
- boxes = REGION_RECTS(region);
- n = REGION_NUM_RECTS(region);
- } else {
- boxes = REGION_RECTS(&win->clipList);
- n = REGION_NUM_RECTS(&win->clipList);
- region = &win->clipList;
+ if (region == NULL) {
+ pixman_region_init_rects(&clip, &box, 1);
+ region = &clip;
}
- if (n == 0)
+
+ pixman_region_intersect(region, &win->clipList, region);
+ if (!pixman_region_not_empty(region)) {
+ DBG(("%s: all clipped\n", __FUNCTION__));
return;
+ }
- if (sync)
- flush = sna_wait_for_scanline(sna, sna->front, NULL,
+ if (dst == sna->front && sync)
+ flush = sna_wait_for_scanline(sna, dst, NULL,
&region->extents);
- dst = sna->front;
- dst_bo = sna_pixmap_get_bo(sna->front);
get_drawable_deltas(draw, dst, &dx, &dy);
}
+ if (region) {
+ boxes = REGION_RECTS(region);
+ n = REGION_NUM_RECTS(region);
+ assert(n);
+ } else {
+ boxes = &box;
+ n = 1;
+ }
/* It's important that this copy gets submitted before the
* direct rendering client submits rendering for the next
* frame, but we don't actually need to submit right now. The
@@ -463,16 +448,21 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
* again.
*/
sna->render.copy_boxes(sna, GXcopy,
- src, src_priv->bo, -draw->x, -draw->y,
+ src, src_priv->bo, sx, sy,
dst, dst_bo, dx, dy,
boxes, n);
- damage(draw, dst, region);
-
DBG(("%s: flushing? %d\n", __FUNCTION__, flush));
if (flush) /* STAT! */
kgem_submit(&sna->kgem);
+ if (region) {
+ pixman_region_translate(region, dx, dy);
+ DamageRegionAppend(&dst->drawable, region);
+ DamageRegionProcessPending(&dst->drawable);
+ damage(draw, dst, region);
+ }
+
if (region == &clip)
pixman_region_fini(&clip);
}
@@ -1427,8 +1417,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
if (pipe > 0)
vbl.request.type |= DRM_VBLANK_SECONDARY;
- vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder;
+ vbl.request.sequence = current_msc - current_msc % divisor + remainder;
/*
* If calculated remainder is larger than requested remainder,
@@ -1437,7 +1426,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
* that will happen.
*/
if ((current_msc % divisor) >= remainder)
- vbl.request.sequence += divisor;
+ vbl.request.sequence += divisor;
vbl.request.signal = (unsigned long)info;
if (drmWaitVBlank(sna->kgem.fd, &vbl)) {