xf86-video-intel: 7 commits - src/sna/gen6_render.c src/sna/gen7_render.c src/sna/gen8_render.c src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c src/sna/sna_display.c src/sna/sna_render.h src/uxa/intel_display.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 31 15:18:31 PDT 2015


 src/sna/gen6_render.c   |    7 +++
 src/sna/gen7_render.c   |    9 +++-
 src/sna/gen8_render.c   |   11 ++++-
 src/sna/kgem.c          |   21 +++-------
 src/sna/kgem.h          |    5 ++
 src/sna/sna_accel.c     |   96 ++++++++++++++++++++++++++++++++++--------------
 src/sna/sna_display.c   |   42 +++++++++++++++++++++
 src/sna/sna_render.h    |    1 
 src/uxa/intel_display.c |   43 +++++++++++++++++++++
 9 files changed, 187 insertions(+), 48 deletions(-)

New commits:
commit 61f8dcdfa5972cfd918fc60504345482fedd1a65
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 22:08:55 2015 +0100

    sna: Consider idleness of both rings if we need a semaphore
    
    When emitting batches early for improved GPU/CPU concurrency, we only
    want to do so if the target ring is not busy. However, if the batch
    requires a semaphore, we also need to consider the other ring as well.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 51072e2..f1042a0 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -344,6 +344,11 @@ static inline bool kgem_ring_is_idle(struct kgem *kgem, int ring)
 {
 	ring = ring == KGEM_BLT;
 
+	if (kgem->needs_semaphore &&
+	    !list_is_empty(&kgem->requests[!ring]) &&
+	    !__kgem_ring_is_idle(kgem, !ring))
+		return false;
+
 	if (list_is_empty(&kgem->requests[ring]))
 		return true;
 
commit 56f9d2c1d9770437e82f07f5a40b52940a2e8ef7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 15:34:16 2015 +0100

    sna: Flush BLT operations to an idle GPU
    
    We improve dispatch latency if after creating a command buffer we
    immediately submit if the GPU is idle. This improves concurrency as we
    continue to build the next command buffer as the GPU executes and helps
    prevent needlessly using one engine for too long (i.e. sometimes we may
    be able to execute the work much early and do the ring switch cheaply).
    
    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 0bd3bb6..9b84d5c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -5228,6 +5228,16 @@ static inline uint8_t blt_depth(int depth)
 	}
 }
 
+inline static void blt_done(struct sna *sna)
+{
+	sna->blt_state.fill_bo = 0;
+	if (sna->kgem.nbatch && __kgem_ring_empty(&sna->kgem)) {
+		DBG(("%s: flushing BLT operation on empty ring\n",
+		     __FUNCTION__));
+		_kgem_submit(&sna->kgem);
+	}
+}
+
 static bool
 sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 		     int x, int y, int w, int  h, char *bits)
@@ -5387,7 +5397,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 		box++;
 	} while (--n);
 
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -5565,7 +5575,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 		} while (--n);
 	}
 
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -8467,7 +8477,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
 		sna_damage_add_to_pixmap(arg->damage, region, pixmap);
 	}
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 }
 
 static void
@@ -8700,7 +8710,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
 		sna_damage_add_to_pixmap(arg->damage, region, dst_pixmap);
 	}
 	assert_pixmap_damage(dst_pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 }
 
 static RegionPtr
@@ -12661,7 +12671,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
 	}
 done:
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -13508,7 +13518,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
 	}
 
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -14153,7 +14163,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
 		}
 	}
 
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -14615,7 +14625,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
 	}
 
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -14762,7 +14772,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
 	assert_pixmap_damage(pixmap);
 	if (tile)
 		kgem_bo_destroy(&sna->kgem, tile);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -15568,7 +15578,7 @@ skip:
 	}
 
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -16318,7 +16328,7 @@ skip:
 	}
 
 	assert_pixmap_damage(pixmap);
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
@@ -16653,7 +16663,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
 		box++;
 	} while (--n);
 
-	sna->blt_state.fill_bo = 0;
+	blt_done(sna);
 	return true;
 }
 
commit 68632e100034ae7cf3086a85f5d6f38cd9a94adc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 15:01:10 2015 +0100

    sna: Use more explicit retire-requests after syncing
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 63eda3a..4565f24 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -299,6 +299,7 @@ static void assert_bo_retired(struct kgem_bo *bo)
 	assert(bo->refcnt);
 	assert(bo->rq == NULL);
 	assert(bo->exec == NULL);
+	assert(!bo->needs_flush);
 	assert(list_is_empty(&bo->request));
 }
 #else
@@ -639,16 +640,10 @@ static void kgem_bo_retire(struct kgem *kgem, struct kgem_bo *bo)
 	assert(bo->exec == NULL);
 	assert(list_is_empty(&bo->vma));
 
-	if (bo->rq) {
-		__kgem_bo_clear_busy(bo);
-		kgem_retire(kgem);
-		assert_bo_retired(bo);
-	} else {
-		assert(bo->exec == NULL);
-		assert(list_is_empty(&bo->request));
-		assert(!bo->needs_flush);
-		ASSERT_IDLE(kgem, bo->handle);
-	}
+	if (bo->rq)
+		__kgem_retire_requests_upto(kgem, bo);
+	ASSERT_IDLE(kgem, bo->handle);
+	assert_bo_retired(bo);
 }
 
 static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
@@ -660,10 +655,8 @@ static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
 	assert(list_is_empty(&bo->vma));
 
 	if (bo->rq) {
-		if (!__kgem_busy(kgem, bo->handle)) {
-			__kgem_bo_clear_busy(bo);
-			kgem_retire(kgem);
-		}
+		if (!__kgem_busy(kgem, bo->handle))
+			__kgem_retire_requests_upto(kgem, bo);
 	} else {
 		assert(!bo->needs_flush);
 		ASSERT_IDLE(kgem, bo->handle);
commit 8b358076f2b2d6a6d69e7511735316dc51dd9ec5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 12:58:19 2015 +0100

    sna: Query the engine residency on foreign bo before use
    
    Since knowing which ring the bo is currently active on is important when
    considering the impact of semaphores on the next operation, be sure to
    query it on foreign bo before we use them.
    
    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 b6510e7..0bd3bb6 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -52,6 +52,7 @@
 
 #include <sys/time.h>
 #include <sys/mman.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
 
 #ifdef HAVE_VALGRIND
@@ -3270,6 +3271,35 @@ __sna_pixmap_for_gpu(struct sna *sna, PixmapPtr pixmap, unsigned flags)
 	return priv;
 }
 
+inline static void sna_pixmap_unclean(struct sna *sna, struct sna_pixmap *priv)
+{
+	struct drm_i915_gem_busy busy;
+
+	assert(DAMAGE_IS_ALL(priv->gpu_damage));
+	assert(priv->gpu_bo);
+	assert(priv->gpu_bo->proxy == NULL);
+	assert_pixmap_map(priv->pixmap, priv);
+
+	sna_damage_destroy(&priv->cpu_damage);
+	list_del(&priv->flush_list);
+
+	if ((priv->gpu_bo->needs_flush & priv->flush) == 0 ||
+	    priv->gpu_bo->exec == NULL)
+		return;
+
+	busy.handle = priv->gpu_bo->handle;
+	busy.busy = 0;
+	ioctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
+
+	if (busy.busy) {
+		unsigned mode = KGEM_RENDER;
+		if (busy.busy & (0xfffe << 16))
+			mode = KGEM_BLT;
+		kgem_bo_mark_busy(&sna->kgem, priv->gpu_bo, mode);
+	} else
+		__kgem_bo_clear_busy(priv->gpu_bo);
+}
+
 struct sna_pixmap *
 sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags)
 {
@@ -3347,10 +3377,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 	if (sna_damage_is_all(&priv->gpu_damage,
 			      pixmap->drawable.width,
 			      pixmap->drawable.height)) {
-		assert(priv->gpu_bo);
-		assert(priv->gpu_bo->proxy == NULL);
-		sna_damage_destroy(&priv->cpu_damage);
-		list_del(&priv->flush_list);
+		DBG(("%s: already all-damaged\n", __FUNCTION__));
+		sna_pixmap_unclean(sna, priv);
 		goto done;
 	}
 
@@ -4168,12 +4196,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 			      pixmap->drawable.width,
 			      pixmap->drawable.height)) {
 		DBG(("%s: already all-damaged\n", __FUNCTION__));
-		assert(DAMAGE_IS_ALL(priv->gpu_damage));
-		assert(priv->gpu_bo);
-		assert(priv->gpu_bo->proxy == NULL);
-		assert_pixmap_map(pixmap, priv);
-		sna_damage_destroy(&priv->cpu_damage);
-		list_del(&priv->flush_list);
+		sna_pixmap_unclean(sna, priv);
 		goto active;
 	}
 
commit ef24cb1b223486d7dfe57f33c28d8692f9857c98
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 11:58:26 2015 +0100

    sna/gen6+: Prefer the BLT for small copies
    
    Even on GT3, it is preferrential to use the blitter if the copy is small
    (due to the latency in execution).
    
    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 750881a..b6510e7 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -6544,7 +6544,7 @@ discard_cow:
 			if (!sna->render.copy_boxes(sna, alu,
 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
 						    &dst_pixmap->drawable, bo, 0, 0,
-						    box, n, 0)) {
+						    box, n, small_copy(region))) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -6581,7 +6581,7 @@ discard_cow:
 			if (!sna->render.copy_boxes(sna, alu,
 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
 						    &dst_pixmap->drawable, bo, 0, 0,
-						    box, n, 0)) {
+						    box, n, small_copy(region))) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -6624,7 +6624,7 @@ discard_cow:
 			if (!sna->render.copy_boxes(sna, alu,
 						    &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)) {
+						    box, n, small_copy(region) | (src_priv->shm ? COPY_LAST : 0))) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -6676,8 +6676,7 @@ discard_cow:
 				ok = sna->render.copy_boxes(sna, alu,
 							    &src_pixmap->drawable, src_bo, src_dx, src_dy,
 							    &dst_pixmap->drawable, bo, 0, 0,
-							    box, n, COPY_LAST);
-
+							    box, n, small_copy(region) |  COPY_LAST);
 				kgem_bo_sync__cpu(&sna->kgem, src_bo);
 				assert(src_bo->rq == NULL);
 				kgem_bo_destroy(&sna->kgem, src_bo);
commit 5a872056de61ca8724d5d476783c4dcc8c1a6af7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 11:58:26 2015 +0100

    sna/gen6+: Prefer the BLT for small self-copies
    
    Even on GT3, it is preferrential to use the blitter if the copy is small
    (due to the latency in execution).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 2afe5ee..afebab4 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -1991,6 +1991,10 @@ try_blt(struct sna *sna,
 	if (bo->rq)
 		return RQ_IS_BLT(bo->rq);
 
+	if (src->pDrawable == dst->pDrawable &&
+	    can_switch_to_blt(sna, bo, 0))
+		return true;
+
 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
 		return true;
 
@@ -2680,7 +2684,8 @@ static inline bool prefer_blt_copy(struct sna *sna,
 	if (sna->kgem.ring == KGEM_BLT)
 		return true;
 
-	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
+	if ((flags & COPY_SMALL || src_bo == dst_bo) &&
+	    can_switch_to_blt(sna, dst_bo, flags))
 		return true;
 
 	if (untiled_tlb_miss(src_bo) ||
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index e8e14b5..8780786 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2210,6 +2210,11 @@ try_blt(struct sna *sna,
 	if (bo->rq)
 		return RQ_IS_BLT(bo->rq);
 
+	if (src->pDrawable == dst->pDrawable &&
+	    (sna->render_state.gt < 3 || width*height < 1024) &&
+	    can_switch_to_blt(sna, bo, 0))
+		return true;
+
 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
 		return true;
 
@@ -2888,8 +2893,8 @@ prefer_blt_copy(struct sna *sna,
 	if (force_blt_ring(sna))
 		return true;
 
-        if (sna->render_state.gt < 3 &&
-            src_bo == dst_bo &&
+	if ((flags & COPY_SMALL ||
+	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
             can_switch_to_blt(sna, dst_bo, flags))
 		return true;
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index b5a4895..043e268 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -2031,6 +2031,11 @@ try_blt(struct sna *sna,
 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
 		return true;
 
+	if (src->pDrawable == dst->pDrawable &&
+	    (sna->render_state.gt < 3 || width*height < 1024) &&
+	    can_switch_to_blt(sna, bo, 0))
+		return true;
+
 	if (src->pDrawable) {
 		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
 		if (s == NULL)
@@ -2711,9 +2716,9 @@ prefer_blt_copy(struct sna *sna,
 	if (force_blt_ring(sna))
 		return true;
 
-        if (sna->render_state.gt < 3 &&
-            src_bo == dst_bo &&
-            can_switch_to_blt(sna, dst_bo, flags))
+	if ((flags & COPY_SMALL ||
+	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
+	    can_switch_to_blt(sna, dst_bo, flags))
 		return true;
 
 	if (kgem_bo_is_render(dst_bo) ||
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index eda4c33..750881a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1081,6 +1081,14 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 	return pixmap;
 }
 
+static unsigned small_copy(const RegionRec *region)
+{
+	if ((region->extents.x2 - region->extents.x1)*(region->extents.y2 - region->extents.y1) < 1024)
+		return COPY_SMALL;
+
+	return 0;
+}
+
 #ifdef CREATE_PIXMAP_USAGE_SHARED
 static Bool
 sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
@@ -5862,7 +5870,7 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 		if (!sna->render.copy_boxes(sna, alu,
 					    &pixmap->drawable, priv->gpu_bo, sx, sy,
 					    &pixmap->drawable, priv->gpu_bo, tx, ty,
-					    box, n, 0)) {
+					    box, n, small_copy(region))) {
 			DBG(("%s: fallback - accelerated copy boxes failed\n",
 			     __FUNCTION__));
 			goto fallback;
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 6e1fa48..dcc0ddd 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -286,6 +286,7 @@ struct sna_render {
 #define COPY_LAST 0x1
 #define COPY_SYNC 0x2
 #define COPY_NO_OVERLAP 0x4
+#define COPY_SMALL 0x8
 
 	bool (*copy)(struct sna *sna, uint8_t alu,
 		     PixmapPtr src, struct kgem_bo *src_bo,
commit 1be5b715827ef2bbc75ef795c301a1a7ba6e5f09
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 09:59:58 2015 +0100

    Add TILE property support (for MST tiled monitors)
    
    Based on the patch for modesetting (and lots of work) by Dave Airlie
    
    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 633133d..f0cf481 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3185,6 +3185,47 @@ done:
 	}
 }
 
+static void
+sna_output_attach_tile(xf86OutputPtr output)
+{
+#if XF86_OUTPUT_VERSION >= 3
+	struct sna *sna = to_sna(output->scrn);
+	struct sna_output *sna_output = output->driver_private;
+	struct drm_mode_get_blob blob;
+	struct xf86CrtcTileInfo tile_info, *set = NULL;
+	char *tile;
+	int id;
+
+	id = find_property(sna, sna_output, "TILE");
+	DBG(("%s: found? TILE=%d\n", __FUNCTION__, id));
+	if (id == -1)
+		goto out;
+
+	VG_CLEAR(blob);
+	blob.blob_id = sna_output->prop_values[id];
+	blob.length = 0;
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+		goto out;
+
+	do {
+		id = blob.length;
+		tile = alloca(id + 1);
+		blob.data = (uintptr_t)tile;
+		VG(memset(tile, 0, id));
+		DBG(("%s: reading %d bytes for TILE blob\n", __FUNCTION__, id));
+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+			goto out;
+	} while (id != blob.length);
+
+	tile[blob.length] = '\0'; /* paranoia */
+	DBG(("%s: TILE='%s'\n", __FUNCTION__, tile));
+	if (xf86OutputParseKMSTile(tile, blob.length, &tile_info))
+		set = &tile_info;
+out:
+	xf86OutputSetTile(output, set);
+#endif
+}
+
 static bool duplicate_mode(DisplayModePtr modes, DisplayModePtr m)
 {
 	if (m == NULL)
@@ -3281,6 +3322,7 @@ sna_output_get_modes(xf86OutputPtr output)
 	assert(sna_output->id);
 
 	sna_output_attach_edid(output);
+	sna_output_attach_tile(output);
 
 	if (output->crtc) {
 		struct drm_mode_crtc mode;
diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 544382a..a95b3de 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -868,6 +868,48 @@ intel_output_attach_edid(xf86OutputPtr output)
 	xf86OutputSetEDID(output, mon);
 }
 
+static void
+intel_output_attach_tile(xf86OutputPtr output)
+{
+#if XF86_OUTPUT_VERSION >= 3
+	struct intel_output *intel_output = output->driver_private;
+	drmModeConnectorPtr koutput = intel_output->mode_output;
+	struct intel_mode *mode = intel_output->mode;
+	drmModePropertyBlobPtr blob = NULL;
+	struct xf86CrtcTileInfo tile_info, *set = NULL;
+	int i;
+
+	for (i = 0; koutput && i < koutput->count_props; i++) {
+		drmModePropertyPtr props;
+
+		props = drmModeGetProperty(mode->fd, koutput->props[i]);
+		if (!props)
+			continue;
+
+		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
+			drmModeFreeProperty(props);
+			continue;
+		}
+
+		if (!strcmp(props->name, "TILE")) {
+			blob = drmModeGetPropertyBlob(mode->fd,
+						      koutput->prop_values[i]);
+		}
+		drmModeFreeProperty(props);
+	}
+
+	if (blob) {
+		if (xf86OutputParseKMSTile(blob->data,
+					   blob->length,
+					   &tile_info))
+			set = &tile_info;
+		drmModeFreePropertyBlob(blob);
+	}
+
+	xf86OutputSetTile(output, set);
+#endif
+}
+
 static DisplayModePtr
 intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
 {
@@ -923,6 +965,7 @@ intel_output_get_modes(xf86OutputPtr output)
 	int i;
 
 	intel_output_attach_edid(output);
+	intel_output_attach_tile(output);
 
 	if (!koutput)
 		return Modes;


More information about the xorg-commit mailing list