summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel van Vugt <daniel.van.vugt@canonical.com>2021-07-16 18:34:11 +0800
committerFlorian Müllner <fmuellner@gnome.org>2022-03-20 15:56:35 +0100
commit4270d9040197855df66290e3998cb9d4271151e8 (patch)
tree4c3a680bb29623584a83f04a6cf7b846ffcdafa6
parente5315d2c31cd90aa76e8fa9ef87c3250c0d6302a (diff)
downloadgnome-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.c35
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) {