1
0
Fork 0

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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3433>
This commit is contained in:
Jonas Ådahl 2023-11-09 16:14:40 +08:00 committed by Sebastian Wick
parent 6836a511db
commit b7291cfe48
4 changed files with 179 additions and 31 deletions

View file

@ -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,

View file

@ -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);
}

View file

@ -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);

View file

@ -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);