From 9750b90f37127c85f7092c16ca64fb0b63501882 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 26 Mar 2010 22:34:56 +0000 Subject: [PATCH] cogl-bitmap: Fix converting formats with and without alpha channels _cogl_bitmap_convert_format_and_premult was failing when converting from RGBA to RGB and vice versa. _cogl_bitmap_fallback_convert converts without altering the premult status so when choosing a new format it would copy over the premult bit. However, it did this regardless of whether the new format had an alpha channel so when converting from RGBA_8888_PRE to RGB_888 it would end up inventing a new meaningless format which would be RGB_888_PRE. This patch makes it avoid copying the premult flag if the destination has no alpha. It doesn't matter if it copies when the source format has no alpha because it will always be unset. _cogl_bitmap_convert_format_and_premult was also breaking when converting from RGBA_8888_PRE to RGB_888 because it would think RGB_888 is unpremultiplied and try to convert but then _cogl_bitmap_fallback_premult wouldn't know how to do the conversion. http://bugzilla.openedhand.com/show_bug.cgi?id=2057 --- clutter/cogl/cogl/cogl-bitmap-fallback.c | 8 ++++++-- clutter/cogl/cogl/cogl-bitmap.c | 10 +++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clutter/cogl/cogl/cogl-bitmap-fallback.c b/clutter/cogl/cogl/cogl-bitmap-fallback.c index 00428d57a..a1802980f 100644 --- a/clutter/cogl/cogl/cogl-bitmap-fallback.c +++ b/clutter/cogl/cogl/cogl-bitmap-fallback.c @@ -359,8 +359,12 @@ _cogl_bitmap_fallback_convert (const CoglBitmap *bmp, /* Initialize destination bitmap */ *dst_bmp = *bmp; dst_bmp->rowstride = sizeof(guint8) * dst_bpp * dst_bmp->width; - dst_bmp->format = ((bmp->format & COGL_PREMULT_BIT) | - (dst_format & COGL_UNPREMULT_MASK)); + /* Copy the premult bit if the new format has an alpha channel */ + if ((dst_format & COGL_A_BIT)) + dst_bmp->format = ((bmp->format & COGL_PREMULT_BIT) | + (dst_format & COGL_UNPREMULT_MASK)); + else + dst_bmp->format = dst_format; /* Allocate a new buffer to hold converted data */ dst_bmp->data = g_malloc (sizeof(guint8) diff --git a/clutter/cogl/cogl/cogl-bitmap.c b/clutter/cogl/cogl/cogl-bitmap.c index 3b00cb8c9..77a28c76a 100644 --- a/clutter/cogl/cogl/cogl-bitmap.c +++ b/clutter/cogl/cogl/cogl-bitmap.c @@ -107,7 +107,15 @@ _cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp, dst_bmp->data = g_memdup (bmp->data, bmp->rowstride * bmp->height); } - if (!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format)) + /* We only need to do a premult conversion if both formats have an + alpha channel. If we're converting from RGB to RGBA then the + alpha will have been filled with 255 so the premult won't do + anything or if we are converting from RGBA to RGB we're losing + information so either converting or not will be wrong for + transparent pixels */ + if ((dst_bmp->format & COGL_A_BIT) == COGL_A_BIT && + (dst_format & COGL_A_BIT) == COGL_A_BIT && + !_cogl_bitmap_convert_premult_status (dst_bmp, dst_format)) { g_free (dst_bmp->data); return FALSE;