[gtk+] GdkGL: Fix up GL_ARB_texture_rectangle support



commit 5f9e6ec2dc2e5ae4442d5cdb64684cd4a51d20d4
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Nov 6 11:31:01 2014 +0100

    GdkGL: Fix up GL_ARB_texture_rectangle support
    
    This broke when gdk_gl_texture_quad moved to shaders. We need
    a specialized shader for the rectangle case.

 gdk/gdkgl.c                |   80 ++++++++++++++++++++++++++++++++++++++------
 gdk/gdkglcontextprivate.h  |    5 +++
 gdk/gdkinternals.h         |    1 +
 gdk/x11/gdkglcontext-x11.c |   47 +++++++++++++++----------
 4 files changed, 103 insertions(+), 30 deletions(-)
---
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index 44d205e..6d0e8f4 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -140,7 +140,10 @@ bind_vao (GdkGLContextPaintData *paint_data)
 }
 
 static void
-use_texture_program (GdkGLContextPaintData *paint_data)
+use_texture_2d_program (GdkGLContextPaintData *paint_data,
+                        guint *position_location,
+                        guint *uv_location,
+                        guint *map_location)
 {
   const char *vertex_shader_code =
     "#version 120\n"
@@ -165,6 +168,7 @@ use_texture_program (GdkGLContextPaintData *paint_data)
       paint_data->texture_quad_program = make_program (vertex_shader_code, fragment_shader_code);
       paint_data->texture_quad_program_position_location = glGetAttribLocation 
(paint_data->texture_quad_program, "position");
       paint_data->texture_quad_program_uv_location = glGetAttribLocation (paint_data->texture_quad_program, 
"uv");
+      paint_data->texture_quad_program_map_location = glGetUniformLocation 
(paint_data->texture_quad_program, "map");
     }
 
   if (paint_data->current_program != paint_data->texture_quad_program)
@@ -172,10 +176,59 @@ use_texture_program (GdkGLContextPaintData *paint_data)
       glUseProgram (paint_data->texture_quad_program);
       paint_data->current_program = paint_data->texture_quad_program;
     }
+
+  *position_location = paint_data->texture_quad_program_position_location;
+  *uv_location = paint_data->texture_quad_program_uv_location;
+  *map_location = paint_data->texture_quad_program_map_location;
 }
 
+static void
+use_texture_rect_program (GdkGLContextPaintData *paint_data,
+                          guint *position_location,
+                          guint *uv_location,
+                          guint *map_location)
+{
+  const char *vertex_shader_code =
+    "#version 120\n"
+    "uniform sampler2DRect map;"
+    "attribute vec2 position;\n"
+    "attribute vec2 uv;\n"
+    "varying vec2 vUv;\n"
+    "void main() {\n"
+    "  gl_Position = vec4(position, 0, 1);\n"
+    "  vUv = uv;\n"
+    "}\n";
+  const char *fragment_shader_code =
+    "#version 120\n"
+    "varying vec2 vUv;\n"
+    "uniform sampler2DRect map;\n"
+    "void main() {\n"
+    "  gl_FragColor = texture2DRect (map, vUv);\n"
+    "}\n";
+
+  if (paint_data->texture_quad_rect_program == 0)
+    {
+      paint_data->texture_quad_rect_program = make_program (vertex_shader_code, fragment_shader_code);
+      paint_data->texture_quad_rect_program_position_location = glGetAttribLocation 
(paint_data->texture_quad_rect_program, "position");
+      paint_data->texture_quad_rect_program_uv_location = glGetAttribLocation 
(paint_data->texture_quad_rect_program, "uv");
+      paint_data->texture_quad_rect_program_map_location = glGetUniformLocation 
(paint_data->texture_quad_rect_program, "map");
+    }
+
+  if (paint_data->current_program != paint_data->texture_quad_rect_program)
+    {
+      glUseProgram (paint_data->texture_quad_rect_program);
+      paint_data->current_program = paint_data->texture_quad_rect_program;
+    }
+
+  *position_location = paint_data->texture_quad_rect_program_position_location;
+  *uv_location = paint_data->texture_quad_rect_program_uv_location;
+  *map_location = paint_data->texture_quad_rect_program_map_location;
+}
+
+
 void
 gdk_gl_texture_quad (GdkGLContext *paint_context,
+                     guint texture_target,
                      float x1, float y1,
                      float x2, float y2,
                      float u1, float v1,
@@ -197,6 +250,7 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
     u1, v2,
     u1, v1,
   };
+  guint position_location, uv_location, map_location;
 
   bind_vao (paint_data);
 
@@ -206,19 +260,22 @@ gdk_gl_texture_quad (GdkGLContext *paint_context,
   if (paint_data->tmp_uv_buffer == 0)
     glGenBuffers(1, &paint_data->tmp_uv_buffer);
 
-  use_texture_program (paint_data);
+  if (texture_target == GL_TEXTURE_RECTANGLE_ARB)
+    use_texture_rect_program (paint_data, &position_location, &uv_location, &map_location);
+  else
+    use_texture_2d_program (paint_data, &position_location, &uv_location, &map_location);
 
   glActiveTexture (GL_TEXTURE0);
+  glUniform1i(map_location, 0); /* Use texture unit 0 */
+
   glEnableVertexAttribArray (0);
   glBindBuffer (GL_ARRAY_BUFFER, paint_data->tmp_vertex_buffer);
   glBufferData (GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STREAM_DRAW);
-  glVertexAttribPointer (paint_data->texture_quad_program_position_location,
-                         2, GL_FLOAT, GL_FALSE, 0, NULL);
+  glVertexAttribPointer (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 (paint_data->texture_quad_program_uv_location,
-                         2, GL_FLOAT, GL_FALSE, 0, NULL);
+  glVertexAttribPointer (uv_location, 2, GL_FLOAT, GL_FALSE, 0, NULL);
   glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
   glDisableVertexAttribArray (0);
   glDisableVertexAttribArray (1);
@@ -497,6 +554,7 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
               int clipped_src_y = y + (height - dest.height - (dest.y - dy * window_scale));
 
               gdk_gl_texture_quad (paint_context,
+                                   GL_TEXTURE_2D,
                                    dest.x, FLIP_Y(dest.y),
                                    dest.x + dest.width, FLIP_Y(dest.y + dest.height),
                                    clipped_src_x / (float)texture_width, (clipped_src_y + dest.height) / 
(float)texture_height,
@@ -634,10 +692,10 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
   glBindTexture (target, texture_id);
   glEnable (target);
 
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
   n_rects = cairo_region_num_rectangles (region);
   for (i = 0; i < n_rects; i++)
@@ -677,7 +735,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
           vmax = 1.0;
         }
 
-      gdk_gl_texture_quad (paint_context,
+      gdk_gl_texture_quad (paint_context, target,
                            rect.x * window_scale, FLIP_Y(rect.y) * window_scale,
                            (rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale,
                            0, 0,
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index c738fa5..ec4ab33 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -65,6 +65,11 @@ typedef struct {
   guint texture_quad_program;
   guint texture_quad_program_position_location;
   guint texture_quad_program_uv_location;
+  guint texture_quad_program_map_location;
+  guint texture_quad_rect_program;
+  guint texture_quad_rect_program_position_location;
+  guint texture_quad_rect_program_uv_location;
+  guint texture_quad_rect_program_map_location;
 } GdkGLContextPaintData;
 
 GdkGLContextPaintData *gdk_gl_context_get_paint_data (GdkGLContext *context);
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 14141bd..6543f55 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -351,6 +351,7 @@ gboolean        _gdk_cairo_surface_extents       (cairo_surface_t *surface,
 void            gdk_gl_texture_from_surface      (cairo_surface_t *surface,
                                                   cairo_region_t  *region);
 void           gdk_gl_texture_quad               (GdkGLContext *paint_context,
+                                                  guint texture_target,
                                                   float x1, float y1,
                                                   float x2, float y2,
                                                   float u1, float v1,
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index a0258b9..fe1b18a 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -280,7 +280,7 @@ glx_pixmap_destroy (void *data)
 }
 
 static GdkGLXPixmap *
-glx_pixmap_get (cairo_surface_t *surface)
+glx_pixmap_get (cairo_surface_t *surface, guint texture_target)
 {
   Display *display = cairo_xlib_surface_get_display (surface);
   Screen *screen = cairo_xlib_surface_get_screen (surface);
@@ -324,12 +324,22 @@ glx_pixmap_get (cairo_surface_t *surface)
       glXGetFBConfigAttrib (display, fbconfigs[i],
                             GLX_BIND_TO_TEXTURE_TARGETS_EXT,
                             &value);
-      if ((value & (GLX_TEXTURE_RECTANGLE_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT)) == 0)
-        continue;
-      if ((value & GLX_TEXTURE_2D_BIT_EXT))
-        target = GLX_TEXTURE_2D_EXT;
+      if (texture_target == GL_TEXTURE_2D)
+        {
+          if (value & GLX_TEXTURE_2D_BIT_EXT)
+            target = GLX_TEXTURE_2D_EXT;
+          else
+            continue;
+        }
+      else if (texture_target == GL_TEXTURE_RECTANGLE_ARB)
+        {
+          if (value & GLX_TEXTURE_RECTANGLE_BIT_EXT)
+            target = GLX_TEXTURE_RECTANGLE_EXT;
+          else
+            continue;
+        }
       else
-        target = GLX_TEXTURE_RECTANGLE_EXT;
+        continue;
 
       if (!with_alpha)
         {
@@ -400,12 +410,16 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
   if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
     return FALSE;
 
-  glx_pixmap = glx_pixmap_get (surface);
+  use_texture_rectangle = gdk_gl_context_use_texture_rectangle (paint_context);
+  if (use_texture_rectangle)
+    target = GL_TEXTURE_RECTANGLE_ARB;
+  else
+    target = GL_TEXTURE_2D;
+
+  glx_pixmap = glx_pixmap_get (surface, target);
   if (glx_pixmap == NULL)
     return FALSE;
 
-  use_texture_rectangle = gdk_gl_context_use_texture_rectangle (paint_context);
-
   window = gdk_gl_context_get_window (paint_context)->impl_window;
   window_scale = gdk_window_get_scale_factor (window);
   window_height = gdk_window_get_height (window);
@@ -421,19 +435,14 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
   /* Ensure all the X stuff are synced before we read it back via texture-from-pixmap */
   glXWaitX();
 
-  if (use_texture_rectangle)
-    target = GL_TEXTURE_RECTANGLE_ARB;
-  else
-    target = GL_TEXTURE_2D;
-
   glGenTextures (1, &texture_id);
   glBindTexture (target, texture_id);
   glEnable (target);
 
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
   glXBindTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
                      GLX_FRONT_LEFT_EXT, NULL);
@@ -466,7 +475,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
           vscale = 1.0 / cairo_xlib_surface_get_height (surface);
         }
 
-      gdk_gl_texture_quad (paint_context,
+      gdk_gl_texture_quad (paint_context, target,
                            rect.x * window_scale, FLIP_Y(rect.y) * window_scale,
                            (rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale,
                            uscale * src_x, vscale * src_y,


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