diff options
| author | Matthias Clasen <mclasen@redhat.com> | 2021-03-07 10:02:46 -0500 |
|---|---|---|
| committer | Matthias Clasen <mclasen@redhat.com> | 2021-03-07 10:02:46 -0500 |
| commit | a4676e1109eb9899f427e69e3cfffce0ac4474c5 (patch) | |
| tree | 24edde4733d83af57c06ba20faef2d1c612c04c9 | |
| parent | 6ab779cd0689d35a6e164cc629e25f1aea864649 (diff) | |
| download | gtk+-ngl-clip-stats.tar.gz | |
wip: Classify clips and produce statsngl-clip-stats
This is in preparation for avoiding clipping in
shaders if we don't need to.
| -rw-r--r-- | gsk/ngl/gsknglrenderer.c | 4 | ||||
| -rw-r--r-- | gsk/ngl/gsknglrenderjob.c | 100 |
2 files changed, 101 insertions, 3 deletions
diff --git a/gsk/ngl/gsknglrenderer.c b/gsk/ngl/gsknglrenderer.c index c20660f09e..a4c9b983fe 100644 --- a/gsk/ngl/gsknglrenderer.c +++ b/gsk/ngl/gsknglrenderer.c @@ -277,6 +277,8 @@ gsk_ngl_renderer_dispose (GObject *object) G_OBJECT_CLASS (gsk_ngl_renderer_parent_class)->dispose (object); } +extern void dump_clip_stats (void); + static void gsk_ngl_renderer_class_init (GskNglRendererClass *klass) { @@ -289,6 +291,8 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass) renderer_class->unrealize = gsk_ngl_renderer_unrealize; renderer_class->render = gsk_ngl_renderer_render; renderer_class->render_texture = gsk_ngl_renderer_render_texture; + + g_atexit (dump_clip_stats); } static void diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index b8f983f862..12d67e036a 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -742,13 +742,107 @@ gsk_ngl_render_job_transform_rounded_rect (GskNglRenderJob *job, memcpy (out_rect->corner, rect->corner, sizeof rect->corner); } +typedef enum { + CLIP_ALL_CLIPPED, + CLIP_NONE, + CLIP_RECT, + CLIP_ROUNDED +} ClipComplexity; + +static inline void +rounded_rect_get_inner (const GskRoundedRect *rect, + graphene_rect_t *inner) +{ + float left = MAX (rect->corner[GSK_CORNER_TOP_LEFT].width, rect->corner[GSK_CORNER_BOTTOM_LEFT].width); + float right = MAX (rect->corner[GSK_CORNER_TOP_RIGHT].width, rect->corner[GSK_CORNER_BOTTOM_RIGHT].width); + float top = MAX (rect->corner[GSK_CORNER_TOP_LEFT].height, rect->corner[GSK_CORNER_TOP_RIGHT].height); + float bottom = MAX (rect->corner[GSK_CORNER_BOTTOM_LEFT].height, rect->corner[GSK_CORNER_BOTTOM_RIGHT].height); + + inner->origin.x = rect->bounds.origin.x + left; + inner->size.width = rect->bounds.size.width - (left + right); + + inner->origin.y = rect->bounds.origin.y + top; + inner->size.height = rect->bounds.size.height - (top + bottom); +} + static inline gboolean -gsk_ngl_render_job_node_overlaps_clip (GskNglRenderJob *job, - const GskRenderNode *node) +interval_contains (float p1, float w1, + float p2, float w2) +{ + if (p2 < p1) + return FALSE; + + if (p2 + w2 > p1 + w1) + return FALSE; + + return TRUE; +} + +static ClipComplexity +classify_clip (GskNglRenderJob *job, + const GskRenderNode *node) { graphene_rect_t transformed_bounds; + graphene_rect_t inner; + gsk_ngl_render_job_transform_bounds (job, &node->bounds, &transformed_bounds); - return rect_intersects (&job->current_clip->rect.bounds, &transformed_bounds); + + if (!rect_intersects (&job->current_clip->rect.bounds, &transformed_bounds)) + return CLIP_ALL_CLIPPED; + + if (job->current_clip->is_rectilinear) + { + if (rect_contains_rect (&job->current_clip->rect.bounds, &transformed_bounds)) + return CLIP_NONE; + + return CLIP_RECT; + } + + if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_bounds)) + return CLIP_NONE; + + rounded_rect_get_inner (&job->current_clip->rect, &inner); + + if (interval_contains (inner.origin.x, inner.size.width, + transformed_bounds.origin.x, transformed_bounds.size.width)) + return CLIP_RECT; + + if (interval_contains (inner.origin.y, inner.size.height, + transformed_bounds.origin.y, transformed_bounds.size.height)) + return CLIP_RECT; + + return CLIP_ROUNDED; +} + +static guint64 total_clips; +static guint64 clips[CLIP_ROUNDED+1]; + +void dump_clip_stats (void); + +void +dump_clip_stats (void) +{ + g_print ("%.2f%% outside\n", clips[CLIP_ALL_CLIPPED] * 100.0 / (double) (total_clips)); + g_print ("%.2f%% inside\n", clips[CLIP_NONE] * 100.0 / (double) (total_clips)); + g_print ("%.2f%% rect clip\n", clips[CLIP_RECT] * 100.0 / (double) (total_clips)); + g_print ("%.2f%% round clip\n", clips[CLIP_ROUNDED] * 100.0 / (double) (total_clips)); +} + +static inline gboolean +gsk_ngl_render_job_node_overlaps_clip (GskNglRenderJob *job, + const GskRenderNode *node) +{ + ClipComplexity c; + + c = classify_clip (job, node); + + total_clips++; + clips[c]++; + + if (c == CLIP_ALL_CLIPPED) + return FALSE; + + return TRUE; } /* load_vertex_data_with_region */ |
