[gtk/wip/baedert/transforms6: 7/31] gl renderer: Render non-trivial transforms to a texture
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/baedert/transforms6: 7/31] gl renderer: Render non-trivial transforms to a texture
- Date: Thu, 29 Nov 2018 08:08:59 +0000 (UTC)
commit 5907ff694fc7402982261922b1b8693efcfa3c8f
Author: Timm Bäder <mail baedert org>
Date: Thu Nov 29 08:09:02 2018 +0100
gl renderer: Render non-trivial transforms to a texture
This way we can e.g. render rotated clips, borders, etc.
gsk/gl/gskglrenderer.c | 63 +++++++++++++++++++++++++++++++++++++++++-
gsk/gl/gskglrenderops.c | 13 +++++++++
gsk/gl/gskglrenderopsprivate.h | 1 +
3 files changed, 76 insertions(+), 1 deletion(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index a75f8b3823..c92b71b0f2 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -219,6 +219,31 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
MAX (self->corner[2].height, self->corner[3].height)) * 2);
}
+static inline gboolean
+node_supports_transform (GskRenderNode *node)
+{
+ /* Some nodes can't handle non-trivial transforms without being
+ * rendered to a texture (e.g. rotated clips, etc.). Some however
+ * work just fine, mostly because they already draw their child
+ * to a texture and just render the texture manipulated in some
+ * way, think opacity or color matrix. */
+ const guint node_type = gsk_render_node_get_node_type (node);
+
+ switch (node_type)
+ {
+ case GSK_COLOR_NODE:
+ case GSK_OPACITY_NODE:
+ case GSK_COLOR_MATRIX_NODE:
+ case GSK_TEXTURE_NODE:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+
static void gsk_gl_renderer_setup_render_mode (GskGLRenderer *self);
static void add_offscreen_ops (GskGLRenderer *self,
RenderOpBuilder *builder,
@@ -736,7 +761,43 @@ render_transform_node (GskGLRenderer *self,
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
ops_push_modelview (builder, &transformed_mv);
- gsk_gl_renderer_add_render_ops (self, child, builder);
+ if (ops_modelview_is_simple (builder) ||
+ node_supports_transform (child))
+ {
+ gsk_gl_renderer_add_render_ops (self, child, builder);
+ }
+ else
+ {
+ const float min_x = builder->dx + child->bounds.origin.x;
+ const float min_y = builder->dy + child->bounds.origin.y;
+ const float max_x = min_x + child->bounds.size.width;
+ const float max_y = min_y + child->bounds.size.height;
+ const GskQuadVertex 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 }, },
+ };
+ int texture_id;
+ gboolean is_offscreen;
+ /* 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,
+ min_x, max_x, min_y, max_y,
+ child,
+ &texture_id, &is_offscreen,
+ FALSE, TRUE);
+ ops_set_texture (builder, texture_id);
+ ops_set_program (builder, &self->blit_program);
+ ops_draw (builder, vertex_data);
+ }
ops_pop_modelview (builder);
}
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
index 1ac8f8866e..85026d8e63 100644
--- a/gsk/gl/gskglrenderops.c
+++ b/gsk/gl/gskglrenderops.c
@@ -116,6 +116,19 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
graphene_rect_offset (dst, builder->dx, builder->dy);
}
+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;
+}
+
void
ops_set_program (RenderOpBuilder *builder,
const Program *program)
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index 7b0b1f824f..97ce3a28b1 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -263,6 +263,7 @@ void ops_finish (RenderOpBuilder *builder);
void ops_push_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *mv);
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]