[gtk+/wip/baedert/gl: 54/90] gl renderer: Don't draw texture nodes to a framebuffer



commit f65ba3fd54ba00ea53712eb3d72c6193a652ea55
Author: Timm Bäder <mail baedert org>
Date:   Fri Nov 24 10:43:17 2017 +0100

    gl renderer: Don't draw texture nodes to a framebuffer
    
    We don't need to create a texture from a texture node. We can simply use
    its texture instead and draw it however we want.

 gsk/gl/gskglrenderer.c |  112 ++++++++++++++++++++++++++++++++----------------
 1 files changed, 75 insertions(+), 37 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index d3b0273..b0673bf 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -42,8 +42,6 @@
                 g_assert (self->program_name.location_name != 0); \
               }G_STMT_END
 
-
-
 static void G_GNUC_UNUSED
 dump_framebuffer (const char *filename, int w, int h)
 {
@@ -77,13 +75,15 @@ font_has_color_glyphs (const PangoFont *font)
 }
 
 static void gsk_gl_renderer_setup_render_mode (GskGLRenderer   *self);
-static int  add_offscreen_ops                 (GskGLRenderer   *self,
+static void add_offscreen_ops                 (GskGLRenderer   *self,
                                                RenderOpBuilder *builder,
                                                float            min_x,
                                                float            max_x,
                                                float            min_y,
                                                float            max_y,
-                                               GskRenderNode   *child_node);
+                                               GskRenderNode   *child_node,
+                                               int             *texture_id,
+                                               gboolean        *is_offscreen);
 
 #ifdef G_ENABLE_DEBUG
 typedef struct
@@ -719,25 +719,36 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
     case GSK_OPACITY_NODE:
       {
         int texture_id;
+        gboolean is_offscreen;
         float prev_opacity;
-        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 }, },
-        };
 
-        texture_id = add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
-                                        gsk_opacity_node_get_child (node));
+        add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
+                           gsk_opacity_node_get_child (node),
+                           &texture_id, &is_offscreen);
 
         /* Now draw the texture with the node's opacity */
         ops_set_program (builder, &self->blit_program);
         prev_opacity = ops_set_opacity (builder, gsk_opacity_node_get_opacity (node));
         ops_set_texture (builder, texture_id);
-        ops_draw (builder, vertex_data);
+
+        if (is_offscreen)
+          {
+            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 }, },
+            };
+            ops_draw (builder, vertex_data);
+          }
+        else
+          {
+            ops_draw (builder, vertex_data);
+          }
         ops_set_opacity (builder, prev_opacity);
       }
     break;
@@ -911,23 +922,14 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
 
       }
     break;
-
     case GSK_COLOR_MATRIX_NODE:
       {
         int texture_id;
+        gboolean is_offscreen;
         RenderOp op;
-        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 }, },
-        };
-
-        texture_id = add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
-                                        gsk_color_matrix_node_get_child (node));
+        add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
+                           gsk_color_matrix_node_get_child (node),
+                           &texture_id, &is_offscreen);
 
         ops_set_program (builder, &self->color_matrix_program);
         op.op = OP_CHANGE_COLOR_MATRIX;
@@ -936,7 +938,26 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
         ops_add (builder, &op);
 
         ops_set_texture (builder, texture_id);
-        ops_draw (builder, vertex_data);
+
+        if (is_offscreen)
+          {
+            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 }, },
+            };
+
+            ops_draw (builder, vertex_data);
+          }
+        else
+          {
+            ops_draw (builder, vertex_data);
+          }
+
       }
     break;
 
@@ -994,16 +1015,17 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
     }
 }
 
-static int
+static void
 add_offscreen_ops (GskGLRenderer   *self,
                    RenderOpBuilder *builder,
                    float            min_x,
                    float            max_x,
                    float            min_y,
                    float            max_y,
-                   GskRenderNode   *child_node)
+                   GskRenderNode   *child_node,
+                   int             *texture_id,
+                   gboolean        *is_offscreen)
 {
-  int texture_id;
   int render_target;
   int prev_render_target;
   RenderOp op;
@@ -1013,11 +1035,27 @@ add_offscreen_ops (GskGLRenderer   *self,
   graphene_rect_t prev_viewport;
   graphene_matrix_t item_proj;
 
+  /* We need the child node as a texture. If it already is one, we don't need to draw
+   * it on a framebuffer of course. */
+  if (gsk_render_node_get_node_type (child_node) == GSK_TEXTURE_NODE)
+    {
+      GdkTexture *texture = gsk_texture_node_get_texture (child_node);
+      int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
+
+      get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
+
+      *texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
+                                                           texture,
+                                                           gl_min_filter,
+                                                           gl_mag_filter);
+      *is_offscreen = FALSE;
+      return;
+    }
 
-  texture_id = gsk_gl_driver_create_texture (self->gl_driver, max_x - min_x, max_y - min_y);
-  gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
-  gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
-  render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
+  *texture_id = gsk_gl_driver_create_texture (self->gl_driver, max_x - min_x, max_y - min_y);
+  gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
+  gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
+  render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
 
   graphene_matrix_init_ortho (&item_proj,
                               min_x, max_x,
@@ -1041,7 +1079,7 @@ add_offscreen_ops (GskGLRenderer   *self,
   ops_set_projection (builder, &prev_projection);
   ops_set_render_target (builder, prev_render_target);
 
-  return texture_id;
+  *is_offscreen = TRUE;
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]