diff options
author | Daniel van Vugt <daniel.van.vugt@canonical.com> | 2021-07-16 18:34:11 +0800 |
---|---|---|
committer | Florian Müllner <fmuellner@gnome.org> | 2022-03-20 15:56:35 +0100 |
commit | 4270d9040197855df66290e3998cb9d4271151e8 (patch) | |
tree | 4c3a680bb29623584a83f04a6cf7b846ffcdafa6 | |
parent | e5315d2c31cd90aa76e8fa9ef87c3250c0d6302a (diff) | |
download | gnome-shell-4270d9040197855df66290e3998cb9d4271151e8.tar.gz |
st: Generate shadows from the silhouette of the source texture
As first mentioned in commit 672171093, the CSS spec defines shadow
colors independently from the colors casting the shadow. It's not
a physical light simulation so a shadow is allowed to be a different
color from texture casting it.
This means we only care about the shape of the source where alpha
values of zero are adjacent to alpha values of non-zero. And all such
non-zero pixels should be treated as fully opaque for the purpose of
shadow generation. While this would be wrong for a physical light
simulation it does allow us to cast shadows around semi-translucent
shapes and better support CSS.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4477
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1918>
(cherry picked from commit 918c063693450a7333abbd02134ad1eb0a95ef8c)
-rw-r--r-- | src/st/st-private.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/st/st-private.c b/src/st/st-private.c index 540bad425..bb981516d 100644 --- a/src/st/st-private.c +++ b/src/st/st-private.c @@ -394,7 +394,10 @@ _st_create_shadow_pipeline (StShadow *shadow_spec, float sigma; int src_height, dst_height; int src_width, dst_width; + CoglPipeline *texture_pipeline; + static CoglPipelineKey texture_pipeline_key = + "st-create-shadow-pipeline-saturate-alpha"; static CoglPipeline *shadow_pipeline_template = NULL; g_return_val_if_fail (shadow_spec != NULL, NULL); @@ -433,10 +436,34 @@ _st_create_shadow_pipeline (StShadow *shadow_spec, }); /* Texture */ - texture_node = clutter_texture_node_new (src_texture, - 0, - CLUTTER_SCALING_FILTER_NEAREST, - CLUTTER_SCALING_FILTER_NEAREST); + texture_pipeline = cogl_context_get_named_pipeline (ctx, + &texture_pipeline_key); + + if (G_UNLIKELY (texture_pipeline == NULL)) + { + CoglSnippet *snippet; + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + "", + "if (cogl_color_out.a > 0.0)\n" + " cogl_color_out.a = 1.0;"); + + texture_pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_add_snippet (texture_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_context_set_named_pipeline (ctx, + &texture_pipeline_key, + texture_pipeline); + } + + /* No need to unref texture_pipeline since the named pipeline hash + * doesn't change its ref count from 1. Also no need to copy texture_pipeline + * since we'll be completely finished with it after clutter_paint_node_paint. + */ + + cogl_pipeline_set_layer_texture (texture_pipeline, 0, src_texture); + texture_node = clutter_pipeline_node_new (texture_pipeline); clutter_paint_node_add_child (blur_node, texture_node); clutter_paint_node_add_rectangle (texture_node, &(ClutterActorBox) { |