xf86-video-intel: 8 commits - src/render_program/exa_wm_yuv_rgb_bt601.g4a src/render_program/exa_wm_yuv_rgb_bt601.g4b src/render_program/exa_wm_yuv_rgb_bt601.g4b.gen5 src/render_program/exa_wm_yuv_rgb_bt601.g5a src/render_program/exa_wm_yuv_rgb_bt601.g5b src/render_program/exa_wm_yuv_rgb_bt601.g6a src/render_program/exa_wm_yuv_rgb_bt601.g6b src/render_program/exa_wm_yuv_rgb_bt601.g7a src/render_program/exa_wm_yuv_rgb_bt601.g7b src/render_program/exa_wm_yuv_rgb_bt601.g8a src/render_program/exa_wm_yuv_rgb_bt601.g8b src/render_program/exa_wm_yuv_rgb_bt709.g4a src/render_program/exa_wm_yuv_rgb_bt709.g4b src/render_program/exa_wm_yuv_rgb_bt709.g4b.gen5 src/render_program/exa_wm_yuv_rgb_bt709.g5a src/render_program/exa_wm_yuv_rgb_bt709.g5b src/render_program/exa_wm_yuv_rgb_bt709.g6a src/render_program/exa_wm_yuv_rgb_bt709.g6b src/render_program/exa_wm_yuv_rgb_bt709.g7a src/render_program/exa_wm_yuv_rgb_bt709.g7b src/render_program/exa_wm_yuv_rgb_bt709.g8a src/render_program/exa_wm _yuv_rgb_bt709.g8b src/render_program/exa_wm_yuv_rgb.g4a src/render_program/exa_wm_yuv_rgb.g4b src/render_program/exa_wm_yuv_rgb.g4b.gen5 src/render_program/exa_wm_yuv_rgb.g5a src/render_program/exa_wm_yuv_rgb.g5b src/render_program/exa_wm_yuv_rgb.g6a src/render_program/exa_wm_yuv_rgb.g6b src/render_program/exa_wm_yuv_rgb.g7a src/render_program/exa_wm_yuv_rgb.g7b src/render_program/exa_wm_yuv_rgb.g8a src/render_program/exa_wm_yuv_rgb.g8b src/render_program/Makefile.am src/sna/brw 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/sna_display.c src/sna/sna.h src/sna/sna_render.h src/sna/sna_video_sprite.c src/sna/sna_video_textured.c src/uxa/i965_video.c

Chris Wilson ickle at kemper.freedesktop.org
Thu May 31 19:36:40 UTC 2018


 src/render_program/Makefile.am                   |   33 ++++--
 src/render_program/exa_wm_yuv_rgb.g6a            |    1 
 src/render_program/exa_wm_yuv_rgb.g7a            |    1 
 src/render_program/exa_wm_yuv_rgb_bt601.g4a      |   32 ++++--
 src/render_program/exa_wm_yuv_rgb_bt601.g5a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt601.g6a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt601.g7a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt601.g8a      |   31 ++++--
 src/render_program/exa_wm_yuv_rgb_bt709.g4a      |   39 +++++--
 src/render_program/exa_wm_yuv_rgb_bt709.g4b      |   12 ++
 src/render_program/exa_wm_yuv_rgb_bt709.g4b.gen5 |   12 ++
 src/render_program/exa_wm_yuv_rgb_bt709.g5a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt709.g5b      |   12 ++
 src/render_program/exa_wm_yuv_rgb_bt709.g6a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt709.g6b      |   12 ++
 src/render_program/exa_wm_yuv_rgb_bt709.g7a      |    1 
 src/render_program/exa_wm_yuv_rgb_bt709.g7b      |   12 ++
 src/render_program/exa_wm_yuv_rgb_bt709.g8a      |  118 +++++++++++++++++++++++
 src/render_program/exa_wm_yuv_rgb_bt709.g8b      |   19 +++
 src/sna/brw/brw_test_gen4.c                      |    4 
 src/sna/brw/brw_test_gen5.c                      |    4 
 src/sna/brw/brw_test_gen6.c                      |    4 
 src/sna/brw/brw_test_gen7.c                      |    4 
 src/sna/gen4_render.c                            |   73 +++++++++++---
 src/sna/gen4_render.h                            |   11 +-
 src/sna/gen5_render.c                            |   73 +++++++++++---
 src/sna/gen5_render.h                            |   11 +-
 src/sna/gen6_render.c                            |   73 +++++++++++---
 src/sna/gen7_render.c                            |   59 ++++++++---
 src/sna/gen8_render.c                            |   59 ++++++++---
 src/sna/gen9_render.c                            |   59 ++++++++---
 src/sna/sna.h                                    |    1 
 src/sna/sna_display.c                            |   78 +++++++++++++++
 src/sna/sna_render.h                             |   44 ++++++--
 src/sna/sna_video_sprite.c                       |   85 ++++++++++++++--
 src/sna/sna_video_textured.c                     |   12 ++
 src/uxa/i965_video.c                             |   16 +--
 37 files changed, 837 insertions(+), 173 deletions(-)

New commits:
commit 42c24d32d03410c65bb7165b90cf166d762ccb8e
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:15 2018 +0300

    sna/video/sprite: Try disabling plane before giving up on colorkey
    
    When we're trying to reinstate the colorkey we might fail on account of
    the plane still being enable with a configuration that prevent the
    use of colorkey. This happens easily with NV12 since the plane scaler
    required by even unscaled NV12 is not compatible with colorkey.
    
    To work around the problem let's try disabling the plane first, then
    re-enable the colorkey, and finally we will try to re-enable the plane.
    The plane re-enable may fail, in which case we'll head to the GPU
    scaling fallback path. The cost is a flash of the colorkey when the
    plane blink off and then back on.
    
    Help me atomic ioctl, you're my only hope!
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index 0f52f032..f713abcb 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -270,9 +270,19 @@ sna_video_sprite_show(struct sna *sna,
 		if (drmIoctl(sna->kgem.fd,
 			     LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY,
 			     &set)) {
-			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
-				   "failed to update color key, disabling future updates\n");
-			video->has_color_key = false;
+			memset(&s, 0, sizeof(s));
+			s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
+
+			/* try to disable the plane first */
+			if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
+				xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
+					   "failed to disable plane\n");
+
+			if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY, &set)) {
+				xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
+					   "failed to update color key, disabling future updates\n");
+				video->has_color_key = false;
+			}
 		}
 
 		video->color_key_changed &= ~(1 << pipe);
commit bb5ee1adea838b99d60e18523c3632eb02fb04d8
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:14 2018 +0300

    sna/video/sprite: Make NV12 take the GPU scaling fallback
    
    Even unscaled NV12 needs the plane scaler on SKL+, so when
    unscaled NV12 setplane fails we should still take the GPU
    scaling fallback path.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index f6d6f0b4..0f52f032 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -415,6 +415,15 @@ sna_video_sprite_show(struct sna *sna,
 	return true;
 }
 
+static bool need_scaling(const struct sna_video_frame *frame,
+			 const BoxRec *dst)
+{
+	/* SKL+ need the plane scaler even for unscaled NV12 */
+	return frame->id == FOURCC_NV12 ||
+		frame->src.x2 - frame->src.x1 != dst->x2 - dst->x1 ||
+		frame->src.y2 - frame->src.y1 != dst->y2 - dst->y1;
+}
+
 static int sna_video_sprite_put_image(ddPutImage_ARGS)
 {
 	struct sna_video *video = port->devPriv.ptr;
@@ -562,8 +571,7 @@ off:
 		}
 
 		if (!hw_scaling && sna->render.video &&
-		    !((frame.src.x2 - frame.src.x1) == (dst.x2 - dst.x1) &&
-		      (frame.src.y2 - frame.src.y1) == (dst.y2 - dst.y1))) {
+		    need_scaling(&frame, &dst)) {
 			ScreenPtr screen = to_screen_from_sna(sna);
 			PixmapPtr scaled;
 			RegionRec r;
commit 13ac0a81a6c77b801623b2c0e47398a7aa099730
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:13 2018 +0300

    sna/video/sprite: Add NV12 support
    
    Starting from ~KBL planes can do NV12. Let's make use that
    capability in the sprite Xv adaptor.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index a4f3205b..f6d6f0b4 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -46,6 +46,7 @@
 #define DRM_FORMAT_XRGB8888     fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
 #define DRM_FORMAT_YUYV         fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
 #define DRM_FORMAT_UYVY         fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
+#define DRM_FORMAT_NV12         fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
 
 #define has_hw_scaling(sna, video) ((sna)->kgem.gen < 071 || \
 				    ((sna)->kgem.gen >= 0110 && (video)->AlwaysOnTop))
@@ -72,7 +73,12 @@ struct local_mode_set_plane {
 static Atom xvColorKey, xvAlwaysOnTop, xvSyncToVblank, xvColorspace;
 
 static XvFormatRec formats[] = { {15}, {16}, {24} };
-static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY, XVMC_RGB888, XVMC_RGB565 };
+static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY,
+				     XVMC_RGB888 };
+static const XvImageRec images_rgb565[] = { XVIMAGE_YUY2, XVIMAGE_UYVY,
+					    XVMC_RGB888, XVMC_RGB565 };
+static const XvImageRec images_nv12[] = { XVIMAGE_YUY2, XVIMAGE_UYVY,
+					  XVIMAGE_NV12, XVMC_RGB888, XVMC_RGB565 };
 static const XvAttributeRec attribs[] = {
 	{ XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE" }, /* BT.601, BT.709 */
 	{ XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" },
@@ -307,8 +313,6 @@ sna_video_sprite_show(struct sna *sna,
 		f.width = frame->width;
 		f.height = frame->height;
 		f.flags = 1 << 1; /* +modifiers */
-		f.handles[0] = frame->bo->handle;
-		f.pitches[0] = frame->pitch[0];
 
 		switch (frame->bo->tiling) {
 		case I915_TILING_NONE:
@@ -323,6 +327,18 @@ sna_video_sprite_show(struct sna *sna,
 			break;
 		}
 
+		if (is_nv12_fourcc(frame->id)) {
+			f.handles[0] = frame->bo->handle;
+			f.handles[1] = frame->bo->handle;
+			f.pitches[0] = frame->pitch[1];
+			f.pitches[1] = frame->pitch[0];
+			f.offsets[0] = 0;
+			f.offsets[1] = frame->UBufOffset;
+		} else {
+			f.handles[0] = frame->bo->handle;
+			f.pitches[0] = frame->pitch[0];
+		}
+
 		switch (frame->id) {
 		case FOURCC_RGB565:
 			f.pixel_format = DRM_FORMAT_RGB565;
@@ -332,6 +348,9 @@ sna_video_sprite_show(struct sna *sna,
 			f.pixel_format = DRM_FORMAT_XRGB8888;
 			purged = sna->scrn->depth != 24;
 			break;
+		case FOURCC_NV12:
+			f.pixel_format = DRM_FORMAT_NV12;
+			break;
 		case FOURCC_UYVY:
 			f.pixel_format = DRM_FORMAT_UYVY;
 			break;
@@ -633,7 +652,7 @@ static int sna_video_sprite_query(ddQueryImageAttributes_ARGS)
 {
 	struct sna_video *video = port->devPriv.ptr;
 	struct sna_video_frame frame;
-	int size;
+	int size, tmp;
 
 	if (*w > video->sna->mode.max_crtc_width)
 		*w = video->sna->mode.max_crtc_width;
@@ -654,6 +673,21 @@ static int sna_video_sprite_query(ddQueryImageAttributes_ARGS)
 		size = 4;
 		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;
+
 	default:
 		*w = (*w + 1) & ~1;
 		*h = (*h + 1) & ~1;
@@ -752,10 +786,17 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 						 ARRAY_SIZE(formats));
 	adaptor->nAttributes = ARRAY_SIZE(attribs);
 	adaptor->pAttributes = (XvAttributeRec *)attribs;
-	adaptor->pImages = (XvImageRec *)images;
-	adaptor->nImages = 3;
-	if (sna_has_sprite_format(sna, DRM_FORMAT_RGB565))
-		adaptor->nImages = 4;
+
+	if (sna_has_sprite_format(sna, DRM_FORMAT_NV12)) {
+		adaptor->pImages = (XvImageRec *)images_nv12;
+		adaptor->nImages = ARRAY_SIZE(images_nv12);
+	} else if (sna_has_sprite_format(sna, DRM_FORMAT_RGB565)) {
+		adaptor->pImages = (XvImageRec *)images_rgb565;
+		adaptor->nImages = ARRAY_SIZE(images_rgb565);
+	} else {
+		adaptor->pImages = (XvImageRec *)images;
+		adaptor->nImages = ARRAY_SIZE(images);
+	}
 
 #if XORG_XV_VERSION < 2
 	adaptor->ddAllocatePort = sna_xv_alloc_port;
commit 9c281c62dd8cd40913fd21ec5857bb55624fed8e
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:12 2018 +0300

    sna/video/sprite: Query planes for RGB565
    
    Not all sprite planes support RGB565. Insrtead of hardcoding which
    platforms have it let's ask the kernel instead.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 6fe1f0d2..496460ca 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -636,6 +636,7 @@ extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_
 extern void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc, unsigned idx, int colorspace);
 extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx);
 extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
+bool sna_has_sprite_format(struct sna *sna, uint32_t format);
 
 #define CRTC_VBLANK 0x7
 #define CRTC_ON 0x80000000
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 66a941ae..96e7b1bc 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3560,6 +3560,82 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
 		free(planes);
 }
 
+static bool plane_has_format(const uint32_t formats[],
+			     int count_formats,
+			     uint32_t format)
+{
+	int i;
+
+	for (i = 0; i < count_formats; i++) {
+		if (formats[i] == format)
+			return true;
+	}
+
+	return false;
+}
+
+bool sna_has_sprite_format(struct sna *sna, uint32_t format)
+{
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+	int i;
+
+	if (sna->mode.num_real_crtc == 0)
+		return false;
+
+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
+		struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]);
+		struct plane *plane;
+
+		list_for_each_entry(plane, &sna_crtc->sprites, link) {
+			struct local_mode_get_plane p;
+			uint32_t *formats;
+			int count_formats;
+			bool has_format;
+
+			VG_CLEAR(p);
+			p.plane_id = plane->id;
+			p.count_format_types = 0;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_GETPLANE,
+				     &p))
+				continue;
+			count_formats = p.count_format_types;
+
+			formats = calloc(count_formats, sizeof(formats[0]));
+			if (!formats)
+				continue;
+
+			p.count_format_types = count_formats;
+			p.format_type_ptr = (uintptr_t)formats;
+			if (drmIoctl(sna->kgem.fd,
+				     LOCAL_IOCTL_MODE_GETPLANE,
+				     &p)) {
+				free(formats);
+				continue;
+			}
+
+			assert(p.count_format_types == count_formats);
+
+			has_format = plane_has_format(formats,
+						      count_formats,
+						      format);
+
+			free(formats);
+
+			/*
+			 * As long as one plane supports the
+			 * format we declare it as supported.
+			 * Not all planes may support it, but
+			 * then the GPU fallback will kick in.
+			 */
+			if (has_format)
+				return true;
+		}
+	}
+
+	return false;
+}
+
 static void
 sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *crtc)
 {
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index 56391aa6..a4f3205b 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -754,7 +754,7 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 	adaptor->pAttributes = (XvAttributeRec *)attribs;
 	adaptor->pImages = (XvImageRec *)images;
 	adaptor->nImages = 3;
-	if (sna->kgem.gen == 071)
+	if (sna_has_sprite_format(sna, DRM_FORMAT_RGB565))
 		adaptor->nImages = 4;
 
 #if XORG_XV_VERSION < 2
commit d2a21702bde1d368177b5ead977b1fa9e078f25e
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:11 2018 +0300

    sna/video/sprite: Add sprite planes in order
    
    On SKL+ dst color keying only works between the first sprite and the
    primary. We probably wante the first Xv port to be the first sprite
    plane so that the user gets working colorkeying for the port that is
    most likely to be used first. No way to get dst colorkeying with the
    other ports :(
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    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 62cd3ab5..66a941ae 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3475,7 +3475,7 @@ static void add_sprite_plane(struct sna_crtc *crtc,
 		return;
 
 	memcpy(sprite, details, sizeof(*sprite));
-	list_add(&sprite->link, &crtc->sprites);
+	list_add_tail(&sprite->link, &crtc->sprites);
 }
 
 static void
commit e4f2b5d5af9548f950b20b4699a2f751ca2146dc
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:10 2018 +0300

    sna/video: Add XV_COLORSPACE attribute for the textured Xv adaptor
    
    Allow the client to select between BT.601 and BT.709 via the
    XV_COLORSPACE port attribute with the textured Xv adaptor as well.
    
    Since the BT.601 coefficients are currently hardcoded in the
    yuv->rgb shader, let's just add a mostly duplicated shader with
    hardcoded BT.709 coefficients instead. Not the most elegant solution
    but avoids having to touch any state setup etc.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/render_program/Makefile.am b/src/render_program/Makefile.am
index 44936734..dc58138f 100644
--- a/src/render_program/Makefile.am
+++ b/src/render_program/Makefile.am
@@ -16,6 +16,7 @@ INTEL_G4A =				\
 	exa_wm_ca_srcalpha.g4a		\
 	exa_wm_write.g4a 		\
 	exa_wm_yuv_rgb_bt601.g4a	\
+	exa_wm_yuv_rgb_bt709.g4a	\
 	exa_wm_xy.g4a			\
 	$(NULL)
 
@@ -46,6 +47,7 @@ INTEL_G4B = 				\
 	exa_wm_ca_srcalpha.g4b		\
 	exa_wm_write.g4b 		\
 	exa_wm_yuv_rgb_bt601.g4b	\
+	exa_wm_yuv_rgb_bt709.g4b	\
 	exa_wm_xy.g4b			\
 	$(NULL)
 
@@ -68,6 +70,7 @@ INTEL_G4B_GEN5 = 				\
 	exa_wm_ca_srcalpha.g4b.gen5		\
 	exa_wm_write.g4b.gen5 			\
 	exa_wm_yuv_rgb_bt601.g4b.gen5		\
+	exa_wm_yuv_rgb_bt709.g4b.gen5		\
 	exa_wm_xy.g4b.gen5			\
 	$(NULL)
 
@@ -89,6 +92,7 @@ INTEL_G5A =				\
 	exa_wm_ca_srcalpha.g5a		\
 	exa_wm_write.g5a 		\
 	exa_wm_yuv_rgb_bt601.g5a	\
+	exa_wm_yuv_rgb_bt709.g5a	\
 	exa_wm_xy.g5a			\
 	$(NULL)
 
@@ -110,6 +114,7 @@ INTEL_G5B = 				\
 	exa_wm_ca_srcalpha.g5b		\
 	exa_wm_write.g5b 		\
 	exa_wm_yuv_rgb_bt601.g5b	\
+	exa_wm_yuv_rgb_bt709.g5b	\
 	exa_wm_xy.g5b			\
 	$(NULL)
 
@@ -134,6 +139,7 @@ INTEL_G6A =				\
 	exa_wm_noca.g6a			\
 	exa_wm_write.g6a 		\
 	exa_wm_yuv_rgb_bt601.g6a	\
+	exa_wm_yuv_rgb_bt709.g6a	\
 	$(NULL)
 
 INTEL_G6B =				\
@@ -152,6 +158,7 @@ INTEL_G6B =				\
 	exa_wm_noca.g6b			\
 	exa_wm_write.g6b 		\
 	exa_wm_yuv_rgb_bt601.g6b	\
+	exa_wm_yuv_rgb_bt709.g6b	\
 	$(NULL)
 
 INTEL_G7A =				\
@@ -167,6 +174,7 @@ INTEL_G7A =				\
 	exa_wm_src_sample_planar.g7a 	\
 	exa_wm_write.g7a 		\
 	exa_wm_yuv_rgb_bt601.g7a	\
+	exa_wm_yuv_rgb_bt709.g7a	\
 	$(NULL)
 
 INTEL_G7B =				\
@@ -182,6 +190,7 @@ INTEL_G7B =				\
 	exa_wm_src_sample_planar.g7b 	\
 	exa_wm_write.g7b 		\
 	exa_wm_yuv_rgb_bt601.g7b	\
+	exa_wm_yuv_rgb_bt709.g7b	\
 	$(NULL)
 
 INTEL_G8A =				\
@@ -191,6 +200,7 @@ INTEL_G8A =				\
 	exa_wm_src_sample_planar.g8a 	\
 	exa_wm_write.g8a 		\
 	exa_wm_yuv_rgb_bt601.g8a	\
+	exa_wm_yuv_rgb_bt709.g8a	\
 	$(NULL)
 
 INTEL_G8B =				\
@@ -200,6 +210,7 @@ INTEL_G8B =				\
 	exa_wm_src_sample_planar.g8b 	\
 	exa_wm_write.g8b 		\
 	exa_wm_yuv_rgb_bt601.g8b	\
+	exa_wm_yuv_rgb_bt709.g8b	\
 	$(NULL)
 
 EXTRA_DIST = 		\
diff --git a/src/render_program/exa_wm_yuv_rgb_bt601.g4a b/src/render_program/exa_wm_yuv_rgb_bt601.g4a
index 4fb2576a..7bc8dd14 100644
--- a/src/render_program/exa_wm_yuv_rgb_bt601.g4a
+++ b/src/render_program/exa_wm_yuv_rgb_bt601.g4a
@@ -55,14 +55,24 @@ define(`Cbn_01',	`mask_sample_b_01')
 define(`Cbn_23',	`mask_sample_b_23')
 
     /* color space conversion function:
-     * R = Clamp ( 1.164(Y-16/255) + 1.596(Cr-128/255), 0, 1)
-     * G = Clamp ( 1.164(Y-16/255) - 0.813(Cr-128/255) - 0.392(Cb-128/255), 0, 1)
-     * B = Clamp ( 1.164(Y-16/255) + 2.017(Cb-128/255), 0, 1)
+     * Cy = 255/(235-16)
+     * R = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kr)(Cr-128/255), 0, 1)
+     * G = Clamp ( 255/(235-16)(Y-16/255) -
+     *             255/112(1.0-Kr)Kr/Kg(Cr-128/255) -
+     *             255/112(1.0-Kb)Kb/Kg(Cb-128/255), 0, 1)
+     * B = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kb)(Cb-128/255), 0, 1)
+     *
+     * BT.601:
+     * Kr = 0.299
+     * Kb = 0.114
+     * Kg = (1.0 - Kr - Kb) = 0.587
      */
 
     /* Normalize Y, Cb and Cr:
      *
-     * Yn = (Y - 16/255) * 1.164
+     * Yn = (Y - 16/255) * 255/(235-16)
      * Crn = Cr - 128 / 255
      * Cbn = Cb - 128 / 255
      */
@@ -73,21 +83,25 @@ add (16)    Crn<1>F		Cr<8,8,1>F	-0.501961F  { compr align1 };
 
 add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
 
-    /* 
-     * R = Y + Cr * 1.596
+    /*
+     * R = Yn +
+     *     Crn * 255/112 * (1.0 - Kr)
      */
 mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
 mac.sat(16) src_sample_r<1>F	Crn<8,8,1>F	1.596F	    { compr align1 };
-     
+
     /*
-     * G = Crn * -0.813 + Cbn * -0.392 + Y
+     * G = Yn -
+     *     Crn * 255/112 * (1.0 - Kr) * Kr / Kg -
+     *     Cbn * 255/112 * (1.0 - Kb) * Kb / Kg
      */
 mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
 mac (16)    acc0<1>F		Crn<8,8,1>F    	-0.813F	    { compr align1 };
 mac.sat(16) src_sample_g<1>F	Cbn<8,8,1>F    	-0.392F	    { compr align1 };
 
     /*
-     * B = Cbn * 2.017 + Y
+     * B = Yn +
+     *     Cbn * 255/112 * (1.0 - Kb)
      */
 mov (16)    acc0<1>F	        Yn<8,8,1>F		    { compr align1 };
 mac.sat(16) src_sample_b<1>F	Cbn<8,8,1>F     2.017F	    { compr align1 };
diff --git a/src/render_program/exa_wm_yuv_rgb_bt601.g8a b/src/render_program/exa_wm_yuv_rgb_bt601.g8a
index 34973ba8..360501dc 100644
--- a/src/render_program/exa_wm_yuv_rgb_bt601.g8a
+++ b/src/render_program/exa_wm_yuv_rgb_bt601.g8a
@@ -55,14 +55,23 @@ define(`Cbn_01',	`mask_sample_b_01')
 define(`Cbn_23',	`mask_sample_b_23')
 
     /* color space conversion function:
-     * R = Clamp ( 1.164(Y-16/255) + 1.596(Cr-128/255), 0, 1)
-     * G = Clamp ( 1.164(Y-16/255) - 0.813(Cr-128/255) - 0.392(Cb-128/255), 0, 1)
-     * B = Clamp ( 1.164(Y-16/255) + 2.017(Cb-128/255), 0, 1)
+     * R = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kr)(Cr-128/255), 0, 1)
+     * G = Clamp ( 255/(235-16)(Y-16/255) -
+     *             255/112(1.0-Kr)Kr/Kg(Cr-128/255) -
+     *             255/112(1.0-Kb)Kb/Kg(Cb-128/255), 0, 1)
+     * B = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kb)(Cb-128/255), 0, 1)
+     *
+     * BT.601:
+     * Kr = 0.299
+     * Kb = 0.114
+     * Kg = (1.0 - Kr - Kb) = 0.587
      */
 
     /* Normalize Y, Cb and Cr:
      *
-     * Yn = (Y - 16/255) * 1.164
+     * Yn = (Y - 16/255) * 255/(235-16)
      * Crn = Cr - 128 / 255
      * Cbn = Cb - 128 / 255
      */
@@ -73,16 +82,19 @@ add (16)    Crn<1>F		Cr<8,8,1>F	-0.501961F  { compr align1 };
 
 add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
 
-    /* 
-     * R = Y + Cr * 1.596
+    /*
+     * R = Yn +
+     *     Crn * 255/112 * (1.0 - Kr)
      */
 mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
 mac.sat(8) src_sample_r_01<1>F	Crn_01<8,8,1>F	1.596F	    { compr align1 };
-     
+
 mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
 mac.sat(8) src_sample_r_23<1>F	Crn_23<8,8,1>F	1.596F	    { compr align1 };
     /*
-     * G = Crn * -0.813 + Cbn * -0.392 + Y
+     * G = Yn -
+     *     Crn * 255/112 * (1.0 - Kr) * Kr / Kg -
+     *     Cbn * 255/112 * (1.0 - Kb) * Kb / Kg
      */
 mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
 mac (8)    acc0<1>F		Crn_01<8,8,1>F    	-0.813F	    { compr align1 };
@@ -92,7 +104,8 @@ mov (8)    acc0<1>F		Yn_23<8,8,1>F	    { compr align1 };
 mac (8)    acc0<1>F		Crn_23<8,8,1>F    	-0.813F	    { compr align1 };
 mac.sat(16) src_sample_g_23<1>F	Cbn_23<8,8,1>F    	-0.392F	    { compr align1 };
     /*
-     * B = Cbn * 2.017 + Y
+     * B = Yn +
+     *     Cbn * 255/112 * (1.0 - Kb)
      */
 mov (8)    acc0<1>F	        Yn_01<8,8,1>F		    { compr align1 };
 mac.sat(8) src_sample_b_01<1>F	Cbn_01<8,8,1>F     2.017F	    { compr align1 };
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g4a b/src/render_program/exa_wm_yuv_rgb_bt709.g4a
new file mode 100644
index 00000000..e498f18f
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g4a
@@ -0,0 +1,111 @@
+/*
+ * 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:
+ *    Keith Packard <keithp at keithp.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+include(`exa_wm.g4i')
+
+define(`YCbCr_base',	`src_sample_base')
+
+define(`Cr',		`src_sample_r')
+define(`Cr_01',		`src_sample_r_01')
+define(`Cr_23',		`src_sample_r_23')
+
+define(`Y',		`src_sample_g')
+define(`Y_01',		`src_sample_g_01')
+define(`Y_23',		`src_sample_g_23')
+
+define(`Cb',		`src_sample_b')
+define(`Cb_01',		`src_sample_b_01')
+define(`Cb_23',		`src_sample_b_23')
+
+define(`Crn',		`mask_sample_r')
+define(`Crn_01',	`mask_sample_r_01')
+define(`Crn_23',	`mask_sample_r_23')
+
+define(`Yn',		`mask_sample_g')
+define(`Yn_01',		`mask_sample_g_01')
+define(`Yn_23',		`mask_sample_g_23')
+
+define(`Cbn',		`mask_sample_b')
+define(`Cbn_01',	`mask_sample_b_01')
+define(`Cbn_23',	`mask_sample_b_23')
+
+    /* color space conversion function:
+     * R = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kr)(Cr-128/255), 0, 1)
+     * G = Clamp ( 255/(235-16)(Y-16/255) -
+     *             255/112(1.0-Kr)Kr/Kg(Cr-128/255) -
+     *             255/112(1.0-Kb)Kb/Kg(Cb-128/255), 0, 1)
+     * B = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kb)(Cb-128/255), 0, 1)
+     *
+     * BT.709:
+     * Kr = .2126
+     * Kb = .0722
+     * Kg = (1.0 - Kr - Kb) = 0.7152
+     */
+
+    /* Normalize Y, Cb and Cr:
+     *
+     * Yn = (Y - 16/255) * 255/(235-16)
+     * Crn = Cr - 128 / 255
+     * Cbn = Cb - 128 / 255
+     */
+add (16)    Yn<1>F		Y<8,8,1>F	-0.0627451F { compr align1 };
+mul (16)    Yn<1>F		Yn<8,8,1>F	1.164F	    { compr align1 };
+
+add (16)    Crn<1>F		Cr<8,8,1>F	-0.501961F  { compr align1 };
+
+add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
+
+    /*
+     * R = Yn +
+     *     Crn * 255/112 * (1.0 - Kr)
+     */
+mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
+mac.sat(16) src_sample_r<1>F	Crn<8,8,1>F	1.793F	    { compr align1 };
+
+    /*
+     * G = Yn -
+     *     Crn * 255/112 * (1.0 - Kr) * Kr / Kg -
+     *     Cbn * 255/112 * (1.0 - Kb) * Kb / Kg
+     */
+mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
+mac (16)    acc0<1>F		Crn<8,8,1>F    	-0.533F	    { compr align1 };
+mac.sat(16) src_sample_g<1>F	Cbn<8,8,1>F    	-0.213F	    { compr align1 };
+
+    /*
+     * B = Yn +
+     *     Cbn * 255/112 * (1.0 - Kb)
+     */
+mov (16)    acc0<1>F	        Yn<8,8,1>F		    { compr align1 };
+mac.sat(16) src_sample_b<1>F	Cbn<8,8,1>F     2.112F	    { compr align1 };
+
+    /*
+     * A = 1.0
+     */
+mov (16)    src_sample_a<1>F	1.0F			    { compr align1 };
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g4b b/src/render_program/exa_wm_yuv_rgb_bt709.g4b
new file mode 100644
index 00000000..5b7621b5
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g4b
@@ -0,0 +1,12 @@
+   { 0x00802040, 0x23007fbd, 0x008d0200, 0xbd808081 },
+   { 0x00802041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
+   { 0x00802040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
+   { 0x00802040, 0x23407fbd, 0x008d0240, 0xbf008084 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x21c07fbd, 0x008d02c0, 0x3fe58106 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x00802048, 0x24007fbc, 0x008d02c0, 0xbf0872b0 },
+   { 0x80802048, 0x22007fbd, 0x008d0340, 0xbe5a1cac },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x22407fbd, 0x008d0340, 0x40072b02 },
+   { 0x00802001, 0x228003fd, 0x00000000, 0x3f800000 },
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g4b.gen5 b/src/render_program/exa_wm_yuv_rgb_bt709.g4b.gen5
new file mode 100644
index 00000000..5b7621b5
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g4b.gen5
@@ -0,0 +1,12 @@
+   { 0x00802040, 0x23007fbd, 0x008d0200, 0xbd808081 },
+   { 0x00802041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
+   { 0x00802040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
+   { 0x00802040, 0x23407fbd, 0x008d0240, 0xbf008084 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x21c07fbd, 0x008d02c0, 0x3fe58106 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x00802048, 0x24007fbc, 0x008d02c0, 0xbf0872b0 },
+   { 0x80802048, 0x22007fbd, 0x008d0340, 0xbe5a1cac },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x22407fbd, 0x008d0340, 0x40072b02 },
+   { 0x00802001, 0x228003fd, 0x00000000, 0x3f800000 },
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g5a b/src/render_program/exa_wm_yuv_rgb_bt709.g5a
new file mode 120000
index 00000000..9b4ca312
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g5a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt709.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g5b b/src/render_program/exa_wm_yuv_rgb_bt709.g5b
new file mode 100644
index 00000000..5b7621b5
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g5b
@@ -0,0 +1,12 @@
+   { 0x00802040, 0x23007fbd, 0x008d0200, 0xbd808081 },
+   { 0x00802041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
+   { 0x00802040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
+   { 0x00802040, 0x23407fbd, 0x008d0240, 0xbf008084 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x21c07fbd, 0x008d02c0, 0x3fe58106 },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x00802048, 0x24007fbc, 0x008d02c0, 0xbf0872b0 },
+   { 0x80802048, 0x22007fbd, 0x008d0340, 0xbe5a1cac },
+   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80802048, 0x22407fbd, 0x008d0340, 0x40072b02 },
+   { 0x00802001, 0x228003fd, 0x00000000, 0x3f800000 },
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g6a b/src/render_program/exa_wm_yuv_rgb_bt709.g6a
new file mode 120000
index 00000000..9b4ca312
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g6a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt709.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g6b b/src/render_program/exa_wm_yuv_rgb_bt709.g6b
new file mode 100644
index 00000000..392957e7
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g6b
@@ -0,0 +1,12 @@
+   { 0x00800040, 0x23007fbd, 0x008d0200, 0xbd808081 },
+   { 0x00800041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
+   { 0x00800040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
+   { 0x00800040, 0x23407fbd, 0x008d0240, 0xbf008084 },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80800048, 0x21c07fbd, 0x008d02c0, 0x3fe58106 },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x00800048, 0x24007fbc, 0x008d02c0, 0xbf0872b0 },
+   { 0x80800048, 0x22007fbd, 0x008d0340, 0xbe5a1cac },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80800048, 0x22407fbd, 0x008d0340, 0x40072b02 },
+   { 0x00800001, 0x228003fd, 0x00000000, 0x3f800000 },
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g7a b/src/render_program/exa_wm_yuv_rgb_bt709.g7a
new file mode 120000
index 00000000..9b4ca312
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g7a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt709.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g7b b/src/render_program/exa_wm_yuv_rgb_bt709.g7b
new file mode 100644
index 00000000..392957e7
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g7b
@@ -0,0 +1,12 @@
+   { 0x00800040, 0x23007fbd, 0x008d0200, 0xbd808081 },
+   { 0x00800041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
+   { 0x00800040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
+   { 0x00800040, 0x23407fbd, 0x008d0240, 0xbf008084 },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80800048, 0x21c07fbd, 0x008d02c0, 0x3fe58106 },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x00800048, 0x24007fbc, 0x008d02c0, 0xbf0872b0 },
+   { 0x80800048, 0x22007fbd, 0x008d0340, 0xbe5a1cac },
+   { 0x00800001, 0x240003bc, 0x008d0300, 0x00000000 },
+   { 0x80800048, 0x22407fbd, 0x008d0340, 0x40072b02 },
+   { 0x00800001, 0x228003fd, 0x00000000, 0x3f800000 },
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g8a b/src/render_program/exa_wm_yuv_rgb_bt709.g8a
new file mode 100644
index 00000000..9ab2ca0d
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g8a
@@ -0,0 +1,118 @@
+/*
+ * 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:
+ *    Keith Packard <keithp at keithp.com>
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+include(`exa_wm.g4i')
+
+define(`YCbCr_base',	`src_sample_base')
+
+define(`Cr',		`src_sample_r')
+define(`Cr_01',		`src_sample_r_01')
+define(`Cr_23',		`src_sample_r_23')
+
+define(`Y',		`src_sample_g')
+define(`Y_01',		`src_sample_g_01')
+define(`Y_23',		`src_sample_g_23')
+
+define(`Cb',		`src_sample_b')
+define(`Cb_01',		`src_sample_b_01')
+define(`Cb_23',		`src_sample_b_23')
+
+define(`Crn',		`mask_sample_r')
+define(`Crn_01',	`mask_sample_r_01')
+define(`Crn_23',	`mask_sample_r_23')
+
+define(`Yn',		`mask_sample_g')
+define(`Yn_01',		`mask_sample_g_01')
+define(`Yn_23',		`mask_sample_g_23')
+
+define(`Cbn',		`mask_sample_b')
+define(`Cbn_01',	`mask_sample_b_01')
+define(`Cbn_23',	`mask_sample_b_23')
+
+    /* color space conversion function:
+     * R = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kr)(Cr-128/255), 0, 1)
+     * G = Clamp ( 255/(235-16)(Y-16/255) -
+     *             255/112(1.0-Kr)Kr/Kg(Cr-128/255) -
+     *             255/112(1.0-Kb)Kb/Kg(Cb-128/255), 0, 1)
+     * B = Clamp ( 255/(235-16)(Y-16/255) +
+     *             255/112(1.0-Kb)(Cb-128/255), 0, 1)
+     *
+     * BT.709:
+     * Kr = .2126
+     * Kb = .0722
+     * Kg = (1.0 - Kr - Kb) = 0.7152
+     */
+
+    /* Normalize Y, Cb and Cr:
+     *
+     * Yn = (Y - 16/255) * 255/(235-16)
+     * Crn = Cr - 128 / 255
+     * Cbn = Cb - 128 / 255
+     */
+add (16)    Yn<1>F		Y<8,8,1>F	-0.0627451F { compr align1 };
+mul (16)    Yn<1>F		Yn<8,8,1>F	1.164F	    { compr align1 };
+
+add (16)    Crn<1>F		Cr<8,8,1>F	-0.501961F  { compr align1 };
+
+add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
+
+    /*
+     * R = Yn +
+     *     Crn * 255/112 * (1.0 - Kr)
+     */
+mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
+mac.sat(8) src_sample_r_01<1>F	Crn_01<8,8,1>F	1.793F	    { compr align1 };
+
+mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
+mac.sat(8) src_sample_r_23<1>F	Crn_23<8,8,1>F	1.793F	    { compr align1 };
+    /*
+     * G = Yn -
+     *     Crn * 255/112 * (1.0 - Kr) * Kr / Kg
+     *     Cbn * 255/112 * (1.0 - Kb) * Kb / Kg
+     */
+mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
+mac (8)    acc0<1>F		Crn_01<8,8,1>F    	-0.533F	    { compr align1 };
+mac.sat(8) src_sample_g_01<1>F	Cbn_01<8,8,1>F    	-0.213F	    { compr align1 };
+
+mov (8)    acc0<1>F		Yn_23<8,8,1>F	    { compr align1 };
+mac (8)    acc0<1>F		Crn_23<8,8,1>F    	-0.533F	    { compr align1 };
+mac.sat(16) src_sample_g_23<1>F	Cbn_23<8,8,1>F    	-0.213F	    { compr align1 };
+    /*
+     * B = Yn +
+     *     Cbn * 255/112 * (1.0 - Kb)
+     */
+mov (8)    acc0<1>F	        Yn_01<8,8,1>F		    { compr align1 };
+mac.sat(8) src_sample_b_01<1>F	Cbn_01<8,8,1>F     2.112F	    { compr align1 };
+
+mov (8)    acc0<1>F	        Yn_23<8,8,1>F		    { compr align1 };
+mac.sat(8) src_sample_b_23<1>F	Cbn_23<8,8,1>F     2.112F	    { compr align1 };
+    /*
+     * A = 1.0
+     */
+mov (16)    src_sample_a<1>F	1.0F			    { compr align1 };
diff --git a/src/render_program/exa_wm_yuv_rgb_bt709.g8b b/src/render_program/exa_wm_yuv_rgb_bt709.g8b
new file mode 100644
index 00000000..9bfe1ca4
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt709.g8b
@@ -0,0 +1,19 @@
+   { 0x00800040, 0x23003ae8, 0x3e8d0200, 0xbd808081 },
+   { 0x00800041, 0x23003ae8, 0x3e8d0300, 0x3f94fdf4 },
+   { 0x00800040, 0x22c03ae8, 0x3e8d01c0, 0xbf008084 },
+   { 0x00800040, 0x23403ae8, 0x3e8d0240, 0xbf008084 },
+   { 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
+   { 0x80600048, 0x21c03ae8, 0x3e8d02c0, 0x3fe58106 },
+   { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
+   { 0x80600048, 0x21e03ae8, 0x3e8d02e0, 0x3fe58106 },
+   { 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
+   { 0x00600048, 0x24003ae0, 0x3e8d02c0, 0xbf0872b0 },
+   { 0x80600048, 0x22003ae8, 0x3e8d0340, 0xbe5a1cac },
+   { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
+   { 0x00600048, 0x24003ae0, 0x3e8d02e0, 0xbf0872b0 },
+   { 0x80800048, 0x22203ae8, 0x3e8d0360, 0xbe5a1cac },
+   { 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
+   { 0x80600048, 0x22403ae8, 0x3e8d0340, 0x40072b02 },
+   { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
+   { 0x80600048, 0x22603ae8, 0x3e8d0360, 0x40072b02 },
+   { 0x00800001, 0x22803ee8, 0x38000000, 0x3f800000 },
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 01f8040f..b6a496ca 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -99,7 +99,7 @@
 #define GEN4_MAX_WM_THREADS 32
 #define G4X_MAX_WM_THREADS 50
 
-static const uint32_t ps_kernel_packed_static[][4] = {
+static const uint32_t ps_kernel_packed_bt601_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_argb.g4b"
@@ -107,7 +107,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_write.g4b"
 };
 
-static const uint32_t ps_kernel_planar_static[][4] = {
+static const uint32_t ps_kernel_planar_bt601_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_planar.g4b"
@@ -115,7 +115,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_write.g4b"
 };
 
-static const uint32_t ps_kernel_nv12_static[][4] = {
+static const uint32_t ps_kernel_nv12_bt601_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_nv12.g4b"
@@ -123,6 +123,30 @@ static const uint32_t ps_kernel_nv12_static[][4] = {
 #include "exa_wm_write.g4b"
 };
 
+static const uint32_t ps_kernel_packed_bt709_static[][4] = {
+#include "exa_wm_xy.g4b"
+#include "exa_wm_src_affine.g4b"
+#include "exa_wm_src_sample_argb.g4b"
+#include "exa_wm_yuv_rgb_bt709.g4b"
+#include "exa_wm_write.g4b"
+};
+
+static const uint32_t ps_kernel_planar_bt709_static[][4] = {
+#include "exa_wm_xy.g4b"
+#include "exa_wm_src_affine.g4b"
+#include "exa_wm_src_sample_planar.g4b"
+#include "exa_wm_yuv_rgb_bt709.g4b"
+#include "exa_wm_write.g4b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709_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_bt709.g4b"
+#include "exa_wm_write.g4b"
+};
+
 #define NOKERNEL(kernel_enum, func, masked) \
     [kernel_enum] = {func, 0, masked}
 #define KERNEL(kernel_enum, kernel, masked) \
@@ -147,9 +171,13 @@ static const struct wm_kernel_info {
 	NOKERNEL(WM_KERNEL_OPACITY, brw_wm_kernel__affine_opacity, true),
 	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),
+	KERNEL(WM_KERNEL_VIDEO_PLANAR_BT601, ps_kernel_planar_bt601_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12_BT601, ps_kernel_nv12_bt601_static, false),
+	KERNEL(WM_KERNEL_VIDEO_PACKED_BT601, ps_kernel_packed_bt601_static, false),
+
+	KERNEL(WM_KERNEL_VIDEO_PLANAR_BT709, ps_kernel_planar_bt709_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12_BT709, ps_kernel_nv12_bt709_static, false),
+	KERNEL(WM_KERNEL_VIDEO_PACKED_BT709, ps_kernel_packed_bt709_static, false),
 };
 #undef KERNEL
 
@@ -1404,6 +1432,29 @@ static void gen4_video_bind_surfaces(struct sna *sna,
 	gen4_emit_state(sna, op, offset | dirty);
 }
 
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
+{
+	switch (frame->id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_PLANAR_BT709 :
+			WM_KERNEL_VIDEO_PLANAR_BT601;
+
+	case FOURCC_NV12:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_NV12_BT709 :
+			WM_KERNEL_VIDEO_NV12_BT601;
+
+	default:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_PACKED_BT709 :
+			WM_KERNEL_VIDEO_PACKED_BT601;
+	}
+}
+
 static bool
 gen4_render_video(struct sna *sna,
 		  struct sna_video *video,
@@ -1442,9 +1493,7 @@ gen4_render_video(struct sna *sna,
 	tmp.src.repeat = SAMPLER_EXTEND_PAD;
 	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.wm_kernel = select_video_kernel(video, frame);
 	tmp.u.gen4.ve_id = 2;
 	tmp.is_affine = true;
 	tmp.floats_per_vertex = 3;
diff --git a/src/sna/gen4_render.h b/src/sna/gen4_render.h
index 3b37f96a..f516c316 100644
--- a/src/sna/gen4_render.h
+++ b/src/sna/gen4_render.h
@@ -2685,9 +2685,14 @@ typedef enum {
 	WM_KERNEL_OPACITY,
 	WM_KERNEL_OPACITY_P,
 
-	WM_KERNEL_VIDEO_PLANAR,
-	WM_KERNEL_VIDEO_NV12,
-	WM_KERNEL_VIDEO_PACKED,
+	WM_KERNEL_VIDEO_PLANAR_BT601,
+	WM_KERNEL_VIDEO_NV12_BT601,
+	WM_KERNEL_VIDEO_PACKED_BT601,
+
+	WM_KERNEL_VIDEO_PLANAR_BT709,
+	WM_KERNEL_VIDEO_NV12_BT709,
+	WM_KERNEL_VIDEO_PACKED_BT709,
+
 	KERNEL_COUNT
 } wm_kernel_t;
 
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index bed4a3ed..3d9d35f1 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -89,7 +89,7 @@
 #define PS_KERNEL_NUM_GRF   32
 #define PS_MAX_THREADS	    72
 
-static const uint32_t ps_kernel_packed_static[][4] = {
+static const uint32_t ps_kernel_packed_bt601_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_argb.g5b"
@@ -97,7 +97,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_write.g5b"
 };
 
-static const uint32_t ps_kernel_planar_static[][4] = {
+static const uint32_t ps_kernel_planar_bt601_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_planar.g5b"
@@ -105,7 +105,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_write.g5b"
 };
 
-static const uint32_t ps_kernel_nv12_static[][4] = {
+static const uint32_t ps_kernel_nv12_bt601_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_nv12.g5b"
@@ -113,6 +113,30 @@ static const uint32_t ps_kernel_nv12_static[][4] = {
 #include "exa_wm_write.g5b"
 };
 
+static const uint32_t ps_kernel_packed_bt709_static[][4] = {
+#include "exa_wm_xy.g5b"
+#include "exa_wm_src_affine.g5b"
+#include "exa_wm_src_sample_argb.g5b"
+#include "exa_wm_yuv_rgb_bt709.g5b"
+#include "exa_wm_write.g5b"
+};
+
+static const uint32_t ps_kernel_planar_bt709_static[][4] = {
+#include "exa_wm_xy.g5b"
+#include "exa_wm_src_affine.g5b"
+#include "exa_wm_src_sample_planar.g5b"
+#include "exa_wm_yuv_rgb_bt709.g5b"
+#include "exa_wm_write.g5b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709_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_bt709.g5b"
+#include "exa_wm_write.g5b"
+};
+
 #define NOKERNEL(kernel_enum, func, masked) \
     [kernel_enum] = {func, 0, masked}
 #define KERNEL(kernel_enum, kernel, masked) \
@@ -137,9 +161,13 @@ static const struct wm_kernel_info {
 	NOKERNEL(WM_KERNEL_OPACITY, brw_wm_kernel__affine_opacity, true),
 	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),
+	KERNEL(WM_KERNEL_VIDEO_PLANAR_BT601, ps_kernel_planar_bt601_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12_BT601, ps_kernel_nv12_bt601_static, false),
+	KERNEL(WM_KERNEL_VIDEO_PACKED_BT601, ps_kernel_packed_bt601_static, false),
+
+	KERNEL(WM_KERNEL_VIDEO_PLANAR_BT709, ps_kernel_planar_bt709_static, false),
+	KERNEL(WM_KERNEL_VIDEO_NV12_BT709, ps_kernel_nv12_bt709_static, false),
+	KERNEL(WM_KERNEL_VIDEO_PACKED_BT709, ps_kernel_packed_bt709_static, false),
 };
 #undef KERNEL
 
@@ -1354,6 +1382,29 @@ static void gen5_video_bind_surfaces(struct sna *sna,
 	gen5_emit_state(sna, op, offset | dirty);
 }
 
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
+{
+	switch (frame->id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_PLANAR_BT709 :
+			WM_KERNEL_VIDEO_PLANAR_BT601;
+
+	case FOURCC_NV12:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_NV12_BT709 :
+			WM_KERNEL_VIDEO_NV12_BT601;
+
+	default:
+		return video->colorspace ?
+			WM_KERNEL_VIDEO_PACKED_BT709 :
+			WM_KERNEL_VIDEO_PACKED_BT601;
+	}
+}
+
 static bool
 gen5_render_video(struct sna *sna,
 		  struct sna_video *video,
@@ -1392,9 +1443,7 @@ gen5_render_video(struct sna *sna,
 	tmp.src.repeat = SAMPLER_EXTEND_PAD;
 	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.wm_kernel = select_video_kernel(video, frame);
 	tmp.u.gen5.ve_id = 2;
 	tmp.is_affine = true;
 	tmp.floats_per_vertex = 3;
diff --git a/src/sna/gen5_render.h b/src/sna/gen5_render.h
index f1a9a68c..8901480a 100644
--- a/src/sna/gen5_render.h
+++ b/src/sna/gen5_render.h
@@ -2765,9 +2765,14 @@ typedef enum {
 	WM_KERNEL_OPACITY,
 	WM_KERNEL_OPACITY_P,
 
-	WM_KERNEL_VIDEO_PLANAR,
-	WM_KERNEL_VIDEO_NV12,
-	WM_KERNEL_VIDEO_PACKED,
+	WM_KERNEL_VIDEO_PLANAR_BT601,
+	WM_KERNEL_VIDEO_NV12_BT601,
+	WM_KERNEL_VIDEO_PACKED_BT601,
+
+	WM_KERNEL_VIDEO_PLANAR_BT709,
+	WM_KERNEL_VIDEO_NV12_BT709,
+	WM_KERNEL_VIDEO_PACKED_BT709,
+
 	KERNEL_COUNT
 } wm_kernel_t;
 #endif
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 39ea5b6f..0a53ef56 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -101,27 +101,48 @@ static const struct gt_info gt2_info = {
 	.gt = 2,
 };
 
-static const uint32_t ps_kernel_packed[][4] = {
+static const uint32_t ps_kernel_packed_bt601[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_argb.g6b"
 #include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
-static const uint32_t ps_kernel_planar[][4] = {
+static const uint32_t ps_kernel_planar_bt601[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_planar.g6b"
 #include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
-static const uint32_t ps_kernel_nv12[][4] = {
+static const uint32_t ps_kernel_nv12_bt601[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_nv12.g6b"
 #include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
+static const uint32_t ps_kernel_packed_bt709[][4] = {
+#include "exa_wm_src_affine.g6b"
+#include "exa_wm_src_sample_argb.g6b"
+#include "exa_wm_yuv_rgb_bt709.g6b"
+#include "exa_wm_write.g6b"
+};
+
+static const uint32_t ps_kernel_planar_bt709[][4] = {
+#include "exa_wm_src_affine.g6b"
+#include "exa_wm_src_sample_planar.g6b"
+#include "exa_wm_yuv_rgb_bt709.g6b"
+#include "exa_wm_write.g6b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709[][4] = {
+#include "exa_wm_src_affine.g6b"
+#include "exa_wm_src_sample_nv12.g6b"
+#include "exa_wm_yuv_rgb_bt709.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) \
@@ -148,9 +169,14 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY, brw_wm_kernel__affine_opacity, 2),
 	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_PLANAR_BT601, ps_kernel_planar_bt601, 7),
+	KERNEL(VIDEO_NV12_BT601, ps_kernel_nv12_bt601, 7),
+	KERNEL(VIDEO_PACKED_BT601, ps_kernel_packed_bt601, 2),
+
+	KERNEL(VIDEO_PLANAR_BT709, ps_kernel_planar_bt709, 7),
+	KERNEL(VIDEO_NV12_BT709, ps_kernel_nv12_bt709, 7),
+	KERNEL(VIDEO_PACKED_BT709, ps_kernel_packed_bt709, 2),
 };
 #undef KERNEL
 
@@ -1631,6 +1657,29 @@ static void gen6_emit_video_state(struct sna *sna,
 	gen6_emit_state(sna, op, offset | dirty);
 }
 
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
+{
+	switch (frame->id) {
+	case FOURCC_YV12:
+	case FOURCC_I420:
+	case FOURCC_XVMC:
+		return video->colorspace ?
+			GEN6_WM_KERNEL_VIDEO_PLANAR_BT709 :
+			GEN6_WM_KERNEL_VIDEO_PLANAR_BT601;
+
+	case FOURCC_NV12:
+		return video->colorspace ?
+			GEN6_WM_KERNEL_VIDEO_NV12_BT709 :
+			GEN6_WM_KERNEL_VIDEO_NV12_BT601;
+
+	default:
+		return video->colorspace ?
+			GEN6_WM_KERNEL_VIDEO_PACKED_BT709 :
+			GEN6_WM_KERNEL_VIDEO_PACKED_BT601;
+	}
+}
+
 static bool
 gen6_render_video(struct sna *sna,
 		  struct sna_video *video,
@@ -1683,11 +1732,7 @@ 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,
+			       select_video_kernel(video, frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index b1fdfb51..0a3bda76 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -193,27 +193,48 @@ inline static bool is_hsw(struct sna *sna)
 	return sna->kgem.gen == 075;
 }
 
-static const uint32_t ps_kernel_packed[][4] = {
+static const uint32_t ps_kernel_packed_bt601[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_argb.g7b"
 #include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
-static const uint32_t ps_kernel_planar[][4] = {
+static const uint32_t ps_kernel_planar_bt601[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_planar.g7b"
 #include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
-static const uint32_t ps_kernel_nv12[][4] = {
+static const uint32_t ps_kernel_nv12_bt601[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_nv12.g7b"
 #include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
+static const uint32_t ps_kernel_packed_bt709[][4] = {
+#include "exa_wm_src_affine.g7b"
+#include "exa_wm_src_sample_argb.g7b"
+#include "exa_wm_yuv_rgb_bt709.g7b"
+#include "exa_wm_write.g7b"
+};
+
+static const uint32_t ps_kernel_planar_bt709[][4] = {
+#include "exa_wm_src_affine.g7b"
+#include "exa_wm_src_sample_planar.g7b"
+#include "exa_wm_yuv_rgb_bt709.g7b"
+#include "exa_wm_write.g7b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709[][4] = {
+#include "exa_wm_src_affine.g7b"
+#include "exa_wm_src_sample_nv12.g7b"
+#include "exa_wm_yuv_rgb_bt709.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"
@@ -245,9 +266,12 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY, brw_wm_kernel__affine_opacity, 2),
 	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_PLANAR_BT601, ps_kernel_planar_bt601, 7),
+	KERNEL(VIDEO_NV12_BT601, ps_kernel_nv12_bt601, 7),
+	KERNEL(VIDEO_PACKED_BT601, ps_kernel_packed_bt601, 2),
+	KERNEL(VIDEO_PLANAR_BT709, ps_kernel_planar_bt709, 7),
+	KERNEL(VIDEO_NV12_BT709, ps_kernel_nv12_bt709, 7),
+	KERNEL(VIDEO_PACKED_BT709, ps_kernel_packed_bt709, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 };
 #undef KERNEL
@@ -1846,23 +1870,30 @@ 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)
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
 {
 	switch (frame->id) {
 	case FOURCC_YV12:
 	case FOURCC_I420:
 	case FOURCC_XVMC:
-		return GEN7_WM_KERNEL_VIDEO_PLANAR;
+		return video->colorspace ?
+			GEN7_WM_KERNEL_VIDEO_PLANAR_BT709 :
+			GEN7_WM_KERNEL_VIDEO_PLANAR_BT601;
 
 	case FOURCC_NV12:
-		return GEN7_WM_KERNEL_VIDEO_NV12;
+		return video->colorspace ?
+			GEN7_WM_KERNEL_VIDEO_NV12_BT709 :
+			GEN7_WM_KERNEL_VIDEO_NV12_BT601;
 
 	case FOURCC_RGB888:
 	case FOURCC_RGB565:
 		return GEN7_WM_KERNEL_VIDEO_RGB;
 
 	default:
-		return GEN7_WM_KERNEL_VIDEO_PACKED;
+		return video->colorspace ?
+			GEN7_WM_KERNEL_VIDEO_PACKED_BT709 :
+			GEN7_WM_KERNEL_VIDEO_PACKED_BT601;
 	}
 }
 
@@ -1918,7 +1949,7 @@ gen7_render_video(struct sna *sna,
 		GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
-			       select_video_kernel(frame),
+			       select_video_kernel(video, frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index eadb09eb..69617da5 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -93,27 +93,48 @@
  */
 
 #if !NO_VIDEO
-static const uint32_t ps_kernel_packed[][4] = {
+static const uint32_t ps_kernel_packed_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_argb.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
-static const uint32_t ps_kernel_planar[][4] = {
+static const uint32_t ps_kernel_planar_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_planar.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
-static const uint32_t ps_kernel_nv12[][4] = {
+static const uint32_t ps_kernel_nv12_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_nv12.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
+static const uint32_t ps_kernel_packed_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_argb.g8b"
+#include "exa_wm_yuv_rgb_bt709.g8b"
+#include "exa_wm_write.g8b"
+};
+
+static const uint32_t ps_kernel_planar_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_planar.g8b"
+#include "exa_wm_yuv_rgb_bt709.g8b"
+#include "exa_wm_write.g8b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_nv12.g8b"
+#include "exa_wm_yuv_rgb_bt709.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"
@@ -149,9 +170,12 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY_P, gen8_wm_kernel__projective_opacity, 2),
 
 #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_PLANAR_BT601, ps_kernel_planar_bt601, 7),
+	KERNEL(VIDEO_NV12_BT601, ps_kernel_nv12_bt601, 7),
+	KERNEL(VIDEO_PACKED_BT601, ps_kernel_packed_bt601, 2),
+	KERNEL(VIDEO_PLANAR_BT709, ps_kernel_planar_bt709, 7),
+	KERNEL(VIDEO_NV12_BT709, ps_kernel_nv12_bt709, 7),
+	KERNEL(VIDEO_PACKED_BT709, ps_kernel_packed_bt709, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 #endif
 };
@@ -3790,23 +3814,30 @@ 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)
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
 {
 	switch (frame->id) {
 	case FOURCC_YV12:
 	case FOURCC_I420:
 	case FOURCC_XVMC:
-		return GEN8_WM_KERNEL_VIDEO_PLANAR;
+		return video->colorspace ?
+			GEN8_WM_KERNEL_VIDEO_PLANAR_BT709 :
+			GEN8_WM_KERNEL_VIDEO_PLANAR_BT601;
 
 	case FOURCC_NV12:
-		return GEN8_WM_KERNEL_VIDEO_NV12;
+		return video->colorspace ?
+			GEN8_WM_KERNEL_VIDEO_NV12_BT709 :
+			GEN8_WM_KERNEL_VIDEO_NV12_BT601;
 
 	case FOURCC_RGB888:
 	case FOURCC_RGB565:
 		return GEN8_WM_KERNEL_VIDEO_RGB;
 
 	default:
-		return GEN8_WM_KERNEL_VIDEO_PACKED;
+		return video->colorspace ?
+			GEN8_WM_KERNEL_VIDEO_PACKED_BT709 :
+			GEN8_WM_KERNEL_VIDEO_PACKED_BT601;
 	}
 }
 
@@ -3870,7 +3901,7 @@ gen8_render_video(struct sna *sna,
 		GEN8_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
-			       select_video_kernel(frame),
+			       select_video_kernel(video, frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c
index 721a186a..505b98af 100644
--- a/src/sna/gen9_render.c
+++ b/src/sna/gen9_render.c
@@ -94,27 +94,48 @@
  */
 
 #if !NO_VIDEO
-static const uint32_t ps_kernel_packed[][4] = {
+static const uint32_t ps_kernel_packed_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_argb.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
-static const uint32_t ps_kernel_planar[][4] = {
+static const uint32_t ps_kernel_planar_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_planar.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
-static const uint32_t ps_kernel_nv12[][4] = {
+static const uint32_t ps_kernel_nv12_bt601[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_nv12.g8b"
 #include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
+static const uint32_t ps_kernel_packed_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_argb.g8b"
+#include "exa_wm_yuv_rgb_bt709.g8b"
+#include "exa_wm_write.g8b"
+};
+
+static const uint32_t ps_kernel_planar_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_planar.g8b"
+#include "exa_wm_yuv_rgb_bt709.g8b"
+#include "exa_wm_write.g8b"
+};
+
+static const uint32_t ps_kernel_nv12_bt709[][4] = {
+#include "exa_wm_src_affine.g8b"
+#include "exa_wm_src_sample_nv12.g8b"
+#include "exa_wm_yuv_rgb_bt709.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"
@@ -150,9 +171,12 @@ static const struct wm_kernel_info {
 	NOKERNEL(OPACITY_P, gen8_wm_kernel__projective_opacity, 2),
 
 #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_PLANAR_BT601, ps_kernel_planar_bt601, 7),
+	KERNEL(VIDEO_NV12_BT601, ps_kernel_nv12_bt601, 7),
+	KERNEL(VIDEO_PACKED_BT601, ps_kernel_packed_bt601, 2),
+	KERNEL(VIDEO_PLANAR_BT709, ps_kernel_planar_bt709, 7),
+	KERNEL(VIDEO_NV12_BT709, ps_kernel_nv12_bt709, 7),
+	KERNEL(VIDEO_PACKED_BT709, ps_kernel_packed_bt709, 2),
 	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
 #endif
 };
@@ -3853,23 +3877,30 @@ static void gen9_emit_video_state(struct sna *sna,
 	gen9_emit_state(sna, op, offset);
 }
 
-static unsigned select_video_kernel(const struct sna_video_frame *frame)
+static unsigned select_video_kernel(const struct sna_video *video,
+				    const struct sna_video_frame *frame)
 {
 	switch (frame->id) {
 	case FOURCC_YV12:
 	case FOURCC_I420:
 	case FOURCC_XVMC:
-		return GEN9_WM_KERNEL_VIDEO_PLANAR;
+		return video->colorspace ?
+			GEN9_WM_KERNEL_VIDEO_PLANAR_BT709 :
+			GEN9_WM_KERNEL_VIDEO_PLANAR_BT601;
 
 	case FOURCC_NV12:
-		return GEN9_WM_KERNEL_VIDEO_NV12;
+		return video->colorspace ?
+			GEN9_WM_KERNEL_VIDEO_NV12_BT709 :
+			GEN9_WM_KERNEL_VIDEO_NV12_BT601;
 
 	case FOURCC_RGB888:
 	case FOURCC_RGB565:
 		return GEN9_WM_KERNEL_VIDEO_RGB;
 
 	default:
-		return GEN9_WM_KERNEL_VIDEO_PACKED;
+		return video->colorspace ?
+			GEN9_WM_KERNEL_VIDEO_PACKED_BT709 :
+			GEN9_WM_KERNEL_VIDEO_PACKED_BT601;
 	}
 }
 
@@ -3933,7 +3964,7 @@ gen9_render_video(struct sna *sna,
 		GEN9_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
 			       NO_BLEND,
-			       select_video_kernel(frame),
+			       select_video_kernel(video, frame),
 			       2);
 	tmp.priv = frame;
 
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 730cb21f..6669af9d 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -436,9 +436,14 @@ enum {
 	GEN6_WM_KERNEL_OPACITY,
 	GEN6_WM_KERNEL_OPACITY_P,
 
-	GEN6_WM_KERNEL_VIDEO_PLANAR,
-	GEN6_WM_KERNEL_VIDEO_NV12,
-	GEN6_WM_KERNEL_VIDEO_PACKED,
+	GEN6_WM_KERNEL_VIDEO_PLANAR_BT601,
+	GEN6_WM_KERNEL_VIDEO_NV12_BT601,
+	GEN6_WM_KERNEL_VIDEO_PACKED_BT601,
+
+	GEN6_WM_KERNEL_VIDEO_PLANAR_BT709,
+	GEN6_WM_KERNEL_VIDEO_NV12_BT709,
+	GEN6_WM_KERNEL_VIDEO_PACKED_BT709,
+
 	GEN6_KERNEL_COUNT
 };
 
@@ -487,9 +492,14 @@ enum {
 	GEN7_WM_KERNEL_OPACITY,
 	GEN7_WM_KERNEL_OPACITY_P,
 
-	GEN7_WM_KERNEL_VIDEO_PLANAR,
-	GEN7_WM_KERNEL_VIDEO_NV12,
-	GEN7_WM_KERNEL_VIDEO_PACKED,
+	GEN7_WM_KERNEL_VIDEO_PLANAR_BT601,
+	GEN7_WM_KERNEL_VIDEO_NV12_BT601,
+	GEN7_WM_KERNEL_VIDEO_PACKED_BT601,
+
+	GEN7_WM_KERNEL_VIDEO_PLANAR_BT709,
+	GEN7_WM_KERNEL_VIDEO_NV12_BT709,
+	GEN7_WM_KERNEL_VIDEO_PACKED_BT709,
+
 	GEN7_WM_KERNEL_VIDEO_RGB,
 	GEN7_WM_KERNEL_COUNT
 };
@@ -541,9 +551,14 @@ enum {
 	GEN8_WM_KERNEL_OPACITY,
 	GEN8_WM_KERNEL_OPACITY_P,
 
-	GEN8_WM_KERNEL_VIDEO_PLANAR,
-	GEN8_WM_KERNEL_VIDEO_NV12,
-	GEN8_WM_KERNEL_VIDEO_PACKED,
+	GEN8_WM_KERNEL_VIDEO_PLANAR_BT601,
+	GEN8_WM_KERNEL_VIDEO_NV12_BT601,
+	GEN8_WM_KERNEL_VIDEO_PACKED_BT601,
+
+	GEN8_WM_KERNEL_VIDEO_PLANAR_BT709,
+	GEN8_WM_KERNEL_VIDEO_NV12_BT709,
+	GEN8_WM_KERNEL_VIDEO_PACKED_BT709,
+
 	GEN8_WM_KERNEL_VIDEO_RGB,
 	GEN8_WM_KERNEL_COUNT
 };
@@ -593,9 +608,14 @@ enum {
 	GEN9_WM_KERNEL_OPACITY,
 	GEN9_WM_KERNEL_OPACITY_P,
 
-	GEN9_WM_KERNEL_VIDEO_PLANAR,
-	GEN9_WM_KERNEL_VIDEO_NV12,
-	GEN9_WM_KERNEL_VIDEO_PACKED,
+	GEN9_WM_KERNEL_VIDEO_PLANAR_BT601,
+	GEN9_WM_KERNEL_VIDEO_NV12_BT601,
+	GEN9_WM_KERNEL_VIDEO_PACKED_BT601,
+
+	GEN9_WM_KERNEL_VIDEO_PLANAR_BT709,
+	GEN9_WM_KERNEL_VIDEO_NV12_BT709,
+	GEN9_WM_KERNEL_VIDEO_PACKED_BT709,
+
 	GEN9_WM_KERNEL_VIDEO_RGB,
 	GEN9_WM_KERNEL_COUNT
 };
diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
index bcd42320..a784fe2e 100644
--- a/src/sna/sna_video_textured.c
+++ b/src/sna/sna_video_textured.c
@@ -36,7 +36,7 @@
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, true)
 
-static Atom xvBrightness, xvContrast, xvSyncToVblank;
+static Atom xvBrightness, xvContrast, xvSyncToVblank, xvColorspace;
 
 static XvFormatRec Formats[] = {
 	{15}, {16}, {24}
@@ -44,6 +44,7 @@ static XvFormatRec Formats[] = {
 
 static const XvAttributeRec Attributes[] = {
 	{XvSettable | XvGettable, -1, 1, (char *)"XV_SYNC_TO_VBLANK"},
+	{XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"}, /* BT.601, BT.709 */
 	//{XvSettable | XvGettable, -128, 127, (char *)"XV_BRIGHTNESS"},
 	//{XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"},
 };
@@ -102,6 +103,11 @@ sna_video_textured_set_attribute(ddSetPortAttribute_ARGS)
 			return BadValue;
 
 		video->SyncToVblank = value;
+	} else if (attribute == xvColorspace) {
+		if (value < 0 || value > 1)
+			return BadValue;
+
+		video->colorspace = value;
 	} else
 		return BadMatch;
 
@@ -119,6 +125,8 @@ sna_video_textured_get_attribute(ddGetPortAttribute_ARGS)
 		*value = video->contrast;
 	else if (attribute == xvSyncToVblank)
 		*value = video->SyncToVblank;
+	else if (attribute == xvColorspace)
+		*value = video->colorspace;
 	else
 		return BadMatch;
 
@@ -426,6 +434,7 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
 		v->sna = sna;
 		v->textured = true;
 		v->alignment = 4;
+		v->colorspace = 1; /* BT.709 */
 		v->SyncToVblank = (sna->flags & SNA_NO_WAIT) == 0;
 
 		RegionNull(&v->clip);
@@ -446,6 +455,7 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
 
 	xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
 	xvContrast = MAKE_ATOM("XV_CONTRAST");
+	xvColorspace = MAKE_ATOM("XV_COLORSPACE");
 	xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
 
 	DBG(("%s: '%s' initialized %d ports\n", __FUNCTION__, adaptor->name, adaptor->nPorts));
commit 35a9e96992a9298577d81e6b98c1329475282db1
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:09 2018 +0300

    Rename current yuv->rgb shader sources to exa_wm_yuv_rgb_bt601
    
    Our current yuv->rgb shaders follow the BT.601 conversion formula.
    Rename the shader sources to indicate that fact.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/render_program/Makefile.am b/src/render_program/Makefile.am
index 7b835e1a..44936734 100644
--- a/src/render_program/Makefile.am
+++ b/src/render_program/Makefile.am
@@ -15,7 +15,7 @@ INTEL_G4A =				\
 	exa_wm_ca.g4a			\
 	exa_wm_ca_srcalpha.g4a		\
 	exa_wm_write.g4a 		\
-	exa_wm_yuv_rgb.g4a		\
+	exa_wm_yuv_rgb_bt601.g4a	\
 	exa_wm_xy.g4a			\
 	$(NULL)
 
@@ -45,7 +45,7 @@ INTEL_G4B = 				\
 	exa_wm_ca.g4b			\
 	exa_wm_ca_srcalpha.g4b		\
 	exa_wm_write.g4b 		\
-	exa_wm_yuv_rgb.g4b		\
+	exa_wm_yuv_rgb_bt601.g4b	\
 	exa_wm_xy.g4b			\
 	$(NULL)
 
@@ -67,7 +67,7 @@ INTEL_G4B_GEN5 = 				\
 	exa_wm_ca.g4b.gen5			\
 	exa_wm_ca_srcalpha.g4b.gen5		\
 	exa_wm_write.g4b.gen5 			\
-	exa_wm_yuv_rgb.g4b.gen5			\
+	exa_wm_yuv_rgb_bt601.g4b.gen5		\
 	exa_wm_xy.g4b.gen5			\
 	$(NULL)
 
@@ -88,7 +88,7 @@ INTEL_G5A =				\
 	exa_wm_ca.g5a			\
 	exa_wm_ca_srcalpha.g5a		\
 	exa_wm_write.g5a 		\
-	exa_wm_yuv_rgb.g5a		\
+	exa_wm_yuv_rgb_bt601.g5a	\
 	exa_wm_xy.g5a			\
 	$(NULL)
 
@@ -109,7 +109,7 @@ INTEL_G5B = 				\
 	exa_wm_ca.g5b			\
 	exa_wm_ca_srcalpha.g5b		\
 	exa_wm_write.g5b 		\
-	exa_wm_yuv_rgb.g5b		\
+	exa_wm_yuv_rgb_bt601.g5b	\
 	exa_wm_xy.g5b			\
 	$(NULL)
 
@@ -133,7 +133,7 @@ INTEL_G6A =				\
 	exa_wm_ca_srcalpha.g6a		\
 	exa_wm_noca.g6a			\
 	exa_wm_write.g6a 		\
-	exa_wm_yuv_rgb.g6a		\
+	exa_wm_yuv_rgb_bt601.g6a	\
 	$(NULL)
 
 INTEL_G6B =				\
@@ -151,7 +151,7 @@ INTEL_G6B =				\
 	exa_wm_ca_srcalpha.g6b		\
 	exa_wm_noca.g6b			\
 	exa_wm_write.g6b 		\
-	exa_wm_yuv_rgb.g6b		\
+	exa_wm_yuv_rgb_bt601.g6b	\
 	$(NULL)
 
 INTEL_G7A =				\
@@ -166,7 +166,7 @@ INTEL_G7A =				\
 	exa_wm_src_sample_nv12.g7a 	\
 	exa_wm_src_sample_planar.g7a 	\
 	exa_wm_write.g7a 		\
-	exa_wm_yuv_rgb.g7a		\
+	exa_wm_yuv_rgb_bt601.g7a	\
 	$(NULL)
 
 INTEL_G7B =				\
@@ -181,7 +181,7 @@ INTEL_G7B =				\
 	exa_wm_src_sample_nv12.g7b 	\
 	exa_wm_src_sample_planar.g7b 	\
 	exa_wm_write.g7b 		\
-	exa_wm_yuv_rgb.g7b		\
+	exa_wm_yuv_rgb_bt601.g7b	\
 	$(NULL)
 
 INTEL_G8A =				\
@@ -190,7 +190,7 @@ INTEL_G8A =				\
 	exa_wm_src_sample_nv12.g8a 	\
 	exa_wm_src_sample_planar.g8a 	\
 	exa_wm_write.g8a 		\
-	exa_wm_yuv_rgb.g8a		\
+	exa_wm_yuv_rgb_bt601.g8a	\
 	$(NULL)
 
 INTEL_G8B =				\
@@ -199,7 +199,7 @@ INTEL_G8B =				\
 	exa_wm_src_sample_nv12.g8b 	\
 	exa_wm_src_sample_planar.g8b 	\
 	exa_wm_write.g8b 		\
-	exa_wm_yuv_rgb.g8b		\
+	exa_wm_yuv_rgb_bt601.g8b	\
 	$(NULL)
 
 EXTRA_DIST = 		\
diff --git a/src/render_program/exa_wm_yuv_rgb.g5a b/src/render_program/exa_wm_yuv_rgb.g5a
deleted file mode 120000
index d34d246d..00000000
--- a/src/render_program/exa_wm_yuv_rgb.g5a
+++ /dev/null
@@ -1 +0,0 @@
-exa_wm_yuv_rgb.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g6a b/src/render_program/exa_wm_yuv_rgb.g6a
deleted file mode 120000
index d34d246d..00000000
--- a/src/render_program/exa_wm_yuv_rgb.g6a
+++ /dev/null
@@ -1 +0,0 @@
-exa_wm_yuv_rgb.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g7a b/src/render_program/exa_wm_yuv_rgb.g7a
deleted file mode 120000
index d34d246d..00000000
--- a/src/render_program/exa_wm_yuv_rgb.g7a
+++ /dev/null
@@ -1 +0,0 @@
-exa_wm_yuv_rgb.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g4a b/src/render_program/exa_wm_yuv_rgb_bt601.g4a
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g4a
rename to src/render_program/exa_wm_yuv_rgb_bt601.g4a
diff --git a/src/render_program/exa_wm_yuv_rgb.g4b b/src/render_program/exa_wm_yuv_rgb_bt601.g4b
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g4b
rename to src/render_program/exa_wm_yuv_rgb_bt601.g4b
diff --git a/src/render_program/exa_wm_yuv_rgb.g4b.gen5 b/src/render_program/exa_wm_yuv_rgb_bt601.g4b.gen5
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g4b.gen5
rename to src/render_program/exa_wm_yuv_rgb_bt601.g4b.gen5
diff --git a/src/render_program/exa_wm_yuv_rgb_bt601.g5a b/src/render_program/exa_wm_yuv_rgb_bt601.g5a
new file mode 120000
index 00000000..8c98e82d
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt601.g5a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt601.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g5b b/src/render_program/exa_wm_yuv_rgb_bt601.g5b
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g5b
rename to src/render_program/exa_wm_yuv_rgb_bt601.g5b
diff --git a/src/render_program/exa_wm_yuv_rgb_bt601.g6a b/src/render_program/exa_wm_yuv_rgb_bt601.g6a
new file mode 120000
index 00000000..8c98e82d
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt601.g6a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt601.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g6b b/src/render_program/exa_wm_yuv_rgb_bt601.g6b
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g6b
rename to src/render_program/exa_wm_yuv_rgb_bt601.g6b
diff --git a/src/render_program/exa_wm_yuv_rgb_bt601.g7a b/src/render_program/exa_wm_yuv_rgb_bt601.g7a
new file mode 120000
index 00000000..8c98e82d
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb_bt601.g7a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb_bt601.g4a
\ No newline at end of file
diff --git a/src/render_program/exa_wm_yuv_rgb.g7b b/src/render_program/exa_wm_yuv_rgb_bt601.g7b
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g7b
rename to src/render_program/exa_wm_yuv_rgb_bt601.g7b
diff --git a/src/render_program/exa_wm_yuv_rgb.g8a b/src/render_program/exa_wm_yuv_rgb_bt601.g8a
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g8a
rename to src/render_program/exa_wm_yuv_rgb_bt601.g8a
diff --git a/src/render_program/exa_wm_yuv_rgb.g8b b/src/render_program/exa_wm_yuv_rgb_bt601.g8b
similarity index 100%
rename from src/render_program/exa_wm_yuv_rgb.g8b
rename to src/render_program/exa_wm_yuv_rgb_bt601.g8b
diff --git a/src/sna/brw/brw_test_gen4.c b/src/sna/brw/brw_test_gen4.c
index c0a185f3..78ff7465 100644
--- a/src/sna/brw/brw_test_gen4.c
+++ b/src/sna/brw/brw_test_gen4.c
@@ -115,7 +115,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_argb.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
@@ -123,7 +123,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_planar.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
diff --git a/src/sna/brw/brw_test_gen5.c b/src/sna/brw/brw_test_gen5.c
index 5f909fe5..e821ce8b 100644
--- a/src/sna/brw/brw_test_gen5.c
+++ b/src/sna/brw/brw_test_gen5.c
@@ -115,7 +115,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_argb.g5b"
-#include "exa_wm_yuv_rgb.g5b"
+#include "exa_wm_yuv_rgb_bt601.g5b"
 #include "exa_wm_write.g5b"
 };
 
@@ -123,7 +123,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_planar.g5b"
-#include "exa_wm_yuv_rgb.g5b"
+#include "exa_wm_yuv_rgb_bt601.g5b"
 #include "exa_wm_write.g5b"
 };
 
diff --git a/src/sna/brw/brw_test_gen6.c b/src/sna/brw/brw_test_gen6.c
index 813ea8ac..9603b9d9 100644
--- a/src/sna/brw/brw_test_gen6.c
+++ b/src/sna/brw/brw_test_gen6.c
@@ -98,14 +98,14 @@ static const uint32_t ps_kernel_masknoca_projective[][4] = {
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_argb.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_planar.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
diff --git a/src/sna/brw/brw_test_gen7.c b/src/sna/brw/brw_test_gen7.c
index 297ae470..658b6699 100644
--- a/src/sna/brw/brw_test_gen7.c
+++ b/src/sna/brw/brw_test_gen7.c
@@ -98,14 +98,14 @@ static const uint32_t ps_kernel_masknoca_projective[][4] = {
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_argb.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_planar.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index f74b76f0..01f8040f 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -103,7 +103,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_argb.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
@@ -111,7 +111,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_planar.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
@@ -119,7 +119,7 @@ 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_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 46535f7b..bed4a3ed 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -93,7 +93,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_argb.g5b"
-#include "exa_wm_yuv_rgb.g5b"
+#include "exa_wm_yuv_rgb_bt601.g5b"
 #include "exa_wm_write.g5b"
 };
 
@@ -101,7 +101,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_xy.g5b"
 #include "exa_wm_src_affine.g5b"
 #include "exa_wm_src_sample_planar.g5b"
-#include "exa_wm_yuv_rgb.g5b"
+#include "exa_wm_yuv_rgb_bt601.g5b"
 #include "exa_wm_write.g5b"
 };
 
@@ -109,7 +109,7 @@ 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_yuv_rgb_bt601.g5b"
 #include "exa_wm_write.g5b"
 };
 
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index e847062f..39ea5b6f 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -104,21 +104,21 @@ static const struct gt_info gt2_info = {
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_argb.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_planar.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #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_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index c3f81c52..b1fdfb51 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -196,21 +196,21 @@ inline static bool is_hsw(struct sna *sna)
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_argb.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_planar.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #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_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 46369d6b..eadb09eb 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -96,21 +96,21 @@
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_argb.g8b"
-#include "exa_wm_yuv_rgb.g8b"
+#include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_planar.g8b"
-#include "exa_wm_yuv_rgb.g8b"
+#include "exa_wm_yuv_rgb_bt601.g8b"
 #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_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c
index dd25b7b1..721a186a 100644
--- a/src/sna/gen9_render.c
+++ b/src/sna/gen9_render.c
@@ -97,21 +97,21 @@
 static const uint32_t ps_kernel_packed[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_argb.g8b"
-#include "exa_wm_yuv_rgb.g8b"
+#include "exa_wm_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
 static const uint32_t ps_kernel_planar[][4] = {
 #include "exa_wm_src_affine.g8b"
 #include "exa_wm_src_sample_planar.g8b"
-#include "exa_wm_yuv_rgb.g8b"
+#include "exa_wm_yuv_rgb_bt601.g8b"
 #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_yuv_rgb_bt601.g8b"
 #include "exa_wm_write.g8b"
 };
 
diff --git a/src/uxa/i965_video.c b/src/uxa/i965_video.c
index 438ab909..9b9203b6 100644
--- a/src/uxa/i965_video.c
+++ b/src/uxa/i965_video.c
@@ -101,7 +101,7 @@ static const uint32_t ps_kernel_packed_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_argb.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
@@ -109,7 +109,7 @@ static const uint32_t ps_kernel_planar_static[][4] = {
 #include "exa_wm_xy.g4b"
 #include "exa_wm_src_affine.g4b"
 #include "exa_wm_src_sample_planar.g4b"
-#include "exa_wm_yuv_rgb.g4b"
+#include "exa_wm_yuv_rgb_bt601.g4b"
 #include "exa_wm_write.g4b"
 };
 
@@ -122,7 +122,7 @@ static const uint32_t ps_kernel_packed_static_gen5[][4] = {
 #include "exa_wm_xy.g4b.gen5"
 #include "exa_wm_src_affine.g4b.gen5"
 #include "exa_wm_src_sample_argb.g4b.gen5"
-#include "exa_wm_yuv_rgb.g4b.gen5"
+#include "exa_wm_yuv_rgb_bt601.g4b.gen5"
 #include "exa_wm_write.g4b.gen5"
 };
 
@@ -130,7 +130,7 @@ static const uint32_t ps_kernel_planar_static_gen5[][4] = {
 #include "exa_wm_xy.g4b.gen5"
 #include "exa_wm_src_affine.g4b.gen5"
 #include "exa_wm_src_sample_planar.g4b.gen5"
-#include "exa_wm_yuv_rgb.g4b.gen5"
+#include "exa_wm_yuv_rgb_bt601.g4b.gen5"
 #include "exa_wm_write.g4b.gen5"
 };
 
@@ -138,14 +138,14 @@ static const uint32_t ps_kernel_planar_static_gen5[][4] = {
 static const uint32_t ps_kernel_packed_static_gen6[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_argb.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
 static const uint32_t ps_kernel_planar_static_gen6[][4] = {
 #include "exa_wm_src_affine.g6b"
 #include "exa_wm_src_sample_planar.g6b"
-#include "exa_wm_yuv_rgb.g6b"
+#include "exa_wm_yuv_rgb_bt601.g6b"
 #include "exa_wm_write.g6b"
 };
 
@@ -153,14 +153,14 @@ static const uint32_t ps_kernel_planar_static_gen6[][4] = {
 static const uint32_t ps_kernel_packed_static_gen7[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_argb.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
 static const uint32_t ps_kernel_planar_static_gen7[][4] = {
 #include "exa_wm_src_affine.g7b"
 #include "exa_wm_src_sample_planar.g7b"
-#include "exa_wm_yuv_rgb.g7b"
+#include "exa_wm_yuv_rgb_bt601.g7b"
 #include "exa_wm_write.g7b"
 };
 
commit d3c93e66df0e9cb95c1b6003a19c1997dc2f1dc1
Author: Ville Syrjälä <ville.syrjala at linux.intel.com>
Date:   Tue May 29 21:33:08 2018 +0300

    Remove duplicate exa_wm_yuv_rgb.g5a shader source
    
    exa_wm_yuv_rgb.g5a is identical to exa_wm_yuv_rgb.g4a. Just use a
    symlink intead of duplicating the whole file.
    
    Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/render_program/exa_wm_yuv_rgb.g5a b/src/render_program/exa_wm_yuv_rgb.g5a
deleted file mode 100644
index 4fb2576a..00000000
--- a/src/render_program/exa_wm_yuv_rgb.g5a
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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:
- *    Keith Packard <keithp at keithp.com>
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-include(`exa_wm.g4i')
-
-define(`YCbCr_base',	`src_sample_base')
-
-define(`Cr',		`src_sample_r')
-define(`Cr_01',		`src_sample_r_01')
-define(`Cr_23',		`src_sample_r_23')
-
-define(`Y',		`src_sample_g')
-define(`Y_01',		`src_sample_g_01')
-define(`Y_23',		`src_sample_g_23')
-
-define(`Cb',		`src_sample_b')
-define(`Cb_01',		`src_sample_b_01')
-define(`Cb_23',		`src_sample_b_23')
-
-define(`Crn',		`mask_sample_r')
-define(`Crn_01',	`mask_sample_r_01')
-define(`Crn_23',	`mask_sample_r_23')
-
-define(`Yn',		`mask_sample_g')
-define(`Yn_01',		`mask_sample_g_01')
-define(`Yn_23',		`mask_sample_g_23')
-
-define(`Cbn',		`mask_sample_b')
-define(`Cbn_01',	`mask_sample_b_01')
-define(`Cbn_23',	`mask_sample_b_23')
-
-    /* color space conversion function:
-     * R = Clamp ( 1.164(Y-16/255) + 1.596(Cr-128/255), 0, 1)
-     * G = Clamp ( 1.164(Y-16/255) - 0.813(Cr-128/255) - 0.392(Cb-128/255), 0, 1)
-     * B = Clamp ( 1.164(Y-16/255) + 2.017(Cb-128/255), 0, 1)
-     */
-
-    /* Normalize Y, Cb and Cr:
-     *
-     * Yn = (Y - 16/255) * 1.164
-     * Crn = Cr - 128 / 255
-     * Cbn = Cb - 128 / 255
-     */
-add (16)    Yn<1>F		Y<8,8,1>F	-0.0627451F { compr align1 };
-mul (16)    Yn<1>F		Yn<8,8,1>F	1.164F	    { compr align1 };
-
-add (16)    Crn<1>F		Cr<8,8,1>F	-0.501961F  { compr align1 };
-
-add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
-
-    /* 
-     * R = Y + Cr * 1.596
-     */
-mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
-mac.sat(16) src_sample_r<1>F	Crn<8,8,1>F	1.596F	    { compr align1 };
-     
-    /*
-     * G = Crn * -0.813 + Cbn * -0.392 + Y
-     */
-mov (16)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
-mac (16)    acc0<1>F		Crn<8,8,1>F    	-0.813F	    { compr align1 };
-mac.sat(16) src_sample_g<1>F	Cbn<8,8,1>F    	-0.392F	    { compr align1 };
-
-    /*
-     * B = Cbn * 2.017 + Y
-     */
-mov (16)    acc0<1>F	        Yn<8,8,1>F		    { compr align1 };
-mac.sat(16) src_sample_b<1>F	Cbn<8,8,1>F     2.017F	    { compr align1 };
-
-    /*
-     * A = 1.0
-     */
-mov (16)    src_sample_a<1>F	1.0F			    { compr align1 };
diff --git a/src/render_program/exa_wm_yuv_rgb.g5a b/src/render_program/exa_wm_yuv_rgb.g5a
new file mode 120000
index 00000000..d34d246d
--- /dev/null
+++ b/src/render_program/exa_wm_yuv_rgb.g5a
@@ -0,0 +1 @@
+exa_wm_yuv_rgb.g4a
\ No newline at end of file


More information about the xorg-commit mailing list