mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
scene: send color_management_v1 surface feedback
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3999
This commit is contained in:
parent
26c1476827
commit
7cb3393e75
3 changed files with 84 additions and 0 deletions
|
|
@ -43,6 +43,7 @@ struct wlr_scene_output_layout;
|
|||
struct wlr_presentation;
|
||||
struct wlr_linux_dmabuf_v1;
|
||||
struct wlr_gamma_control_manager_v1;
|
||||
struct wlr_color_manager_v1;
|
||||
struct wlr_output_state;
|
||||
|
||||
typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)(
|
||||
|
|
@ -102,11 +103,13 @@ struct wlr_scene {
|
|||
// May be NULL
|
||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1;
|
||||
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
||||
struct wlr_color_manager_v1 *color_manager_v1;
|
||||
|
||||
struct {
|
||||
struct wl_listener linux_dmabuf_v1_destroy;
|
||||
struct wl_listener gamma_control_manager_v1_destroy;
|
||||
struct wl_listener gamma_control_manager_v1_set_gamma;
|
||||
struct wl_listener color_manager_v1_destroy;
|
||||
|
||||
enum wlr_scene_debug_damage_option debug_damage_option;
|
||||
bool direct_scanout;
|
||||
|
|
@ -366,6 +369,13 @@ void wlr_scene_set_linux_dmabuf_v1(struct wlr_scene *scene,
|
|||
void wlr_scene_set_gamma_control_manager_v1(struct wlr_scene *scene,
|
||||
struct wlr_gamma_control_manager_v1 *gamma_control);
|
||||
|
||||
/**
|
||||
* Handles color_management_v1 feedback for all surfaces in the scene.
|
||||
*
|
||||
* Asserts that a struct wlr_color_manager_v1 hasn't already been set for the scene.
|
||||
*/
|
||||
void wlr_scene_set_color_manager_v1(struct wlr_scene *scene, struct wlr_color_manager_v1 *manager);
|
||||
|
||||
/**
|
||||
* Add a node displaying nothing but its children.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,16 +35,74 @@ static struct wlr_output *get_surface_frame_pacing_output(struct wlr_surface *su
|
|||
return frame_pacing_output;
|
||||
}
|
||||
|
||||
static bool get_tf_preference(enum wlr_color_transfer_function tf) {
|
||||
switch (tf) {
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
|
||||
return 0;
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ:
|
||||
return 1;
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR:
|
||||
return -1;
|
||||
}
|
||||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static bool get_primaries_preference(enum wlr_color_named_primaries primaries) {
|
||||
switch (primaries) {
|
||||
case WLR_COLOR_NAMED_PRIMARIES_SRGB:
|
||||
return 0;
|
||||
case WLR_COLOR_NAMED_PRIMARIES_BT2020:
|
||||
return 1;
|
||||
}
|
||||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static void get_surface_preferred_image_description(struct wlr_surface *surface,
|
||||
struct wlr_image_description_v1_data *out) {
|
||||
struct wlr_output_image_description preferred = {
|
||||
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_SRGB,
|
||||
.primaries = WLR_COLOR_NAMED_PRIMARIES_SRGB,
|
||||
};
|
||||
|
||||
struct wlr_surface_output *surface_output;
|
||||
wl_list_for_each(surface_output, &surface->current_outputs, link) {
|
||||
const struct wlr_output_image_description *img_desc =
|
||||
surface_output->output->image_description;
|
||||
if (img_desc == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (get_tf_preference(preferred.transfer_function) < get_tf_preference(img_desc->transfer_function)) {
|
||||
preferred.transfer_function = img_desc->transfer_function;
|
||||
}
|
||||
if (get_primaries_preference(preferred.primaries) < get_primaries_preference(img_desc->primaries)) {
|
||||
preferred.primaries = img_desc->primaries;
|
||||
}
|
||||
}
|
||||
|
||||
*out = (struct wlr_image_description_v1_data){
|
||||
.tf_named = wlr_color_manager_v1_transfer_function_from_wlr(preferred.transfer_function),
|
||||
.primaries_named = wlr_color_manager_v1_primaries_from_wlr(preferred.primaries),
|
||||
};
|
||||
}
|
||||
|
||||
static void handle_scene_buffer_outputs_update(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_surface *surface =
|
||||
wl_container_of(listener, surface, outputs_update);
|
||||
struct wlr_scene *scene = scene_node_get_root(&surface->buffer->node);
|
||||
|
||||
surface->frame_pacing_output = get_surface_frame_pacing_output(surface->surface);
|
||||
|
||||
double scale = get_surface_preferred_buffer_scale(surface->surface);
|
||||
wlr_fractional_scale_v1_notify_scale(surface->surface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(surface->surface, ceil(scale));
|
||||
|
||||
if (scene->color_manager_v1 != NULL) {
|
||||
struct wlr_image_description_v1_data img_desc = {0};
|
||||
get_surface_preferred_image_description(surface->surface, &img_desc);
|
||||
wlr_color_manager_v1_set_surface_preferred_image_description(scene->color_manager_v1,
|
||||
surface->surface, &img_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_scene_buffer_output_enter(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_color_management_v1.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_damage_ring.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
|
|
@ -1562,6 +1563,21 @@ void wlr_scene_set_gamma_control_manager_v1(struct wlr_scene *scene,
|
|||
wl_signal_add(&gamma_control->events.set_gamma, &scene->gamma_control_manager_v1_set_gamma);
|
||||
}
|
||||
|
||||
static void scene_handle_color_manager_v1_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene *scene = wl_container_of(listener, scene, color_manager_v1_destroy);
|
||||
wl_list_remove(&scene->color_manager_v1_destroy.link);
|
||||
wl_list_init(&scene->color_manager_v1_destroy.link);
|
||||
scene->color_manager_v1 = NULL;
|
||||
}
|
||||
|
||||
void wlr_scene_set_color_manager_v1(struct wlr_scene *scene, struct wlr_color_manager_v1 *manager) {
|
||||
assert(scene->color_manager_v1 == NULL);
|
||||
scene->color_manager_v1 = manager;
|
||||
|
||||
scene->color_manager_v1_destroy.notify = scene_handle_color_manager_v1_destroy;
|
||||
wl_signal_add(&manager->events.destroy, &scene->color_manager_v1_destroy);
|
||||
}
|
||||
|
||||
static void scene_output_handle_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_scene_output *scene_output =
|
||||
wl_container_of(addon, scene_output, addon);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue