cogl-texture: Don't use the source rowstride if we have to copy bitmap

If we have to copy the bitmap to do the premultiplication then we were
previously using the rowstride of the source image as the rowstride
for the new image. This is wasteful if the source image is a subregion
of a larger image which would make it use a large rowstride. If we
have to copy the data anyway we might as well compact it to the
smallest rowstride. This also prevents the copy from reading past the
end of the last row of pixels.

An internal function called _cogl_bitmap_copy has been added to do the
copy. It creates a new bitmap with the smallest possible rowstride
rounded up the nearest multiple of 4 bytes. There may be other places
in Cogl that are currently assuming we can read height*rowstride of
the source buffer so they may want to take advantage of this function
too.

http://bugzilla.clutter-project.org/show_bug.cgi?id=2491
This commit is contained in:
Neil Roberts 2010-12-17 14:52:25 +00:00
parent 7ae61c3763
commit 0b2dc74dbc
3 changed files with 34 additions and 21 deletions

View File

@ -155,6 +155,10 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
int width, int width,
int height); int height);
/* Creates a deep copy of the source bitmap */
CoglBitmap *
_cogl_bitmap_copy (CoglBitmap *src_bmp);
gboolean gboolean
_cogl_bitmap_get_size_from_file (const char *filename, _cogl_bitmap_get_size_from_file (const char *filename,
int *width, int *width,

View File

@ -181,6 +181,35 @@ _cogl_bitmap_convert_format_and_premult (CoglBitmap *bmp,
return dst_bmp; return dst_bmp;
} }
CoglBitmap *
_cogl_bitmap_copy (CoglBitmap *src_bmp)
{
CoglBitmap *dst_bmp;
CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp);
int bpp = _cogl_get_format_bpp (src_format);
int width = _cogl_bitmap_get_width (src_bmp);
int height = _cogl_bitmap_get_height (src_bmp);
int dst_rowstride = width * bpp;
/* Round the rowstride up to the next nearest multiple of 4 bytes */
dst_rowstride = (dst_rowstride + 3) & ~3;
dst_bmp = _cogl_bitmap_new_from_data (g_malloc (dst_rowstride * height),
src_format,
width, height,
dst_rowstride,
(CoglBitmapDestroyNotify) g_free,
NULL);
_cogl_bitmap_copy_subregion (src_bmp,
dst_bmp,
0, 0, /* src_x/y */
0, 0, /* dst_x/y */
width, height);
return dst_bmp;
}
void void
_cogl_bitmap_copy_subregion (CoglBitmap *src, _cogl_bitmap_copy_subregion (CoglBitmap *src,
CoglBitmap *dst, CoglBitmap *dst,

View File

@ -184,27 +184,7 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
if (_cogl_texture_needs_premult_conversion (src_format, if (_cogl_texture_needs_premult_conversion (src_format,
dst_format)) dst_format))
{ {
guint8 *src_data; dst_bmp = _cogl_bitmap_copy (src_bmp);
guint8 *dst_data;
if ((src_data = _cogl_bitmap_map (src_bmp,
COGL_BUFFER_ACCESS_READ, 0)) == NULL)
return NULL;
dst_data = g_memdup (src_data,
_cogl_bitmap_get_height (src_bmp) *
_cogl_bitmap_get_rowstride (src_bmp));
_cogl_bitmap_unmap (src_bmp);
dst_bmp =
_cogl_bitmap_new_from_data (dst_data,
src_format,
_cogl_bitmap_get_width (src_bmp),
_cogl_bitmap_get_height (src_bmp),
_cogl_bitmap_get_rowstride (src_bmp),
(CoglBitmapDestroyNotify) g_free,
NULL);
if (!_cogl_bitmap_convert_premult_status (dst_bmp, if (!_cogl_bitmap_convert_premult_status (dst_bmp,
src_format ^ src_format ^