summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-24 12:19:09 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-24 12:48:48 +0100
commitc3b1a0d7046a83b6daec03e5a562116e3adf3c71 (patch)
treef5db3d823fd4827de18e790c6cb37e31e93d56c5
parent669378cd8db8af89d12f1b95a07fc1ead0b1569c (diff)
sna/dri: Copy to real front upon swap
The front-buffer of a DRI2 drawable, may not in fact be pointing to the scanout pixmap. So override the destination for swapbuffers to update the scanout. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri.c204
1 files changed, 65 insertions, 139 deletions
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 9d6369e1..3a8a753e 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -374,134 +374,81 @@ static void damage(DrawablePtr drawable, PixmapPtr pixmap, RegionPtr region)
}
static void
-sna_dri_copy_region(DrawablePtr draw,
- RegionPtr region,
- DRI2BufferPtr dst_buffer,
- DRI2BufferPtr src_buffer)
+sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
+ DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer,
+ bool sync)
{
- struct sna *sna = to_sna_from_drawable(draw);
struct sna_dri_private *src_priv = src_buffer->driverPrivate;
struct sna_dri_private *dst_priv = dst_buffer->driverPrivate;
PixmapPtr src = src_priv->pixmap;
PixmapPtr dst = dst_priv->pixmap;
+ struct kgem_bo *dst_bo = dst_priv->bo;
pixman_region16_t clip;
+ bool flush = false;
+ BoxRec box, *boxes;
int16_t dx, dy;
+ int n;
- DBG(("%s(region=(%d, %d), (%d, %d)))\n", __FUNCTION__,
- REGION_EXTENTS(NULL, region)->x1,
- REGION_EXTENTS(NULL, region)->y1,
- REGION_EXTENTS(NULL, region)->x2,
- REGION_EXTENTS(NULL, region)->y2));
-
- DBG(("%s: draw (%d, %d)\n", __FUNCTION__, draw->x, draw->y));
- DBG(("%s: dst -- attachment=%d, name=%d, handle=%d [screen %d]\n",
+ DBG(("%s: dst -- attachment=%d, name=%d, handle=%d [screen=%d]\n",
__FUNCTION__,
dst_buffer->attachment,
dst_buffer->name,
dst_priv->bo->handle,
- sna_pixmap(sna->front)->gpu_bo->handle));
+ sna_pixmap_get_bo(sna->front)->handle));
DBG(("%s: src -- attachment=%d, name=%d, handle=%d\n",
__FUNCTION__,
src_buffer->attachment,
src_buffer->name,
src_priv->bo->handle));
- if (draw->type == DRAWABLE_WINDOW) {
+ 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;
+
+ boxes = &box;
+ n = 1;
+ }
+ dx = dy = 0;
+ } else {
WindowPtr win = (WindowPtr)draw;
DBG(("%s: draw=(%d, %d), delta=(%d, %d)\n",
__FUNCTION__, draw->x, draw->y,
get_drawable_dx(draw), get_drawable_dy(draw)));
- 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_deltas(draw, dst, &dx, &dy);
-
- DBG(("%s clipped=(%d, %d), (%d, %d)x%d\n", __FUNCTION__,
- REGION_EXTENTS(NULL, region)->x1,
- REGION_EXTENTS(NULL, region)->y1,
- REGION_EXTENTS(NULL, region)->x2,
- REGION_EXTENTS(NULL, region)->y2,
- REGION_NUM_RECTS(region)));
+ 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;
- if (dst_buffer->attachment == DRI2BufferFrontLeft) {
- assert(dst == sna->front);
- assert(dst_priv->bo == sna_pixmap(sna->front)->gpu_bo);
+ boxes = REGION_RECTS(region);
+ n = REGION_NUM_RECTS(region);
+ } else {
+ boxes = REGION_RECTS(&win->clipList);
+ n = REGION_NUM_RECTS(&win->clipList);
+ region = &win->clipList;
}
- } else {
- assert(draw->x == 0);
- assert(draw->y == 0);
- dx = dy = 0;
- }
-
- assert(sna_pixmap(src)->cpu_damage == NULL);
- assert(sna_pixmap(dst)->cpu_damage == NULL);
-
- /* 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
- * client will wait for the DRI2CopyRegion reply or the swap
- * buffer event before rendering, and we'll hit the flush
- * callback chain before those messages are sent. We submit
- * our batch buffers from the flush callback chain so we know
- * that will happen before the client tries to render
- * again.
- */
- sna->render.copy_boxes(sna, GXcopy,
- src, src_priv->bo, -draw->x, -draw->y,
- dst, dst_priv->bo, dx, dy,
- REGION_RECTS(region),
- REGION_NUM_RECTS(region));
-
- damage(draw, dst, region);
- if (region == &clip)
- pixman_region_fini(&clip);
-}
-
-static void
-sna_dri_swap_blit(struct sna *sna, DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
-{
- struct sna_dri_private *src_priv = back->driverPrivate;
- struct sna_dri_private *dst_priv = front->driverPrivate;
- PixmapPtr src = src_priv->pixmap;
- PixmapPtr dst = dst_priv->pixmap;
- bool flush = false;
- BoxRec box, *boxes;
- int16_t dx, dy;
- int n;
-
- DBG(("%s: back -- attachment=%d, name=%d, handle=%d\n",
- __FUNCTION__,
- back->attachment,
- back->name,
- src_priv->bo->handle));
-
- if (draw->type == DRAWABLE_PIXMAP) {
- box.x1 = box.y1 = 0;
- box.x2 = draw->width;
- box.y2 = draw->height;
-
- boxes = &box;
- n = 1;
- dx = dy = 0;
- } else {
- WindowPtr win = (WindowPtr)draw;
-
- boxes = REGION_RECTS(&win->clipList);
- n = REGION_NUM_RECTS(&win->clipList);
if (n == 0)
return;
- flush = sna_wait_for_scanline(sna, sna->front,
- NULL, &win->clipList.extents);
+ if (sync)
+ flush = sna_wait_for_scanline(sna, sna->front, NULL,
+ &region->extents);
+ dst = sna->front;
+ dst_bo = sna_pixmap_get_bo(sna->front);
get_drawable_deltas(draw, dst, &dx, &dy);
}
@@ -517,14 +464,27 @@ sna_dri_swap_blit(struct sna *sna, DrawablePtr draw, DRI2BufferPtr front, DRI2Bu
*/
sna->render.copy_boxes(sna, GXcopy,
src, src_priv->bo, -draw->x, -draw->y,
- dst, dst_priv->bo, dx, dy,
+ dst, dst_bo, dx, dy,
boxes, n);
- damage(draw, dst, NULL);
+ damage(draw, dst, region);
DBG(("%s: flushing? %d\n", __FUNCTION__, flush));
if (flush) /* STAT! */
kgem_submit(&sna->kgem);
+
+ if (region == &clip)
+ pixman_region_fini(&clip);
+}
+
+static void
+sna_dri_copy_region(DrawablePtr draw,
+ RegionPtr region,
+ DRI2BufferPtr dst_buffer,
+ DRI2BufferPtr src_buffer)
+{
+ sna_dri_copy(to_sna_from_drawable(draw), draw,region,
+ dst_buffer, src_buffer, false);
}
#if DRI2INFOREC_VERSION >= 4
@@ -841,7 +801,7 @@ static void sna_dri_vblank_handle(int fd,
}
/* else fall through to exchange/blit */
case DRI2_SWAP:
- sna_dri_swap_blit(sna, draw, info->front, info->back);
+ sna_dri_copy(sna, draw, NULL, info->front, info->back, true);
case DRI2_SWAP_THROTTLE:
DRI2SwapComplete(info->client,
draw, frame,
@@ -1145,7 +1105,7 @@ immediate:
if (drmWaitVBlank(sna->kgem.fd, &vbl))
sna_dri_frame_event_info_free(info);
- sna_dri_swap_blit(sna, draw, front, back);
+ sna_dri_copy(sna, draw, NULL, front, back, true);
return TRUE;
}
@@ -1207,7 +1167,7 @@ immediate:
blit_fallback:
DBG(("%s -- blit\n", __FUNCTION__));
- sna_dri_swap_blit(sna, draw, front, back);
+ sna_dri_copy(sna, draw, NULL, front, back, true);
if (info)
sna_dri_frame_event_info_free(info);
DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
@@ -1233,41 +1193,7 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
DBG(("%s()\n", __FUNCTION__));
if (!can_flip(sna, draw, front, back)) {
- BoxRec box, *boxes;
- int16_t dx, dy;
- int n;
-
- if (draw->type == DRAWABLE_PIXMAP) {
- box.x1 = box.y1 = 0;
- box.x2 = draw->width;
- box.y2 = draw->height;
-
- boxes = &box;
- n = 1;
- dx = dy = 0;
- } else {
- WindowPtr win = (WindowPtr)draw;
-
- assert(front_priv->pixmap == sna->front);
- boxes = REGION_RECTS(&win->clipList);
- n = REGION_NUM_RECTS(&win->clipList);
- get_drawable_deltas(draw, front_priv->pixmap, &dx, &dy);
- }
-
- DBG(("%s: fallback blit: %dx%d\n",
- __FUNCTION__, draw->width, draw->height));
-
- if (n) {
- sna->render.copy_boxes(sna, GXcopy,
- back_priv->pixmap,
- back_priv->bo,
- -draw->x, -draw->y,
- front_priv->pixmap,
- front_priv->bo,
- dx, dy,
- boxes, n);
- }
-
+ sna_dri_copy(sna, draw, NULL, front, back, false);
DRI2SwapComplete(client, draw, 0, 0, 0,
DRI2_BLIT_COMPLETE, func, data);
return;