texture: remove _cogl_texture_prepare_for_upload

This removes the gl centric _cogl_texture_prepare_for_upload api from
cogl-texture.c and instead adds a _cogl_bitmap_convert_for_upload() api
which everything now uses instead. GL specific code that needed the gl
internal/format/type enums returned by _cogl_texture_prepare_for_upload
now use ->pixel_format_to_gl directly.

Since there was a special case optimization in
cogl_texture_new_from_file that aimed to avoid copying the temporary
bitmap that's created for the given file and allow conversions to
happen in-place the new _cogl_bitmap_convert_for_upload() api supports
converting in place depending on a 'can_convert_in_place' argument.

This ability to convert bitmaps in-place has been integrated across the
different components as appropriate.

In updating cogl-texture-2d-sliced.c this was able to remove a number of
other GL specific parts to how spans are setup.

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

(cherry picked from commit e190dd23c655da34b9c5c263a9f6006dcc0413b0)

Conflicts:
	cogl/cogl-auto-texture.c
	cogl/cogl.symbols
This commit is contained in:
Robert Bragg 2013-06-08 00:28:14 +01:00 committed by Neil Roberts
parent 1e4e68e069
commit 6f480c7530
18 changed files with 344 additions and 321 deletions

View File

@ -61,6 +61,7 @@ CoglAtlasTexture *
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
CoglAtlasTexture *

View File

@ -514,12 +514,13 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
}
static CoglBitmap *
_cogl_atlas_texture_prepare_for_upload (CoglAtlasTexture *atlas_tex,
CoglBitmap *bmp,
CoglError **error)
_cogl_atlas_texture_convert_bitmap_for_upload (CoglAtlasTexture *atlas_tex,
CoglBitmap *bmp,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglPixelFormat internal_format;
CoglBitmap *converted_bmp;
CoglBitmap *upload_bmp;
CoglBitmap *override_bmp;
/* We'll prepare to upload using the format of the actual texture of
@ -533,15 +534,11 @@ _cogl_atlas_texture_prepare_for_upload (CoglAtlasTexture *atlas_tex,
internal_format = (COGL_PIXEL_FORMAT_RGBA_8888 |
(atlas_tex->format & COGL_PREMULT_BIT));
converted_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
NULL, /* dst_format_out */
NULL, /* glintformat */
NULL, /* glformat */
NULL, /* gltype */
error);
if (converted_bmp == NULL)
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
internal_format,
can_convert_in_place,
error);
if (upload_bmp == NULL)
return NULL;
/* We'll create another bitmap which uses the same data but
@ -549,14 +546,14 @@ _cogl_atlas_texture_prepare_for_upload (CoglAtlasTexture *atlas_tex,
to the atlas texture won't trigger the conversion again */
override_bmp =
_cogl_bitmap_new_shared (converted_bmp,
cogl_bitmap_get_format (converted_bmp) &
_cogl_bitmap_new_shared (upload_bmp,
cogl_bitmap_get_format (upload_bmp) &
~COGL_PREMULT_BIT,
cogl_bitmap_get_width (converted_bmp),
cogl_bitmap_get_height (converted_bmp),
cogl_bitmap_get_rowstride (converted_bmp));
cogl_bitmap_get_width (upload_bmp),
cogl_bitmap_get_height (upload_bmp),
cogl_bitmap_get_rowstride (upload_bmp));
cogl_object_unref (converted_bmp);
cogl_object_unref (upload_bmp);
return override_bmp;
}
@ -583,11 +580,13 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
if (atlas_tex->atlas)
{
CoglBool ret;
bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex,
bmp,
error);
if (!bmp)
CoglBitmap *upload_bmp =
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
bmp,
FALSE, /* can't convert
in place */
error);
if (!upload_bmp)
return FALSE;
/* Upload the data ignoring the premult bit */
@ -595,10 +594,10 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
bmp,
upload_bmp,
error);
cogl_object_unref (bmp);
cogl_object_unref (upload_bmp);
return ret;
}
@ -792,11 +791,12 @@ CoglAtlasTexture *
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
CoglAtlasTexture *atlas_tex;
CoglBitmap *dst_bmp;
CoglBitmap *upload_bmp;
int bmp_width;
int bmp_height;
CoglPixelFormat bmp_format;
@ -823,10 +823,12 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
return NULL;
}
dst_bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex,
bmp,
error);
if (dst_bmp == NULL)
upload_bmp =
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
bmp,
can_convert_in_place,
error);
if (upload_bmp == NULL)
{
cogl_object_unref (atlas_tex);
return NULL;
@ -841,15 +843,15 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
0, /* dst_y */
bmp_width, /* dst_width */
bmp_height, /* dst_height */
dst_bmp,
upload_bmp,
error))
{
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
cogl_object_unref (atlas_tex);
return NULL;
}
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
return atlas_tex;
}

View File

@ -35,6 +35,7 @@
#include "cogl-texture.h"
#include "cogl-util.h"
#include "cogl-texture-2d.h"
#include "cogl-texture-2d-private.h"
#include "cogl-primitive-texture.h"
#include "cogl-texture-2d-sliced-private.h"
#include "cogl-private.h"
@ -46,6 +47,13 @@
#include "cogl-sub-texture.h"
#include "cogl-texture-2d-gl.h"
static CoglTexture *
_cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
CoglTexture *
cogl_texture_new_with_size (unsigned int width,
unsigned int height,
@ -128,7 +136,11 @@ _cogl_texture_new_from_data (CoglContext *ctx,
rowstride,
(uint8_t *) data);
tex = _cogl_texture_new_from_bitmap (bmp, flags, internal_format, error);
tex = _cogl_texture_new_from_bitmap (bmp,
flags,
internal_format,
FALSE, /* can't convert in place */
error);
cogl_object_unref (bmp);
@ -161,10 +173,11 @@ cogl_texture_new_from_data (int width,
return tex;
}
CoglTexture *
static CoglTexture *
_cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx = _cogl_bitmap_get_context (bitmap);
@ -176,6 +189,7 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
if ((atlas_tex = _cogl_atlas_texture_new_from_bitmap (bitmap,
flags,
internal_format,
can_convert_in_place,
&internal_error)))
return COGL_TEXTURE (atlas_tex);
@ -188,9 +202,10 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
(cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
{
tex = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap,
internal_format,
&internal_error));
tex = COGL_TEXTURE (_cogl_texture_2d_new_from_bitmap (bitmap,
internal_format,
can_convert_in_place,
&internal_error));
if (!tex)
{
@ -213,6 +228,7 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap,
flags,
internal_format,
can_convert_in_place,
error));
}
@ -226,7 +242,10 @@ cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
{
CoglError *ignore_error = NULL;
CoglTexture *tex =
_cogl_texture_new_from_bitmap (bitmap, flags, internal_format,
_cogl_texture_new_from_bitmap (bitmap,
flags,
internal_format,
FALSE, /* can't convert in-place */
&ignore_error);
if (!tex)
cogl_error_free (ignore_error);
@ -241,7 +260,6 @@ cogl_texture_new_from_file (const char *filename,
{
CoglBitmap *bmp;
CoglTexture *texture = NULL;
CoglPixelFormat src_format;
_COGL_GET_CONTEXT (ctx, NULL);
@ -251,22 +269,10 @@ cogl_texture_new_from_file (const char *filename,
if (bmp == NULL)
return NULL;
src_format = cogl_bitmap_get_format (bmp);
/* We know that the bitmap data is solely owned by this function so
we can do the premult conversion in place. This avoids having to
copy the bitmap which will otherwise happen in
_cogl_texture_prepare_for_upload */
internal_format =
_cogl_texture_determine_internal_format (src_format, internal_format);
if (!_cogl_texture_needs_premult_conversion (src_format, internal_format) ||
_cogl_bitmap_convert_premult_status (bmp,
src_format ^ COGL_PREMULT_BIT,
error))
{
texture =
_cogl_texture_new_from_bitmap (bmp, flags, internal_format, error);
}
texture = _cogl_texture_new_from_bitmap (bmp, flags,
internal_format,
TRUE, /* can convert in-place */
error);
cogl_object_unref (bmp);

View File

@ -506,6 +506,85 @@ _cogl_bitmap_convert (CoglBitmap *src_bmp,
return dst_bmp;
}
CoglBitmap *
_cogl_bitmap_convert_for_upload (CoglBitmap *src_bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx = _cogl_bitmap_get_context (src_bmp);
CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp);
CoglBitmap *dst_bmp;
_COGL_RETURN_VAL_IF_FAIL (internal_format != COGL_PIXEL_FORMAT_ANY, NULL);
/* OpenGL supports specifying a different format for the internal
format when uploading texture data. We should use this to convert
formats because it is likely to be faster and support more types
than the Cogl bitmap code. However under GLES the internal format
must be the same as the bitmap format and it only supports a
limited number of formats so we must convert using the Cogl
bitmap code instead */
/* If the driver doesn't natively support alpha textures then it
* won't work correctly to convert to/from component-alpha
* textures */
if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FORMAT_CONVERSION) &&
((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) ||
(src_format != COGL_PIXEL_FORMAT_A_8 &&
internal_format != COGL_PIXEL_FORMAT_A_8) ||
src_format == internal_format))
{
/* If the source format does not have the same premult flag as the
internal_format then we need to copy and convert it */
if (_cogl_texture_needs_premult_conversion (src_format,
internal_format))
{
if (can_convert_in_place)
{
if (_cogl_bitmap_convert_premult_status (src_bmp,
(src_format ^
COGL_PREMULT_BIT),
error))
{
dst_bmp = cogl_object_ref (src_bmp);
}
else
return NULL;
}
else
{
dst_bmp = _cogl_bitmap_convert (src_bmp,
src_format ^ COGL_PREMULT_BIT,
error);
if (dst_bmp == NULL)
return NULL;
}
}
else
dst_bmp = cogl_object_ref (src_bmp);
}
else
{
CoglPixelFormat closest_format;
closest_format =
ctx->driver_vtable->pixel_format_to_gl (ctx,
internal_format,
NULL, /* ignore gl intformat */
NULL, /* ignore gl format */
NULL); /* ignore gl type */
if (closest_format != src_format)
dst_bmp = _cogl_bitmap_convert (src_bmp, closest_format, error);
else
dst_bmp = cogl_object_ref (src_bmp);
}
return dst_bmp;
}
CoglBool
_cogl_bitmap_unpremult (CoglBitmap *bmp,
CoglError **error)

View File

@ -105,6 +105,12 @@ _cogl_bitmap_convert (CoglBitmap *bmp,
CoglPixelFormat dst_format,
CoglError **error);
CoglBitmap *
_cogl_bitmap_convert_for_upload (CoglBitmap *src_bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
CoglBool
_cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp,
CoglBitmap *dst_bmp,

View File

@ -148,6 +148,7 @@ struct _CoglDriverVtable
CoglTexture2D *
(* texture_2d_new_from_bitmap) (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)

View File

@ -59,6 +59,12 @@ struct _CoglTexture2D
CoglTexturePixel first_pixel;
};
CoglTexture2D *
_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
/* NB: The reason we require the width, height and format to be passed
* even though they may seem redundant is because GLES 1/2 don't

View File

@ -56,6 +56,7 @@ CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
#endif /* __COGL_TEXTURE_2D_SLICED_PRIVATE_H */

View File

@ -332,9 +332,9 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
}
static CoglBool
_cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
CoglBitmap *bmp,
CoglError **error)
_cogl_texture_2d_sliced_upload_bitmap (CoglTexture2DSliced *tex_2ds,
CoglBitmap *bmp,
CoglError **error)
{
CoglSpan *x_span;
CoglSpan *y_span;
@ -422,17 +422,15 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
}
static CoglBool
_cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
int src_x,
int src_y,
int dst_x,
int dst_y,
int width,
int height,
CoglBitmap *source_bmp,
GLuint source_gl_format,
GLuint source_gl_type,
CoglError **error)
_cogl_texture_2d_sliced_upload_subregion (CoglTexture2DSliced *tex_2ds,
int src_x,
int src_y,
int dst_x,
int dst_y,
int width,
int height,
CoglBitmap *source_bmp,
CoglError **error)
{
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
CoglSpan *x_span;
@ -667,16 +665,13 @@ _cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
int width,
int height,
int max_waste,
CoglPixelFormat format,
CoglPixelFormat internal_format,
CoglError **error)
{
int max_width;
int max_height;
int n_x_slices;
int n_y_slices;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
int (*slices_for_size) (int, int, int, GArray*);
@ -694,25 +689,16 @@ _cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
slices_for_size = _cogl_pot_slices_for_size;
}
ctx->driver_vtable->pixel_format_to_gl (ctx,
format,
&gl_intformat,
&gl_format,
&gl_type);
/* Negative number means no slicing forced by the user */
if (max_waste <= -1)
{
CoglSpan span;
/* Check if size supported else bail out */
if (!ctx->texture_driver->size_supported (ctx,
GL_TEXTURE_2D,
gl_intformat,
gl_format,
gl_type,
max_width,
max_height))
if (!ctx->driver_vtable->texture_2d_can_create (ctx,
max_width,
max_height,
internal_format))
{
_cogl_set_error (error,
COGL_TEXTURE_ERROR,
@ -749,13 +735,10 @@ _cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
else
{
/* Decrease the size of largest slice until supported by GL */
while (!ctx->texture_driver->size_supported (ctx,
GL_TEXTURE_2D,
gl_intformat,
gl_format,
gl_type,
max_width,
max_height))
while (!ctx->driver_vtable->texture_2d_can_create (ctx,
max_width,
max_height,
internal_format))
{
/* Alternate between width and height */
if (max_width > max_height)
@ -975,14 +958,12 @@ CoglTexture2DSliced *
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx;
CoglTexture2DSliced *tex_2ds;
CoglBitmap *dst_bmp;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
CoglBitmap *upload_bmp;
int width, height, max_waste;
int i;
@ -1001,14 +982,15 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
else
max_waste = COGL_TEXTURE_MAX_WASTE;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
&internal_format,
&gl_intformat,
&gl_format,
&gl_type,
error);
if (dst_bmp == NULL)
internal_format =
_cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
internal_format);
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
internal_format,
can_convert_in_place,
error);
if (upload_bmp == NULL)
{
_cogl_texture_2d_sliced_free (tex_2ds);
return NULL;
@ -1027,12 +1009,12 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
if (!cogl_texture_allocate (COGL_TEXTURE (tex_2ds), error))
goto error;
if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
dst_bmp,
error))
if (!_cogl_texture_2d_sliced_upload_bitmap (tex_2ds,
upload_bmp,
error))
goto error;
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
if ((flags & COGL_TEXTURE_NO_AUTO_MIPMAP))
for (i = 0; i < tex_2ds->slice_textures->len; i++)
@ -1049,7 +1031,7 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
return _cogl_texture_2d_sliced_object_new (tex_2ds);
error:
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
_cogl_texture_2d_sliced_free (tex_2ds);
return NULL;
}
@ -1359,32 +1341,24 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
CoglError **error)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
GLenum gl_format;
GLenum gl_type;
CoglBitmap *upload_bmp;
CoglBool status;
bmp = _cogl_texture_prepare_for_upload (bmp,
cogl_texture_get_format (tex),
NULL,
NULL,
&gl_format,
&gl_type,
error);
if (!bmp)
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
cogl_texture_get_format (tex),
FALSE, /* can't convert in
place */
error);
if (!upload_bmp)
return FALSE;
/* Send data to GL */
status =
_cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
bmp,
gl_format,
gl_type,
error);
cogl_object_unref (bmp);
status = _cogl_texture_2d_sliced_upload_subregion (tex_2ds,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
upload_bmp,
error);
cogl_object_unref (upload_bmp);
return status;
}

View File

@ -150,9 +150,10 @@ _cogl_texture_2d_allocate (CoglTexture *tex,
}
CoglTexture2D *
cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglError **error)
_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx;
@ -178,9 +179,18 @@ cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
return ctx->driver_vtable->texture_2d_new_from_bitmap (bmp,
internal_format,
can_convert_in_place,
error);
}
CoglTexture2D *
cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglError **error)
{
return _cogl_texture_2d_new_from_bitmap (bmp, internal_format, FALSE, error);
}
CoglTexture2D *
cogl_texture_2d_new_from_data (CoglContext *ctx,
int width,

View File

@ -279,8 +279,9 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
CoglError **error)
{
CoglTexture3D *tex_3d;
CoglBitmap *dst_bmp;
CoglBitmap *upload_bmp;
CoglPixelFormat bmp_format;
CoglPixelFormat upload_format;
unsigned int bmp_width;
GLenum gl_intformat;
GLenum gl_format;
@ -301,16 +302,27 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
error))
return NULL;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
&internal_format,
&gl_intformat,
&gl_format,
&gl_type,
error);
if (dst_bmp == NULL)
upload_bmp =
_cogl_bitmap_convert_for_upload (bmp,
internal_format,
FALSE, /* can't convert in place */
error);
if (upload_bmp == NULL)
return NULL;
upload_format = cogl_bitmap_get_format (upload_bmp);
ctx->driver_vtable->pixel_format_to_gl (ctx,
upload_format,
NULL, /* internal format */
&gl_format,
&gl_type);
ctx->driver_vtable->pixel_format_to_gl (ctx,
internal_format,
&gl_intformat,
NULL,
NULL);
tex_3d = _cogl_texture_3d_create_base (ctx,
bmp_width, height, depth,
internal_format);
@ -320,20 +332,18 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
{
CoglError *ignore = NULL;
uint8_t *data = _cogl_bitmap_map (dst_bmp,
uint8_t *data = _cogl_bitmap_map (upload_bmp,
COGL_BUFFER_ACCESS_READ, 0,
&ignore);
CoglPixelFormat format = cogl_bitmap_get_format (dst_bmp);
tex_3d->first_pixel.gl_format = gl_format;
tex_3d->first_pixel.gl_type = gl_type;
if (data)
{
memcpy (tex_3d->first_pixel.data, data,
_cogl_pixel_format_get_bytes_per_pixel (format));
_cogl_bitmap_unmap (dst_bmp);
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
_cogl_bitmap_unmap (upload_bmp);
}
else
{
@ -341,7 +351,7 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
"glGenerateMipmap fallback");
cogl_error_free (ignore);
memset (tex_3d->first_pixel.data, 0,
_cogl_pixel_format_get_bytes_per_pixel (format));
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
}
}
@ -354,20 +364,20 @@ cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
FALSE, /* is_foreign */
height,
depth,
dst_bmp,
upload_bmp,
gl_intformat,
gl_format,
gl_type,
error))
{
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
cogl_object_unref (tex_3d);
return NULL;
}
tex_3d->gl_format = gl_intformat;
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
_cogl_texture_set_allocated (COGL_TEXTURE (tex_3d), TRUE);

View File

@ -65,9 +65,9 @@ struct _CoglTextureVtable
/* 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
_cogl_texture_prepare_for_upload with a suitable destination
format before uploading */
before being set so the caller is expected to have called
_cogl_bitmap_convert_for_upload with a suitable internal_format
before passing here */
CoglBool (* set_region) (CoglTexture *tex,
int src_x,
int src_y,
@ -227,21 +227,6 @@ CoglPixelFormat
_cogl_texture_determine_internal_format (CoglPixelFormat src_format,
CoglPixelFormat dst_format);
/* Utility function to help uploading a bitmap. If the bitmap needs
* premult conversion then a converted copy will be returned,
* otherwise a reference to the original source will be returned.
*
* The GLenums needed for uploading are returned
*/
CoglBitmap *
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
CoglPixelFormat dst_format,
CoglPixelFormat *dst_format_out,
GLenum *out_glintformat,
GLenum *out_glformat,
GLenum *out_gltype,
CoglError **error);
CoglBool
_cogl_texture_is_foreign (CoglTexture *texture);
@ -293,12 +278,6 @@ _cogl_texture_set_region (CoglTexture *texture,
int level,
CoglError **error);
CoglTexture *
_cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
CoglError **error);
CoglBool
_cogl_texture_set_region_from_bitmap (CoglTexture *texture,
int src_x,

View File

@ -276,11 +276,11 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
CoglError **error)
{
CoglTextureRectangle *tex_rect;
CoglBitmap *dst_bmp;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
CoglContext *ctx;
CoglBitmap *upload_bmp;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
CoglContext *ctx;
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
@ -297,17 +297,25 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
error))
return NULL;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
&internal_format,
&gl_intformat,
&gl_format,
&gl_type,
error);
if (dst_bmp == NULL)
upload_bmp =
_cogl_bitmap_convert_for_upload (bmp,
internal_format,
FALSE, /* can't convert in place */
error);
if (upload_bmp == NULL)
return NULL;
ctx->driver_vtable->pixel_format_to_gl (ctx,
cogl_bitmap_get_format (upload_bmp),
NULL, /* internal format */
&gl_format,
&gl_type);
ctx->driver_vtable->pixel_format_to_gl (ctx,
internal_format,
&gl_intformat,
NULL,
NULL);
tex_rect = _cogl_texture_rectangle_create_base (ctx,
cogl_bitmap_get_width (bmp),
cogl_bitmap_get_height (bmp),
@ -321,20 +329,20 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
GL_TEXTURE_RECTANGLE_ARB,
tex_rect->gl_texture,
FALSE,
dst_bmp,
upload_bmp,
gl_intformat,
gl_format,
gl_type,
error))
{
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
cogl_object_unref (tex_rect);
return NULL;
}
tex_rect->gl_format = gl_intformat;
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), TRUE);
@ -585,21 +593,26 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
CoglBitmap *bmp,
CoglError **error)
{
CoglBitmap *upload_bmp;
GLenum gl_format;
GLenum gl_type;
CoglContext *ctx = tex->context;
CoglBool status;
bmp = _cogl_texture_prepare_for_upload (bmp,
cogl_texture_get_format (tex),
NULL,
NULL,
&gl_format,
&gl_type,
error);
if (!bmp)
upload_bmp =
_cogl_bitmap_convert_for_upload (bmp,
cogl_texture_get_format (tex),
FALSE, /* can't convert in place */
error);
if (upload_bmp == NULL)
return FALSE;
ctx->driver_vtable->pixel_format_to_gl (ctx,
cogl_bitmap_get_format (upload_bmp),
NULL, /* internal format */
&gl_format,
&gl_type);
/* Send data to GL */
status =
ctx->texture_driver->upload_subregion_to_gl (ctx,
@ -609,12 +622,12 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
dst_x, dst_y,
dst_width, dst_height,
level,
bmp,
upload_bmp,
gl_format,
gl_type,
error);
cogl_object_unref (bmp);
cogl_object_unref (upload_bmp);
return status;
}

View File

@ -192,92 +192,6 @@ _cogl_texture_determine_internal_format (CoglPixelFormat src_format,
return dst_format;
}
CoglBitmap *
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
CoglPixelFormat dst_format,
CoglPixelFormat *dst_format_out,
GLenum *out_glintformat,
GLenum *out_glformat,
GLenum *out_gltype,
CoglError **error)
{
CoglContext *ctx = _cogl_bitmap_get_context (src_bmp);
CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp);
CoglBitmap *dst_bmp;
dst_format = _cogl_texture_determine_internal_format (src_format,
dst_format);
/* OpenGL supports specifying a different format for the internal
format when uploading texture data. We should use this to convert
formats because it is likely to be faster and support more types
than the Cogl bitmap code. However under GLES the internal format
must be the same as the bitmap format and it only supports a
limited number of formats so we must convert using the Cogl
bitmap code instead */
/* If the driver doesn't natively support alpha textures then it
* won't work correctly to convert to/from component-alpha
* textures */
if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_FORMAT_CONVERSION) &&
((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) ||
(src_format != COGL_PIXEL_FORMAT_A_8 &&
dst_format != COGL_PIXEL_FORMAT_A_8) ||
src_format == dst_format))
{
/* If the source format does not have the same premult flag as the
dst format then we need to copy and convert it */
if (_cogl_texture_needs_premult_conversion (src_format,
dst_format))
{
dst_bmp = _cogl_bitmap_convert (src_bmp,
src_format ^ COGL_PREMULT_BIT,
error);
if (dst_bmp == NULL)
return NULL;
}
else
dst_bmp = cogl_object_ref (src_bmp);
/* Use the source format from the src bitmap type and the internal
format from the dst format type so that GL can do the
conversion */
ctx->driver_vtable->pixel_format_to_gl (ctx,
src_format,
NULL, /* internal format */
out_glformat,
out_gltype);
ctx->driver_vtable->pixel_format_to_gl (ctx,
dst_format,
out_glintformat,
NULL,
NULL);
}
else
{
CoglPixelFormat closest_format;
closest_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
dst_format,
out_glintformat,
out_glformat,
out_gltype);
if (closest_format != src_format)
dst_bmp = _cogl_bitmap_convert (src_bmp, closest_format, error);
else
dst_bmp = cogl_object_ref (src_bmp);
}
if (dst_format_out)
*dst_format_out = dst_format;
return dst_bmp;
}
CoglBool
_cogl_texture_is_foreign (CoglTexture *texture)
{

View File

@ -51,6 +51,7 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
CoglTexture2D *
_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)

View File

@ -151,25 +151,34 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
CoglTexture2D *
_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
CoglTexture2D *tex_2d;
CoglBitmap *dst_bmp;
CoglBitmap *upload_bmp;
GLenum gl_intformat;
GLenum gl_format;
GLenum gl_type;
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
internal_format,
&internal_format,
&gl_intformat,
&gl_format,
&gl_type,
error);
if (!dst_bmp)
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
internal_format,
can_convert_in_place,
error);
if (upload_bmp == NULL)
return NULL;
ctx->driver_vtable->pixel_format_to_gl (ctx,
cogl_bitmap_get_format (upload_bmp),
NULL, /* internal format */
&gl_format,
&gl_type);
ctx->driver_vtable->pixel_format_to_gl (ctx,
internal_format,
&gl_intformat,
NULL,
NULL);
tex_2d = _cogl_texture_2d_create_base (ctx,
cogl_bitmap_get_width (bmp),
cogl_bitmap_get_height (bmp),
@ -180,10 +189,10 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
{
CoglError *ignore = NULL;
uint8_t *data = _cogl_bitmap_map (dst_bmp,
uint8_t *data = _cogl_bitmap_map (upload_bmp,
COGL_BUFFER_ACCESS_READ, 0,
&ignore);
CoglPixelFormat format = cogl_bitmap_get_format (dst_bmp);
CoglPixelFormat format = cogl_bitmap_get_format (upload_bmp);
tex_2d->first_pixel.gl_format = gl_format;
tex_2d->first_pixel.gl_type = gl_type;
@ -192,7 +201,7 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
{
memcpy (tex_2d->first_pixel.data, data,
_cogl_pixel_format_get_bytes_per_pixel (format));
_cogl_bitmap_unmap (dst_bmp);
_cogl_bitmap_unmap (upload_bmp);
}
else
{
@ -210,25 +219,24 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
GL_TEXTURE_2D,
tex_2d->gl_texture,
FALSE,
dst_bmp,
upload_bmp,
gl_intformat,
gl_format,
gl_type,
error))
{
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
cogl_object_unref (tex_2d);
return NULL;
}
tex_2d->gl_internal_format = gl_intformat;
cogl_object_unref (dst_bmp);
cogl_object_unref (upload_bmp);
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
return tex_2d;
}
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
@ -555,29 +563,37 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
{
CoglTexture *tex = COGL_TEXTURE (tex_2d);
CoglContext *ctx = tex->context;
CoglBitmap *upload_bmp;
CoglPixelFormat upload_format;
GLenum gl_format;
GLenum gl_type;
CoglBool status = TRUE;
bmp = _cogl_texture_prepare_for_upload (bmp,
cogl_texture_get_format (tex),
NULL,
NULL,
&gl_format,
&gl_type,
error);
if (!bmp)
upload_bmp =
_cogl_bitmap_convert_for_upload (bmp,
cogl_texture_get_format (tex),
FALSE, /* can't convert in place */
error);
if (upload_bmp == NULL)
return FALSE;
upload_format = cogl_bitmap_get_format (upload_bmp);
ctx->driver_vtable->pixel_format_to_gl (ctx,
upload_format,
NULL, /* internal format */
&gl_format,
&gl_type);
/* If this touches the first pixel then we'll update our copy */
if (dst_x == 0 && dst_y == 0 &&
!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
{
CoglError *ignore = NULL;
uint8_t *data =
_cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore);
_cogl_bitmap_map (upload_bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore);
CoglPixelFormat bpp =
_cogl_pixel_format_get_bytes_per_pixel (cogl_bitmap_get_format (bmp));
_cogl_pixel_format_get_bytes_per_pixel (upload_format);
tex_2d->first_pixel.gl_format = gl_format;
tex_2d->first_pixel.gl_type = gl_type;
@ -585,7 +601,9 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
if (data)
{
memcpy (tex_2d->first_pixel.data,
data + cogl_bitmap_get_rowstride (bmp) * src_y + bpp * src_x,
(data +
cogl_bitmap_get_rowstride (upload_bmp) * src_y +
bpp * src_x),
bpp);
_cogl_bitmap_unmap (bmp);
}
@ -605,12 +623,12 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
dst_x, dst_y,
width, height,
level,
bmp,
upload_bmp,
gl_format,
gl_type,
error);
cogl_object_unref (bmp);
cogl_object_unref (upload_bmp);
_cogl_texture_gl_maybe_update_max_level (tex, level);

View File

@ -51,6 +51,7 @@ _cogl_texture_2d_nop_allocate (CoglTexture *tex,
CoglTexture2D *
_cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error);
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)

View File

@ -65,6 +65,7 @@ _cogl_texture_2d_nop_allocate (CoglTexture *tex,
CoglTexture2D *
_cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglBool can_convert_in_place,
CoglError **error)
{
return _cogl_texture_2d_create_base (_cogl_bitmap_get_context (bmp),