[9ae8f17cfc8ba7fd8fb34b2a194ef965a3b36a40839a46eeab1350e916692ac9/wip/baedert/for-master: 96/96] gl renderer: Try to intersect rounded clips more often
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [9ae8f17cfc8ba7fd8fb34b2a194ef965a3b36a40839a46eeab1350e916692ac9/wip/baedert/for-master: 96/96] gl renderer: Try to intersect rounded clips more often
- Date: Wed, 8 Jul 2020 03:46:30 +0000 (UTC)
commit cd736376d0a906319b498d598e2975b867ee5db1
Author: Timm Bäder <mail baedert org>
Date: Wed Jul 8 05:45:34 2020 +0200
gl renderer: Try to intersect rounded clips more often
gsk/gl/gskglrenderer.c | 215 ++++++++++++++++++++++++++-----------------------
1 file changed, 116 insertions(+), 99 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 241e7dcce5..0001ca064e 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -905,6 +905,7 @@ upload_texture (GskGLRenderer *self,
}
else
{
+
out_region->texture_id =
gsk_gl_driver_get_texture_for_texture (self->gl_driver,
texture,
@@ -1151,6 +1152,59 @@ rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
return graphene_rect_contains_rect (&inner, rect);
}
+/* Current clip is NOT rounded but new one is definitely! */
+static inline bool
+intersect_rounded_rectilinear (const graphene_rect_t *non_rounded,
+ const GskRoundedRect *rounded,
+ GskRoundedRect *result)
+{
+ int n_corners = 0;
+ bool corners[4];
+
+ /* Intersects with top left corner? */
+ n_corners += corners[0] = rounded_rect_has_corner (rounded, 0) &&
+ graphene_rect_intersection (non_rounded,
+ &rounded_rect_corner (rounded, 0), NULL);
+ /* top right? */
+ n_corners += corners[1] = rounded_rect_has_corner (rounded, 1) &&
+ graphene_rect_intersection (non_rounded,
+ &rounded_rect_corner (rounded, 1), NULL);
+ /* bottom right? */
+ n_corners += corners[2] = rounded_rect_has_corner (rounded, 2) &&
+ graphene_rect_intersection (non_rounded,
+ &rounded_rect_corner (rounded, 2), NULL);
+ /* bottom left */
+ n_corners += corners[3] = rounded_rect_has_corner (rounded, 3) &&
+ graphene_rect_intersection (non_rounded,
+ &rounded_rect_corner (rounded, 3), NULL);
+
+ if (corners[0] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 0)))
+ return false;
+ if (corners[1] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 1)))
+ return false;
+ if (corners[2] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 2)))
+ return false;
+ if (corners[3] && !graphene_rect_contains_rect (non_rounded, &rounded_rect_corner (rounded, 3)))
+ return false;
+
+ /* We do intersect with at least one of the corners, but in such a way that the
+ * intersection between the two clips can still be represented by a single rounded
+ * rect in a trivial way. do that. */
+ graphene_rect_intersection (non_rounded, &rounded->bounds, &result->bounds);
+
+ for (int i = 0; i < 4; i++)
+ {
+ if (corners[i])
+ result->corner[i] = rounded->corner[i];
+ else
+ result->corner[i].width = result->corner[i].height = 0;
+ }
+
+ return true;
+}
+
+/* This code intersects the current (maybe rounded) clip with the new
+ * non-rounded clip */
static inline void
render_clipped_child (GskGLRenderer *self,
RenderOpBuilder *builder,
@@ -1158,112 +1212,57 @@ render_clipped_child (GskGLRenderer *self,
GskRenderNode *child)
{
graphene_rect_t transformed_clip;
- GskRoundedRect child_clip;
+ GskRoundedRect intersection;
ops_transform_bounds_modelview (builder, clip, &transformed_clip);
if (builder->clip_is_rectilinear)
- goto trivial;
-
- {
- const GskRoundedRect *cur_clip = builder->current_clip;
- int n_corners = 0;
- bool corners[4];
-
- /* Intersects with top left corner? */
- n_corners += corners[0] = rounded_rect_has_corner (cur_clip, 0) &&
- graphene_rect_intersection (&transformed_clip,
- &rounded_rect_corner (cur_clip, 0), NULL);
- /* top right? */
- n_corners += corners[1] = rounded_rect_has_corner (cur_clip, 1) &&
- graphene_rect_intersection (&transformed_clip,
- &rounded_rect_corner (cur_clip, 1), NULL);
- /* bottom right? */
- n_corners += corners[2] = rounded_rect_has_corner (cur_clip, 2) &&
- graphene_rect_intersection (&transformed_clip,
- &rounded_rect_corner (cur_clip, 2), NULL);
- /* bottom left */
- n_corners += corners[3] = rounded_rect_has_corner (cur_clip, 3) &&
- graphene_rect_intersection (&transformed_clip,
- &rounded_rect_corner (cur_clip, 3), NULL);
-
- if (n_corners == 0)
- goto trivial;
-
- if (corners[0] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 0)))
- goto rtt;
- if (corners[1] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 1)))
- goto rtt;
- if (corners[2] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 2)))
- goto rtt;
- if (corners[3] && !graphene_rect_contains_rect (&transformed_clip, &rounded_rect_corner (cur_clip, 3)))
- goto rtt;
-
- /* We do intersect with at least one of the corners, but in such a way that the
- * intersection between the two clips can still be represented by a single rounded
- * rect in a trivial way. do that. */
- {
- GskRoundedRect real_intersection;
-
- graphene_rect_intersection (&transformed_clip, &cur_clip->bounds, &real_intersection.bounds);
-
- for (int i = 0; i < 4; i++)
- {
- if (corners[i])
- real_intersection.corner[i] = cur_clip->corner[i];
- else
- real_intersection.corner[i].width = real_intersection.corner[i].height = 0;
- }
+ {
+ memset (&intersection, 0, sizeof (GskRoundedRect));
+ graphene_rect_intersection (&transformed_clip,
+ &builder->current_clip->bounds,
+ &intersection.bounds);
- /* Draw with that new clip */
- ops_push_clip (builder, &real_intersection);
+ ops_push_clip (builder, &intersection);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_clip (builder);
}
- return;
- }
+ else if (intersect_rounded_rectilinear (&transformed_clip,
+ builder->current_clip,
+ &intersection))
+ {
+ ops_push_clip (builder, &intersection);
+ gsk_gl_renderer_add_render_ops (self, child, builder);
+ ops_pop_clip (builder);
+ }
+ else
+ {
+ /* well fuck */
+ const float scale = ops_get_scale (builder);
+ gboolean is_offscreen;
+ TextureRegion region;
+ GskRoundedRect scaled_clip;
-rtt:
- {
- /* well fuck */
- const float scale = ops_get_scale (builder);
- gboolean is_offscreen;
- TextureRegion region;
- GskRoundedRect scaled_clip;
-
- memset (&scaled_clip, 0, sizeof (GskRoundedRect));
-
- scaled_clip.bounds.origin.x = clip->origin.x * scale;
- scaled_clip.bounds.origin.y = clip->origin.y * scale;
- scaled_clip.bounds.size.width = clip->size.width * scale;
- scaled_clip.bounds.size.height = clip->size.height * scale;
-
- ops_push_clip (builder, &scaled_clip);
- if (!add_offscreen_ops (self, builder, &child->bounds,
- child,
- ®ion, &is_offscreen,
- RESET_OPACITY | FORCE_OFFSCREEN))
- g_assert_not_reached ();
- ops_pop_clip (builder);
+ memset (&scaled_clip, 0, sizeof (GskRoundedRect));
- ops_set_program (builder, &self->programs->blit_program);
- ops_set_texture (builder, region.texture_id);
-
- load_offscreen_vertex_data (ops_draw (builder, NULL), child, builder);
- return;
- }
+ scaled_clip.bounds.origin.x = clip->origin.x * scale;
+ scaled_clip.bounds.origin.y = clip->origin.y * scale;
+ scaled_clip.bounds.size.width = clip->size.width * scale;
+ scaled_clip.bounds.size.height = clip->size.height * scale;
+ ops_push_clip (builder, &scaled_clip);
+ if (!add_offscreen_ops (self, builder, &child->bounds,
+ child,
+ ®ion, &is_offscreen,
+ RESET_OPACITY | FORCE_OFFSCREEN))
+ g_assert_not_reached ();
+ ops_pop_clip (builder);
-trivial:
- memset (&child_clip, 0, sizeof (GskRoundedRect));
- graphene_rect_intersection (&transformed_clip,
- &builder->current_clip->bounds,
- &child_clip.bounds);
+ ops_set_program (builder, &self->programs->blit_program);
+ ops_set_texture (builder, region.texture_id);
- ops_push_clip (builder, &child_clip);
- gsk_gl_renderer_add_render_ops (self, child, builder);
- ops_pop_clip (builder);
- return;
+ load_offscreen_vertex_data (ops_draw (builder, NULL), child, builder);
+ }
}
static inline void
@@ -1293,6 +1292,29 @@ render_rounded_clip_node (GskGLRenderer *self,
return;
ops_transform_bounds_modelview (builder, &clip->bounds, &transformed_clip.bounds);
+ for (i = 0; i < 4; i ++)
+ {
+ transformed_clip.corner[i].width = clip->corner[i].width * scale;
+ transformed_clip.corner[i].height = clip->corner[i].height * scale;
+ }
+
+ if (builder->clip_is_rectilinear)
+ {
+ GskRoundedRect intersected_clip;
+
+ if (intersect_rounded_rectilinear (&builder->current_clip->bounds,
+ &transformed_clip,
+ &intersected_clip))
+ {
+ ops_push_clip (builder, &intersected_clip);
+ gsk_gl_renderer_add_render_ops (self, child, builder);
+ ops_pop_clip (builder);
+ return;
+ }
+ }
+
+ /* After this point we are really working with a new and a current clip
+ * which both have rounded corners. */
if (!ops_has_clip (builder))
need_offscreen = FALSE;
@@ -1306,11 +1328,6 @@ render_rounded_clip_node (GskGLRenderer *self,
{
/* If they don't intersect at all, we can simply set
* the new clip and add the render ops */
- for (i = 0; i < 4; i ++)
- {
- transformed_clip.corner[i].width = clip->corner[i].width * scale;
- transformed_clip.corner[i].height = clip->corner[i].height * scale;
- }
/* If the new clip entirely contains the current clip, the intersection is simply
* the current clip, so we can ignore the new one */
@@ -1352,7 +1369,7 @@ render_rounded_clip_node (GskGLRenderer *self,
if (!add_offscreen_ops (self, builder, &node->bounds,
child,
®ion, &is_offscreen,
- FORCE_OFFSCREEN | RESET_OPACITY))
+ FORCE_OFFSCREEN | RESET_OPACITY | DUMP_FRAMEBUFFER))
g_assert_not_reached ();
ops_pop_clip (builder);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]