[gtk+] opengl: Use GL_TEXTURE_2D rather than GL_TEXTURE_RECTANGLE_ARB when possible



commit f7b1ba09430f07a02c5c29b0eba59516bf92aa9a
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Oct 27 21:15:37 2014 +0100

    opengl: Use GL_TEXTURE_2D rather than GL_TEXTURE_RECTANGLE_ARB when possible
    
    This is more standard, and most driver support non-power-of-2 TEXTURE_2D
    these days. We fall back for ancient drivers.

 gdk/gdkgl.c                |   73 ++++++++++++++++++++++---------
 gdk/x11/gdkglcontext-x11.c |  105 +++++++++++++++++++++++++++++++++----------
 2 files changed, 132 insertions(+), 46 deletions(-)
---
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index 09ee79e..a4b290a 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -113,20 +113,15 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
       glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, source);
       glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                                     GL_RENDERBUFFER_EXT, source);
-      glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+      glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0);
     }
   else if (source_type == GL_TEXTURE)
     {
+      glBindTexture (GL_TEXTURE_2D, source);
+
       glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE,  &alpha_size);
 
-      glBindTexture (GL_TEXTURE_2D, source);
-      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);
-      glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                                 GL_TEXTURE_2D, source, 0);
-      glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+      glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0);
     }
   else
     {
@@ -234,9 +229,6 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
       /* Translate to impl coords */
       cairo_region_translate (clip_region, dx, dy);
 
-      glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &texture_width);
-      glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,  &texture_height);
-
       if (alpha_size != 0)
         {
           cairo_region_t *opaque_region, *blend_region;
@@ -260,6 +252,19 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
           cairo_region_destroy (opaque_region);
           cairo_region_destroy (blend_region);
         }
+
+      glBindTexture (GL_TEXTURE_2D, source);
+
+      glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &texture_width);
+      glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,  &texture_height);
+
+      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);
+      glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+                                 GL_TEXTURE_2D, source, 0);
+
       glEnable (GL_SCISSOR_TEST);
       glEnable (GL_TEXTURE_2D);
 
@@ -389,6 +394,9 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
   unsigned int texture_id;
   int window_scale;
   double sx, sy;
+  float umax, vmax;
+  gboolean use_texture_rectangle;
+  guint target;
 
   current = gdk_gl_context_get_current ();
   if (current &&
@@ -398,7 +406,9 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
 
   /* Software fallback */
 
-  window = gdk_gl_context_get_window (gdk_gl_context_get_current ());
+  use_texture_rectangle = gdk_gl_context_use_texture_rectangle (current);
+
+  window = gdk_gl_context_get_window (current);
   window_scale = gdk_window_get_scale_factor (window);
   window_height = gdk_window_get_height (window);
 
@@ -411,8 +421,18 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
                                    &device_x_offset, &device_y_offset);
 
   glGenTextures (1, &texture_id);
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_id);
-  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  if (use_texture_rectangle)
+    target = GL_TEXTURE_RECTANGLE_ARB;
+  else
+    target = GL_TEXTURE_2D;
+
+  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);
 
   n_rects = cairo_region_num_rectangles (region);
   for (i = 0; i < n_rects; i++)
@@ -433,7 +453,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
 
       glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
       glPixelStorei (GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride (image)/4);
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 4, e.width, e.height, 0, GL_BGRA, 
GL_UNSIGNED_INT_8_8_8_8_REV,
+      glTexImage2D (target, 0, 4, e.width, e.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                     cairo_image_surface_get_data (image));
       glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
 
@@ -441,21 +461,32 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
 
 #define FLIP_Y(_y) (window_height - (_y))
 
+      if (use_texture_rectangle)
+        {
+          umax = rect.width * sx;
+          vmax = rect.height * sy;
+        }
+      else
+        {
+          umax = 1.0;
+          vmax = 1.0;
+        }
+
       glBegin (GL_QUADS);
-      glTexCoord2f (0.0f * sx, rect.height * sy);
+      glTexCoord2f (0, vmax);
       glVertex2f (rect.x * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
 
-      glTexCoord2f (rect.width * sx, rect.height * sy);
+      glTexCoord2f (umax, vmax);
       glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
 
-      glTexCoord2f (rect.width * sx, 0.0f * sy);
+      glTexCoord2f (umax, 0);
       glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y) * window_scale);
 
-      glTexCoord2f (0.0f * sx, 0.0f * sy);
+      glTexCoord2f (0, 0);
       glVertex2f (rect.x * window_scale, FLIP_Y(rect.y) * window_scale);
       glEnd();
     }
 
-  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+  glDisable (target);
   glDeleteTextures (1, &texture_id);
 }
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 6162b10..accc8a5 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -288,41 +288,64 @@ glx_pixmap_get (cairo_surface_t *surface)
   XVisualInfo *visinfo;
   int i, value;
   gboolean y_inverted;
-  const int pixmap_attributes[] = {
-    GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
-    GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+  gboolean with_alpha;
+  guint target = 0;
+  guint format = 0;
+  int pixmap_attributes[] = {
+    GLX_TEXTURE_TARGET_EXT, 0,
+    GLX_TEXTURE_FORMAT_EXT, 0,
     None
   };
 
+  with_alpha = cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA;
+
   y_inverted = FALSE;
   fbconfigs = glXGetFBConfigs (display, XScreenNumberOfScreen (screen), &nfbconfigs);
   for (i = 0; i < nfbconfigs; i++)
     {
       visinfo = glXGetVisualFromFBConfig (display, fbconfigs[i]);
       if (!visinfo || visinfo->visualid != XVisualIDFromVisual (visual))
-       continue;
+        continue;
 
       glXGetFBConfigAttrib (display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
       if (!(value & GLX_PIXMAP_BIT))
-       continue;
-
-      glXGetFBConfigAttrib (display, fbconfigs[i],
-                           GLX_BIND_TO_TEXTURE_TARGETS_EXT,
-                           &value);
-      if ((value & GLX_TEXTURE_RECTANGLE_BIT_EXT))
-       continue;
+        continue;
 
       glXGetFBConfigAttrib (display, fbconfigs[i],
-                           GLX_BIND_TO_TEXTURE_RGBA_EXT,
-                           &value);
-      if (value == FALSE)
+                            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;
+      else
+        target = GLX_TEXTURE_RECTANGLE_EXT;
+
+      if (!with_alpha)
+        {
+          glXGetFBConfigAttrib (display, fbconfigs[i],
+                                GLX_BIND_TO_TEXTURE_RGB_EXT,
+                                &value);
+          if (!value)
+            continue;
+
+          format = GLX_TEXTURE_FORMAT_RGB_EXT;
+        }
+      else
+        {
+          glXGetFBConfigAttrib (display, fbconfigs[i],
+                                GLX_BIND_TO_TEXTURE_RGBA_EXT,
+                                &value);
+          if (!value)
+            continue;
+          format = GLX_TEXTURE_FORMAT_RGBA_EXT;
+        }
 
       glXGetFBConfigAttrib (display, fbconfigs[i],
-                           GLX_Y_INVERTED_EXT,
-                           &value);
+                            GLX_Y_INVERTED_EXT,
+                            &value);
       if (value == TRUE)
-       y_inverted = TRUE;
+        y_inverted = TRUE;
 
       break;
     }
@@ -330,6 +353,9 @@ glx_pixmap_get (cairo_surface_t *surface)
   if (i == nfbconfigs)
     return NULL;
 
+  pixmap_attributes[1] = target;
+  pixmap_attributes[3] = format;
+
   glx_pixmap = g_slice_new0 (GdkGLXPixmap);
   glx_pixmap->y_inverted = y_inverted;
   glx_pixmap->display = display;
@@ -345,6 +371,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
                                         cairo_surface_t *surface,
                                         cairo_region_t *region)
 {
+  GdkGLContext *current;
   GdkGLXPixmap *glx_pixmap;
   double device_x_offset, device_y_offset;
   cairo_rectangle_int_t rect;
@@ -353,7 +380,10 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
   int window_height;
   int window_scale;
   unsigned int texture_id;
+  gboolean use_texture_rectangle;
+  guint target;
   double sx, sy;
+  float uscale, vscale;
 
   if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
     return FALSE;
@@ -362,7 +392,11 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
   if (glx_pixmap == NULL)
     return FALSE;
 
-  window = gdk_gl_context_get_window (gdk_gl_context_get_current ())->impl_window;
+  current = gdk_gl_context_get_current ();
+
+  use_texture_rectangle = gdk_gl_context_use_texture_rectangle (current);
+
+  window = gdk_gl_context_get_window (current)->impl_window;
   window_scale = gdk_window_get_scale_factor (window);
   window_height = gdk_window_get_height (window);
 
@@ -377,9 +411,19 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *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 (GL_TEXTURE_RECTANGLE_ARB, texture_id);
-  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  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);
 
   glXBindTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
                      GLX_FRONT_LEFT_EXT, NULL);
@@ -401,17 +445,28 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
 
 #define FLIP_Y(_y) (window_height - (_y))
 
+      if (use_texture_rectangle)
+        {
+          uscale = 1.0;
+          vscale = 1.0;
+        }
+      else
+        {
+          uscale = 1.0 / cairo_xlib_surface_get_width (surface);
+          vscale = 1.0 / cairo_xlib_surface_get_height (surface);
+        }
+
       glBegin (GL_QUADS);
-      glTexCoord2f (src_x, src_y + src_height);
+      glTexCoord2f (uscale * src_x, vscale * (src_y + src_height));
       glVertex2f (rect.x * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
 
-      glTexCoord2f (src_x + src_width, src_y + src_height);
+      glTexCoord2f (uscale * (src_x + src_width), vscale * (src_y + src_height));
       glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
 
-      glTexCoord2f (src_x + src_width, src_y);
+      glTexCoord2f (uscale * (src_x + src_width), vscale * src_y);
       glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y) * window_scale);
 
-      glTexCoord2f (src_x, src_y);
+      glTexCoord2f (uscale * src_x, vscale * src_y);
       glVertex2f (rect.x * window_scale, FLIP_Y(rect.y) * window_scale);
       glEnd();
     }
@@ -419,7 +474,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
   glXReleaseTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
                         GLX_FRONT_LEFT_EXT);
 
-  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+  glDisable (target);
   glDeleteTextures (1, &texture_id);
 
   glx_pixmap_destroy(glx_pixmap);


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