diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 037c3c23a..63589cfa2 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -378,6 +378,15 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm, atomic_add(atom, id, props->crtc_y, dst_box->y); atomic_add(atom, id, props->crtc_w, dst_box->width); atomic_add(atom, id, props->crtc_h, dst_box->height); + + // Always set the color encoding on every plane to BT.709. This only + // affects YUV planes (eg. scanout video). This won't be correct for + // all video but at least means we will be consistent and most + // importantly should match the GLES2 renderer, so avoids visible + // color-shifts when direct scanout is enabled/disabled. + if (props->color_encoding) { + atomic_add(atom, id, props->color_encoding, DRM_COLOR_YCBCR_BT709); + } } static bool supports_cursor_hotspots(const struct wlr_drm_plane *plane) { diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 0104304e5..91ce8c4dd 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -48,6 +48,7 @@ static const struct prop_info crtc_info[] = { static const struct prop_info plane_info[] = { #define INDEX(name) (offsetof(struct wlr_drm_plane_props, name) / sizeof(uint32_t)) + { "COLOR_ENCODING", INDEX(color_encoding) }, { "CRTC_H", INDEX(crtc_h) }, { "CRTC_ID", INDEX(crtc_id) }, { "CRTC_W", INDEX(crtc_w) }, diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index 421eb4275..1765a4951 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -63,6 +63,18 @@ struct wlr_drm_plane_props { uint32_t hotspot_x; uint32_t hotspot_y; uint32_t in_fence_fd; + + uint32_t color_encoding; // Not guaranteed to exist +}; + +/* + * The encoding and range enums are defined in the kernel but not + * exposed in public headers. + */ +enum drm_color_encoding { + DRM_COLOR_YCBCR_BT601, + DRM_COLOR_YCBCR_BT709, + DRM_COLOR_YCBCR_BT2020, }; bool get_drm_connector_props(int fd, uint32_t id,