From b7291cfe48bd9319c57e8b95eb1dfdc9b3a7b493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 9 Nov 2023 16:14:40 +0800 Subject: [PATCH] shaped-texture: Use color aware rendering This looks at the color state it got from the actor on construction, and the target color state from the paint context and generates (and caches) color aware pipelines used for painting. One of the purposes here is for mixing SDR and HDR content and painting to a HDR monitor. If HDR (or optical blending) isn't activated, the produced shaders will be equivalent to what we had before. Also add some names to the piplines, as this helps identifying what pipeline source is associated with what pipeline. Part-of: --- src/compositor/meta-shaped-texture-private.h | 5 +- src/compositor/meta-shaped-texture.c | 196 ++++++++++++++++--- src/compositor/meta-surface-actor.c | 4 +- src/wayland/meta-wayland-actor-surface.c | 5 + 4 files changed, 179 insertions(+), 31 deletions(-) diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index b6cf9d486..a47772729 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -27,9 +27,12 @@ #include "backends/meta-monitor-manager-private.h" #include "meta/meta-shaped-texture.h" -MetaShapedTexture * meta_shaped_texture_new (ClutterContext *clutter_context); +MetaShapedTexture * meta_shaped_texture_new (ClutterContext *clutter_context, + ClutterColorState *color_state); void meta_shaped_texture_set_texture (MetaShapedTexture *stex, MetaMultiTexture *multi_texture); +void meta_shaped_texture_set_color_state (MetaShapedTexture *stex, + ClutterColorState *color_state); void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, gboolean is_y_inverted); void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index f5d33af43..b10ab1fe1 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -56,6 +56,7 @@ enum PROP_0, PROP_CLUTTER_CONTEXT, + PROP_COLOR_STATE, N_PROPS }; @@ -76,6 +77,16 @@ static CoglPipelineKey opaque_overlay_pipeline_key = static CoglPipelineKey blended_overlay_pipeline_key = "meta-shaped-texture-blended-pipeline-key"; +typedef enum _PipelineCacheSlot +{ + PIPELINE_CACHE_SLOT_UNMASKED, + PIPELINE_CACHE_SLOT_UNMASKED_TOWER, + PIPELINE_CACHE_SLOT_MASKED, + PIPELINE_CACHE_SLOT_MASKED_TOWER, + PIPELINE_CACHE_SLOT_UNBLENDED, + PIPELINE_CACHE_SLOT_UNBLENDED_TOWER, +} PipelineCacheSlot; + struct _MetaShapedTexture { GObject parent; @@ -85,15 +96,10 @@ struct _MetaShapedTexture MetaMultiTexture *texture; CoglTexture *mask_texture; CoglSnippet *snippet; + ClutterColorState *color_state; CoglPipeline *base_pipeline; CoglPipeline *combined_pipeline; - CoglPipeline *unmasked_pipeline; - CoglPipeline *unmasked_tower_pipeline; - CoglPipeline *masked_pipeline; - CoglPipeline *masked_tower_pipeline; - CoglPipeline *unblended_pipeline; - CoglPipeline *unblended_tower_pipeline; MetaTextureMipmap *texture_mipmap; @@ -140,6 +146,9 @@ meta_shaped_texture_set_property (GObject *object, case PROP_CLUTTER_CONTEXT: stex->clutter_context = g_value_get_object (value); break; + case PROP_COLOR_STATE: + g_set_object (&stex->color_state, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -158,6 +167,9 @@ meta_shaped_texture_get_property (GObject *object, case PROP_CLUTTER_CONTEXT: g_value_set_object (value, stex->clutter_context); break; + case PROP_COLOR_STATE: + g_value_set_object (value, stex->clutter_context); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -185,6 +197,12 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_props[PROP_COLOR_STATE] = + g_param_spec_object ("color-state", NULL, NULL, + CLUTTER_TYPE_COLOR_STATE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, obj_props); } @@ -285,14 +303,13 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, static void meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) { + ClutterPipelineCache *pipeline_cache = + clutter_context_get_pipeline_cache (stex->clutter_context); + g_clear_object (&stex->base_pipeline); g_clear_object (&stex->combined_pipeline); - g_clear_object (&stex->unmasked_pipeline); - g_clear_object (&stex->unmasked_tower_pipeline); - g_clear_object (&stex->masked_pipeline); - g_clear_object (&stex->masked_tower_pipeline); - g_clear_object (&stex->unblended_pipeline); - g_clear_object (&stex->unblended_tower_pipeline); + + clutter_pipeline_cache_unset_all_pipelines (pipeline_cache, stex); } static void @@ -303,6 +320,7 @@ meta_shaped_texture_dispose (GObject *object) g_clear_pointer (&stex->texture_mipmap, meta_texture_mipmap_free); g_clear_object (&stex->texture); + g_clear_object (&stex->color_state); meta_shaped_texture_set_mask_texture (stex, NULL); meta_shaped_texture_reset_pipelines (stex); @@ -440,31 +458,84 @@ get_combined_pipeline (MetaShapedTexture *stex, return pipeline; } +static void +attach_and_save_color_snippet (MetaShapedTexture *stex, + ClutterColorState *color_state, + ClutterColorState *target_color_state, + CoglPipeline *pipeline, + PipelineCacheSlot cache_slot) +{ + ClutterPipelineCache *pipeline_cache = + clutter_context_get_pipeline_cache (stex->clutter_context); + g_autoptr (CoglSnippet) color_snippet = NULL; + + color_snippet = + clutter_color_state_get_transform_snippet (color_state, target_color_state); + if (color_snippet) + cogl_pipeline_add_snippet (pipeline, color_snippet); + + clutter_pipeline_cache_set_pipeline (pipeline_cache, + stex, + cache_slot, + color_state, + target_color_state, + pipeline); +} + static CoglPipeline * get_unmasked_pipeline (MetaShapedTexture *stex, ClutterPaintContext *paint_context, MetaMultiTexture *tex) { + ClutterPipelineCache *pipeline_cache = + clutter_context_get_pipeline_cache (stex->clutter_context); + ClutterColorState *color_state; + ClutterColorState *target_color_state; + + color_state = stex->color_state; + target_color_state = + clutter_paint_context_get_target_color_state (paint_context); + if (stex->texture == tex) { CoglPipeline *pipeline; - if (stex->unmasked_pipeline) - return stex->unmasked_pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_UNMASKED, + color_state, + target_color_state); + if (pipeline) + return pipeline; pipeline = cogl_pipeline_copy (get_combined_pipeline (stex, paint_context)); if (stex->snippet) cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); - stex->unmasked_pipeline = pipeline; + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_UNMASKED); return pipeline; } else { CoglPipeline *pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_UNMASKED_TOWER, + color_state, + target_color_state); + if (pipeline) + return pipeline; + pipeline = cogl_pipeline_copy (get_base_pipeline (stex, paint_context)); - stex->unmasked_tower_pipeline = pipeline; + + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_UNMASKED_TOWER); return pipeline; } } @@ -474,14 +545,29 @@ get_masked_pipeline (MetaShapedTexture *stex, ClutterPaintContext *paint_context, MetaMultiTexture *tex) { + ClutterPipelineCache *pipeline_cache = + clutter_context_get_pipeline_cache (stex->clutter_context); + ClutterColorState *color_state; + ClutterColorState *target_color_state; + + color_state = stex->color_state; + target_color_state = + clutter_paint_context_get_target_color_state (paint_context); + g_assert (meta_multi_texture_get_n_planes (stex->texture) == 1); if (stex->texture == tex) { CoglPipeline *pipeline; - if (stex->masked_pipeline) - return stex->masked_pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_MASKED, + color_state, + target_color_state); + if (pipeline) + return pipeline; pipeline = cogl_pipeline_copy (get_base_pipeline (stex, paint_context)); cogl_pipeline_set_layer_combine (pipeline, 1, @@ -490,22 +576,32 @@ get_masked_pipeline (MetaShapedTexture *stex, if (stex->snippet) cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); - stex->masked_pipeline = pipeline; + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_MASKED); return pipeline; } else { CoglPipeline *pipeline; - if (stex->masked_tower_pipeline) - return stex->masked_tower_pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_MASKED_TOWER, + color_state, + target_color_state); + if (pipeline) + return pipeline; pipeline = cogl_pipeline_copy (get_base_pipeline (stex, paint_context)); cogl_pipeline_set_layer_combine (pipeline, 1, "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", NULL); - stex->masked_tower_pipeline = pipeline; + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_MASKED_TOWER); return pipeline; } } @@ -515,12 +611,27 @@ get_unblended_pipeline (MetaShapedTexture *stex, ClutterPaintContext *paint_context, MetaMultiTexture *tex) { + ClutterPipelineCache *pipeline_cache = + clutter_context_get_pipeline_cache (stex->clutter_context); + ClutterColorState *color_state; + ClutterColorState *target_color_state; + + color_state = stex->color_state; + target_color_state = + clutter_paint_context_get_target_color_state (paint_context); + if (stex->texture == tex) { CoglPipeline *pipeline; - if (stex->unblended_pipeline) - return stex->unblended_pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_UNBLENDED, + color_state, + target_color_state); + if (pipeline) + return pipeline; pipeline = cogl_pipeline_copy (get_combined_pipeline (stex, paint_context)); cogl_pipeline_set_layer_combine (pipeline, 0, @@ -529,22 +640,32 @@ get_unblended_pipeline (MetaShapedTexture *stex, if (stex->snippet) cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); - stex->unblended_pipeline = pipeline; + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_UNBLENDED); return pipeline; } else { CoglPipeline *pipeline; - if (stex->unblended_tower_pipeline) - return stex->unblended_tower_pipeline; + pipeline = + clutter_pipeline_cache_get_pipeline (pipeline_cache, + stex, + PIPELINE_CACHE_SLOT_UNBLENDED_TOWER, + color_state, + target_color_state); + if (pipeline) + return pipeline; pipeline = cogl_pipeline_copy (get_base_pipeline (stex, paint_context)); cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA = REPLACE (TEXTURE)", NULL); - stex->unblended_tower_pipeline = pipeline; + attach_and_save_color_snippet (stex, + color_state, target_color_state, + pipeline, PIPELINE_CACHE_SLOT_UNBLENDED_TOWER); return pipeline; } } @@ -1211,6 +1332,21 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex, set_multi_texture (stex, texture); } +/** + * meta_shaped_texture_set_color_state: + * @stex: The #MetaShapedTexture + * @color_state: A #ClutterColorState + */ +void +meta_shaped_texture_set_color_state (MetaShapedTexture *stex, + ClutterColorState *color_state) +{ + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + if (g_set_object (&stex->color_state, color_state)) + meta_shaped_texture_reset_pipelines (stex); +} + /** * meta_shaped_texture_set_is_y_inverted: (skip) */ @@ -1576,10 +1712,12 @@ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, } MetaShapedTexture * -meta_shaped_texture_new (ClutterContext *clutter_context) +meta_shaped_texture_new (ClutterContext *clutter_context, + ClutterColorState *color_state) { return g_object_new (META_TYPE_SHAPED_TEXTURE, "clutter-context", clutter_context, + "color-state", color_state, NULL); } diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 7b08640be..1034d1ff4 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -265,9 +265,11 @@ meta_surface_actor_constructed (GObject *object) meta_surface_actor_get_instance_private (surface_actor); ClutterContext *clutter_context = clutter_actor_get_context (CLUTTER_ACTOR (surface_actor)); + ClutterColorState *color_state = + clutter_actor_get_color_state (CLUTTER_ACTOR (surface_actor)); priv->is_obscured = TRUE; - priv->texture = meta_shaped_texture_new (clutter_context); + priv->texture = meta_shaped_texture_new (clutter_context, color_state); g_signal_connect_object (priv->texture, "size-changed", G_CALLBACK (texture_size_changed), surface_actor, G_CONNECT_DEFAULT); diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index 9f1e5d4ef..6c83fdce8 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -183,13 +183,18 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor { CoglSnippet *snippet; gboolean is_y_inverted; + ClutterColorState *color_state; MetaMultiTexture *texture; snippet = meta_wayland_buffer_create_snippet (buffer); is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer); + color_state = + clutter_actor_get_color_state (CLUTTER_ACTOR (surface_actor)); + texture = meta_wayland_surface_get_texture (surface); meta_shaped_texture_set_texture (stex, texture); + meta_shaped_texture_set_color_state (stex, color_state); meta_shaped_texture_set_snippet (stex, snippet); meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); meta_shaped_texture_set_buffer_scale (stex, surface->applied_state.scale);