diff --git a/cogl/Makefile.am b/cogl/Makefile.am index a0ccc391e..91451bb4f 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -75,6 +75,7 @@ cogl_public_h = \ $(srcdir)/cogl-shader.h \ $(srcdir)/cogl-texture.h \ $(srcdir)/cogl-texture-3d.h \ + $(srcdir)/cogl-texture-2d.h \ $(srcdir)/cogl-types.h \ $(srcdir)/cogl-vertex-buffer.h \ $(srcdir)/cogl-index-buffer.h \ diff --git a/cogl/cogl-atlas.c b/cogl/cogl-atlas.c index 9a75a6020..6138d46e6 100644 --- a/cogl/cogl-atlas.c +++ b/cogl/cogl-atlas.c @@ -285,12 +285,18 @@ _cogl_atlas_create_texture (CoglAtlas *atlas, NULL); tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE, - atlas->texture_format); + atlas->texture_format, + NULL); cogl_object_unref (clear_bmp); } else - tex = _cogl_texture_2d_new_with_size (width, height, COGL_TEXTURE_NONE, - atlas->texture_format); + { + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + tex = cogl_texture_2d_new_with_size (ctx, + width, height, + atlas->texture_format, + NULL); + } return tex; } diff --git a/cogl/cogl-blit.c b/cogl/cogl-blit.c index 944244155..b0e93e40f 100644 --- a/cogl/cogl-blit.c +++ b/cogl/cogl-blit.c @@ -199,7 +199,7 @@ _cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data) _COGL_GET_CONTEXT (ctx, FALSE); /* This will only work if the target texture is a CoglTexture2D */ - if (!_cogl_is_texture_2d (data->dst_tex)) + if (!cogl_is_texture_2d (data->dst_tex)) return FALSE; fbo = _cogl_offscreen_new_to_texture_full diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h index 9c303414e..d05b342d9 100644 --- a/cogl/cogl-texture-2d-private.h +++ b/cogl/cogl-texture-2d-private.h @@ -28,10 +28,6 @@ #include "cogl-pipeline-private.h" #include "cogl-texture-private.h" -#define COGL_TEXTURE_2D(tex) ((CoglTexture2D *) tex) - -typedef struct _CoglTexture2D CoglTexture2D; - struct _CoglTexture2D { CoglTexture _parent; @@ -59,25 +55,11 @@ struct _CoglTexture2D GQuark _cogl_handle_texture_2d_get_type (void); -gboolean -_cogl_is_texture_2d (CoglHandle object); - -CoglHandle -_cogl_texture_2d_new_with_size (unsigned int width, - unsigned int height, - CoglTextureFlags flags, - CoglPixelFormat internal_format); - CoglHandle _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, CoglTextureFlags flags, - CoglPixelFormat internal_format); - -CoglHandle -_cogl_texture_2d_new_from_foreign (GLuint gl_handle, - GLuint width, - GLuint height, - CoglPixelFormat format); + CoglPixelFormat internal_format, + GError **error); /* * _cogl_texture_2d_externally_modified: diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index 29152b7fc..6cda2c349 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -1041,6 +1041,8 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, CoglSpan y_span; CoglHandle tex_2d; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + /* This should only be called when the texture target is 2D. If a rectangle texture is used then _cogl_texture_new_from_foreign will create a cogl_texture_rectangle instead */ @@ -1054,10 +1056,12 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, y_pot_waste < 0 || y_pot_waste >= height) return COGL_INVALID_HANDLE; - tex_2d = _cogl_texture_2d_new_from_foreign (gl_target, - gl_width, - gl_height, - format); + tex_2d = cogl_texture_2d_new_from_foreign (ctx, + gl_target, + gl_width, + gl_height, + format, + NULL); if (!tex_2d) return COGL_INVALID_HANDLE; diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 05a455a10..178bfc85d 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -45,7 +45,7 @@ static void _cogl_texture_2d_free (CoglTexture2D *tex_2d); -COGL_TEXTURE_INTERNAL_DEFINE (Texture2D, texture_2d); +COGL_TEXTURE_DEFINE (Texture2D, texture_2d); static const CoglTextureVtable cogl_texture_2d_vtable; @@ -220,11 +220,12 @@ _cogl_texture_2d_create_base (unsigned int width, return tex_2d; } -CoglHandle -_cogl_texture_2d_new_with_size (unsigned int width, - unsigned int height, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +CoglTexture2D * +cogl_texture_2d_new_with_size (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + GError **error) { CoglTexture2D *tex_2d; GLenum gl_intformat; @@ -236,14 +237,21 @@ _cogl_texture_2d_new_with_size (unsigned int width, internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; if (!_cogl_texture_2d_can_create (width, height, internal_format)) - return COGL_INVALID_HANDLE; + { + g_set_error (error, COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "Failed to create texture 2d due to size/format" + " constraints"); + return NULL; + } internal_format = _cogl_pixel_format_to_gl (internal_format, &gl_intformat, &gl_format, &gl_type); - tex_2d = _cogl_texture_2d_create_base (width, height, flags, internal_format); + tex_2d = _cogl_texture_2d_create_base (width, height, COGL_TEXTURE_NONE, + internal_format); _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, @@ -258,7 +266,8 @@ _cogl_texture_2d_new_with_size (unsigned int width, CoglHandle _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, CoglTextureFlags flags, - CoglPixelFormat internal_format) + CoglPixelFormat internal_format, + GError **error) { CoglTexture2D *tex_2d; CoglBitmap *dst_bmp; @@ -276,7 +285,14 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, if (!_cogl_texture_2d_can_create (_cogl_bitmap_get_width (bmp), _cogl_bitmap_get_height (bmp), internal_format)) - return COGL_INVALID_HANDLE; + { + g_set_error (error, COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "Failed to create texture 2d due to size/format" + " constraints"); + return NULL; + + } if ((dst_bmp = _cogl_texture_prepare_for_upload (bmp, internal_format, @@ -284,7 +300,12 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, &gl_intformat, &gl_format, &gl_type)) == NULL) - return COGL_INVALID_HANDLE; + { + g_set_error (error, COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_FORMAT, + "Failed to prepare texture upload due to format"); + return NULL; + } tex_2d = _cogl_texture_2d_create_base (_cogl_bitmap_get_width (bmp), _cogl_bitmap_get_height (bmp), @@ -321,11 +342,50 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, return _cogl_texture_2d_handle_new (tex_2d); } -CoglHandle -_cogl_texture_2d_new_from_foreign (GLuint gl_handle, - GLuint width, - GLuint height, - CoglPixelFormat format) +CoglTexture2D * +cogl_texture_2d_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + CoglPixelFormat internal_format, + int rowstride, + const guint8 *data, + GError **error) +{ + CoglBitmap *bmp; + CoglHandle tex; + + g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL); + g_return_val_if_fail (data != NULL, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_get_format_bpp (format); + + /* Wrap the data into a bitmap */ + bmp = _cogl_bitmap_new_from_data ((guint8 *)data, + format, + width, + height, + rowstride, + NULL, NULL); + + tex =_cogl_texture_2d_new_from_bitmap (bmp, COGL_TEXTURE_NONE, + internal_format, + error); + + cogl_object_unref (bmp); + + return tex; +} + +CoglTexture2D * +cogl_texture_2d_new_from_foreign (CoglContext *ctx, + GLuint gl_handle, + int width, + int height, + CoglPixelFormat format, + GError **error) { /* NOTE: width, height and internal format are not queriable * in GLES, hence such a function prototype. @@ -436,7 +496,7 @@ _cogl_texture_2d_new_from_foreign (GLuint gl_handle, void _cogl_texture_2d_externally_modified (CoglHandle handle) { - if (!_cogl_is_texture_2d (handle)) + if (!cogl_is_texture_2d (handle)) return; COGL_TEXTURE_2D (handle)->mipmaps_dirty = TRUE; @@ -453,7 +513,7 @@ _cogl_texture_2d_copy_from_framebuffer (CoglHandle handle, { CoglTexture2D *tex_2d; - g_return_if_fail (_cogl_is_texture_2d (handle)); + g_return_if_fail (cogl_is_texture_2d (handle)); tex_2d = COGL_TEXTURE_2D (handle); diff --git a/cogl/cogl-texture-2d.h b/cogl/cogl-texture-2d.h new file mode 100644 index 000000000..1883cade3 --- /dev/null +++ b/cogl/cogl-texture-2d.h @@ -0,0 +1,184 @@ +/* + * 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_2D_H +#define __COGL_TEXURE_2D_H + +#include + +G_BEGIN_DECLS + +/** + * SECTION:cogl-texture-2d + * @short_description: Functions for creating and manipulating 2D textures + * + * These functions allow low-level 2D textures to be allocated. These + * differ from sliced textures for example which may internally be + * made up of multiple 2D textures, or atlas textures where Cogl must + * internally modify user texture coordinates before they can be used + * by the GPU. + * + * You should be aware that many GPUs only support power of two sizes + * for #CoglTexture2D textures. You can check support for non power of + * two textures by checking for the %COGL_FEATURE_TEXTURE_NPOT feature + * via cogl_features_available (). + */ + +typedef struct _CoglTexture2D CoglTexture2D; +#define COGL_TEXTURE_2D(X) ((CoglTexture2D *)X) + +/** + * cogl_is_texture_2d: + * @object: A #CoglObject + * + * Gets whether the given object references an existing #CoglTexture2D + * object. + * + * Return value: %TRUE if the object references a #CoglTexture2D, + * %FALSE otherwise + */ +#define cogl_is_texture_2d cogl_is_texture_2d_EXP +gboolean +cogl_is_texture_2d (void *object); + +/** + * cogl_texture_2d_new_with_size: + * @ctx: A #CoglContext + * @width: Width of the texture to allocate + * @height: Height of the texture to allocate + * @internal_format: The format of the texture + * @error: A #GError for exceptions + * + * Allocates a low-level #CoglTexture2D texture that your GPU can + * texture from directly. This is unlike sliced textures for example + * which may be comprised of multiple internal textures, or atlas + * textures where Cogl has to modify texture coordinates before they + * may be used by the GPU. + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_TEXTURE_NPOT feature via + * cogl_features_available (). + * + * Returns: A newly allocated #CoglTexture2D, or if the size is not + * supported (because it is too large or a non-power-of-two + * size that the hardware doesn't support) it will return + * %NULL and set @error. + * + * Since: 2.0 + */ +#define cogl_texture_2d_new_with_size cogl_texture_2d_new_with_size_EXP +CoglTexture2D * +cogl_texture_2d_new_with_size (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + GError **error); + +/** + * cogl_texture_2d_new_from_data: + * @ctx: A #CoglContext + * @width: width of texture in pixels + * @height: height of texture in pixels + * @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. If COGL_PIXEL_FORMAT_ANY is given then a + * premultiplied format similar to the format of the source data will + * be used. The default blending equations of Cogl expect premultiplied + * color data; the main use of passing a non-premultiplied format here + * is if you have non-premultiplied source data and are going to adjust + * the blend mode (see cogl_material_set_blend()) or use the data for + * something other than straight blending. + * @rowstride: the memory offset in bytes between the starts of + * scanlines in @data. A value of 0 will make Cogl automatically + * calculate @rowstride from @width and @format. + * @data: pointer the memory region where the source buffer resides + * @error: A #GError for exceptions + * + * Creates a new #CoglTexture2D texture based on data residing in memory. + * These are unlike sliced textures for example which may be comprised + * of multiple internal textures, or atlas textures where Cogl has to + * modify texture coordinates before they may be used by the GPU. + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_TEXTURE_NPOT feature via + * cogl_features_available (). + * + * Returns: A newly allocated #CoglTexture2D, or if the size is not + * supported (because it is too large or a non-power-of-two + * size that the hardware doesn't support) it will return + * %NULL and set @error. + * + * Since: 2.0 + */ +#define cogl_texture_2d_new_from_data cogl_texture_2d_new_from_data_EXP +CoglTexture2D * +cogl_texture_2d_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + CoglPixelFormat internal_format, + int rowstride, + const guint8 *data, + GError **error); + +/** + * cogl_texture_2d_new_from_foreign: + * @ctx: A #CoglContext + * @gl_handle: A GL handle for a GL_TEXTURE_2D texture object + * @width: Width of the foreign GL texture + * @height: Height of the foreign GL texture + * @internal_format: The format of the texture + * @error: A #GError for exceptions + * + * Wraps an existing GL_TEXTURE_2D texture object as a #CoglTexture2D. + * This can be used for integrating Cogl with software using OpenGL + * directly. + * + * The results are undefined for passing an invalid @gl_handle + * or if @width or @height don't have the correct texture + * geometry. + * + * Returns: A newly allocated #CoglTexture2D, or if Cogl could not + * validate the @gl_handle in some way (perhaps because of + * an unsupported format) it will return %NULL and set + * @error. + * + * Since: 2.0 + */ +#define cogl_texture_2d_new_from_foreign cogl_texture_2d_new_from_foreign_EXP +CoglTexture2D * +cogl_texture_2d_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + int width, + int height, + CoglPixelFormat format, + GError **error); + +G_END_DECLS + +#endif /* __COGL_TEXURE_2D_H */ diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index 57f4905c5..d7b207051 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -57,6 +57,12 @@ #include #include +GQuark +cogl_texture_error_quark (void) +{ + return g_quark_from_static_string ("cogl-texture-error-quark"); +} + /* XXX: * The CoglHandle macros don't support any form of inheritance, so for * now we implement the CoglHandle support for the CoglTexture @@ -385,8 +391,12 @@ cogl_texture_new_with_size (unsigned int width, { CoglHandle tex; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + /* First try creating a fast-path non-sliced texture */ - tex = _cogl_texture_2d_new_with_size (width, height, flags, internal_format); + tex = cogl_texture_2d_new_with_size (ctx, + width, height, internal_format, + NULL); /* If it fails resort to sliced textures */ if (tex == COGL_INVALID_HANDLE) @@ -451,7 +461,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, /* If that doesn't work try a fast path 2D texture */ if ((tex = _cogl_texture_2d_new_from_bitmap (bmp_handle, flags, - internal_format))) + internal_format, + NULL))) return tex; /* Otherwise create a sliced texture */ @@ -530,10 +541,15 @@ cogl_texture_new_from_foreign (GLuint gl_handle, y_pot_waste, format); else - return _cogl_texture_2d_new_from_foreign (gl_handle, - width, - height, - format); + { + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + return cogl_texture_2d_new_from_foreign (ctx, + gl_handle, + width, + height, + format, + NULL); + } } gboolean diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h index c8968e6af..288a25b2b 100644 --- a/cogl/cogl-texture.h +++ b/cogl/cogl-texture.h @@ -44,6 +44,33 @@ G_BEGIN_DECLS #define COGL_TEXTURE_MAX_WASTE 127 +/** + * COGL_TEXTURE_ERROR: + * + * #GError domain for texture errors. + * + * Since: 2.0 + * Stability: Unstable + */ +#define COGL_TEXTURE_ERROR (cogl_texture_error_quark ()) + + +/** + * CoglTextureError: + * @COGL_TEXTURE_ERROR_SIZE: Unsupported size + * + * Error codes that can be thrown when allocating textures. + * + * Since: 2.0 + * Stability: Unstable + */ +typedef enum { + COGL_TEXTURE_ERROR_SIZE, + COGL_TEXTURE_ERROR_FORMAT +} CoglTextureError; + +GQuark cogl_texture_error_quark (void); + /** * cogl_texture_new_with_size: * @width: width of texture in pixels. diff --git a/cogl/cogl.h b/cogl/cogl.h index d7dfc0715..d1da3ac8c 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -79,6 +79,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer; #include #include #include +#include #include #include #include diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c index 424910df2..412f8fe89 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -1799,10 +1799,11 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, else { glx_tex_pixmap->glx_tex = - _cogl_texture_2d_new_with_size (tex_pixmap->width, - tex_pixmap->height, - COGL_TEXTURE_NO_ATLAS, - texture_format); + cogl_texture_2d_new_with_size (ctx, + tex_pixmap->width, + tex_pixmap->height, + texture_format, + NULL); if (glx_tex_pixmap->glx_tex) COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p", diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 34df2ec1b..c737a8b4c 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -225,6 +225,16 @@ cogl_texture_set_region COGL_TEXTURE_MAX_WASTE +
+cogl-texture-2d +2D textures +CoglTexture2D +cogl_is_texture_2d +cogl_texture_2d_new_with_size +cogl_texture_2d_new_from_data +cogl_texture_2d_new_from_foreign +
+
cogl-texture-3d 3D textures