color: add support to the color-management protocol

In this MR we add support to the majority of the interfaces from the
color-management protocol.

That means that we are able to advertise output's images descriptions to
clients, preferred surface images descriptions, and so on. We also
support clients that wants to create ICC-based images descriptions and
set such descriptions for surfaces.

We still don't support the interface to allow clients to create
image descriptions from parameters, but that should be addressed
in the near future.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
Leandro Ribeiro 2024-01-26 12:15:51 -03:00
parent c7d33edd01
commit 5706d7e5d2
12 changed files with 1558 additions and 23 deletions

View File

@ -410,6 +410,12 @@ struct weston_head {
/** Current content protection status */
enum weston_hdcp_protection current_protection;
/* xx_color_manager_v1.get_color_management_output
*
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_output_resource_list;
};
/** Output properties derived from its color characteristics and profile
@ -1804,6 +1810,11 @@ struct weston_surface_state {
/* weston_protected_surface.enforced/relaxed */
enum weston_surface_protection_mode protection_mode;
/* color_management_surface_v1_interface.set_image_description or
* color_management_surface_v1_interface.unset_image_description */
struct weston_color_profile *color_profile;
const struct weston_render_intent_info *render_intent;
};
struct weston_surface_activation_data {
@ -1949,6 +1960,16 @@ struct weston_surface {
enum weston_surface_protection_mode protection_mode;
struct weston_tearing_control *tear_control;
struct weston_color_profile *color_profile;
struct weston_color_profile *preferred_color_profile;
const struct weston_render_intent_info *render_intent;
/* xx_color_manager_v1.get_color_management_surface
*
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_surface_resource_list;
};
struct weston_subsurface {
@ -2190,6 +2211,11 @@ weston_compositor_set_default_pointer_grab(struct weston_compositor *compositor,
struct weston_surface *
weston_surface_create(struct weston_compositor *compositor);
void
weston_surface_set_color_profile(struct weston_surface *surface,
struct weston_color_profile *cprof,
const struct weston_render_intent_info *intent_info);
struct weston_view *
weston_view_create(struct weston_surface *surface);

View File

@ -35,6 +35,7 @@
#include "color-properties.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "shared/weston-assert.h"
const char *
cmlcms_category_name(enum cmlcms_category cat)
@ -56,17 +57,22 @@ cmlcms_get_render_intent(enum cmlcms_category cat,
struct weston_surface *surface,
struct weston_output *output)
{
const struct weston_render_intent_info *render_intent;
struct weston_color_manager *cm = output->compositor->color_manager;
/*
* TODO: Take into account client provided content profile,
* output profile, and the category of the wanted color
* transformation.
*/
render_intent =
weston_render_intent_info_from(output->compositor,
WESTON_RENDER_INTENT_RELATIVE);
return render_intent;
/* TODO: take into account the cmlcms_category. */
/* Use default render intent. TODO: default should be
* WESTON_RENDER_INTENT_PERCEPTUAL. That requires tweaking the tests. */
if (!surface || !surface->render_intent) {
weston_assert_true(output->compositor, (cm->supported_rendering_intents >>
WESTON_RENDER_INTENT_RELATIVE) & 1);
return weston_render_intent_info_from(output->compositor,
WESTON_RENDER_INTENT_RELATIVE);
}
weston_assert_ptr(surface->compositor, surface->color_profile);
return surface->render_intent;
}
static struct cmlcms_color_profile *
@ -100,7 +106,7 @@ cmlcms_get_surface_color_transform(struct weston_color_manager *cm_base,
struct cmlcms_color_transform_search_param param = {
.category = CMLCMS_CATEGORY_INPUT_TO_BLEND,
.input_profile = get_cprof_or_stock_sRGB(cm, NULL /* TODO: surface->color_profile */),
.input_profile = get_cprof_or_stock_sRGB(cm, surface->color_profile),
.output_profile = get_cprof_or_stock_sRGB(cm, output->color_profile),
};
param.render_intent = cmlcms_get_render_intent(param.category,
@ -373,10 +379,30 @@ cmlcms_destroy(struct weston_color_manager *cm_base)
struct weston_color_manager_lcms *cm = get_cmlcms(cm_base);
if (cm->sRGB_profile) {
assert(cm->sRGB_profile->base.ref_count == 1);
/* TODO: when we fix the ugly bug described below, we should
* change this assert to == 1. */
weston_assert_true(cm->base.compositor,
cm->sRGB_profile->base.ref_count >= 1);
unref_cprof(cm->sRGB_profile);
}
/* TODO: this is an ugly hack. Remove it when we stop leaking surfaces
* when shutting down Weston with client surfaces alive. */
if (!wl_list_empty(&cm->color_profile_list)) {
struct cmlcms_color_profile *cprof, *tmp;
weston_log("BUG: When Weston is shutting down with client surfaces alive, it may\n" \
"leak them. This is a bug that needs to be fixed. At this point (in which\n" \
"we are destroying the color manager), we expect all the objects referencing\n" \
"color profiles to be already gone and, consequently, the color profiles\n" \
"themselves should have been already destroyed. But because of this other\n" \
"bug, this didn't happen, and now we destroy the color profiles and leave\n" \
"dangling pointers around.");
wl_list_for_each_safe(cprof, tmp, &cm->color_profile_list, link)
cmlcms_color_profile_destroy(cprof);
}
assert(wl_list_empty(&cm->color_transform_list));
assert(wl_list_empty(&cm->color_profile_list));
@ -450,10 +476,21 @@ weston_color_manager_create(struct weston_compositor *compositor)
cm->base.destroy_color_profile = cmlcms_destroy_color_profile;
cm->base.get_stock_sRGB_color_profile = cmlcms_get_stock_sRGB_color_profile;
cm->base.get_color_profile_from_icc = cmlcms_get_color_profile_from_icc;
cm->base.send_image_desc_info = cmlcms_send_image_desc_info;
cm->base.destroy_color_transform = cmlcms_destroy_color_transform;
cm->base.get_surface_color_transform = cmlcms_get_surface_color_transform;
cm->base.create_output_color_outcome = cmlcms_create_output_color_outcome;
/* We still do not support creating parametric color profiles. */
cm->base.supported_color_features = (1 << WESTON_COLOR_FEATURE_ICC);
/* We support all rendering intents. */
cm->base.supported_rendering_intents = (1 << WESTON_RENDER_INTENT_PERCEPTUAL) |
(1 << WESTON_RENDER_INTENT_SATURATION) |
(1 << WESTON_RENDER_INTENT_ABSOLUTE) |
(1 << WESTON_RENDER_INTENT_RELATIVE) |
(1 << WESTON_RENDER_INTENT_RELATIVE_BPC);
wl_list_init(&cm->color_transform_list);
wl_list_init(&cm->color_profile_list);

View File

@ -33,6 +33,7 @@
#include "color.h"
#include "shared/helpers.h"
#include "shared/os-compatibility.h"
struct weston_color_manager_lcms {
struct weston_color_manager base;
@ -65,6 +66,9 @@ struct cmlcms_color_profile {
cmsHPROFILE profile;
struct cmlcms_md5_sum md5sum;
/* Only for profiles created from an ICC file. */
struct ro_anonymous_file *prof_rofile;
/** The curves to decode an electrical signal
*
* For ICC profiles, if the profile type is matrix-shaper, then eotf
@ -138,6 +142,10 @@ cmlcms_get_color_profile_from_icc(struct weston_color_manager *cm,
struct weston_color_profile **cprof_out,
char **errmsg);
bool
cmlcms_send_image_desc_info(struct cm_image_desc_info *cm_image_desc_info,
struct weston_color_profile *cprof_base);
void
cmlcms_destroy_color_profile(struct weston_color_profile *cprof_base);

View File

@ -26,16 +26,17 @@
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <libweston/libweston.h>
#include "color.h"
#include "color-lcms.h"
#include "color-management.h"
#include "shared/helpers.h"
#include "shared/string-helpers.h"
#include "shared/xalloc.h"
#include "shared/weston-assert.h"
struct xyz_arr_flt {
float v[3];
@ -350,6 +351,10 @@ cmlcms_color_profile_destroy(struct cmlcms_color_profile *cprof)
cmsFreeToneCurveTriple(cprof->output_inv_eotf_vcgt);
cmsCloseProfile(cprof->profile);
/* Only profiles created from ICC files have these. */
if (cprof->prof_rofile)
os_ro_anonymous_file_destroy(cprof->prof_rofile);
weston_log_scope_printf(cm->profiles_scope, "Destroyed color profile %p. " \
"Description: %s\n", cprof, cprof->base.description);
@ -464,7 +469,7 @@ cmlcms_get_color_profile_from_icc(struct weston_color_manager *cm_base,
struct weston_color_manager_lcms *cm = get_cmlcms(cm_base);
cmsHPROFILE profile;
struct cmlcms_md5_sum md5sum;
struct cmlcms_color_profile *cprof;
struct cmlcms_color_profile *cprof = NULL;
char *desc = NULL;
if (!icc_data || icc_len < 1) {
@ -506,15 +511,85 @@ cmlcms_get_color_profile_from_icc(struct weston_color_manager *cm_base,
if (!cprof)
goto err_close;
cprof->prof_rofile = os_ro_anonymous_file_create(icc_len, icc_data);
if (!cprof->prof_rofile)
goto err_close;
*cprof_out = &cprof->base;
return true;
err_close:
if (cprof)
cmlcms_color_profile_destroy(cprof);
free(desc);
cmsCloseProfile(profile);
return false;
}
bool
cmlcms_send_image_desc_info(struct cm_image_desc_info *cm_image_desc_info,
struct weston_color_profile *cprof_base)
{
struct weston_color_manager_lcms *cm = get_cmlcms(cprof_base->cm);
struct weston_compositor *compositor = cm->base.compositor;
struct cmlcms_color_profile *cprof = get_cprof(cprof_base);
const struct weston_color_primaries_info *primaries_info;
const struct weston_color_tf_info *tf_info;
int32_t fd;
uint32_t len;
if (cprof->prof_rofile) {
/* ICC-based color profile, so just send the ICC file fd. If we
* get an error (negative fd), the helper will send the proper
* error to the client. */
fd = os_ro_anonymous_file_get_fd(cprof->prof_rofile,
RO_ANONYMOUS_FILE_MAPMODE_PRIVATE);
if (fd < 0) {
weston_cm_send_icc_file(cm_image_desc_info, -1, 0);
return false;
}
len = os_ro_anonymous_file_size(cprof->prof_rofile);
weston_assert_uint32_gt(compositor, len, 0);
weston_cm_send_icc_file(cm_image_desc_info, fd, len);
os_ro_anonymous_file_put_fd(fd);
} else {
/* TODO: we still don't support parametric color profiles that
* are not the stock one. This should change when we start
* advertising parametric image description support in our
* color-management protocol implementation. */
if (cprof != cm->sRGB_profile)
weston_assert_not_reached(compositor, "we don't support parametric " \
"cprof's that are not the stock sRGB one");
/* Stock sRGB color profile. TODO: when we add support for
* parametric color profiles, the stock sRGB will be crafted
* using parameters, instead of cmsCreate_sRGBProfileTHR()
* (which we currently use). So we'll get the parameters
* directly from it, instead of hardcoding as we are doing here.
* We don't get the parameters from the stock sRGB color profile
* because it is not trivial to retrieve that from LittleCMS. */
/* Send the H.273 ColourPrimaries code point that matches the
* Rec709 primaries and the D65 white point. */
primaries_info = weston_color_primaries_info_from(compositor,
WESTON_PRIMARIES_CICP_SRGB);
weston_cm_send_primaries_named(cm_image_desc_info, primaries_info);
/* These are the Rec709 primaries and D65 white point. */
weston_cm_send_primaries(cm_image_desc_info,
&primaries_info->color_gamut);
/* sRGB transfer function. */
tf_info = weston_color_tf_info_from(compositor, WESTON_TF_GAMMA22);
weston_cm_send_tf_named(cm_image_desc_info, tf_info);
}
return true;
}
void
cmlcms_destroy_color_profile(struct weston_color_profile *cprof_base)
{

View File

@ -16,6 +16,7 @@ config_h.set10('HAVE_CMS_GET_TONE_CURVE_SEGMENT',
has_function_cmsGetToneCurveSegment)
srcs_color_lcms = [
color_management_v1_server_protocol_h,
'color-lcms.c',
'color-profile.c',
'color-transform.c',
@ -28,6 +29,7 @@ deps_color_lcms = [
dep_libm,
dep_libweston_private,
dep_lcms2,
dep_libshared,
]
plugin_color_lcms = shared_library(

1119
libweston/color-management.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
/*
* Copyright 2023 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef WESTON_COLOR_MANAGEMENT_H
#define WESTON_COLOR_MANAGEMENT_H
#include "color-properties.h"
int
weston_compositor_enable_color_management_protocol(struct weston_compositor *compositor);
void
weston_output_send_image_description_changed(struct weston_output *output);
void
weston_surface_send_preferred_image_description_changed(struct weston_surface *surface);
void
weston_cm_send_icc_file(struct cm_image_desc_info *cm_image_desc_info,
int32_t fd, uint32_t len);
void
weston_cm_send_primaries_named(struct cm_image_desc_info *cm_image_desc_info,
const struct weston_color_primaries_info *primaries_info);
void
weston_cm_send_primaries(struct cm_image_desc_info *cm_image_desc_info,
const struct weston_color_gamut *color_gamut);
void
weston_cm_send_tf_named(struct cm_image_desc_info *cm_image_desc_info,
const struct weston_color_tf_info *tf_info);
#endif /* WESTON_COLOR_MANAGEMENT_H */

View File

@ -30,6 +30,7 @@
#include "color.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "shared/weston-assert.h"
struct cmnoop_color_profile {
struct weston_color_profile base;
@ -146,12 +147,18 @@ cmnoop_get_surface_color_transform(struct weston_color_manager *cm_base,
struct weston_output *output,
struct weston_surface_color_transform *surf_xform)
{
struct weston_compositor *compositor = output->compositor;
struct weston_color_manager_noop *cmnoop = get_cmnoop(cm_base);
/* TODO: Assert that, if the surface has a cprof, it is the stock one */
/* If surface has a cprof, it has to be the stock one. */
if (surface->color_profile)
weston_assert_ptr_eq(compositor, get_cprof(surface->color_profile),
cmnoop->stock_cprof);
assert(output->color_profile &&
get_cprof(output->color_profile) == cmnoop->stock_cprof);
/* The output must have a cprof, and it has to be the stock one. */
weston_assert_ptr(compositor, output->color_profile);
weston_assert_ptr_eq(compositor, get_cprof(output->color_profile),
cmnoop->stock_cprof);
if (!check_output_eotf_mode(output))
return false;
@ -242,9 +249,14 @@ weston_color_manager_noop_create(struct weston_compositor *compositor)
cm->base.destroy_color_profile = cmnoop_destroy_color_profile;
cm->base.get_stock_sRGB_color_profile = cmnoop_get_stock_sRGB_color_profile;
cm->base.get_color_profile_from_icc = cmnoop_get_color_profile_from_icc;
cm->base.send_image_desc_info = NULL;
cm->base.destroy_color_transform = cmnoop_destroy_color_transform;
cm->base.get_surface_color_transform = cmnoop_get_surface_color_transform;
cm->base.create_output_color_outcome = cmnoop_create_output_color_outcome;
/* We don't support anything related to the CM&HDR protocol extension */
cm->base.supported_color_features = 0;
cm->base.supported_rendering_intents = 0;
return &cm->base;
}

View File

@ -243,6 +243,8 @@ struct weston_surface_color_transform {
bool identity_pipeline;
};
struct cm_image_desc_info;
struct weston_color_manager {
/** Identifies this CMS component */
const char *name;
@ -253,6 +255,22 @@ struct weston_color_manager {
/** Supports the Wayland CM&HDR protocol extension? */
bool supports_client_protocol;
/**
* Supported color features from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_color_feature v) is a supported color
* feature, the bit v of this will be set to 1.
*/
uint32_t supported_color_features;
/**
* Supported rendering intents from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_render_intent v) is a supported rendering
* intent, the bit v of this will be set to 1.
*/
uint32_t supported_rendering_intents;
/** Initialize color manager */
bool
(*init)(struct weston_color_manager *cm);
@ -298,6 +316,23 @@ struct weston_color_manager {
struct weston_color_profile **cprof_out,
char **errmsg);
/** Send image description to clients.
*
* \param cm_image_desc_info The image description info object
* \param cprof_base The color profile that backs the image description
* \return True on success, false on failure
*
* This should be used only by the CM&HDR protocol extension
* implementation.
*
* The color manager implementing this function should use the helpers
* from color-management.c (weston_cm_send_primaries(), etc) to send the
* information to clients.
*/
bool
(*send_image_desc_info)(struct cm_image_desc_info *cm_image_desc_info,
struct weston_color_profile *cprof_base);
/** Destroy a color transform after refcount fell to zero */
void
(*destroy_color_transform)(struct weston_color_transform *xform);

View File

@ -72,6 +72,7 @@
#include "shared/string-helpers.h"
#include "shared/timespec-util.h"
#include "shared/xalloc.h"
#include "shared/weston-assert.h"
#include "tearing-control-v1-server-protocol.h"
#include "git-version.h"
#include <libweston/version.h>
@ -80,6 +81,7 @@
#include "backend.h"
#include "libweston-internal.h"
#include "color.h"
#include "color-management.h"
#include "id-number-allocator.h"
#include "output-capture.h"
#include "pixman-renderer.h"
@ -779,6 +781,9 @@ weston_surface_state_init(struct weston_surface *surface,
state->desired_protection = WESTON_HDCP_DISABLE;
state->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
state->color_profile = NULL;
state->render_intent = NULL;
}
static void
@ -802,6 +807,10 @@ weston_surface_state_fini(struct weston_surface_state *state)
fd_clear(&state->acquire_fence_fd);
weston_buffer_release_reference(&state->buffer_release_ref, NULL);
weston_color_profile_unref(state->color_profile);
state->color_profile = NULL;
state->render_intent = NULL;
}
static void
@ -819,6 +828,55 @@ weston_surface_state_set_buffer(struct weston_surface_state *state,
&state->buffer_destroy_listener);
}
static void
weston_surface_update_preferred_color_profile(struct weston_surface *surface)
{
struct weston_compositor *compositor = surface->compositor;
struct weston_color_manager *cm = compositor->color_manager;
struct weston_color_profile *old, *new;
old = surface->preferred_color_profile;
if (surface->output) {
/* The surface preferred color profile is the same color profile
* of its primary output. */
new = weston_color_profile_ref(surface->output->color_profile);
} else if (!wl_list_empty(&compositor->output_list)) {
/* Surface is still unmapped, with no primary output. To map the
* surface, clients need to draw, and in order to do that they
* should ask the preferred color profile for the surface (at
* least for color-aware clients). So in order to maximize the
* changes of the first frame being correct, we arbitrarily pick
* an output and use its color profile as the preferred. The
* most common scenario is a system with a single monitor (and
* output), so when the surface gets mapped this output will
* become the surface primary one, and the preferred color
* profile will stay the same. */
struct weston_output *output;
output = wl_container_of(surface->compositor->output_list.next,
output, link);
new = weston_color_profile_ref(output->color_profile);
} else {
/* Unmapped surface and no outputs available, so let's pick
* stock sRGB color profile. */
new = cm->get_stock_sRGB_color_profile(cm);
}
/* Nothing to do. */
if (new == old) {
weston_color_profile_unref(new);
return;
}
weston_color_profile_unref(old);
/* Update the preferred color profile and notify color-aware clients
* that the surface preferred image description changed. Part of the
* CM&HDR protocol extension implementation. */
surface->preferred_color_profile = new;
weston_surface_send_preferred_image_description_changed(surface);
}
WL_EXPORT struct weston_surface *
weston_surface_create(struct weston_compositor *compositor)
{
@ -867,6 +925,17 @@ weston_surface_create(struct weston_compositor *compositor)
surface->current_protection = WESTON_HDCP_DISABLE;
surface->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
wl_list_init(&surface->cm_surface_resource_list);
/* The surfaces start with no color profile and render intent. It's up
* to the color manager what to do with that. Later, clients are able to
* define these values using the CM&HDR protocol extension. */
surface->color_profile = NULL;
surface->render_intent = NULL;
/* Also part of the CM&HDR protocol extension implementation. */
weston_surface_update_preferred_color_profile(surface);
return surface;
}
@ -1129,6 +1198,46 @@ weston_surface_send_enter_leave(struct weston_surface *surface,
}
}
/** Set the color profile and render intent of a surface.
*
* \param surface The surface to update
* \param cprof The new color profile, or NULL
* \param render_intent The render intent info object, or NULL
*
* It is forbidden to pass a valid cprof and a NULL render intent, and
* vice-versa. But both NULL is valid.
*/
void
weston_surface_set_color_profile(struct weston_surface *surface,
struct weston_color_profile *cprof,
const struct weston_render_intent_info *render_intent)
{
struct weston_color_manager *cm = surface->compositor->color_manager;
struct weston_paint_node *pnode;
/* Nothing to do. */
if (surface->color_profile == cprof &&
surface->render_intent == render_intent)
return;
if (!!cprof ^ !!render_intent)
weston_assert_not_reached(cm->compositor,
"received valid cprof and NULL render intent, " \
"or vice versa; invalid for this function");
/* Remove outdated cached color transformations */
wl_list_for_each(pnode, &surface->paint_node_list, surface_link) {
weston_surface_color_transform_fini(&pnode->surf_xform);
pnode->surf_xform_valid = false;
}
/* Caller gave us a color profile and render intent (or NULL for both,
* which is also valid), so update the surface with them. */
weston_color_profile_unref(surface->color_profile);
surface->color_profile = weston_color_profile_ref(cprof);
surface->render_intent = render_intent;
}
static void
weston_surface_compute_protection(struct protected_surface *psurface)
{
@ -1378,6 +1487,11 @@ weston_surface_assign_output(struct weston_surface *es)
es->output = new_output;
weston_surface_update_output_mask(es, mask);
/* Surface primary output may have changed, and that may change the
* surface preferred color profile. Part of the CM&HDR protocol
* extension implementation. */
weston_surface_update_preferred_color_profile(es);
}
/** Recalculate which output(s) the view is displayed on
@ -2487,6 +2601,7 @@ weston_surface_unref(struct weston_surface *surface)
struct wl_resource *cb, *next;
struct weston_view *ev, *nv;
struct weston_pointer_constraint *constraint, *next_constraint;
struct wl_resource *cm_surface_res, *cm_surface_res_tmp;
struct weston_paint_node *pnode, *pntmp;
if (!surface)
@ -2539,6 +2654,16 @@ weston_surface_unref(struct weston_surface *surface)
if (surface->tear_control)
surface->tear_control->surface = NULL;
weston_color_profile_unref(surface->color_profile);
weston_color_profile_unref(surface->preferred_color_profile);
wl_resource_for_each_safe(cm_surface_res, cm_surface_res_tmp,
&surface->cm_surface_resource_list) {
wl_list_remove(wl_resource_get_link(cm_surface_res));
wl_list_init(wl_resource_get_link(cm_surface_res));
wl_resource_set_user_data(cm_surface_res, NULL);
}
free(surface);
}
@ -4549,6 +4674,11 @@ weston_surface_commit_state(struct weston_surface *surface,
/* weston_protected_surface.set_type */
weston_surface_set_desired_protection(surface, state->desired_protection);
/* color_management_surface_v1_interface.set_image_description or
* color_management_surface_v1_interface.unset_image_description */
weston_surface_set_color_profile(surface, state->color_profile,
state->render_intent);
wl_signal_emit(&surface->commit_signal, surface);
/* Surface is now quiescent */
@ -4878,6 +5008,10 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
&surface->pending.damage_buffer);
pixman_region32_clear(&surface->pending.damage_buffer);
sub->cached.render_intent = surface->pending.render_intent;
weston_color_profile_unref(sub->cached.color_profile);
sub->cached.color_profile =
weston_color_profile_ref(surface->pending.color_profile);
if (surface->pending.status & WESTON_SURFACE_DIRTY_BUFFER) {
weston_surface_state_set_buffer(&sub->cached,
@ -6014,6 +6148,12 @@ weston_head_remove_global(struct weston_head *head)
wl_resource_set_destructor(resource, NULL);
}
wl_list_init(&head->xdg_output_resource_list);
wl_resource_for_each_safe(resource, tmp, &head->cm_output_resource_list) {
wl_list_remove(wl_resource_get_link(resource));
wl_list_init(wl_resource_get_link(resource));
wl_resource_set_user_data(resource, NULL);
}
}
/** Get the backing object of wl_output
@ -6059,6 +6199,7 @@ weston_head_init(struct weston_head *head, const char *name)
wl_list_init(&head->output_link);
wl_list_init(&head->resource_list);
wl_list_init(&head->xdg_output_resource_list);
wl_list_init(&head->cm_output_resource_list);
head->name = xstrdup(name);
head->supported_eotf_mask = WESTON_EOTF_MODE_SDR;
head->current_protection = WESTON_HDCP_DISABLE;
@ -7430,18 +7571,24 @@ WL_EXPORT bool
weston_output_set_color_profile(struct weston_output *output,
struct weston_color_profile *cprof)
{
struct weston_color_manager *cm = output->compositor->color_manager;
struct weston_color_profile *old;
struct weston_compositor *compositor = output->compositor;
struct weston_color_manager *cm = compositor->color_manager;
struct weston_color_profile *old, *new;
struct weston_paint_node *pnode;
struct weston_view *view;
old = output->color_profile;
new = cprof ? weston_color_profile_ref(cprof) :
cm->get_stock_sRGB_color_profile(cm);
if (!cprof) {
output->color_profile = cm->get_stock_sRGB_color_profile(cm);
} else {
output->color_profile = weston_color_profile_ref(cprof);
/* Nothing to do. */
if (new == old) {
weston_color_profile_unref(new);
return true;
}
output->color_profile = new;
if (output->enabled) {
if (!weston_output_set_color_outcome(output)) {
/* Failed, roll back */
@ -7455,10 +7602,22 @@ weston_output_set_color_profile(struct weston_output *output,
weston_surface_color_transform_fini(&pnode->surf_xform);
pnode->surf_xform_valid = false;
}
/* The preferred color profile of a surface is its primary
* output color profile. For each surface that has this output
* as primary, we may need to update their preferred color
* profile. Part of the CM&HDR protocol extension
* implementation. */
wl_list_for_each(view, &compositor->view_list, link)
weston_surface_update_preferred_color_profile(view->surface);
}
weston_color_profile_unref(old);
/* Output color profile has changed, so we need to notify clients about
* that. Part of the CM&HDR protocol extension implementation. */
weston_output_send_image_description_changed(output);
return true;
}

View File

@ -15,6 +15,7 @@ srcs_libweston = [
'clipboard.c',
'color.c',
'color-properties.c',
'color-management.c',
'color-noop.c',
'compositor.c',
'content-protection.c',
@ -39,6 +40,8 @@ srcs_libweston = [
'weston-log-flight-rec.c',
'weston-log.c',
'weston-direct-display.c',
color_management_v1_protocol_c,
color_management_v1_server_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
linux_dmabuf_unstable_v1_server_protocol_h,
linux_explicit_synchronization_unstable_v1_protocol_c,

View File

@ -99,6 +99,9 @@ do { \
#define weston_assert_uint32_neq(compositor, a, b) \
weston_assert_(compositor, a, b, uint32_t, "%u", !=)
#define weston_assert_uint32_gt(compositor, a, b) \
weston_assert_(compositor, a, b, uint32_t, "%u", >)
#define weston_assert_uint32_lt(compositor, a, b) \
weston_assert_(compositor, a, b, uint32_t, "%u", <)