[gtk] gl renderer: Use stack to keep track of modelview matrix
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk] gl renderer: Use stack to keep track of modelview matrix
- Date: Tue, 27 Nov 2018 05:18:41 +0000 (UTC)
commit ef751bc809dbaabf8c08efb2e38171e3181371d8
Author: Timm Bäder <mail baedert org>
Date: Mon Nov 26 17:52:35 2018 +0100
gl renderer: Use stack to keep track of modelview matrix
So we can avoid calculating metadata for matrices all the time.
gsk/gl/gskglrenderer.c | 38 ++++++------
gsk/gl/gskglrenderops.c | 128 ++++++++++++++++++++++++++++++++---------
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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]