[gtk+] gdkgl: Texture many quads at once for performance reasons



commit 37ad6e11477060c74c2818210583b6fa37b1b027
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sat Nov 22 09:47:35 2014 -0800

    gdkgl: Texture many quads at once for performance reasons
    
    This isn't fully performant yet. To be fully performant, we'd need to
    do everything in one giant buffer.

 gdk/gdkgl.c                |   83 +++++++++++++++++++++++++++++---------------
 gdk/gdkinternals.h         |    7 ++--
 gdk/x11/gdkglcontext-x11.c |   22 ++++++++---
 3 files changed, 75 insertions(+), 37 deletions(-)
---
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index d61c87d..78be223 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -205,9 +205,10 @@ use_texture_rect_program (GdkGLContextPaintData *paint_data)
 }
 
 void
-gdk_gl_texture_quad (GdkGLContext *paint_context,
-                     guint texture_target,
-                     GdkTexturedQuad *quad)
+gdk_gl_texture_quads (GdkGLContext *paint_context,
+                      guint texture_target,
+                      int n_quads,
+                      GdkTexturedQuad *quads)
 {
   GdkGLContextPaintData *paint_data  = gdk_gl_context_get_paint_data (paint_context);
   GdkGLContextProgram *program;
@@ -215,18 +216,7 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
   int window_scale = gdk_window_get_scale_factor (window);
   float w = gdk_window_get_width (window) * window_scale;
   float h = gdk_window_get_height (window) * window_scale;
-  float vertex_buffer_data[] = {
-    (quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1,
-    (quad->x2 * 2) / w - 1, (quad->y2 * 2) / h - 1,
-    (quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1,
-    (quad->x1 * 2) / w - 1, (quad->y1 * 2) / h - 1,
-  };
-  float uv_buffer_data[] = {
-    quad->u2, quad->v1,
-    quad->u2, quad->v2,
-    quad->u1, quad->v2,
-    quad->u1, quad->v1,
-  };
+  int i;
 
   bind_vao (paint_data);
 
@@ -247,14 +237,37 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
   glUniform1i(program->map_location, 0); /* Use texture unit 0 */
 
   glEnableVertexAttribArray (0);
+  glEnableVertexAttribArray (1);
   glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
-  glBufferData (GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STREAM_DRAW);
   glVertexAttribPointer (program->position_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
-  glEnableVertexAttribArray (1);
   glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_uv_buffer);
-  glBufferData (GL_ARRAY_BUFFER, sizeof(uv_buffer_data), uv_buffer_data, GL_STREAM_DRAW);
   glVertexAttribPointer (program->uv_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
-  glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+
+  for (i = 0; i < n_quads; i++)
+    {
+      GdkTexturedQuad *quad = &quads[i];
+      float vertex_buffer_data[] = {
+        (quad->x2 * 2) / w - 1, (quad->y1 * 2) / h - 1,
+        (quad->x2 * 2) / w - 1, (quad->y2 * 2) / h - 1,
+        (quad->x1 * 2) / w - 1, (quad->y2 * 2) / h - 1,
+        (quad->x1 * 2) / w - 1, (quad->y1 * 2) / h - 1,
+      };
+      float uv_buffer_data[] = {
+        quad->u2, quad->v1,
+        quad->u2, quad->v2,
+        quad->u1, quad->v2,
+        quad->u1, quad->v1,
+      };
+
+      glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
+      glBufferData (GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STREAM_DRAW);
+
+      glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_uv_buffer);
+      glBufferData (GL_ARRAY_BUFFER, sizeof(uv_buffer_data), uv_buffer_data, GL_STREAM_DRAW);
+
+      glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+    }
+
   glDisableVertexAttribArray (0);
   glDisableVertexAttribArray (1);
 }
@@ -460,7 +473,9 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
       int unscaled_window_height;
       GLint texture_width;
       GLint texture_height;
-      int i;
+      int i, n_rects;
+      GdkTexturedQuad *quads;
+      cairo_rectangle_int_t clip_rect;
 
       /* Translate to impl coords */
       cairo_region_translate (clip_region, dx, dy);
@@ -506,9 +521,16 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
 
 #define FLIP_Y(_y) (unscaled_window_height - (_y))
 
-      for (i = 0; i < cairo_region_num_rectangles (clip_region); i++)
+      cairo_region_get_extents (clip_region, &clip_rect);
+
+      glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height),
+                 clip_rect.width, clip_rect.height);
+
+      n_rects = cairo_region_num_rectangles (clip_region);
+      quads = g_new (GdkTexturedQuad, n_rects);
+      for (i = 0; i < n_rects; i++)
         {
-          cairo_rectangle_int_t clip_rect, dest;
+          cairo_rectangle_int_t dest;
 
           cairo_region_get_rectangle (clip_region, i, &clip_rect);
 
@@ -517,9 +539,6 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
           clip_rect.width *= window_scale;
           clip_rect.height *= window_scale;
 
-          glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height),
-                     clip_rect.width, clip_rect.height);
-
           dest.x = dx * window_scale;
           dest.y = dy * window_scale;
           dest.width = width * window_scale / buffer_scale;
@@ -536,7 +555,7 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
                 (clipped_src_x + dest.width) / (float)texture_width, clipped_src_y / (float)texture_height,
               };
 
-              gdk_gl_texture_quad (paint_context, GL_TEXTURE_2D, &quad);
+              quads[i] = quad;
 
               if (impl_window->current_paint.flushed_region)
                 {
@@ -555,11 +574,13 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
             }
         }
 
+      gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_rects, quads);
+      g_free (quads);
+
       if (alpha_size != 0)
         glDisable (GL_BLEND);
 
       glDisable (GL_TEXTURE_2D);
-      glDisable (GL_SCISSOR_TEST);
 
 #undef FLIP_Y
 
@@ -636,6 +657,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
   float umax, vmax;
   gboolean use_texture_rectangle;
   guint target;
+  GdkTexturedQuad *quads;
 
   paint_context = gdk_gl_context_get_current ();
   if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_SURFACE) == 0 &&
@@ -673,6 +695,8 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
   glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
   n_rects = cairo_region_num_rectangles (region);
+  quads = g_new (GdkTexturedQuad, n_rects);
+
   for (i = 0; i < n_rects; i++)
     {
       cairo_region_get_rectangle (region, i, &rect);
@@ -718,10 +742,13 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
           umax, vmax,
         };
 
-        gdk_gl_texture_quad (paint_context, target, &quad);
+        quads[i] = quad;
       }
     }
 
+  gdk_gl_texture_quads (paint_context, target, n_rects, quads);
+  g_free (quads);
+
   glDisable (GL_SCISSOR_TEST);
   glDisable (target);
   glDeleteTextures (1, &texture_id);
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index d945a19..67a58da 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -356,9 +356,10 @@ typedef struct {
   float u1, v1, u2, v2;
 } GdkTexturedQuad;
 
-void           gdk_gl_texture_quad               (GdkGLContext *paint_context,
-                                                  guint texture_target,
-                                                  GdkTexturedQuad *quad);
+void           gdk_gl_texture_quads               (GdkGLContext *paint_context,
+                                                   guint texture_target,
+                                                   int n_quads,
+                                                   GdkTexturedQuad *quads);
 
 void            gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface,
                                                   GdkWindow       *window);
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 171ad05..566473a 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -431,6 +431,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
   guint target;
   double sx, sy;
   float uscale, vscale;
+  GdkTexturedQuad *quads;
 
   if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
     return FALSE;
@@ -473,22 +474,25 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
   glEnable (GL_SCISSOR_TEST);
 
   n_rects = cairo_region_num_rectangles (region);
+  quads = g_new (GdkTexturedQuad, n_rects);
+
+#define FLIP_Y(_y) (window_height - (_y))
+
+  cairo_region_get_extents (region, &rect);
+  glScissor (rect.x * window_scale, FLIP_Y(rect.y) * window_scale,
+             (rect.x + rect.width) * window_scale, FLIP_Y (rect.y + rect.height) * window_scale);
+
   for (i = 0; i < n_rects; i++)
     {
       int src_x, src_y, src_height, src_width;
 
       cairo_region_get_rectangle (region, i, &rect);
 
-      glScissor (rect.x * window_scale, (window_height - rect.y - rect.height) * window_scale,
-                rect.width * window_scale, rect.height * window_scale);
-
       src_x = rect.x * sx + device_x_offset;
       src_y = rect.y * sy + device_y_offset;
       src_width = rect.width * sx;
       src_height = rect.height * sy;
 
-#define FLIP_Y(_y) (window_height - (_y))
-
       if (use_texture_rectangle)
         {
           uscale = 1.0;
@@ -507,12 +511,18 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
           uscale * src_x, vscale * src_y,
           uscale * (src_x + src_width), vscale * (src_y + src_height),
         };
-        gdk_gl_texture_quad (paint_context, target, &quad);
+
+        quads[i] = quad;
       }
     }
 
+#undef FLIP_Y
+
   glDisable (GL_SCISSOR_TEST);
 
+  gdk_gl_texture_quads (paint_context, target, n_rects, quads);
+  g_free (quads);
+
   glXReleaseTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
                         GLX_FRONT_LEFT_EXT);
 


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