diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-25 16:34:15 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-06-25 16:34:15 +0100 |
commit | b460b9645451af84136c5daebbc00c7545de67f4 (patch) | |
tree | 993f7cea56ec4a4207fefc10b30cdf83f17e4297 | |
parent | 28fffbd1d07890c8b4d697369159f6a30f267675 (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.c | 157 |
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, ®ion->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)) { |