diff --git a/cogl/cogl-atlas-texture-private.h b/cogl/cogl-atlas-texture-private.h index 670eea454..75c740e04 100644 --- a/cogl/cogl-atlas-texture-private.h +++ b/cogl/cogl-atlas-texture-private.h @@ -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 * diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c index 30dd319e5..6abc585cb 100644 --- a/cogl/cogl-atlas-texture.c +++ b/cogl/cogl-atlas-texture.c @@ -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; } diff --git a/cogl/cogl-auto-texture.c b/cogl/cogl-auto-texture.c index 9a5819d94..26a192bb2 100644 --- a/cogl/cogl-auto-texture.c +++ b/cogl/cogl-auto-texture.c @@ -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); diff --git a/cogl/cogl-bitmap-conversion.c b/cogl/cogl-bitmap-conversion.c index 259783ec0..add221eb0 100644 --- a/cogl/cogl-bitmap-conversion.c +++ b/cogl/cogl-bitmap-conversion.c @@ -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) diff --git a/cogl/cogl-bitmap-private.h b/cogl/cogl-bitmap-private.h index ae96aafd5..34ad4cfec 100644 --- a/cogl/cogl-bitmap-private.h +++ b/cogl/cogl-bitmap-private.h @@ -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, diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h index 196f5a19f..ca62c44ab 100644 --- a/cogl/cogl-driver.h +++ b/cogl/cogl-driver.h @@ -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) diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h index 12e582024..5d193bceb 100644 --- a/cogl/cogl-texture-2d-private.h +++ b/cogl/cogl-texture-2d-private.h @@ -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 diff --git a/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl-texture-2d-sliced-private.h index fbfd1982b..2d5106f9e 100644 --- a/cogl/cogl-texture-2d-sliced-private.h +++ b/cogl/cogl-texture-2d-sliced-private.h @@ -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 */ diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index 17184bbf0..f083e92da 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -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; } diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index d8c293901..d9cc03145 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -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, diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c index b40448a7f..fd1b21e35 100644 --- a/cogl/cogl-texture-3d.c +++ b/cogl/cogl-texture-3d.c @@ -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); diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h index 7e70e5efa..b17dc257b 100644 --- a/cogl/cogl-texture-private.h +++ b/cogl/cogl-texture-private.h @@ -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, diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c index 6e30622a5..8d25fb86c 100644 --- a/cogl/cogl-texture-rectangle.c +++ b/cogl/cogl-texture-rectangle.c @@ -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; } diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index fbc1b01a2..a616891c3 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -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) { diff --git a/cogl/driver/gl/cogl-texture-2d-gl-private.h b/cogl/driver/gl/cogl-texture-2d-gl-private.h index c71908fc0..0bab9e256 100644 --- a/cogl/driver/gl/cogl-texture-2d-gl-private.h +++ b/cogl/driver/gl/cogl-texture-2d-gl-private.h @@ -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) diff --git a/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/driver/gl/cogl-texture-2d-gl.c index 98c155395..2a79f67af 100644 --- a/cogl/driver/gl/cogl-texture-2d-gl.c +++ b/cogl/driver/gl/cogl-texture-2d-gl.c @@ -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); diff --git a/cogl/driver/nop/cogl-texture-2d-nop-private.h b/cogl/driver/nop/cogl-texture-2d-nop-private.h index 1aa558a15..f822a7f15 100644 --- a/cogl/driver/nop/cogl-texture-2d-nop-private.h +++ b/cogl/driver/nop/cogl-texture-2d-nop-private.h @@ -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) diff --git a/cogl/driver/nop/cogl-texture-2d-nop.c b/cogl/driver/nop/cogl-texture-2d-nop.c index 5831e2790..b63a7b7a4 100644 --- a/cogl/driver/nop/cogl-texture-2d-nop.c +++ b/cogl/driver/nop/cogl-texture-2d-nop.c @@ -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),