xf86-video-intel: src/sna/gen7_render.c src/sna/gen8_render.c src/sna/sna_display.c src/sna/sna_render.h src/sna/sna_video_sprite.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Mar 31 19:42:27 UTC 2016


 src/sna/gen7_render.c      |   34 ++++++++++++++++++++---
 src/sna/gen8_render.c      |   39 +++++++++++++++++++++++----
 src/sna/sna_display.c      |    2 -
 src/sna/sna_render.h       |    2 +
 src/sna/sna_video_sprite.c |   65 ++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 127 insertions(+), 15 deletions(-)

New commits:
commit 2c4890001db18cc0534dd4a1f8d09c5df72c9404
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Mar 31 19:43:07 2016 +0100

    sna/video: Use the GPU to prescale overlay sprites
    
    Since Haswell, we lost the ability to use hardware scalers on the
    overlay planes. Allow Xv clients to pass in unscaled data and use the 3D
    pipe to prescale the images before display.
    
    (I doubt I have the rotations corrected!...)
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 1c420a7..f707d39 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -207,6 +207,12 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_write.g7b"
 };
 
+static const uint32_t ps_kernel_rgb[][4] = {
+#include "exa_wm_src_affine.g7b"
+#include "exa_wm_src_sample_argb.g7b"
+#include "exa_wm_write.g7b"
+};
+
 #define KERNEL(kernel_enum, kernel, num_surfaces) \
     [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces}
 #define NOKERNEL(kernel_enum, func, num_surfaces) \
@@ -216,7 +222,7 @@ static const struct wm_kernel_info {
 	const void *data;
 	unsigned int size;
 	int num_surfaces;
-} wm_kernels[] = {
+} wm_kernels[GEN7_WM_KERNEL_COUNT] = {
 	NOKERNEL(NOMASK, brw_wm_kernel__affine, 2),
 	NOKERNEL(NOMASK_P, brw_wm_kernel__projective, 2),
 
@@ -234,6 +240,7 @@ static const struct wm_kernel_info {
 
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
+	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 };
 #undef KERNEL
 
@@ -1790,7 +1797,9 @@ static void gen7_emit_video_state(struct sna *sna,
 			frame->pitch[0];
 		n_src = 6;
 	} else {
-		if (frame->id == FOURCC_UYVY)
+		if (frame->id == FOURCC_RGB888)
+			src_surf_format = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
+		else if (frame->id == FOURCC_UYVY)
 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY;
 		else
 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL;
@@ -1824,6 +1833,23 @@ static void gen7_emit_video_state(struct sna *sna,
 	gen7_emit_state(sna, op, offset | dirty);
 }
 
+static unsigned select_video_kernel(const struct sna_video_frame *frame)
+{
+	switch (frame->id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+		return GEN7_WM_KERNEL_VIDEO_PLANAR;
+
+	case FOURCC_RGB888:
+	case FOURCC_RGB565:
+		return GEN7_WM_KERNEL_VIDEO_RGB;
+
+	default:
+		return GEN7_WM_KERNEL_VIDEO_PACKED;
+	}
+}
+
 static bool
 gen7_render_video(struct sna *sna,
 		  struct sna_video *video,
@@ -1876,9 +1902,7 @@ gen7_render_video(struct sna *sna,
 		GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
-			       is_planar_fourcc(frame->id) ?
-			       GEN7_WM_KERNEL_VIDEO_PLANAR :
-			       GEN7_WM_KERNEL_VIDEO_PACKED,
+			       select_video_kernel(frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 0631e0a..0947576 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -106,6 +106,12 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_yuv_rgb.g8b"
 #include "exa_wm_write.g8b"
 };
+
+static const uint32_t ps_kernel_rgb[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_argb.g8b"
+#include "exa_wm_write.g8b"
+};
 #endif
 
 #define SURFACE_DW (64 / sizeof(uint32_t));
@@ -119,7 +125,7 @@ static const struct wm_kernel_info {
 	const void *data;
 	unsigned int size;
 	int num_surfaces;
-} wm_kernels[] = {
+} wm_kernels[GEN8_WM_KERNEL_COUNT] = {
 	NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2),
 	NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2),
 
@@ -138,6 +144,7 @@ static const struct wm_kernel_info {
 #if !NO_VIDEO
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
+	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 #endif
 };
 #undef KERNEL
@@ -3733,7 +3740,9 @@ static void gen8_emit_video_state(struct sna *sna,
 			frame->pitch[0];
 		n_src = 6;
 	} else {
-		if (frame->id == FOURCC_UYVY)
+		if (frame->id == FOURCC_RGB888)
+			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
+		else if (frame->id == FOURCC_UYVY)
 			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
 		else
 			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
@@ -3765,6 +3774,23 @@ static void gen8_emit_video_state(struct sna *sna,
 	gen8_emit_state(sna, op, offset);
 }
 
+static unsigned select_video_kernel(const struct sna_video_frame *frame)
+{
+	switch (frame->id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+		return GEN8_WM_KERNEL_VIDEO_PLANAR;
+
+	case FOURCC_RGB888:
+	case FOURCC_RGB565:
+		return GEN8_WM_KERNEL_VIDEO_RGB;
+
+	default:
+		return GEN8_WM_KERNEL_VIDEO_PACKED;
+	}
+}
+
 static bool
 gen8_render_video(struct sna *sna,
 		  struct sna_video *video,
@@ -3811,6 +3837,11 @@ gen8_render_video(struct sna *sna,
 	tmp.floats_per_vertex = 3;
 	tmp.floats_per_rect = 9;
 
+	DBG(("%s: scaling?=%d, planar?=%d [%x]\n",
+	     __FUNCTION__,
+	     src_width != dst_width || src_height != dst_height,
+	     is_planar_fourcc(frame->id), frame->id));
+
 	if (src_width == dst_width && src_height == dst_height)
 		filter = SAMPLER_FILTER_NEAREST;
 	else
@@ -3820,9 +3851,7 @@ gen8_render_video(struct sna *sna,
 		GEN8_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
-			       is_planar_fourcc(frame->id) ?
-			       GEN8_WM_KERNEL_VIDEO_PLANAR :
-			       GEN8_WM_KERNEL_VIDEO_PACKED,
+			       select_video_kernel(frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 6ceb515..6cb10e6 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -166,7 +166,7 @@ struct local_mode_get_plane_res {
 };
 #define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
 
-#if 0
+#if 1
 #define __DBG DBG
 #else
 #define __DBG(x)
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 1baf945..fa1ca8e 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -484,6 +484,7 @@ enum {
 
 	GEN7_WM_KERNEL_VIDEO_PLANAR,
 	GEN7_WM_KERNEL_VIDEO_PACKED,
+	GEN7_WM_KERNEL_VIDEO_RGB,
 	GEN7_WM_KERNEL_COUNT
 };
 
@@ -536,6 +537,7 @@ enum {
 
 	GEN8_WM_KERNEL_VIDEO_PLANAR,
 	GEN8_WM_KERNEL_VIDEO_PACKED,
+	GEN8_WM_KERNEL_VIDEO_RGB,
 	GEN8_WM_KERNEL_COUNT
 };
 
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index ae08ef7..1498707 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -151,7 +151,7 @@ static int sna_video_sprite_best_size(ddQueryBestSize_ARGS)
 	struct sna_video *video = port->devPriv.ptr;
 	struct sna *sna = video->sna;
 
-	if (sna->kgem.gen >= 075) {
+	if (sna->kgem.gen >= 075 && !sna->render.video) {
 		*p_w = vid_w;
 		*p_h = vid_h;
 	} else {
@@ -407,6 +407,7 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
 		BoxRec dst;
 		RegionRec reg;
 		Rotation rotation;
+		bool cache_bo;
 
 		pipe = sna_crtc_pipe(crtc);
 
@@ -491,6 +492,8 @@ off:
 			frame.image.y1 = 0;
 			frame.image.x2 = frame.width;
 			frame.image.y2 = frame.height;
+
+			cache_bo = false;
 		} else {
 			frame.bo = sna_video_buffer(video, &frame);
 			if (frame.bo == NULL) {
@@ -504,6 +507,60 @@ off:
 				ret = BadAlloc;
 				goto err;
 			}
+
+			cache_bo = true;
+		}
+
+		if (sna->kgem.gen >= 075 && sna->render.video &&
+		    !((frame.src.x2 - frame.src.x1) == (dst.x2 - dst.x1) &&
+		      (frame.src.y2 - frame.src.y1) == (dst.y2 - dst.y1))) {
+			ScreenPtr screen = to_screen_from_sna(sna);
+			PixmapPtr scaled;
+			RegionRec r;
+
+			r.extents.x1 = r.extents.y1 = 0;
+			r.extents.x2 = dst.x2 - dst.x1;
+			r.extents.y2 = dst.y2 - dst.y1;
+			r.data = NULL;
+
+			DBG(("%s: scaling from (%d, %d) to (%d, %d)\n",
+			     __FUNCTION__,
+			     frame.src.x2 - frame.src.x1,
+			     frame.src.y2 - frame.src.y1,
+			     r.extents.x2, r.extents.y2));
+
+			scaled = screen->CreatePixmap(screen,
+						      r.extents.x2,
+						      r.extents.y2,
+						      24,
+						      CREATE_PIXMAP_USAGE_SCRATCH);
+			if (scaled == NULL) {
+				ret = BadAlloc;
+				goto err;
+			}
+
+			if (!sna->render.video(sna, video, &frame, &r, scaled)) {
+				screen->DestroyPixmap(scaled);
+				ret = BadAlloc;
+				goto err;
+			}
+
+			if (cache_bo)
+				sna_video_buffer_fini(video);
+			else
+				kgem_bo_destroy(&sna->kgem, frame.bo);
+
+			frame.bo = kgem_bo_reference(__sna_pixmap_get_bo(scaled));
+			kgem_bo_submit(&sna->kgem, frame.bo);
+
+			frame.id = FOURCC_RGB888;
+			frame.src = frame.image = r.extents;
+			frame.width = frame.image.x2;
+			frame.height = frame.image.y2;
+			frame.pitch[0] = frame.bo->pitch;
+
+			screen->DestroyPixmap(scaled);
+			cache_bo = false;
 		}
 
 		ret = Success;
@@ -513,10 +570,10 @@ off:
 		}
 
 		frame.bo->domain = DOMAIN_NONE;
-		if (xvmc_passthrough(format->id))
-			kgem_bo_destroy(&sna->kgem, frame.bo);
-		else
+		if (cache_bo)
 			sna_video_buffer_fini(video);
+		else
+			kgem_bo_destroy(&sna->kgem, frame.bo);
 
 		if (ret != Success)
 			goto err;


More information about the xorg-commit mailing list