xf86-video-intel: 8 commits - 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_display.c src/sna/sna_render.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Sep 25 08:49:46 PDT 2014


 src/sna/gen4_render.c |    2 
 src/sna/gen5_render.c |    2 
 src/sna/gen6_render.c |    2 
 src/sna/gen7_render.c |    2 
 src/sna/gen8_render.c |    2 
 src/sna/sna_accel.c   |   24 ++++-
 src/sna/sna_display.c |  233 +++++++++++++++++++++++++++++++++++++-------------
 src/sna/sna_render.c  |   16 +++
 8 files changed, 218 insertions(+), 65 deletions(-)

New commits:
commit 7302f8a6482f4eed497536fc5a8a487c10da4d52
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 25 16:44:08 2014 +0100

    sna: Pass scanout hints along to move-to-gpu
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index ea355aa..0aa7557 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1740,7 +1740,7 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
 		return true;
 	}
 
-	priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ);
+	priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
 	if (priv == NULL)
 		return true; /* maybe we can create a bo for the scanout? */
 
@@ -4180,7 +4180,7 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
 	if (!old_priv)
 		return;
 
-	new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE);
+	new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE | __MOVE_SCANOUT);
 	if (!new_priv)
 		return;
 
commit e9087f50bf6dafff87c566d3bdbe6cef29d71fde
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 25 16:41:11 2014 +0100

    sna: Check scanout Pixmaps are the correct pitch and convert if necessary
    
    As a final precaution, fixup the pitch on the bo to be used for
    scanout by switching the bo on the Pixmap for a new correctly aligned
    scanout bo.
    
    Reported-by: Egbert Eich <eich at suse.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index e7908cb..ea355aa 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1832,6 +1832,61 @@ static void set_shadow(struct sna *sna, RegionPtr region)
 	priv->move_to_gpu_data = sna;
 }
 
+static struct kgem_bo *
+get_scanout_bo(struct sna *sna, PixmapPtr pixmap)
+{
+	struct sna_pixmap *priv;
+
+	priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT);
+	if (!priv)
+		return NULL;
+
+	if (priv->gpu_bo->pitch & 63) {
+		struct kgem_bo *tmp;
+		BoxRec b;
+
+		DBG(("%s: converting to scanout bo due to bad pitch [%d]\n",
+		     __FUNCTION__, priv->gpu_bo->pitch));
+
+		if (priv->pinned) {
+			DBG(("%s: failed as the Pixmap is already pinned [%x]\n",
+			     __FUNCTION__, priv->pinned));
+			return NULL;
+		}
+
+		tmp = kgem_create_2d(&sna->kgem,
+				     pixmap->drawable.width,
+				     pixmap->drawable.height,
+				     sna->scrn->bitsPerPixel,
+				     priv->gpu_bo->tiling,
+				     CREATE_EXACT | CREATE_SCANOUT);
+		if (tmp == NULL) {
+			DBG(("%s: allocation failed\n", __FUNCTION__));
+			return NULL;
+		}
+
+		b.x1 = 0;
+		b.y1 = 0;
+		b.x2 = pixmap->drawable.width;
+		b.y2 = pixmap->drawable.height;
+
+		if (sna->render.copy_boxes(sna, GXcopy,
+					   &pixmap->drawable, priv->gpu_bo, 0, 0,
+					   &pixmap->drawable, tmp, 0, 0,
+					   &b, 1, COPY_LAST)) {
+			DBG(("%s: copy failed\n", __FUNCTION__));
+			kgem_bo_destroy(&sna->kgem, tmp);
+			return NULL;
+		}
+
+		kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+		priv->gpu_bo = tmp;
+	}
+
+	priv->pinned |= PIN_SCANOUT;
+	return priv->gpu_bo;
+}
+
 static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 {
 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
@@ -1937,7 +1992,7 @@ out_shadow:
 
 		if (sna_crtc->slave_pixmap) {
 			DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
-			bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
+			bo = get_scanout_bo(sna, sna_crtc->slave_pixmap);
 			if (bo == NULL) {
 				DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
 				sna_crtc->fallback_shadow = true;
@@ -1953,7 +2008,7 @@ out_shadow:
 			}
 		} else {
 			DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
-			bo = sna_pixmap_pin(sna->front, PIN_SCANOUT);
+			bo = get_scanout_bo(sna, sna->front);
 			if (bo == NULL) {
 				DBG(("%s: failed to pin framebuffer\n", __FUNCTION__));
 				sna_crtc->fallback_shadow = true;
commit 9f7c1a4c4f2a6352263c36e75a984ed4095adbc0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 25 16:29:14 2014 +0100

    sna: Check for scanout pitch restrictions on linear GPU bo
    
    When converting a linear cached CPU bo into an uncached GPU bo, we must
    be careful to adhere to the scanout restrictions if they apply for this
    transfer or this Pixmap.
    
    Reported-by: Egbert Eich <eich at suse.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 37e1e7c..4462207 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4051,6 +4051,27 @@ sna_pixmap_create_upload(ScreenPtr screen,
 	return pixmap;
 }
 
+static bool can_convert_to_gpu(struct sna_pixmap *priv, unsigned flags)
+{
+	assert(priv->gpu_bo == NULL);
+
+	if (priv->cpu_bo == NULL)
+		return false;
+
+	if (priv->shm)
+		return false;
+
+	/* Linear scanout have a restriction that their pitch must be
+	 * 64 byte aligned. Force the creation of a proper GPU bo if
+	 * this CPU bo is not suitable for scanout.
+	 */
+	if (priv->pixmap->usage_hint == SNA_CREATE_FB || flags & __MOVE_SCANOUT)
+		if (priv->cpu_bo->pitch & 63)
+			return false;
+
+	return true;
+}
+
 struct sna_pixmap *
 sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 {
@@ -4141,7 +4162,8 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 				return NULL;
 			}
 
-			if (is_linear && priv->cpu_bo && !priv->shm &&
+			if (is_linear &&
+			    can_convert_to_gpu(priv, flags) &&
 			    kgem_bo_convert_to_gpu(&sna->kgem, priv->cpu_bo, flags)) {
 				assert(!priv->mapped);
 				assert(!IS_STATIC_PTR(priv->ptr));
commit 4827c518fe3323eedb56e7af7aef33801236d11f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Sep 25 16:22:06 2014 +0100

    sna: Use shadow CRTC bo if we fail to obtain an framebuffer for the Pixmap
    
    This should mask driver bugs whereby we ask the kernel to make a
    framebuffer out of an improper bo.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 07f5dff..e7908cb 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1846,6 +1846,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 		unsigned long tiled_limit;
 		int tiling;
 
+force_shadow:
 		if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
 			DBG(("%s: failed to enable crtc shadow\n"));
 			return NULL;
@@ -1939,26 +1940,30 @@ out_shadow:
 			bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
 			if (bo == NULL) {
 				DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
-				return NULL;
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
 			}
 
 			if (!get_fb(sna, bo,
 				    sna_crtc->slave_pixmap->drawable.width,
 				    sna_crtc->slave_pixmap->drawable.height)) {
 				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
-				return NULL;
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
 			}
 		} else {
 			DBG(("%s: attaching to framebuffer\n", __FUNCTION__));
 			bo = sna_pixmap_pin(sna->front, PIN_SCANOUT);
 			if (bo == NULL) {
 				DBG(("%s: failed to pin framebuffer\n", __FUNCTION__));
-				return NULL;
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
 			}
 
 			if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY)) {
 				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
-				return NULL;
+				sna_crtc->fallback_shadow = true;
+				goto force_shadow;
 			}
 		}
 
@@ -1995,7 +2000,8 @@ out_shadow:
 							CREATE_SCANOUT);
 				if (shadow == NULL) {
 					DBG(("%s: failed to allocate TearFree shadow bo\n", __FUNCTION__));
-					return NULL;
+					sna_crtc->fallback_shadow = true;
+					goto force_shadow;
 				}
 
 				if (!get_fb(sna, shadow,
@@ -2003,7 +2009,8 @@ out_shadow:
 					    region.extents.y2)) {
 					DBG(("%s: failed to bind fb for TearFeee shadow\n", __FUNCTION__));
 					kgem_bo_destroy(&sna->kgem, shadow);
-					return NULL;
+					sna_crtc->fallback_shadow = true;
+					goto force_shadow;
 				}
 
 				sna->mode.shadow = shadow;
commit f3d27eec52cac63378c0e466db971ae125c813a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 24 16:16:25 2014 +0100

    sna/gen4+: Assert that the offset coordinate is within range if negative
    
    Invalid negative offsets could slip into the drawing rectangle
    without triggering the assertion - the assertion being that they were
    not greater than the maximum positive coordinate of the 3d engine.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 9a6761f..6c2d380 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -941,7 +941,7 @@ gen4_emit_drawing_rectangle(struct sna *sna, const struct sna_composite_op *op)
 	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
 	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
 
-	assert(!too_large(op->dst.x, op->dst.y));
+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
 	assert(!too_large(op->dst.width, op->dst.height));
 
 	if (sna->render_state.gen4.drawrect_limit == limit &&
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 1ebaef9..435e674 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -877,7 +877,7 @@ gen5_emit_drawing_rectangle(struct sna *sna, const struct sna_composite_op *op)
 	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
 	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
 
-	assert(!too_large(op->dst.x, op->dst.y));
+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
 	assert(!too_large(op->dst.width, op->dst.height));
 
 	if (!DBG_NO_STATE_CACHE &&
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 86ea146..5c625ef 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -687,7 +687,7 @@ gen6_emit_drawing_rectangle(struct sna *sna,
 	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
 	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
 
-	assert(!too_large(op->dst.x, op->dst.y));
+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
 	assert(!too_large(op->dst.width, op->dst.height));
 
 	if (sna->render_state.gen6.drawrect_limit  == limit &&
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 571de6e..16e666b 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -923,7 +923,7 @@ gen7_emit_drawing_rectangle(struct sna *sna,
 	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
 	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
 
-	assert(!too_large(op->dst.x, op->dst.y));
+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
 	assert(!too_large(op->dst.width, op->dst.height));
 
 	if (sna->render_state.gen7.drawrect_limit == limit &&
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index e251315..6cc7a68 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -989,7 +989,7 @@ gen8_emit_drawing_rectangle(struct sna *sna,
 	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
 	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
 
-	assert(!too_large(op->dst.x, op->dst.y));
+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
 	assert(!too_large(op->dst.width, op->dst.height));
 
 	if (sna->render_state.gen8.drawrect_limit == limit &&
commit a60ccd546e081f5b7bd7de762e1638927a4145a2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 24 15:55:11 2014 +0100

    sna: Relax constant numCrtcs assertion when ZaphodHeads is active
    
    If ZaphodHeads is active, each screen only has a subset of the CRTC
    assigned to it, in fact just the single CRTC associated with the pipe of
    that screen. In that case, we only expect to have the single CRTC and so
    should not assert that we have a list of all CRTCS.
    
    It should still hold that we dynamically attach ZaphodHeads upon
    hotplugging, so it is just the assert that is overzealous.
    
    Reported-by: Nick Bowler <nbowler at draconx.ca>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84281
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index cab17c3..07f5dff 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -217,6 +217,11 @@ enum { /* XXX copied from hw/xfree86/modes/xf86Crtc.c */
 
 static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
 
+static bool is_zaphod(ScrnInfoPtr scrn)
+{
+	return xf86IsEntityShared(scrn->entityList[0]);
+}
+
 inline static unsigned count_to_mask(int x)
 {
 	return (1 << x) - 1;
@@ -1022,7 +1027,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
 		     (uint32_t)output->possible_clones));
 
 		assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
-		       xf86IsEntityShared(crtc->scrn->entityList[0]));
+		       is_zaphod(crtc->scrn));
 
 		output_ids[output_count] = to_connector_id(output);
 		if (++output_count == ARRAY_SIZE(output_ids)) {
@@ -2636,7 +2641,7 @@ sna_crtc_add(ScrnInfoPtr scrn, int id)
 	}
 	sna_crtc->pipe = get_pipe.pipe;
 
-	if (xf86IsEntityShared(scrn->entityList[0]) &&
+	if (is_zaphod(scrn) &&
 	    scrn->confScreen->device->screen != sna_crtc->pipe) {
 		free(sna_crtc);
 		return true;
@@ -3715,7 +3720,7 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
 		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc);
 	}
 
-	if (xf86IsEntityShared(scrn->entityList[0])) {
+	if (is_zaphod(scrn)) {
 		const char *str;
 
 		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
@@ -4031,7 +4036,7 @@ void sna_mode_discover(struct sna *sna)
 	if (res.count_connectors > 32)
 		return;
 
-	assert(sna->mode.num_real_crtc == res.count_crtcs);
+	assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn));
 	assert(sna->mode.max_crtc_width  == res.max_width);
 	assert(sna->mode.max_crtc_height == res.max_height);
 	assert(sna->mode.num_real_encoder == res.count_encoders);
@@ -5106,7 +5111,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
 		     (uint32_t)output->possible_clones));
 
 		assert(output->possible_crtcs & (1 << crtc->pipe) ||
-		       xf86IsEntityShared(sna->scrn->entityList[0]));
+		       is_zaphod(sna->scrn));
 
 		output_ids[output_count] = to_connector_id(output);
 		if (++output_count == ARRAY_SIZE(output_ids))
commit 7637f547ca34668ef9d4f0c417de16e7126927b5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 24 15:43:53 2014 +0100

    sna: Tweak partial Picture extraction to prefer limiting to max 3D coordinates
    
    Where possible, keep the offset of the partial Picture within the 3D
    coordinate limit so that we can use the DrawRectangle offset to
    automatically adjust the coordinates.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 71330c1..af072f0 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1977,6 +1977,14 @@ sna_render_composite_redirect(struct sna *sna,
 			box.x1 = box.x1 & ~(tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel - 1);
 			box.x2 = ALIGN(box.x2, tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel);
 
+			if (box.x1 > sna->render.max_3d_size &&
+			    box.x2 <= 2*sna->render.max_3d_size)
+				box.x1 = sna->render.max_3d_size;
+
+			if (box.y1 > sna->render.max_3d_size &&
+			    box.y2 <= 2*sna->render.max_3d_size)
+				box.y1 = sna->render.max_3d_size;
+
 			offset = box.x1 * op->dst.pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size;
 		} else {
 			if (sna->kgem.gen < 040) {
@@ -1993,6 +2001,14 @@ sna_render_composite_redirect(struct sna *sna,
 				box.x2 = ALIGN(box.x2, 2);
 			}
 
+			if (box.x1 > sna->render.max_3d_size &&
+			    box.x2 <= 2*sna->render.max_3d_size)
+				box.x1 = sna->render.max_3d_size;
+
+			if (box.y1 > sna->render.max_3d_size &&
+			    box.y2 <= 2*sna->render.max_3d_size)
+				box.y1 = sna->render.max_3d_size;
+
 			offset = box.x1 * op->dst.pixmap->drawable.bitsPerPixel / 8;
 		}
 
commit 65a23ef90975f95444da103f45eb240b2895ef44
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 24 14:06:30 2014 +0100

    sna: Reuse the same buffer when panning large CRTCs
    
    Rather than alternating between a pair of fb each time, we can reuse the
    last shadow buffer so long as it remains the right size.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 3ca56f1..cab17c3 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -120,7 +120,7 @@ struct sna_crtc {
 	int dpms_mode;
 	PixmapPtr slave_pixmap;
 	DamagePtr slave_damage;
-	struct kgem_bo *bo, *shadow_bo;
+	struct kgem_bo *bo, *shadow_bo, *client_bo;
 	struct sna_cursor *cursor;
 	unsigned int last_cursor_size;
 	uint32_t offset;
@@ -130,6 +130,8 @@ struct sna_crtc {
 	uint8_t id;
 	uint8_t pipe;
 
+	uint16_t shadow_bo_width, shadow_bo_height;
+
 	uint32_t rotation;
 	struct plane {
 		uint32_t id;
@@ -1121,17 +1123,17 @@ static bool wait_for_shadow(struct sna *sna,
 					     crtc->base->bounds.y1,
 					     crtc->base->bounds.x2,
 					     crtc->base->bounds.y2,
-					     crtc->shadow_bo->handle));
+					     crtc->client_bo->handle));
 
 					ret &= sna->render.copy_boxes(sna, GXcopy,
-								      &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+								      &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
 								      &pixmap->drawable, priv->gpu_bo, 0, 0,
 								      &crtc->base->bounds, 1,
 								      0);
 				}
 
-				kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
-				crtc->shadow_bo = NULL;
+				kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+				crtc->client_bo = NULL;
 				list_del(&crtc->shadow_link);
 			}
 		}
@@ -1226,10 +1228,10 @@ static bool wait_for_shadow(struct sna *sna,
 			     crtc->base->bounds.y1,
 			     crtc->base->bounds.x2,
 			     crtc->base->bounds.y2,
-			     crtc->shadow_bo->handle));
+			     crtc->client_bo->handle));
 
 			ret = sna->render.copy_boxes(sna, GXcopy,
-						     &draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+						     &draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
 						     &pixmap->drawable, bo, 0, 0,
 						     &crtc->base->bounds, 1,
 						     0);
@@ -1240,8 +1242,8 @@ static bool wait_for_shadow(struct sna *sna,
 			RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, &region);
 		}
 
-		kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
-		crtc->shadow_bo = NULL;
+		kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+		crtc->client_bo = NULL;
 		list_del(&crtc->shadow_link);
 	}
 
@@ -1433,7 +1435,7 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
 
 static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
 {
-	if (crtc->shadow_bo == NULL)
+	if (crtc->client_bo == NULL)
 		return;
 
 	if (!crtc->transform) {
@@ -1445,13 +1447,13 @@ static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
 		tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
 
 		sna->render.copy_boxes(sna, GXcopy,
-				       &tmp, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
+				       &tmp, crtc->client_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);
 	}
-	kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
-	crtc->shadow_bo = NULL;
+	kgem_bo_destroy(&sna->kgem, crtc->client_bo);
+	crtc->client_bo = NULL;
 }
 
 static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
@@ -1499,6 +1501,10 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
 		sna->mode.dirty = true;
 	}
 
+	if (sna_crtc->shadow_bo) {
+		kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+		sna_crtc->shadow_bo = NULL;
+	}
 	sna_crtc->transform = false;
 
 	assert(!sna_crtc->shadow);
@@ -1843,6 +1849,19 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 		DBG(("%s: attaching to per-crtc pixmap %dx%d\n",
 		     __FUNCTION__, crtc->mode.HDisplay, crtc->mode.VDisplay));
 
+		bo = sna_crtc->shadow_bo;
+		if (bo) {
+			if (sna_crtc->shadow_bo_width == crtc->mode.HDisplay &&
+			    sna_crtc->shadow_bo_height == crtc->mode.VDisplay) {
+				DBG(("%s: reusing current shadow bo handle=%d\n",
+				     __FUNCTION__, bo->handle));
+				goto out_shadow;
+			}
+
+			kgem_bo_destroy(&sna->kgem, bo);
+			sna_crtc->shadow_bo = NULL;
+		}
+
 		tiling = I915_TILING_X;
 		if (sna->kgem.gen == 071)
 			tiled_limit = 16 * 1024 * 8;
@@ -1862,25 +1881,29 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 				    scrn->bitsPerPixel,
 				    tiling, CREATE_SCANOUT);
 		if (bo == NULL) {
-			DBG(("%s: failed to allocate crtc scanout\n"));
+			DBG(("%s: failed to allocate crtc scanout\n", __FUNCTION__));
 			return NULL;
 		}
 
 		if (!get_fb(sna, bo, crtc->mode.HDisplay, crtc->mode.VDisplay)) {
-			DBG(("%s: failed to bind fb for crtc scanout\n"));
+			DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
 			kgem_bo_destroy(&sna->kgem, bo);
 			return NULL;
 		}
 
-		if (__sna_pixmap_get_bo(sna->front)) {
+		if (__sna_pixmap_get_bo(sna->front) && !crtc->transformPresent) {
 			DrawableRec tmp;
+			BoxRec b;
+
+			b.x1 = crtc->x;
+			b.y1 = crtc->y;
+			b.x2 = crtc->x + crtc->mode.HDisplay;
+			b.y2 = crtc->y + crtc->mode.VDisplay;
 
-			DBG(("%s: copying onto shadow CRTC: (%d, %d), (%d, %d), handle=%d\n",
+			DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d), handle=%d\n",
 			     __FUNCTION__,
-			     crtc->bounds.x1,
-			     crtc->bounds.y1,
-			     crtc->bounds.x2,
-			     crtc->bounds.y2,
+			     b.x1, b.y1,
+			     b.x2, b.y2,
 			     bo->handle));
 
 			tmp.width = crtc->mode.HDisplay;
@@ -1890,26 +1913,34 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 
 			(void)sna->render.copy_boxes(sna, GXcopy,
 						     &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
-						     &tmp, bo, -crtc->bounds.x1, -crtc->bounds.y1,
-						     &crtc->bounds, 1,
-						     0);
+						     &tmp, bo, -b.x1, -b.y1,
+						     &b, 1, 0);
 		}
 
+		sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
+		sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
+		sna_crtc->shadow_bo = bo;
+out_shadow:
 		sna_crtc->transform = true;
-		return bo;
+		return kgem_bo_reference(bo);
 	} else {
+		if (sna_crtc->shadow_bo) {
+			kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+			sna_crtc->shadow_bo = NULL;
+		}
+
 		if (sna_crtc->slave_pixmap) {
 			DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
 			bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
 			if (bo == NULL) {
-				DBG(("%s: failed to pin crtc scanout\n"));
+				DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
 				return NULL;
 			}
 
 			if (!get_fb(sna, bo,
 				    sna_crtc->slave_pixmap->drawable.width,
 				    sna_crtc->slave_pixmap->drawable.height)) {
-				DBG(("%s: failed to bind fb for crtc scanout\n"));
+				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
 				return NULL;
 			}
 		} else {
@@ -1921,7 +1952,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 			}
 
 			if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY)) {
-				DBG(("%s: failed to bind fb for crtc scanout\n"));
+				DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
 				return NULL;
 			}
 		}
@@ -1931,7 +1962,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 
 			DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
 			if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
-				DBG(("%s: failed to enable crtc shadow\n"));
+				DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
 				return NULL;
 			}
 
@@ -1965,7 +1996,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 				if (!get_fb(sna, shadow,
 					    region.extents.x2,
 					    region.extents.y2)) {
-					DBG(("%s: failed to bind fb for TearFeee shadow\n"));
+					DBG(("%s: failed to bind fb for TearFeee shadow\n", __FUNCTION__));
 					kgem_bo_destroy(&sna->kgem, shadow);
 					return NULL;
 				}
@@ -2145,6 +2176,8 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
 	uint32_t saved_offset;
 	bool saved_transform;
 
+	DBG(("%s\n", __FUNCTION__));
+
 	saved_bo = sna_crtc->bo;
 	saved_transform = sna_crtc->transform;
 	saved_offset = sna_crtc->offset;
@@ -5169,6 +5202,11 @@ fixup_flip:
 				crtc->bo->active_scanout--;
 				kgem_bo_destroy(&sna->kgem, crtc->bo);
 
+				if (crtc->shadow_bo) {
+					kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+					crtc->shadow_bo = NULL;
+				}
+
 				crtc->bo = kgem_bo_reference(bo);
 				crtc->bo->active_scanout++;
 
@@ -6723,11 +6761,11 @@ void sna_shadow_set_crtc(struct sna *sna,
 	assert(sna_crtc);
 	assert(!sna_crtc->transform);
 
-	if (sna_crtc->shadow_bo != bo) {
-		if (sna_crtc->shadow_bo)
-			kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
+	if (sna_crtc->client_bo != bo) {
+		if (sna_crtc->client_bo)
+			kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
 
-		sna_crtc->shadow_bo = kgem_bo_reference(bo);
+		sna_crtc->client_bo = kgem_bo_reference(bo);
 		sna_crtc_damage(crtc);
 	}
 
@@ -6748,11 +6786,11 @@ void sna_shadow_unset_crtc(struct sna *sna,
 	DBG(("%s: clearin shadow override for CRTC:%d\n",
 	     __FUNCTION__, sna_crtc->id));
 
-	if (sna_crtc->shadow_bo == NULL)
+	if (sna_crtc->client_bo == NULL)
 		return;
 
-	kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
-	sna_crtc->shadow_bo = NULL;
+	kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
+	sna_crtc->client_bo = NULL;
 	list_del(&sna_crtc->shadow_link);
 	sna->mode.shadow_dirty = true;
 
@@ -6884,7 +6922,7 @@ void sna_mode_redisplay(struct sna *sna)
 				damage.extents = crtc->bounds;
 				damage.data = NULL;
 
-				bo = sna_crtc->shadow_bo;
+				bo = sna_crtc->client_bo;
 				if (bo == NULL)
 					bo = kgem_create_2d(&sna->kgem,
 							    crtc->mode.HDisplay,
@@ -6934,7 +6972,7 @@ disable1:
 					}
 
 					kgem_bo_destroy(&sna->kgem, bo);
-					sna_crtc->shadow_bo = NULL;
+					sna_crtc->client_bo = NULL;
 					continue;
 				}
 				sna->mode.flip_active++;
@@ -6945,7 +6983,7 @@ disable1:
 				sna_crtc->flip_bo->active_scanout++;
 				sna_crtc->flip_serial = sna_crtc->mode_serial;
 
-				sna_crtc->shadow_bo = kgem_bo_reference(sna_crtc->bo);
+				sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
 			} else {
 				sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
 				kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
@@ -6992,14 +7030,14 @@ disable1:
 			arg.crtc_id = crtc->id;
 			arg.user_data = (uintptr_t)crtc;
 
-			if (crtc->shadow_bo) {
+			if (crtc->client_bo) {
 				DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
-				     __FUNCTION__, crtc->id, crtc->pipe, crtc->shadow_bo->handle));
-				arg.fb_id = get_fb(sna, crtc->shadow_bo,
+				     __FUNCTION__, crtc->id, crtc->pipe, crtc->client_bo->handle));
+				arg.fb_id = get_fb(sna, crtc->client_bo,
 						   crtc->base->mode.HDisplay,
 						   crtc->base->mode.VDisplay);
 				assert(arg.fb_id != fb);
-				flip_bo = crtc->shadow_bo;
+				flip_bo = crtc->client_bo;
 				x = y = 0;
 			} else {
 				if (fb == 0)
@@ -7047,6 +7085,11 @@ fixup_flip:
 					crtc->bo->active_scanout--;
 					kgem_bo_destroy(&sna->kgem, crtc->bo);
 
+					if (crtc->shadow_bo) {
+						kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+						crtc->shadow_bo = NULL;
+					}
+
 					crtc->bo = kgem_bo_reference(flip_bo);
 					crtc->bo->active_scanout++;
 				} else {
@@ -7152,6 +7195,11 @@ void sna_mode_wakeup(struct sna *sna)
 					crtc->bo->active_scanout--;
 					kgem_bo_destroy(&sna->kgem, crtc->bo);
 
+					if (crtc->shadow_bo) {
+						kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
+						crtc->shadow_bo = NULL;
+					}
+
 					crtc->bo = crtc->flip_bo;
 					crtc->flip_bo = NULL;
 				} else {


More information about the xorg-commit mailing list