diff --git a/cogl-pango/cogl-pango-glyph-cache.c b/cogl-pango/cogl-pango-glyph-cache.c
index 14c8295a7..59cb5f430 100644
--- a/cogl-pango/cogl-pango-glyph-cache.c
+++ b/cogl-pango/cogl-pango-glyph-cache.c
@@ -214,6 +214,7 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
CoglPangoGlyphCacheValue *value)
{
CoglAtlasTexture *texture;
+ CoglError *ignore_error = NULL;
if (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SHARED_ATLAS))
return FALSE;
@@ -227,10 +228,14 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
value->draw_width,
value->draw_height,
COGL_TEXTURE_NONE,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE);
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ &ignore_error);
if (texture == NULL)
- return FALSE;
+ {
+ cogl_error_free (ignore_error);
+ return FALSE;
+ }
value->texture = COGL_TEXTURE (texture);
value->tx1 = 0;
diff --git a/cogl/cogl-atlas-texture-private.h b/cogl/cogl-atlas-texture-private.h
index 52fdf0693..670eea454 100644
--- a/cogl/cogl-atlas-texture-private.h
+++ b/cogl/cogl-atlas-texture-private.h
@@ -68,7 +68,8 @@ _cogl_atlas_texture_new_with_size (CoglContext *ctx,
int width,
int height,
CoglTextureFlags flags,
- CoglPixelFormat internal_format);
+ CoglPixelFormat internal_format,
+ CoglError **error);
void
_cogl_atlas_texture_add_reorganize_callback (CoglContext *ctx,
diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c
index c37908adb..7f62efceb 100644
--- a/cogl/cogl-atlas-texture.c
+++ b/cogl/cogl-atlas-texture.c
@@ -651,32 +651,60 @@ _cogl_atlas_texture_new_with_size (CoglContext *ctx,
int width,
int height,
CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+ CoglPixelFormat internal_format,
+ CoglError **error)
{
CoglAtlasTexture *atlas_tex;
- CoglAtlas *atlas;
- GSList *l;
/* Don't put textures in the atlas if the user has explicitly
requested to disable it */
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ATLAS)))
- return NULL;
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Atlasing disabled");
+ return NULL;
+ }
/* We can't put the texture in the atlas if there are any special
flags. This precludes textures with COGL_TEXTURE_NO_ATLAS and
COGL_TEXTURE_NO_SLICING from being atlased */
if (flags)
- return NULL;
+ {
+ /* XXX: This is a bit of an odd error; if we make this api
+ * public then this should probably be dealt with at a higher
+ * level, in cogl-auto-texture.c:cogl_texture_new_with_size().
+ */
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Usage constraints preclude atlasing texture");
+ return NULL;
+ }
/* We can't atlas zero-sized textures because it breaks the atlas
data structure */
if (width < 1 || height < 1)
- return NULL;
+ {
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_SIZE,
+ "1x1 atlas textures not supported");
+ return NULL;
+ }
/* If we can't use FBOs then it will be too slow to migrate textures
and we shouldn't use the atlas */
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
- return NULL;
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Atlasing disabled because migrations "
+ "would be too slow");
+ return NULL;
+ }
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height);
@@ -685,7 +713,10 @@ _cogl_atlas_texture_new_with_size (CoglContext *ctx,
{
COGL_NOTE (ATLAS, "Texture can not be added because the "
"format is unsupported");
-
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_FORMAT,
+ "Texture format unsuitable for atlasing");
return NULL;
}
@@ -703,12 +734,27 @@ _cogl_atlas_texture_new_with_size (CoglContext *ctx,
atlas_tex->sub_texture = NULL;
+ atlas_tex->format = internal_format;
+ atlas_tex->atlas = NULL;
+
+ return _cogl_atlas_texture_object_new (atlas_tex);
+}
+
+static CoglBool
+_cogl_atlas_texture_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglContext *ctx = tex->context;
+ CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
+ CoglAtlas *atlas;
+ GSList *l;
+
/* Look for an existing atlas that can hold the texture */
for (l = ctx->atlases; l; l = l->next)
/* Try to make some space in the atlas for the texture */
if (_cogl_atlas_reserve_space (atlas = l->data,
/* Add two pixels for the border */
- width + 2, height + 2,
+ tex->width + 2, tex->height + 2,
atlas_tex))
{
cogl_object_ref (atlas);
@@ -722,20 +768,23 @@ _cogl_atlas_texture_new_with_size (CoglContext *ctx,
COGL_NOTE (ATLAS, "Created new atlas for textures: %p", atlas);
if (!_cogl_atlas_reserve_space (atlas,
/* Add two pixels for the border */
- width + 2, height + 2,
+ tex->width + 2, tex->height + 2,
atlas_tex))
{
/* Ok, this means we really can't add it to the atlas */
cogl_object_unref (atlas);
- g_free (atlas_tex);
- return NULL;
+
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_NO_MEMORY,
+ "Not enough memory to atlas texture");
+ return FALSE;
}
}
- atlas_tex->format = internal_format;
atlas_tex->atlas = atlas;
- return _cogl_atlas_texture_object_new (atlas_tex);
+ return TRUE;
}
CoglAtlasTexture *
@@ -762,14 +811,14 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
atlas_tex = _cogl_atlas_texture_new_with_size (ctx,
bmp_width, bmp_height,
- flags, internal_format);
+ flags, internal_format,
+ error);
+ if (!atlas_tex)
+ return NULL;
- if (atlas_tex == NULL)
+ if (!cogl_texture_allocate (COGL_TEXTURE (atlas_tex), error))
{
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_UNSUPPORTED,
- "Texture type not compatible with atlas");
+ cogl_object_unref (atlas_tex);
return NULL;
}
@@ -839,6 +888,7 @@ static const CoglTextureVtable
cogl_atlas_texture_vtable =
{
FALSE, /* not primitive */
+ _cogl_atlas_texture_allocate,
_cogl_atlas_texture_set_region,
NULL, /* get_data */
_cogl_atlas_texture_foreach_sub_texture_in_region,
diff --git a/cogl/cogl-atlas.c b/cogl/cogl-atlas.c
index 62b11f850..d6c0e74f1 100644
--- a/cogl/cogl-atlas.c
+++ b/cogl/cogl-atlas.c
@@ -301,6 +301,9 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
tex = cogl_texture_2d_new_from_bitmap (clear_bmp,
atlas->texture_format,
&ignore_error);
+ if (!tex)
+ cogl_error_free (ignore_error);
+
cogl_object_unref (clear_bmp);
g_free (clear_data);
@@ -309,13 +312,15 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
{
tex = cogl_texture_2d_new_with_size (ctx,
width, height,
- atlas->texture_format,
- &ignore_error);
+ atlas->texture_format);
+ if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error))
+ {
+ cogl_error_free (ignore_error);
+ cogl_object_unref (tex);
+ tex = NULL;
+ }
}
- if (!tex)
- cogl_error_free (ignore_error);
-
return tex;
}
@@ -547,11 +552,18 @@ _cogl_atlas_copy_rectangle (CoglAtlas *atlas,
{
CoglTexture *tex;
CoglBlitData blit_data;
+ CoglError *ignore_error = NULL;
_COGL_GET_CONTEXT (ctx, NULL);
/* Create a new texture at the right size */
tex = cogl_texture_new_with_size (width, height, flags, format);
+ if (!cogl_texture_allocate (tex, &ignore_error))
+ {
+ cogl_error_free (ignore_error);
+ cogl_object_unref (tex);
+ return NULL;
+ }
/* Blit the data out of the atlas to the new texture. If FBOs
aren't available this will end up having to copy the entire
diff --git a/cogl/cogl-auto-texture.c b/cogl/cogl-auto-texture.c
index bcbb1d0c0..ff7673b94 100644
--- a/cogl/cogl-auto-texture.c
+++ b/cogl/cogl-auto-texture.c
@@ -47,12 +47,13 @@
#include "cogl-texture-2d-gl.h"
CoglTexture *
-cogl_texture_new_with_size (unsigned int width,
- unsigned int height,
+cogl_texture_new_with_size (unsigned int width,
+ unsigned int height,
CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+ CoglPixelFormat internal_format)
{
CoglTexture *tex;
+ CoglError *skip_error = NULL;
_COGL_GET_CONTEXT (ctx, NULL);
@@ -63,8 +64,18 @@ cogl_texture_new_with_size (unsigned int width,
/* First try creating a fast-path non-sliced texture */
tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
width, height,
- internal_format,
- NULL));
+ internal_format));
+
+ /* TODO: instead of allocating storage here it would be better
+ * if we had some api that let us just check that the size is
+ * supported by the hardware so storage could be allocated
+ * lazily when uploading data. */
+ if (!cogl_texture_allocate (tex, &skip_error))
+ {
+ cogl_error_free (skip_error);
+ cogl_object_unref (tex);
+ tex = NULL;
+ }
}
else
tex = NULL;
@@ -83,8 +94,7 @@ cogl_texture_new_with_size (unsigned int width,
width,
height,
max_waste,
- internal_format,
- NULL));
+ internal_format));
}
return tex;
diff --git a/cogl/cogl-blit.c b/cogl/cogl-blit.c
index 5cb5ea4c3..ea457b958 100644
--- a/cogl/cogl-blit.c
+++ b/cogl/cogl-blit.c
@@ -49,16 +49,15 @@ _cogl_blit_texture_render_begin (CoglBlitData *data)
CoglFramebuffer *fb;
CoglPipeline *pipeline;
unsigned int dst_width, dst_height;
+ CoglError *ignore_error = NULL;
offscreen = _cogl_offscreen_new_to_texture_full
(data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
- if (offscreen == NULL)
- return FALSE;
-
fb = COGL_FRAMEBUFFER (offscreen);
- if (!cogl_framebuffer_allocate (fb, NULL))
+ if (!cogl_framebuffer_allocate (fb, &ignore_error))
{
+ cogl_error_free (ignore_error);
cogl_object_unref (fb);
return FALSE;
}
@@ -148,6 +147,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
CoglContext *ctx = data->src_tex->context;
CoglOffscreen *dst_offscreen = NULL, *src_offscreen = NULL;
CoglFramebuffer *dst_fb, *src_fb;
+ CoglError *ignore_error = NULL;
/* We can only blit between FBOs if both textures are the same
format and the blit framebuffer extension is supported */
@@ -158,24 +158,25 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
dst_offscreen = _cogl_offscreen_new_to_texture_full
(data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
- if (dst_offscreen == NULL)
- return FALSE;
dst_fb = COGL_FRAMEBUFFER (dst_offscreen);
- if (!cogl_framebuffer_allocate (dst_fb, NULL))
- goto error;
+ if (!cogl_framebuffer_allocate (dst_fb, &ignore_error))
+ {
+ cogl_error_free (ignore_error);
+ goto error;
+ }
src_offscreen= _cogl_offscreen_new_to_texture_full
(data->src_tex,
COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
0 /* level */);
- if (src_offscreen == NULL)
- goto error;
-
src_fb = COGL_FRAMEBUFFER (src_offscreen);
- if (!cogl_framebuffer_allocate (src_fb, NULL))
- goto error;
+ if (!cogl_framebuffer_allocate (src_fb, &ignore_error))
+ {
+ cogl_error_free (ignore_error);
+ goto error;
+ }
data->src_fb = src_fb;
data->dest_fb = dst_fb;
@@ -220,6 +221,7 @@ _cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data)
{
CoglOffscreen *offscreen;
CoglFramebuffer *fb;
+ CoglError *ignore_error = NULL;
/* This will only work if the target texture is a CoglTexture2D */
if (!cogl_is_texture_2d (data->dst_tex))
@@ -228,12 +230,10 @@ _cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data)
offscreen = _cogl_offscreen_new_to_texture_full
(data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
- if (offscreen == NULL)
- return FALSE;
-
fb = COGL_FRAMEBUFFER (offscreen);
- if (!cogl_framebuffer_allocate (fb, NULL))
+ if (!cogl_framebuffer_allocate (fb, &ignore_error))
{
+ cogl_error_free (ignore_error);
cogl_object_unref (fb);
return FALSE;
}
diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h
index e46bec8fe..0c42e716c 100644
--- a/cogl/cogl-driver.h
+++ b/cogl/cogl-driver.h
@@ -138,14 +138,11 @@ struct _CoglDriverVtable
void
(* texture_2d_init) (CoglTexture2D *tex_2d);
- /* Instantiates a new CoglTexture2D object with un-initialized
- * storage for a given size and internal format */
- CoglTexture2D *
- (* texture_2d_new_with_size) (CoglContext *ctx,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglError **error);
+ /* Allocates (uninitialized) storage for the given texture according
+ * to the configured size and format of the texture */
+ CoglBool
+ (* texture_2d_allocate) (CoglTexture *tex,
+ CoglError **error);
/* Instantiates a new CoglTexture2D object with storage initialized
* with the contents of the given bitmap, using the specified
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 7664f7c08..a88c59181 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -306,7 +306,7 @@ _cogl_free_framebuffer_stack (GSList *stack);
CoglOffscreen *
_cogl_offscreen_new_to_texture_full (CoglTexture *texture,
CoglOffscreenFlags create_flags,
- unsigned int level);
+ int level);
/*
* _cogl_push_framebuffers:
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 148e7f461..8b95796f3 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -49,6 +49,7 @@
#include "cogl-primitives-private.h"
#include "cogl-path-private.h"
#include "cogl-error-private.h"
+#include "cogl-texture-gl-private.h"
typedef struct _CoglFramebufferStackEntry
{
@@ -569,48 +570,24 @@ _cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer)
CoglOffscreen *
_cogl_offscreen_new_to_texture_full (CoglTexture *texture,
CoglOffscreenFlags create_flags,
- unsigned int level)
+ int level)
{
CoglContext *ctx = texture->context;
CoglOffscreen *offscreen;
CoglFramebuffer *fb;
int level_width;
int level_height;
- int i;
CoglOffscreen *ret;
- if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
- return NULL;
+ _COGL_RETURN_VAL_IF_FAIL (cogl_is_texture (texture), NULL);
+ _COGL_RETURN_VAL_IF_FAIL (level < _cogl_texture_get_n_levels (texture),
+ NULL);
- /* Make texture is a valid texture object */
- if (!cogl_is_texture (texture))
- return NULL;
-
- /* The texture must not be sliced */
- if (cogl_texture_is_sliced (texture))
- return NULL;
-
- /* Calculate the size of the texture at this mipmap level to ensure
- that it's a valid level */
- level_width = cogl_texture_get_width (texture);
- level_height = cogl_texture_get_height (texture);
-
- for (i = 0; i < level; i++)
- {
- /* If neither dimension can be further divided then the level is
- invalid */
- if (level_width == 1 && level_height == 1)
- {
- g_warning ("Invalid texture level passed to "
- "_cogl_offscreen_new_to_texture_full");
- return NULL;
- }
-
- if (level_width > 1)
- level_width >>= 1;
- if (level_height > 1)
- level_height >>= 1;
- }
+ _cogl_texture_get_level_size (texture,
+ level,
+ &level_width,
+ &level_height,
+ NULL);
offscreen = g_new0 (CoglOffscreen, 1);
offscreen->texture = cogl_object_ref (texture);
@@ -688,7 +665,29 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
else
{
CoglContext *ctx = framebuffer->context;
- if (!ctx->driver_vtable->offscreen_allocate (COGL_OFFSCREEN (framebuffer), error))
+ CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer);
+
+ if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
+ {
+ _cogl_set_error (error, COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Offscreen framebuffers not supported by system");
+ return FALSE;
+ }
+
+ if (cogl_texture_is_sliced (offscreen->texture))
+ {
+ _cogl_set_error (error, COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Can't create offscreen framebuffer from "
+ "sliced texture");
+ return FALSE;
+ }
+
+ if (!cogl_texture_allocate (offscreen->texture, error))
+ return FALSE;
+
+ if (!ctx->driver_vtable->offscreen_allocate (offscreen, error))
return FALSE;
}
diff --git a/cogl/cogl-sub-texture.c b/cogl/cogl-sub-texture.c
index 18447f83e..9a308be57 100644
--- a/cogl/cogl-sub-texture.c
+++ b/cogl/cogl-sub-texture.c
@@ -259,6 +259,15 @@ cogl_sub_texture_new (CoglContext *ctx,
return _cogl_sub_texture_object_new (sub_tex);
}
+static CoglBool
+_cogl_sub_texture_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
+
+ return cogl_texture_allocate (sub_tex->full_texture, error);
+}
+
CoglTexture *
cogl_sub_texture_get_parent (CoglSubTexture *sub_texture)
{
@@ -433,6 +442,7 @@ static const CoglTextureVtable
cogl_sub_texture_vtable =
{
FALSE, /* not primitive */
+ _cogl_sub_texture_allocate,
_cogl_sub_texture_set_region,
NULL, /* get_data */
_cogl_sub_texture_foreach_sub_texture_in_region,
diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h
index 3ae8ded3e..12e582024 100644
--- a/cogl/cogl-texture-2d-private.h
+++ b/cogl/cogl-texture-2d-private.h
@@ -39,7 +39,7 @@ struct _CoglTexture2D
/* The internal format of the GL texture represented as a
CoglPixelFormat */
- CoglPixelFormat format;
+ CoglPixelFormat internal_format;
CoglBool auto_mipmap;
CoglBool mipmaps_dirty;
diff --git a/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl-texture-2d-sliced-private.h
index 5bc4e5f83..fbfd1982b 100644
--- a/cogl/cogl-texture-2d-sliced-private.h
+++ b/cogl/cogl-texture-2d-sliced-private.h
@@ -38,6 +38,7 @@ struct _CoglTexture2DSliced
GArray *slice_y_spans;
GArray *slice_textures;
int max_waste;
+ CoglPixelFormat internal_format;
};
CoglTexture2DSliced *
diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c
index 51997bd3a..ef9d72d9f 100644
--- a/cogl/cogl-texture-2d-sliced.c
+++ b/cogl/cogl-texture-2d-sliced.c
@@ -656,20 +656,18 @@ _cogl_texture_2d_sliced_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
}
static CoglBool
-_cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
- CoglTexture2DSliced *tex_2ds,
- int width, int height,
- CoglPixelFormat format)
+_cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
+ CoglTexture2DSliced *tex_2ds,
+ int width,
+ int height,
+ int max_waste,
+ CoglPixelFormat format,
+ CoglError **error)
{
int max_width;
int max_height;
- CoglTexture2D **slice_textures;
int n_x_slices;
int n_y_slices;
- int n_slices;
- int x, y;
- CoglSpan *x_span;
- CoglSpan *y_span;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
@@ -697,7 +695,7 @@ _cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
&gl_type);
/* Negative number means no slicing forced by the user */
- if (tex_2ds->max_waste <= -1)
+ if (max_waste <= -1)
{
CoglSpan span;
@@ -710,6 +708,13 @@ _cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
max_width,
max_height))
{
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_SIZE,
+ "Sliced texture size of %d x %d not possible "
+ "with max waste set to -1",
+ width,
+ height);
return FALSE;
}
@@ -753,16 +758,25 @@ _cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
max_height /= 2;
if (max_width == 0 || max_height == 0)
- return FALSE;
+ {
+ /* Maybe it would be ok to just g_warn_if_reached() for this
+ * codepath */
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_SIZE,
+ "No suitable slice geometry found");
+ return FALSE;
+
+ }
}
/* Determine the slices required to cover the bitmap area */
n_x_slices = slices_for_size (width,
- max_width, tex_2ds->max_waste,
+ max_width, max_waste,
NULL);
n_y_slices = slices_for_size (height,
- max_height, tex_2ds->max_waste,
+ max_height, max_waste,
NULL);
/* Init span arrays with reserved size */
@@ -776,64 +790,20 @@ _cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
/* Fill span arrays with info */
slices_for_size (width,
- max_width, tex_2ds->max_waste,
+ max_width, max_waste,
tex_2ds->slice_x_spans);
slices_for_size (height,
- max_height, tex_2ds->max_waste,
+ max_height, max_waste,
tex_2ds->slice_y_spans);
}
- /* Init and resize GL handle array */
- n_slices = n_x_slices * n_y_slices;
-
- tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglTexture2D *),
- n_slices);
-
- g_array_set_size (tex_2ds->slice_textures, n_slices);
-
- slice_textures = (CoglTexture2D **) tex_2ds->slice_textures->data;
-
- /* Init each GL texture object */
- for (y = 0; y < n_y_slices; ++y)
- {
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y);
-
- for (x = 0; x < n_x_slices; ++x)
- {
- CoglError *error = NULL;
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x);
-
- COGL_NOTE (SLICING, "CREATE SLICE (%d,%d)\tsize (%d,%d)",
- x, y,
- (int)(x_span->size - x_span->waste),
- (int)(y_span->size - y_span->waste));
-
- slice_textures[y * n_x_slices + x] =
- cogl_texture_2d_new_with_size (ctx, x_span->size, y_span->size,
- format, &error);
- if (!slice_textures[y * n_x_slices + x])
- {
- g_array_set_size (tex_2ds->slice_textures, y * n_x_slices + x);
- cogl_error_free (error);
- return FALSE;
- }
- }
- }
-
return TRUE;
}
static void
_cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds)
{
- if (tex_2ds->slice_x_spans != NULL)
- g_array_free (tex_2ds->slice_x_spans, TRUE);
-
- if (tex_2ds->slice_y_spans != NULL)
- g_array_free (tex_2ds->slice_y_spans, TRUE);
-
if (tex_2ds->slice_textures != NULL)
{
int i;
@@ -854,6 +824,12 @@ _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
{
_cogl_texture_2d_sliced_slices_free (tex_2ds);
+ if (tex_2ds->slice_x_spans != NULL)
+ g_array_free (tex_2ds->slice_x_spans, TRUE);
+
+ if (tex_2ds->slice_y_spans != NULL)
+ g_array_free (tex_2ds->slice_y_spans, TRUE);
+
/* Chain up */
_cogl_texture_free (COGL_TEXTURE (tex_2ds));
}
@@ -863,76 +839,148 @@ _cogl_texture_2d_sliced_init_base (CoglContext *ctx,
CoglTexture2DSliced *tex_2ds,
int width,
int height,
- CoglPixelFormat internal_format)
+ int max_waste,
+ CoglPixelFormat internal_format,
+ CoglError **error)
{
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_2d_sliced_vtable);
- tex_2ds->slice_x_spans = NULL;
- tex_2ds->slice_y_spans = NULL;
- tex_2ds->slice_textures = NULL;
+ tex_2ds->max_waste = max_waste;
+ tex_2ds->internal_format = internal_format;
- /* Create slices for the given format and size */
- if (!_cogl_texture_2d_sliced_slices_create (ctx,
- tex_2ds,
- width,
- height,
- internal_format))
- return FALSE;
-
- return TRUE;
+ return _cogl_texture_2d_sliced_setup_spans (ctx, tex_2ds,
+ width, height,
+ max_waste,
+ internal_format,
+ error);
}
CoglTexture2DSliced *
cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
- unsigned int width,
- unsigned int height,
+ int width,
+ int height,
int max_waste,
- CoglPixelFormat internal_format,
- CoglError **error)
+ CoglPixelFormat internal_format)
{
- CoglTexture2DSliced *tex_2ds;
+ CoglTexture2DSliced *tex_2ds;
+ CoglError *ignore_error = NULL;
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
/* Init texture with empty bitmap */
- tex_2ds = g_new (CoglTexture2DSliced, 1);
-
- tex_2ds->max_waste = max_waste;
+ tex_2ds = g_new0 (CoglTexture2DSliced, 1);
if (!_cogl_texture_2d_sliced_init_base (ctx,
tex_2ds,
width, height,
- internal_format))
+ max_waste,
+ internal_format,
+ &ignore_error))
{
- _cogl_texture_2d_sliced_free (tex_2ds);
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_NO_MEMORY,
- "Not enough memory to allocate texture slices");
- return NULL;
+ /* In this case we failed to find any suitable slicing geometry
+ * for the given texture size.
+ *
+ * We don't need to do anything with the error here since it
+ * will be picked up on later when trying to allocate the
+ * texture.
+ */
+ cogl_error_free (ignore_error);
}
+ /* NB: We need to be sure that cogl_texture_is_sliced() will work
+ * correctly before returning since
+ * cogl_framebuffer_allocate() uses this api to determine
+ * if a texture can be rendered to which may be before the
+ * slices have been allocated.
+ */
+
return _cogl_texture_2d_sliced_object_new (tex_2ds);
}
+static CoglBool
+_cogl_texture_2d_sliced_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglContext *ctx = tex->context;
+ CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
+ int n_x_slices;
+ int n_y_slices;
+ int n_slices;
+ int x, y;
+ CoglPixelFormat format = tex_2ds->internal_format;
+ CoglSpan *x_span;
+ CoglSpan *y_span;
+
+ if (!tex_2ds->slice_x_spans || !tex_2ds->slice_y_spans)
+ {
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_SIZE,
+ "Couldn't find suitable slicing geometry "
+ "for given size");
+ return FALSE;
+ }
+
+ n_x_slices = tex_2ds->slice_x_spans->len;
+ n_y_slices = tex_2ds->slice_y_spans->len;
+ n_slices = n_x_slices * n_y_slices;
+
+ tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE,
+ sizeof (CoglTexture2D *),
+ n_slices);
+
+ g_array_set_size (tex_2ds->slice_textures, n_slices);
+
+ /* Allocate each slice */
+ for (y = 0; y < n_y_slices; ++y)
+ {
+ y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y);
+
+ for (x = 0; x < n_x_slices; ++x)
+ {
+ CoglTexture *slice;
+
+ x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x);
+
+ COGL_NOTE (SLICING, "CREATE SLICE (%d,%d)\tsize (%d,%d)",
+ x, y,
+ (int)(x_span->size - x_span->waste),
+ (int)(y_span->size - y_span->waste));
+
+ slice = COGL_TEXTURE (
+ cogl_texture_2d_new_with_size (ctx,
+ x_span->size, y_span->size,
+ format));
+ g_array_append_val (tex_2ds->slice_textures, slice);
+ if (!cogl_texture_allocate (slice, error))
+ {
+ _cogl_texture_2d_sliced_slices_free (tex_2ds);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglError **error)
{
+ CoglContext *ctx;
CoglTexture2DSliced *tex_2ds;
- CoglBitmap *dst_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- int width, height;
- CoglContext *ctx;
- int i;
+ CoglBitmap *dst_bmp;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+ int width, height, max_waste;
+ int i;
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
@@ -945,9 +993,9 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
if (flags & COGL_TEXTURE_NO_SLICING)
- tex_2ds->max_waste = -1;
+ max_waste = -1;
else
- tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
+ max_waste = COGL_TEXTURE_MAX_WASTE;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
@@ -962,10 +1010,17 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
return NULL;
}
+ /* NB: we may fail to find any suitable slicing geometry for the
+ * given texture size. */
if (!_cogl_texture_2d_sliced_init_base (ctx,
tex_2ds,
width, height,
- internal_format))
+ max_waste,
+ internal_format,
+ error))
+ goto error;
+
+ if (!cogl_texture_allocate (COGL_TEXTURE (tex_2ds), error))
goto error;
if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
@@ -1054,6 +1109,7 @@ _cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx,
&cogl_texture_2d_sliced_vtable);
tex_2ds->max_waste = 0;
+ tex_2ds->internal_format = format;
/* Create slice arrays */
tex_2ds->slice_x_spans =
@@ -1081,6 +1137,8 @@ _cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx,
g_array_append_val (tex_2ds->slice_textures, tex_2d);
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_2ds), TRUE);
+
return _cogl_texture_2d_sliced_object_new (tex_2ds);
}
@@ -1112,13 +1170,23 @@ _cogl_texture_2d_sliced_is_sliced (CoglTexture *tex)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- if (tex_2ds->slice_textures == NULL)
+ /* It's possible that we failed to calculate valid slicing geometry
+ * when initializing the texture due to the max_waste size and in
+ * this case we report that the texture is not sliced.
+ *
+ * In this case though we know that we will be throwing an error
+ * when this texture is later allocated so it shouldn't really
+ * matter what we report here since the texture won't be used in the
+ * end.
+ */
+ if (!tex_2ds->slice_x_spans || !tex_2ds->slice_y_spans)
return FALSE;
- if (tex_2ds->slice_textures->len <= 1)
+ if (tex_2ds->slice_x_spans->len != 1 ||
+ tex_2ds->slice_y_spans->len != 1)
+ return TRUE;
+ else
return FALSE;
-
- return TRUE;
}
static CoglBool
@@ -1223,12 +1291,10 @@ _cogl_texture_2d_sliced_gl_flush_legacy_texobj_filters (CoglTexture *tex,
GLenum mag_filter)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglTexture2D *slice_tex;
- int i;
+ CoglTexture2D *slice_tex;
+ int i;
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
+ _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL);
/* Apply new filters to every slice. The slice texture itself should
cache the value and avoid resubmitting the same filter value to
@@ -1246,11 +1312,9 @@ _cogl_texture_2d_sliced_pre_paint (CoglTexture *tex,
CoglTexturePrePaintFlags flags)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- int i;
+ int i;
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
+ _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL);
/* Pass the pre-paint on to every slice */
for (i = 0; i < tex_2ds->slice_textures->len; i++)
@@ -1267,9 +1331,7 @@ _cogl_texture_2d_sliced_ensure_non_quad_rendering (CoglTexture *tex)
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
int i;
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
+ _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL);
/* Pass the call on to every slice */
for (i = 0; i < tex_2ds->slice_textures->len; i++)
@@ -1327,15 +1389,8 @@ static CoglPixelFormat
_cogl_texture_2d_sliced_get_format (CoglTexture *tex)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglTexture2D *slice_tex;
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return 0;
-
- /* Pass the call on to the first slice */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0);
- return cogl_texture_get_format (COGL_TEXTURE (slice_tex));
+ return tex_2ds->internal_format;
}
static GLenum
@@ -1344,9 +1399,8 @@ _cogl_texture_2d_sliced_get_gl_format (CoglTexture *tex)
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
CoglTexture2D *slice_tex;
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return 0;
+ /* Assert that we've allocated our slices at this point */
+ cogl_texture_allocate (tex, NULL); /* (abort on error) */
/* Pass the call on to the first slice */
slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0);
@@ -1363,6 +1417,7 @@ static const CoglTextureVtable
cogl_texture_2d_sliced_vtable =
{
FALSE, /* not primitive */
+ _cogl_texture_2d_sliced_allocate,
_cogl_texture_2d_sliced_set_region,
NULL, /* get_data */
_cogl_texture_2d_sliced_foreach_sub_texture_in_region,
diff --git a/cogl/cogl-texture-2d-sliced.h b/cogl/cogl-texture-2d-sliced.h
index 8d2cc4b90..e26157e6b 100644
--- a/cogl/cogl-texture-2d-sliced.h
+++ b/cogl/cogl-texture-2d-sliced.h
@@ -70,32 +70,48 @@ typedef struct _CoglTexture2DSliced CoglTexture2DSliced;
* @width: The virtual width of your sliced texture.
* @height: The virtual height of your sliced texture.
* @max_waste: The threshold of how wide a strip of wasted texels
- * are allowed in the non-power-of-two textures before
- * they must be sliced to reduce the amount of waste.
+ * are allowed along the right and bottom textures before
+ * they must be sliced to reduce the amount of waste. A
+ * negative can be passed to disable slicing.
* @internal_format: The format of the texture
- * @error: A #CoglError for exceptions.
*
* Creates a #CoglTexture2DSliced that may internally be comprised of
- * 1 or more #CoglTexture2D textures with power-of-two sizes.
- * @max_waste is used as a threshold for recursively slicing the
- * right-most or bottom-most slices into smaller power-of-two sizes
- * until the wasted padding at the bottom and right of the
- * power-of-two textures is less than specified.
+ * 1 or more #CoglTexture2D textures depending on GPU limitations.
+ * For example if the GPU only supports power-of-two sized textures
+ * then a sliced texture will turn a non-power-of-two size into a
+ * combination of smaller power-of-two sized textures. If the
+ * requested texture size is larger than is supported by the hardware
+ * then the texture will be sliced into smaller textures that can be
+ * accessed by the hardware.
*
- * Returns: A newly allocated #CoglTexture2DSliced or if there was
- * an error allocating any of the internal slices %NULL is
- * returned and @error is updated.
+ * @max_waste is used as a threshold for recursively slicing the
+ * right-most or bottom-most slices into smaller sizes until the
+ * wasted padding at the bottom and right of the textures is less than
+ * specified. A negative @max_waste will disable slicing.
+ *
+ * The storage for the texture is not allocated before this function
+ * returns. You can call cogl_texture_allocate() to explicitly
+ * allocate the underlying storage or let Cogl automatically allocate
+ * storage lazily.
+ *
+ * It's possible for the allocation of a sliced texture to fail
+ * later due to impossible slicing constraints if a negative
+ * @max_waste value is given. If the given virtual texture size size
+ * is larger than is supported by the hardware but slicing is disabled
+ * the texture size would be too large to handle.
+ *
+ * Returns: A new #CoglTexture2DSliced object with no storage
+ * allocated yet.
*
* Since: 1.10
* Stability: unstable
*/
CoglTexture2DSliced *
cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
- unsigned int width,
- unsigned int height,
+ int width,
+ int height,
int max_waste,
- CoglPixelFormat internal_format,
- CoglError **error);
+ CoglPixelFormat internal_format);
/**
* cogl_is_texture_2d_sliced:
diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index 74ab1ab83..7492e128e 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -119,7 +119,7 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
tex_2d->is_foreign = FALSE;
- tex_2d->format = internal_format;
+ tex_2d->internal_format = internal_format;
ctx->driver_vtable->texture_2d_init (tex_2d);
@@ -130,27 +130,23 @@ CoglTexture2D *
cogl_texture_2d_new_with_size (CoglContext *ctx,
int width,
int height,
- CoglPixelFormat internal_format,
- CoglError **error)
+ CoglPixelFormat internal_format)
{
/* 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_2d_can_create (ctx, width, height, internal_format))
- {
- _cogl_set_error (error, COGL_TEXTURE_ERROR,
- COGL_TEXTURE_ERROR_SIZE,
- "Failed to create texture 2d due to size/format"
- " constraints");
- return NULL;
- }
+ return _cogl_texture_2d_create_base (ctx,
+ width, height,
+ internal_format);
+}
- return ctx->driver_vtable->texture_2d_new_with_size (ctx,
- width,
- height,
- internal_format,
- error);
+static CoglBool
+_cogl_texture_2d_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglContext *ctx = tex->context;
+ return ctx->driver_vtable->texture_2d_allocate (tex, error);
}
CoglTexture2D *
@@ -178,7 +174,6 @@ cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
"Failed to create texture 2d due to size/format"
" constraints");
return NULL;
-
}
return ctx->driver_vtable->texture_2d_new_from_bitmap (bmp,
@@ -350,7 +345,11 @@ _cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *tex_2d,
int dst_y,
int level)
{
- CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+ CoglTexture *tex = COGL_TEXTURE (tex_2d);
+ CoglContext *ctx = tex->context;
+
+ /* Assert that the storage for this texture has been allocated */
+ cogl_texture_allocate (tex, NULL); /* (abort on error) */
ctx->driver_vtable->texture_2d_copy_from_framebuffer (tex_2d,
src_x,
@@ -525,7 +524,7 @@ _cogl_texture_2d_get_data (CoglTexture *tex,
static CoglPixelFormat
_cogl_texture_2d_get_format (CoglTexture *tex)
{
- return COGL_TEXTURE_2D (tex)->format;
+ return COGL_TEXTURE_2D (tex)->internal_format;
}
static GLenum
@@ -550,6 +549,7 @@ static const CoglTextureVtable
cogl_texture_2d_vtable =
{
TRUE, /* primitive */
+ _cogl_texture_2d_allocate,
_cogl_texture_2d_set_region,
_cogl_texture_2d_get_data,
NULL, /* foreach_sub_texture_in_region */
diff --git a/cogl/cogl-texture-2d.h b/cogl/cogl-texture-2d.h
index fcd86f77a..5a5ff2f54 100644
--- a/cogl/cogl-texture-2d.h
+++ b/cogl/cogl-texture-2d.h
@@ -74,7 +74,6 @@ cogl_is_texture_2d (void *object);
* @width: Width of the texture to allocate
* @height: Height of the texture to allocate
* @internal_format: The format of the texture
- * @error: A #CoglError for exceptions
*
* Allocates a low-level #CoglTexture2D texture that your GPU can
* texture from directly. This is unlike sliced textures for example
@@ -82,15 +81,18 @@ cogl_is_texture_2d (void *object);
* textures where Cogl has to modify texture coordinates before they
* may be used by the GPU.
*
+ * The storage for the texture is not allocated before this function
+ * returns. You can call cogl_texture_allocate() to explicitly
+ * allocate the underlying storage or preferably let Cogl
+ * automatically allocate storage lazily when it may know more about
+ * how the texture is being used and can optimize how it is allocated.
+ *
* 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_ID_TEXTURE_NPOT feature via
* cogl_has_feature().
*
- * 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.
+ * Returns: A new #CoglTexture2D object with no storage yet allocated.
*
* Since: 2.0
*/
@@ -98,8 +100,7 @@ CoglTexture2D *
cogl_texture_2d_new_with_size (CoglContext *ctx,
int width,
int height,
- CoglPixelFormat internal_format,
- CoglError **error);
+ CoglPixelFormat internal_format);
/**
* cogl_texture_2d_new_from_data:
diff --git a/cogl/cogl-texture-3d-private.h b/cogl/cogl-texture-3d-private.h
index 88f702665..22e572ebd 100644
--- a/cogl/cogl-texture-3d-private.h
+++ b/cogl/cogl-texture-3d-private.h
@@ -36,7 +36,7 @@ struct _CoglTexture3D
/* The internal format of the texture represented as a
CoglPixelFormat */
- CoglPixelFormat format;
+ CoglPixelFormat internal_format;
int depth;
CoglBool auto_mipmap;
CoglBool mipmaps_dirty;
diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c
index ab7c7e1a7..b40448a7f 100644
--- a/cogl/cogl-texture-3d.c
+++ b/cogl/cogl-texture-3d.c
@@ -95,7 +95,8 @@ _cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
static void
_cogl_texture_3d_free (CoglTexture3D *tex_3d)
{
- _cogl_delete_gl_texture (tex_3d->gl_texture);
+ if (tex_3d->gl_texture)
+ _cogl_delete_gl_texture (tex_3d->gl_texture);
/* Chain up */
_cogl_texture_free (COGL_TEXTURE (tex_3d));
@@ -122,6 +123,8 @@ _cogl_texture_3d_create_base (CoglContext *ctx,
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_3d_vtable);
+ tex_3d->gl_texture = 0;
+
tex_3d->depth = depth;
tex_3d->mipmaps_dirty = TRUE;
tex_3d->auto_mipmap = TRUE;
@@ -135,7 +138,7 @@ _cogl_texture_3d_create_base (CoglContext *ctx,
tex_3d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
tex_3d->gl_legacy_texobj_wrap_mode_p = GL_FALSE;
- tex_3d->format = internal_format;
+ tex_3d->internal_format = internal_format;
return _cogl_texture_3d_object_new (tex_3d);
}
@@ -206,54 +209,66 @@ cogl_texture_3d_new_with_size (CoglContext *ctx,
int width,
int height,
int depth,
- CoglPixelFormat internal_format,
- CoglError **error)
+ CoglPixelFormat internal_format)
{
- CoglTexture3D *tex_3d;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- GLenum gl_error;
-
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
+ return _cogl_texture_3d_create_base (ctx,
+ width, height, depth,
+ internal_format);
+}
+
+static CoglBool
+_cogl_texture_3d_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglContext *ctx = tex->context;
+ CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+ GLenum gl_error;
+ GLenum gl_texture;
+
if (!_cogl_texture_3d_can_create (ctx,
- width, height, depth,
- internal_format,
+ tex->width,
+ tex->height,
+ tex_3d->depth,
+ tex_3d->internal_format,
error))
- return NULL;
+ return FALSE;
- internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
- internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
+ ctx->driver_vtable->pixel_format_to_gl (ctx,
+ tex_3d->internal_format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type);
- tex_3d = _cogl_texture_3d_create_base (ctx,
- width, height, depth,
- internal_format);
-
- tex_3d->gl_texture =
- ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
+ gl_texture =
+ ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, tex_3d->internal_format);
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
+ gl_texture,
FALSE);
/* Clear any GL errors */
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
;
ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
- width, height, depth, 0, gl_format, gl_type, NULL);
+ tex->width, tex->height, tex_3d->depth,
+ 0, gl_format, gl_type, NULL);
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
{
- cogl_object_unref (tex_3d);
- return NULL;
+ GE( ctx, glDeleteTextures (1, &gl_texture) );
+ return FALSE;
}
- return tex_3d;
+ tex_3d->gl_texture = gl_texture;
+ tex_3d->gl_format = gl_intformat;
+
+ return TRUE;
}
CoglTexture3D *
@@ -354,6 +369,8 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
cogl_object_unref (dst_bmp);
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_3d), TRUE);
+
return tex_3d;
}
@@ -628,7 +645,7 @@ _cogl_texture_3d_get_data (CoglTexture *tex,
static CoglPixelFormat
_cogl_texture_3d_get_format (CoglTexture *tex)
{
- return COGL_TEXTURE_3D (tex)->format;
+ return COGL_TEXTURE_3D (tex)->internal_format;
}
static GLenum
@@ -647,6 +664,7 @@ static const CoglTextureVtable
cogl_texture_3d_vtable =
{
TRUE, /* primitive */
+ _cogl_texture_3d_allocate,
_cogl_texture_3d_set_region,
_cogl_texture_3d_get_data,
NULL, /* foreach_sub_texture_in_region */
diff --git a/cogl/cogl-texture-3d.h b/cogl/cogl-texture-3d.h
index c2700efa4..0483d47fa 100644
--- a/cogl/cogl-texture-3d.h
+++ b/cogl/cogl-texture-3d.h
@@ -55,18 +55,23 @@ typedef struct _CoglTexture3D CoglTexture3D;
* @depth: depth of the texture in pixels.
* @internal_format: the #CoglPixelFormat to use for the GPU
* storage of the texture.
- * @error: A CoglError return location.
*
- * Creates a new Cogl 3D texture with the specified dimensions and
- * pixel format.
+ * Creates a new #CoglTexture3D texture with the specified dimensions
+ * and pixel format.
*
- * Note that this function will throw a #CoglError if
- * %COGL_FEATURE_ID_TEXTURE_3D is not advertised. It can also fail if the
- * requested dimensions are not supported by the GPU.
+ * The storage for the texture is not allocated before this function
+ * returns. You can call cogl_texture_allocate() to explicitly
+ * allocate the underlying storage or preferably let Cogl
+ * automatically allocate storage lazily when it may know more about
+ * how the texture is going to be used and can optimize how it is
+ * allocated.
*
- * Return value: a new #CoglTexture3D object or
- * %NULL on failure and an exception will be returned
- * in @error.
+ * This texture will fail to allocate later if
+ * %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also
+ * fail if the requested dimensions are not supported by the
+ * GPU.
+ *
+ * Returns: A new #CoglTexture3D object with no storage yet allocated.
* Since: 1.10
* Stability: Unstable
*/
@@ -75,8 +80,7 @@ cogl_texture_3d_new_with_size (CoglContext *context,
int width,
int height,
int depth,
- CoglPixelFormat internal_format,
- CoglError **error);
+ CoglPixelFormat internal_format);
/**
* cogl_texture_3d_new_from_data:
diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h
index 6ff48605b..7e70e5efa 100644
--- a/cogl/cogl-texture-private.h
+++ b/cogl/cogl-texture-private.h
@@ -60,6 +60,9 @@ struct _CoglTextureVtable
CoglBool is_primitive;
+ CoglBool (* allocate) (CoglTexture *tex,
+ CoglError **error);
+
/* This should update the specified sub region of the texture with a
sub region of the given bitmap. The bitmap is not converted
before being passed so the implementation is expected to call
@@ -144,6 +147,7 @@ struct _CoglTexture
int max_level;
int width;
int height;
+ CoglBool allocated;
const CoglTextureVtable *vtable;
};
@@ -321,4 +325,8 @@ _cogl_texture_get_level_size (CoglTexture *texture,
int *height,
int *depth);
+void
+_cogl_texture_set_allocated (CoglTexture *texture,
+ CoglBool allocated);
+
#endif /* __COGL_TEXTURE_PRIVATE_H */
diff --git a/cogl/cogl-texture-rectangle-private.h b/cogl/cogl-texture-rectangle-private.h
index e6592a547..fe4dfe834 100644
--- a/cogl/cogl-texture-rectangle-private.h
+++ b/cogl/cogl-texture-rectangle-private.h
@@ -34,7 +34,7 @@ struct _CoglTextureRectangle
/* The internal format of the texture represented as a
CoglPixelFormat */
- CoglPixelFormat format;
+ CoglPixelFormat internal_format;
/* TODO: factor out these OpenGL specific members into some form
* of driver private state. */
diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c
index ee4cfcf0e..f8d0811e6 100644
--- a/cogl/cogl-texture-rectangle.c
+++ b/cogl/cogl-texture-rectangle.c
@@ -102,7 +102,7 @@ _cogl_texture_rectangle_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
static void
_cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect)
{
- if (!tex_rect->is_foreign)
+ if (!tex_rect->is_foreign && tex_rect->gl_texture)
_cogl_delete_gl_texture (tex_rect->gl_texture);
/* Chain up */
@@ -173,6 +173,8 @@ _cogl_texture_rectangle_create_base (CoglContext *ctx,
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_rectangle_vtable);
+ tex_rect->gl_texture = 0;
+
/* We default to GL_LINEAR for both filters */
tex_rect->gl_legacy_texobj_min_filter = GL_LINEAR;
tex_rect->gl_legacy_texobj_mag_filter = GL_LINEAR;
@@ -181,7 +183,7 @@ _cogl_texture_rectangle_create_base (CoglContext *ctx,
tex_rect->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
tex_rect->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
- tex_rect->format = internal_format;
+ tex_rect->internal_format = internal_format;
return _cogl_texture_rectangle_object_new (tex_rect);
}
@@ -194,36 +196,59 @@ cogl_texture_rectangle_new_with_size (CoglContext *ctx,
CoglError **error)
{
CoglTextureRectangle *tex_rect;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- GLenum gl_error;
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
+ tex_rect =_cogl_texture_rectangle_create_base (ctx,
+ width, height,
+ internal_format);
+
+ /* XXX: This api has been changed for Cogl 2.0 on the master branch
+ * to not take a CoglError to allow the storage to be allocated
+ * lazily but since Mutter uses this api we are currently
+ * maintaining the semantics of immediately allocating the storage
+ */
+ if (!cogl_texture_allocate (COGL_TEXTURE (tex_rect), error))
+ {
+ cogl_object_unref (tex_rect);
+ return NULL;
+ }
+ return tex_rect;
+}
+
+static CoglBool
+_cogl_texture_rectangle_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ CoglContext *ctx = tex->context;
+ CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+ GLenum gl_error;
+ GLenum gl_texture;
+
if (!_cogl_texture_rectangle_can_create (ctx,
- width, height,
- internal_format, error))
- return NULL;
+ tex->width,
+ tex->height,
+ tex_rect->internal_format,
+ error))
+ return FALSE;
- internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
- internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
+ ctx->driver_vtable->pixel_format_to_gl (ctx,
+ tex_rect->internal_format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type);
- tex_rect = _cogl_texture_rectangle_create_base (ctx,
- width, height,
- internal_format);
-
- tex_rect->gl_texture =
+ gl_texture =
ctx->texture_driver->gen (ctx,
GL_TEXTURE_RECTANGLE_ARB,
- internal_format);
+ tex_rect->internal_format);
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
+ gl_texture,
tex_rect->is_foreign);
/* Clear any GL errors */
@@ -231,15 +256,18 @@ cogl_texture_rectangle_new_with_size (CoglContext *ctx,
;
ctx->glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
- width, height, 0, gl_format, gl_type, NULL);
+ tex->width, tex->height, 0, gl_format, gl_type, NULL);
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
{
- cogl_object_unref (tex_rect);
- return NULL;
+ GE( ctx, glDeleteTextures (1, &gl_texture) );
+ return FALSE;
}
- return tex_rect;
+ tex_rect->gl_texture = gl_texture;
+ tex_rect->gl_format = gl_intformat;
+
+ return TRUE;
}
CoglTextureRectangle *
@@ -308,6 +336,8 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
cogl_object_unref (dst_bmp);
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), TRUE);
+
return tex_rect;
}
@@ -424,7 +454,7 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
/* Setup bitmap info */
tex_rect->is_foreign = TRUE;
- tex_rect->format = format;
+ tex_rect->internal_format = format;
tex_rect->gl_texture = gl_handle;
tex_rect->gl_format = gl_int_format;
@@ -433,6 +463,8 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
tex_rect->gl_legacy_texobj_min_filter = GL_FALSE;
tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE;
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), TRUE);
+
return tex_rect;
}
@@ -624,7 +656,7 @@ _cogl_texture_rectangle_get_data (CoglTexture *tex,
static CoglPixelFormat
_cogl_texture_rectangle_get_format (CoglTexture *tex)
{
- return COGL_TEXTURE_RECTANGLE (tex)->format;
+ return COGL_TEXTURE_RECTANGLE (tex)->internal_format;
}
static GLenum
@@ -649,6 +681,7 @@ static const CoglTextureVtable
cogl_texture_rectangle_vtable =
{
TRUE, /* primitive */
+ _cogl_texture_rectangle_allocate,
_cogl_texture_rectangle_set_region,
_cogl_texture_rectangle_get_data,
NULL, /* foreach_sub_texture_in_region */
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 28d1f4cc9..1b97648ab 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -139,6 +139,7 @@ _cogl_texture_init (CoglTexture *texture,
texture->max_level = 0;
texture->width = width;
texture->height = height;
+ texture->allocated = FALSE;
texture->vtable = vtable;
texture->framebuffers = NULL;
}
@@ -440,6 +441,20 @@ _cogl_texture_get_type (CoglTexture *texture)
void
_cogl_texture_pre_paint (CoglTexture *texture, CoglTexturePrePaintFlags flags)
{
+ /* Assert that the storage for the texture exists already if we're
+ * about to reference it for painting.
+ *
+ * Note: we abort on error here since it's a bit late to do anything
+ * about it if we fail to allocate the texture and the app could
+ * have explicitly allocated the texture earlier to handle problems
+ * gracefully.
+ *
+ * XXX: Maybe it could even be considered a programmer error if the
+ * texture hasn't been allocated by this point since it implies we
+ * are abount to paint with undefined texture contents?
+ */
+ cogl_texture_allocate (texture, NULL);
+
texture->vtable->pre_paint (texture, flags);
}
@@ -465,10 +480,12 @@ _cogl_texture_set_region_from_bitmap (CoglTexture *texture,
>= width, FALSE);
_COGL_RETURN_VAL_IF_FAIL ((cogl_bitmap_get_height (bmp) - src_y)
>= height, FALSE);
+ _COGL_RETURN_VAL_IF_FAIL (width > 0, FALSE);
+ _COGL_RETURN_VAL_IF_FAIL (height > 0, FALSE);
- /* Shortcut out early if the image is empty */
- if (width == 0 || height == 0)
- return TRUE;
+ /* Assert that the storage for this texture has been allocated */
+ if (!cogl_texture_allocate (texture, error))
+ return FALSE;
/* Note that we don't prepare the bitmap for upload here because
some backends may be internally using a different format for the
@@ -897,10 +914,12 @@ get_texture_bits_via_offscreen (CoglTexture *texture,
COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
0);
- if (offscreen == NULL)
- return FALSE;
-
framebuffer = COGL_FRAMEBUFFER (offscreen);
+ if (!cogl_framebuffer_allocate (framebuffer, &ignore_error))
+ {
+ cogl_error_free (ignore_error);
+ return FALSE;
+ }
bitmap = cogl_bitmap_new_for_data (ctx,
width, height,
@@ -1390,3 +1409,22 @@ _cogl_texture_spans_foreach_in_region (CoglSpan *x_spans,
}
}
}
+
+void
+_cogl_texture_set_allocated (CoglTexture *texture,
+ CoglBool allocated)
+{
+ texture->allocated = allocated;
+}
+
+CoglBool
+cogl_texture_allocate (CoglTexture *texture,
+ CoglError **error)
+{
+ if (texture->allocated)
+ return TRUE;
+
+ texture->allocated = texture->vtable->allocate (texture, error);
+
+ return texture->allocated;
+}
diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h
index 17658ead7..b744babe2 100644
--- a/cogl/cogl-texture.h
+++ b/cogl/cogl-texture.h
@@ -112,7 +112,14 @@ uint32_t cogl_texture_error_quark (void);
*
* Creates a new #CoglTexture with the specified dimensions and pixel format.
*
- * Return value: A newly created #CoglTexture or %NULL on failure
+ * The storage for the texture is not necesarily created before this
+ * function returns. The storage can be explicitly allocated using
+ * cogl_texture_allocate() or preferably you can let Cogl
+ * automatically allocate the storage lazily when uploading data when
+ * Cogl may know more about how the texture will be used and can
+ * optimize how it is allocated.
+ *
+ * Return value: A newly created #CoglTexture
*
* Since: 0.8
*/
@@ -517,6 +524,28 @@ cogl_texture_unref (void *texture) G_GNUC_DEPRECATED;
#endif /* COGL_DISABLE_DEPRECATED */
+/**
+ * cogl_texture_allocate:
+ * @texture: A #CoglTexture
+ * @error: A #CoglError to return exceptional errors or %NULL
+ *
+ * Explicitly allocates the storage for the given @texture which
+ * allows you to be sure that there is enough memory for the
+ * texture and if not then the error can be handled gracefully.
+ *
+ * Normally applications don't need to use this api directly
+ * since the texture will be implicitly allocated when data is set on
+ * the texture, or if the texture is attached to a #CoglOffscreen
+ * framebuffer and rendered too.
+ *
+ * Return value: %TRUE if the texture was successfully allocated,
+ * otherwise %FALSE and @error will be updated if it
+ * wasn't %NULL.
+ */
+CoglBool
+cogl_texture_allocate (CoglTexture *texture,
+ CoglError **error);
+
COGL_END_DECLS
#endif /* __COGL_TEXTURE_H__ */
diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c
index a0a50cfaa..043d047ec 100644
--- a/cogl/driver/gl/cogl-framebuffer-gl.c
+++ b/cogl/driver/gl/cogl-framebuffer-gl.c
@@ -382,8 +382,7 @@ create_depth_texture (CoglContext *ctx,
depth_texture = cogl_texture_2d_new_with_size (ctx,
width, height,
- format,
- NULL);
+ format);
return COGL_TEXTURE (depth_texture);
}
@@ -712,14 +711,14 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
offscreen->texture_level_width,
offscreen->texture_level_height);
- if (offscreen->depth_texture)
- _cogl_texture_associate_framebuffer (offscreen->depth_texture, fb);
- else
+ if (!cogl_texture_allocate (offscreen->depth_texture, error))
{
- _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR,
- COGL_FRAMEBUFFER_ERROR_ALLOCATE,
- "Failed to allocate depth texture for framebuffer");
+ cogl_object_unref (offscreen->depth_texture);
+ offscreen->depth_texture = NULL;
+ return FALSE;
}
+
+ _cogl_texture_associate_framebuffer (offscreen->depth_texture, fb);
}
/* XXX: The framebuffer_object spec isn't clear in defining whether attaching
diff --git a/cogl/driver/gl/cogl-texture-2d-gl-private.h b/cogl/driver/gl/cogl-texture-2d-gl-private.h
index d77f460e8..c71908fc0 100644
--- a/cogl/driver/gl/cogl-texture-2d-gl-private.h
+++ b/cogl/driver/gl/cogl-texture-2d-gl-private.h
@@ -44,12 +44,9 @@ _cogl_texture_2d_gl_can_create (CoglContext *ctx,
void
_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d);
-CoglTexture2D *
-_cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglError **error);
+CoglBool
+_cogl_texture_2d_gl_allocate (CoglTexture *tex,
+ CoglError **error);
CoglTexture2D *
_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
diff --git a/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/driver/gl/cogl-texture-2d-gl.c
index 4f57eed61..8bcfb93d5 100644
--- a/cogl/driver/gl/cogl-texture-2d-gl.c
+++ b/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -43,7 +43,7 @@
void
_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d)
{
- if (!tex_2d->is_foreign)
+ if (!tex_2d->is_foreign && tex_2d->gl_texture)
_cogl_delete_gl_texture (tex_2d->gl_texture);
}
@@ -79,6 +79,8 @@ _cogl_texture_2d_gl_can_create (CoglContext *ctx,
void
_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
{
+ tex_2d->gl_texture = 0;
+
/* We default to GL_LINEAR for both filters */
tex_2d->gl_legacy_texobj_min_filter = GL_LINEAR;
tex_2d->gl_legacy_texobj_mag_filter = GL_LINEAR;
@@ -88,36 +90,43 @@ _cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
}
-CoglTexture2D *
-_cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglError **error)
+CoglBool
+_cogl_texture_2d_gl_allocate (CoglTexture *tex,
+ CoglError **error)
{
- CoglTexture2D *tex_2d;
+ CoglContext *ctx = tex->context;
+ CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
GLenum gl_error;
+ GLenum gl_texture;
- internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
- internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
+ if (!_cogl_texture_2d_gl_can_create (ctx,
+ tex->width,
+ tex->height,
+ tex_2d->internal_format))
+ {
+ _cogl_set_error (error, COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_SIZE,
+ "Failed to create texture 2d due to size/format"
+ " constraints");
+ return FALSE;
+ }
- tex_2d = _cogl_texture_2d_create_base (ctx,
- width, height,
- internal_format);
+ ctx->driver_vtable->pixel_format_to_gl (ctx,
+ tex_2d->internal_format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type);
- tex_2d->gl_texture =
- ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);
+ gl_texture =
+ ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, tex_2d->internal_format);
tex_2d->gl_internal_format = gl_intformat;
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
+ gl_texture,
tex_2d->is_foreign);
/* Clear any GL errors */
@@ -125,15 +134,18 @@ _cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
;
ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
- width, height, 0, gl_format, gl_type, NULL);
+ tex->width, tex->height, 0, gl_format, gl_type, NULL);
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
{
- cogl_object_unref (tex_2d);
- return NULL;
+ GE( ctx, glDeleteTextures (1, &gl_texture) );
+ return FALSE;
}
- return tex_2d;
+ tex_2d->gl_texture = gl_texture;
+ tex_2d->gl_internal_format = gl_intformat;
+
+ return TRUE;
}
CoglTexture2D *
@@ -213,6 +225,8 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
cogl_object_unref (dst_bmp);
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
+
return tex_2d;
}
@@ -249,9 +263,12 @@ _cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx,
COGL_TEXTURE_ERROR_BAD_PARAMETER,
"Could not create a CoglTexture2D from a given "
"EGLImage");
+ cogl_object_unref (tex_2d);
return NULL;
}
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
+
return tex_2d;
}
#endif
@@ -442,8 +459,6 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx,
tex_2d->is_foreign = TRUE;
tex_2d->mipmaps_dirty = TRUE;
- tex_2d->format = format;
-
tex_2d->gl_texture = gl_handle;
tex_2d->gl_internal_format = gl_int_format;
@@ -451,6 +466,8 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx,
tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;
+ _cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
+
return tex_2d;
}
@@ -465,7 +482,8 @@ _cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
int dst_y,
int level)
{
- CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+ CoglTexture *tex = COGL_TEXTURE (tex_2d);
+ CoglContext *ctx = tex->context;
/* Make sure the current framebuffers are bound, though we don't need to
* flush the clip state here since we aren't going to draw to the
diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
index bd12c81c8..141371eb9 100644
--- a/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -638,7 +638,7 @@ _cogl_driver_gl =
_cogl_texture_2d_gl_free,
_cogl_texture_2d_gl_can_create,
_cogl_texture_2d_gl_init,
- _cogl_texture_2d_gl_new_with_size,
+ _cogl_texture_2d_gl_allocate,
_cogl_texture_2d_gl_new_from_bitmap,
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
_cogl_egl_texture_2d_gl_new_from_image,
diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c
index b4d5efd3d..494b14eaa 100644
--- a/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -380,7 +380,7 @@ _cogl_driver_gles =
_cogl_texture_2d_gl_free,
_cogl_texture_2d_gl_can_create,
_cogl_texture_2d_gl_init,
- _cogl_texture_2d_gl_new_with_size,
+ _cogl_texture_2d_gl_allocate,
_cogl_texture_2d_gl_new_from_bitmap,
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
_cogl_egl_texture_2d_gl_new_from_image,
diff --git a/cogl/driver/nop/cogl-driver-nop.c b/cogl/driver/nop/cogl-driver-nop.c
index 40b101b26..7a782f9cf 100644
--- a/cogl/driver/nop/cogl-driver-nop.c
+++ b/cogl/driver/nop/cogl-driver-nop.c
@@ -68,7 +68,7 @@ _cogl_driver_nop =
_cogl_texture_2d_nop_free,
_cogl_texture_2d_nop_can_create,
_cogl_texture_2d_nop_init,
- _cogl_texture_2d_nop_new_with_size,
+ _cogl_texture_2d_nop_allocate,
_cogl_texture_2d_nop_new_from_bitmap,
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
_cogl_egl_texture_2d_nop_new_from_image,
diff --git a/cogl/driver/nop/cogl-texture-2d-nop-private.h b/cogl/driver/nop/cogl-texture-2d-nop-private.h
index 2e79e667f..1aa558a15 100644
--- a/cogl/driver/nop/cogl-texture-2d-nop-private.h
+++ b/cogl/driver/nop/cogl-texture-2d-nop-private.h
@@ -44,12 +44,9 @@ _cogl_texture_2d_nop_can_create (CoglContext *ctx,
void
_cogl_texture_2d_nop_init (CoglTexture2D *tex_2d);
-CoglTexture2D *
-_cogl_texture_2d_nop_new_with_size (CoglContext *ctx,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglError **error);
+CoglBool
+_cogl_texture_2d_nop_allocate (CoglTexture *tex,
+ CoglError **error);
CoglTexture2D *
_cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
diff --git a/cogl/driver/nop/cogl-texture-2d-nop.c b/cogl/driver/nop/cogl-texture-2d-nop.c
index 948d62094..5831e2790 100644
--- a/cogl/driver/nop/cogl-texture-2d-nop.c
+++ b/cogl/driver/nop/cogl-texture-2d-nop.c
@@ -55,16 +55,11 @@ _cogl_texture_2d_nop_init (CoglTexture2D *tex_2d)
{
}
-CoglTexture2D *
-_cogl_texture_2d_nop_new_with_size (CoglContext *ctx,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglError **error)
+CoglBool
+_cogl_texture_2d_nop_allocate (CoglTexture *tex,
+ CoglError **error)
{
- return _cogl_texture_2d_create_base (ctx,
- width, height,
- internal_format);
+ return TRUE;
}
CoglTexture2D *
@@ -72,11 +67,10 @@ _cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglError **error)
{
- return _cogl_texture_2d_nop_new_with_size (_cogl_bitmap_get_context (bmp),
- cogl_bitmap_get_width (bmp),
- cogl_bitmap_get_height (bmp),
- internal_format,
- error);
+ return _cogl_texture_2d_create_base (_cogl_bitmap_get_context (bmp),
+ cogl_bitmap_get_width (bmp),
+ cogl_bitmap_get_height (bmp),
+ internal_format);
}
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
diff --git a/cogl/winsys/cogl-texture-pixmap-x11.c b/cogl/winsys/cogl-texture-pixmap-x11.c
index 2b66414ea..71d00ea95 100644
--- a/cogl/winsys/cogl-texture-pixmap-x11.c
+++ b/cogl/winsys/cogl-texture-pixmap-x11.c
@@ -361,9 +361,18 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
if (!tex_pixmap->use_winsys_texture)
tex_pixmap->winsys = NULL;
+ _cogl_texture_set_allocated (tex, TRUE);
+
return _cogl_texture_pixmap_x11_object_new (tex_pixmap);
}
+static CoglBool
+_cogl_texture_pixmap_x11_allocate (CoglTexture *tex,
+ CoglError **error)
+{
+ return TRUE;
+}
+
/* Tries to allocate enough shared mem to handle a full size
* update size of the X Pixmap. */
static void
@@ -1001,6 +1010,7 @@ static const CoglTextureVtable
cogl_texture_pixmap_x11_vtable =
{
FALSE, /* not primitive */
+ _cogl_texture_pixmap_x11_allocate,
_cogl_texture_pixmap_x11_set_region,
_cogl_texture_pixmap_x11_get_data,
_cogl_texture_pixmap_x11_foreach_sub_texture_in_region,
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 2bfa19085..a9f88e075 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -1980,17 +1980,17 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
cogl_texture_2d_new_with_size (ctx,
tex->width,
tex->height,
- texture_format,
- NULL));
+ texture_format));
- if (glx_tex_pixmap->glx_tex)
+ if (cogl_texture_allocate (glx_tex_pixmap->glx_tex, &error))
COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p",
tex_pixmap);
else
{
COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
- "texture 2d could not be created",
- tex_pixmap);
+ "texture 2d could not be created: %s",
+ tex_pixmap, error->message);
+ cogl_error_free (error);
free_glx_pixmap (ctx, glx_tex_pixmap);
return FALSE;
}
diff --git a/tests/conform/test-gles2-context.c b/tests/conform/test-gles2-context.c
index 9a3c8b67f..9e66ab03f 100644
--- a/tests/conform/test-gles2-context.c
+++ b/tests/conform/test-gles2-context.c
@@ -27,8 +27,7 @@ test_push_pop_single_context (void)
cogl_texture_2d_new_with_size (test_ctx,
cogl_framebuffer_get_width (test_fb),
cogl_framebuffer_get_height (test_fb),
- COGL_PIXEL_FORMAT_ANY,
- NULL));
+ COGL_PIXEL_FORMAT_ANY));
offscreen = cogl_offscreen_new_to_texture (offscreen_texture);
pipeline = cogl_pipeline_new (test_ctx);
@@ -152,8 +151,7 @@ create_gles2_context (CoglTexture **offscreen_texture,
cogl_texture_2d_new_with_size (test_ctx,
cogl_framebuffer_get_width (test_fb),
cogl_framebuffer_get_height (test_fb),
- COGL_PIXEL_FORMAT_ANY,
- NULL));
+ COGL_PIXEL_FORMAT_ANY));
*offscreen = cogl_offscreen_new_to_texture (*offscreen_texture);
*pipeline = cogl_pipeline_new (test_ctx);
diff --git a/tests/conform/test-offscreen.c b/tests/conform/test-offscreen.c
index 26578d55a..5a4863b06 100644
--- a/tests/conform/test-offscreen.c
+++ b/tests/conform/test-offscreen.c
@@ -45,8 +45,7 @@ test_paint (TestState *state)
tex_2d = cogl_texture_2d_new_with_size (test_ctx,
state->fb_width,
state->fb_height,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- NULL);
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE);
tex = COGL_TEXTURE (tex_2d);
offscreen = cogl_offscreen_new_to_texture (tex);
@@ -127,8 +126,7 @@ test_flush (TestState *state)
tex_2d = cogl_texture_2d_new_with_size (test_ctx,
16, 16, /* width/height */
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- NULL);
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE);
tex = COGL_TEXTURE (tex_2d);
offscreen = cogl_offscreen_new_to_texture (tex);
diff --git a/tests/conform/test-utils.c b/tests/conform/test-utils.c
index 684327d55..9f3a4b4dd 100644
--- a/tests/conform/test-utils.c
+++ b/tests/conform/test-utils.c
@@ -122,11 +122,7 @@ test_utils_init (TestFlags requirement_flags,
CoglOffscreen *offscreen;
CoglTexture2D *tex = cogl_texture_2d_new_with_size (test_ctx,
FB_WIDTH, FB_HEIGHT,
- COGL_PIXEL_FORMAT_ANY,
- &error);
- if (!tex)
- g_critical ("Failed to allocate texture: %s", error->message);
-
+ COGL_PIXEL_FORMAT_ANY);
offscreen = cogl_offscreen_new_to_texture (COGL_TEXTURE (tex));
test_fb = COGL_FRAMEBUFFER (offscreen);
}