mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 11:20:12 +00:00
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:
parent
fe49f83982
commit
ef751bc809
@ -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);*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user