@@ -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);
@@ -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]);
}
}
@@ -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");