diff --git a/cogl/cogl-auto-texture.c b/cogl/cogl-auto-texture.c
index 62ac65c80..cf65e795b 100644
--- a/cogl/cogl-auto-texture.c
+++ b/cogl/cogl-auto-texture.c
@@ -54,6 +54,16 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
CoglBool can_convert_in_place,
CoglError **error);
+static void
+set_auto_mipmap_cb (CoglTexture *sub_texture,
+ const float *sub_texture_coords,
+ const float *meta_coords,
+ void *user_data)
+{
+ cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (sub_texture),
+ FALSE);
+}
+
CoglTexture *
cogl_texture_new_with_size (unsigned int width,
unsigned int height,
@@ -88,13 +98,7 @@ cogl_texture_new_with_size (unsigned int width,
else
tex = NULL;
- if (tex)
- {
- CoglBool auto_mipmap = !(flags & COGL_TEXTURE_NO_AUTO_MIPMAP);
- cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex),
- auto_mipmap);
- }
- else
+ if (!tex)
{
/* If it fails resort to sliced textures */
int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
@@ -105,6 +109,22 @@ cogl_texture_new_with_size (unsigned int width,
internal_format));
}
+ if (tex &&
+ flags & COGL_TEXTURE_NO_AUTO_MIPMAP)
+ {
+ /* To be able to iterate the slices of a #CoglTexture2DSliced we
+ * need to ensure the texture is allocated... */
+ if (!cogl_texture_allocate (tex, NULL))
+ return NULL;
+
+ cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
+ 0, 0, 1, 1,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
+ set_auto_mipmap_cb,
+ NULL);
+ }
+
return tex;
}
@@ -219,22 +239,28 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
else
tex = NULL;
- if (tex)
- {
- CoglBool auto_mipmap = !(flags & COGL_TEXTURE_NO_AUTO_MIPMAP);
- cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex),
- auto_mipmap);
- }
- else
+ if (!tex)
{
/* Otherwise create a sliced texture */
+ int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap,
- flags,
+ max_waste,
internal_format,
can_convert_in_place,
error));
}
+ if (tex &&
+ flags & COGL_TEXTURE_NO_AUTO_MIPMAP)
+ {
+ cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
+ 0, 0, 1, 1,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
+ set_auto_mipmap_cb,
+ NULL);
+ }
+
return tex;
}
diff --git a/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl-texture-2d-sliced-private.h
index 2d5106f9e..4ba30c511 100644
--- a/cogl/cogl-texture-2d-sliced-private.h
+++ b/cogl/cogl-texture-2d-sliced-private.h
@@ -54,7 +54,7 @@ _cogl_texture_2d_sliced_new_from_foreign (CoglContext *context,
CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
+ int max_waste,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c
index f083e92da..9d8282b02 100644
--- a/cogl/cogl-texture-2d-sliced.c
+++ b/cogl/cogl-texture-2d-sliced.c
@@ -956,7 +956,7 @@ _cogl_texture_2d_sliced_allocate (CoglTexture *tex,
CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
+ int max_waste,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
@@ -964,8 +964,7 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
CoglContext *ctx;
CoglTexture2DSliced *tex_2ds;
CoglBitmap *upload_bmp;
- int width, height, max_waste;
- int i;
+ int width, height;
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
@@ -977,11 +976,6 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
/* Create new texture and fill with loaded data */
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
- if (flags & COGL_TEXTURE_NO_SLICING)
- max_waste = -1;
- else
- max_waste = COGL_TEXTURE_MAX_WASTE;
-
internal_format =
_cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
internal_format);
@@ -1016,18 +1010,6 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
cogl_object_unref (upload_bmp);
- if ((flags & COGL_TEXTURE_NO_AUTO_MIPMAP))
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- CoglPrimitiveTexture *slice_tex;
-
- slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglPrimitiveTexture *,
- i);
-
- cogl_primitive_texture_set_auto_mipmap (slice_tex, FALSE);
- }
-
return _cogl_texture_2d_sliced_object_new (tex_2ds);
error:
@@ -1036,6 +1018,19 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
return NULL;
}
+CoglTexture2DSliced *
+cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
+ int max_waste,
+ CoglPixelFormat internal_format,
+ CoglError **error)
+{
+ return _cogl_texture_2d_sliced_new_from_bitmap (bmp,
+ max_waste,
+ internal_format,
+ FALSE,
+ error);
+}
+
CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx,
unsigned int gl_handle,
@@ -1128,6 +1123,70 @@ _cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx,
return _cogl_texture_2d_sliced_object_new (tex_2ds);
}
+CoglTexture2DSliced *
+cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
+ int width,
+ int height,
+ int max_waste,
+ CoglPixelFormat format,
+ CoglPixelFormat internal_format,
+ int rowstride,
+ const uint8_t *data,
+ CoglError **error)
+{
+ CoglBitmap *bmp;
+ CoglTexture2DSliced *tex_2ds;
+
+ _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL);
+ _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL);
+
+ /* Rowstride from width if not given */
+ if (rowstride == 0)
+ rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
+
+ /* Wrap the data into a bitmap */
+ bmp = cogl_bitmap_new_for_data (ctx,
+ width, height,
+ format,
+ rowstride,
+ (uint8_t *) data);
+
+ tex_2ds = cogl_texture_2d_sliced_new_from_bitmap (bmp, max_waste,
+ internal_format,
+ error);
+
+ cogl_object_unref (bmp);
+
+ return tex_2ds;
+}
+
+CoglTexture2DSliced *
+cogl_texture_2d_sliced_new_from_file (CoglContext *ctx,
+ const char *filename,
+ int max_waste,
+ CoglPixelFormat internal_format,
+ CoglError **error)
+{
+ CoglBitmap *bmp;
+ CoglTexture2DSliced *tex_2ds = NULL;
+
+ _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL);
+
+ bmp = _cogl_bitmap_from_file (ctx, filename, error);
+ if (bmp == NULL)
+ return NULL;
+
+ tex_2ds = _cogl_texture_2d_sliced_new_from_bitmap (bmp,
+ max_waste,
+ internal_format,
+ TRUE, /* can convert in-place */
+ error);
+
+ cogl_object_unref (bmp);
+
+ return tex_2ds;
+}
+
static CoglBool
_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex)
{
diff --git a/cogl/cogl-texture-2d-sliced.h b/cogl/cogl-texture-2d-sliced.h
index e26157e6b..882bdd686 100644
--- a/cogl/cogl-texture-2d-sliced.h
+++ b/cogl/cogl-texture-2d-sliced.h
@@ -113,6 +113,171 @@ cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
int max_waste,
CoglPixelFormat internal_format);
+/**
+ * cogl_texture_2d_sliced_new_from_file:
+ * @ctx: A #CoglContext
+ * @filename: the file to load
+ * @max_waste: The threshold of how wide a strip of wasted texels
+ * 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 #CoglPixelFormat to use for the GPU storage of the
+ * texture. If %COGL_PIXEL_FORMAT_ANY is given then a premultiplied
+ * format similar to the format of the source data will be used. The
+ * default blending equations of Cogl expect premultiplied color data;
+ * the main use of passing a non-premultiplied format here is if you
+ * have non-premultiplied source data and are going to adjust the blend
+ * mode (see cogl_material_set_blend()) or use the data for something
+ * other than straight blending.
+ * @error: A #CoglError to catch exceptional errors or %NULL
+ *
+ * Creates a #CoglTexture2DSliced from an image file.
+ *
+ * A #CoglTexture2DSliced may internally be comprised of 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.
+ *
+ * @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.
+ *
+ *