[gtk] gl renderer: Stop determining the matrix category ourselves
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk] gl renderer: Stop determining the matrix category ourselves
- Date: Mon, 25 Feb 2019 07:46:56 +0000 (UTC)
commit 58c2bea959b447b36f37757fd6a1a2ae8ea675c8
Author: Timm Bäder <mail baedert org>
Date: Sat Feb 23 07:50:51 2019 +0100
gl renderer: Stop determining the matrix category ourselves
Use the category we get from transform nodes and add ops_ API to supply
one when we set a graphene_matrix_t directly.
gsk/gl/gskglrenderer.c | 119 +++++++++++------------
gsk/gl/gskglrenderops.c | 208 ++++++++++++++++++++++++++---------------
gsk/gl/gskglrenderopsprivate.h | 14 ++-
3 files changed, 195 insertions(+), 146 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 24f5452491..4128953430 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -249,6 +249,8 @@ node_supports_transform (GskRenderNode *node)
case GSK_OPACITY_NODE:
case GSK_COLOR_MATRIX_NODE:
case GSK_TEXTURE_NODE:
+ case GSK_TRANSFORM_NODE:
+ case GSK_CROSS_FADE_NODE:
return TRUE;
default:
@@ -769,7 +771,6 @@ render_transform_node (GskGLRenderer *self,
const graphene_matrix_t *node_transform = gsk_transform_node_peek_transform (node);
GskRenderNode *child = gsk_transform_node_get_child (node);
-
switch (category)
{
case GSK_MATRIX_CATEGORY_IDENTITY:
@@ -789,23 +790,9 @@ render_transform_node (GskGLRenderer *self,
case GSK_MATRIX_CATEGORY_2D_AFFINE:
{
- const float scale = ops_get_scale (builder);
- graphene_matrix_t transform, transformed_mv;
- const float dx = builder->dx;
- const float dy = builder->dy;
-
- graphene_matrix_init_from_matrix (&transform, node_transform);
- graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
- graphene_matrix_translate (&transformed_mv,
- &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
-
- builder->dx = 0;
- builder->dy = 0;
- ops_push_modelview (builder, &transformed_mv);
+ ops_push_modelview (builder, node_transform, category);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_modelview (builder);
- builder->dx = dx;
- builder->dy = dy;
}
break;
@@ -814,8 +801,6 @@ render_transform_node (GskGLRenderer *self,
case GSK_MATRIX_CATEGORY_INVERTIBLE:
default:
{
- const float scale = ops_get_scale (builder);
- graphene_matrix_t transform, transformed_mv;
const float min_x = child->bounds.origin.x;
const float min_y = child->bounds.origin.y;
const float max_x = min_x + child->bounds.size.width;
@@ -823,53 +808,56 @@ render_transform_node (GskGLRenderer *self,
int texture_id;
gboolean is_offscreen;
- graphene_matrix_init_from_matrix (&transform, node_transform);
- graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
- graphene_matrix_translate (&transformed_mv,
- &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
-
- ops_push_modelview (builder, &transformed_mv);
- /* For non-trivial transforms, we draw everything on a texture and then
- * draw the texture transformed. */
- /* TODO: We should compute a modelview containing only the "non-trivial"
- * part (e.g. the rotation) and use that. We want to keep the scale
- * for the texture.
- */
- add_offscreen_ops (self, builder,
- &child->bounds,
- child,
- &texture_id, &is_offscreen,
- RESET_CLIP | RESET_OPACITY);
- ops_set_texture (builder, texture_id);
- ops_set_program (builder, &self->blit_program);
-
- if (is_offscreen)
- {
- const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
- { { min_x, min_y }, { 0, 1 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
-
- { { max_x, max_y }, { 1, 0 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
- };
+ ops_push_modelview (builder, node_transform, category);
- ops_draw (builder, offscreen_vertex_data);
+ if (node_supports_transform (child))
+ {
+ gsk_gl_renderer_add_render_ops (self, child, builder);
}
else
{
- const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
- { { min_x, min_y }, { 0, 0 }, },
- { { min_x, max_y }, { 0, 1 }, },
- { { max_x, min_y }, { 1, 0 }, },
-
- { { max_x, max_y }, { 1, 1 }, },
- { { min_x, max_y }, { 0, 1 }, },
- { { max_x, min_y }, { 1, 0 }, },
- };
-
- ops_draw (builder, onscreen_vertex_data);
+ /* For non-trivial transforms, we draw everything on a texture and then
+ * draw the texture transformed. */
+ /* TODO: We should compute a modelview containing only the "non-trivial"
+ * part (e.g. the rotation) and use that. We want to keep the scale
+ * for the texture.
+ */
+ add_offscreen_ops (self, builder,
+ &child->bounds,
+ child,
+ &texture_id, &is_offscreen,
+ RESET_CLIP | RESET_OPACITY);
+ ops_set_texture (builder, texture_id);
+ ops_set_program (builder, &self->blit_program);
+
+ if (is_offscreen)
+ {
+ const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
+ { { min_x, min_y }, { 0, 1 }, },
+ { { min_x, max_y }, { 0, 0 }, },
+ { { max_x, min_y }, { 1, 1 }, },
+
+ { { max_x, max_y }, { 1, 0 }, },
+ { { min_x, max_y }, { 0, 0 }, },
+ { { max_x, min_y }, { 1, 1 }, },
+ };
+
+ ops_draw (builder, offscreen_vertex_data);
+ }
+ else
+ {
+ const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
+ { { min_x, min_y }, { 0, 0 }, },
+ { { min_x, max_y }, { 0, 1 }, },
+ { { max_x, min_y }, { 1, 0 }, },
+
+ { { max_x, max_y }, { 1, 1 }, },
+ { { min_x, max_y }, { 0, 1 }, },
+ { { max_x, min_y }, { 1, 0 }, },
+ };
+
+ ops_draw (builder, onscreen_vertex_data);
+ }
}
ops_pop_modelview (builder);
@@ -1306,7 +1294,7 @@ render_outset_shadow_node (GskGLRenderer *self,
op.op = OP_CLEAR;
ops_add (builder, &op);
prev_projection = ops_set_projection (builder, &item_proj);
- ops_push_modelview (builder, &identity);
+ ops_set_modelview (builder, &identity, GSK_MATRIX_CATEGORY_IDENTITY);
prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
/* Draw outline */
@@ -2368,7 +2356,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
break;
case GSK_DEBUG_NODE:
- gsk_gl_renderer_add_render_ops (self,
+ gsk_gl_renderer_add_render_ops (self,
gsk_debug_node_get_child (node),
builder);
break;
@@ -2523,7 +2511,7 @@ add_offscreen_ops (GskGLRenderer *self,
op.op = OP_CLEAR;
ops_add (builder, &op);
prev_projection = ops_set_projection (builder, &item_proj);
- ops_push_modelview (builder, &identity);
+ ops_set_modelview (builder, &identity, GSK_MATRIX_CATEGORY_IDENTITY);
prev_viewport = ops_set_viewport (builder,
&GRAPHENE_RECT_INIT (bounds->origin.x * scale,
bounds->origin.y * scale,
@@ -2783,7 +2771,8 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
render_op_builder.current_viewport = *viewport;
render_op_builder.current_opacity = 1.0f;
render_op_builder.render_ops = self->render_ops;
- ops_push_modelview (&render_op_builder, &modelview);
+ ops_set_modelview (&render_op_builder, &modelview,
+ scale_factor == 1 ? GSK_MATRIX_CATEGORY_IDENTITY : GSK_MATRIX_CATEGORY_2D_AFFINE);
/* Initial clip is self->render_region! */
if (self->render_region != NULL)
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
index 9fbc9ec405..ee5e19b479 100644
--- a/gsk/gl/gskglrenderops.c
+++ b/gsk/gl/gskglrenderops.c
@@ -63,63 +63,55 @@ static void
extract_matrix_metadata (const graphene_matrix_t *m,
OpsMatrixMetadata *md)
{
- graphene_vec3_t col1;
- graphene_vec3_t col2;
-
- /* Translate */
- md->translate_x = graphene_matrix_get_value (m, 3, 0);
- md->translate_y = graphene_matrix_get_value (m, 3, 1);
-
- /* 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_x = graphene_vec3_length (&col1);
- md->scale_y = graphene_vec3_length (&col2);
-
- /* A simple matrix (in our case) is one that doesn't do anything but scale
- * and/or translate.
- *
- * For orher matrices, we fall back to offscreen drawing.
- */
- md->simple = TRUE;
- {
- static const guchar check_zero[4][4] = {
- { 0, 1, 0, 1 }, /* If any of the values marked as '1' here is non-zero, */
- { 1, 0, 0, 1 }, /* We have to resort to offscreen drawing later on. */
- { 1, 1, 0, 1 },
- { 0, 0, 0, 0 },
- };
- int x, y;
-
- for (x = 0; x < 4; x ++)
- for (y = 0; y < 4; y ++)
- if (check_zero[y][x] &&
- graphene_matrix_get_value (m, y, x) != 0.0f)
- {
- md->simple = FALSE;
- goto out;
- }
- }
-
-out:
- md->only_translation = (md->simple && md->scale_x == 1 && md->scale_y == 1);
+ switch (md->category)
+ {
+ case GSK_MATRIX_CATEGORY_IDENTITY:
+ md->scale_x = 1;
+ md->scale_y = 1;
+ break;
+
+ case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
+ md->translate_x = graphene_matrix_get_value (m, 3, 0);
+ md->translate_y = graphene_matrix_get_value (m, 3, 1);
+ md->scale_x = 1;
+ md->scale_y = 1;
+ break;
+
+ case GSK_MATRIX_CATEGORY_UNKNOWN:
+ case GSK_MATRIX_CATEGORY_ANY:
+ case GSK_MATRIX_CATEGORY_INVERTIBLE:
+ case GSK_MATRIX_CATEGORY_2D_AFFINE:
+ {
+ graphene_vec3_t col1;
+ graphene_vec3_t col2;
+
+ md->translate_x = graphene_matrix_get_value (m, 3, 0);
+ md->translate_y = graphene_matrix_get_value (m, 3, 1);
+
+ 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_x = graphene_vec3_length (&col1);
+ md->scale_y = graphene_vec3_length (&col2);
+ }
+ break;
+ default:
+ {}
+ }
}
-
void
ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst)
{
- const float scale = ops_get_scale (builder);
const MatrixStackEntry *head;
g_assert (builder->mv_stack != NULL);
@@ -127,34 +119,32 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
- if (head->metadata.only_translation)
+ switch (head->metadata.category)
{
+ case GSK_MATRIX_CATEGORY_IDENTITY:
*dst = *src;
- graphene_rect_offset (dst,
- head->metadata.translate_x,
- head->metadata.translate_y);
- }
- else
- {
+ break;
+
+ case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
+ *dst = *src;
+ dst->origin.x += head->metadata.translate_x;
+ dst->origin.y += head->metadata.translate_y;
+ break;
+
+ /* TODO: Handle scale */
+ case GSK_MATRIX_CATEGORY_2D_AFFINE:
+ case GSK_MATRIX_CATEGORY_UNKNOWN:
+ case GSK_MATRIX_CATEGORY_ANY:
+ case GSK_MATRIX_CATEGORY_INVERTIBLE:
+ default:
graphene_matrix_transform_bounds (builder->current_modelview,
src,
dst);
- }
-
- graphene_rect_offset (dst, builder->dx * scale, builder->dy * scale);
-}
-gboolean
-ops_modelview_is_simple (const RenderOpBuilder *builder)
-{
- 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);
+ }
- return head->metadata.simple;
+ dst->origin.x += builder->dx * head->metadata.scale_x;
+ dst->origin.y += builder->dy * head->metadata.scale_y;
}
void
@@ -303,8 +293,8 @@ ops_has_clip (RenderOpBuilder *self)
}
static void
-ops_set_modelview (RenderOpBuilder *builder,
- const graphene_matrix_t *modelview)
+ops_set_modelview_internal (RenderOpBuilder *builder,
+ const graphene_matrix_t *modelview)
{
RenderOp op;
@@ -338,9 +328,12 @@ ops_set_modelview (RenderOpBuilder *builder,
builder->current_program_state->modelview = *modelview;
}
+/* This sets the modelview to the given one without looking at the
+ * one that's currently set */
void
-ops_push_modelview (RenderOpBuilder *builder,
- const graphene_matrix_t *mv)
+ops_set_modelview (RenderOpBuilder *builder,
+ const graphene_matrix_t *mv,
+ GskMatrixCategory mv_category)
{
MatrixStackEntry *entry;
@@ -353,10 +346,64 @@ ops_push_modelview (RenderOpBuilder *builder,
entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
entry->matrix = *mv;
+ entry->metadata.category = mv_category;
+
+ entry->metadata.dx_before = builder->dx;
+ entry->metadata.dy_before = builder->dy;
+ extract_matrix_metadata (mv, &entry->metadata);
+
+ builder->dx = 0;
+ builder->dy = 0;
+ builder->current_modelview = &entry->matrix;
+ ops_set_modelview_internal (builder, &entry->matrix);
+}
+
+/* This sets the given modelview to the one we get when multiplying
+ * the given modelview with the current one. */
+void
+ops_push_modelview (RenderOpBuilder *builder,
+ const graphene_matrix_t *mv,
+ GskMatrixCategory mv_category)
+{
+ float scale = ops_get_scale (builder);
+ MatrixStackEntry *entry;
+
+ 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);
+
+ if (G_LIKELY (builder->mv_stack->len >= 2))
+ {
+ const MatrixStackEntry *cur;
+
+ cur = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 2);
+ /* Multiply given matrix with current modelview */
+
+ graphene_matrix_multiply (mv, &cur->matrix, &entry->matrix);
+ graphene_matrix_translate (&entry->matrix,
+ &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
+
+ entry->metadata.category = MIN (mv_category, cur->metadata.category);
+ }
+ else
+ {
+ entry->matrix = *mv;
+ entry->metadata.category = mv_category;
+ }
+
+ entry->metadata.dx_before = builder->dx;
+ entry->metadata.dy_before = builder->dy;
+
extract_matrix_metadata (mv, &entry->metadata);
+ builder->dx = 0;
+ builder->dy = 0;
builder->current_modelview = &entry->matrix;
- ops_set_modelview (builder, mv);
+ ops_set_modelview_internal (builder, &entry->matrix);
}
void
@@ -368,6 +415,10 @@ ops_pop_modelview (RenderOpBuilder *builder)
g_assert (builder->mv_stack);
g_assert (builder->mv_stack->len >= 1);
+ head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
+ builder->dx = head->metadata.dx_before;
+ builder->dy = head->metadata.dy_before;
+
builder->mv_stack->len --;
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
m = &head->matrix;
@@ -375,7 +426,7 @@ ops_pop_modelview (RenderOpBuilder *builder)
if (builder->mv_stack->len >= 1)
{
builder->current_modelview = m;
- ops_set_modelview (builder, m);
+ ops_set_modelview_internal (builder, m);
}
else
{
@@ -684,6 +735,9 @@ ops_draw (RenderOpBuilder *builder,
builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
}
+/* The offset is only valid for the current modelview.
+ * Setting a new modelview will add the offset to that matrix
+ * and reset the internal offset to 0. */
void
ops_offset (RenderOpBuilder *builder,
float x,
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index 67c50641e1..e80d688259 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -8,6 +8,7 @@
#include "gskgldriverprivate.h"
#include "gskroundedrectprivate.h"
#include "gskglrendererprivate.h"
+#include "gskrendernodeprivate.h"
#define GL_N_VERTICES 6
#define GL_N_PROGRAMS 11
@@ -21,8 +22,10 @@ typedef struct
float scale_x;
float scale_y;
- guint simple : 1;
- guint only_translation : 1;
+ float dx_before;
+ float dy_before;
+
+ GskMatrixCategory category;
} OpsMatrixMetadata;
typedef struct
@@ -277,9 +280,12 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
void ops_finish (RenderOpBuilder *builder);
void ops_push_modelview (RenderOpBuilder *builder,
- const graphene_matrix_t *mv);
+ const graphene_matrix_t *mv,
+ GskMatrixCategory mv_category);
+void ops_set_modelview (RenderOpBuilder *builder,
+ const graphene_matrix_t *mv,
+ GskMatrixCategory mv_category);
void ops_pop_modelview (RenderOpBuilder *builder);
-gboolean ops_modelview_is_simple (const RenderOpBuilder *builder);
float ops_get_scale (const RenderOpBuilder *builder);
void ops_set_program (RenderOpBuilder *builder,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]