diff --git a/cogl/Makefile.am b/cogl/Makefile.am index f12354f54..3135afdc5 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -77,6 +77,7 @@ cogl_public_h = \ $(srcdir)/cogl-texture.h \ $(srcdir)/cogl-texture-3d.h \ $(srcdir)/cogl-texture-2d.h \ + $(srcdir)/cogl-texture-2d-sliced.h \ $(srcdir)/cogl-types.h \ $(srcdir)/cogl-vertex-buffer.h \ $(srcdir)/cogl-index-buffer.h \ diff --git a/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl-texture-2d-sliced-private.h index 67a8ce9a9..1cd09fe41 100644 --- a/cogl/cogl-texture-2d-sliced-private.h +++ b/cogl/cogl-texture-2d-sliced-private.h @@ -21,17 +21,15 @@ * */ -#ifndef __COGL_TEXTURE_2D_SLICED_H -#define __COGL_TEXTURE_2D_SLICED_H +#ifndef __COGL_TEXTURE_2D_SLICED_PRIVATE_H +#define __COGL_TEXTURE_2D_SLICED_PRIVATE_H #include "cogl-bitmap-private.h" -#include "cogl-handle.h" #include "cogl-pipeline-private.h" #include "cogl-texture-private.h" +#include "cogl-texture-2d-sliced.h" -#define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex) - -typedef struct _CoglTexture2DSliced CoglTexture2DSliced; +#include struct _CoglTexture2DSliced { @@ -48,13 +46,7 @@ struct _CoglTexture2DSliced GQuark _cogl_handle_texture_2d_sliced_get_type (void); -CoglHandle -_cogl_texture_2d_sliced_new_with_size (unsigned int width, - unsigned int height, - CoglTextureFlags flags, - CoglPixelFormat internal_format); - -CoglHandle +CoglTexture2DSliced * _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, GLenum gl_target, GLuint width, @@ -63,9 +55,9 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, GLuint y_pot_waste, CoglPixelFormat format); -CoglHandle +CoglTexture2DSliced * _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, CoglTextureFlags flags, CoglPixelFormat internal_format); -#endif /* __COGL_TEXTURE_2D_SLICED_H */ +#endif /* __COGL_TEXTURE_2D_SLICED_PRIVATE_H */ diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index ffaeb7500..0484a0418 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -52,7 +52,7 @@ static void _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds); -COGL_TEXTURE_INTERNAL_DEFINE (Texture2DSliced, texture_2d_sliced); +COGL_TEXTURE_DEFINE (Texture2DSliced, texture_2d_sliced); static const CoglTextureVtable cogl_texture_2d_sliced_vtable; @@ -179,7 +179,7 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( float x_intersect_end = iter_x.intersect_end; float slice_tx1; float slice_tx2; - CoglHandle slice_tex; + CoglTexture2D *slice_tex; /* Discard slices out of rectangle early */ if (!iter_x.intersects) @@ -202,12 +202,12 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( data.x_span = iter_x.span; /* Pluck out the cogl texture for this slice */ - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, iter_y.index * iter_x.array->len + iter_x.index); _cogl_texture_foreach_sub_texture_in_region - (slice_tex, + (COGL_TEXTURE (slice_tex), slice_tx1, slice_ty1, slice_tx2, slice_ty2, _cogl_texture_2d_sliced_foreach_cb, &data); @@ -248,7 +248,7 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds, static void _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, CoglBitmap *source_bmp, - CoglHandle slice_tex, + CoglTexture2D *slice_tex, guint8 *waste_buf, CoglSpan *x_span, CoglSpan *y_span, @@ -318,7 +318,7 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, NULL, NULL); - cogl_texture_set_region_from_bitmap (slice_tex, + cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), 0, /* src_x */ 0, /* src_y */ /* dst_x */ @@ -374,7 +374,7 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, NULL, NULL); - cogl_texture_set_region_from_bitmap (slice_tex, + cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), 0, /* src_x */ 0, /* src_y */ /* dst_x */ @@ -399,7 +399,7 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds, { CoglSpan *x_span; CoglSpan *y_span; - CoglHandle slice_tex; + CoglTexture2D *slice_tex; int x, y; guint8 *waste_buf; CoglPixelFormat bmp_format; @@ -424,9 +424,9 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds, /* Pick the gl texture object handle */ slice_tex = g_array_index (tex_2ds->slice_textures, - CoglHandle, slice_num); + CoglTexture2D *, slice_num); - cogl_texture_set_region_from_bitmap (slice_tex, + cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), x_span->start, /* src x */ y_span->start, /* src y */ 0, /* dst x */ @@ -485,7 +485,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, CoglSpan *y_span; CoglSpanIter x_iter; CoglSpanIter y_iter; - CoglHandle slice_tex; + CoglTexture2D *slice_tex; int source_x = 0, source_y = 0; int inter_w = 0, inter_h = 0; int local_x = 0, local_y = 0; @@ -557,9 +557,9 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, /* Pick slice texture */ slice_tex = g_array_index (tex_2ds->slice_textures, - CoglHandle, slice_num); + CoglTexture2D *, slice_num); - cogl_texture_set_region_from_bitmap (slice_tex, + cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), source_x, source_y, local_x, /* dst x */ @@ -692,11 +692,11 @@ _cogl_texture_2d_sliced_set_wrap_mode_parameters (CoglTexture *tex, /* Pass the set wrap mode on to all of the child textures */ for (i = 0; i < tex_2ds->slice_textures->len; i++) { - CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, - CoglHandle, - i); + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, + i); - _cogl_texture_set_wrap_mode_parameters (slice_tex, + _cogl_texture_set_wrap_mode_parameters (COGL_TEXTURE (slice_tex), wrap_mode_s, wrap_mode_t, wrap_mode_p); @@ -704,27 +704,25 @@ _cogl_texture_2d_sliced_set_wrap_mode_parameters (CoglTexture *tex, } static gboolean -_cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, +_cogl_texture_2d_sliced_slices_create (CoglContext *ctx, + CoglTexture2DSliced *tex_2ds, int width, int height, - CoglPixelFormat format, - CoglTextureFlags flags) + CoglPixelFormat format) { - int max_width; - int max_height; - CoglHandle *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_type; + 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_type; int (*slices_for_size) (int, int, int, GArray*); - _COGL_GET_CONTEXT (ctx, FALSE); - /* Initialize size of largest slice according to supported features */ if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)) { @@ -832,15 +830,12 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, n_slices = n_x_slices * n_y_slices; tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE, - sizeof (CoglHandle), + sizeof (CoglTexture2D *), n_slices); g_array_set_size (tex_2ds->slice_textures, n_slices); - /* Generate a "working set" of GL texture objects - * (some implementations might supported faster - * re-binding between textures inside a set) */ - slice_textures = (CoglHandle *) tex_2ds->slice_textures->data; + slice_textures = (CoglTexture2D **) tex_2ds->slice_textures->data; /* Init each GL texture object */ for (y = 0; y < n_y_slices; ++y) @@ -849,6 +844,7 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, for (x = 0; x < n_x_slices; ++x) { + GError *error = NULL; x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); COGL_NOTE (SLICING, "CREATE SLICE (%d,%d)\tsize (%d,%d)", @@ -857,9 +853,14 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, y_span->size - y_span->waste); slice_textures[y * n_x_slices + x] = - cogl_texture_new_with_size (x_span->size, y_span->size, - COGL_TEXTURE_NO_ATLAS | flags, - format); + 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); + g_error_free (error); + return FALSE; + } } } @@ -881,8 +882,8 @@ _cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds) for (i = 0; i < tex_2ds->slice_textures->len; i++) { - CoglHandle slice_tex = - g_array_index (tex_2ds->slice_textures, CoglHandle, i); + CoglTexture2D *slice_tex = + g_array_index (tex_2ds->slice_textures, CoglTexture2D *, i); cogl_handle_unref (slice_tex); } @@ -900,11 +901,11 @@ _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds) } static gboolean -_cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds, +_cogl_texture_2d_sliced_init_base (CoglContext *ctx, + CoglTexture2DSliced *tex_2ds, int width, int height, - CoglPixelFormat internal_format, - CoglTextureFlags flags) + CoglPixelFormat internal_format) { CoglTexture *tex = COGL_TEXTURE (tex_2ds); @@ -915,11 +916,11 @@ _cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds, tex_2ds->slice_textures = NULL; /* Create slices for the given format and size */ - if (!_cogl_texture_2d_sliced_slices_create (tex_2ds, + if (!_cogl_texture_2d_sliced_slices_create (ctx, + tex_2ds, width, height, - internal_format, - flags)) + internal_format)) return FALSE; tex_2ds->width = width; @@ -928,11 +929,13 @@ _cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds, return TRUE; } -CoglHandle -_cogl_texture_2d_sliced_new_with_size (unsigned int width, - unsigned int height, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_with_size (CoglContext *ctx, + unsigned int width, + unsigned int height, + int max_waste, + CoglPixelFormat internal_format, + GError **error) { CoglTexture2DSliced *tex_2ds; @@ -943,24 +946,25 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width, /* Init texture with empty bitmap */ tex_2ds = g_new (CoglTexture2DSliced, 1); - if ((flags & COGL_TEXTURE_NO_SLICING)) - tex_2ds->max_waste = -1; - else - tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE; + tex_2ds->max_waste = max_waste; - if (!_cogl_texture_2d_sliced_init_base (tex_2ds, + if (!_cogl_texture_2d_sliced_init_base (ctx, + tex_2ds, width, height, - internal_format, - flags)) + internal_format)) { _cogl_texture_2d_sliced_free (tex_2ds); - return COGL_INVALID_HANDLE; + g_set_error (error, + COGL_ERROR, + COGL_ERROR_NO_MEMORY, + "Not enough memory to allocate texture slices"); + return NULL; } return _cogl_texture_2d_sliced_handle_new (tex_2ds); } -CoglHandle +CoglTexture2DSliced * _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, CoglTextureFlags flags, CoglPixelFormat internal_format) @@ -972,7 +976,9 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, GLenum gl_type; int width, height; - g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE); + _COGL_GET_CONTEXT (ctx, NULL); + + g_return_val_if_fail (cogl_is_bitmap (bmp), NULL); width = _cogl_bitmap_get_width (bmp); height = _cogl_bitmap_get_height (bmp); @@ -985,30 +991,22 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, else tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE; - /* FIXME: If upload fails we should set some kind of - * error flag but still return texture handle if the - * user decides to destroy another texture and upload - * this one instead (reloading from file is not needed - * in that case). As a rule then, everytime a valid - * CoglHandle is returned, it should also be destroyed - * with cogl_handle_unref at some point! */ - dst_bmp = _cogl_texture_prepare_for_upload (bmp, internal_format, &internal_format, &gl_intformat, &gl_format, &gl_type); - if (dst_bmp == COGL_INVALID_HANDLE) + if (dst_bmp == NULL) { _cogl_texture_2d_sliced_free (tex_2ds); - return COGL_INVALID_HANDLE; + return NULL; } - if (!_cogl_texture_2d_sliced_init_base (tex_2ds, + if (!_cogl_texture_2d_sliced_init_base (ctx, + tex_2ds, width, height, - internal_format, - flags)) + internal_format)) goto error; if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds, @@ -1022,10 +1020,10 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, error: cogl_object_unref (dst_bmp); _cogl_texture_2d_sliced_free (tex_2ds); - return COGL_INVALID_HANDLE; + return NULL; } -CoglHandle +CoglTexture2DSliced * _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, GLenum gl_target, GLuint width, @@ -1044,9 +1042,9 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, CoglTexture *tex; CoglSpan x_span; CoglSpan y_span; - CoglHandle tex_2d; + CoglTexture2D *tex_2d; - _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + _COGL_GET_CONTEXT (ctx, NULL); /* This should only be called when the texture target is 2D. If a rectangle texture is used then _cogl_texture_new_from_foreign @@ -1059,7 +1057,7 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, /* Validate pot waste */ if (x_pot_waste < 0 || x_pot_waste >= width || y_pot_waste < 0 || y_pot_waste >= height) - return COGL_INVALID_HANDLE; + return NULL; tex_2d = cogl_texture_2d_new_from_foreign (ctx, gl_target, @@ -1069,12 +1067,12 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, NULL); if (!tex_2d) - return COGL_INVALID_HANDLE; + return NULL; /* The texture 2d backend may use a different pixel format if it queries the actual texture so we'll refetch the format it actually used */ - format = cogl_texture_get_format (tex_2d); + format = cogl_texture_get_format (COGL_TEXTURE (tex_2d)); /* Create new texture */ tex_2ds = g_new0 (CoglTexture2DSliced, 1); @@ -1097,7 +1095,7 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE, - sizeof (CoglHandle), 1); + sizeof (CoglTexture2D *), 1); /* Store info for a single slice */ x_span.start = 0; @@ -1119,15 +1117,15 @@ static gboolean _cogl_texture_2d_sliced_is_foreign (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_tex; + CoglTexture2D *slice_tex; /* Make sure slices were created */ if (tex_2ds->slice_textures == NULL) return FALSE; /* Pass the call on to the first slice */ - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); - return _cogl_texture_is_foreign (slice_tex); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_is_foreign (COGL_TEXTURE (slice_tex)); } static int @@ -1156,7 +1154,7 @@ static gboolean _cogl_texture_2d_sliced_can_hardware_repeat (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_tex; + CoglTexture2D *slice_tex; CoglSpan *x_span; CoglSpan *y_span; @@ -1171,8 +1169,8 @@ _cogl_texture_2d_sliced_can_hardware_repeat (CoglTexture *tex) return FALSE; /* Otherwise pass the query on to the single slice texture */ - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); - return _cogl_texture_can_hardware_repeat (slice_tex); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_can_hardware_repeat (COGL_TEXTURE (slice_tex)); } static void @@ -1183,7 +1181,7 @@ _cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex, CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); CoglSpan *x_span; CoglSpan *y_span; - CoglHandle slice_tex; + CoglTexture2D *slice_tex; g_assert (!_cogl_texture_2d_sliced_is_sliced (tex)); @@ -1195,8 +1193,8 @@ _cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex, *t *= tex_2ds->height / (float)y_span->size; /* Let the child texture further transform the coords */ - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); - _cogl_texture_transform_coords_to_gl (slice_tex, s, t); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + _cogl_texture_transform_coords_to_gl (COGL_TEXTURE (slice_tex), s, t); } static CoglTransformResult @@ -1234,7 +1232,7 @@ _cogl_texture_2d_sliced_get_gl_texture (CoglTexture *tex, GLenum *out_gl_target) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_tex; + CoglTexture2D *slice_tex; if (tex_2ds->slice_textures == NULL) return FALSE; @@ -1242,9 +1240,10 @@ _cogl_texture_2d_sliced_get_gl_texture (CoglTexture *tex, if (tex_2ds->slice_textures->len < 1) return FALSE; - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); - return cogl_texture_get_gl_texture (slice_tex, out_gl_handle, out_gl_target); + return cogl_texture_get_gl_texture (COGL_TEXTURE (slice_tex), + out_gl_handle, out_gl_target); } static void @@ -1253,7 +1252,7 @@ _cogl_texture_2d_sliced_set_filters (CoglTexture *tex, GLenum mag_filter) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_tex; + CoglTexture2D *slice_tex; int i; /* Make sure slices were created */ @@ -1265,8 +1264,9 @@ _cogl_texture_2d_sliced_set_filters (CoglTexture *tex, GL */ for (i = 0; i < tex_2ds->slice_textures->len; i++) { - slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, i); - _cogl_texture_set_filters (slice_tex, min_filter, mag_filter); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, i); + _cogl_texture_set_filters (COGL_TEXTURE (slice_tex), + min_filter, mag_filter); } } @@ -1284,9 +1284,9 @@ _cogl_texture_2d_sliced_pre_paint (CoglTexture *tex, /* Pass the pre-paint on to every slice */ for (i = 0; i < tex_2ds->slice_textures->len; i++) { - CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, - CoglHandle, i); - _cogl_texture_pre_paint (slice_tex, flags); + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, i); + _cogl_texture_pre_paint (COGL_TEXTURE (slice_tex), flags); } } @@ -1303,9 +1303,9 @@ _cogl_texture_2d_sliced_ensure_non_quad_rendering (CoglTexture *tex) /* Pass the call on to every slice */ for (i = 0; i < tex_2ds->slice_textures->len; i++) { - CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, - CoglHandle, i); - _cogl_texture_ensure_non_quad_rendering (slice_tex); + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, i); + _cogl_texture_ensure_non_quad_rendering (COGL_TEXTURE (slice_tex)); } } @@ -1350,30 +1350,30 @@ static CoglPixelFormat _cogl_texture_2d_sliced_get_format (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_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, CoglHandle, 0); - return cogl_texture_get_format (slice_tex); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return cogl_texture_get_format (COGL_TEXTURE (slice_tex)); } static GLenum _cogl_texture_2d_sliced_get_gl_format (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - CoglHandle slice_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, CoglHandle, 0); - return _cogl_texture_get_gl_format (slice_tex); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_get_gl_format (COGL_TEXTURE (slice_tex)); } static int diff --git a/cogl/cogl-texture-2d-sliced.h b/cogl/cogl-texture-2d-sliced.h new file mode 100644 index 000000000..ea8c2a3da --- /dev/null +++ b/cogl/cogl-texture-2d-sliced.h @@ -0,0 +1,104 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_TEXURE_2D_SLICED_H +#define __COGL_TEXURE_2D_SLICED_H + +#include "cogl-context.h" +#include "cogl-types.h" + +#include + +/** + * SECTION:cogl-texture-2d-sliced + * @short_description: Functions for creating and manipulating 2D meta + * textures that may internally be comprised of + * multiple 2D textures with power-of-two sizes. + * + * These functions allow high-level meta textures (See the + * #CoglMetaTexture interface) to be allocated that may internally be + * comprised of multiple 2D texture "slices" with power-of-two sizes. + * + * This API can be useful when working with GPUs that don't have + * native support for non-power-of-two textures or if you want to load + * a texture that is larger than the GPUs maximum texture size limits. + * + * The algorithm for slicing works by first trying to map a virtual + * size to the next larger power-of-two size and then seeing how many + * wasted pixels that would result in. For example if you have a + * virtual texture that's 259 texels wide, the next pot size = 512 and + * the amount of waste would be 253 texels. If the amount of waste is + * above a max-waste threshold then we would next slice that texture + * into one that's 256 texels and then looking at how many more texels + * remain unallocated after that we choose the next power-of-two size. + * For the example of a 259 texel image that would mean having a 256 + * texel wide texture, leaving 3 texels unallocated so we'd then + * create a 4 texel wide texture - now there is only one texel of + * waste. The algorithm continues to slice the right most textures + * until the amount of waste is less than or equal to a specfied + * max-waste threshold. The same logic for slicing from left to right + * is also applied from top to bottom. + */ + +typedef struct _CoglTexture2DSliced CoglTexture2DSliced; +#define COGL_TEXTURE_2D_SLICED(X) ((CoglTexture2DSliced *)X) + +#define cogl_texture_2d_sliced_new_with_size \ + cogl_texture_2d_sliced_new_with_size_EXP +/** + * cogl_texture_2d_sliced_new_with_size: + * @ctx: A #CoglContext + * @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. + * @internal_format: The format of the texture + * @error: A #GError 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. + * + * Returns: A newly allocated #CoglTexture2DSliced or if there was + * an error allocating any of the internal slices %NULL is + * returned and @error is updated. + * + * Since: 1.10 + * Stability: unstable + */ +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_with_size (CoglContext *ctx, + unsigned int width, + unsigned int height, + int max_waste, + CoglPixelFormat internal_format, + GError **error); + +#endif /* __COGL_TEXURE_2D_SLICED_H */ diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index c2b3a823a..7bf0d6441 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -405,10 +405,15 @@ cogl_texture_new_with_size (unsigned int width, /* If it fails resort to sliced textures */ if (tex == NULL) - tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_with_size (width, - height, - flags, - internal_format)); + { + int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE; + tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, + width, + height, + max_waste, + internal_format, + NULL)); + } return tex; } @@ -471,9 +476,10 @@ cogl_texture_new_from_bitmap (CoglBitmap *bitmap, return tex; /* Otherwise create a sliced texture */ - return _cogl_texture_2d_sliced_new_from_bitmap (bitmap, - flags, - internal_format); + return + COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap, + flags, + internal_format)); } CoglTexture * @@ -538,13 +544,13 @@ cogl_texture_new_from_foreign (GLuint gl_handle, #endif if (x_pot_waste != 0 || y_pot_waste != 0) - return _cogl_texture_2d_sliced_new_from_foreign (gl_handle, - gl_target, - width, - height, - x_pot_waste, - y_pot_waste, - format); + return COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_foreign (gl_handle, + gl_target, + width, + height, + x_pot_waste, + y_pot_waste, + format)); else { _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h index df9a2866a..1ec6e5771 100644 --- a/cogl/cogl-types.h +++ b/cogl/cogl-types.h @@ -471,6 +471,8 @@ cogl_blend_string_error_quark (void); * CoglError: * @COGL_ERROR_UNSUPPORTED: You tried to use a feature or * configuration not currently available. + * @COGL_ERROR_NO_MEMORY: You tried to allocate a resource + * such as a texture and there wasn't enough memory. * * Error enumeration for Cogl * @@ -480,7 +482,7 @@ cogl_blend_string_error_quark (void); * * You've tried to use a feature that is not * advertised by cogl_get_features(). This could happen if you create - * a non-sliced texture with a non-power-of-two size when + * a 2d texture with a non-power-of-two size when * %COGL_FEATURE_TEXTURE_NPOT is not advertised. * The GPU can not handle the configuration you have * requested. An example might be if you try to use too many texture @@ -493,9 +495,11 @@ cogl_blend_string_error_quark (void); * this enum should also be considered experimental. * * Since: 1.4 + * Stability: unstable */ typedef enum { /*< prefix=COGL_ERROR >*/ - COGL_ERROR_UNSUPPORTED + COGL_ERROR_UNSUPPORTED, + COGL_ERROR_NO_MEMORY } CoglError; GQuark diff --git a/cogl/cogl.h b/cogl/cogl.h index 4cebfa209..08f440261 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -81,6 +81,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer; #include #include #include +#include #include #include #include