xf86-video-intel: 2 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/gen4_render.c src/sna/gen5_render.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/gen8_render.c src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna_composite.c src/sna/sna_display.c src/sna/sna_dri2.c src/sna/sna_io.c src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_render_inline.h src/sna/sna_tiling.c src/sna/sna_trapezoids.c src/sna/sna_trapezoids_imprecise.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Jun 30 13:19:28 PDT 2014


 src/sna/gen2_render.c              |   49 +++++++------
 src/sna/gen3_render.c              |   53 +++++++-------
 src/sna/gen4_render.c              |   51 +++++++-------
 src/sna/gen5_render.c              |   57 ++++++++--------
 src/sna/gen6_render.c              |   57 ++++++++--------
 src/sna/gen7_render.c              |   55 +++++++--------
 src/sna/gen8_render.c              |   59 ++++++++--------
 src/sna/sna_accel.c                |   72 ++++++++++----------
 src/sna/sna_blt.c                  |   51 +++++++++-----
 src/sna/sna_composite.c            |    6 -
 src/sna/sna_display.c              |   75 +++++++++++++--------
 src/sna/sna_dri2.c                 |   79 +++++++++++-----------
 src/sna/sna_io.c                   |  131 ++++++++++++++++++-------------------
 src/sna/sna_render.c               |   80 +++++++++++-----------
 src/sna/sna_render.h               |   22 +++---
 src/sna/sna_render_inline.h        |    2 
 src/sna/sna_tiling.c               |   48 ++++++-------
 src/sna/sna_trapezoids.c           |    4 -
 src/sna/sna_trapezoids_imprecise.c |    4 -
 19 files changed, 502 insertions(+), 453 deletions(-)

New commits:
commit e1c3e6ce79c73d12c814cfda76dbc0df184902ee
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 30 19:56:39 2014 +0100

    sna: Add DBG breadcrumbs before flushes in BLT
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index d6f986a..9b4d0bc 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -89,8 +89,10 @@ static const uint8_t fill_ROP[] = {
 static void nop_done(struct sna *sna, const struct sna_composite_op *op)
 {
 	assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
-	if (sna->kgem.nexec > 1 && __kgem_ring_empty(&sna->kgem))
+	if (sna->kgem.nexec > 1 && __kgem_ring_empty(&sna->kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(&sna->kgem);
+	}
 	(void)op;
 }
 
@@ -100,6 +102,7 @@ static void gen6_blt_copy_done(struct sna *sna, const struct sna_composite_op *o
 
 	assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem));
 	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(kgem);
 		return;
 	}
@@ -2865,8 +2868,10 @@ static void convert_done(struct sna *sna, const struct sna_composite_op *op)
 	struct kgem *kgem = &sna->kgem;
 
 	assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem));
-	if (kgem->nexec > 1 && __kgem_ring_empty(kgem))
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(kgem);
+	}
 
 	kgem_bo_destroy(kgem, op->src.bo);
 	sna_render_composite_redirect_done(sna, op);
@@ -3620,8 +3625,10 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
 		}
 	} while (nbox);
 
-	if (kgem->nexec > 1 && __kgem_ring_empty(kgem))
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(kgem);
+	}
 
 	return true;
 }
@@ -3944,6 +3951,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
 	}
 
 	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(kgem);
 	} else if (kgem->gen >= 060 && src_bo == dst_bo && kgem_check_batch(kgem, 3)) {
 		uint32_t *b = kgem->batch + kgem->nbatch;
@@ -4093,8 +4101,10 @@ bool sna_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
 		box++;
 	}
 
-	if (kgem->nexec > 1 && __kgem_ring_empty(kgem))
+	if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n", __FUNCTION__));
 		_kgem_submit(kgem);
+	}
 
 	sna->blt_state.fill_bo = 0;
 	return true;
commit 43176b9bfafe389c4b9ed676f4e50e3b06f858c4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 30 21:01:11 2014 +0100

    sna/dri2: Pass around the correct DrawableRec for sampling from the foriegn bo
    
    One day, we will move the width/height/bpp to the bo itself...
    
    Reported-by: Ilia Mirkin <imirkin at alum.mit.edu>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index fc0406e..4cc8dcd 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2734,7 +2734,7 @@ static bool
 gen2_render_fill_boxes_try_blt(struct sna *sna,
 			       CARD8 op, PictFormat format,
 			       const xRenderColor *color,
-			       PixmapPtr dst, struct kgem_bo *dst_bo,
+			       const DrawableRec *dst, struct kgem_bo *dst_bo,
 			       const BoxRec *box, int n)
 {
 	uint8_t alu;
@@ -2757,7 +2757,7 @@ gen2_render_fill_boxes_try_blt(struct sna *sna,
 		alu = GXcopy;
 
 	return sna_blt_fill_boxes(sna, alu,
-				  dst_bo, dst->drawable.bitsPerPixel,
+				  dst_bo, dst->bitsPerPixel,
 				  pixel, box, n);
 }
 
@@ -2766,7 +2766,7 @@ gen2_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -2793,7 +2793,7 @@ gen2_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, op, (int)format,
 	     color->red, color->green, color->blue, color->alpha));
 
-	if (too_large(dst->drawable.width, dst->drawable.height) ||
+	if (too_large(dst->width, dst->height) ||
 	    dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH ||
 	    !gen2_check_dst_format(format)) {
 		DBG(("%s: try blt, too large or incompatible destination\n",
@@ -2821,9 +2821,10 @@ gen2_render_fill_boxes(struct sna *sna,
 
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.op = op;
-	tmp.dst.pixmap = dst;
-	tmp.dst.width = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 	tmp.floats_per_vertex = 2;
@@ -3103,20 +3104,20 @@ gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
 
 static void
 gen2_render_copy_setup_source(struct sna_composite_channel *channel,
-			      PixmapPtr pixmap,
+			      const DrawableRec *draw,
 			      struct kgem_bo *bo)
 {
-	assert(pixmap->drawable.width && pixmap->drawable.height);
+	assert(draw->width && draw->height);
 
 	channel->filter = PictFilterNearest;
 	channel->repeat = RepeatNone;
-	channel->width  = pixmap->drawable.width;
-	channel->height = pixmap->drawable.height;
-	channel->scale[0] = 1.f/pixmap->drawable.width;
-	channel->scale[1] = 1.f/pixmap->drawable.height;
+	channel->width  = draw->width;
+	channel->height = draw->height;
+	channel->scale[0] = 1.f/draw->width;
+	channel->scale[1] = 1.f/draw->height;
 	channel->offset[0] = 0;
 	channel->offset[1] = 0;
-	channel->pict_format = sna_format_for_depth(pixmap->drawable.depth);
+	channel->pict_format = sna_format_for_depth(draw->depth);
 	channel->bo = bo;
 	channel->is_affine = 1;
 
@@ -3205,8 +3206,8 @@ static void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op
 
 static bool
 gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
@@ -3225,16 +3226,16 @@ gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
 
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (src_bo == dst_bo || /* XXX handle overlap using 3D ? */
-	    too_large(src->drawable.width, src->drawable.height) ||
+	    too_large(src->width, src->height) ||
 	    src_bo->pitch > MAX_3D_PITCH || dst_bo->pitch < 8) {
 fallback:
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -3254,10 +3255,10 @@ fallback:
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.op = alu;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
-	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width = dst->width;
+	tmp.dst.height = dst->height;
+	tmp.dst.format = sna_format_for_depth(dst->depth);
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
@@ -3428,7 +3429,7 @@ fallback:
 	tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth);
 	tmp->base.dst.bo = dst_bo;
 
-	gen2_render_copy_setup_source(&tmp->base.src, src, src_bo);
+	gen2_render_copy_setup_source(&tmp->base.src, &src->drawable, src_bo);
 	tmp->base.mask.bo = NULL;
 
 	tmp->base.floats_per_vertex = 4;
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 7616a91..8897f52 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -5540,7 +5540,7 @@ gen3_render_video(struct sna *sna,
 
 static void
 gen3_render_copy_setup_source(struct sna_composite_channel *channel,
-			      PixmapPtr pixmap,
+			      const DrawableRec *draw,
 			      struct kgem_bo *bo)
 {
 	int i;
@@ -5548,14 +5548,14 @@ gen3_render_copy_setup_source(struct sna_composite_channel *channel,
 	channel->u.gen3.type = SHADER_TEXTURE;
 	channel->filter = gen3_filter(PictFilterNearest);
 	channel->repeat = gen3_texture_repeat(RepeatNone);
-	channel->width  = pixmap->drawable.width;
-	channel->height = pixmap->drawable.height;
-	channel->scale[0] = 1.f/pixmap->drawable.width;
-	channel->scale[1] = 1.f/pixmap->drawable.height;
+	channel->width  = draw->width;
+	channel->height = draw->height;
+	channel->scale[0] = 1.f/draw->width;
+	channel->scale[1] = 1.f/draw->height;
 	channel->offset[0] = 0;
 	channel->offset[1] = 0;
 
-	channel->pict_format = sna_format_for_depth(pixmap->drawable.depth);
+	channel->pict_format = sna_format_for_depth(draw->depth);
 	if (!gen3_composite_channel_set_format(channel, channel->pict_format)) {
 		for (i = 0; i < ARRAY_SIZE(gen3_tex_formats); i++) {
 			if (gen3_tex_formats[i].xfmt == channel->pict_format) {
@@ -5574,38 +5574,38 @@ gen3_render_copy_setup_source(struct sna_composite_channel *channel,
 
 static bool
 gen3_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
 #if NO_COPY_BOXES
-	if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+	if (!sna_blt_compare_depth(src, dst))
 		return false;
 
 	return sna_blt_copy_boxes(sna, alu,
 				  src_bo, src_dx, src_dy,
 				  dst_bo, dst_dx, dst_dy,
-				  dst->drawable.bitsPerPixel,
+				  dst->bitsPerPixel,
 				  box, n);
 #endif
 
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
 
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear) ||
 	    src_bo == dst_bo || /* XXX handle overlap using 3D ? */
 	    src_bo->pitch > MAX_3D_PITCH ||
-	    too_large(src->drawable.width, src->drawable.height)) {
+	    too_large(src->width, src->height)) {
 fallback_blt:
 		if (!kgem_bo_can_blt(&sna->kgem, src_bo) ||
 		    !kgem_bo_can_blt(&sna->kgem, dst_bo))
@@ -5626,10 +5626,10 @@ fallback_blt:
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
-	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width = dst->width;
+	tmp.dst.height = dst->height;
+	tmp.dst.format = sna_format_for_depth(dst->depth);
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
@@ -5793,7 +5793,7 @@ fallback:
 	tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth);
 	tmp->base.dst.bo = dst_bo;
 
-	gen3_render_copy_setup_source(&tmp->base.src, src, src_bo);
+	gen3_render_copy_setup_source(&tmp->base.src, &src->drawable, src_bo);
 
 	tmp->base.floats_per_vertex = 4;
 	tmp->base.floats_per_rect = 12;
@@ -5818,7 +5818,7 @@ static bool
 gen3_render_fill_boxes_try_blt(struct sna *sna,
 			       CARD8 op, PictFormat format,
 			       const xRenderColor *color,
-			       PixmapPtr dst, struct kgem_bo *dst_bo,
+			       const DrawableRec *dst, struct kgem_bo *dst_bo,
 			       const BoxRec *box, int n)
 {
 	uint8_t alu;
@@ -5826,7 +5826,7 @@ gen3_render_fill_boxes_try_blt(struct sna *sna,
 
 	if (dst_bo->tiling == I915_TILING_Y) {
 		DBG(("%s: y-tiling, can't blit\n", __FUNCTION__));
-		assert(!too_large(dst->drawable.width, dst->drawable.height));
+		assert(!too_large(dst->width, dst->height));
 		return false;
 	}
 
@@ -5847,7 +5847,7 @@ gen3_render_fill_boxes_try_blt(struct sna *sna,
 		alu = GXcopy;
 
 	return sna_blt_fill_boxes(sna, alu,
-				  dst_bo, dst->drawable.bitsPerPixel,
+				  dst_bo, dst->bitsPerPixel,
 				  pixel, box, n);
 }
 
@@ -5865,7 +5865,7 @@ gen3_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -5887,7 +5887,7 @@ gen3_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, op, (int)format,
 	     color->red, color->green, color->blue, color->alpha));
 
-	if (too_large(dst->drawable.width, dst->drawable.height) ||
+	if (too_large(dst->width, dst->height) ||
 	    dst_bo->pitch > MAX_3D_PITCH ||
 	    !gen3_check_dst_format(format)) {
 		DBG(("%s: try blt, too large or incompatible destination\n",
@@ -5927,9 +5927,10 @@ gen3_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, op, (int)format, pixel));
 
 	tmp.op = op;
-	tmp.dst.pixmap = dst;
-	tmp.dst.width = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 	tmp.damage = NULL;
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 5340e7f..0bef20f 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2381,25 +2381,25 @@ gen4_render_copy_one(struct sna *sna,
 
 static bool
 gen4_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
 	DBG(("%s x %d\n", __FUNCTION__, n));
 
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo) {
 fallback_blt:
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+		if (!sna_blt_compare_depth(src, dst))
 			return false;
 
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -2413,21 +2413,21 @@ fallback_blt:
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
 
-	if (dst->drawable.depth == src->drawable.depth) {
-		tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
+	if (dst->depth == src->depth) {
+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
 		tmp.src.pict_format = tmp.dst.format;
 	} else {
-		tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
-		tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
+		tmp.dst.format = sna_format_for_depth(dst->depth);
+		tmp.src.pict_format = sna_format_for_depth(src->depth);
 	}
 	if (!gen4_check_format(tmp.src.pict_format))
 		goto fallback_blt;
 
 	tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.dst.bo = dst_bo;
 	tmp.damage = NULL;
@@ -2460,7 +2460,7 @@ fallback_blt:
 	tmp.src.filter = SAMPLER_FILTER_NEAREST;
 	tmp.src.repeat = SAMPLER_EXTEND_NONE;
 	tmp.src.card_format = gen4_get_card_format(tmp.src.pict_format);
-	if (too_large(src->drawable.width, src->drawable.height)) {
+	if (too_large(src->width, src->height)) {
 		BoxRec extents = box[0];
 		int i;
 
@@ -2484,11 +2484,11 @@ fallback_blt:
 			goto fallback_tiled_dst;
 	} else {
 		tmp.src.bo = kgem_bo_reference(src_bo);
-		tmp.src.width  = src->drawable.width;
-		tmp.src.height = src->drawable.height;
+		tmp.src.width  = src->width;
+		tmp.src.height = src->height;
 		tmp.src.offset[0] = tmp.src.offset[1] = 0;
-		tmp.src.scale[0] = 1.f/src->drawable.width;
-		tmp.src.scale[1] = 1.f/src->drawable.height;
+		tmp.src.scale[0] = 1.f/src->width;
+		tmp.src.scale[1] = 1.f/src->height;
 	}
 
 	tmp.is_affine = true;
@@ -2535,11 +2535,11 @@ fallback_tiled_dst:
 	if (tmp.redirect.real_bo)
 		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 fallback_tiled:
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
@@ -2675,7 +2675,7 @@ gen4_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -2703,14 +2703,14 @@ gen4_render_fill_boxes(struct sna *sna,
 
 		if (alu != GXinvalid &&
 		    sna_blt_fill_boxes(sna, alu,
-				       dst_bo, dst->drawable.bitsPerPixel,
+				       dst_bo, dst->bitsPerPixel,
 				       pixel, box, n))
 			return true;
 
 		if (!gen4_check_dst_format(format))
 			return false;
 
-		if (too_large(dst->drawable.width, dst->drawable.height))
+		if (too_large(dst->width, dst->height))
 			return sna_tiling_fill_boxes(sna, op, format, color,
 						     dst, dst_bo, box, n);
 	}
@@ -2732,9 +2732,10 @@ gen4_render_fill_boxes(struct sna *sna,
 
 	tmp.op = op;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index aa56663..965e60f 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2300,30 +2300,30 @@ gen5_copy_bind_surfaces(struct sna *sna,
 
 static bool
 gen5_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
 	DBG(("%s alu=%d, src=%ld:handle=%d, dst=%ld:handle=%d boxes=%d x [((%d, %d), (%d, %d))...], flags=%x\n",
 	     __FUNCTION__, alu,
-	     src->drawable.serialNumber, src_bo->handle,
-	     dst->drawable.serialNumber, dst_bo->handle,
+	     src->serialNumber, src_bo->handle,
+	     dst->serialNumber, dst_bo->handle,
 	     n, box->x1, box->y1, box->x2, box->y2,
 	     flags));
 
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo) {
 fallback_blt:
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+		if (!sna_blt_compare_depth(src, dst))
 			return false;
 
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -2334,12 +2334,12 @@ fallback_blt:
 
 	memset(&tmp, 0, sizeof(tmp));
 
-	if (dst->drawable.depth == src->drawable.depth) {
-		tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
+	if (dst->depth == src->depth) {
+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
 		tmp.src.pict_format = tmp.dst.format;
 	} else {
-		tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
-		tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
+		tmp.dst.format = sna_format_for_depth(dst->depth);
+		tmp.src.pict_format = sna_format_for_depth(src->depth);
 	}
 	if (!gen5_check_format(tmp.src.pict_format)) {
 		DBG(("%s: unsupported source format, %x, use BLT\n",
@@ -2352,9 +2352,9 @@ fallback_blt:
 
 	tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.dst.bo = dst_bo;
 	tmp.damage = NULL;
@@ -2387,7 +2387,7 @@ fallback_blt:
 	tmp.src.filter = SAMPLER_FILTER_NEAREST;
 	tmp.src.repeat = SAMPLER_EXTEND_NONE;
 	tmp.src.card_format = gen5_get_card_format(tmp.src.pict_format);
-	if (too_large(src->drawable.width, src->drawable.height)) {
+	if (too_large(src->width, src->height)) {
 		BoxRec extents = box[0];
 		int i;
 
@@ -2411,11 +2411,11 @@ fallback_blt:
 			goto fallback_tiled_dst;
 	} else {
 		tmp.src.bo = kgem_bo_reference(src_bo);
-		tmp.src.width  = src->drawable.width;
-		tmp.src.height = src->drawable.height;
+		tmp.src.width  = src->width;
+		tmp.src.height = src->height;
 		tmp.src.offset[0] = tmp.src.offset[1] = 0;
-		tmp.src.scale[0] = 1.f/src->drawable.width;
-		tmp.src.scale[1] = 1.f/src->drawable.height;
+		tmp.src.scale[0] = 1.f/src->width;
+		tmp.src.scale[1] = 1.f/src->height;
 	}
 
 	tmp.is_affine = true;
@@ -2483,11 +2483,11 @@ fallback_tiled_dst:
 	if (tmp.redirect.real_bo)
 		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 fallback_tiled:
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
@@ -2663,7 +2663,7 @@ gen5_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -2682,7 +2682,7 @@ gen5_render_fill_boxes(struct sna *sna,
 
 	if (op <= PictOpSrc &&
 	    (prefer_blt_fill(sna) ||
-	     too_large(dst->drawable.width, dst->drawable.height) ||
+	     too_large(dst->width, dst->height) ||
 	     !gen5_check_dst_format(format))) {
 		uint8_t alu = GXinvalid;
 
@@ -2699,14 +2699,14 @@ gen5_render_fill_boxes(struct sna *sna,
 
 		if (alu != GXinvalid &&
 		    sna_blt_fill_boxes(sna, alu,
-				       dst_bo, dst->drawable.bitsPerPixel,
+				       dst_bo, dst->bitsPerPixel,
 				       pixel, box, n))
 			return true;
 
 		if (!gen5_check_dst_format(format))
 			return false;
 
-		if (too_large(dst->drawable.width, dst->drawable.height))
+		if (too_large(dst->width, dst->height))
 			return sna_tiling_fill_boxes(sna, op, format, color,
 						     dst, dst_bo, box, n);
 	}
@@ -2728,9 +2728,10 @@ gen5_render_fill_boxes(struct sna *sna,
 
 	tmp.op = op;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index fe0426e..ece8cdb 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -720,6 +720,8 @@ gen6_emit_drawing_rectangle(struct sna *sna,
 				 64));
 	OUT_BATCH(0);
 
+	DBG(("%s: offset=(%d, %d), limit=(%d, %d)\n",
+	     __FUNCTION__, op->dst.x, op->dst.y, op->dst.width, op->dst.width));
 	OUT_BATCH(GEN6_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
 	OUT_BATCH(0);
 	OUT_BATCH(limit);
@@ -2657,8 +2659,8 @@ static inline bool prefer_blt_copy(struct sna *sna,
 
 static bool
 gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
@@ -2673,17 +2675,17 @@ gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
-	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	    sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear)) {
 fallback_blt:
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+		if (!sna_blt_compare_depth(src, dst))
 			return false;
 
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -2703,7 +2705,7 @@ fallback_blt:
 		    sna_blt_copy_boxes(sna, alu,
 				       src_bo, src_dx, src_dy,
 				       dst_bo, dst_dx, dst_dy,
-				       dst->drawable.bitsPerPixel,
+				       dst->bitsPerPixel,
 				       box, n))
 			return true;
 
@@ -2711,9 +2713,9 @@ fallback_blt:
 			goto fallback_blt;
 
 		assert(src_bo == dst_bo);
-		assert(src->drawable.depth == dst->drawable.depth);
-		assert(src->drawable.width == dst->drawable.width);
-		assert(src->drawable.height == dst->drawable.height);
+		assert(src->depth == dst->depth);
+		assert(src->width == dst->width);
+		assert(src->height == dst->height);
 		return sna_render_copy_boxes__overlap(sna, alu,
 						      src, src_bo,
 						      src_dx, src_dy,
@@ -2721,19 +2723,19 @@ fallback_blt:
 						      box, n, &extents);
 	}
 
-	if (dst->drawable.depth == src->drawable.depth) {
-		tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
+	if (dst->depth == src->depth) {
+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
 		tmp.src.pict_format = tmp.dst.format;
 	} else {
-		tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
-		tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
+		tmp.dst.format = sna_format_for_depth(dst->depth);
+		tmp.src.pict_format = sna_format_for_depth(src->depth);
 	}
 	if (!gen6_check_format(tmp.src.pict_format))
 		goto fallback_blt;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
@@ -2765,7 +2767,7 @@ fallback_blt:
 	}
 
 	tmp.src.card_format = gen6_get_card_format(tmp.src.pict_format);
-	if (too_large(src->drawable.width, src->drawable.height)) {
+	if (too_large(src->width, src->height)) {
 		int i;
 
 		extents = box[0];
@@ -2791,8 +2793,8 @@ fallback_blt:
 		}
 	} else {
 		tmp.src.bo = src_bo;
-		tmp.src.width  = src->drawable.width;
-		tmp.src.height = src->drawable.height;
+		tmp.src.width  = src->width;
+		tmp.src.height = src->height;
 		tmp.src.offset[0] = tmp.src.offset[1] = 0;
 	}
 
@@ -2872,11 +2874,11 @@ fallback_tiled_dst:
 	if (tmp.redirect.real_bo)
 		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 fallback_tiled:
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
@@ -3034,7 +3036,7 @@ gen6_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -3069,7 +3071,7 @@ gen6_render_fill_boxes(struct sna *sna,
 
 		if (alu != GXinvalid &&
 		    sna_blt_fill_boxes(sna, alu,
-				       dst_bo, dst->drawable.bitsPerPixel,
+				       dst_bo, dst->bitsPerPixel,
 				       pixel, box, n))
 			return true;
 
@@ -3092,16 +3094,17 @@ gen6_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, pixel, n,
 	     box[0].x1, box[0].y1, box[0].x2, box[0].y2));
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
 
 	sna_render_composite_redirect_init(&tmp);
-	if (too_large(dst->drawable.width, dst->drawable.height)) {
+	if (too_large(dst->width, dst->height)) {
 		BoxRec extents;
 
 		boxes_extents(box, n, &extents);
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index a588254..0a35d95 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2893,8 +2893,8 @@ prefer_blt_copy(struct sna *sna,
 
 static bool
 gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
@@ -2909,18 +2909,18 @@ gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
-	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	    sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear)) {
 fallback_blt:
 		DBG(("%s: fallback blt\n", __FUNCTION__));
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+		if (!sna_blt_compare_depth(src, dst))
 			return false;
 
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -2940,7 +2940,7 @@ fallback_blt:
 		    sna_blt_copy_boxes(sna, alu,
 				       src_bo, src_dx, src_dy,
 				       dst_bo, dst_dx, dst_dy,
-				       dst->drawable.bitsPerPixel,
+				       dst->bitsPerPixel,
 				       box, n))
 			return true;
 
@@ -2948,9 +2948,9 @@ fallback_blt:
 			goto fallback_blt;
 
 		assert(src_bo == dst_bo);
-		assert(src->drawable.depth == dst->drawable.depth);
-		assert(src->drawable.width == dst->drawable.width);
-		assert(src->drawable.height == dst->drawable.height);
+		assert(src->depth == dst->depth);
+		assert(src->width == dst->width);
+		assert(src->height == dst->height);
 		return sna_render_copy_boxes__overlap(sna, alu,
 						      src, src_bo,
 						      src_dx, src_dy,
@@ -2958,19 +2958,19 @@ fallback_blt:
 						      box, n, &extents);
 	}
 
-	if (dst->drawable.depth == src->drawable.depth) {
-		tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
+	if (dst->depth == src->depth) {
+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
 		tmp.src.pict_format = tmp.dst.format;
 	} else {
-		tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
-		tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
+		tmp.dst.format = sna_format_for_depth(dst->depth);
+		tmp.src.pict_format = sna_format_for_depth(src->depth);
 	}
 	if (!gen7_check_format(tmp.src.pict_format))
 		goto fallback_blt;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
@@ -3002,7 +3002,7 @@ fallback_blt:
 	}
 
 	tmp.src.card_format = gen7_get_card_format(tmp.src.pict_format);
-	if (too_large(src->drawable.width, src->drawable.height)) {
+	if (too_large(src->width, src->height)) {
 		int i;
 
 		extents = box[0];
@@ -3026,8 +3026,8 @@ fallback_blt:
 			goto fallback_tiled_dst;
 	} else {
 		tmp.src.bo = src_bo;
-		tmp.src.width  = src->drawable.width;
-		tmp.src.height = src->drawable.height;
+		tmp.src.width  = src->width;
+		tmp.src.height = src->height;
 		tmp.src.offset[0] = tmp.src.offset[1] = 0;
 	}
 
@@ -3103,11 +3103,11 @@ fallback_tiled_dst:
 		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 fallback_tiled:
 	DBG(("%s: fallback tiled\n", __FUNCTION__));
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
@@ -3270,7 +3270,7 @@ gen7_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -3305,7 +3305,7 @@ gen7_render_fill_boxes(struct sna *sna,
 
 		if (alu != GXinvalid &&
 		    sna_blt_fill_boxes(sna, alu,
-				       dst_bo, dst->drawable.bitsPerPixel,
+				       dst_bo, dst->bitsPerPixel,
 				       pixel, box, n))
 			return true;
 
@@ -3328,16 +3328,17 @@ gen7_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, pixel, n,
 	     box[0].x1, box[0].y1, box[0].x2, box[0].y2));
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
 
 	sna_render_composite_redirect_init(&tmp);
-	if (too_large(dst->drawable.width, dst->drawable.height)) {
+	if (too_large(dst->width, dst->height)) {
 		BoxRec extents;
 
 		boxes_extents(box, n, &extents);
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 365e8f6..392a107 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -2715,8 +2715,8 @@ prefer_blt_copy(struct sna *sna,
 
 static bool
 gen8_render_copy_boxes(struct sna *sna, uint8_t alu,
-		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
@@ -2731,20 +2731,20 @@ gen8_render_copy_boxes(struct sna *sna, uint8_t alu,
 		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
-	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	    sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
 	if (!(alu == GXcopy || alu == GXclear) ||
-	    unaligned(src_bo, src->drawable.bitsPerPixel) ||
-	    unaligned(dst_bo, dst->drawable.bitsPerPixel)) {
+	    unaligned(src_bo, src->bitsPerPixel) ||
+	    unaligned(dst_bo, dst->bitsPerPixel)) {
 fallback_blt:
 		DBG(("%s: fallback blt\n", __FUNCTION__));
-		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+		if (!sna_blt_compare_depth(src, dst))
 			return false;
 
 		return sna_blt_copy_boxes_fallback(sna, alu,
@@ -2764,7 +2764,7 @@ fallback_blt:
 		    sna_blt_copy_boxes(sna, alu,
 				       src_bo, src_dx, src_dy,
 				       dst_bo, dst_dx, dst_dy,
-				       dst->drawable.bitsPerPixel,
+				       dst->bitsPerPixel,
 				       box, n))
 			return true;
 
@@ -2772,9 +2772,9 @@ fallback_blt:
 			goto fallback_blt;
 
 		assert(src_bo == dst_bo);
-		assert(src->drawable.depth == dst->drawable.depth);
-		assert(src->drawable.width == dst->drawable.width);
-		assert(src->drawable.height == dst->drawable.height);
+		assert(src->depth == dst->depth);
+		assert(src->width == dst->width);
+		assert(src->height == dst->height);
 		return sna_render_copy_boxes__overlap(sna, alu,
 						      src, src_bo,
 						      src_dx, src_dy,
@@ -2782,19 +2782,19 @@ fallback_blt:
 						      box, n, &extents);
 	}
 
-	if (dst->drawable.depth == src->drawable.depth) {
-		tmp.dst.format = sna_render_format_for_depth(dst->drawable.depth);
+	if (dst->depth == src->depth) {
+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
 		tmp.src.pict_format = tmp.dst.format;
 	} else {
-		tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
-		tmp.src.pict_format = sna_format_for_depth(src->drawable.depth);
+		tmp.dst.format = sna_format_for_depth(dst->depth);
+		tmp.src.pict_format = sna_format_for_depth(src->depth);
 	}
 	if (!gen8_check_format(tmp.src.pict_format))
 		goto fallback_blt;
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
@@ -2826,7 +2826,7 @@ fallback_blt:
 	}
 
 	tmp.src.card_format = gen8_get_card_format(tmp.src.pict_format);
-	if (too_large(src->drawable.width, src->drawable.height)) {
+	if (too_large(src->width, src->height)) {
 		int i;
 
 		extents = box[0];
@@ -2850,8 +2850,8 @@ fallback_blt:
 			goto fallback_tiled_dst;
 	} else {
 		tmp.src.bo = src_bo;
-		tmp.src.width  = src->drawable.width;
-		tmp.src.height = src->drawable.height;
+		tmp.src.width  = src->width;
+		tmp.src.height = src->height;
 		tmp.src.offset[0] = tmp.src.offset[1] = 0;
 	}
 
@@ -2927,11 +2927,11 @@ fallback_tiled_dst:
 		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
 fallback_tiled:
 	DBG(("%s: fallback tiled\n", __FUNCTION__));
-	if (sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
+	if (sna_blt_compare_depth(src, dst) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
 			       dst_bo, dst_dx, dst_dy,
-			       dst->drawable.bitsPerPixel,
+			       dst->bitsPerPixel,
 			       box, n))
 		return true;
 
@@ -3094,7 +3094,7 @@ gen8_render_fill_boxes(struct sna *sna,
 		       CARD8 op,
 		       PictFormat format,
 		       const xRenderColor *color,
-		       PixmapPtr dst, struct kgem_bo *dst_bo,
+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
 		       const BoxRec *box, int n)
 {
 	struct sna_composite_op tmp;
@@ -3130,7 +3130,7 @@ gen8_render_fill_boxes(struct sna *sna,
 
 		if (alu != GXinvalid &&
 		    sna_blt_fill_boxes(sna, alu,
-				       dst_bo, dst->drawable.bitsPerPixel,
+				       dst_bo, dst->bitsPerPixel,
 				       pixel, box, n))
 			return true;
 
@@ -3153,16 +3153,17 @@ gen8_render_fill_boxes(struct sna *sna,
 	     __FUNCTION__, pixel, n,
 	     box[0].x1, box[0].y1, box[0].x2, box[0].y2));
 
-	tmp.dst.pixmap = dst;
-	tmp.dst.width  = dst->drawable.width;
-	tmp.dst.height = dst->drawable.height;
+	assert(dst->type == DRAWABLE_PIXMAP);
+	tmp.dst.pixmap = (PixmapPtr)dst;
+	tmp.dst.width  = dst->width;
+	tmp.dst.height = dst->height;
 	tmp.dst.format = format;
 	tmp.dst.bo = dst_bo;
 	tmp.dst.x = tmp.dst.y = 0;
 	tmp.damage = NULL;
 
 	sna_render_composite_redirect_init(&tmp);
-	if (too_large(dst->drawable.width, dst->drawable.height)) {
+	if (too_large(dst->width, dst->height)) {
 		BoxRec extents;
 
 		boxes_extents(box, n, &extents);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2f723eb..324107f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -706,8 +706,8 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 	box.y2 = pixmap->drawable.height;
 
 	if (!sna->render.copy_boxes(sna, GXcopy,
-				    pixmap, priv->gpu_bo, 0, 0,
-				    pixmap, bo, 0, 0,
+				    &pixmap->drawable, priv->gpu_bo, 0, 0,
+				    &pixmap->drawable, bo, 0, 0,
 				    &box, 1, 0)) {
 		DBG(("%s: copy failed\n", __FUNCTION__));
 		kgem_bo_destroy(&sna->kgem, bo);
@@ -1144,8 +1144,8 @@ sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
 
 		assert(!wedged(sna)); /* XXX */
 		if (!sna->render.copy_boxes(sna, GXcopy,
-					    pixmap, priv->gpu_bo, 0, 0,
-					    pixmap, bo, 0, 0,
+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
+					    &pixmap->drawable, bo, 0, 0,
 					    &box, 1, 0)) {
 			DBG(("%s: copy failed\n", __FUNCTION__));
 			kgem_bo_destroy(&sna->kgem, bo);
@@ -1777,8 +1777,8 @@ static inline bool cpu_bo_download(struct sna *sna,
 
 	DBG(("%s: using GPU write to CPU bo for download from GPU\n", __FUNCTION__));
 	return sna->render.copy_boxes(sna, GXcopy,
-				      priv->pixmap, priv->gpu_bo, 0, 0,
-				      priv->pixmap, priv->cpu_bo, 0, 0,
+				      &priv->pixmap->drawable, priv->gpu_bo, 0, 0,
+				      &priv->pixmap->drawable, priv->cpu_bo, 0, 0,
 				      box, n, COPY_LAST);
 }
 
@@ -1883,8 +1883,8 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 		}
 
 		if (!sna->render.copy_boxes(sna, GXcopy,
-					    pixmap, priv->gpu_bo, 0, 0,
-					    pixmap, bo, 0, 0,
+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
+					    &pixmap->drawable, bo, 0, 0,
 					    &box, 1, 0)) {
 			DBG(("%s: copy failed\n", __FUNCTION__));
 			kgem_bo_destroy(&sna->kgem, bo);
@@ -1932,8 +1932,8 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 			}
 
 			if (!sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, priv->gpu_bo, 0, 0,
-						    pixmap, bo, 0, 0,
+						    &pixmap->drawable, priv->gpu_bo, 0, 0,
+						    &pixmap->drawable, bo, 0, 0,
 						    &box, 1, 0)) {
 				DBG(("%s: copy failed\n", __FUNCTION__));
 				kgem_bo_destroy(&sna->kgem, bo);
@@ -3361,8 +3361,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 		if (use_cpu_bo_for_upload(sna, priv, 0)) {
 			DBG(("%s: using CPU bo for upload to GPU\n", __FUNCTION__));
 			ok = sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, priv->cpu_bo, 0, 0,
-						    pixmap, priv->gpu_bo, 0, 0,
+						    &pixmap->drawable, priv->cpu_bo, 0, 0,
+						    &pixmap->drawable, priv->gpu_bo, 0, 0,
 						    box, n, 0);
 		}
 		if (!ok) {
@@ -3401,8 +3401,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 		if (use_cpu_bo_for_upload(sna, priv, 0)) {
 			DBG(("%s: using CPU bo for upload to GPU\n", __FUNCTION__));
 			ok = sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, priv->cpu_bo, 0, 0,
-						    pixmap, priv->gpu_bo, 0, 0,
+						    &pixmap->drawable, priv->cpu_bo, 0, 0,
+						    &pixmap->drawable, priv->gpu_bo, 0, 0,
 						    box, 1, 0);
 		}
 		if (!ok) {
@@ -3430,8 +3430,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 		if (use_cpu_bo_for_upload(sna, priv, 0)) {
 			DBG(("%s: using CPU bo for upload to GPU, %d boxes\n", __FUNCTION__, n));
 			ok = sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, priv->cpu_bo, 0, 0,
-						    pixmap, priv->gpu_bo, 0, 0,
+						    &pixmap->drawable, priv->cpu_bo, 0, 0,
+						    &pixmap->drawable, priv->gpu_bo, 0, 0,
 						    box, n, 0);
 		}
 		if (!ok) {
@@ -4236,8 +4236,8 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 		if (use_cpu_bo_for_upload(sna, priv, flags)) {
 			DBG(("%s: using CPU bo for upload to GPU\n", __FUNCTION__));
 			ok = sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, priv->cpu_bo, 0, 0,
-						    pixmap, priv->gpu_bo, 0, 0,
+						    &pixmap->drawable, priv->cpu_bo, 0, 0,
+						    &pixmap->drawable, priv->gpu_bo, 0, 0,
 						    box, n, 0);
 		}
 		if (!ok) {
@@ -4903,8 +4903,8 @@ try_upload__blt(PixmapPtr pixmap, RegionRec *region,
 
 	if (sigtrap_get() == 0) {
 		ok = sna->render.copy_boxes(sna, GXcopy,
-					    pixmap, src_bo, -x, -y,
-					    pixmap, priv->gpu_bo, 0, 0,
+					    &pixmap->drawable, src_bo, -x, -y,
+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
 					    region_rects(region),
 					    region_num_rects(region),
 					    COPY_LAST);
@@ -5756,8 +5756,8 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 		assert(priv->cpu_damage == NULL);
 
 		if (!sna->render.copy_boxes(sna, alu,
-					    pixmap, priv->gpu_bo, sx, sy,
-					    pixmap, priv->gpu_bo, tx, ty,
+					    &pixmap->drawable, priv->gpu_bo, sx, sy,
+					    &pixmap->drawable, priv->gpu_bo, tx, ty,
 					    box, n, 0)) {
 			DBG(("%s: fallback - accelerated copy boxes failed\n",
 			     __FUNCTION__));
@@ -6410,8 +6410,8 @@ discard_cow:
 				}
 			}
 			if (!sna->render.copy_boxes(sna, alu,
-						    src_pixmap, src_priv->gpu_bo, src_dx, src_dy,
-						    dst_pixmap, bo, 0, 0,
+						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
+						    &dst_pixmap->drawable, bo, 0, 0,
 						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
@@ -6447,8 +6447,8 @@ discard_cow:
 				kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
 
 			if (!sna->render.copy_boxes(sna, alu,
-						    src_pixmap, src_priv->gpu_bo, src_dx, src_dy,
-						    dst_pixmap, bo, 0, 0,
+						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
+						    &dst_pixmap->drawable, bo, 0, 0,
 						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
@@ -6490,8 +6490,8 @@ discard_cow:
 			}
 
 			if (!sna->render.copy_boxes(sna, alu,
-						    src_pixmap, src_priv->cpu_bo, src_dx, src_dy,
-						    dst_pixmap, bo, 0, 0,
+						    &src_pixmap->drawable, src_priv->cpu_bo, src_dx, src_dy,
+						    &dst_pixmap->drawable, bo, 0, 0,
 						    box, n, src_priv->shm ? COPY_LAST : 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
@@ -6542,8 +6542,8 @@ discard_cow:
 				kgem_bo_mark_unreusable(src_bo);
 
 				ok = sna->render.copy_boxes(sna, alu,
-							    src_pixmap, src_bo, src_dx, src_dy,
-							    dst_pixmap, bo, 0, 0,
+							    &src_pixmap->drawable, src_bo, src_dx, src_dy,
+							    &dst_pixmap->drawable, bo, 0, 0,
 							    box, n, COPY_LAST);
 
 				kgem_bo_sync__cpu(&sna->kgem, src_bo);
@@ -6620,8 +6620,8 @@ discard_cow:
 			}
 
 			if (!sna->render.copy_boxes(sna, alu,
-						    tmp, src_bo, dx, dy,
-						    dst_pixmap, bo, 0, 0,
+						    &tmp->drawable, src_bo, dx, dy,
+						    &dst_pixmap->drawable, bo, 0, 0,
 						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
@@ -16738,8 +16738,8 @@ sna_get_image__blt(PixmapPtr pixmap,
 		kgem_bo_mark_unreusable(dst_bo);
 
 		ok = sna->render.copy_boxes(sna, GXcopy,
-					    pixmap, priv->gpu_bo, 0, 0,
-					    pixmap, dst_bo,
+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
+					    &pixmap->drawable, dst_bo,
 					    -region->extents.x1,
 					    -region->extents.y1,
 					    &region->extents, 1,
@@ -17304,8 +17304,8 @@ fallback:
 				goto fallback;
 
 			if (!sna->render.copy_boxes(sna, GXcopy,
-						    src, __sna_pixmap_get_bo(src), dirty->x, dirty->y,
-						    dst, __sna_pixmap_get_bo(dst),0, 0,
+						    &src->drawable, __sna_pixmap_get_bo(src), dirty->x, dirty->y,
+						    &dst->drawable, __sna_pixmap_get_bo(dst),0, 0,
 						    box, n, COPY_LAST))
 				goto fallback;
 
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 99cb7d2..d6f986a 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -4118,8 +4118,8 @@ static void box_extents(const BoxRec *box, int n, BoxRec *extents)
 }
 
 bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
-				 PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-				 PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+				 const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+				 const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 				 const BoxRec *box, int nbox)
 {
 	struct kgem_bo *free_bo = NULL;
@@ -4127,9 +4127,9 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 
 	DBG(("%s: alu=%d, n=%d\n", __FUNCTION__, alu, nbox));
 
-	if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) {
+	if (!sna_blt_compare_depth(src, dst)) {
 		DBG(("%s: mismatching depths %d -> %d\n",
-		     __FUNCTION__, src->drawable.depth, dst->drawable.depth));
+		     __FUNCTION__, src->depth, dst->depth));
 		return false;
 	}
 
@@ -4142,8 +4142,11 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 
 			DBG(("%s: src is Y-tiled\n", __FUNCTION__));
 
-			assert(src_bo == sna_pixmap(src)->gpu_bo);
-			bo = sna_pixmap_change_tiling(src, I915_TILING_X);
+			if (src->type != DRAWABLE_PIXMAP)
+				return false;
+
+			assert(sna_pixmap((PixmapPtr)src)->gpu_bo == src_bo);
+			bo = sna_pixmap_change_tiling((PixmapPtr)src, I915_TILING_X);
 			if (bo == NULL) {
 				BoxRec extents;
 
@@ -4154,7 +4157,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 				free_bo = kgem_create_2d(&sna->kgem,
 							 extents.x2 - extents.x1,
 							 extents.y2 - extents.y1,
-							 src->drawable.bitsPerPixel,
+							 src->bitsPerPixel,
 							 I915_TILING_X, 0);
 				if (free_bo == NULL) {
 					DBG(("%s: fallback -- temp allocation failed\n",
@@ -4165,7 +4168,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 				if (!sna_blt_copy_boxes(sna, GXcopy,
 							src_bo, src_dx, src_dy,
 							free_bo, -extents.x1, -extents.y1,
-							src->drawable.bitsPerPixel,
+							src->bitsPerPixel,
 							box, nbox)) {
 					DBG(("%s: fallback -- temp copy failed\n",
 					     __FUNCTION__));
@@ -4183,8 +4186,10 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 		if (src_bo->tiling == I915_TILING_Y &&
 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
 			DBG(("%s: src is y-tiled\n", __FUNCTION__));
-			assert(src_bo == sna_pixmap(src)->gpu_bo);
-			src_bo = sna_pixmap_change_tiling(src, I915_TILING_X);
+			if (src->type != DRAWABLE_PIXMAP)
+				return false;
+			assert(sna_pixmap((PixmapPtr)src)->gpu_bo == src_bo);
+			src_bo = sna_pixmap_change_tiling((PixmapPtr)src, I915_TILING_X);
 			if (src_bo == NULL) {
 				DBG(("%s: fallback -- src y-tiling conversion failed\n",
 				     __FUNCTION__));
@@ -4195,8 +4200,10 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 		if (dst_bo->tiling == I915_TILING_Y &&
 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, dst_bo)) {
 			DBG(("%s: dst is y-tiled\n", __FUNCTION__));
-			assert(dst_bo == sna_pixmap(dst)->gpu_bo);
-			dst_bo = sna_pixmap_change_tiling(dst, I915_TILING_X);
+			if (dst->type != DRAWABLE_PIXMAP)
+				return false;
+			assert(sna_pixmap((PixmapPtr)dst)->gpu_bo == dst_bo);
+			dst_bo = sna_pixmap_change_tiling((PixmapPtr)dst, I915_TILING_X);
 			if (dst_bo == NULL) {
 				DBG(("%s: fallback -- dst y-tiling conversion failed\n",
 				     __FUNCTION__));
@@ -4208,7 +4215,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
 	ret =  sna_blt_copy_boxes(sna, alu,
 				  src_bo, src_dx, src_dy,
 				  dst_bo, dst_dx, dst_dy,
-				  dst->drawable.bitsPerPixel,
+				  dst->bitsPerPixel,
 				  box, nbox);
 
 	if (free_bo)
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index f20d3c3..bc50109 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -1026,7 +1026,7 @@ sna_composite_rectangles(CARD8		 op,
 	if (op <= PictOpSrc) {
 		b = pixman_region_rectangles(&region, &num_boxes);
 		if (!sna->render.fill_boxes(sna, op, dst->format, color,
-					    pixmap, bo, b, num_boxes)) {
+					    &pixmap->drawable, bo, b, num_boxes)) {
 			DBG(("%s: fallback - acceleration failed\n", __FUNCTION__));
 			goto fallback;
 		}
@@ -1038,7 +1038,7 @@ sna_composite_rectangles(CARD8		 op,
 			boxes[i].y2 += dst_y;
 		}
 		if (!sna->render.fill_boxes(sna, op, dst->format, color,
-					    pixmap, bo, boxes, num_boxes)) {
+					    &pixmap->drawable, bo, boxes, num_boxes)) {
 			DBG(("%s: fallback - acceleration failed\n", __FUNCTION__));
 			goto fallback;
 		}
@@ -1054,7 +1054,7 @@ sna_composite_rectangles(CARD8		 op,
 						pixman_region_translate(&tmp, dst_x, dst_y);
 
 					n = !sna->render.fill_boxes(sna, op, dst->format, color,
-								    pixmap, bo, b, n);
+								    &pixmap->drawable, bo, b, n);
 				}
 
 				pixman_region_fini(&tmp);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 166203a..38ebc11 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1088,6 +1088,13 @@ static bool wait_for_shadow(struct sna *sna,
 							 shadow_link);
 				if (overlap(&sna->mode.shadow_region.extents,
 					    &crtc->base->bounds)) {
+					DrawableRec draw;
+
+					draw.width = crtc->base->mode.HDisplay;
+					draw.height = crtc->base->mode.VDisplay;
+					draw.depth = sna->front->drawable.depth;
+					draw.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
 					DBG(("%s: copying replaced CRTC: (%d, %d), (%d, %d), handle=%d\n",
 					     __FUNCTION__,
 					     crtc->base->bounds.x1,
@@ -1097,8 +1104,8 @@ static bool wait_for_shadow(struct sna *sna,
 					     crtc->shadow_bo->handle));
 
 					ret &= sna->render.copy_boxes(sna, GXcopy,
-								      pixmap, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
-								      pixmap, priv->gpu_bo, 0, 0,
+								      &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+								      &pixmap->drawable, priv->gpu_bo, 0, 0,
 								      &crtc->base->bounds, 1,
 								      0);
 				}
@@ -1186,6 +1193,12 @@ static bool wait_for_shadow(struct sna *sna,
 		if (overlap(&crtc->base->bounds,
 			    &sna->mode.shadow_region.extents)) {
 			RegionRec region;
+			DrawableRec draw;
+
+			draw.width = crtc->base->mode.HDisplay;
+			draw.height = crtc->base->mode.VDisplay;
+			draw.depth = sna->front->drawable.depth;
+			draw.bitsPerPixel = sna->front->drawable.bitsPerPixel;
 
 			DBG(("%s: copying replaced CRTC: (%d, %d), (%d, %d), handle=%d\n",
 			     __FUNCTION__,
@@ -1196,8 +1209,8 @@ static bool wait_for_shadow(struct sna *sna,
 			     crtc->shadow_bo->handle));
 
 			ret = sna->render.copy_boxes(sna, GXcopy,
-						     pixmap, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
-						     pixmap, bo, 0, 0,
+						     &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+						     &pixmap->drawable, bo, 0, 0,
 						     &crtc->base->bounds, 1,
 						     0);
 
@@ -1220,8 +1233,8 @@ static bool wait_for_shadow(struct sna *sna,
 		     sna->mode.shadow_region.extents.x2,
 		     sna->mode.shadow_region.extents.y2));
 		ret = sna->render.copy_boxes(sna, GXcopy,
-					     pixmap, priv->gpu_bo, 0, 0,
-					     pixmap, bo, 0, 0,
+					     &pixmap->drawable, priv->gpu_bo, 0, 0,
+					     &pixmap->drawable, bo, 0, 0,
 					     region_rects(&sna->mode.shadow_region),
 					     region_num_rects(&sna->mode.shadow_region),
 					     0);
@@ -1376,9 +1389,16 @@ static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
 
 	if (crtc->shadow_bo) {
 		if (!crtc->transform) {
+			DrawableRec tmp;
+
+			tmp.width = crtc->base->mode.HDisplay;
+			tmp.height = crtc->base->mode.VDisplay;
+			tmp.depth = sna->front->drawable.depth;
+			tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+
 			sna->render.copy_boxes(sna, GXcopy,
-					       sna->front, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
-					       sna->front, __sna_pixmap_get_bo(sna->front), 0, 0,
+					       &tmp, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+					       &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
 					       &crtc->base->bounds, 1, 0);
 			list_del(&crtc->shadow_link);
 		}
@@ -1586,8 +1606,8 @@ void sna_copy_fbcon(struct sna *sna)
 		dy = (sna->front->drawable.height - box.y2) / 2;
 
 	ok = sna->render.copy_boxes(sna, GXcopy,
-				    &scratch, bo, sx, sy,
-				    sna->front, priv->gpu_bo, dx, dy,
+				    &scratch.drawable, bo, sx, sy,
+				    &sna->front->drawable, priv->gpu_bo, dx, dy,
 				    &box, 1, 0);
 	if (!DAMAGE_IS_ALL(priv->gpu_damage))
 		sna_damage_add_box(&priv->gpu_damage, &box);
@@ -3732,8 +3752,8 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
 						box.x2 = new->drawable.width - dx;
 
 					(void)sna->render.copy_boxes(sna, GXcopy,
-								     old, old_priv->gpu_bo, 0, 0,
-								     new, new_priv->gpu_bo, dx, dy,
+								     &old->drawable, old_priv->gpu_bo, 0, 0,
+								     &new->drawable, new_priv->gpu_bo, dx, dy,
 								     &box, 1, 0);
 					dx += old->drawable.width;
 				}
@@ -3767,8 +3787,8 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
 							   GXclear);
 			}
 			(void)sna->render.copy_boxes(sna, GXcopy,
-						     old, old_priv->gpu_bo, sx, sy,
-						     new, new_priv->gpu_bo, dx, dy,
+						     &old->drawable, old_priv->gpu_bo, sx, sy,
+						     &new->drawable, new_priv->gpu_bo, dx, dy,
 						     &box, 1, 0);
 		}
 	}
@@ -6118,17 +6138,17 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region)
 	if (crtc->filter == NULL &&
 	    sna_transform_is_integer_translation(&crtc->crtc_to_framebuffer,
 						 &tx, &ty)) {
-		PixmapRec tmp;
+		DrawableRec tmp;
 
 		DBG(("%s: copy damage boxes\n", __FUNCTION__));
 
-		tmp.drawable.width = crtc->mode.HDisplay;
-		tmp.drawable.height = crtc->mode.VDisplay;
-		tmp.drawable.depth = sna->front->drawable.depth;
-		tmp.drawable.bitsPerPixel = sna->front->drawable.bitsPerPixel;
+		tmp.width = crtc->mode.HDisplay;
+		tmp.height = crtc->mode.VDisplay;
+		tmp.depth = sna->front->drawable.depth;
+		tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
 
 		if (sna->render.copy_boxes(sna, GXcopy,
-					   sna->front, priv->gpu_bo, 0, 0,
+					   &sna->front->drawable, priv->gpu_bo, 0, 0,
 					   &tmp, sna_crtc->bo, -tx, -ty,
 					   region_rects(region), region_num_rects(region), 0))
 			return;
@@ -6341,18 +6361,21 @@ void sna_mode_redisplay(struct sna *sna)
 
 				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
 					BoxRec box;
+					DrawableRec tmp;
 
 					DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
 					     __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
 disable1:
 					box.x1 = 0;
 					box.y1 = 0;
-					box.x2 = crtc->mode.HDisplay;
-					box.y2 = crtc->mode.VDisplay;
+					tmp.width = box.x2 = crtc->mode.HDisplay;
+					tmp.height = box.y2 = crtc->mode.VDisplay;
+					tmp.depth = sna->front->drawable.depth;
+					tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
 
 					if (!sna->render.copy_boxes(sna, GXcopy,
-								    sna->front, bo, 0, 0,
-								    sna->front, sna_crtc->bo, 0, 0,
+								    &sna->front->drawable, bo, 0, 0,
+								    &tmp, sna_crtc->bo, 0, 0,
 								    &box, 1, COPY_LAST)) {
 						xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
 							   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
@@ -6404,8 +6427,8 @@ fixup_shadow:
 				box.x2 = sna->scrn->virtualX;
 				box.y2 = sna->scrn->virtualY;
 				if (sna->render.copy_boxes(sna, GXcopy,
-							   sna->front, __sna_pixmap_get_bo(sna->front), 0, 0,
-							   sna->front, old, 0, 0,
+							   &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
+							   &sna->front->drawable, old, 0, 0,
 							   &box, 1, COPY_LAST)) {
 					kgem_submit(&sna->kgem);
 					RegionEmpty(region);
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 000ebcf..d0b5da5 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -859,6 +859,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		      bool sync)
 {
 	PixmapPtr pixmap = get_drawable_pixmap(draw);
+	DrawableRec scratch, *src_draw = &pixmap->drawable, *dst_draw = &pixmap->drawable;
 	struct sna_dri2_private *src_priv = get_private(src);
 	struct sna_dri2_private *dst_priv = get_private(dst);
 	pixman_region16_t clip;
@@ -956,29 +957,28 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		     __FUNCTION__, src_priv->bo->handle, src_bo->handle));
 		assert(src_bo->refcnt);
 	} else {
-		bool changed = false;
+		RegionRec source;
+
+		scratch.x = scratch.y = 0;
+		scratch.width = src_priv->size & 0xffff;
+		scratch.height = src_priv->size >> 16;
+		src_draw = &scratch;
 
 		DBG(("%s: source size %dx%d, region size %dx%d\n",
 		     __FUNCTION__,
-		     src_priv->size & 0xffff, src_priv->size >> 16,
-		     (region ?: &clip)->extents.x2 - (region ?: &clip)->extents.x1,
-		     (region ?: &clip)->extents.y2 - (region ?: &clip)->extents.y1));
-
-		assert(sx + clip.extents.x1 >= 0);
-		assert(sy + clip.extents.y1 >= 0);
+		     scratch.width, scratch.height,
+		     clip.extents.x2 - clip.extents.x1,
+		     clip.extents.y2 - clip.extents.y1));
 
-		if (sx + clip.extents.x2 > (src_priv->size & 0xffff)) {
-			clip.extents.x2 = (src_priv->size & 0xffff) - sx;
-			changed = !!region;
-		}
+		source.extents.x1 = -sx;
+		source.extents.y1 = -sy;
+		source.extents.x2 = source.extents.x1 + scratch.width;
+		source.extents.y2 = source.extents.y1 + scratch.height;
+		source.data = NULL;
 
-		if (sy + clip.extents.y2 > (src_priv->size >> 16)) {
-			clip.extents.y2 = (src_priv->size >> 16) - sy;
-			changed = !!region;
-		}
+		assert(region == NULL || region == &clip);
+		pixman_region_intersect(&clip, &clip, &source);
 
-		if (changed)
-			pixman_region_intersect(region, &clip, region);
 	}
 
 	dst_bo = dst_priv->bo;
@@ -991,6 +991,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		if (clip.data)
 			flags |= MOVE_READ;
 
+		assert(region == NULL || region == &clip);
 		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, flags);
 		if (priv) {
 			damage(pixmap, priv, region);
@@ -1000,29 +1001,27 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		     __FUNCTION__, dst_priv->bo->handle, dst_bo->handle));
 		assert(dst_bo->refcnt);
 	} else {
-		bool changed = false;
+		RegionRec target;
+
+		scratch.x = scratch.y = 0;
+		scratch.width = dst_priv->size & 0xffff;
+		scratch.height = dst_priv->size >> 16;
+		dst_draw = &scratch;
 
 		DBG(("%s: target size %dx%d, region size %dx%d\n",
 		     __FUNCTION__,
-		     dst_priv->size & 0xffff, dst_priv->size >> 16,
-		     (region ?: &clip)->extents.x2 - (region ?: &clip)->extents.x1,
-		     (region ?: &clip)->extents.y2 - (region ?: &clip)->extents.y1));
+		     scratch.width, scratch.height,
+		     clip.extents.x2 - clip.extents.x1,
+		     clip.extents.y2 - clip.extents.y1));
 
-		assert(dx + clip.extents.x1 >= 0);
-		assert(dy + clip.extents.y1 >= 0);
+		target.extents.x1 = -dx;
+		target.extents.y1 = -dy;
+		target.extents.x2 = target.extents.x1 + scratch.width;
+		target.extents.y2 = target.extents.y1 + scratch.height;
+		target.data = NULL;
 
-		if (dx + clip.extents.x2 > (dst_priv->size & 0xffff)) {
-			clip.extents.x2 = (dst_priv->size & 0xffff) - dx;
-			changed = !!region;
-		}
-
-		if (dy + clip.extents.y2 > (dst_priv->size >> 16)) {
-			clip.extents.y2 = (dst_priv->size >> 16) - dy;
-			changed = !!region;
-		}
-
-		if (changed)
-			pixman_region_intersect(region, &clip, region);
+		assert(region == NULL || region == &clip);
+		pixman_region_intersect(&clip, &clip, &target);
 
 		sync = false;
 	}
@@ -1060,12 +1059,18 @@ fallback:
 	} else {
 		unsigned flags;
 
+		DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
+		     __FUNCTION__,
+		     boxes[0].x1, boxes[0].y1,
+		     boxes[0].x2, boxes[0].y2,
+		     n, sx, sy, dx, dy));
+
 		flags = COPY_LAST;
 		if (sync)
 			flags |= COPY_SYNC;
 		if (!sna->render.copy_boxes(sna, GXcopy,
-					    pixmap, src_bo, sx, sy,
-					    pixmap, dst_bo, dx, dy,
+					    src_draw, src_bo, sx, sy,
+					    dst_draw, dst_bo, dx, dy,
 					    boxes, n, flags))
 			goto fallback;
 
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index eaa2052..51d3af0 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -290,18 +290,17 @@ fallback:
 	/* Try to avoid switching rings... */
 	if (!can_blt || kgem->ring == KGEM_RENDER ||
 	    upload_too_large(sna, extents.x2 - extents.x1, extents.y2 - extents.y1)) {
-		PixmapRec tmp;
+		DrawableRec tmp;
 
-		tmp.drawable.width  = extents.x2 - extents.x1;
-		tmp.drawable.height = extents.y2 - extents.y1;
-		tmp.drawable.depth  = dst->drawable.depth;
-		tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
-		tmp.devPrivate.ptr = NULL;
+		tmp.width  = extents.x2 - extents.x1;
+		tmp.height = extents.y2 - extents.y1;
+		tmp.depth  = dst->drawable.depth;
+		tmp.bitsPerPixel = dst->drawable.bitsPerPixel;
 
-		assert(tmp.drawable.width);
-		assert(tmp.drawable.height);
+		assert(tmp.width);
+		assert(tmp.height);
 
-		if (must_tile(sna, tmp.drawable.width, tmp.drawable.height)) {
+		if (must_tile(sna, tmp.width, tmp.height)) {
 			BoxRec tile, stack[64], *clipped, *c;
 			int step;
 
@@ -333,8 +332,8 @@ fallback:
 						x2 = extents.x2;
 					tile.x2 = x2;
 
-					tmp.drawable.width  = tile.x2 - tile.x1;
-					tmp.drawable.height = tile.y2 - tile.y1;
+					tmp.width  = tile.x2 - tile.x1;
+					tmp.height = tile.y2 - tile.y1;
 
 					c = clipped;
 					for (n = 0; n < nbox; n++) {
@@ -354,9 +353,9 @@ fallback:
 						continue;
 
 					dst_bo = kgem_create_buffer_2d(kgem,
-								       tmp.drawable.width,
-								       tmp.drawable.height,
-								       tmp.drawable.bitsPerPixel,
+								       tmp.width,
+								       tmp.height,
+								       tmp.bitsPerPixel,
 								       KGEM_BUFFER_LAST,
 								       &ptr);
 					if (!dst_bo) {
@@ -366,7 +365,7 @@ fallback:
 					}
 
 					if (!sna->render.copy_boxes(sna, GXcopy,
-								    dst, src_bo, 0, 0,
+								    &dst->drawable, src_bo, 0, 0,
 								    &tmp, dst_bo, -tile.x1, -tile.y1,
 								    clipped, c-clipped, COPY_LAST)) {
 						kgem_bo_destroy(&sna->kgem, dst_bo);
@@ -380,7 +379,7 @@ fallback:
 
 					if (sigtrap_get() == 0) {
 						while (c-- != clipped) {
-							memcpy_blt(ptr, dst->devPrivate.ptr, tmp.drawable.bitsPerPixel,
+							memcpy_blt(ptr, dst->devPrivate.ptr, tmp.bitsPerPixel,
 								   dst_bo->pitch, dst->devKind,
 								   c->x1 - tile.x1,
 								   c->y1 - tile.y1,
@@ -399,16 +398,16 @@ fallback:
 				free(clipped);
 		} else {
 			dst_bo = kgem_create_buffer_2d(kgem,
-						       tmp.drawable.width,
-						       tmp.drawable.height,
-						       tmp.drawable.bitsPerPixel,
+						       tmp.width,
+						       tmp.height,
+						       tmp.bitsPerPixel,
 						       KGEM_BUFFER_LAST,
 						       &ptr);
 			if (!dst_bo)
 				goto fallback;
 
 			if (!sna->render.copy_boxes(sna, GXcopy,
-						    dst, src_bo, 0, 0,
+						    &dst->drawable, src_bo, 0, 0,
 						    &tmp, dst_bo, -extents.x1, -extents.y1,
 						    box, nbox, COPY_LAST)) {
 				kgem_bo_destroy(&sna->kgem, dst_bo);
@@ -420,7 +419,7 @@ fallback:
 
 			if (sigtrap_get() == 0) {
 				for (n = 0; n < nbox; n++) {
-					memcpy_blt(ptr, dst->devPrivate.ptr, tmp.drawable.bitsPerPixel,
+					memcpy_blt(ptr, dst->devPrivate.ptr, tmp.bitsPerPixel,
 						   dst_bo->pitch, dst->devKind,
 						   box[n].x1 - extents.x1,
 						   box[n].y1 - extents.y1,
@@ -841,23 +840,22 @@ bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
 	/* Try to avoid switching rings... */
 	if (!can_blt || kgem->ring == KGEM_RENDER ||
 	    upload_too_large(sna, extents.x2 - extents.x1, extents.y2 - extents.y1)) {
-		PixmapRec tmp;
+		DrawableRec tmp;
 
-		tmp.drawable.width  = extents.x2 - extents.x1;
-		tmp.drawable.height = extents.y2 - extents.y1;
-		tmp.drawable.depth  = dst->drawable.depth;
-		tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
-		tmp.devPrivate.ptr = NULL;
+		tmp.width  = extents.x2 - extents.x1;
+		tmp.height = extents.y2 - extents.y1;
+		tmp.depth  = dst->drawable.depth;
+		tmp.bitsPerPixel = dst->drawable.bitsPerPixel;
 
-		assert(tmp.drawable.width);
-		assert(tmp.drawable.height);
+		assert(tmp.width);
+		assert(tmp.height);
 
 		DBG(("%s: upload (%d, %d)x(%d, %d), max %dx%d\n",
 		     __FUNCTION__,
 		     extents.x1, extents.y1,
-		     tmp.drawable.width, tmp.drawable.height,
+		     tmp.width, tmp.height,
 		     sna->render.max_3d_size, sna->render.max_3d_size));
-		if (must_tile(sna, tmp.drawable.width, tmp.drawable.height)) {
+		if (must_tile(sna, tmp.width, tmp.height)) {
 			BoxRec tile, stack[64], *clipped;
 			int cpp, step;
 
@@ -894,13 +892,13 @@ tile:
 						x2 = extents.x2;
 					tile.x2 = x2;
 
-					tmp.drawable.width  = tile.x2 - tile.x1;
-					tmp.drawable.height = tile.y2 - tile.y1;
+					tmp.width  = tile.x2 - tile.x1;
+					tmp.height = tile.y2 - tile.y1;
 
 					src_bo = kgem_create_buffer_2d(kgem,
-								       tmp.drawable.width,
-								       tmp.drawable.height,
-								       tmp.drawable.bitsPerPixel,
+								       tmp.width,
+								       tmp.height,
+								       tmp.bitsPerPixel,
 								       KGEM_BUFFER_WRITE_INPLACE,
 								       &ptr);
 					if (!src_bo) {
@@ -923,7 +921,7 @@ tile:
 							     src_dx, src_dy,
 							     c->x1 - tile.x1,
 							     c->y1 - tile.y1));
-							memcpy_blt(src, ptr, tmp.drawable.bitsPerPixel,
+							memcpy_blt(src, ptr, tmp.bitsPerPixel,
 								   stride, src_bo->pitch,
 								   c->x1 + src_dx,
 								   c->y1 + src_dy,
@@ -937,7 +935,7 @@ tile:
 						if (c != clipped)
 							n = sna->render.copy_boxes(sna, GXcopy,
 										   &tmp, src_bo, -tile.x1, -tile.y1,
-										   dst, dst_bo, dst_dx, dst_dy,
+										   &dst->drawable, dst_bo, dst_dx, dst_dy,
 										   clipped, c - clipped, 0);
 						else
 							n = 1;
@@ -959,9 +957,9 @@ tile:
 				free(clipped);
 		} else {
 			src_bo = kgem_create_buffer_2d(kgem,
-						       tmp.drawable.width,
-						       tmp.drawable.height,
-						       tmp.drawable.bitsPerPixel,
+						       tmp.width,
+						       tmp.height,
+						       tmp.bitsPerPixel,
 						       KGEM_BUFFER_WRITE_INPLACE,
 						       &ptr);
 			if (!src_bo)
@@ -976,7 +974,7 @@ tile:
 					     src_dx, src_dy,
 					     box[n].x1 - extents.x1,
 					     box[n].y1 - extents.y1));
-					memcpy_blt(src, ptr, tmp.drawable.bitsPerPixel,
+					memcpy_blt(src, ptr, tmp.bitsPerPixel,
 						   stride, src_bo->pitch,
 						   box[n].x1 + src_dx,
 						   box[n].y1 + src_dy,
@@ -988,7 +986,7 @@ tile:
 
 				n = sna->render.copy_boxes(sna, GXcopy,
 							   &tmp, src_bo, -extents.x1, -extents.y1,
-							   dst, dst_bo, dst_dx, dst_dy,
+							   &dst->drawable, dst_bo, dst_dx, dst_dy,
 							   box, nbox, 0);
 				sigtrap_put();
 			} else
@@ -1344,23 +1342,22 @@ bool sna_write_boxes__xor(struct sna *sna, PixmapPtr dst,
 	/* Try to avoid switching rings... */
 	if (!can_blt || kgem->ring == KGEM_RENDER ||
 	    upload_too_large(sna, extents.x2 - extents.x1, extents.y2 - extents.y1)) {
-		PixmapRec tmp;
+		DrawableRec tmp;
 
-		tmp.drawable.width  = extents.x2 - extents.x1;
-		tmp.drawable.height = extents.y2 - extents.y1;
-		tmp.drawable.depth  = dst->drawable.depth;
-		tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
-		tmp.devPrivate.ptr = NULL;
+		tmp.width  = extents.x2 - extents.x1;
+		tmp.height = extents.y2 - extents.y1;
+		tmp.depth  = dst->drawable.depth;
+		tmp.bitsPerPixel = dst->drawable.bitsPerPixel;
 
-		assert(tmp.drawable.width);
-		assert(tmp.drawable.height);
+		assert(tmp.width);
+		assert(tmp.height);
 
 		DBG(("%s: upload (%d, %d)x(%d, %d), max %dx%d\n",
 		     __FUNCTION__,
 		     extents.x1, extents.y1,
-		     tmp.drawable.width, tmp.drawable.height,
+		     tmp.width, tmp.height,
 		     sna->render.max_3d_size, sna->render.max_3d_size));
-		if (must_tile(sna, tmp.drawable.width, tmp.drawable.height)) {
+		if (must_tile(sna, tmp.width, tmp.height)) {
 			BoxRec tile, stack[64], *clipped;
 			int step;
 
@@ -1393,13 +1390,13 @@ tile:
 						x2 = extents.x2;
 					tile.x2 = x2;
 
-					tmp.drawable.width  = tile.x2 - tile.x1;
-					tmp.drawable.height = tile.y2 - tile.y1;
+					tmp.width  = tile.x2 - tile.x1;
+					tmp.height = tile.y2 - tile.y1;
 
 					src_bo = kgem_create_buffer_2d(kgem,
-								       tmp.drawable.width,
-								       tmp.drawable.height,
-								       tmp.drawable.bitsPerPixel,
+								       tmp.width,
+								       tmp.height,
+								       tmp.bitsPerPixel,
 								       KGEM_BUFFER_WRITE_INPLACE,
 								       &ptr);
 					if (!src_bo) {
@@ -1422,7 +1419,7 @@ tile:
 							     src_dx, src_dy,
 							     c->x1 - tile.x1,
 							     c->y1 - tile.y1));
-							memcpy_xor(src, ptr, tmp.drawable.bitsPerPixel,
+							memcpy_xor(src, ptr, tmp.bitsPerPixel,
 								   stride, src_bo->pitch,
 								   c->x1 + src_dx,
 								   c->y1 + src_dy,
@@ -1437,7 +1434,7 @@ tile:
 						if (c != clipped)
 							n = sna->render.copy_boxes(sna, GXcopy,
 										   &tmp, src_bo, -tile.x1, -tile.y1,
-										   dst, dst_bo, dst_dx, dst_dy,
+										   &dst->drawable, dst_bo, dst_dx, dst_dy,
 										   clipped, c - clipped, 0);
 						else
 							n = 1;
@@ -1460,9 +1457,9 @@ tile:
 				free(clipped);
 		} else {
 			src_bo = kgem_create_buffer_2d(kgem,
-						       tmp.drawable.width,
-						       tmp.drawable.height,
-						       tmp.drawable.bitsPerPixel,
+						       tmp.width,
+						       tmp.height,
+						       tmp.bitsPerPixel,
 						       KGEM_BUFFER_WRITE_INPLACE,
 						       &ptr);
 			if (!src_bo)
@@ -1477,7 +1474,7 @@ tile:
 					     src_dx, src_dy,
 					     box[n].x1 - extents.x1,
 					     box[n].y1 - extents.y1));
-					memcpy_xor(src, ptr, tmp.drawable.bitsPerPixel,
+					memcpy_xor(src, ptr, tmp.bitsPerPixel,
 						   stride, src_bo->pitch,
 						   box[n].x1 + src_dx,
 						   box[n].y1 + src_dy,
@@ -1490,7 +1487,7 @@ tile:
 
 				n = sna->render.copy_boxes(sna, GXcopy,
 							   &tmp, src_bo, -extents.x1, -extents.y1,
-							   dst, dst_bo, dst_dx, dst_dy,
+							   &dst->drawable, dst_bo, dst_dx, dst_dy,
 							   box, nbox, 0);
 				sigtrap_put();
 			} else
@@ -1781,8 +1778,8 @@ indirect_replace(struct sna *sna,
 		box.y2 = pixmap->drawable.height;
 
 		ret = sna->render.copy_boxes(sna, GXcopy,
-					     pixmap, src_bo, 0, 0,
-					     pixmap, bo, 0, 0,
+					     &pixmap->drawable, src_bo, 0, 0,
+					     &pixmap->drawable, bo, 0, 0,
 					     &box, 1, 0);
 		sigtrap_put();
 	} else
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 3eb4355..5135c11 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -125,19 +125,19 @@ no_render_check_composite_spans(struct sna *sna,
 
 static bool
 no_render_copy_boxes(struct sna *sna, uint8_t alu,
-		     PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		     PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		     const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		     const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		     const BoxRec *box, int n, unsigned flags)
 {
 	DBG(("%s (n=%d)\n", __FUNCTION__, n));
 
-	if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
+	if (!sna_blt_compare_depth(src, dst))
 		return false;
 
 	return sna_blt_copy_boxes(sna, alu,
 				  src_bo, src_dx, src_dy,
 				  dst_bo, dst_dx, dst_dy,
-				  dst->drawable.bitsPerPixel,
+				  dst->bitsPerPixel,
 				  box, n);
 }
 
@@ -163,7 +163,7 @@ no_render_fill_boxes(struct sna *sna,
 		     CARD8 op,
 		     PictFormat format,
 		     const xRenderColor *color,
-		     PixmapPtr dst, struct kgem_bo *dst_bo,
+		     const DrawableRec *dst, struct kgem_bo *dst_bo,
 		     const BoxRec *box, int n)
 {
 	uint8_t alu = GXcopy;
@@ -197,7 +197,7 @@ no_render_fill_boxes(struct sna *sna,
 		return false;
 
 	return sna_blt_fill_boxes(sna, alu,
-				  dst_bo, dst->drawable.bitsPerPixel,
+				  dst_bo, dst->bitsPerPixel,
 				  pixel, box, n);
 }
 
@@ -892,7 +892,7 @@ cleanup_tmp:
 
 bool
 sna_render_pixmap_partial(struct sna *sna,
-			  PixmapPtr pixmap,
+			  const DrawableRec *draw,
 			  struct kgem_bo *bo,
 			  struct sna_composite_channel *channel,
 			  int16_t x, int16_t y,
@@ -933,11 +933,11 @@ sna_render_pixmap_partial(struct sna *sna,
 		box.y1 = box.y1 & ~(2*tile_height - 1);
 		box.y2 = ALIGN(box.y2, 2*tile_height);
 
-		assert(tile_width * 8 >= pixmap->drawable.bitsPerPixel);
-		box.x1 = box.x1 & ~(tile_width * 8 / pixmap->drawable.bitsPerPixel - 1);
-		box.x2 = ALIGN(box.x2, tile_width * 8 / pixmap->drawable.bitsPerPixel);
+		assert(tile_width * 8 >= draw->bitsPerPixel);
+		box.x1 = box.x1 & ~(tile_width * 8 / draw->bitsPerPixel - 1);
+		box.x2 = ALIGN(box.x2, tile_width * 8 / draw->bitsPerPixel);
 
-		offset = box.x1 * pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size;
+		offset = box.x1 * draw->bitsPerPixel / 8 / tile_width * tile_size;
 	} else {
 		box.y1 = box.y1 & ~1;
 		box.y2 = ALIGN(box.y2, 2);
@@ -945,19 +945,19 @@ sna_render_pixmap_partial(struct sna *sna,
 		box.x1 = box.x1 & ~1;
 		box.x2 = ALIGN(box.x2, 2);
 
-		offset = box.x1 * pixmap->drawable.bitsPerPixel / 8;
+		offset = box.x1 * draw->bitsPerPixel / 8;
 	}
 
-	if (box.x2 > pixmap->drawable.width)
-		box.x2 = pixmap->drawable.width;
-	if (box.y2 > pixmap->drawable.height)
-		box.y2 = pixmap->drawable.height;
+	if (box.x2 > draw->width)
+		box.x2 = draw->width;
+	if (box.y2 > draw->height)
+		box.y2 = draw->height;
 
 	w = box.x2 - box.x1;
 	h = box.y2 - box.y1;
 	DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d)\n", __FUNCTION__,
 	     box.x1, box.y1, box.x2, box.y2, w, h,
-	     pixmap->drawable.width, pixmap->drawable.height));
+	     draw->width, draw->height));
 	if (w <= 0 || h <= 0 ||
 	    w > sna->render.max_3d_size ||
 	    h > sna->render.max_3d_size) {
@@ -1220,19 +1220,18 @@ sna_render_picture_extract(struct sna *sna,
 						       pixmap->drawable.bitsPerPixel),
 				    CREATE_TEMPORARY);
 		if (bo) {
-			PixmapRec tmp;
+			DrawableRec tmp;
 
-			tmp.drawable.width  = w;
-			tmp.drawable.height = h;
-			tmp.drawable.depth  = pixmap->drawable.depth;
-			tmp.drawable.bitsPerPixel = pixmap->drawable.bitsPerPixel;
-			tmp.devPrivate.ptr = NULL;
+			tmp.width  = w;
+			tmp.height = h;
+			tmp.depth  = pixmap->drawable.depth;
+			tmp.bitsPerPixel = pixmap->drawable.bitsPerPixel;
 
-			assert(tmp.drawable.width);
-			assert(tmp.drawable.height);
+			assert(tmp.width);
+			assert(tmp.height);
 
 			if (!sna->render.copy_boxes(sna, GXcopy,
-						    pixmap, src_bo, 0, 0,
+						    &pixmap->drawable, src_bo, 0, 0,
 						    &tmp, bo, -box.x1, -box.y1,
 						    &box, 1, 0)) {
 				kgem_bo_destroy(&sna->kgem, bo);
@@ -2126,12 +2125,12 @@ sna_render_composite_redirect_done(struct sna *sna,
 
 static bool
 copy_overlap(struct sna *sna, uint8_t alu,
-	     PixmapPtr pixmap, struct kgem_bo *bo,
+	     const DrawableRec *draw, struct kgem_bo *bo,
 	     int16_t src_dx, int16_t src_dy,
 	     int16_t dst_dx, int16_t dst_dy,
 	     const BoxRec *box, int n, const BoxRec *extents)
 {
-	ScreenPtr screen = pixmap->drawable.pScreen;
+	ScreenPtr screen = draw->pScreen;
 	struct kgem_bo *tmp_bo;
 	PixmapPtr tmp;
 	bool ret = false;
@@ -2149,7 +2148,7 @@ copy_overlap(struct sna *sna, uint8_t alu,
 	tmp = screen->CreatePixmap(screen,
 				   extents->x2 - extents->x1,
 				   extents->y2 - extents->y1,
-				   pixmap->drawable.depth,
+				   draw->depth,
 				   SNA_CREATE_SCRATCH);
 	if (tmp == NULL)
 		return false;
@@ -2158,12 +2157,12 @@ copy_overlap(struct sna *sna, uint8_t alu,
 	assert(tmp_bo);
 
 	ret = (sna->render.copy_boxes(sna, GXcopy,
-				      pixmap, bo, src_dx, src_dy,
-				      tmp, tmp_bo, -extents->x1, -extents->y1,
+				      draw, bo, src_dx, src_dy,
+				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
 				      box, n , 0) &&
 	       sna->render.copy_boxes(sna, alu,
-				      tmp, tmp_bo, -extents->x1, -extents->y1,
-				      pixmap, bo, dst_dx, dst_dy,
+				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
+				      draw, bo, dst_dx, dst_dy,
 				      box, n , 0));
 
 	screen->DestroyPixmap(tmp);
@@ -2171,7 +2170,7 @@ copy_overlap(struct sna *sna, uint8_t alu,
 }
 bool
 sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
-			       PixmapPtr pixmap, struct kgem_bo *bo,
+			       const DrawableRec *draw, struct kgem_bo *bo,
 			       int16_t src_dx, int16_t src_dy,
 			       int16_t dst_dx, int16_t dst_dy,
 			       const BoxRec *box, int n, const BoxRec *extents)
@@ -2182,14 +2181,15 @@ sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
 	pixman_box16_t stack_boxes[64], *boxes = stack_boxes;
 	int num_boxes, i;
 
+	assert(draw->type == DRAWABLE_PIXMAP);
 	DBG(("%s: pixmap=%ld, handle=%d, %d x [(%d, %d), (%d, %d)], dst=(%d, %d), src=(%d, %d)\n",
-	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle,
+	     __FUNCTION__, draw->serialNumber, bo->handle,
 	     n, extents->x1, extents->y1, extents->x2, extents->y2,
 	     src_dx, src_dy, dst_dx, dst_dy));
 
 	if ((dst_dx - src_dx < 4 && src_dx - dst_dx < 4) &&
 	    (dst_dy - src_dy < 4 && src_dy - dst_dy < 4))
-		return copy_overlap(sna, alu, pixmap, bo,
+		return copy_overlap(sna, alu, draw, bo,
 				    src_dx, src_dy,
 				    dst_dx, dst_dy,
 				    box, n, extents);
@@ -2197,7 +2197,7 @@ sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
 	if (n > ARRAY_SIZE(stack_boxes)) {
 		boxes = malloc(sizeof(pixman_box16_t) * n);
 		if (boxes == NULL)
-			return copy_overlap(sna, alu, pixmap, bo,
+			return copy_overlap(sna, alu, draw, bo,
 					    src_dx, src_dy,
 					    dst_dx, dst_dy,
 					    box, n, extents);
@@ -2262,14 +2262,14 @@ sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
 	n = region_num_rects(&non_overlap);
 	box = region_rects(&non_overlap);
 	if (n && !sna->render.copy_boxes(sna, alu,
-					 pixmap, bo, -dst_dx + src_dx, -dst_dy + src_dy,
-					 pixmap, bo, 0, 0,
+					 draw, bo, -dst_dx + src_dx, -dst_dy + src_dy,
+					 draw, bo, 0, 0,
 					 box, n , COPY_NO_OVERLAP))
 		goto cleanup_boxes;
 
 	n = region_num_rects(&overlap);
 	box = region_rects(&overlap);
-	ret = copy_overlap(sna, alu, pixmap, bo,
+	ret = copy_overlap(sna, alu, draw, bo,
 			   -dst_dx + src_dx, -dst_dy + src_dy,
 			   0, 0,
 			   box, n, &overlap.extents);
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 0637ceb..8b839de 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -44,7 +44,7 @@ struct sna_composite_op {
 	uint32_t op;
 
 	struct {
-		PixmapPtr pixmap;
+		PixmapPtr pixmap; /* XXX */
 		CARD32 format;
 		struct kgem_bo *bo;
 		int16_t x, y;
@@ -264,7 +264,7 @@ struct sna_render {
 			   CARD8 op,
 			   PictFormat format,
 			   const xRenderColor *color,
-			   PixmapPtr dst, struct kgem_bo *dst_bo,
+			   const DrawableRec *dst, struct kgem_bo *dst_bo,
 			   const BoxRec *box, int n);
 	bool (*fill)(struct sna *sna, uint8_t alu,
 		     PixmapPtr dst, struct kgem_bo *dst_bo,
@@ -280,8 +280,8 @@ struct sna_render {
 	bool (*clear)(struct sna *sna, PixmapPtr dst, struct kgem_bo *dst_bo);
 
 	bool (*copy_boxes)(struct sna *sna, uint8_t alu,
-			   PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-			   PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+			   const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+			   const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 			   const BoxRec *box, int n, unsigned flags);
 #define COPY_LAST 0x1
 #define COPY_SYNC 0x2
@@ -641,12 +641,12 @@ bool sna_tiling_fill_boxes(struct sna *sna,
 			   CARD8 op,
 			   PictFormat format,
 			   const xRenderColor *color,
-			   PixmapPtr dst, struct kgem_bo *dst_bo,
+			   const DrawableRec *dst, struct kgem_bo *dst_bo,
 			   const BoxRec *box, int n);
 
 bool sna_tiling_copy_boxes(struct sna *sna, uint8_t alu,
-			   PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-			   PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+			   const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+			   const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 			   const BoxRec *box, int n);
 
 bool sna_tiling_blt_copy_boxes(struct sna *sna, uint8_t alu,
@@ -703,8 +703,8 @@ bool sna_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
 				    int bpp, int alpha_fixup,
 				    const BoxRec *box, int nbox);
 bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
-				 PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-				 PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+				 const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+				 const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 				 const BoxRec *box, int nbox);
 
 bool _sna_get_pixel_from_rgba(uint32_t *pixel,
@@ -756,7 +756,7 @@ sna_render_pixmap_bo(struct sna *sna,
 
 bool
 sna_render_pixmap_partial(struct sna *sna,
-			  PixmapPtr pixmap,
+			  const DrawableRec *draw,
 			  struct kgem_bo *bo,
 			  struct sna_composite_channel *channel,
 			  int16_t x, int16_t y,
@@ -815,7 +815,7 @@ sna_render_composite_redirect_done(struct sna *sna,
 
 bool
 sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
-			       PixmapPtr pixmap, struct kgem_bo *bo,
+			       const DrawableRec *draw, struct kgem_bo *bo,
 			       int16_t src_dx, int16_t src_dy,
 			       int16_t dst_dx, int16_t dst_dy,
 			       const BoxRec *box, int n, const BoxRec *extents);
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index d51730e..40a9ac4 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -178,7 +178,7 @@ picture_is_cpu(struct sna *sna, PicturePtr picture)
 	return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER);
 }
 
-static inline bool sna_blt_compare_depth(DrawablePtr src, DrawablePtr dst)
+static inline bool sna_blt_compare_depth(const DrawableRec *src, const DrawableRec *dst)
 {
 	if (src->depth == dst->depth)
 		return true;
diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c
index 3237185..308efc0 100644
--- a/src/sna/sna_tiling.c
+++ b/src/sna/sna_tiling.c
@@ -596,7 +596,7 @@ sna_tiling_fill_boxes(struct sna *sna,
 		      CARD8 op,
 		      PictFormat format,
 		      const xRenderColor *color,
-		      PixmapPtr dst, struct kgem_bo *dst_bo,
+		      const DrawableRec *dst, struct kgem_bo *dst_bo,
 		      const BoxRec *box, int n)
 {
 	RegionRec region, tile, this;
@@ -608,7 +608,7 @@ sna_tiling_fill_boxes(struct sna *sna,
 
 	/* Use a small step to accommodate enlargement through tile alignment */
 	step = sna->render.max_3d_size;
-	if (region.extents.x1 & (8*512 / dst->drawable.bitsPerPixel - 1) ||
+	if (region.extents.x1 & (8*512 / dst->bitsPerPixel - 1) ||
 	    region.extents.y1 & 63)
 		step /= 2;
 
@@ -637,7 +637,7 @@ sna_tiling_fill_boxes(struct sna *sna,
 		for (tile.extents.x1 = tile.extents.x2 = region.extents.x1;
 		     tile.extents.x2 < region.extents.x2;
 		     tile.extents.x1 = tile.extents.x2) {
-			PixmapRec tmp;
+			DrawableRec tmp;
 			int x2 = tile.extents.x1 + step;
 			if (x2 > region.extents.x2)
 				x2 = region.extents.x2;
@@ -650,21 +650,20 @@ sna_tiling_fill_boxes(struct sna *sna,
 			if (RegionNil(&this))
 				continue;
 
-			tmp.drawable.width  = this.extents.x2 - this.extents.x1;
-			tmp.drawable.height = this.extents.y2 - this.extents.y1;
-			tmp.drawable.depth  = dst->drawable.depth;
-			tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel;
-			tmp.devPrivate.ptr = NULL;
+			tmp.width  = this.extents.x2 - this.extents.x1;
+			tmp.height = this.extents.y2 - this.extents.y1;
+			tmp.depth  = dst->depth;
+			tmp.bitsPerPixel = dst->bitsPerPixel;
 
 			bo = kgem_create_2d(&sna->kgem,
-					    tmp.drawable.width,
-					    tmp.drawable.height,
-					    dst->drawable.bitsPerPixel,
+					    tmp.width,
+					    tmp.height,
+					    dst->bitsPerPixel,
 					    kgem_choose_tiling(&sna->kgem,
 							       I915_TILING_X,
-							       tmp.drawable.width,
-							       tmp.drawable.height,
-							       dst->drawable.bitsPerPixel),
+							       tmp.width,
+							       tmp.height,
+							       dst->bitsPerPixel),
 					    CREATE_TEMPORARY);
 			if (bo) {
 				int16_t dx = this.extents.x1;
@@ -1125,12 +1124,12 @@ done:
 
 bool
 sna_tiling_copy_boxes(struct sna *sna, uint8_t alu,
-		      PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		      PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+		      const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+		      const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
 		      const BoxRec *box, int n)
 {
 	BoxRec extents, tile, stack[64], *clipped, *c;
-	PixmapRec p;
+	DrawableRec p;
 	int i, step, tiling;
 	bool create = true;
 	bool ret = false;
@@ -1174,9 +1173,8 @@ sna_tiling_copy_boxes(struct sna *sna, uint8_t alu,
 	} else
 		clipped = stack;
 
-	p.drawable.depth = src->drawable.depth;
-	p.drawable.bitsPerPixel = src->drawable.bitsPerPixel;
-	p.devPrivate.ptr = NULL;
+	p.depth = src->depth;
+	p.bitsPerPixel = src->bitsPerPixel;
 
 	for (tile.y1 = extents.y1; tile.y1 < extents.y2; tile.y1 = tile.y2) {
 		int y2 = tile.y1 + step;
@@ -1209,17 +1207,17 @@ sna_tiling_copy_boxes(struct sna *sna, uint8_t alu,
 			if (c == clipped)
 				continue;
 
-			p.drawable.width  = tile.x2 - tile.x1;
-			p.drawable.height = tile.y2 - tile.y1;
+			p.width  = tile.x2 - tile.x1;
+			p.height = tile.y2 - tile.y1;
 
 			DBG(("%s: tile (%d, %d), (%d, %d)\n",
 			     __FUNCTION__, tile.x1, tile.y1, tile.x2, tile.y2));
 
 			if (create) {
 				tmp_bo = kgem_create_2d(&sna->kgem,
-							p.drawable.width,
-							p.drawable.height,
-							p.drawable.bitsPerPixel,
+							p.width,
+							p.height,
+							p.bitsPerPixel,
 							tiling, CREATE_TEMPORARY);
 				if (!tmp_bo)
 					goto tiled_error;
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 789be9c..2c1fa65 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -801,8 +801,8 @@ trap_upload(PicturePtr picture,
 	/* XXX clip boxes */
 	get_drawable_deltas(picture->pDrawable, pixmap, &x, &y);
 	sna->render.copy_boxes(sna, GXcopy,
-			       scratch, __sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
-			       pixmap, priv->gpu_bo, x, y,
+			       &scratch->drawable, __sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
+			       &pixmap->drawable, priv->gpu_bo, x, y,
 			       &extents, 1, 0);
 	mark_damaged(pixmap, priv, &extents, x, y);
 
diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
index ebde762..47adf5a 100644
--- a/src/sna/sna_trapezoids_imprecise.c
+++ b/src/sna/sna_trapezoids_imprecise.c
@@ -3526,8 +3526,8 @@ trap_mask_converter(struct sna *sna,
 	get_drawable_deltas(picture->pDrawable, pixmap, &x, &y);
 	sna = to_sna_from_screen(screen);
 	sna->render.copy_boxes(sna, GXcopy,
-			       scratch, __sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
-			       pixmap, priv->gpu_bo, x, y,
+			       &scratch->drawable, __sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
+			       &pixmap->drawable, priv->gpu_bo, x, y,
 			       &extents, 1, 0);
 	mark_damaged(pixmap, priv, &extents ,x, y);
 	sna_pixmap_destroy(scratch);


More information about the xorg-commit mailing list