[PATCH] Allow controlling the user of GL_ARB_texture_rectangle



cogl/cogl.h.in: Add cogl_texture_new_{with_size,from_data,from_file}_and_options()
  These functions allow passing in a set of CoglTextureOptions flags.
  Flags replace the auto_mipmap option and additionally control whether
  GL_ARB_texture_rectangle is used at all, and is used in preference
  to NPOT_textures.

cogl/gl/cogle-texture.c cogl/gles/cogle-texture.c: Implement the
  _and_options() variants of the cogl_texture constructors.

glx/clutter-glx-texture-pixmap.c: By default enable GL_ARB_texture_rectangle
  for our pixmap textures. Add environment variable
  CLUTTER_PIXMAP_TEXTURE_RECTANGLE=[force,disable] to control.
---
 clutter/cogl/cogl.h.in                   |   87 ++++++++++++++++++++++++++++++
 clutter/cogl/gl/cogl-texture.c           |   64 +++++++++++++++++++---
 clutter/cogl/gles/cogl-texture.c         |   45 ++++++++++++++-
 clutter/glx/clutter-glx-texture-pixmap.c |   59 ++++++++++++++++++---
 4 files changed, 236 insertions(+), 19 deletions(-)

diff --git a/clutter/cogl/cogl.h.in b/clutter/cogl/cogl.h.in
index 814ca33..ab3d482 100644
--- a/clutter/cogl/cogl.h.in
+++ b/clutter/cogl/cogl.h.in
@@ -197,6 +197,24 @@ typedef enum
 } CoglBufferTarget;
 
 /**
+ * CoglTextureOptions:
+ * @COGL_TEXTURE_ALLOW_RECTANGLE: Use GL_ARB_texture_rectangle if
+ *   it's available and GL_ARB_texture_non_power_of_two isn't.
+ * @COGL_TEXTURE_FORCE_RECTANGLE:Use  GL_ARB_texture_rectangle
+ *   even if GL_ARB_texture_non_power_of_two is available.
+ * @COGL_TEXTURE_AUTO_MIPMAP: enable generation of mipmap pyramid
+ *   from the base level image whenever it is updated.
+ *
+ */
+typedef enum
+{
+  COGL_TEXTURE_ALLOW_RECTANGLE      = (1 << 1),
+  COGL_TEXTURE_FORCE_RECTANGLE      = (1 << 2),
+  COGL_TEXTURE_AUTO_MIPMAP          = (1 << 3)
+
+} CoglTextureOptions;
+
+/**
  * CoglTextureVertex:
  * @x: Model x-coordinate
  * @y: Model y-coordinate
@@ -654,6 +672,27 @@ CoglHandle      cogl_texture_new_with_size    (guint           width,
                                                CoglPixelFormat internal_format);
 
 /**
+ * cogl_texture_new_with_size_and_options:
+ * @width: width of texture in pixels.
+ * @height: height of texture in pixels.
+ * @max_waste: maximum extra horizontal and|or vertical margin pixels to make
+ * texture fit GPU limitations.
+ * @options: a set of bit flags that affect how the texture is created
+ * @internal_format: the #CoglPixelFormat to use for the GPU storage of the
+ * texture.
+ *
+ * Create a new texture with specified dimensions, options, and pixel format.
+ *
+ * Returns: a #CoglHandle to the newly created texture or COGL_INVALID_HANDLE
+ * if texture creation failed.
+ */
+CoglHandle      cogl_texture_new_with_size_and_options (guint              width,
+							guint              height,
+							gint               max_waste,
+							CoglTextureOptions options,
+							CoglPixelFormat    internal_format);
+
+/**
  * cogl_texture_new_from_file:
  * @filename: the file to load
  * @max_waste: maximum extra horizontal and|or vertical margin pixels to make
@@ -676,6 +715,27 @@ CoglHandle      cogl_texture_new_from_file    (const gchar    *filename,
                                                GError        **error);
 
 /**
+ * cogl_texture_new_from_file_and_options:
+ * @filename: the file to load
+ * @max_waste: maximum extra horizontal and|or vertical margin pixels to make
+ * texture fit GPU limitations.
+ * @options: a set of bit flags that affect how the texture is created
+ * @internal_format: the #CoglPixelFormat to use for the GPU storage of the
+ * texture.
+ * @error: a #GError or NULL.
+ *
+ * Load an image file from disk with specified options.
+ *
+ * Returns: a #CoglHandle to the newly created texture or COGL_INVALID_HANDLE
+ * if creating the texture failed.
+ */
+CoglHandle      cogl_texture_new_from_file_and_options    (const gchar        *filename,
+							   gint               max_waste,
+							   CoglTextureOptions options,
+							   CoglPixelFormat    internal_format,
+							   GError           **error);
+
+/**
  * cogl_texture_new_from_data:
  * @width: width of texture in pixels.
  * @height: height of texture in pixels.
@@ -704,6 +764,33 @@ CoglHandle      cogl_texture_new_from_data    (guint            width,
                                                const guchar    *data);
 
 /**
+ * cogl_texture_new_from_data_and_options:
+ * @width: width of texture in pixels.
+ * @height: height of texture in pixels.
+ * @max_waste: maximum extra horizontal and|or vertical margin pixels to make
+ * @options: a set of bit flags that affect how the texture is created.
+ * @format: the #CoglPixelFormat the buffer is stored in in RAM
+ * @internal_format: the #CoglPixelFormat that will be used for storing the
+ * buffer on the GPU.
+ * @rowstride: the memory offset in bytes between the starts of scanlines in
+ * @data.
+ * @data: pointer the memory region where the source buffer resides.
+ *
+ * Create a new cogl texture based on data residing in memory with specified options
+ *
+ * Returns: a #CoglHandle to the newly created texture or COGL_INVALID_HANDLE
+ * if creating the texture failed.
+ */
+CoglHandle      cogl_texture_new_from_data_and_options    (guint              width,
+							   guint              height,
+							   gint               max_waste,
+							   CoglTextureOptions options,
+							   CoglPixelFormat    format,
+							   CoglPixelFormat    internal_format,
+							   guint              rowstride,
+							   const guchar      *data);
+
+/**
  * cogl_texture_new_from_foreign:
  * @gl_handle: opengl target type of foreign texture
  * @gl_target: opengl handle of foreign texture.
diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c
index 7cae747..f5b37a2 100644
--- a/clutter/cogl/gl/cogl-texture.c
+++ b/clutter/cogl/gl/cogl-texture.c
@@ -788,7 +788,8 @@ _cogl_texture_size_supported (GLenum gl_target,
 }
 
 static gboolean
-_cogl_texture_slices_create (CoglTexture *tex)
+_cogl_texture_slices_create (CoglTexture       *tex,
+			     CoglTextureOptions options)
 {  
   gint              bpp;
   gint              max_width;
@@ -807,15 +808,20 @@ _cogl_texture_slices_create (CoglTexture *tex)
   bpp = _cogl_get_format_bpp (tex->bitmap.format);
   
   /* Initialize size of largest slice according to supported features*/
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
+  if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
+      ((options & COGL_TEXTURE_FORCE_RECTANGLE) == 0 ||
+       !cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE)))
     {
+      g_printerr("NPOT!\n");
       max_width = tex->bitmap.width;
       max_height = tex->bitmap.height;
       tex->gl_target  = GL_TEXTURE_2D;
       slices_for_size = _cogl_rect_slices_for_size;
     }
-  else if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
+  else if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE) &&
+           ((options & (COGL_TEXTURE_ALLOW_RECTANGLE | COGL_TEXTURE_FORCE_RECTANGLE)) != 0))
     {
+      g_printerr("RECTANGLE!\n");
       max_width = tex->bitmap.width;
       max_height = tex->bitmap.height;
       tex->gl_target = GL_TEXTURE_RECTANGLE_ARB;
@@ -823,6 +829,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
     }
   else
     {
+      g_printerr("SLICED!\n");
       max_width = cogl_util_next_p2 (tex->bitmap.width);
       max_height = cogl_util_next_p2 (tex->bitmap.height);
       tex->gl_target = GL_TEXTURE_2D;
@@ -1208,6 +1215,18 @@ cogl_texture_new_with_size (guint           width,
                             gboolean        auto_mipmap,
 			    CoglPixelFormat internal_format)
 {
+  return cogl_texture_new_with_size_and_options (width, height, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 internal_format);
+}
+
+CoglHandle
+cogl_texture_new_with_size_and_options (guint              width,
+					guint              height,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    internal_format)
+{
   CoglTexture *tex;
   gint         bpp;
   gint         rowstride;
@@ -1227,7 +1246,7 @@ cogl_texture_new_with_size (guint           width,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
 
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
   
   tex->bitmap.width = width;
   tex->bitmap.height = height;
@@ -1252,7 +1271,7 @@ cogl_texture_new_with_size (guint           width,
 			      &tex->gl_type);
   
   /* Create slices for the given format and size */
-  if (!_cogl_texture_slices_create (tex))
+  if (!_cogl_texture_slices_create (tex, options))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
@@ -1271,6 +1290,21 @@ cogl_texture_new_from_data (guint              width,
 			    guint              rowstride,
 			    const guchar      *data)
 {
+  return cogl_texture_new_from_data_and_options (width, height, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 format, internal_format, rowstride, data);
+}
+
+CoglHandle
+cogl_texture_new_from_data_and_options (guint              width,
+					guint              height,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    format,
+					CoglPixelFormat    internal_format,
+					guint              rowstride,
+					const guchar      *data)
+{
   CoglTexture *tex;
   gint         bpp;
   
@@ -1291,7 +1325,7 @@ cogl_texture_new_from_data (guint              width,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
 
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
   
   tex->bitmap.width = width;
   tex->bitmap.height = height;
@@ -1319,7 +1353,7 @@ cogl_texture_new_from_data (guint              width,
       return COGL_INVALID_HANDLE;
     }
   
-  if (!_cogl_texture_slices_create (tex))
+  if (!_cogl_texture_slices_create (tex, options))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
@@ -1343,6 +1377,18 @@ cogl_texture_new_from_file (const gchar     *filename,
 			    CoglPixelFormat  internal_format,
 			    GError         **error)
 {
+  return cogl_texture_new_from_file_and_options (filename, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 internal_format, error);
+}
+
+CoglHandle
+cogl_texture_new_from_file_and_options (const gchar       *filename,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    internal_format,
+					GError            **error)
+{
   CoglBitmap   bmp;
   CoglTexture *tex;
   
@@ -1368,7 +1414,7 @@ cogl_texture_new_from_file (const gchar     *filename,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
   
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
   
   tex->bitmap = bmp;
   tex->bitmap_owner = TRUE;
@@ -1395,7 +1441,7 @@ cogl_texture_new_from_file (const gchar     *filename,
       return COGL_INVALID_HANDLE;
     }
   
-  if (!_cogl_texture_slices_create (tex))
+  if (!_cogl_texture_slices_create (tex, options))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c
index 97cd258..bf0f004 100644
--- a/clutter/cogl/gles/cogl-texture.c
+++ b/clutter/cogl/gles/cogl-texture.c
@@ -1168,6 +1168,18 @@ cogl_texture_new_with_size (guint           width,
                             gboolean        auto_mipmap,
 			    CoglPixelFormat internal_format)
 {
+  return cogl_texture_new_with_size_and_options (width, height, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 internal_format);
+}
+
+CoglHandle
+cogl_texture_new_with_size_and_options (guint              width,
+					guint              height,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    internal_format)
+{
   CoglTexture *tex;
   gint         bpp;
   gint         rowstride;
@@ -1187,7 +1199,7 @@ cogl_texture_new_with_size (guint           width,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
   
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
   
   tex->bitmap.width = width;
   tex->bitmap.height = height;
@@ -1230,6 +1242,21 @@ cogl_texture_new_from_data (guint              width,
 			    guint              rowstride,
 			    const guchar      *data)
 {
+  return cogl_texture_new_from_data_and_options (width, height, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 format, internal_format, rowstride, data);
+}
+
+CoglHandle
+cogl_texture_new_from_data_and_options (guint              width,
+					guint              height,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    format,
+					CoglPixelFormat    internal_format,
+					guint              rowstride,
+					const guchar      *data)
+{
   CoglTexture *tex;
   gint         bpp;
   
@@ -1250,7 +1277,7 @@ cogl_texture_new_from_data (guint              width,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
   
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
 
   tex->bitmap.width = width;
   tex->bitmap.height = height;
@@ -1302,6 +1329,18 @@ cogl_texture_new_from_file (const gchar     *filename,
 			    CoglPixelFormat  internal_format,
 			    GError         **error)
 {
+  return cogl_texture_new_from_file_and_options (filename, max_waste,
+						 auto_mipmap ? COGL_TEXTURE_AUTO_MIPMAP : 0,
+						 internal_format, error);
+}
+
+CoglHandle
+cogl_texture_new_from_file_and_options (const gchar       *filename,
+					gint               max_waste,
+					CoglTextureOptions options,
+					CoglPixelFormat    internal_format,
+					GError            **error)
+{
   CoglBitmap   bmp;
   CoglTexture *tex;
   
@@ -1327,7 +1366,7 @@ cogl_texture_new_from_file (const gchar     *filename,
   COGL_HANDLE_DEBUG_NEW (texture, tex);
   
   tex->is_foreign = FALSE;
-  tex->auto_mipmap = auto_mipmap;
+  tex->auto_mipmap = (options & COGL_TEXTURE_AUTO_MIPMAP) != 0;
 
   tex->bitmap = bmp;
   tex->bitmap_owner = TRUE;  
diff --git a/clutter/glx/clutter-glx-texture-pixmap.c b/clutter/glx/clutter-glx-texture-pixmap.c
index 0083fbf..4a2f3fe 100644
--- a/clutter/glx/clutter-glx-texture-pixmap.c
+++ b/clutter/glx/clutter-glx-texture-pixmap.c
@@ -48,6 +48,8 @@
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "../x11/clutter-x11-texture-pixmap.h"
 #include "clutter-glx-texture-pixmap.h"
 #include "clutter-glx.h"
@@ -200,6 +202,36 @@ clutter_glx_texture_pixmap_notify (GObject *object, GParamSpec *pspec)
     }
 }
 
+static CoglTextureOptions
+get_texture_options (void)
+{
+  static gboolean initialized = FALSE;
+  static CoglTextureOptions options;
+
+  if (!initialized)
+    {
+      const char *env_string;
+
+      initialized = TRUE;
+
+      options = COGL_TEXTURE_ALLOW_RECTANGLE;
+
+      env_string = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE");
+      if (env_string)
+	{
+	  if (strcasecmp (env_string, "force") == 0)
+	    options |= COGL_TEXTURE_FORCE_RECTANGLE;
+	  else if (strcasecmp (env_string, "disable") == 0)
+	    options &= ~COGL_TEXTURE_ALLOW_RECTANGLE;
+	  else if (env_string[0])
+	    g_warning ("Unknown value for CLUTTER_PIXMAP_TEXTURE_RECTANGLE, "
+		       "should be 'force' or 'disable'");
+	}
+    }
+
+  return options;
+}
+
 static gboolean
 create_cogl_texture (ClutterTexture *texture,
 		     guint width,
@@ -207,10 +239,10 @@ create_cogl_texture (ClutterTexture *texture,
 {
   CoglHandle  handle;
 
-  handle 
-    = cogl_texture_new_with_size (width, height,
-                                  -1, FALSE,
-                                  COGL_PIXEL_FORMAT_RGBA_8888|COGL_BGR_BIT);
+  handle = cogl_texture_new_with_size_and_options (width, height,
+						   -1,
+						   get_texture_options(),
+						   COGL_PIXEL_FORMAT_RGBA_8888|COGL_BGR_BIT);
 
   if (handle)
     {
@@ -718,9 +750,22 @@ clutter_glx_texture_pixmap_using_extension (ClutterGLXTexturePixmap *texture)
 
   priv = CLUTTER_GLX_TEXTURE_PIXMAP (texture)->priv;
 
-  return (_have_tex_from_pixmap_ext
-	  && (clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT)
-	      || clutter_feature_available (COGL_FEATURE_TEXTURE_RECTANGLE)));
+  if (!_have_tex_from_pixmap_ext)
+    return FALSE;
+
+  /* EXT_texture_from_pixmap is only useful if we have the
+   * ARGB_texture_non_power_of_two or ARB_texture_rectangle
+   */
+  if (clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT))
+    return TRUE;
+
+  if (clutter_feature_available (COGL_FEATURE_TEXTURE_RECTANGLE))
+    {
+      CoglTextureOptions options = get_texture_options();
+      return (options & (COGL_TEXTURE_ALLOW_RECTANGLE | COGL_TEXTURE_FORCE_RECTANGLE)) != 0;
+    }
+
+  return FALSE;
 }
 
 /**
-- 
1.6.0.3


--=-1gOaMbTF0IoDctbcw5Ip
Content-Disposition: attachment; filename*0=0002-Use-ARB_texture_rectangle-for-pixmap-shape-rectangle.pat; filename*1=ch
Content-Type: text/x-patch; name="0002-Use-ARB_texture_rectangle-for-pixmap-shape-rectangle.patch"; charset="UTF-8"
Content-Transfer-Encoding: 7bit



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