diff --git a/include/render/egl.h b/include/render/egl.h index 103ab57df..2711c8f16 100644 --- a/include/render/egl.h +++ b/include/render/egl.h @@ -3,6 +3,8 @@ #include +struct wlr_color_representation_v1_state; + struct wlr_egl { EGLDisplay display; EGLContext context; @@ -74,7 +76,8 @@ void wlr_egl_destroy(struct wlr_egl *egl); * of the dmabuf with wlr_egl_check_import_dmabuf once first. */ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, - struct wlr_dmabuf_attributes *attributes, bool *external_only); + struct wlr_dmabuf_attributes *attributes, bool *external_only, + const struct wlr_color_representation_v1_state *color_repr); /** * Get DMA-BUF formats suitable for sampling usage. diff --git a/include/wlr/types/wlr_linux_dmabuf_v1.h b/include/wlr/types/wlr_linux_dmabuf_v1.h index 33a5e7751..fe769700c 100644 --- a/include/wlr/types/wlr_linux_dmabuf_v1.h +++ b/include/wlr/types/wlr_linux_dmabuf_v1.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ struct wlr_dmabuf_v1_buffer { struct wl_resource *resource; // can be NULL if the client destroyed it struct wlr_dmabuf_attributes attributes; + struct wlr_color_representation_v1_state color_repr; struct { struct wl_listener release; diff --git a/render/egl.c b/render/egl.c index 6f3e9c8ca..42b48234c 100644 --- a/render/egl.c +++ b/render/egl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -733,7 +734,8 @@ bool wlr_egl_restore_context(struct wlr_egl_context *context) { } EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, - struct wlr_dmabuf_attributes *attributes, bool *external_only) { + struct wlr_dmabuf_attributes *attributes, bool *external_only, + const struct wlr_color_representation_v1_state *color_repr) { if (!egl->exts.KHR_image_base || !egl->exts.EXT_image_dma_buf_import) { wlr_log(WLR_ERROR, "dmabuf import extension not present"); return NULL; @@ -747,7 +749,7 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, } unsigned int atti = 0; - EGLint attribs[50]; + EGLint attribs[54]; attribs[atti++] = EGL_WIDTH; attribs[atti++] = attributes->width; attribs[atti++] = EGL_HEIGHT; @@ -805,6 +807,39 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, } } + // Add color representation metadata, if provided + if (color_repr != NULL) { + switch (color_repr->coefficients) { + case WLR_COLOR_ENCODING_BT601: + attribs[atti++] = EGL_YUV_COLOR_SPACE_HINT_EXT; + attribs[atti++] = EGL_ITU_REC601_EXT; + break; + case WLR_COLOR_ENCODING_BT709: + attribs[atti++] = EGL_YUV_COLOR_SPACE_HINT_EXT; + attribs[atti++] = EGL_ITU_REC709_EXT; + break; + case WLR_COLOR_ENCODING_BT2020: + attribs[atti++] = EGL_YUV_COLOR_SPACE_HINT_EXT; + attribs[atti++] = EGL_ITU_REC2020_EXT; + break; + default: + break; + } + + switch (color_repr->range) { + case WLR_COLOR_RANGE_FULL: + attribs[atti++] = EGL_SAMPLE_RANGE_HINT_EXT; + attribs[atti++] = EGL_YUV_FULL_RANGE_EXT; + break; + case WLR_COLOR_RANGE_LIMITED: + attribs[atti++] = EGL_SAMPLE_RANGE_HINT_EXT; + attribs[atti++] = EGL_YUV_NARROW_RANGE_EXT; + break; + default: + break; + } + } + // Our clients don't expect our usage to trash the buffer contents attribs[atti++] = EGL_IMAGE_PRESERVED_KHR; attribs[atti++] = EGL_TRUE; diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index e362daee8..14a6b7d08 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -143,8 +145,16 @@ struct wlr_gles2_buffer *gles2_buffer_get_or_create(struct wlr_gles2_renderer *r goto error_buffer; } + // Try to fetch color representation if present + const struct wlr_color_representation_v1_state *color_repr = NULL; + struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer = + wlr_dmabuf_v1_buffer_try_from_buffer(wlr_buffer); + if (dmabuf_v1_buffer != NULL) { + color_repr = &dmabuf_v1_buffer->color_repr; + } + buffer->image = wlr_egl_create_image_from_dmabuf(renderer->egl, - &dmabuf, &buffer->external_only); + &dmabuf, &buffer->external_only, color_repr); if (buffer->image == EGL_NO_IMAGE_KHR) { goto error_buffer; } diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index d2c881e2a..0362520ac 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -199,6 +201,17 @@ static void surface_finalize_pending(struct wlr_surface *surface) { } if (pending->buffer != NULL) { + // If buffer is a dmabuf, copy color representation from surface + struct wlr_dmabuf_v1_buffer *dmabuf_buffer = + wlr_dmabuf_v1_buffer_try_from_buffer(pending->buffer); + if (dmabuf_buffer != NULL) { + const struct wlr_color_representation_v1_state *surface_color_repr = + wlr_color_representation_v1_get_surface_state(surface); + if (surface_color_repr != NULL) { + dmabuf_buffer->color_repr = *surface_color_repr; + } + } + pending->buffer_width = pending->buffer->width; pending->buffer_height = pending->buffer->height; } else {