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 static gboolean
_cogl_bitmap_can_premult (CoglPixelFormat format) _cogl_bitmap_can_fast_premult (CoglPixelFormat format)
{ {
switch (format & ~COGL_PREMULT_BIT) 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 /* If the base format is the same then we can just copy the bitmap
instead */ instead */
if ((src_format & ~COGL_PREMULT_BIT) == (dst_format & ~COGL_PREMULT_BIT) && 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, if (!_cogl_bitmap_copy_subregion (src_bmp, dst_bmp,
0, 0, /* src_x / src_y */ 0, 0, /* src_x / src_y */
@ -504,6 +504,7 @@ gboolean
_cogl_bitmap_unpremult (CoglBitmap *bmp) _cogl_bitmap_unpremult (CoglBitmap *bmp)
{ {
guint8 *p, *data; guint8 *p, *data;
guint16 *tmp_row;
int x,y; int x,y;
CoglPixelFormat format; CoglPixelFormat format;
int width, height; int width, height;
@ -514,20 +515,32 @@ _cogl_bitmap_unpremult (CoglBitmap *bmp)
height = _cogl_bitmap_get_height (bmp); height = _cogl_bitmap_get_height (bmp);
rowstride = _cogl_bitmap_get_rowstride (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, if ((data = _cogl_bitmap_map (bmp,
COGL_BUFFER_ACCESS_READ | COGL_BUFFER_ACCESS_READ |
COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_ACCESS_WRITE,
0)) == NULL) 0)) == NULL)
return FALSE; 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++) for (y = 0; y < height; y++)
{ {
p = (guint8*) data + y * rowstride; p = (guint8*) data + y * rowstride;
if (tmp_row)
{
_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
{
if (format & COGL_AFIRST_BIT) if (format & COGL_AFIRST_BIT)
{ {
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
@ -542,6 +555,9 @@ _cogl_bitmap_unpremult (CoglBitmap *bmp)
else else
_cogl_bitmap_unpremult_unpacked_span_guint8 (p, width); _cogl_bitmap_unpremult_unpacked_span_guint8 (p, width);
} }
}
g_free (tmp_row);
_cogl_bitmap_unmap (bmp); _cogl_bitmap_unmap (bmp);
@ -554,6 +570,7 @@ gboolean
_cogl_bitmap_premult (CoglBitmap *bmp) _cogl_bitmap_premult (CoglBitmap *bmp)
{ {
guint8 *p, *data; guint8 *p, *data;
guint16 *tmp_row;
int x,y; int x,y;
CoglPixelFormat format; CoglPixelFormat format;
int width, height; int width, height;
@ -564,20 +581,31 @@ _cogl_bitmap_premult (CoglBitmap *bmp)
height = _cogl_bitmap_get_height (bmp); height = _cogl_bitmap_get_height (bmp);
rowstride = _cogl_bitmap_get_rowstride (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, if ((data = _cogl_bitmap_map (bmp,
COGL_BUFFER_ACCESS_READ | COGL_BUFFER_ACCESS_READ |
COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_ACCESS_WRITE,
0)) == NULL) 0)) == NULL)
return FALSE; 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++) for (y = 0; y < height; y++)
{ {
p = (guint8*) data + y * rowstride; p = (guint8*) data + y * rowstride;
if (tmp_row)
{
_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
{
if (format & COGL_AFIRST_BIT) if (format & COGL_AFIRST_BIT)
{ {
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
@ -589,6 +617,9 @@ _cogl_bitmap_premult (CoglBitmap *bmp)
else else
_cogl_bitmap_premult_unpacked_span_guint8 (p, width); _cogl_bitmap_premult_unpacked_span_guint8 (p, width);
} }
}
g_free (tmp_row);
_cogl_bitmap_unmap (bmp); _cogl_bitmap_unmap (bmp);