texture: Make CoglTextureRectangle experimentally public

This exposes CoglTextureRectangle in the experimental cogl 2.0 api. For
now we just expose a single constructor;
cogl_texture_rectangle_new_with_size() but we can add more later.

This is part of going work to improve our texture apis with more
emphasis on providing low-level access to the varying semantics of
different texture types understood by the gpu instead of only trying to
present a lowest common denominator api.

CoglTextureRectangle is notably useful for never being restricted to
power of two sizes and for being sampled with non-normalized texture
coordinates which can be convenient for use a lookup tables in glsl due
to not needing separate uniforms for mapping normalized coordinates to
texels. Unlike CoglTexture2D though rectangle textures can't have a
mipmap and they only support the _CLAMP_TO_EDGE wrap mode.

Applications wanting to use CoglTextureRectangle should first check
cogl_has_feature (COGL_FEATURE_ID_TEXTURE_RECTANGLE).

Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
Robert Bragg 2011-10-14 09:25:12 +01:00
parent e70071ff1d
commit 90f106117f
11 changed files with 191 additions and 64 deletions

View File

@ -77,6 +77,7 @@ cogl_public_h = \
$(srcdir)/cogl-texture.h \
$(srcdir)/cogl-texture-3d.h \
$(srcdir)/cogl-texture-2d.h \
$(srcdir)/cogl-texture-rectangle.h \
$(srcdir)/cogl-texture-2d-sliced.h \
$(srcdir)/cogl-meta-texture.h \
$(srcdir)/cogl-types.h \

View File

@ -291,7 +291,7 @@ cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture,
* coordinates beyond this point and only re-normalize just before
* calling the user's callback... */
if (!_cogl_is_texture_rectangle (COGL_TEXTURE (meta_texture)))
if (!cogl_is_texture_rectangle (COGL_TEXTURE (meta_texture)))
{
normalize_data.callback = callback;
normalize_data.user_data = user_data;
@ -367,7 +367,7 @@ cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture,
* callback that un_normalizes the slice coordinates we get from
* _cogl_texture_spans_foreach_in_region before passing them to
* the user's callback. */
if (_cogl_is_texture_rectangle (meta_texture))
if (cogl_is_texture_rectangle (meta_texture))
{
un_normalize_data.callback = callback;
un_normalize_data.user_data = user_data;

View File

@ -58,7 +58,7 @@ _cogl_sub_texture_unmap_quad (CoglSubTexture *sub_tex,
* NB: sub_tex->sub_x/y/width/height are in non-normalized
* coordinates.
*/
if (_cogl_is_texture_rectangle (sub_tex->full_texture))
if (cogl_is_texture_rectangle (sub_tex->full_texture))
{
coords[0] = (coords[0] - sub_tex->sub_x) / sub_tex->sub_width;
coords[1] = (coords[1] - sub_tex->sub_y) / sub_tex->sub_height;
@ -88,7 +88,7 @@ _cogl_sub_texture_map_quad (CoglSubTexture *sub_tex,
* coordinates.
*/
if (_cogl_is_texture_rectangle (sub_tex->full_texture))
if (cogl_is_texture_rectangle (sub_tex->full_texture))
{
coords[0] = coords[0] * sub_tex->sub_width + sub_tex->sub_x;
coords[1] = coords[1] * sub_tex->sub_height + sub_tex->sub_y;
@ -154,7 +154,7 @@ _cogl_sub_texture_foreach_sub_texture_in_region (
/* TODO: Add something like cogl_is_low_level_texture() */
if (cogl_is_texture_2d (full_texture) ||
_cogl_is_texture_rectangle (full_texture))
cogl_is_texture_rectangle (full_texture))
{
callback (sub_tex->full_texture,
mapped_coords,

View File

@ -24,14 +24,9 @@
#ifndef __COGL_TEXTURE_RECTANGLE_H
#define __COGL_TEXTURE_RECTANGLE_H
#include "cogl-handle.h"
#include "cogl-pipeline-private.h"
#include "cogl-texture-private.h"
#define COGL_TEXTURE_RECTANGLE(tex) ((CoglTextureRectangle *) tex)
typedef struct _CoglTextureRectangle CoglTextureRectangle;
struct _CoglTextureRectangle
{
CoglTexture _parent;
@ -52,24 +47,15 @@ struct _CoglTextureRectangle
gboolean is_foreign;
};
gboolean
_cogl_is_texture_rectangle (void *object);
GQuark
_cogl_handle_texture_rectangle_get_type (void);
CoglHandle
_cogl_texture_rectangle_new_with_size (unsigned int width,
unsigned int height,
CoglTextureFlags flags,
CoglPixelFormat internal_format);
CoglHandle
CoglTextureRectangle *
_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format);
CoglHandle
CoglTextureRectangle *
_cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
GLuint width,
GLuint height,

View File

@ -55,7 +55,7 @@
static void _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect);
COGL_TEXTURE_INTERNAL_DEFINE (TextureRectangle, texture_rectangle);
COGL_TEXTURE_DEFINE (TextureRectangle, texture_rectangle);
static const CoglTextureVtable cogl_texture_rectangle_vtable;
@ -112,7 +112,8 @@ _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect)
static gboolean
_cogl_texture_rectangle_can_create (unsigned int width,
unsigned int height,
CoglPixelFormat internal_format)
CoglPixelFormat internal_format,
GError **error)
{
GLenum gl_intformat;
GLenum gl_type;
@ -120,7 +121,13 @@ _cogl_texture_rectangle_can_create (unsigned int width,
_COGL_GET_CONTEXT (ctx, FALSE);
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
return FALSE;
{
g_set_error (error,
COGL_TEXTURE_ERROR,
COGL_TEXTURE_ERROR_TYPE,
"The CoglTextureRectangle feature isn't available");
return FALSE;
}
ctx->texture_driver->pixel_format_to_gl (internal_format,
&gl_intformat,
@ -133,7 +140,13 @@ _cogl_texture_rectangle_can_create (unsigned int width,
gl_type,
width,
height))
return FALSE;
{
g_set_error (error,
COGL_TEXTURE_ERROR,
COGL_TEXTURE_ERROR_SIZE,
"The requested texture size + format is unsupported");
return FALSE;
}
return TRUE;
}
@ -141,7 +154,6 @@ _cogl_texture_rectangle_can_create (unsigned int width,
static CoglTextureRectangle *
_cogl_texture_rectangle_create_base (unsigned int width,
unsigned int height,
CoglTextureFlags flags,
CoglPixelFormat internal_format)
{
CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
@ -165,32 +177,32 @@ _cogl_texture_rectangle_create_base (unsigned int width,
return tex_rect;
}
CoglHandle
_cogl_texture_rectangle_new_with_size (unsigned int width,
unsigned int height,
CoglTextureFlags flags,
CoglPixelFormat internal_format)
CoglTextureRectangle *
cogl_texture_rectangle_new_with_size (CoglContext *ctx,
int width,
int height,
CoglPixelFormat internal_format,
GError **error)
{
CoglTextureRectangle *tex_rect;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
if (!_cogl_texture_rectangle_can_create (width, height, internal_format))
return COGL_INVALID_HANDLE;
if (!_cogl_texture_rectangle_can_create (width, height,
internal_format, error))
return NULL;
internal_format = ctx->texture_driver->pixel_format_to_gl (internal_format,
&gl_intformat,
&gl_format,
&gl_type);
tex_rect = _cogl_texture_rectangle_create_base (width, height, flags,
tex_rect = _cogl_texture_rectangle_create_base (width, height,
internal_format);
ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
@ -200,10 +212,10 @@ _cogl_texture_rectangle_new_with_size (unsigned int width,
GE( ctx, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
width, height, 0, gl_format, gl_type, NULL) );
return _cogl_texture_rectangle_handle_new (tex_rect);
return _cogl_texture_rectangle_object_new (tex_rect);
}
CoglHandle
CoglTextureRectangle *
_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format)
@ -214,9 +226,9 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
GLenum gl_format;
GLenum gl_type;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
internal_format =
_cogl_texture_determine_internal_format (_cogl_bitmap_get_format (bmp),
@ -224,8 +236,9 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
if (!_cogl_texture_rectangle_can_create (_cogl_bitmap_get_width (bmp),
_cogl_bitmap_get_height (bmp),
internal_format))
return COGL_INVALID_HANDLE;
internal_format,
NULL))
return NULL;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
@ -235,11 +248,10 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
&gl_type);
if (dst_bmp == NULL)
return COGL_INVALID_HANDLE;
return NULL;
tex_rect = _cogl_texture_rectangle_create_base (_cogl_bitmap_get_width (bmp),
_cogl_bitmap_get_height (bmp),
flags,
internal_format);
ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
@ -255,10 +267,10 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
cogl_object_unref (dst_bmp);
return _cogl_texture_rectangle_handle_new (tex_rect);
return _cogl_texture_rectangle_object_new (tex_rect);
}
CoglHandle
CoglTextureRectangle *
_cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
GLuint width,
GLuint height,
@ -273,14 +285,14 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
GLenum gl_int_format = 0;
CoglTextureRectangle *tex_rect;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
_COGL_GET_CONTEXT (ctx, NULL);
if (!ctx->texture_driver->allows_foreign_gl_target (GL_TEXTURE_RECTANGLE_ARB))
return COGL_INVALID_HANDLE;
return NULL;
/* Make sure it is a valid GL texture object */
if (!ctx->glIsTexture (gl_handle))
return COGL_INVALID_HANDLE;
return NULL;
/* Make sure binding succeeds */
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
@ -288,7 +300,7 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, gl_handle, TRUE);
if (ctx->glGetError () != GL_NO_ERROR)
return COGL_INVALID_HANDLE;
return NULL;
/* Obtain texture parameters */
@ -311,7 +323,7 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
the passed in format and use that. */
if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
&format))
return COGL_INVALID_HANDLE;
return NULL;
}
else
#endif
@ -333,16 +345,14 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
/* Validate width and height */
if (width <= 0 || height <= 0)
return COGL_INVALID_HANDLE;
return NULL;
/* Compressed texture images not supported */
if (gl_compressed == GL_TRUE)
return COGL_INVALID_HANDLE;
return NULL;
/* Create new texture */
tex_rect = _cogl_texture_rectangle_create_base (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
format);
tex_rect = _cogl_texture_rectangle_create_base (width, height, format);
/* Setup bitmap info */
tex_rect->is_foreign = TRUE;

View File

@ -0,0 +1,118 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef __COGL_TEXURE_RECTANGLE_H
#define __COGL_TEXURE_RECTANGLE_H
#include "cogl-context.h"
G_BEGIN_DECLS
/**
* SECTION:cogl-texture-rectangle
* @short_description: Functions for creating and manipulating rectangle
* textures for use with non-normalized coordinates.
*
* These functions allow low-level "rectangle" textures to be allocated.
* These textures are never constrained to power-of-two sizes but they
* also don't support having a mipmap and can only be wrapped with
* %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE.
*
* The most notable difference between rectangle textures and 2D
* textures is that rectangle textures are sampled using un-normalized
* texture coordinates, so instead of using coordinates (0,0) and
* (1,1) to map to the top-left and bottom right corners of the
* texture you would instead use (0,0) and (width,height).
*
* The use of non-normalized coordinates can be particularly
* convenient when writing glsl shaders that use a texture as a lookup
* table since you don't need to upload separate uniforms to map
* normalized coordinates to texels.
*
* If you want to sample from a rectangle texture from GLSL you should
* use the sampler2DRect sampler type.
*
* Applications wanting to use #CoglTextureRectangle should first check
* for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature using
* cogl_has_feature().
*/
typedef struct _CoglTextureRectangle CoglTextureRectangle;
#define COGL_TEXTURE_RECTANGLE(X) ((CoglTextureRectangle *)X)
#define cogl_is_texture_rectangle cogl_is_texture_rectangle_EXP
/**
* cogl_is_texture_rectangle:
* @object: A #CoglObject
*
* Gets whether the given object references an existing
* #CoglTextureRectangle object.
*
* Return value: %TRUE if the object references a
* #CoglTextureRectangle, %FALSE otherwise.
*/
gboolean
cogl_is_texture_rectangle (void *object);
#define cogl_texture_rectangle_new_with_size \
cogl_texture_rectangle_new_with_size_EXP
/**
* cogl_texture_rectangle_new_with_size:
* @context: A #CoglContext pointer
* @width: The texture width to allocate
* @height: The texture height to allocate
* @internal_format: The desired internal texture format
* @error: An optional GError pointer for reporting exceptions
*
* Allocates a new #CoglRectangle texture with a given @width, @height
* and @internal_format. This texture is a low-level texture that
* the GPU can sample from directly unlike high-level textures such
* as #CoglTexture2DSliced and #CoglAtlasTexture.
*
* <note>If you want to sample from a rectangle texture from GLSL you
* should use the sampler2DRect sampler type.</note>
*
* <note>Applications wanting to use #CoglTextureRectangle should
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
* using cogl_has_feature().</note>
*
* Returns: A pointer to a newly allocated #CoglRectangle texture
* or if the size was too large or there wasn't enough memory
* %NULL is returned and @error set.
*
* Since: 1.10
* Stability: unstable
*/
CoglTextureRectangle *
cogl_texture_rectangle_new_with_size (CoglContext *ctx,
int width,
int height,
CoglPixelFormat internal_format,
GError **error);
G_END_DECLS
#endif /* __COGL_TEXURE_RECTANGLE_H */

View File

@ -74,7 +74,8 @@ typedef struct _CoglTexture CoglTexture;
typedef enum {
COGL_TEXTURE_ERROR_SIZE,
COGL_TEXTURE_ERROR_FORMAT,
COGL_TEXTURE_ERROR_BAD_PARAMETER
COGL_TEXTURE_ERROR_BAD_PARAMETER,
COGL_TEXTURE_ERROR_TYPE
} CoglTextureError;
GQuark cogl_texture_error_quark (void);

View File

@ -80,6 +80,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
#include <cogl/cogl-euler.h>
#include <cogl/cogl-quaternion.h>
#include <cogl/cogl-texture-2d.h>
#include <cogl/cogl-texture-rectangle.h>
#include <cogl/cogl-texture-3d.h>
#include <cogl/cogl-texture-2d-sliced.h>
#include <cogl/cogl-meta-texture.h>

View File

@ -785,7 +785,7 @@ _cogl_texture_pixmap_x11_foreach_sub_texture_in_region
* CoglTextureRectangle texture which uses un-normalized texture
* coordinates but we want to consistently deal with normalized
* texture coordinates with CoglTexturePixmapX11... */
if (_cogl_is_texture_rectangle (child_tex))
if (cogl_is_texture_rectangle (child_tex))
{
NormalizeCoordsWrapperData data;
int width = tex_pixmap->width;

View File

@ -1923,6 +1923,7 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
if (glx_tex_pixmap->glx_tex == COGL_INVALID_HANDLE)
{
CoglPixelFormat texture_format;
GError *error = NULL;
texture_format = (tex_pixmap->depth >= 32 ?
COGL_PIXEL_FORMAT_RGBA_8888_PRE :
@ -1931,10 +1932,11 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
if (should_use_rectangle (ctx))
{
glx_tex_pixmap->glx_tex =
_cogl_texture_rectangle_new_with_size (tex_pixmap->width,
tex_pixmap->height,
COGL_TEXTURE_NO_ATLAS,
texture_format);
cogl_texture_rectangle_new_with_size (ctx,
tex_pixmap->width,
tex_pixmap->height,
texture_format,
&error);
if (glx_tex_pixmap->glx_tex)
COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p",
@ -1942,8 +1944,9 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
else
{
COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
"texture rectangle could not be created",
tex_pixmap);
"texture rectangle could not be created: %s",
tex_pixmap, error->message);
g_error_free (error);
free_glx_pixmap (ctx, glx_tex_pixmap);
return FALSE;
}

View File

@ -304,6 +304,13 @@ cogl_texture_set_region
COGL_TEXTURE_MAX_WASTE
</SECTION>
<SECTION>
<FILE>cogl-texture-rectangle</FILE>
<TITLE>Rectangle textures (non-normalized coordinates)</TITLE>
cogl_texture_rectangle_new_with_size
cogl_is_texture_rectangle
</SECTION>
<SECTION>
<FILE>cogl-texture-3d</FILE>
<TITLE>3D textures</TITLE>