diff --git a/clutter/cogl/cogl/cogl-atlas-texture.c b/clutter/cogl/cogl/cogl-atlas-texture.c index 545c68db5..efd8052a5 100644 --- a/clutter/cogl/cogl/cogl-atlas-texture.c +++ b/clutter/cogl/cogl/cogl-atlas-texture.c @@ -543,9 +543,9 @@ _cogl_atlas_texture_set_region (CoglTexture *tex, if (closest_format != format) { /* Convert to required format */ - success = _cogl_bitmap_convert_and_premult (&source_bmp, - &temp_bmp, - closest_format); + success = _cogl_bitmap_convert_format_and_premult (&source_bmp, + &temp_bmp, + closest_format); /* Swap bitmaps if succeeded */ if (!success) return FALSE; diff --git a/clutter/cogl/cogl/cogl-bitmap-fallback.c b/clutter/cogl/cogl/cogl-bitmap-fallback.c index ddff6ea40..097cc5292 100644 --- a/clutter/cogl/cogl/cogl-bitmap-fallback.c +++ b/clutter/cogl/cogl/cogl-bitmap-fallback.c @@ -150,7 +150,7 @@ _cogl_rgba_to_abgr (const guchar *src, guchar *dst) /* (Un)Premultiplication */ inline static void -_cogl_unpremult_alpha_0 (const guchar *src, guchar *dst) +_cogl_unpremult_alpha_0 (guchar *dst) { dst[0] = 0; dst[1] = 0; @@ -159,58 +159,58 @@ _cogl_unpremult_alpha_0 (const guchar *src, guchar *dst) } inline static void -_cogl_unpremult_alpha_last (const guchar *src, guchar *dst) +_cogl_unpremult_alpha_last (guchar *dst) { - guchar alpha = src[3]; + guchar alpha = dst[3]; - dst[0] = (src[0] * 255) / alpha; - dst[1] = (src[1] * 255) / alpha; - dst[2] = (src[2] * 255) / alpha; - dst[3] = alpha; + dst[0] = (dst[0] * 255) / alpha; + dst[1] = (dst[1] * 255) / alpha; + dst[2] = (dst[2] * 255) / alpha; } inline static void -_cogl_unpremult_alpha_first (const guchar *src, guchar *dst) +_cogl_unpremult_alpha_first (guchar *dst) { - guchar alpha = src[0]; + guchar alpha = dst[0]; - dst[0] = alpha; - dst[1] = (src[1] * 255) / alpha; - dst[2] = (src[2] * 255) / alpha; - dst[3] = (src[3] * 255) / alpha; + dst[1] = (dst[1] * 255) / alpha; + dst[2] = (dst[2] * 255) / alpha; + dst[3] = (dst[3] * 255) / alpha; } /* No division form of floor((c*a + 128)/255) (I first encountered * this in the RENDER implementation in the X server.) Being exact * is important for a == 255 - we want to get exactly c. */ -#define MULT(d,c,a,t) G_STMT_START { t = c * a + 128; d = ((t >> 8) + t) >> 8; } G_STMT_END +#define MULT(d,a,t) \ + G_STMT_START { \ + t = d * a + 128; \ + d = ((t >> 8) + t) >> 8; \ + } G_STMT_END inline static void -_cogl_premult_alpha_last (const guchar *src, guchar *dst) +_cogl_premult_alpha_last (guchar *dst) { - guchar alpha = src[3]; + guchar alpha = dst[3]; /* Using a separate temporary per component has given slightly better * code generation with GCC in the past; it shouldn't do any worse in * any case. */ guint t1, t2, t3; - MULT(dst[0], src[0], alpha, t1); - MULT(dst[1], src[1], alpha, t2); - MULT(dst[2], src[2], alpha, t3); - dst[3] = alpha; + MULT(dst[0], alpha, t1); + MULT(dst[1], alpha, t2); + MULT(dst[2], alpha, t3); } inline static void -_cogl_premult_alpha_first (const guchar *src, guchar *dst) +_cogl_premult_alpha_first (guchar *dst) { - guchar alpha = src[0]; + guchar alpha = dst[0]; guint t1, t2, t3; - dst[0] = alpha; - MULT(dst[1], src[1], alpha, t1); - MULT(dst[2], src[2], alpha, t2); - MULT(dst[3], src[3], alpha, t3); + MULT(dst[1], alpha, t1); + MULT(dst[2], alpha, t2); + MULT(dst[3], alpha, t3); } #undef MULT @@ -342,56 +342,39 @@ _cogl_bitmap_fallback_convert (const CoglBitmap *bmp, } gboolean -_cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp) +_cogl_bitmap_fallback_unpremult (CoglBitmap *bmp) { - guchar *src; - guchar *dst; - gint bpp; + guchar *p; gint x,y; /* Make sure format supported for un-premultiplication */ if (!_cogl_bitmap_fallback_can_unpremult (bmp->format)) return FALSE; - bpp = _cogl_get_format_bpp (bmp->format); - - /* Initialize destination bitmap */ - *dst_bmp = *bmp; - dst_bmp->format = (bmp->format & COGL_UNPREMULT_MASK); - - /* Allocate a new buffer to hold converted data */ - dst_bmp->data = g_malloc (sizeof(guchar) - * dst_bmp->height - * dst_bmp->rowstride); - for (y = 0; y < bmp->height; y++) { - src = (guchar*)bmp->data + y * bmp->rowstride; - dst = (guchar*)dst_bmp->data + y * dst_bmp->rowstride; + p = (guchar*) bmp->data + y * bmp->rowstride; if (bmp->format & COGL_AFIRST_BIT) { for (x = 0; x < bmp->width; x++) { - if (src[0] == 0) - _cogl_unpremult_alpha_0 (src, dst); + if (p[0] == 0) + _cogl_unpremult_alpha_0 (p); else - _cogl_unpremult_alpha_first (src, dst); - src += bpp; - dst += bpp; + _cogl_unpremult_alpha_first (p); + p += 4; } } else { for (x = 0; x < bmp->width; x++) { - if (src[0] == 0) - _cogl_unpremult_alpha_0 (src, dst); + if (p[3] == 0) + _cogl_unpremult_alpha_0 (p); else - _cogl_unpremult_alpha_last (src, dst); - src += bpp; - dst += bpp; + _cogl_unpremult_alpha_last (p); + p += 4; } } } @@ -400,52 +383,35 @@ _cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp, } gboolean -_cogl_bitmap_fallback_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp) +_cogl_bitmap_fallback_premult (CoglBitmap *bmp) { - guchar *src; - guchar *dst; - gint bpp; + guchar *p; gint x,y; /* Make sure format supported for un-premultiplication */ if (!_cogl_bitmap_fallback_can_premult (bmp->format)) return FALSE; - bpp = _cogl_get_format_bpp (bmp->format); - - /* Initialize destination bitmap */ - *dst_bmp = *bmp; - dst_bmp->format |= COGL_PREMULT_BIT; - - /* Allocate a new buffer to hold converted data */ - dst_bmp->data = g_malloc (sizeof(guchar) - * dst_bmp->height - * dst_bmp->rowstride); - for (y = 0; y < bmp->height; y++) { - src = (guchar*)bmp->data + y * bmp->rowstride; - dst = (guchar*)dst_bmp->data + y * dst_bmp->rowstride; + p = (guchar*) bmp->data + y * bmp->rowstride; if (bmp->format & COGL_AFIRST_BIT) - { - for (x = 0; x < bmp->width; x++) - { - _cogl_premult_alpha_first (src, dst); - src += bpp; - dst += bpp; - } - } + { + for (x = 0; x < bmp->width; x++) + { + _cogl_premult_alpha_first (p); + p += 4; + } + } else - { - for (x = 0; x < bmp->width; x++) - { - _cogl_premult_alpha_last (src, dst); - src += bpp; - dst += bpp; - } - } + { + for (x = 0; x < bmp->width; x++) + { + _cogl_premult_alpha_last (p); + p += 4; + } + } } return TRUE; diff --git a/clutter/cogl/cogl/cogl-bitmap-pixbuf.c b/clutter/cogl/cogl/cogl-bitmap-pixbuf.c index 79ed62a7f..b1a756a24 100644 --- a/clutter/cogl/cogl/cogl-bitmap-pixbuf.c +++ b/clutter/cogl/cogl/cogl-bitmap-pixbuf.c @@ -64,15 +64,13 @@ _cogl_bitmap_convert (const CoglBitmap *bmp, } gboolean -_cogl_bitmap_unpremult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp) +_cogl_bitmap_unpremult (CoglBitmap *dst_bmp) { return FALSE; } gboolean -_cogl_bitmap_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp) +_cogl_bitmap_premult (CoglBitmap *dst_bmp) { return FALSE; } diff --git a/clutter/cogl/cogl/cogl-bitmap-private.h b/clutter/cogl/cogl/cogl-bitmap-private.h index b6e425733..803e10bb0 100644 --- a/clutter/cogl/cogl/cogl-bitmap-private.h +++ b/clutter/cogl/cogl/cogl-bitmap-private.h @@ -68,20 +68,16 @@ _cogl_bitmap_fallback_convert (const CoglBitmap *bmp, CoglPixelFormat dst_format); gboolean -_cogl_bitmap_unpremult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp); +_cogl_bitmap_unpremult (CoglBitmap *dst_bmp); gboolean -_cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp); +_cogl_bitmap_fallback_unpremult (CoglBitmap *dst_bmp); gboolean -_cogl_bitmap_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp); +_cogl_bitmap_premult (CoglBitmap *dst_bmp); gboolean -_cogl_bitmap_fallback_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp); +_cogl_bitmap_fallback_premult (CoglBitmap *dst_bmp); gboolean _cogl_bitmap_from_file (CoglBitmap *bmp, @@ -93,9 +89,13 @@ _cogl_bitmap_fallback_from_file (CoglBitmap *bmp, const gchar *filename); gboolean -_cogl_bitmap_convert_and_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp, - CoglPixelFormat dst_format); +_cogl_bitmap_convert_premult_status (CoglBitmap *bmp, + CoglPixelFormat dst_format); + +gboolean +_cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp, + CoglBitmap *dst_bmp, + CoglPixelFormat dst_format); void _cogl_bitmap_copy_subregion (CoglBitmap *src, diff --git a/clutter/cogl/cogl/cogl-bitmap.c b/clutter/cogl/cogl/cogl-bitmap.c index 3dc7fd534..fe3cbdb72 100644 --- a/clutter/cogl/cogl/cogl-bitmap.c +++ b/clutter/cogl/cogl/cogl-bitmap.c @@ -61,84 +61,58 @@ _cogl_get_format_bpp (CoglPixelFormat format) } gboolean -_cogl_bitmap_convert_and_premult (const CoglBitmap *bmp, - CoglBitmap *dst_bmp, - CoglPixelFormat dst_format) +_cogl_bitmap_convert_premult_status (CoglBitmap *bmp, + CoglPixelFormat dst_format) { - CoglBitmap tmp_bmp = *bmp; - CoglBitmap new_bmp = *bmp; - gboolean new_bmp_owner = FALSE; + /* Do we need to unpremultiply? */ + if ((bmp->format & COGL_PREMULT_BIT) > 0 && + (dst_format & COGL_PREMULT_BIT) == 0) + /* Try unpremultiplying using imaging library */ + return (_cogl_bitmap_unpremult (bmp) + /* ... or try fallback */ + || _cogl_bitmap_fallback_unpremult (bmp)); + /* Do we need to premultiply? */ + if ((bmp->format & COGL_PREMULT_BIT) == 0 && + (dst_format & COGL_PREMULT_BIT) > 0) + /* Try premultiplying using imaging library */ + return (_cogl_bitmap_premult (bmp) + /* ... or try fallback */ + || _cogl_bitmap_fallback_premult (bmp)); + + return TRUE; +} + +gboolean +_cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp, + CoglBitmap *dst_bmp, + CoglPixelFormat dst_format) +{ /* Is base format different (not considering premult status)? */ if ((bmp->format & COGL_UNPREMULT_MASK) != (dst_format & COGL_UNPREMULT_MASK)) { /* Try converting using imaging library */ - if (!_cogl_bitmap_convert (&new_bmp, &tmp_bmp, dst_format)) - { - /* ... or try fallback */ - if (!_cogl_bitmap_fallback_convert (&new_bmp, &tmp_bmp, dst_format)) - return FALSE; - } - - /* Update bitmap with new data */ - new_bmp = tmp_bmp; - new_bmp_owner = TRUE; + if (!_cogl_bitmap_convert (bmp, dst_bmp, dst_format)) + { + /* ... or try fallback */ + if (!_cogl_bitmap_fallback_convert (bmp, dst_bmp, dst_format)) + return FALSE; + } } - - /* Do we need to unpremultiply */ - if ((bmp->format & COGL_PREMULT_BIT) > 0 && - (dst_format & COGL_PREMULT_BIT) == 0) + else { - /* Try unpremultiplying using imaging library */ - if (!_cogl_bitmap_unpremult (&new_bmp, &tmp_bmp)) - { - /* ... or try fallback */ - if (!_cogl_bitmap_fallback_unpremult (&new_bmp, &tmp_bmp)) - { - if (new_bmp_owner) - g_free (new_bmp.data); - - return FALSE; - } - } - - /* Update bitmap with new data */ - if (new_bmp_owner) - g_free (new_bmp.data); - - new_bmp = tmp_bmp; - new_bmp_owner = TRUE; + /* Copy the bitmap so that we can premultiply in-place */ + *dst_bmp = *bmp; + dst_bmp->data = g_memdup (bmp->data, bmp->rowstride * bmp->height); } - /* Do we need to premultiply */ - if ((bmp->format & COGL_PREMULT_BIT) == 0 && - (dst_format & COGL_PREMULT_BIT) > 0) + if (!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format)) { - /* Try premultiplying using imaging library */ - if (!_cogl_bitmap_premult (&new_bmp, &tmp_bmp)) - { - /* ... or try fallback */ - if (!_cogl_bitmap_fallback_premult (&new_bmp, &tmp_bmp)) - { - if (new_bmp_owner) - g_free (new_bmp.data); - - return FALSE; - } - } - - /* Update bitmap with new data */ - if (new_bmp_owner) - g_free (new_bmp.data); - - new_bmp = tmp_bmp; - new_bmp_owner = TRUE; + g_free (dst_bmp->data); + return FALSE; } - /* Output new bitmap info */ - *dst_bmp = new_bmp; - return TRUE; } diff --git a/clutter/cogl/cogl/cogl-texture-2d-sliced.c b/clutter/cogl/cogl/cogl-texture-2d-sliced.c index 7743f9f2f..9716062d2 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced.c +++ b/clutter/cogl/cogl/cogl-texture-2d-sliced.c @@ -1433,9 +1433,9 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex, if (closest_format != format) { /* Convert to required format */ - success = _cogl_bitmap_convert_and_premult (&source_bmp, - &temp_bmp, - closest_format); + success = _cogl_bitmap_convert_format_and_premult (&source_bmp, + &temp_bmp, + closest_format); /* Swap bitmaps if succeeded */ if (!success) return FALSE; @@ -1635,9 +1635,9 @@ _cogl_texture_2d_sliced_get_data (CoglTexture *tex, if (closest_format != format) { /* Convert to requested format */ - success = _cogl_bitmap_convert_and_premult (&target_bmp, - &new_bmp, - format); + success = _cogl_bitmap_convert_format_and_premult (&target_bmp, + &new_bmp, + format); /* Free intermediate data and return if failed */ g_free (target_bmp.data); diff --git a/clutter/cogl/cogl/cogl-texture-2d.c b/clutter/cogl/cogl/cogl-texture-2d.c index cd3f3a1ef..8c8a31c5a 100644 --- a/clutter/cogl/cogl/cogl-texture-2d.c +++ b/clutter/cogl/cogl/cogl-texture-2d.c @@ -466,9 +466,9 @@ _cogl_texture_2d_set_region (CoglTexture *tex, if (closest_format != format) { /* Convert to required format */ - success = _cogl_bitmap_convert_and_premult (&source_bmp, - &temp_bmp, - closest_format); + success = _cogl_bitmap_convert_format_and_premult (&source_bmp, + &temp_bmp, + closest_format); /* Swap bitmaps if succeeded */ if (!success) return FALSE; @@ -570,9 +570,9 @@ _cogl_texture_2d_get_data (CoglTexture *tex, if (closest_format != format) { /* Convert to requested format */ - success = _cogl_bitmap_convert_and_premult (&target_bmp, - &new_bmp, - format); + success = _cogl_bitmap_convert_format_and_premult (&target_bmp, + &new_bmp, + format); /* Free intermediate data and return if failed */ g_free (target_bmp.data); diff --git a/clutter/cogl/cogl/cogl-texture.c b/clutter/cogl/cogl/cogl-texture.c index 09acb0182..fe349f725 100644 --- a/clutter/cogl/cogl/cogl-texture.c +++ b/clutter/cogl/cogl/cogl-texture.c @@ -193,9 +193,9 @@ _cogl_texture_upload_data_convert (CoglTextureUploadData *data, /* Convert to internal format */ if (internal_format != data->bitmap.format) { - success = _cogl_bitmap_convert_and_premult (&data->bitmap, - &new_bitmap, - internal_format); + success = _cogl_bitmap_convert_format_and_premult (&data->bitmap, + &new_bitmap, + internal_format); if (!success) return FALSE;