From 90f106117fada67c084dd6cda7e70a0f6246c807 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Fri, 14 Oct 2011 09:25:12 +0100 Subject: [PATCH] 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 --- cogl/Makefile.am | 1 + cogl/cogl-meta-texture.c | 4 +- cogl/cogl-sub-texture.c | 6 +- cogl/cogl-texture-rectangle-private.h | 18 +-- cogl/cogl-texture-rectangle.c | 80 ++++++------ cogl/cogl-texture-rectangle.h | 118 ++++++++++++++++++ cogl/cogl-texture.h | 3 +- cogl/cogl.h | 1 + cogl/winsys/cogl-texture-pixmap-x11.c | 2 +- cogl/winsys/cogl-winsys-glx.c | 15 ++- .../cogl-2.0-experimental-sections.txt | 7 ++ 11 files changed, 191 insertions(+), 64 deletions(-) create mode 100644 cogl/cogl-texture-rectangle.h diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 2d844cf0f..ca7d4b67b 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -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 \ diff --git a/cogl/cogl-meta-texture.c b/cogl/cogl-meta-texture.c index 811ded65d..6ec006b0d 100644 --- a/cogl/cogl-meta-texture.c +++ b/cogl/cogl-meta-texture.c @@ -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; diff --git a/cogl/cogl-sub-texture.c b/cogl/cogl-sub-texture.c index 4776e3556..961126e87 100644 --- a/cogl/cogl-sub-texture.c +++ b/cogl/cogl-sub-texture.c @@ -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, diff --git a/cogl/cogl-texture-rectangle-private.h b/cogl/cogl-texture-rectangle-private.h index 07eca5e80..dde910970 100644 --- a/cogl/cogl-texture-rectangle-private.h +++ b/cogl/cogl-texture-rectangle-private.h @@ -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, diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c index 9ea93921e..c43779b27 100644 --- a/cogl/cogl-texture-rectangle.c +++ b/cogl/cogl-texture-rectangle.c @@ -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; diff --git a/cogl/cogl-texture-rectangle.h b/cogl/cogl-texture-rectangle.h new file mode 100644 index 000000000..927bb933e --- /dev/null +++ b/cogl/cogl-texture-rectangle.h @@ -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 + * . + * + * + * Authors: + * Robert Bragg + */ + +#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. + * + * 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(). + * + * 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 */ diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h index 295e27988..ba5418812 100644 --- a/cogl/cogl-texture.h +++ b/cogl/cogl-texture.h @@ -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); diff --git a/cogl/cogl.h b/cogl/cogl.h index 336736065..aa32948da 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -80,6 +80,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer; #include #include #include +#include #include #include #include diff --git a/cogl/winsys/cogl-texture-pixmap-x11.c b/cogl/winsys/cogl-texture-pixmap-x11.c index 76ad7feb0..caacc909b 100644 --- a/cogl/winsys/cogl-texture-pixmap-x11.c +++ b/cogl/winsys/cogl-texture-pixmap-x11.c @@ -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; diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c index 61af5fd78..dec96a1ec 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -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; } diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt index d97ddcca5..f26fc4f3f 100644 --- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt +++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt @@ -304,6 +304,13 @@ cogl_texture_set_region COGL_TEXTURE_MAX_WASTE +
+cogl-texture-rectangle +Rectangle textures (non-normalized coordinates) +cogl_texture_rectangle_new_with_size +cogl_is_texture_rectangle +
+
cogl-texture-3d 3D textures