xf86-video-intel: 8 commits - src/render_program/exa_wm_sample_nv12.g4i src/render_program/exa_wm_src_sample_nv12.g4a src/render_program/exa_wm_src_sample_nv12.g4b src/render_program/exa_wm_src_sample_nv12.g4b.gen5 src/render_program/exa_wm_src_sample_nv12.g5a src/render_program/exa_wm_src_sample_nv12.g5b src/render_program/exa_wm_src_sample_nv12.g6a src/render_program/exa_wm_src_sample_nv12.g6b src/render_program/exa_wm_src_sample_nv12.g7a src/render_program/exa_wm_src_sample_nv12.g7b src/render_program/exa_wm_src_sample_nv12.g8a src/render_program/exa_wm_src_sample_nv12.g8b src/render_program/Makefile.am src/sna/gen4_render.c src/sna/gen4_render.h src/sna/gen5_render.c src/sna/gen5_render.h src/sna/gen6_render.c src/sna/gen7_render.c src/sna/gen8_render.c src/sna/gen9_render.c src/sna/kgem.c src/sna/sna_display.c src/sna/sna_render.h src/sna/sna_video.c src/sna/sna_video.h src/sna/sna_video_textured.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 27 18:03:32 UTC 2017


 src/render_program/Makefile.am                     |   12 +
 src/render_program/exa_wm_sample_nv12.g4i          |   66 +++++++++
 src/render_program/exa_wm_src_sample_nv12.g4a      |   32 ++++
 src/render_program/exa_wm_src_sample_nv12.g4b      |    7 +
 src/render_program/exa_wm_src_sample_nv12.g4b.gen5 |    7 +
 src/render_program/exa_wm_src_sample_nv12.g5a      |    1 
 src/render_program/exa_wm_src_sample_nv12.g5b      |    7 +
 src/render_program/exa_wm_src_sample_nv12.g6a      |    1 
 src/render_program/exa_wm_src_sample_nv12.g6b      |    7 +
 src/render_program/exa_wm_src_sample_nv12.g7a      |   38 +++++
 src/render_program/exa_wm_src_sample_nv12.g7b      |    7 +
 src/render_program/exa_wm_src_sample_nv12.g8a      |    1 
 src/render_program/exa_wm_src_sample_nv12.g8b      |    7 +
 src/sna/gen4_render.c                              |   43 ++++--
 src/sna/gen4_render.h                              |    1 
 src/sna/gen5_render.c                              |   43 ++++--
 src/sna/gen5_render.h                              |    1 
 src/sna/gen6_render.c                              |   43 ++++--
 src/sna/gen7_render.c                              |   46 ++++--
 src/sna/gen8_render.c                              |   43 ++++--
 src/sna/gen9_render.c                              |   46 ++++--
 src/sna/kgem.c                                     |    4 
 src/sna/sna_display.c                              |    2 
 src/sna/sna_render.h                               |    4 
 src/sna/sna_video.c                                |  146 +++++++++++++++++++--
 src/sna/sna_video.h                                |   21 +++
 src/sna/sna_video_textured.c                       |   28 +++-
 27 files changed, 562 insertions(+), 102 deletions(-)

New commits:
commit 291fdcdc09420d8e422617070731eb3da3d55b44
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 18:15:11 2017 +0300

    sna/video: Expose NV12 support for the textured Xv adaptor on gen4+
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h
index bb963e7f..6b1c864c 100644
--- a/src/sna/sna_video.h
+++ b/src/sna/sna_video.h
@@ -70,6 +70,15 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 	XvTopToBottom \
 }
 
+/* no standard define for this */
+#define XVIMAGE_NV12 { \
+	FOURCC_NV12, XvYUV, LSBFirst,				\
+	{'N','V','1','2', 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+	12, XvPlanar, 2, 0, 0, 0, 0, 8, 8, 8, 1, 2, 2, 1, 2, 2, \
+	{'Y','U','V', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
+	XvTopToBottom \
+}
+
 struct sna_video {
 	struct sna *sna;
 
diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
index 3cce5cf1..bcd42320 100644
--- a/src/sna/sna_video_textured.c
+++ b/src/sna/sna_video_textured.c
@@ -61,6 +61,15 @@ static const XvImageRec gen3_Images[] = {
 	XVMC_YUV,
 };
 
+static const XvImageRec gen4_Images[] = {
+	XVIMAGE_YUY2,
+	XVIMAGE_YV12,
+	XVIMAGE_I420,
+	XVIMAGE_NV12,
+	XVIMAGE_UYVY,
+	XVMC_YUV,
+};
+
 static int sna_video_textured_stop(ddStopVideo_ARGS)
 {
 	struct sna_video *video = port->devPriv.ptr;
@@ -298,6 +307,20 @@ sna_video_textured_query(ddQueryImageAttributes_ARGS)
 			offsets[2] = size;
 		size += tmp;
 		break;
+	case FOURCC_NV12:
+		*h = (*h + 1) & ~1;
+		size = (*w + 3) & ~3;
+		if (pitches)
+			pitches[0] = size;
+		size *= *h;
+		if (offsets)
+			offsets[1] = size;
+		tmp = (*w + 3) & ~3;
+		if (pitches)
+			pitches[1] = tmp;
+		tmp *= (*h >> 1);
+		size += tmp;
+		break;
 	case FOURCC_UYVY:
 	case FOURCC_YUY2:
 	default:
@@ -374,9 +397,12 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
 	if (sna->kgem.gen < 030) {
 		adaptor->nImages = ARRAY_SIZE(gen2_Images);
 		adaptor->pImages = (XvImageRec *)gen2_Images;
-	} else {
+	} else if (sna->kgem.gen < 040) {
 		adaptor->nImages = ARRAY_SIZE(gen3_Images);
 		adaptor->pImages = (XvImageRec *)gen3_Images;
+	} else {
+		adaptor->nImages = ARRAY_SIZE(gen4_Images);
+		adaptor->pImages = (XvImageRec *)gen4_Images;
 	}
 #if XORG_XV_VERSION < 2
 	adaptor->ddAllocatePort = sna_xv_alloc_port;
commit 8906d8b0e2767c91e54c89434c6229944c6c7ab0
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 18:06:39 2017 +0300

    sna/video: Add NV12 video copy funcs
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c
index e2b11c31..55405f81 100644
--- a/src/sna/sna_video.c
+++ b/src/sna/sna_video.c
@@ -233,7 +233,29 @@ sna_video_frame_set_rotation(struct sna_video *video,
 	/* Determine the desired destination pitch (representing the
 	 * chroma's pitch in the planar case).
 	 */
-	if (is_planar_fourcc(frame->id)) {
+	if (is_nv12_fourcc(frame->id)) {
+		assert((width & 1) == 0);
+		assert((height & 1) == 0);
+		if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+			frame->pitch[0] = ALIGN(height, align);
+			frame->pitch[1] = ALIGN(height, align);
+			frame->size = width * frame->pitch[1] +
+				width / 2 * frame->pitch[0];
+		} else {
+			frame->pitch[0] = ALIGN(width, align);
+			frame->pitch[1] = ALIGN(width, align);
+			frame->size = height * frame->pitch[1] +
+				height / 2 * frame->pitch[0];
+		}
+
+		if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+			frame->UBufOffset = (int)frame->pitch[1] * width;
+			frame->VBufOffset = frame->UBufOffset;
+		} else {
+			frame->UBufOffset = (int)frame->pitch[1] * height;
+			frame->VBufOffset = frame->UBufOffset;
+		}
+	} else if (is_planar_fourcc(frame->id)) {
 		assert((width & 1) == 0);
 		assert((height & 1) == 0);
 		if (rotation & (RR_Rotate_90 | RR_Rotate_270)) {
@@ -297,6 +319,78 @@ sna_video_frame_set_rotation(struct sna_video *video,
 	assert(frame->size);
 }
 
+static void plane_dims(const struct sna_video_frame *frame, int sub,
+		       int *x, int *y, int *w, int *h)
+{
+	*x = frame->image.x1;
+	*y = frame->image.y1;
+	*w = frame->image.x2 - frame->image.x1;
+	*h = frame->image.y2 - frame->image.y1;
+
+	if (sub) {
+		*x >>= 1; *w >>= 1;
+		*y >>= 1; *h >>= 1;
+	}
+}
+
+static void sna_memcpy_cbcr_plane(struct sna_video *video,
+				  uint16_t *dst, const uint16_t *src,
+				  const struct sna_video_frame *frame)
+{
+	int dstPitch = frame->pitch[0] >> 1, srcPitch;
+	const uint16_t *s;
+	int i, j = 0;
+	int x, y, w, h;
+
+	plane_dims(frame, 1, &x, &y, &w, &h);
+
+	srcPitch = ALIGN((frame->width >> 1), 2);
+
+	src += y * srcPitch + x;
+	if (!video->textured)
+		x = y = 0;
+
+	switch (frame->rotation) {
+	case RR_Rotate_0:
+		dst += y * dstPitch + x;
+		if (srcPitch == dstPitch && srcPitch == w)
+			memcpy(dst, src, (srcPitch * h) << 1);
+		else while (h--) {
+			memcpy(dst, src, w << 1);
+			src += srcPitch;
+			dst += dstPitch;
+		}
+		break;
+	case RR_Rotate_90:
+		for (i = 0; i < h; i++) {
+			s = src;
+			for (j = 0; j < w; j++)
+				dst[i + ((x + w - j - 1) * dstPitch)] = *s++;
+			src += srcPitch;
+		}
+		break;
+	case RR_Rotate_180:
+		for (i = 0; i < h; i++) {
+			s = src;
+			for (j = 0; j < w; j++) {
+				dst[(x + w - j - 1) +
+				    ((h - i - 1) * dstPitch)] = *s++;
+			}
+			src += srcPitch;
+		}
+		break;
+	case RR_Rotate_270:
+		for (i = 0; i < h; i++) {
+			s = src;
+			for (j = 0; j < w; j++) {
+				dst[(h - i - 1) + (x + j * dstPitch)] = *s++;
+			}
+			src += srcPitch;
+		}
+		break;
+	}
+}
+
 static void sna_memcpy_plane(struct sna_video *video,
 			     uint8_t *dst, const uint8_t *src,
 			     const struct sna_video_frame *frame, int sub)
@@ -306,15 +400,11 @@ static void sna_memcpy_plane(struct sna_video *video,
 	int i, j = 0;
 	int x, y, w, h;
 
-	x = frame->image.x1;
-	y = frame->image.y1;
-	w = frame->image.x2 - frame->image.x1;
-	h = frame->image.y2 - frame->image.y1;
-	if (sub) {
-		x >>= 1; w >>= 1;
-		y >>= 1; h >>= 1;
+	plane_dims(frame, sub, &x, &y, &w, &h);
+
+	if (sub)
 		srcPitch = ALIGN((frame->width >> 1), 4);
-	} else
+	else
 		srcPitch = ALIGN(frame->width, 4);
 
 	src += y * srcPitch + x;
@@ -363,6 +453,17 @@ static void sna_memcpy_plane(struct sna_video *video,
 }
 
 static void
+sna_copy_nv12_data(struct sna_video *video,
+		   const struct sna_video_frame *frame,
+		   const uint8_t *src, uint8_t *dst)
+{
+	sna_memcpy_plane(video, dst, src, frame, 0);
+	src += frame->height * ALIGN(frame->width, 4);
+	dst += frame->UBufOffset;
+	sna_memcpy_cbcr_plane(video, (void*)dst, (void*)src, frame);
+}
+
+static void
 sna_copy_planar_data(struct sna_video *video,
 		     const struct sna_video_frame *frame,
 		     const uint8_t *src, uint8_t *dst)
@@ -506,7 +607,28 @@ sna_video_copy_data(struct sna_video *video,
 	if (frame->rotation == RR_Rotate_0 && !video->tiled) {
 		DBG(("%s: unrotated, untiled fast paths: is-planar?=%d\n",
 		     __FUNCTION__, is_planar_fourcc(frame->id)));
-		if (is_planar_fourcc(frame->id)) {
+		if (is_nv12_fourcc(frame->id)) {
+			int w = frame->image.x2 - frame->image.x1;
+			int h = frame->image.y2 - frame->image.y1;
+			if (ALIGN(h, 2) == frame->height &&
+			    ALIGN(w, 4) == frame->pitch[0] &&
+			    ALIGN(w, 4) == frame->pitch[1]) {
+				if (frame->bo) {
+					if (!kgem_bo_write(&video->sna->kgem, frame->bo,
+							   buf, frame->size))
+						goto use_gtt;
+				} else {
+					frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size,
+								       KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE,
+								       (void **)&dst);
+					if (frame->bo == NULL)
+						return false;
+
+					memcpy(dst, buf, frame->size);
+				}
+				return true;
+			}
+		} else if (is_planar_fourcc(frame->id)) {
 			int w = frame->image.x2 - frame->image.x1;
 			int h = frame->image.y2 - frame->image.y1;
 			if (ALIGN(h, 2) == frame->height &&
@@ -583,7 +705,9 @@ use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */
 			return false;
 	}
 
-	if (is_planar_fourcc(frame->id))
+	if (is_nv12_fourcc(frame->id))
+		sna_copy_nv12_data(video, frame, buf, dst);
+	else if (is_planar_fourcc(frame->id))
 		sna_copy_planar_data(video, frame, buf, dst);
 	else
 		sna_copy_packed_data(video, frame, buf, dst);
commit 27d58e4b37ad775c325c497fd206f8b1b02af921
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 03:53:46 2017 +0300

    sna/video: Add support for NV12 video in all gen4+ render paths
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 72a98aee..84529994 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -115,6 +115,14 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_write.g4b"
 };
 
+static const uint32_t ps_kernel_nv12_static[][4] = {
+#include "exa_wm_xy.g4b"
+#include "exa_wm_src_affine.g4b"
+#include "exa_wm_src_sample_nv12.g4b"
+#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_write.g4b"
+};
+
 #define NOKERNEL(kernel_enum, func, masked) \
     [kernel_enum] = {func, 0, masked}
 #define KERNEL(kernel_enum, kernel, masked) \
@@ -140,6 +148,7 @@ static const struct wm_kernel_info {
 	NOKERNEL(WM_KERNEL_OPACITY_P, brw_wm_kernel__projective_opacity, true),
 
 	KERNEL(WM_KERNEL_VIDEO_PLANAR, ps_kernel_planar_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12, ps_kernel_nv12_static, false),
 	KERNEL(WM_KERNEL_VIDEO_PACKED, ps_kernel_packed_static, false),
 };
 #undef KERNEL
@@ -1324,7 +1333,7 @@ static void gen4_video_bind_surfaces(struct sna *sna,
 				     const struct sna_composite_op *op)
 {
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -1341,22 +1350,27 @@ static void gen4_video_bind_surfaces(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = GEN4_SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = GEN4_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n]  = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = GEN4_SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = GEN4_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n]  = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_UYVY)
-			src_surf_format = GEN4_SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = GEN4_SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = GEN4_SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = GEN4_SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -1381,7 +1395,7 @@ static void gen4_video_bind_surfaces(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	if (!ALWAYS_FLUSH && sna->kgem.batch[sna->render_state.gen4.surface_table] == binding_table[0])
@@ -1429,6 +1443,7 @@ gen4_render_video(struct sna *sna,
 	tmp.src.bo = frame->bo;
 	tmp.mask.bo = NULL;
 	tmp.u.gen4.wm_kernel =
+		is_nv12_fourcc(frame->id) ? WM_KERNEL_VIDEO_NV12 :
 		is_planar_fourcc(frame->id) ? WM_KERNEL_VIDEO_PLANAR : WM_KERNEL_VIDEO_PACKED;
 	tmp.u.gen4.ve_id = 2;
 	tmp.is_affine = true;
diff --git a/src/sna/gen4_render.h b/src/sna/gen4_render.h
index 64d11e66..3b37f96a 100644
--- a/src/sna/gen4_render.h
+++ b/src/sna/gen4_render.h
@@ -2686,6 +2686,7 @@ typedef enum {
 	WM_KERNEL_OPACITY_P,
 
 	WM_KERNEL_VIDEO_PLANAR,
+	WM_KERNEL_VIDEO_NV12,
 	WM_KERNEL_VIDEO_PACKED,
 	KERNEL_COUNT
 } wm_kernel_t;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index fb3e79bf..91c58236 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -105,6 +105,14 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_write.g5b"
 };
 
+static const uint32_t ps_kernel_nv12_static[][4] = {
+#include "exa_wm_xy.g5b"
+#include "exa_wm_src_affine.g5b"
+#include "exa_wm_src_sample_nv12.g5b"
+#include "exa_wm_yuv_rgb.g5b"
+#include "exa_wm_write.g5b"
+};
+
 #define NOKERNEL(kernel_enum, func, masked) \
     [kernel_enum] = {func, 0, masked}
 #define KERNEL(kernel_enum, kernel, masked) \
@@ -130,6 +138,7 @@ static const struct wm_kernel_info {
 	NOKERNEL(WM_KERNEL_OPACITY_P, brw_wm_kernel__projective_opacity, true),
 
 	KERNEL(WM_KERNEL_VIDEO_PLANAR, ps_kernel_planar_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12, ps_kernel_nv12_static, false),
 	KERNEL(WM_KERNEL_VIDEO_PACKED, ps_kernel_packed_static, false),
 };
 #undef KERNEL
@@ -1278,7 +1287,7 @@ static void gen5_video_bind_surfaces(struct sna *sna,
 {
 	bool dirty = kgem_bo_is_dirty(op->dst.bo);
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -1295,22 +1304,27 @@ static void gen5_video_bind_surfaces(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = GEN5_SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = GEN5_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n]  = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = GEN5_SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = GEN5_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n]  = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_UYVY)
-			src_surf_format = GEN5_SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = GEN5_SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = GEN5_SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = GEN5_SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -1334,7 +1348,7 @@ static void gen5_video_bind_surfaces(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	gen5_emit_state(sna, op, offset | dirty);
@@ -1379,6 +1393,7 @@ gen5_render_video(struct sna *sna,
 	tmp.src.bo = frame->bo;
 	tmp.mask.bo = NULL;
 	tmp.u.gen5.wm_kernel =
+		is_nv12_fourcc(frame->id) ? WM_KERNEL_VIDEO_NV12 :
 		is_planar_fourcc(frame->id) ? WM_KERNEL_VIDEO_PLANAR : WM_KERNEL_VIDEO_PACKED;
 	tmp.u.gen5.ve_id = 2;
 	tmp.is_affine = true;
diff --git a/src/sna/gen5_render.h b/src/sna/gen5_render.h
index 0f6bae6b..f1a9a68c 100644
--- a/src/sna/gen5_render.h
+++ b/src/sna/gen5_render.h
@@ -2766,6 +2766,7 @@ typedef enum {
 	WM_KERNEL_OPACITY_P,
 
 	WM_KERNEL_VIDEO_PLANAR,
+	WM_KERNEL_VIDEO_NV12,
 	WM_KERNEL_VIDEO_PACKED,
 	KERNEL_COUNT
 } wm_kernel_t;
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 6b69f216..f8776c61 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -115,6 +115,13 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_write.g6b"
 };
 
+static const uint32_t ps_kernel_nv12[][4] = {
+#include "exa_wm_src_affine.g6b"
+#include "exa_wm_src_sample_nv12.g6b"
+#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_write.g6b"
+};
+
 #define NOKERNEL(kernel_enum, func, ns) \
     [GEN6_WM_KERNEL_##kernel_enum] = {#kernel_enum, func, 0, ns}
 #define KERNEL(kernel_enum, kernel, ns) \
@@ -142,6 +149,7 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY_P, brw_wm_kernel__projective_opacity, 2),
 
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
+	KERNEL(VIDEO_NV12, ps_kernel_nv12, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
 };
 #undef KERNEL
@@ -1554,7 +1562,7 @@ static void gen6_emit_video_state(struct sna *sna,
 				  const struct sna_composite_op *op)
 {
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -1574,22 +1582,27 @@ static void gen6_emit_video_state(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = GEN6_SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = GEN6_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n]  = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = GEN6_SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = GEN6_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n]  = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_UYVY)
-			src_surf_format = GEN6_SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = GEN6_SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = GEN6_SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = GEN6_SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -1612,7 +1625,7 @@ static void gen6_emit_video_state(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	gen6_emit_state(sna, op, offset | dirty);
@@ -1670,6 +1683,8 @@ gen6_render_video(struct sna *sna,
 		GEN6_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					       SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
+			       is_nv12_fourcc(frame->id) ?
+			       GEN6_WM_KERNEL_VIDEO_NV12 :
 			       is_planar_fourcc(frame->id) ?
 			       GEN6_WM_KERNEL_VIDEO_PLANAR :
 			       GEN6_WM_KERNEL_VIDEO_PACKED,
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index aabb8693..ad48453a 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -207,6 +207,13 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_write.g7b"
 };
 
+static const uint32_t ps_kernel_nv12[][4] = {
+#include "exa_wm_src_affine.g7b"
+#include "exa_wm_src_sample_nv12.g7b"
+#include "exa_wm_yuv_rgb.g7b"
+#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"
@@ -239,6 +246,7 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY_P, brw_wm_kernel__projective_opacity, 2),
 
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
+	KERNEL(VIDEO_NV12, ps_kernel_nv12, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 };
@@ -1766,7 +1774,7 @@ static void gen7_emit_video_state(struct sna *sna,
 				  const struct sna_composite_op *op)
 {
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -1785,24 +1793,29 @@ static void gen7_emit_video_state(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = GEN7_SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = GEN7_SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n]  = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = GEN7_SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = GEN7_SURFACEFORMAT_R8_UNORM;
+			src_width[n] = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n] = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_RGB888)
-			src_surf_format = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
+			src_surf_format[0] = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
 		else if (frame->id == FOURCC_UYVY)
-			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = GEN7_SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = GEN7_SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -1827,7 +1840,7 @@ static void gen7_emit_video_state(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	gen7_emit_state(sna, op, offset | dirty);
@@ -1841,6 +1854,9 @@ static unsigned select_video_kernel(const struct sna_video_frame *frame)
 	case FOURCC_XVMC:
 		return GEN7_WM_KERNEL_VIDEO_PLANAR;
 
+	case FOURCC_NV12:
+		return GEN7_WM_KERNEL_VIDEO_NV12;
+
 	case FOURCC_RGB888:
 	case FOURCC_RGB565:
 		return GEN7_WM_KERNEL_VIDEO_RGB;
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 445983b1..02f69b6a 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -107,6 +107,13 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_write.g8b"
 };
 
+static const uint32_t ps_kernel_nv12[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_nv12.g8b"
+#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"
@@ -143,6 +150,7 @@ static const struct wm_kernel_info {
 
 #if !NO_VIDEO
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
+	KERNEL(VIDEO_NV12, ps_kernel_nv12, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 #endif
@@ -3710,7 +3718,7 @@ static void gen8_emit_video_state(struct sna *sna,
 				  const struct sna_composite_op *op)
 {
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -3731,24 +3739,29 @@ static void gen8_emit_video_state(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = SURFACEFORMAT_R8_UNORM;
+			src_width[n] = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n] = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = SURFACEFORMAT_R8_UNORM;
+			src_width[n] = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n] = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_RGB888)
-			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
+			src_surf_format[0] = SURFACEFORMAT_B8G8R8X8_UNORM;
 		else if (frame->id == FOURCC_UYVY)
-			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -3771,7 +3784,7 @@ static void gen8_emit_video_state(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	gen8_emit_state(sna, op, offset);
diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c
index e5f12c72..68ac1438 100644
--- a/src/sna/gen9_render.c
+++ b/src/sna/gen9_render.c
@@ -108,6 +108,13 @@ static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_write.g8b"
 };
 
+static const uint32_t ps_kernel_nv12[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_nv12.g8b"
+#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"
@@ -144,6 +151,7 @@ static const struct wm_kernel_info {
 
 #if !NO_VIDEO
 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
+	KERNEL(VIDEO_NV12, ps_kernel_nv12, 7),
 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 #endif
@@ -3764,7 +3772,7 @@ static void gen9_emit_video_state(struct sna *sna,
 				  const struct sna_composite_op *op)
 {
 	struct sna_video_frame *frame = op->priv;
-	uint32_t src_surf_format;
+	uint32_t src_surf_format[6];
 	uint32_t src_surf_base[6];
 	int src_width[6];
 	int src_height[6];
@@ -3785,24 +3793,29 @@ static void gen9_emit_video_state(struct sna *sna,
 	src_surf_base[5] = frame->UBufOffset;
 
 	if (is_planar_fourcc(frame->id)) {
-		src_surf_format = SURFACEFORMAT_R8_UNORM;
-		src_width[1]  = src_width[0]  = frame->width;
-		src_height[1] = src_height[0] = frame->height;
-		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
-		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
-			frame->width / 2;
-		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
-			frame->height / 2;
-		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
-			frame->pitch[0];
+		for (n = 0; n < 2; n++) {
+			src_surf_format[n] = SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width;
+			src_height[n] = frame->height;
+			src_pitch[n]  = frame->pitch[1];
+		}
+		for (; n < 6; n++) {
+			if (is_nv12_fourcc(frame->id))
+				src_surf_format[n] = SURFACEFORMAT_R8G8_UNORM;
+			else
+				src_surf_format[n] = SURFACEFORMAT_R8_UNORM;
+			src_width[n]  = frame->width / 2;
+			src_height[n] = frame->height / 2;
+			src_pitch[n]  = frame->pitch[0];
+		}
 		n_src = 6;
 	} else {
 		if (frame->id == FOURCC_RGB888)
-			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
+			src_surf_format[0] = SURFACEFORMAT_B8G8R8X8_UNORM;
 		else if (frame->id == FOURCC_UYVY)
-			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
+			src_surf_format[0] = SURFACEFORMAT_YCRCB_SWAPY;
 		else
-			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
+			src_surf_format[0] = SURFACEFORMAT_YCRCB_NORMAL;
 
 		src_width[0]  = frame->width;
 		src_height[0] = frame->height;
@@ -3825,7 +3838,7 @@ static void gen9_emit_video_state(struct sna *sna,
 					       src_width[n],
 					       src_height[n],
 					       src_pitch[n],
-					       src_surf_format);
+					       src_surf_format[n]);
 	}
 
 	gen9_emit_state(sna, op, offset);
@@ -3839,6 +3852,9 @@ static unsigned select_video_kernel(const struct sna_video_frame *frame)
 	case FOURCC_XVMC:
 		return GEN9_WM_KERNEL_VIDEO_PLANAR;
 
+	case FOURCC_NV12:
+		return GEN9_WM_KERNEL_VIDEO_NV12;
+
 	case FOURCC_RGB888:
 	case FOURCC_RGB565:
 		return GEN9_WM_KERNEL_VIDEO_RGB;
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 4ba345a7..730cb21f 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -437,6 +437,7 @@ enum {
 	GEN6_WM_KERNEL_OPACITY_P,
 
 	GEN6_WM_KERNEL_VIDEO_PLANAR,
+	GEN6_WM_KERNEL_VIDEO_NV12,
 	GEN6_WM_KERNEL_VIDEO_PACKED,
 	GEN6_KERNEL_COUNT
 };
@@ -487,6 +488,7 @@ enum {
 	GEN7_WM_KERNEL_OPACITY_P,
 
 	GEN7_WM_KERNEL_VIDEO_PLANAR,
+	GEN7_WM_KERNEL_VIDEO_NV12,
 	GEN7_WM_KERNEL_VIDEO_PACKED,
 	GEN7_WM_KERNEL_VIDEO_RGB,
 	GEN7_WM_KERNEL_COUNT
@@ -540,6 +542,7 @@ enum {
 	GEN8_WM_KERNEL_OPACITY_P,
 
 	GEN8_WM_KERNEL_VIDEO_PLANAR,
+	GEN8_WM_KERNEL_VIDEO_NV12,
 	GEN8_WM_KERNEL_VIDEO_PACKED,
 	GEN8_WM_KERNEL_VIDEO_RGB,
 	GEN8_WM_KERNEL_COUNT
@@ -591,6 +594,7 @@ enum {
 	GEN9_WM_KERNEL_OPACITY_P,
 
 	GEN9_WM_KERNEL_VIDEO_PLANAR,
+	GEN9_WM_KERNEL_VIDEO_NV12,
 	GEN9_WM_KERNEL_VIDEO_PACKED,
 	GEN9_WM_KERNEL_VIDEO_RGB,
 	GEN9_WM_KERNEL_COUNT
commit 0fee13926a2a42cf1e6da43268f83f9c1d653f37
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 22:27:43 2017 +0300

    sna/video: Add NV12 shader binaries
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/render_program/exa_wm_src_sample_nv12.g4b b/src/render_program/exa_wm_src_sample_nv12.g4b
new file mode 100644
index 00000000..858a8887
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g4b
@@ -0,0 +1,7 @@
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22401c09, 0x00000000, 0x02540003 },
+   { 0x00802001, 0x21c00021, 0x008d0280, 0x00000000 },
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22001c09, 0x00000000, 0x02520001 },
diff --git a/src/render_program/exa_wm_src_sample_nv12.g4b.gen5 b/src/render_program/exa_wm_src_sample_nv12.g4b.gen5
new file mode 100644
index 00000000..0ab44598
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g4b.gen5
@@ -0,0 +1,7 @@
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22401c09, 0x20000000, 0x0a4a0003 },
+   { 0x00802001, 0x21c00021, 0x008d0280, 0x00000000 },
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22001c09, 0x20000000, 0x0a2a0001 },
diff --git a/src/render_program/exa_wm_src_sample_nv12.g5b b/src/render_program/exa_wm_src_sample_nv12.g5b
new file mode 100644
index 00000000..0ab44598
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g5b
@@ -0,0 +1,7 @@
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22401c09, 0x20000000, 0x0a4a0003 },
+   { 0x00802001, 0x21c00021, 0x008d0280, 0x00000000 },
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x01800031, 0x22001c09, 0x20000000, 0x0a2a0001 },
diff --git a/src/render_program/exa_wm_src_sample_nv12.g6b b/src/render_program/exa_wm_src_sample_nv12.g6b
new file mode 100644
index 00000000..464d2fd2
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g6b
@@ -0,0 +1,7 @@
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22401cc9, 0x00000020, 0x0a4a0003 },
+   { 0x00800001, 0x21c00021, 0x008d0280, 0x00000000 },
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22001cc9, 0x00000020, 0x0a2a0001 },
diff --git a/src/render_program/exa_wm_src_sample_nv12.g7b b/src/render_program/exa_wm_src_sample_nv12.g7b
new file mode 100644
index 00000000..d906043c
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g7b
@@ -0,0 +1,7 @@
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x28200021, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22401ca9, 0x00000820, 0x0a4c0003 },
+   { 0x00800001, 0x21c00021, 0x008d0280, 0x00000000 },
+   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x28200021, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22001ca9, 0x00000820, 0x0a2c0001 },
diff --git a/src/render_program/exa_wm_src_sample_nv12.g8b b/src/render_program/exa_wm_src_sample_nv12.g8b
new file mode 100644
index 00000000..809d5fcb
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g8b
@@ -0,0 +1,7 @@
+   { 0x00000001, 0x2008060c, 0x00000000, 0x0000c000 },
+   { 0x00600001, 0x28200208, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22400a48, 0x0e000820, 0x0a4c0003 },
+   { 0x00800001, 0x21c00208, 0x008d0280, 0x00000000 },
+   { 0x00000001, 0x2008060c, 0x00000000, 0x0000e000 },
+   { 0x00600001, 0x28200208, 0x008d0000, 0x00000000 },
+   { 0x02800031, 0x22000a48, 0x0e000820, 0x0a2c0001 },
commit 4322c978f8ab469966b0efc6d3db2eb10b357e1e
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 03:26:44 2017 +0300

    sna/video: Add NV12 shaders
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/render_program/Makefile.am b/src/render_program/Makefile.am
index 67a74ad8..7b835e1a 100644
--- a/src/render_program/Makefile.am
+++ b/src/render_program/Makefile.am
@@ -5,6 +5,7 @@ INTEL_G4A =				\
 	exa_wm_src_projective.g4a 	\
 	exa_wm_src_sample_argb.g4a 	\
 	exa_wm_src_sample_a.g4a 	\
+	exa_wm_src_sample_nv12.g4a 	\
 	exa_wm_src_sample_planar.g4a 	\
 	exa_wm_mask_affine.g4a 		\
 	exa_wm_mask_projective.g4a 	\
@@ -22,6 +23,7 @@ INTEL_G4I =				\
 	exa_wm.g4i			\
 	exa_wm_affine.g4i		\
 	exa_wm_projective.g4i		\
+	exa_wm_sample_nv12.g4i		\
 	exa_wm_sample_planar.g4i	\
 	exa_wm_src_sample_argb.g4i	\
 	$(NULL)
@@ -33,6 +35,7 @@ INTEL_G4B = 				\
 	exa_wm_src_projective.g4b 	\
 	exa_wm_src_sample_argb.g4b 	\
 	exa_wm_src_sample_a.g4b 	\
+	exa_wm_src_sample_nv12.g4b 	\
 	exa_wm_src_sample_planar.g4b 	\
 	exa_wm_mask_affine.g4b 		\
 	exa_wm_mask_projective.g4b 	\
@@ -54,6 +57,7 @@ INTEL_G4B_GEN5 = 				\
 	exa_wm_src_projective.g4b.gen5 		\
 	exa_wm_src_sample_argb.g4b.gen5 	\
 	exa_wm_src_sample_a.g4b.gen5 		\
+	exa_wm_src_sample_nv12.g4b.gen5 	\
 	exa_wm_src_sample_planar.g4b.gen5 	\
 	exa_wm_mask_affine.g4b.gen5 		\
 	exa_wm_mask_projective.g4b.gen5 	\
@@ -74,6 +78,7 @@ INTEL_G5A =				\
 	exa_wm_src_projective.g5a 	\
 	exa_wm_src_sample_argb.g5a 	\
 	exa_wm_src_sample_a.g5a 	\
+	exa_wm_src_sample_nv12.g5a 	\
 	exa_wm_src_sample_planar.g5a 	\
 	exa_wm_mask_affine.g5a 		\
 	exa_wm_mask_projective.g5a 	\
@@ -94,6 +99,7 @@ INTEL_G5B = 				\
 	exa_wm_src_projective.g5b 	\
 	exa_wm_src_sample_argb.g5b 	\
 	exa_wm_src_sample_a.g5b 	\
+	exa_wm_src_sample_nv12.g5b 	\
 	exa_wm_src_sample_planar.g5b 	\
 	exa_wm_mask_affine.g5b 		\
 	exa_wm_mask_projective.g5b 	\
@@ -116,6 +122,7 @@ INTEL_G6A =				\
 	exa_wm_src_affine.g6a 		\
 	exa_wm_src_projective.g6a	\
 	exa_wm_src_sample_argb.g6a 	\
+	exa_wm_src_sample_nv12.g6a 	\
 	exa_wm_src_sample_planar.g6a 	\
 	exa_wm_src_sample_a.g6a		\
 	exa_wm_mask_affine.g6a		\
@@ -133,6 +140,7 @@ INTEL_G6B =				\
 	exa_wm_src_affine.g6b 		\
 	exa_wm_src_projective.g6b	\
 	exa_wm_src_sample_argb.g6b 	\
+	exa_wm_src_sample_nv12.g6b 	\
 	exa_wm_src_sample_planar.g6b 	\
 	exa_wm_src_sample_a.g6b		\
 	exa_wm_mask_affine.g6b		\
@@ -155,6 +163,7 @@ INTEL_G7A =				\
 	exa_wm_src_projective.g7a	\
 	exa_wm_src_sample_a.g7a		\
 	exa_wm_src_sample_argb.g7a 	\
+	exa_wm_src_sample_nv12.g7a 	\
 	exa_wm_src_sample_planar.g7a 	\
 	exa_wm_write.g7a 		\
 	exa_wm_yuv_rgb.g7a		\
@@ -169,6 +178,7 @@ INTEL_G7B =				\
 	exa_wm_src_projective.g7b	\
 	exa_wm_src_sample_a.g7b		\
 	exa_wm_src_sample_argb.g7b 	\
+	exa_wm_src_sample_nv12.g7b 	\
 	exa_wm_src_sample_planar.g7b 	\
 	exa_wm_write.g7b 		\
 	exa_wm_yuv_rgb.g7b		\
@@ -177,6 +187,7 @@ INTEL_G7B =				\
 INTEL_G8A =				\
 	exa_wm_src_affine.g8a 		\
 	exa_wm_src_sample_argb.g8a 	\
+	exa_wm_src_sample_nv12.g8a 	\
 	exa_wm_src_sample_planar.g8a 	\
 	exa_wm_write.g8a 		\
 	exa_wm_yuv_rgb.g8a		\
@@ -185,6 +196,7 @@ INTEL_G8A =				\
 INTEL_G8B =				\
 	exa_wm_src_affine.g8b 		\
 	exa_wm_src_sample_argb.g8b 	\
+	exa_wm_src_sample_nv12.g8b 	\
 	exa_wm_src_sample_planar.g8b 	\
 	exa_wm_write.g8b 		\
 	exa_wm_yuv_rgb.g8b		\
diff --git a/src/render_program/exa_wm_sample_nv12.g4i b/src/render_program/exa_wm_sample_nv12.g4i
new file mode 100644
index 00000000..28ebb8df
--- /dev/null
+++ b/src/render_program/exa_wm_sample_nv12.g4i
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Keith Packard <keithp at keithp.com>
+ */
+
+/* Sample the src surface in planar format */
+
+/* prepare sampler read back gX register, which would be written back to output */
+
+/* use simd16 sampler, param 0 is u, param 1 is v. */
+/* 'payload' loading, assuming tex coord start from g4 */
+
+/* load rg */
+mov (1) g0.8<1>UD	0x0000c000UD { align1 mask_disable };
+
+/* src_msg will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* Sample CbCr */
+mov (8) src_msg<1>UD g0<8,8,1>UD { align1 }; /* copy to msg start reg*/
+send (16) src_msg_ind		/* msg reg index */
+	src_sample_b<1>UW 	/* readback */
+	null
+	sampler (3,0,F)		/* sampler message description, (binding_table,sampler_index,datatype)
+				/* here(src->dst) we should use src_sampler and src_surface */
+	mlen 5 rlen 4 { align1 };   /* required message len 5, readback len 4 */
+
+/* Move Cr to its proper place */
+mov (16) src_sample_r<1>UD src_sample_a<8,8,1>UD { align1 };
+
+/* load r */
+mov (1) g0.8<1>UD	0x0000e000UD { align1 mask_disable };
+
+/* src_msg will be copied with g0, as it contains send desc */
+/* emit sampler 'send' cmd */
+
+/* Sample Y */
+mov (8) src_msg<1>UD g0<8,8,1>UD { align1 }; /* copy to msg start reg*/
+send (16) src_msg_ind		/* msg reg index */
+	src_sample_g<1>UW 	/* readback */
+	null
+	sampler (1,0,F)		/* sampler message description, (binding_table,sampler_index,datatype)
+				/* here(src->dst) we should use src_sampler and src_surface */
+	mlen 5 rlen 2 { align1 };   /* required message len 5, readback len 2 */
diff --git a/src/render_program/exa_wm_src_sample_nv12.g4a b/src/render_program/exa_wm_src_sample_nv12.g4a
new file mode 100644
index 00000000..84677588
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g4a
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Keith Packard <keithp at keithp.com>
+ */
+
+/* Sample the src surface in planar format */
+
+include(`exa_wm.g4i')
+
+include(`exa_wm_sample_nv12.g4i')
diff --git a/src/render_program/exa_wm_src_sample_nv12.g5a b/src/render_program/exa_wm_src_sample_nv12.g5a
new file mode 120000
index 00000000..4f276b09
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g5a
@@ -0,0 +1 @@
+exa_wm_src_sample_nv12.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_src_sample_nv12.g6a b/src/render_program/exa_wm_src_sample_nv12.g6a
new file mode 120000
index 00000000..4f276b09
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g6a
@@ -0,0 +1 @@
+exa_wm_src_sample_nv12.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_src_sample_nv12.g7a b/src/render_program/exa_wm_src_sample_nv12.g7a
new file mode 100644
index 00000000..873f880e
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g7a
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Wang Zhenyu <zhenyu.z.wang at intel.com>
+ *    Keith Packard <keithp at keithp.com>
+ */
+
+/* Sample the src surface in planar format */
+
+include(`exa_wm.g4i')
+
+undefine(`src_msg')
+undefine(`src_msg_ind')
+
+define(`src_msg',       `g65')
+define(`src_msg_ind',   `65')
+
+include(`exa_wm_sample_nv12.g4i')
diff --git a/src/render_program/exa_wm_src_sample_nv12.g8a b/src/render_program/exa_wm_src_sample_nv12.g8a
new file mode 120000
index 00000000..8d964a99
--- /dev/null
+++ b/src/render_program/exa_wm_src_sample_nv12.g8a
@@ -0,0 +1 @@
+exa_wm_src_sample_nv12.g7a
\ No newline at end of file
commit 0a3d4a1a20186d2eaa0d5cc1b7db47eb1e44be71
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Fri Jun 9 18:10:52 2017 +0300

    sna/video: Add FOURCC_NV12
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h
index 39cb725f..bb963e7f 100644
--- a/src/sna/sna_video.h
+++ b/src/sna/sna_video.h
@@ -38,6 +38,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define FOURCC_XVMC (('C' << 24) + ('M' << 16) + ('V' << 8) + 'X')
 #define FOURCC_RGB565 ((16 << 24) + ('B' << 16) + ('G' << 8) + 'R')
 #define FOURCC_RGB888 ((24 << 24) + ('B' << 16) + ('G' << 8) + 'R')
+#define FOURCC_NV12 (('2' << 24) + ('1' << 16) + ('V' << 8) + 'N')
 
 /*
  * Below, a dummy picture type that is used in XvPutImage
@@ -160,6 +161,17 @@ static inline int is_planar_fourcc(int id)
 	case FOURCC_YV12:
 	case FOURCC_I420:
 	case FOURCC_XVMC:
+	case FOURCC_NV12:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int is_nv12_fourcc(int id)
+{
+	switch (id) {
+	case FOURCC_NV12:
 		return 1;
 	default:
 		return 0;
commit 54a1f6337eba77ea4275f48f7d29623bf05ea515
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 31 14:01:10 2017 +0100

    sna: Allow reallocation of larger framebuffers
    
    Since we can assign larger framebuffer to a smaller CRTC, we can reuse
    a bo even if it was last used for a bigger framebuffer (without
    discarding that framebuffer or bo).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index f0d171ac..b8338237 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2737,7 +2737,7 @@ static bool check_scanout_size(struct kgem *kgem,
 
 	gem_close(kgem->fd, info.handle);
 
-	if (width != info.width || height != info.height) {
+	if (width > info.width || height > info.height) {
 		DBG(("%s: not using scanout %d (%dx%d), want (%dx%d)\n",
 		     __FUNCTION__,
 		     info.fb_id, info.width, info.height,
@@ -5411,7 +5411,7 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 				continue;
 
 			if (bo->delta && !check_scanout_size(kgem, bo, width, height))
-				continue;
+				kgem_bo_rmfb(kgem, bo);
 
 			if (flags & CREATE_INACTIVE && bo->rq) {
 				last = bo;
commit 88db4f1dc194c37c3868acc04b7d9f6fb2a1883a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 30 13:10:43 2017 +0100

    sna: Tweak fb size assertion
    
    When pageflipping, we should be able to flip to an fb that is larger
    than the CRTC, so we can relax the assertion that checking for the exact
    size.
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=102442#c12
    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 d1f01218..3f70d536 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -565,7 +565,7 @@ static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
 	assert(drmIoctl(kgem->fd, DRM_IOCTL_MODE_GETFB, &info) == 0);
 	gem_close(kgem->fd, info.handle);
 
-	assert(width == info.width && height == info.height);
+	assert(width <= info.width && height <= info.height);
 }
 #else
 #define assert_scanout(k, b, w, h)


More information about the xorg-commit mailing list