diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 9f27b4373..5d4a056ce 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -193,6 +193,7 @@ struct wlr_scene_buffer { enum wl_output_transform transform; pixman_region32_t opaque_region; enum wlr_color_transfer_function transfer_function; + enum wlr_color_named_primaries primaries; struct { uint64_t active_outputs; @@ -545,6 +546,9 @@ void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_transfer_function(struct wlr_scene_buffer *scene_buffer, enum wlr_color_transfer_function transfer_function); +void wlr_scene_buffer_set_primaries(struct wlr_scene_buffer *scene_buffer, + enum wlr_color_named_primaries primaries); + /** * Calls the buffer's frame_done signal. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index baa36bf3a..144329491 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -14,6 +14,7 @@ #include #include #include +#include "render/color.h" #include "types/wlr_output.h" #include "types/wlr_scene.h" #include "util/array.h" @@ -1109,6 +1110,16 @@ void wlr_scene_buffer_set_transfer_function(struct wlr_scene_buffer *scene_buffe scene_node_update(&scene_buffer->node, NULL); } +void wlr_scene_buffer_set_primaries(struct wlr_scene_buffer *scene_buffer, + enum wlr_color_named_primaries primaries) { + if (scene_buffer->primaries == primaries) { + return; + } + + scene_buffer->primaries = primaries; + scene_node_update(&scene_buffer->node, NULL); +} + static struct wlr_texture *scene_buffer_get_texture( struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { if (scene_buffer->buffer == NULL || scene_buffer->texture != NULL) { @@ -1445,6 +1456,11 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren wlr_output_transform_invert(scene_buffer->transform); transform = wlr_output_transform_compose(transform, data->transform); + struct wlr_color_primaries primaries = {0}; + if (scene_buffer->primaries != 0) { + wlr_color_primaries_from_named(&primaries, scene_buffer->primaries); + } + wlr_render_pass_add_texture(data->render_pass, &(struct wlr_render_texture_options) { .texture = texture, .src_box = scene_buffer->src_box, @@ -1457,6 +1473,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren !pixman_region32_empty(&opaque) ? WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE, .transfer_function = scene_buffer->transfer_function, + .primaries = scene_buffer->primaries != 0 ? &primaries : NULL, .wait_timeline = scene_buffer->wait_timeline, .wait_point = scene_buffer->wait_point, }); @@ -1950,6 +1967,9 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout( if (buffer->transfer_function != 0 && buffer->transfer_function != WLR_COLOR_TRANSFER_FUNCTION_SRGB) { return false; } + if (buffer->primaries != 0 && buffer->primaries != WLR_COLOR_NAMED_PRIMARIES_SRGB) { + return false; + } // We want to ensure optimal buffer selection, but as direct-scanout can be enabled and disabled // on a frame-by-frame basis, we wait for a few frames to send the new format recommendations.