[xf86-video-intel,6/6] sna/video/sprite: Add XV_COLOR_RANGE port attribute

Submitted by Ville Syrjälä on July 4, 2018, 6:59 p.m.

Details

Message ID 20180704185919.30946-6-ville.syrjala@linux.intel.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in X.org

Not browsing as part of any series.

Commit Message

Ville Syrjälä July 4, 2018, 6:59 p.m.
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a new Xv port attribute XV_COLOR_RANGE to select the incoming YUV
quantization range. 0 means limited range (Y: 16-235, Cb/Cr: 16-240),
1 means full range (0-255).

We'll forward the quantization range information to the kernel via
the COLOR_RANGE kms property.

Cc: xorg-devel@lists.x.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 src/sna/sna.h              |  3 +-
 src/sna/sna_display.c      | 72 ++++++++++++++++++++++++++++++++++++++++------
 src/sna/sna_video_sprite.c | 18 +++++++++---
 3 files changed, 80 insertions(+), 13 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 496460ca6a84..658093f3c04c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -633,7 +633,8 @@  static inline void sna_present_cancel_flip(struct sna *sna) { }
 
 extern unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc);
 extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_t rotation);
-extern void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc, unsigned idx, int colorspace);
+extern void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc, unsigned idx,
+					   int colorspace, int color_range);
 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);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 96e7b1bc50d3..9438408b937f 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -226,6 +226,10 @@  struct sna_crtc {
 			uint32_t prop;
 			uint64_t values[2];
 		} color_encoding;
+		struct {
+			uint32_t prop;
+			uint64_t values[2];
+		} color_range;
 		struct list link;
 	} primary;
 	struct list sprites;
@@ -3374,8 +3378,55 @@  static void parse_color_encoding_prop(struct sna *sna, struct plane *p,
 		p->color_encoding.prop = prop->prop_id;
 }
 
+inline static bool prop_is_color_range(const struct drm_mode_get_property *prop)
+{
+	return prop_has_type_and_name(prop, 3, "COLOR_RANGE");
+}
+
+static void parse_color_range_prop(struct sna *sna, struct plane *p,
+				   struct drm_mode_get_property *prop,
+				   uint64_t value)
+{
+	struct drm_mode_property_enum *enums;
+	unsigned int supported = 0;
+	int j;
+
+	DBG(("%s: found color range property .id=%d, value=%ld, num_enums=%d\n",
+	     __FUNCTION__, prop->prop_id, (long)value, prop->count_enum_blobs));
+
+	enums = malloc(prop->count_enum_blobs * sizeof(struct drm_mode_property_enum));
+	if (!enums)
+		return;
+
+	prop->count_values = 0;
+	prop->enum_blob_ptr = (uintptr_t)enums;
+
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, prop)) {
+		free(enums);
+		return;
+	}
+
+	VG(VALGRIND_MAKE_MEM_DEFINED(enums, sizeof(*enums)*prop->count_enum_blobs));
+	for (j = 0; j < prop->count_enum_blobs; j++) {
+		if (!strcmp(enums[j].name, "YCbCr limited range")) {
+			p->color_range.values[0] = enums[j].value;
+			supported |= 1 << 0;
+		} else if (!strcmp(enums[j].name, "YCbCr full range")) {
+			p->color_range.values[1] = enums[j].value;
+			supported |= 1 << 1;
+		}
+	}
+
+	free(enums);
+
+	if (supported == 3)
+		p->color_range.prop = prop->prop_id;
+}
+
 void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc,
-				    unsigned idx, int colorspace)
+				    unsigned idx,
+				    int colorspace,
+				    int color_range)
 {
 	struct plane *p;
 
@@ -3384,13 +3435,16 @@  void sna_crtc_set_sprite_colorspace(xf86CrtcPtr crtc,
 
 	p = lookup_sprite(to_sna_crtc(crtc), idx);
 
-	if (!p->color_encoding.prop)
-		return;
-
-	drmModeObjectSetProperty(to_sna(crtc->scrn)->kgem.fd,
-				 p->id, DRM_MODE_OBJECT_PLANE,
-				 p->color_encoding.prop,
-				 p->color_encoding.values[colorspace]);
+	if (p->color_encoding.prop)
+		drmModeObjectSetProperty(to_sna(crtc->scrn)->kgem.fd,
+					 p->id, DRM_MODE_OBJECT_PLANE,
+					 p->color_encoding.prop,
+					 p->color_encoding.values[colorspace]);
+	if (p->color_range.prop)
+		drmModeObjectSetProperty(to_sna(crtc->scrn)->kgem.fd,
+					 p->id, DRM_MODE_OBJECT_PLANE,
+					 p->color_range.prop,
+					 p->color_range.values[color_range]);
 }
 
 static int plane_details(struct sna *sna, struct plane *p)
@@ -3452,6 +3506,8 @@  static int plane_details(struct sna *sna, struct plane *p)
 			parse_rotation_prop(sna, p, &prop, values[i]);
 		} else if (prop_is_color_encoding(&prop)) {
 			parse_color_encoding_prop(sna, p, &prop, values[i]);
+		} else if (prop_is_color_range(&prop)) {
+			parse_color_range_prop(sna, p, &prop, values[i]);
 		}
 	}
 
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index 8b7ae8ae9e75..1f41e3f8528d 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -70,7 +70,7 @@  struct local_mode_set_plane {
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, true)
 
-static Atom xvColorKey, xvAlwaysOnTop, xvSyncToVblank, xvColorspace;
+static Atom xvColorKey, xvAlwaysOnTop, xvSyncToVblank, xvColorspace, xvColorRange;
 
 static XvFormatRec formats[] = { {15}, {16}, {24} };
 static const XvImageRec images[] = { XVIMAGE_YUY2, XVIMAGE_UYVY,
@@ -81,6 +81,7 @@  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, 1, (char *)"XV_COLOR_RANGE" }, /* limited, full */
 	{ XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_COLORKEY" },
 	{ XvSettable | XvGettable, 0, 1, (char *)"XV_ALWAYS_ON_TOP" },
 };
@@ -130,6 +131,10 @@  static int sna_video_sprite_set_attr(ddSetPortAttribute_ARGS)
 		video->colorspace_changed = ~0;
 		video->colorspace = value;
 		DBG(("COLORSPACE = %ld\n", (long)value));
+	} else if (attribute == xvColorRange) {
+		video->colorspace_changed = ~0;
+		video->color_range = value;
+		DBG(("COLOR_RANGE = %ld\n", (long)value));
 	} else if (attribute == xvSyncToVblank) {
 		DBG(("%s: SYNC_TO_VBLANK: %d -> %d\n", __FUNCTION__,
 		     video->SyncToVblank, !!value));
@@ -153,6 +158,8 @@  static int sna_video_sprite_get_attr(ddGetPortAttribute_ARGS)
 		*value = video->color_key;
 	else if (attribute == xvColorspace)
 		*value = video->colorspace;
+	else if (attribute == xvColorRange)
+		*value = video->color_range;
 	else if (attribute == xvAlwaysOnTop)
 		*value = video->AlwaysOnTop;
 	else if (attribute == xvSyncToVblank)
@@ -289,11 +296,12 @@  sna_video_sprite_show(struct sna *sna,
 	}
 
 	if (video->colorspace_changed & (1 << pipe)) {
-		DBG(("%s: updating colorspace: %x\n",
-		     __FUNCTION__, video->colorspace));
+		DBG(("%s: updating colorspace: %x / color_range: %x\n",
+		     __FUNCTION__, video->colorspace, video->color_range));
 
 		sna_crtc_set_sprite_colorspace(crtc, video->idx,
-					       video->colorspace);
+					       video->colorspace,
+					       video->color_range);
 
 		video->colorspace_changed &= ~(1 << pipe);
 	}
@@ -851,6 +859,7 @@  void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 		video->color_key = sna_video_sprite_color_key(sna);
 		video->color_key_changed = ~0;
 		video->colorspace = 1; /* BT.709 */
+		video->color_range = 0; /* limited */
 		video->colorspace_changed = ~0;
 		video->has_color_key = true;
 		video->brightness = -19;	/* (255/219) * -16 */
@@ -873,6 +882,7 @@  void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
 
 	xvColorKey = MAKE_ATOM("XV_COLORKEY");
 	xvColorspace = MAKE_ATOM("XV_COLORSPACE");
+	xvColorRange = MAKE_ATOM("XV_COLOR_RANGE");
 	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");
 	xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK");