gl renderer: Use stack to keep track of modelview matrix

So we can avoid calculating metadata for matrices all the time.
This commit is contained in:
Timm Bäder 2018-11-26 17:52:35 +01:00
parent fe49f83982
commit ef751bc809
3 changed files with 140 additions and 55 deletions

View File

@ -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);*/

View File

@ -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... */
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
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));
head = &g_array_index (builder->mv_stack, MatrixStackEntry, 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));
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

View File

@ -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);