bitmap: Support pre/unpre-multiplying any format

If the fast-path inplace premult conversion can't be used then it will
now fallback to unpacking the buffer into a row of guint16s and use
the generic conversion.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2012-03-02 18:03:02 +00:00
parent 031dd661c0
commit 1b47ff0dfe

View File

@ -279,7 +279,7 @@ _cogl_bitmap_premult_unpacked_span_guint16 (guint16 *data,
}
static gboolean
_cogl_bitmap_can_premult (CoglPixelFormat format)
_cogl_bitmap_can_fast_premult (CoglPixelFormat format)
{
switch (format & ~COGL_PREMULT_BIT)
{
@ -379,7 +379,7 @@ _cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp,
/* If the base format is the same then we can just copy the bitmap
instead */
if ((src_format & ~COGL_PREMULT_BIT) == (dst_format & ~COGL_PREMULT_BIT) &&
(!need_premult || _cogl_bitmap_can_premult (dst_format)))
(!need_premult || _cogl_bitmap_can_fast_premult (dst_format)))
{
if (!_cogl_bitmap_copy_subregion (src_bmp, dst_bmp,
0, 0, /* src_x / src_y */
@ -504,6 +504,7 @@ gboolean
_cogl_bitmap_unpremult (CoglBitmap *bmp)
{
guint8 *p, *data;
guint16 *tmp_row;
int x,y;
CoglPixelFormat format;
int width, height;
@ -514,35 +515,50 @@ _cogl_bitmap_unpremult (CoglBitmap *bmp)
height = _cogl_bitmap_get_height (bmp);
rowstride = _cogl_bitmap_get_rowstride (bmp);
/* If we can premult that implies we can un-premult too... */
if (!_cogl_bitmap_can_premult (format))
return FALSE;
if ((data = _cogl_bitmap_map (bmp,
COGL_BUFFER_ACCESS_READ |
COGL_BUFFER_ACCESS_WRITE,
0)) == NULL)
return FALSE;
/* If we can't directly unpremult the data inline then we'll
allocate a temporary row and unpack the data. This assumes if we
can fast premult then we can also fast unpremult */
if (_cogl_bitmap_can_fast_premult (format))
tmp_row = NULL;
else
tmp_row = g_malloc (sizeof (guint16) * 4 * width);
for (y = 0; y < height; y++)
{
p = (guint8*) data + y * rowstride;
if (format & COGL_AFIRST_BIT)
if (tmp_row)
{
for (x = 0; x < width; x++)
{
if (p[0] == 0)
_cogl_unpremult_alpha_0 (p);
else
_cogl_unpremult_alpha_first (p);
p += 4;
}
_cogl_unpack_guint16 (format, p, tmp_row, width);
_cogl_bitmap_unpremult_unpacked_span_guint16 (tmp_row, width);
_cogl_pack_guint16 (format, tmp_row, p, width);
}
else
_cogl_bitmap_unpremult_unpacked_span_guint8 (p, width);
{
if (format & COGL_AFIRST_BIT)
{
for (x = 0; x < width; x++)
{
if (p[0] == 0)
_cogl_unpremult_alpha_0 (p);
else
_cogl_unpremult_alpha_first (p);
p += 4;
}
}
else
_cogl_bitmap_unpremult_unpacked_span_guint8 (p, width);
}
}
g_free (tmp_row);
_cogl_bitmap_unmap (bmp);
_cogl_bitmap_set_format (bmp, format & ~COGL_PREMULT_BIT);
@ -554,6 +570,7 @@ gboolean
_cogl_bitmap_premult (CoglBitmap *bmp)
{
guint8 *p, *data;
guint16 *tmp_row;
int x,y;
CoglPixelFormat format;
int width, height;
@ -564,32 +581,46 @@ _cogl_bitmap_premult (CoglBitmap *bmp)
height = _cogl_bitmap_get_height (bmp);
rowstride = _cogl_bitmap_get_rowstride (bmp);
/* Make sure format supported for un-premultiplication */
if (!_cogl_bitmap_can_premult (format))
return FALSE;
if ((data = _cogl_bitmap_map (bmp,
COGL_BUFFER_ACCESS_READ |
COGL_BUFFER_ACCESS_WRITE,
0)) == NULL)
return FALSE;
/* If we can't directly premult the data inline then we'll allocate
a temporary row and unpack the data. */
if (_cogl_bitmap_can_fast_premult (format))
tmp_row = NULL;
else
tmp_row = g_malloc (sizeof (guint16) * 4 * width);
for (y = 0; y < height; y++)
{
p = (guint8*) data + y * rowstride;
if (format & COGL_AFIRST_BIT)
if (tmp_row)
{
for (x = 0; x < width; x++)
{
_cogl_premult_alpha_first (p);
p += 4;
}
_cogl_unpack_guint16 (format, p, tmp_row, width);
_cogl_bitmap_premult_unpacked_span_guint16 (tmp_row, width);
_cogl_pack_guint16 (format, tmp_row, p, width);
}
else
_cogl_bitmap_premult_unpacked_span_guint8 (p, width);
{
if (format & COGL_AFIRST_BIT)
{
for (x = 0; x < width; x++)
{
_cogl_premult_alpha_first (p);
p += 4;
}
}
else
_cogl_bitmap_premult_unpacked_span_guint8 (p, width);
}
}
g_free (tmp_row);
_cogl_bitmap_unmap (bmp);
_cogl_bitmap_set_format (bmp, format | COGL_PREMULT_BIT);