diff options
author | Neil Roberts <neil@linux.intel.com> | 2012-03-01 14:44:41 +0000 |
---|---|---|
committer | Neil Roberts <neil@linux.intel.com> | 2012-03-05 17:46:57 +0000 |
commit | 031dd661c0a1687638b01a30b635aa1cb151535e (patch) | |
tree | b7fafcc8edfed941ddd3b962ff4dc7d2d110143a /cogl/cogl-bitmap-conversion.c | |
parent | f4cd5aceb923bc984a97f73a7ac4a5a9c588bb28 (diff) | |
download | cogl-031dd661c0a1687638b01a30b635aa1cb151535e.tar.gz |
bitmap: Add a function to convert into an existing buffer
This adds _cogl_bitmap_convert_into_bitmap which is the same as
_cogl_bitmap_convert except that it writes into an existing bitmap
instead of allocating a new one. _cogl_bitmap_convert now just
allocates a buffer and calls the new function. This is used in
_cogl_read_pixels to avoid allocating a second intermediate buffer
when the pixel format to store in is not GL_RGBA.
Reviewed-by: Robert Bragg <robert@linux.intel.com>
Diffstat (limited to 'cogl/cogl-bitmap-conversion.c')
-rw-r--r-- | cogl/cogl-bitmap-conversion.c | 96 |
1 files changed, 72 insertions, 24 deletions
diff --git a/cogl/cogl-bitmap-conversion.c b/cogl/cogl-bitmap-conversion.c index b9bcf750..5b971f89 100644 --- a/cogl/cogl-bitmap-conversion.c +++ b/cogl/cogl-bitmap-conversion.c @@ -342,29 +342,34 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format) g_assert_not_reached (); } -CoglBitmap * -_cogl_bitmap_convert (CoglBitmap *src_bmp, - CoglPixelFormat dst_format) +gboolean +_cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp, + CoglBitmap *dst_bmp) { guint8 *src_data; guint8 *dst_data; guint8 *src; guint8 *dst; void *tmp_row; - int dst_bpp; int src_rowstride; int dst_rowstride; int y; int width, height; CoglPixelFormat src_format; + CoglPixelFormat dst_format; gboolean use_16; gboolean need_premult; src_format = _cogl_bitmap_get_format (src_bmp); src_rowstride = _cogl_bitmap_get_rowstride (src_bmp); + dst_format = _cogl_bitmap_get_format (dst_bmp); + dst_rowstride = _cogl_bitmap_get_rowstride (dst_bmp); width = _cogl_bitmap_get_width (src_bmp); height = _cogl_bitmap_get_height (src_bmp); + _COGL_RETURN_VAL_IF_FAIL (width == _cogl_bitmap_get_width (dst_bmp), FALSE); + _COGL_RETURN_VAL_IF_FAIL (height == _cogl_bitmap_get_height (dst_bmp), FALSE); + need_premult = ((src_format & COGL_PREMULT_BIT) != (dst_format & COGL_PREMULT_BIT) && src_format != COGL_PIXEL_FORMAT_A_8 && @@ -376,32 +381,44 @@ _cogl_bitmap_convert (CoglBitmap *src_bmp, if ((src_format & ~COGL_PREMULT_BIT) == (dst_format & ~COGL_PREMULT_BIT) && (!need_premult || _cogl_bitmap_can_premult (dst_format))) { - CoglBitmap *dst_bmp = _cogl_bitmap_copy (src_bmp); + if (!_cogl_bitmap_copy_subregion (src_bmp, dst_bmp, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + width, height)) + return FALSE; - if (need_premult && - !_cogl_bitmap_convert_premult_status (dst_bmp, dst_format)) + if (need_premult) { - cogl_object_unref (dst_bmp); - return NULL; + if ((dst_format & COGL_PREMULT_BIT)) + { + if (!_cogl_bitmap_premult (dst_bmp)) + return FALSE; + } + else + { + if (!_cogl_bitmap_unpremult (dst_bmp)) + return FALSE; + } } - return dst_bmp; + return TRUE; } src_data = _cogl_bitmap_map (src_bmp, COGL_BUFFER_ACCESS_READ, 0); if (src_data == NULL) - return NULL; + return FALSE; + dst_data = _cogl_bitmap_map (dst_bmp, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + if (dst_data == NULL) + { + _cogl_bitmap_unmap (src_bmp); + return FALSE; + } use_16 = _cogl_bitmap_needs_short_temp_buffer (dst_format); - dst_bpp = _cogl_pixel_format_get_bytes_per_pixel (dst_format); - - /* Initialize destination bitmap */ - dst_rowstride = (sizeof(guint8) * dst_bpp * width + 3) & ~3; - - /* Allocate a new buffer to hold converted data */ - dst_data = g_malloc (height * dst_rowstride); - /* and a buffer to hold a temporary RGBA row */ + /* Allocate a buffer to hold a temporary RGBA row */ tmp_row = g_malloc (width * (use_16 ? sizeof (guint16) : sizeof (guint8)) * 4); @@ -442,14 +459,45 @@ _cogl_bitmap_convert (CoglBitmap *src_bmp, } _cogl_bitmap_unmap (src_bmp); + _cogl_bitmap_unmap (dst_bmp); g_free (tmp_row); - return _cogl_bitmap_new_from_data (dst_data, - dst_format, - width, height, dst_rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + return TRUE; +} + +CoglBitmap * +_cogl_bitmap_convert (CoglBitmap *src_bmp, + CoglPixelFormat dst_format) +{ + int dst_bpp; + int dst_rowstride; + guint8 *dst_data; + CoglBitmap *dst_bmp; + int width, height; + + width = _cogl_bitmap_get_width (src_bmp); + height = _cogl_bitmap_get_height (src_bmp); + dst_bpp = _cogl_pixel_format_get_bytes_per_pixel (dst_format); + dst_rowstride = (sizeof (guint8) * dst_bpp * width + 3) & ~3; + + /* Allocate a new buffer to hold converted data */ + dst_data = g_malloc (height * dst_rowstride); + + dst_bmp = _cogl_bitmap_new_from_data (dst_data, + dst_format, + width, height, + dst_rowstride, + (CoglBitmapDestroyNotify) g_free, + NULL); + + if (!_cogl_bitmap_convert_into_bitmap (src_bmp, dst_bmp)) + { + cogl_object_unref (dst_bmp); + return NULL; + } + + return dst_bmp; } gboolean |