[gtk] gl renderer: Implement blurred shadow nodes
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk] gl renderer: Implement blurred shadow nodes
- Date: Tue, 3 Dec 2019 08:13:54 +0000 (UTC)
commit fb5dc7384148111bcec2993b853601efe0de5bd1
Author: Timm Bäder <mail baedert org>
Date: Fri Nov 29 06:54:43 2019 +0100
gl renderer: Implement blurred shadow nodes
gsk/gl/gskglrenderer.c | 121 +++++++++++++++++++++++++++++++++----------------
1 file changed, 82 insertions(+), 39 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 3c874a7450..9f439e5c32 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -64,7 +64,9 @@ typedef enum
FORCE_OFFSCREEN = 1 << 0,
RESET_CLIP = 1 << 1,
RESET_OPACITY = 1 << 2,
- DUMP_FRAMEBUFFER = 1 << 3
+ DUMP_FRAMEBUFFER = 1 << 3,
+ CENTER_CHILD = 1 << 4,
+ NO_CACHE_PLZ = 1 << 5,
} OffscreenFlags;
typedef struct
@@ -1966,31 +1968,16 @@ render_outset_shadow_node (GskGLRenderer *self,
}
static inline void
-render_shadow_node (GskGLRenderer *self,
- GskRenderNode *node,
- RenderOpBuilder *builder)
-{
- float min_x;
- float min_y;
- float max_x;
- float max_y;
+render_shadow_node (GskGLRenderer *self,
+ GskRenderNode *node,
+ RenderOpBuilder *builder)
+{
+ const float scale = ops_get_scale (builder);
+ const gsize n_shadows = gsk_shadow_node_get_n_shadows (node);
GskRenderNode *original_child = gsk_shadow_node_get_child (node);
GskRenderNode *shadow_child = original_child;
- gsize n_shadows = gsk_shadow_node_get_n_shadows (node);
guint i;
- /* TODO: Implement blurred shadow nodes */;
- for (i = 0; i < n_shadows; i ++)
- {
- const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
-
- if (shadow->radius > 0)
- {
- render_fallback_node (self, node, builder);
- return;
- }
- }
-
/* Shadow nodes recolor every pixel of the source texture, but leave the alpha in tact.
* If the child is a color matrix node that doesn't touch the alpha, we can throw that away. */
if (gsk_render_node_get_node_type (shadow_child) == GSK_COLOR_MATRIX_NODE &&
@@ -1999,11 +1986,6 @@ render_shadow_node (GskGLRenderer *self,
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
}
- min_x = builder->dx + shadow_child->bounds.origin.x;
- min_y = builder->dy + shadow_child->bounds.origin.y;
- max_x = min_x + shadow_child->bounds.size.width;
- max_y = min_y + shadow_child->bounds.size.height;
-
for (i = 0; i < n_shadows; i ++)
{
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
@@ -2011,10 +1993,13 @@ render_shadow_node (GskGLRenderer *self,
const float dy = shadow->dy;
TextureRegion region;
gboolean is_offscreen;
+ float min_x;
+ float min_y;
+ float max_x;
+ float max_y;
- g_assert (shadow->radius <= 0);
-
- if (gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
+ if (shadow->radius == 0 &&
+ gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
{
ops_offset (builder, dx, dy);
render_text_node (self, shadow_child, builder, &shadow->color, TRUE);
@@ -2028,12 +2013,57 @@ render_shadow_node (GskGLRenderer *self,
if (node_is_invisible (shadow_child))
continue;
- /* Draw the child offscreen, without the offset. */
- if (!add_offscreen_ops (self, builder,
- &shadow_child->bounds,
- shadow_child, ®ion, &is_offscreen,
- RESET_CLIP | RESET_OPACITY))
- g_assert_not_reached ();
+ if (shadow->radius > 0)
+ {
+ const float blur_extra = shadow->radius * 3.0 / 2.0;
+
+ /* TODO: - same problem as in render_blur_node: we're forcing the
+ * child node on a texture, even though it might already be a texture. */
+ if (!add_offscreen_ops (self, builder,
+ &GRAPHENE_RECT_INIT (
+ 0, 0,
+ shadow_child->bounds.size.width + (blur_extra * 2),
+ shadow_child->bounds.size.height + (blur_extra * 2)
+ ),
+ shadow_child, ®ion, &is_offscreen,
+ RESET_CLIP | RESET_OPACITY | CENTER_CHILD |
+ NO_CACHE_PLZ | FORCE_OFFSCREEN))
+ g_assert_not_reached ();
+
+ region.texture_id = blur_texture (self, builder,
+ ®ion,
+ (shadow_child->bounds.size.width + blur_extra * 2) * scale,
+ (shadow_child->bounds.size.height + blur_extra * 2) * scale,
+ shadow->radius * scale);
+ init_full_texture_region (®ion, region.texture_id);
+
+ is_offscreen = TRUE;
+
+ min_x = builder->dx + shadow_child->bounds.origin.x - blur_extra;
+ min_y = builder->dy + shadow_child->bounds.origin.y - blur_extra;
+ max_x = min_x + shadow_child->bounds.size.width + blur_extra * 2;
+ max_y = min_y + shadow_child->bounds.size.height + blur_extra * 2;
+ }
+ else if (dx == 0 && dy == 0)
+ {
+ continue; /* Invisible anyway */
+ }
+ else
+ {
+ if (dx == 0 && dy == 0)
+ continue;
+
+ if (!add_offscreen_ops (self, builder,
+ &shadow_child->bounds,
+ shadow_child, ®ion, &is_offscreen,
+ RESET_CLIP | RESET_OPACITY | NO_CACHE_PLZ))
+ g_assert_not_reached ();
+
+ min_x = builder->dx + shadow_child->bounds.origin.x;
+ min_y = builder->dy + shadow_child->bounds.origin.y;
+ max_x = min_x + shadow_child->bounds.size.width;
+ max_y = min_y + shadow_child->bounds.size.height;
+ }
ops_set_program (builder, &self->coloring_program);
ops_set_color (builder, &shadow->color);
@@ -3131,8 +3161,20 @@ add_offscreen_ops (GskGLRenderer *self,
bounds->origin.y * scale,
width, height));
- builder->dx = 0;
- builder->dy = 0;
+ if (flags & CENTER_CHILD)
+ {
+ ops_offset (builder,
+ (bounds->size.width - child_node->bounds.size.width) / 2.0 -
+ child_node->bounds.origin.x,
+ (bounds->size.height - child_node->bounds.size.height) / 2.0 -
+ child_node->bounds.origin.y);
+ }
+ else
+ {
+ builder->dx = 0;
+ builder->dy = 0;
+ }
+
if (flags & RESET_OPACITY)
prev_opacity = ops_set_opacity (builder, 1.0);
@@ -3167,7 +3209,8 @@ add_offscreen_ops (GskGLRenderer *self,
*is_offscreen = TRUE;
init_full_texture_region (texture_region_out, texture_id);
- gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
+ if ((flags & NO_CACHE_PLZ) == 0)
+ gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]