Allow lazy texture storage allocation

Consistent with how we lazily allocate framebuffers this patch allows us
to instantiate textures but still specify constraints and requirements
before allocating storage so that we can be sure to allocate the most
appropriate/efficient storage.

This adds a cogl_texture_allocate() function that is analogous to
cogl_framebuffer_allocate() which can optionally be called to explicitly
allocate storage and catch any errors. If this function isn't used
explicitly then Cogl will implicitly ensure textures are allocated
before the storage is needed.

It is generally recommended to rely on lazy storage allocation or at
least perform explicit allocation as late as possible so Cogl can be
fully informed about the best way to allocate storage.

Reviewed-by: Neil Roberts <neil@linux.intel.com>

(cherry picked from commit 1fa7c0f10a8a03043e3c75cb079a49625df098b7)

Note: This reverts the cogl_texture_rectangle_new_with_size API change
that dropped the CoglError argument and keeps the semantics of
allocating the texture immediately. This is because Mutter currently
uses this API so we will probably look at updating this later once
we have a corresponding Mutter patch prepared. The other API changes
were kept since they only affected experimental api.
This commit is contained in:
Robert Bragg 2012-11-22 23:01:08 +00:00
parent 5a814e386a
commit 73e8a6d7ce
37 changed files with 713 additions and 419 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -38,6 +38,7 @@ struct _CoglTexture2DSliced
GArray *slice_y_spans;
GArray *slice_textures;
int max_waste;
CoglPixelFormat internal_format;
};
CoglTexture2DSliced *

View File

@ -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,

View File

@ -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.
*
* <note>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.</note>
*
* 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:

View File

@ -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 */

View File

@ -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.
*
* <note>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().</note>
*
* 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:

View File

@ -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;

View File

@ -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 */

View File

@ -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.
* <note>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.</note>
*
* 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:

View File

@ -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 */

View File

@ -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. */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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.
*
* <note>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.</note>
*
* 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__ */

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}