On Wed, 2008-11-05 at 13:03 -0500, Owen Taylor wrote:
> On Wed, 2008-11-05 at 16:36 +0000, Matthew Allum wrote:
> > On Wed, 2008-11-05 at 10:22 -0500, Owen Taylor wrote:
>
> > > I see two basic routes I could take:
> > >
> > > 1) I could add support for ARB_texture_rectangle into cogl_texture.
> > > Presumably this would look like cogl_texture_new_rectangle()
> > > or something ... you'd have to explicitly ask to get a rectangular
> > > texture, since they do behave significantly different.
[...]
> [...]
> >
> > I think making it usage explicit and contained like this is really the
> > only way to go in we do bring back in support for ARB_texture_rectangle
> > without a lot of complexity and other pain elsewhere.
> >
> > Re devel branch - I dont see why this could not end up in the stable
> > branch of which we are already having to track pretty much with mutter.
>
> My initial expectation was that there would be significant code churn
> and API changes, but looking at it, the "remove texture_rectangle
> support" patch is a lot smaller than I expected and doesn't look to hard
> or intrusive to reintroduce.
>
> I'll do some more experimentation with that and see if it I can get it
> to work and see if it fixes some of the other issues people are having.
OK, here's a stab at this. The first two patches (one for clutter, one
for metacity-clutter) basically simply revert the removal of
ARB_texture_rectangle support from clutter.
However, that leaves two problems:
- texture_rectangle might unexpectedly be used in places that
clutter-0.8 code won't expect, breaking compatibility.
- for texture_from_pixmap, I want a way to actually force
texture_rectangle to be used, to deal with driver bugs.
(The current proprietary NVIDIA drivers are buggy this way;
and I think also older Intel drivers.)
So, the second two patches add:
cogl_texture_new_with_size_and_options()
cogl_texture_new_from_data_and_options()
cogl_texture_new_from_file_and_options() // for completeness
Where auto_mipmap is replaced with a flags field. (If breaking cogl
compat, you'd just want to change existing functions.) texture_rectangle
is not used by default, but you can pass:
COGL_TEXTURE_ALLOW_RECTANGLE: allow it to be used
COGL_TEXTURE_FORCE_RECTANGLE: use in preference to NPOT textures
And ClutterGLXPixmapTexture supports an environment variable
CLUTTER_PIXMAP_TEXTURE_RECTANGLE=[force|disable].
The default is to allow - there's a good argument that it should default
to 'force' instead, considering the widespread presence of such buggy
drivers.
- Owen
>From 5b97816731c039a7cf6fbdb23f0d6716554bdbc0 Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <[EMAIL PROTECTED]>
Date: Wed, 5 Nov 2008 16:17:57 -0500
Subject: [PATCH] Add back support for GL_ARB_texture_rectangle
Revert most of:
2008-06-06 Matthew Allum <[EMAIL PROTECTED]>
Bug #948 - Remove texture rectangle support
GL_EXT_texture_for_pixmap only works with GL_ARGB_texture_rectangle on
many systems, either because of HW limitations (General NPOT textures
are not supported on older ATI cards), or because of driver bugs.
Changes to clutter_texture_new_from_actor() are not reverted; setting
disable-slicing there is pretty much orthogonal to texture_rectangle
and works fine with the rest of the revert.
---
clutter/clutter-feature.c | 3 +
clutter/clutter-feature.h | 1 +
clutter/cogl/gl/cogl-texture.c | 69 ++++++++++++++++++++++++++----
clutter/cogl/gl/cogl.c | 15 ++++++-
clutter/glx/clutter-glx-texture-pixmap.c | 13 +++---
5 files changed, 85 insertions(+), 16 deletions(-)
diff --git a/clutter/clutter-feature.c b/clutter/clutter-feature.c
index 54ac41e..10edfe9 100644
--- a/clutter/clutter-feature.c
+++ b/clutter/clutter-feature.c
@@ -58,6 +58,9 @@ _clutter_features_from_cogl (guint cogl_flags)
{
ClutterFeatureFlags clutter_flags = 0;
+ if (cogl_flags & COGL_FEATURE_TEXTURE_RECTANGLE)
+ clutter_flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
+
if (cogl_flags & COGL_FEATURE_TEXTURE_NPOT)
clutter_flags |= CLUTTER_FEATURE_TEXTURE_NPOT;
diff --git a/clutter/clutter-feature.h b/clutter/clutter-feature.h
index 89be737..0276fcf 100644
--- a/clutter/clutter-feature.h
+++ b/clutter/clutter-feature.h
@@ -57,6 +57,7 @@ G_BEGIN_DECLS
*/
typedef enum
{
+ CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
CLUTTER_FEATURE_TEXTURE_NPOT = (1 << 2),
CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 3),
CLUTTER_FEATURE_TEXTURE_YUV = (1 << 4),
diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c
index 3bdf3bd..7cae747 100644
--- a/clutter/cogl/gl/cogl-texture.c
+++ b/clutter/cogl/gl/cogl-texture.c
@@ -752,7 +752,20 @@ _cogl_texture_size_supported (GLenum gl_target,
int width,
int height)
{
-if (gl_target == GL_TEXTURE_2D)
+ if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ {
+ /* There is no proxy rectangle texture target so best we can
+ * do is to check against the safest value (although depending
+ * on our specific format and type the size could be supported
+ * when it seems it is not) */
+
+ GLint max_size = 0;
+
+ GE( glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_size) );
+
+ return (max_size && width <= max_size && height <= max_size);
+ }
+ else if (gl_target == GL_TEXTURE_2D)
{
/* Proxy texture allows for a quick check for supported size */
@@ -801,6 +814,13 @@ _cogl_texture_slices_create (CoglTexture *tex)
tex->gl_target = GL_TEXTURE_2D;
slices_for_size = _cogl_rect_slices_for_size;
}
+ else if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
+ {
+ max_width = tex->bitmap.width;
+ max_height = tex->bitmap.height;
+ tex->gl_target = GL_TEXTURE_RECTANGLE_ARB;
+ slices_for_size = _cogl_rect_slices_for_size;
+ }
else
{
max_width = cogl_util_next_p2 (tex->bitmap.width);
@@ -1423,7 +1443,8 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
CoglTexSliceSpan y_span;
/* Allow 2-dimensional textures only */
- if (gl_target != GL_TEXTURE_2D)
+ if (gl_target != GL_TEXTURE_2D &&
+ gl_target != GL_TEXTURE_RECTANGLE_ARB)
return COGL_INVALID_HANDLE;
/* Make sure it is a valid GL texture object */
@@ -1942,7 +1963,10 @@ _cogl_texture_quad_sw (CoglTexture *tex,
#endif
/* Prepare GL state */
- enable_flags |= COGL_ENABLE_TEXTURE_2D;
+ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ enable_flags |= COGL_ENABLE_TEXTURE_RECT;
+ else
+ enable_flags |= COGL_ENABLE_TEXTURE_2D;
if (ctx->color_alpha < 255
|| tex->bitmap.format & COGL_A_BIT)
@@ -1998,8 +2022,11 @@ _cogl_texture_quad_sw (CoglTexture *tex,
/* Normalize texture coordinates to current slice
(rectangle texture targets take denormalized) */
- slice_ty1 /= iter_y.span->size;
- slice_ty2 /= iter_y.span->size;
+ if (tex->gl_target != GL_TEXTURE_RECTANGLE_ARB)
+ {
+ slice_ty1 /= iter_y.span->size;
+ slice_ty2 /= iter_y.span->size;
+ }
/* Iterate until whole quad width covered */
@@ -2024,8 +2051,11 @@ _cogl_texture_quad_sw (CoglTexture *tex,
/* Normalize texture coordinates to current slice
(rectangle texture targets take denormalized) */
- slice_tx1 /= iter_x.span->size;
- slice_tx2 /= iter_x.span->size;
+ if (tex->gl_target != GL_TEXTURE_RECTANGLE_ARB)
+ {
+ slice_tx1 /= iter_x.span->size;
+ slice_tx2 /= iter_x.span->size;
+ }
#if COGL_DEBUG
printf("~~~~~ slice (%d,%d)\n", iter_x.index, iter_y.index);
@@ -2093,7 +2123,10 @@ _cogl_texture_quad_hw (CoglTexture *tex,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Prepare GL state */
- enable_flags |= COGL_ENABLE_TEXTURE_2D;
+ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ enable_flags |= COGL_ENABLE_TEXTURE_RECT;
+ else
+ enable_flags |= COGL_ENABLE_TEXTURE_2D;
if (ctx->color_alpha < 255
|| tex->bitmap.format & COGL_A_BIT)
@@ -2116,6 +2149,15 @@ _cogl_texture_quad_hw (CoglTexture *tex,
ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size;
ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size;
+ /* Denormalize texture coordinates for rectangle textures */
+ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ {
+ tx1 *= x_span->size;
+ tx2 *= x_span->size;
+ ty1 *= y_span->size;
+ ty2 *= y_span->size;
+ }
+
#define CFX_F(x) CLUTTER_FIXED_TO_FLOAT(x)
/* Draw textured quad */
@@ -2261,7 +2303,10 @@ cogl_texture_polygon (CoglHandle handle,
tex = _cogl_texture_pointer_from_handle (handle);
/* Prepare GL state */
- cogl_enable (COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_BLEND);
+ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ cogl_enable (COGL_ENABLE_TEXTURE_RECT | COGL_ENABLE_BLEND);
+ else
+ cogl_enable (COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_BLEND);
/* Temporarily change the wrapping mode on all of the slices to use
a transparent border */
@@ -2310,6 +2355,12 @@ cogl_texture_polygon (CoglHandle handle,
- y_span->start / (GLfloat) tex->bitmap.height)
* tex->bitmap.height / y_span->size;
+ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB)
+ {
+ tx *= x_span->size;
+ ty *= y_span->size;
+ }
+
glTexCoord2f (tx, ty);
glVertex3f (CLUTTER_FIXED_TO_FLOAT (vertices[vnum].x),
diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c
index 6906927..d56c306 100644
--- a/clutter/cogl/gl/cogl.c
+++ b/clutter/cogl/gl/cogl.c
@@ -323,6 +323,11 @@ cogl_enable (gulong flags)
COGL_ENABLE_TEXCOORD_ARRAY,
GL_TEXTURE_COORD_ARRAY);
+#ifdef GL_TEXTURE_RECTANGLE_ARB
+ cogl_toggle_flag (ctx, flags,
+ COGL_ENABLE_TEXTURE_RECT,
+ GL_TEXTURE_RECTANGLE_ARB);
+#endif
}
gulong
@@ -934,7 +939,15 @@ _cogl_features_init ()
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
- if (cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
+#if defined(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB) && defined(GL_TEXTURE_RECTANGLE_ARB)
+ if (cogl_check_extension ("GL_ARB_texture_rectangle", gl_extensions) ||
+ cogl_check_extension ("GL_EXT_texture_rectangle", gl_extensions))
+ {
+ flags |= COGL_FEATURE_TEXTURE_RECTANGLE;
+ }
+#endif
+
+ if (0 && cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
{
#ifdef HAVE_CLUTTER_OSX
if (really_enable_npot ())
diff --git a/clutter/glx/clutter-glx-texture-pixmap.c b/clutter/glx/clutter-glx-texture-pixmap.c
index 3ae6f54..0083fbf 100644
--- a/clutter/glx/clutter-glx-texture-pixmap.c
+++ b/clutter/glx/clutter-glx-texture-pixmap.c
@@ -548,7 +548,10 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
attribs[i++] = GLX_TEXTURE_TARGET_EXT;
- attribs[i++] = GLX_TEXTURE_2D_EXT;
+ if (clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT))
+ attribs[i++] = GLX_TEXTURE_2D_EXT;
+ else
+ attribs[i++] = GLX_TEXTURE_RECTANGLE_EXT;
attribs[i++] = None;
@@ -715,11 +718,9 @@ clutter_glx_texture_pixmap_using_extension (ClutterGLXTexturePixmap *texture)
priv = CLUTTER_GLX_TEXTURE_PIXMAP (texture)->priv;
- return (_have_tex_from_pixmap_ext);
- /* Assume NPOT TFP's are supported even if regular NPOT isn't advertised
- * but tfp is. Seemingly some Intel drivers do this ?
- */
- /* && clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT)); */
+ return (_have_tex_from_pixmap_ext
+ && (clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT)
+ || clutter_feature_available (COGL_FEATURE_TEXTURE_RECTANGLE)));
}
/**
--
1.6.0.3
>From f681d6dd400f342a54fa692dc29872f8a7deb74b Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <[EMAIL PROTECTED]>
Date: Wed, 5 Nov 2008 17:45:00 -0500
Subject: [PATCH] Support GL_ARB_texture_rectangle in MutterShapedTexture
mutter-shaped-texture.c: Retrieve the target from the cogl_texture
and use it, instead of hardcoding GL_TEXTURE_2D.
---
src/compositor/mutter/mutter-shaped-texture.c | 36 +++++++++++++++---------
1 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/src/compositor/mutter/mutter-shaped-texture.c b/src/compositor/mutter/mutter-shaped-texture.c
index 19e850e..c237870 100644
--- a/src/compositor/mutter/mutter-shaped-texture.c
+++ b/src/compositor/mutter/mutter-shaped-texture.c
@@ -233,6 +233,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
CoglHandle paint_tex;
guint tex_width, tex_height;
GLuint mask_gl_tex;
+ GLenum mask_target;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
@@ -291,14 +292,17 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
priv->mask_width = tex_width;
priv->mask_height = tex_height;
- cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, NULL);
+ cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target);
mutter_shaped_texture_get_gl_size (priv->mask_texture,
&priv->mask_gl_width,
&priv->mask_gl_height);
- if ((guint) priv->mask_gl_width == tex_width
- && (guint) priv->mask_gl_height == tex_height)
+ if (mask_target == GL_TEXTURE_RECTANGLE_ARB)
+ mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height,
+ priv->mask_tex_coords);
+ else if ((guint) priv->mask_gl_width == tex_width
+ && (guint) priv->mask_gl_height == tex_height)
mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f,
priv->mask_tex_coords);
else
@@ -322,6 +326,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
GLboolean vertex_array_was_enabled, tex_coord_array_was_enabled;
GLboolean color_array_was_enabled;
GLuint paint_gl_tex, mask_gl_tex;
+ GLenum paint_target, mask_target;
guint paint_gl_width, paint_gl_height;
GLfloat vertex_coords[8], paint_tex_coords[8];
ClutterActorBox alloc;
@@ -358,18 +363,18 @@ mutter_shaped_texture_paint (ClutterActor *actor)
mutter_shaped_texture_ensure_mask (stex);
- cogl_texture_get_gl_texture (paint_tex, &paint_gl_tex, NULL);
- cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, NULL);
+ cogl_texture_get_gl_texture (paint_tex, &paint_gl_tex, &paint_target);
+ cogl_texture_get_gl_texture (priv->mask_texture, &mask_gl_tex, &mask_target);
/* We need to keep track of the some of the old state so that we
don't confuse Cogl */
- texture_was_enabled = glIsEnabled (GL_TEXTURE_2D);
+ texture_was_enabled = glIsEnabled (paint_target);
blend_was_enabled = glIsEnabled (GL_BLEND);
vertex_array_was_enabled = glIsEnabled (GL_VERTEX_ARRAY);
tex_coord_array_was_enabled = glIsEnabled (GL_TEXTURE_COORD_ARRAY);
color_array_was_enabled = glIsEnabled (GL_COLOR_ARRAY);
- glEnable (GL_TEXTURE_2D);
+ glEnable (paint_target);
glEnable (GL_BLEND);
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
@@ -379,7 +384,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
cogl_color (&white);
/* Put the main painting texture in the first texture unit */
- glBindTexture (GL_TEXTURE_2D, paint_gl_tex);
+ glBindTexture (paint_target, paint_gl_tex);
/* We need the actual size of the texture so that we can calculate
the right texture coordinates if NPOTs textures are not supported
@@ -391,9 +396,9 @@ mutter_shaped_texture_paint (ClutterActor *actor)
/* Put the mask texture in the second texture unit */
tst_active_texture (GL_TEXTURE1);
tst_client_active_texture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_2D, mask_gl_tex);
+ glBindTexture (mask_target, mask_gl_tex);
- glEnable (GL_TEXTURE_2D);
+ glEnable (mask_target);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, priv->mask_tex_coords);
@@ -419,8 +424,11 @@ mutter_shaped_texture_paint (ClutterActor *actor)
- alloc.y1),
vertex_coords);
- if ((guint) paint_gl_width == tex_width
- && (guint) paint_gl_height == tex_height)
+ if (paint_target == GL_TEXTURE_RECTANGLE_ARB)
+ mutter_shaped_texture_set_coord_array (0.0f, 0.0f, tex_width, tex_height,
+ paint_tex_coords);
+ else if ((guint) paint_gl_width == tex_width
+ && (guint) paint_gl_height == tex_height)
mutter_shaped_texture_set_coord_array (0.0f, 0.0f, 1.0f, 1.0f,
paint_tex_coords);
else
@@ -434,7 +442,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
/* Disable the second texture unit and coord array */
- glDisable (GL_TEXTURE_2D);
+ glDisable (mask_target);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
/* Go back to operating on the first texture unit */
@@ -443,7 +451,7 @@ mutter_shaped_texture_paint (ClutterActor *actor)
/* Restore the old state */
if (!texture_was_enabled)
- glDisable (GL_TEXTURE_2D);
+ glDisable (paint_target);
if (!blend_was_enabled)
glDisable (GL_BLEND);
if (!vertex_array_was_enabled)
--
1.6.0.3
>From 4ac3e3ec460338d0f3f086b11e891552cd05453c Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <[EMAIL PROTECTED]>
Date: Wed, 5 Nov 2008 18:27:30 -0500
Subject: [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
>From f3df37a11ccc159141d944bfe6f93a709263d0dc Mon Sep 17 00:00:00 2001
From: Owen W. Taylor <[EMAIL PROTECTED]>
Date: Wed, 5 Nov 2008 18:33:10 -0500
Subject: [PATCH] Use ARB_texture_rectangle for pixmap shape rectangle when appropriate
Use the newly added cogl_texture_new_from_data_and_options() to enable
use of ARB_texture_rectangle.
Support CLUTTER_PIXMAP_TEXTURE_RECTANGLE=[force|disable] in the same
way as Clutter now does.
---
src/compositor/mutter/mutter-shaped-texture.c | 43 +++++++++++++++++++++---
1 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/src/compositor/mutter/mutter-shaped-texture.c b/src/compositor/mutter/mutter-shaped-texture.c
index c237870..3bb88f3 100644
--- a/src/compositor/mutter/mutter-shaped-texture.c
+++ b/src/compositor/mutter/mutter-shaped-texture.c
@@ -226,6 +226,36 @@ mutter_shaped_texture_get_gl_size (CoglHandle tex,
}
}
+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 void
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
{
@@ -280,12 +310,13 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
memset (p, 255, x2 - x1);
}
- priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
- -1, FALSE,
- COGL_PIXEL_FORMAT_A_8,
- COGL_PIXEL_FORMAT_ANY,
- tex_width,
- mask_data);
+ priv->mask_texture = cogl_texture_new_from_data_and_options (tex_width, tex_height,
+ -1,
+ get_texture_options(),
+ COGL_PIXEL_FORMAT_A_8,
+ COGL_PIXEL_FORMAT_ANY,
+ tex_width,
+ mask_data);
g_free (mask_data);
--
1.6.0.3