texture: When reading, convert data directly into user's buffer

On GLES, when reading texture data back it may need to allocate a
temporary CoglBitmap if the requested format is not supported by the
driver. Previously it would then copy this temporary buffer back into
the user's buffer by calling _cogl_bitmap_convert which would allocate
a second temporary buffer. It would then copy that data into the
user's buffer. This patch changes it to create a CoglBitmap which
points to the user's data and then convert directly into that buffer
using the new _cogl_bitmap_convert_into_bitmap.

This also fixes a small leak where target_bmp would not get freed if
the target format and the closest supported format do match.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2012-03-13 11:33:05 +00:00
parent de5d55ae93
commit f65a895b4f

View File

@ -1129,10 +1129,6 @@ cogl_texture_get_data (CoglTexture *texture,
GLenum closest_gl_format;
GLenum closest_gl_type;
CoglBitmap *target_bmp;
CoglBitmap *new_bmp;
guint8 *src;
guint8 *dst;
int y;
int tex_width;
int tex_height;
CoglPixelFormat texture_format;
@ -1236,42 +1232,27 @@ cogl_texture_get_data (CoglTexture *texture,
/* Was intermediate used? */
if (closest_format != format)
{
guint8 *new_bmp_data;
int new_bmp_rowstride;
CoglBitmap *new_bmp;
gboolean result;
/* Convert to requested format */
new_bmp = _cogl_bitmap_convert (target_bmp, format);
/* Convert to requested format directly into the user's buffer */
new_bmp = _cogl_bitmap_new_from_data (data,
format,
tex_width, tex_height,
rowstride,
NULL, /* destroy_fn */
NULL /* destroy_fn_data */);
result = _cogl_bitmap_convert_into_bitmap (target_bmp, new_bmp);
/* Free intermediate data and return if failed */
cogl_object_unref (target_bmp);
if (!result)
/* Return failure after cleaning up */
byte_size = 0;
if (new_bmp == NULL)
return 0;
new_bmp_rowstride = cogl_bitmap_get_rowstride (new_bmp);
new_bmp_data = _cogl_bitmap_map (new_bmp, COGL_BUFFER_ACCESS_WRITE,
COGL_BUFFER_MAP_HINT_DISCARD);
if (new_bmp_data == NULL)
{
cogl_object_unref (new_bmp);
return 0;
}
/* Copy to user buffer */
for (y = 0; y < tex_height; ++y)
{
src = new_bmp_data + y * new_bmp_rowstride;
dst = data + y * rowstride;
memcpy (dst, src, tex_width * bpp);
}
_cogl_bitmap_unmap (new_bmp);
/* Free converted data */
cogl_object_unref (new_bmp);
}
cogl_object_unref (target_bmp);
return byte_size;
}