diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c index 986707f42..08e1db90f 100644 --- a/cogl/cogl-atlas-texture.c +++ b/cogl/cogl-atlas-texture.c @@ -488,6 +488,52 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex, return TRUE; } +static CoglBitmap * +_cogl_atlas_texture_prepare_for_upload (CoglAtlasTexture *atlas_tex, + CoglBitmap *bmp) +{ + CoglPixelFormat internal_format; + CoglBitmap *converted_bmp; + CoglBitmap *override_bmp; + + /* We'll prepare to upload using the format of the actual texture of + the atlas texture instead of the format reported by + cogl_texture_get_format which would be the original internal + format specified when the texture was created. However we'll + preserve the premult status of the internal format because the + images are all stored in the original premult format of the + orignal format so we do need to trigger the conversion */ + + 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 */); + + if (converted_bmp == NULL) + return NULL; + + /* We'll create another bitmap which uses the same data but + overrides the format to remove the premult flag so that uploads + 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_PREMULT_BIT, + _cogl_bitmap_get_width (converted_bmp), + _cogl_bitmap_get_height (converted_bmp), + _cogl_bitmap_get_rowstride (converted_bmp)); + + cogl_object_unref (converted_bmp); + + return override_bmp; +} + static gboolean _cogl_atlas_texture_set_region (CoglTexture *tex, int src_x, @@ -506,12 +552,8 @@ _cogl_atlas_texture_set_region (CoglTexture *tex, { gboolean ret; - bmp = _cogl_bitmap_new_shared (bmp, - _cogl_bitmap_get_format (bmp) & - ~COGL_PREMULT_BIT, - _cogl_bitmap_get_width (bmp), - _cogl_bitmap_get_height (bmp), - _cogl_bitmap_get_rowstride (bmp)); + bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex, + bmp); /* Upload the data ignoring the premult bit */ ret = _cogl_atlas_texture_set_region_with_border (atlas_tex, @@ -684,10 +726,6 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, CoglHandle atlas_tex_handle; CoglAtlasTexture *atlas_tex; CoglBitmap *dst_bmp; - CoglBitmap *override_bmp; - GLenum gl_intformat; - GLenum gl_format; - GLenum gl_type; int bmp_width; int bmp_height; CoglPixelFormat bmp_format; @@ -711,12 +749,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, atlas_tex = atlas_tex_handle; - dst_bmp = _cogl_texture_prepare_for_upload (bmp, - internal_format, - &internal_format, - &gl_intformat, - &gl_format, - &gl_type); + dst_bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex, + bmp); if (dst_bmp == NULL) { @@ -724,19 +758,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, return COGL_INVALID_HANDLE; } - /* Make another bitmap so that we can override the format */ - override_bmp = _cogl_bitmap_new_shared (dst_bmp, - _cogl_bitmap_get_format (dst_bmp) & - ~COGL_PREMULT_BIT, - _cogl_bitmap_get_width (dst_bmp), - _cogl_bitmap_get_height (dst_bmp), - _cogl_bitmap_get_rowstride (dst_bmp)); - cogl_object_unref (dst_bmp); - /* Defer to set_region so that we can share the code for copying the - edge pixels to the border. We don't want to pass the actual - format of the converted texture because otherwise it will get - unpremultiplied. */ + edge pixels to the border. */ _cogl_atlas_texture_set_region_with_border (atlas_tex, 0, /* src_x */ 0, /* src_y */ @@ -744,9 +767,9 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, 0, /* dst_y */ bmp_width, /* dst_width */ bmp_height, /* dst_height */ - override_bmp); + dst_bmp); - cogl_object_unref (override_bmp); + cogl_object_unref (dst_bmp); return atlas_tex_handle; } diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index 0775277c4..f59261733 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -1325,10 +1325,12 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex, _COGL_GET_CONTEXT (ctx, FALSE); - ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + bmp = _cogl_texture_prepare_for_upload (bmp, + cogl_texture_get_format (tex), + NULL, + NULL, + &gl_format, + &gl_type); /* Send data to GL */ _cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds, @@ -1339,6 +1341,8 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex, gl_format, gl_type); + cogl_object_unref (bmp); + return TRUE; } diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 71ff44ad0..f800fcb49 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -816,10 +816,12 @@ _cogl_texture_2d_set_region (CoglTexture *tex, _COGL_GET_CONTEXT (ctx, FALSE); - ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + bmp = _cogl_texture_prepare_for_upload (bmp, + cogl_texture_get_format (tex), + NULL, + NULL, + &gl_format, + &gl_type); /* If this touches the first pixel then we'll update our copy */ if (dst_x == 0 && dst_y == 0 && @@ -850,6 +852,8 @@ _cogl_texture_2d_set_region (CoglTexture *tex, tex_2d->mipmaps_dirty = TRUE; + cogl_object_unref (bmp); + return TRUE; } diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h index 767069a4e..01fba91b6 100644 --- a/cogl/cogl-texture-private.h +++ b/cogl/cogl-texture-private.h @@ -67,8 +67,10 @@ struct _CoglTextureVtable backend */ /* This should update the specified sub region of the texture with a - sub region of the given bitmap. The bitmap will have first been - converted to a suitable format for uploading if neccessary. */ + 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 */ gboolean (* set_region) (CoglTexture *tex, int src_x, int src_y, diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c index e98be8d95..ca12fcb0c 100644 --- a/cogl/cogl-texture-rectangle.c +++ b/cogl/cogl-texture-rectangle.c @@ -564,10 +564,12 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex, _COGL_GET_CONTEXT (ctx, FALSE); - ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + bmp = _cogl_texture_prepare_for_upload (bmp, + cogl_texture_get_format (tex), + NULL, + NULL, + &gl_format, + &gl_type); /* Send data to GL */ ctx->texture_driver->upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB, @@ -580,6 +582,8 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex, gl_format, gl_type); + cogl_object_unref (bmp); + return TRUE; } diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index 165811f9e..8a6fbd2a3 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -862,22 +862,18 @@ cogl_texture_set_region_from_bitmap (CoglHandle handle, CoglBitmap *bmp) { CoglTexture *tex = COGL_TEXTURE (handle); - GLenum closest_gl_format; - GLenum closest_gl_type; gboolean ret; /* Shortcut out early if the image is empty */ if (dst_width == 0 || dst_height == 0) return TRUE; - /* Prepare the bitmap so that it will do the premultiplication - conversion */ - bmp = _cogl_texture_prepare_for_upload (bmp, - cogl_texture_get_format (handle), - NULL, - NULL, - &closest_gl_format, - &closest_gl_type); + /* Note that we don't prepare the bitmap for upload here because + some backends may be internally using a different format for the + actual GL texture than that reported by + cogl_texture_get_format. For example the atlas textures are + always stored in an RGBA texture even if the texture format is + advertised as RGB. */ ret = tex->vtable->set_region (handle, src_x, src_y, @@ -885,8 +881,6 @@ cogl_texture_set_region_from_bitmap (CoglHandle handle, dst_width, dst_height, bmp); - cogl_object_unref (bmp); - return ret; }