diff options
author | Timm Bäder <mail@baedert.org> | 2018-11-26 17:52:35 +0100 |
---|---|---|
committer | Timm Bäder <mail@baedert.org> | 2018-11-27 05:39:27 +0100 |
commit | ef751bc809dbaabf8c08efb2e38171e3181371d8 (patch) | |
tree | 575ed7821898cd4921c0d26679e87a3708c5d829 /gsk | |
parent | fe49f83982a79108cf28e1b14091654268c45e7e (diff) | |
download | gtk+-ef751bc809dbaabf8c08efb2e38171e3181371d8.tar.gz |
gl renderer: Use stack to keep track of modelview matrix
So we can avoid calculating metadata for matrices all the time.
Diffstat (limited to 'gsk')
-rw-r--r-- | gsk/gl/gskglrenderer.c | 38 | ||||
-rw-r--r-- | gsk/gl/gskglrenderops.c | 128 | ||||
-rw-r--r-- | gsk/gl/gskglrenderopsprivate.h | 29 |
3 files changed, 140 insertions, 55 deletions
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 5ba5840a53..f8074a4531 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -301,7 +301,7 @@ rounded_rect_to_floats (GskGLRenderer *self, int i; graphene_rect_t transformed_bounds; - graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_bounds); + graphene_matrix_transform_bounds (builder->current_modelview, &rect->bounds, &transformed_bounds); outline[0] = transformed_bounds.origin.x; outline[1] = transformed_bounds.origin.y; @@ -578,7 +578,7 @@ render_border_node (GskGLRenderer *self, /* Prepare outline */ outline = *rounded_outline; - graphene_matrix_transform_bounds (&builder->current_modelview, + graphene_matrix_transform_bounds (builder->current_modelview, &outline.bounds, &outline.bounds); for (i = 0; i < 4; i ++) { @@ -711,17 +711,15 @@ render_offset_node (GskGLRenderer *self, default: { - graphene_matrix_t prev_mv; graphene_matrix_t transform, transformed_mv; graphene_matrix_init_translate (&transform, &GRAPHENE_POINT3D_INIT(dx, dy, 1.0)); - graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv); - prev_mv = ops_set_modelview (builder, &transformed_mv); + graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv); + ops_push_modelview (builder, &transformed_mv); gsk_gl_renderer_add_render_ops (self, child, builder); - - ops_set_modelview (builder, &prev_mv); + ops_pop_modelview (builder); } } } @@ -732,16 +730,14 @@ render_transform_node (GskGLRenderer *self, RenderOpBuilder *builder) { GskRenderNode *child = gsk_transform_node_get_child (node); - graphene_matrix_t prev_mv; graphene_matrix_t transform, transformed_mv; graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node)); - graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv); - prev_mv = ops_set_modelview (builder, &transformed_mv); + graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv); + ops_push_modelview (builder, &transformed_mv); gsk_gl_renderer_add_render_ops (self, child, builder); - - ops_set_modelview (builder, &prev_mv); + ops_pop_modelview (builder); } static inline void @@ -805,7 +801,7 @@ render_clip_node (GskGLRenderer *self, GskRoundedRect child_clip; transformed_clip = *gsk_clip_node_peek_clip (node); - graphene_matrix_transform_bounds (&builder->current_modelview, &transformed_clip, &transformed_clip); + graphene_matrix_transform_bounds (builder->current_modelview, &transformed_clip, &transformed_clip); graphene_rect_intersection (&transformed_clip, &builder->current_clip.bounds, @@ -835,7 +831,7 @@ render_rounded_clip_node (GskGLRenderer *self, int i; transformed_clip = child_clip; - graphene_matrix_transform_bounds (&builder->current_modelview, &child_clip.bounds, &transformed_clip.bounds); + graphene_matrix_transform_bounds (builder->current_modelview, &child_clip.bounds, &transformed_clip.bounds); if (graphene_rect_contains_rect (&builder->current_clip.bounds, &transformed_clip.bounds)) @@ -1071,7 +1067,6 @@ render_outset_shadow_node (GskGLRenderer *self, RenderOp op; graphene_matrix_t identity; graphene_matrix_t prev_projection; - graphene_matrix_t prev_modelview; graphene_rect_t prev_viewport; graphene_matrix_t item_proj; int blurred_texture_id; @@ -1124,7 +1119,7 @@ render_outset_shadow_node (GskGLRenderer *self, op.op = OP_CLEAR; ops_add (builder, &op); prev_projection = ops_set_projection (builder, &item_proj); - prev_modelview = ops_set_modelview (builder, &identity); + ops_push_modelview (builder, &identity); prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height)); /* Draw outline */ @@ -1175,7 +1170,7 @@ render_outset_shadow_node (GskGLRenderer *self, ops_set_clip (builder, &prev_clip); ops_set_viewport (builder, &prev_viewport); - ops_set_modelview (builder, &prev_modelview); + ops_pop_modelview (builder); ops_set_projection (builder, &prev_projection); ops_set_render_target (builder, prev_render_target); @@ -2273,7 +2268,6 @@ add_offscreen_ops (GskGLRenderer *self, RenderOp op; graphene_matrix_t identity; graphene_matrix_t prev_projection; - graphene_matrix_t prev_modelview; graphene_rect_t prev_viewport; graphene_matrix_t item_proj; GskRoundedRect prev_clip; @@ -2313,7 +2307,7 @@ add_offscreen_ops (GskGLRenderer *self, op.op = OP_CLEAR; ops_add (builder, &op); prev_projection = ops_set_projection (builder, &item_proj); - prev_modelview = ops_set_modelview (builder, &identity); + ops_push_modelview (builder, &identity); prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (min_x * scale, min_y * scale, width, height)); @@ -2329,7 +2323,7 @@ add_offscreen_ops (GskGLRenderer *self, ops_set_clip (builder, &prev_clip); ops_set_viewport (builder, &prev_viewport); - ops_set_modelview (builder, &prev_modelview); + ops_pop_modelview (builder); ops_set_projection (builder, &prev_projection); ops_set_render_target (builder, prev_render_target); @@ -2547,11 +2541,11 @@ gsk_gl_renderer_do_render (GskRenderer *renderer, memset (&render_op_builder, 0, sizeof (render_op_builder)); render_op_builder.renderer = self; render_op_builder.current_projection = projection; - render_op_builder.current_modelview = modelview; render_op_builder.current_viewport = *viewport; render_op_builder.current_opacity = 1.0f; render_op_builder.render_ops = self->render_ops; gsk_rounded_rect_init_from_rect (&render_op_builder.current_clip, viewport, 0.0f); + ops_push_modelview (&render_op_builder, &modelview); if (fbo_id != 0) ops_set_render_target (&render_op_builder, fbo_id); @@ -2560,6 +2554,8 @@ gsk_gl_renderer_do_render (GskRenderer *renderer, /* We correctly reset the state everywhere */ g_assert_cmpint (render_op_builder.current_render_target, ==, fbo_id); + ops_pop_modelview (&render_op_builder); + ops_finish (&render_op_builder); /*g_message ("Ops: %u", self->render_ops->len);*/ diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c index f89022b133..f0ef2f633e 100644 --- a/gsk/gl/gskglrenderops.c +++ b/gsk/gl/gskglrenderops.c @@ -1,5 +1,13 @@ #include "gskglrenderopsprivate.h" +void +ops_finish (RenderOpBuilder *builder) +{ + if (builder->mv_stack) + g_array_free (builder->mv_stack, TRUE); +} + + static inline void rgba_to_float (const GdkRGBA *c, float *f) @@ -13,24 +21,14 @@ rgba_to_float (const GdkRGBA *c, float ops_get_scale (const RenderOpBuilder *builder) { - const graphene_matrix_t *mv = &builder->current_modelview; - graphene_vec3_t col1; - graphene_vec3_t col2; + const MatrixStackEntry *head; - /* TODO: We should probably split this up into two values... */ - - graphene_vec3_init (&col1, - graphene_matrix_get_value (mv, 0, 0), - graphene_matrix_get_value (mv, 1, 0), - graphene_matrix_get_value (mv, 2, 0)); + g_assert (builder->mv_stack != NULL); + g_assert (builder->mv_stack->len >= 1); - graphene_vec3_init (&col2, - graphene_matrix_get_value (mv, 0, 1), - graphene_matrix_get_value (mv, 1, 1), - graphene_matrix_get_value (mv, 2, 1)); + head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1); - return MAX (graphene_vec3_length (&col1), - graphene_vec3_length (&col2)); + return head->metadata.scale; } static inline gboolean @@ -64,23 +62,59 @@ matrix_is_only_translation (const graphene_matrix_t *mat) return TRUE; } +static void +extract_matrix_metadata (const graphene_matrix_t *m, + OpsMatrixMetadata *md) +{ + graphene_vec3_t col1; + graphene_vec3_t col2; + + /* Is this matrix JUST a translation? */ + md->is_only_translation = matrix_is_only_translation (m); + + /* TODO: We should probably split this up into two values... */ + + /* Scale */ + graphene_vec3_init (&col1, + graphene_matrix_get_value (m, 0, 0), + graphene_matrix_get_value (m, 1, 0), + graphene_matrix_get_value (m, 2, 0)); + + graphene_vec3_init (&col2, + graphene_matrix_get_value (m, 0, 1), + graphene_matrix_get_value (m, 1, 1), + graphene_matrix_get_value (m, 2, 1)); + + md->scale = MAX (graphene_vec3_length (&col1), + graphene_vec3_length (&col2)); + +} + + void ops_transform_bounds_modelview (const RenderOpBuilder *builder, const graphene_rect_t *src, graphene_rect_t *dst) { - if (builder->modelview_is_translation) + const MatrixStackEntry *head; + + g_assert (builder->mv_stack != NULL); + g_assert (builder->mv_stack->len >= 1); + + head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1); + + if (head->metadata.is_only_translation) { graphene_vec4_t row4; /* TODO: We could do the get_row here only once, when setting the new modelview matrix. */ - graphene_matrix_get_row (&builder->current_modelview, 3, &row4); + graphene_matrix_get_row (builder->current_modelview, 3, &row4); *dst = *src; graphene_rect_offset (dst, graphene_vec4_get_x (&row4), graphene_vec4_get_y (&row4)); } else { - graphene_matrix_transform_bounds (&builder->current_modelview, + graphene_matrix_transform_bounds (builder->current_modelview, src, dst); } @@ -118,12 +152,12 @@ ops_set_program (RenderOpBuilder *builder, } if (memcmp (&empty_matrix, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) == 0 || - memcmp (&builder->current_modelview, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) != 0) + memcmp (builder->current_modelview, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) != 0) { op.op = OP_CHANGE_MODELVIEW; - op.modelview = builder->current_modelview; + op.modelview = *builder->current_modelview; g_array_append_val (builder->render_ops, op); - builder->program_state[program->index].modelview = builder->current_modelview; + builder->program_state[program->index].modelview = *builder->current_modelview; } if (memcmp (&empty_rect, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) == 0 || @@ -187,17 +221,16 @@ ops_set_clip (RenderOpBuilder *builder, return prev_clip; } -graphene_matrix_t +static void ops_set_modelview (RenderOpBuilder *builder, const graphene_matrix_t *modelview) { RenderOp op; - graphene_matrix_t prev_mv; if (builder->current_program && memcmp (&builder->program_state[builder->current_program->index].modelview, modelview, sizeof (graphene_matrix_t)) == 0) - return *modelview; + return; if (builder->render_ops->len > 0) { @@ -222,12 +255,51 @@ ops_set_modelview (RenderOpBuilder *builder, if (builder->current_program != NULL) builder->program_state[builder->current_program->index].modelview = *modelview; +} - prev_mv = builder->current_modelview; - builder->current_modelview = *modelview; - builder->modelview_is_translation = matrix_is_only_translation (modelview); +void +ops_push_modelview (RenderOpBuilder *builder, + const graphene_matrix_t *mv) +{ + MatrixStackEntry *entry; - return prev_mv; + if (G_UNLIKELY (builder->mv_stack == NULL)) + builder->mv_stack = g_array_new (FALSE, TRUE, sizeof (MatrixStackEntry)); + + g_assert (builder->mv_stack != NULL); + + g_array_set_size (builder->mv_stack, builder->mv_stack->len + 1); + entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1); + + entry->matrix = *mv; + extract_matrix_metadata (mv, &entry->metadata); + + builder->current_modelview = &entry->matrix; + ops_set_modelview (builder, mv); +} + +void +ops_pop_modelview (RenderOpBuilder *builder) +{ + const graphene_matrix_t *m; + const MatrixStackEntry *head; + + g_assert (builder->mv_stack); + g_assert (builder->mv_stack->len >= 1); + + builder->mv_stack->len --; + head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1); + m = &head->matrix; + + if (builder->mv_stack->len >= 1) + { + builder->current_modelview = m; + ops_set_modelview (builder, m); + } + else + { + builder->current_modelview = NULL; + } } graphene_matrix_t diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index c77de348b4..18a4734257 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -12,6 +12,20 @@ #define GL_N_VERTICES 6 #define GL_N_PROGRAMS 12 + + +typedef struct +{ + guint is_only_translation : 1; + float scale; +} OpsMatrixMetadata; + +typedef struct +{ + graphene_matrix_t matrix; + OpsMatrixMetadata metadata; +} MatrixStackEntry; + enum { OP_NONE, OP_CHANGE_OPACITY = 1, @@ -222,9 +236,6 @@ typedef struct int current_texture; GskRoundedRect current_clip; - graphene_matrix_t current_modelview; - guint modelview_is_translation : 1; - graphene_matrix_t current_projection; graphene_rect_t current_viewport; float current_opacity; @@ -234,10 +245,19 @@ typedef struct GArray *render_ops; GskGLRenderer *renderer; + + /* Stack of modelview matrices */ + GArray *mv_stack; + /* Pointer into mv_stack */ + const graphene_matrix_t *current_modelview; } RenderOpBuilder; +void ops_finish (RenderOpBuilder *builder); +void ops_push_modelview (RenderOpBuilder *builder, + const graphene_matrix_t *mv); +void ops_pop_modelview (RenderOpBuilder *builder); float ops_get_scale (const RenderOpBuilder *builder); void ops_set_program (RenderOpBuilder *builder, @@ -246,9 +266,6 @@ void ops_set_program (RenderOpBuilder *builder, GskRoundedRect ops_set_clip (RenderOpBuilder *builder, const GskRoundedRect *clip); -graphene_matrix_t ops_set_modelview (RenderOpBuilder *builder, - const graphene_matrix_t *modelview); - void ops_transform_bounds_modelview (const RenderOpBuilder *builder, const graphene_rect_t *src, graphene_rect_t *dst); |