From d18b59d9e67f6ec2dd747da91d8c1380e1730d3e Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 13 Mar 2012 14:46:18 +0000 Subject: [PATCH] Add a public cogl_bitmap_new_for_data This creates a CoglBitmap which points into an existing buffer in system memory. That way it can be used to create a texture or to read pixel data into. The function replaces the existing internal function _cogl_bitmap_new_from_data but removes the destroy notify call back. If the application wants notification of destruction it can just use the cogl_object_set_user_data function as normal. Internally there is now a convenience function to create a bitmap for system memory and automatically free the buffer using that mechanism. The name of the function is inspired by cairo_image_surface_create_for_data which has similar semantics. Reviewed-by: Robert Bragg --- cogl/cogl-atlas.c | 18 +-- cogl/cogl-bitmap-conversion.c | 20 +-- cogl/cogl-bitmap-pixbuf.c | 32 ++--- cogl/cogl-bitmap-private.h | 48 +++----- cogl/cogl-bitmap.c | 94 +++++++++------ cogl/cogl-bitmap.h | 28 +++++ cogl/cogl-context.c | 18 +-- cogl/cogl-framebuffer.c | 20 +-- cogl/cogl-texture-2d-sliced.c | 32 +++-- cogl/cogl-texture-2d.c | 11 +- cogl/cogl-texture-3d.c | 43 ++++--- cogl/cogl-texture.c | 127 +++++++++----------- cogl/cogl.c | 13 +- cogl/driver/gles/cogl-texture-driver-gles.c | 30 ++--- 14 files changed, 273 insertions(+), 261 deletions(-) diff --git a/cogl/cogl-atlas.c b/cogl/cogl-atlas.c index 2a4e06e25..bfa76dcf2 100644 --- a/cogl/cogl-atlas.c +++ b/cogl/cogl-atlas.c @@ -272,6 +272,8 @@ _cogl_atlas_create_texture (CoglAtlas *atlas, { CoglHandle tex; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE)) { guint8 *clear_data; @@ -280,22 +282,22 @@ _cogl_atlas_create_texture (CoglAtlas *atlas, /* Create a buffer of zeroes to initially clear the texture */ clear_data = g_malloc0 (width * height * bpp); - clear_bmp = _cogl_bitmap_new_from_data (clear_data, - atlas->texture_format, - width, - height, - width * bpp, - (CoglBitmapDestroyNotify) g_free, - NULL); + clear_bmp = cogl_bitmap_new_for_data (ctx, + width, + height, + atlas->texture_format, + width * bpp, + clear_data); tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE, atlas->texture_format, NULL); cogl_object_unref (clear_bmp); + + g_free (clear_data); } else { - _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); tex = cogl_texture_2d_new_with_size (ctx, width, height, atlas->texture_format, diff --git a/cogl/cogl-bitmap-conversion.c b/cogl/cogl-bitmap-conversion.c index 64ce8cc4c..6a57dbfe2 100644 --- a/cogl/cogl-bitmap-conversion.c +++ b/cogl/cogl-bitmap-conversion.c @@ -27,6 +27,7 @@ #include "cogl-private.h" #include "cogl-bitmap-private.h" +#include "cogl-context-private.h" #include @@ -470,26 +471,17 @@ 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; + _COGL_GET_CONTEXT (ctx, NULL); + 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); + dst_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + dst_format); if (!_cogl_bitmap_convert_into_bitmap (src_bmp, dst_bmp)) { diff --git a/cogl/cogl-bitmap-pixbuf.c b/cogl/cogl-bitmap-pixbuf.c index 3f5663198..ada8e54d1 100644 --- a/cogl/cogl-bitmap-pixbuf.c +++ b/cogl/cogl-bitmap-pixbuf.c @@ -28,6 +28,7 @@ #include "cogl-util.h" #include "cogl-internal.h" #include "cogl-bitmap-private.h" +#include "cogl-context-private.h" #include @@ -166,17 +167,11 @@ _cogl_bitmap_get_size_from_file (const char *filename, return FALSE; } -static void -_cogl_bitmap_unref_pixbuf (guint8 *pixels, - void *pixbuf) -{ - g_object_unref (pixbuf); -} - CoglBitmap * _cogl_bitmap_from_file (const char *filename, GError **error) { + static CoglUserDataKey pixbuf_key; GdkPixbuf *pixbuf; gboolean has_alpha; GdkColorspace color_space; @@ -186,6 +181,9 @@ _cogl_bitmap_from_file (const char *filename, int rowstride; int bits_per_sample; int n_channels; + CoglBitmap *bmp; + + _COGL_GET_CONTEXT (ctx, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE); @@ -233,13 +231,19 @@ _cogl_bitmap_from_file (const char *filename, to read past the end of bpp*width on the last row even if the rowstride is much larger so we don't need to worry about GdkPixbuf's semantics that it may under-allocate the buffer. */ - return _cogl_bitmap_new_from_data (gdk_pixbuf_get_pixels (pixbuf), - pixel_format, - width, - height, - rowstride, - _cogl_bitmap_unref_pixbuf, - pixbuf); + bmp = cogl_bitmap_new_for_data (ctx, + width, + height, + pixel_format, + rowstride, + gdk_pixbuf_get_pixels (pixbuf)); + + cogl_object_set_user_data (COGL_OBJECT (bmp), + &pixbuf_key, + pixbuf, + g_object_unref); + + return bmp; } #else diff --git a/cogl/cogl-bitmap-private.h b/cogl/cogl-bitmap-private.h index ab80868fb..fc9340652 100644 --- a/cogl/cogl-bitmap-private.h +++ b/cogl/cogl-bitmap-private.h @@ -33,43 +33,27 @@ #include "cogl-bitmap.h" /* - * CoglBitmapDestroyNotify: - * @data: The image data - * @destroy_data: The callback closure data that was given to - * _cogl_bitmap_new_from_data(). + * _cogl_bitmap_new_with_malloc_buffer: + * @context: A #CoglContext + * @width: width of the bitmap in pixels + * @height: height of the bitmap in pixels + * @format: the format of the pixels the array will store * - * Function prototype that is used to destroy the bitmap data when - * _cogl_bitmap_new_from_data() is called. - */ -typedef void (* CoglBitmapDestroyNotify) (guint8 *data, void *destroy_data); - -/* - * _cogl_bitmap_new_from_data: - * @data: A pointer to the data. The bitmap will take ownership of this data. - * @format: The format of the pixel data. - * @width: The width of the bitmap. - * @height: The height of the bitmap. - * @rowstride: The rowstride of the bitmap (the number of bytes from - * the start of one row of the bitmap to the next). - * @destroy_fn: A function to be called when the bitmap is - * destroyed. This should free @data. %NULL can be used instead if - * no free is needed. - * @destroy_fn_data: This pointer will get passed to @destroy_fn. + * This is equivalent to cogl_bitmap_new_with_size() except that it + * allocated the buffer using g_malloc() instead of creating a + * #CoglPixelBuffer. The buffer will be automatically destroyed when + * the bitmap is freed. * - * Creates a bitmap using some existing data. The data is not copied - * so the bitmap will take ownership of the data pointer. When the - * bitmap is freed @destroy_fn will be called to free the data. + * Return value: a #CoglPixelBuffer representing the newly created array * - * Return value: A new %CoglBitmap. + * Since: 1.10 + * Stability: Unstable */ CoglBitmap * -_cogl_bitmap_new_from_data (guint8 *data, - CoglPixelFormat format, - int width, - int height, - int rowstride, - CoglBitmapDestroyNotify destroy_fn, - gpointer destroy_fn_data); +_cogl_bitmap_new_with_malloc_buffer (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format); /* The idea of this function is that it will create a bitmap that shares the actual data with another bitmap. This is needed for the diff --git a/cogl/cogl-bitmap.c b/cogl/cogl-bitmap.c index 4d263055c..b0c6ec76e 100644 --- a/cogl/cogl-bitmap.c +++ b/cogl/cogl-bitmap.c @@ -31,6 +31,7 @@ #include "cogl-bitmap-private.h" #include "cogl-buffer-private.h" #include "cogl-pixel-buffer.h" +#include "cogl-context-private.h" #include @@ -43,8 +44,6 @@ struct _CoglBitmap int rowstride; guint8 *data; - CoglBitmapDestroyNotify destroy_fn; - void *destroy_fn_data; gboolean mapped; gboolean bound; @@ -68,9 +67,6 @@ _cogl_bitmap_free (CoglBitmap *bmp) g_assert (!bmp->mapped); g_assert (!bmp->bound); - if (bmp->destroy_fn) - bmp->destroy_fn (bmp->data, bmp->destroy_fn_data); - if (bmp->shared_bmp) cogl_object_unref (bmp->shared_bmp); @@ -105,20 +101,15 @@ _cogl_bitmap_copy (CoglBitmap *src_bmp) { CoglBitmap *dst_bmp; CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp); - int bpp = _cogl_pixel_format_get_bytes_per_pixel (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; + _COGL_GET_CONTEXT (ctx, NULL); - dst_bmp = _cogl_bitmap_new_from_data (g_malloc (dst_rowstride * height), - src_format, - width, height, - dst_rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + dst_bmp = + _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + src_format); _cogl_bitmap_copy_subregion (src_bmp, dst_bmp, @@ -185,23 +176,23 @@ cogl_bitmap_get_size_from_file (const char *filename, } CoglBitmap * -_cogl_bitmap_new_from_data (guint8 *data, - CoglPixelFormat format, - int width, - int height, - int rowstride, - CoglBitmapDestroyNotify destroy_fn, - void *destroy_fn_data) +cogl_bitmap_new_for_data (CoglContext *context, + int width, + int height, + CoglPixelFormat format, + int rowstride, + guint8 *data) { - CoglBitmap *bmp = g_slice_new (CoglBitmap); + CoglBitmap *bmp; + g_return_val_if_fail (cogl_is_context (context), NULL); + + bmp = g_slice_new (CoglBitmap); bmp->format = format; bmp->width = width; bmp->height = height; bmp->rowstride = rowstride; bmp->data = data; - bmp->destroy_fn = destroy_fn; - bmp->destroy_fn_data = destroy_fn_data; bmp->mapped = FALSE; bmp->bound = FALSE; bmp->shared_bmp = NULL; @@ -210,6 +201,31 @@ _cogl_bitmap_new_from_data (guint8 *data, return _cogl_bitmap_object_new (bmp); } +CoglBitmap * +_cogl_bitmap_new_with_malloc_buffer (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format) +{ + static CoglUserDataKey bitmap_free_key; + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + int rowstride = ((width * bpp) + 3) & ~3; + guint8 *data = g_malloc (rowstride * height); + CoglBitmap *bitmap; + + bitmap = cogl_bitmap_new_for_data (context, + width, height, + format, + rowstride, + data); + cogl_object_set_user_data (COGL_OBJECT (bitmap), + &bitmap_free_key, + data, + g_free); + + return bitmap; +} + CoglBitmap * _cogl_bitmap_new_shared (CoglBitmap *shared_bmp, CoglPixelFormat format, @@ -217,13 +233,15 @@ _cogl_bitmap_new_shared (CoglBitmap *shared_bmp, int height, int rowstride) { - CoglBitmap *bmp = _cogl_bitmap_new_from_data (NULL, /* data */ - format, - width, - height, - rowstride, - NULL, /* destroy_fn */ - NULL /* destroy_fn_data */); + CoglBitmap *bmp; + + _COGL_GET_CONTEXT (ctx, NULL); + + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + NULL /* data */); bmp->shared_bmp = cogl_object_ref (shared_bmp); @@ -251,13 +269,11 @@ cogl_bitmap_new_from_buffer (CoglBuffer *buffer, _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL); - bmp = _cogl_bitmap_new_from_data (NULL, /* data */ - format, - width, - height, - rowstride, - NULL, /* destroy_fn */ - NULL /* destroy_fn_data */); + bmp = cogl_bitmap_new_for_data (buffer->context, + width, height, + format, + rowstride, + NULL /* data */); bmp->buffer = cogl_object_ref (buffer); bmp->data = GINT_TO_POINTER (offset); diff --git a/cogl/cogl-bitmap.h b/cogl/cogl-bitmap.h index 3787d921b..e2e2962c0 100644 --- a/cogl/cogl-bitmap.h +++ b/cogl/cogl-bitmap.h @@ -129,6 +129,34 @@ cogl_bitmap_new_with_size (CoglContext *context, unsigned int height, CoglPixelFormat format); +/** + * cogl_bitmap_new_for_data: + * @context: A #CoglContext + * @width: The width of the bitmap. + * @height: The height of the bitmap. + * @format: The format of the pixel data. + * @rowstride: The rowstride of the bitmap (the number of bytes from + * the start of one row of the bitmap to the next). + * @data: A pointer to the data. The bitmap will take ownership of this data. + * + * Creates a bitmap using some existing data. The data is not copied + * so the application must keep the buffer alive for the lifetime of + * the #CoglBitmap. This can be used for example with + * cogl_framebuffer_read_pixels_into_bitmap() to read data directly + * into an application buffer with the specified rowstride. + * + * Return value: A new #CoglBitmap. + * Since: 1.10 + * Stability: unstable + */ +CoglBitmap * +cogl_bitmap_new_for_data (CoglContext *context, + int width, + int height, + CoglPixelFormat format, + int rowstride, + guint8 *data); + /** * cogl_bitmap_get_format: * @bitmap: A #CoglBitmap diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index b3c404e2a..8b1ea2b8f 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -158,6 +158,11 @@ cogl_context_new (CoglDisplay *display, /* Allocate context memory */ context = g_malloc (sizeof (CoglContext)); + /* Convert the context into an object immediately in case any of the + code below wants to verify that the context pointer is a valid + object */ + _cogl_context_object_new (context); + /* XXX: Gross hack! * Currently everything in Cogl just assumes there is a default * context which it can access via _COGL_GET_CONTEXT() including @@ -380,12 +385,11 @@ cogl_context_new (CoglDisplay *display, _cogl_matrix_stack_init_cache (&_context->builtin_flushed_modelview); default_texture_bitmap = - _cogl_bitmap_new_from_data (default_texture_data, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - 1, 1, /* width/height */ - 4, /* rowstride */ - NULL, /* destroy function */ - NULL /* destroy function data */); + cogl_bitmap_new_for_data (_context, + 1, 1, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + default_texture_data); /* Create default textures used for fall backs */ context->default_gl_texture_2d_tex = @@ -430,7 +434,7 @@ cogl_context_new (CoglDisplay *display, cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE)) GE (context, glEnable (GL_POINT_SPRITE)); - return _cogl_context_object_new (context); + return context; } static void diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index cdf5f8d26..799f4060c 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -2036,9 +2036,9 @@ cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, (required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT)) { CoglBitmap *tmp_bmp; - guint8 *tmp_data; CoglPixelFormat read_format; int bpp, rowstride; + guint8 *tmp_data; int succeeded; if (ctx->driver == COGL_DRIVER_GL) @@ -2054,22 +2054,24 @@ cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, read_format = ((read_format & ~COGL_PREMULT_BIT) | (framebuffer->format & COGL_PREMULT_BIT)); + tmp_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + read_format); bpp = _cogl_pixel_format_get_bytes_per_pixel (read_format); - rowstride = (width * bpp + 3) & ~3; - tmp_data = g_malloc (rowstride * height); - - tmp_bmp = _cogl_bitmap_new_from_data (tmp_data, - read_format, - width, height, rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + rowstride = cogl_bitmap_get_rowstride (tmp_bmp); ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); + tmp_data = _cogl_bitmap_bind (tmp_bmp, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + GE( ctx, glReadPixels (x, y, width, height, gl_format, gl_type, tmp_data) ); + _cogl_bitmap_unbind (tmp_bmp); + succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap); cogl_object_unref (tmp_bmp); diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index 73ed34889..836caaff1 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -175,6 +175,8 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, { gboolean need_x, need_y; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* If the x_span is sliced and the upload touches the rightmost pixels then fill the waste with copies of the pixels */ @@ -222,15 +224,13 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, src += bmp_rowstride; } - waste_bmp = - _cogl_bitmap_new_from_data (waste_buf, - source_format, - x_span->waste, - y_iter->intersect_end - - y_iter->intersect_start, - x_span->waste * bpp, - NULL, - NULL); + waste_bmp = cogl_bitmap_new_for_data (ctx, + x_span->waste, + y_iter->intersect_end - + y_iter->intersect_start, + source_format, + x_span->waste * bpp, + waste_buf); cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), 0, /* src_x */ @@ -279,14 +279,12 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, } } - waste_bmp = - _cogl_bitmap_new_from_data (waste_buf, - source_format, - copy_width, - y_span->waste, - copy_width * bpp, - NULL, - NULL); + waste_bmp = cogl_bitmap_new_for_data (ctx, + copy_width, + y_span->waste, + source_format, + copy_width * bpp, + waste_buf); cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), 0, /* src_x */ diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index da57cb4f7..93bb07ce8 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -313,12 +313,11 @@ cogl_texture_2d_new_from_data (CoglContext *ctx, rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); /* Wrap the data into a bitmap */ - bmp = _cogl_bitmap_new_from_data ((guint8 *)data, - format, - width, - height, - rowstride, - NULL, NULL); + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (guint8 *) data); tex =_cogl_texture_2d_new_from_bitmap (bmp, COGL_TEXTURE_NONE, internal_format, diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c index c2066f7b5..8662d5afd 100644 --- a/cogl/cogl-texture-3d.c +++ b/cogl/cogl-texture-3d.c @@ -353,18 +353,26 @@ cogl_texture_3d_new_from_data (CoglContext *context, recommends avoiding this situation. */ if (image_stride % rowstride != 0) { + guint8 *bmp_data; + int bmp_rowstride; int z, y; - int bmp_rowstride = - _cogl_pixel_format_get_bytes_per_pixel (format) * width; - guint8 *bmp_data = g_malloc (bmp_rowstride * height * depth); - bitmap = _cogl_bitmap_new_from_data (bmp_data, - format, - width, - depth * height, - bmp_rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL /* destroy_fn_data */); + bitmap = _cogl_bitmap_new_with_malloc_buffer (context, + width, + depth * height, + format); + + bmp_data = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + + if (bmp_data == NULL) + { + cogl_object_unref (bitmap); + return NULL; + } + + bmp_rowstride = cogl_bitmap_get_rowstride (bitmap); /* Copy all of the images in */ for (z = 0; z < depth; z++) @@ -373,15 +381,16 @@ cogl_texture_3d_new_from_data (CoglContext *context, bmp_rowstride * y), data + z * image_stride + rowstride * y, bmp_rowstride); + + _cogl_bitmap_unmap (bitmap); } else - bitmap = _cogl_bitmap_new_from_data ((guint8 *) data, - format, - width, - image_stride / rowstride * depth, - rowstride, - NULL, /* destroy_fn */ - NULL /* destroy_fn_data */); + bitmap = cogl_bitmap_new_for_data (context, + width, + image_stride / rowstride * depth, + format, + rowstride, + (guint8 *) data); ret = _cogl_texture_3d_new_from_bitmap (context, bitmap, diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index 6d6a1f275..6b08ec50d 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -329,6 +329,8 @@ cogl_texture_new_from_data (unsigned int width, CoglBitmap *bmp; CoglTexture *tex; + _COGL_GET_CONTEXT (ctx, NULL); + if (format == COGL_PIXEL_FORMAT_ANY) return NULL; @@ -340,12 +342,11 @@ cogl_texture_new_from_data (unsigned int width, rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); /* Wrap the data into a bitmap */ - bmp = _cogl_bitmap_new_from_data ((guint8 *) data, - format, - width, - height, - rowstride, - NULL, NULL); + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (guint8 *) data); tex = cogl_texture_new_from_bitmap (bmp, flags, internal_format); @@ -663,6 +664,8 @@ cogl_texture_set_region (CoglTexture *texture, CoglBitmap *source_bmp; gboolean ret; + _COGL_GET_CONTEXT (ctx, FALSE); + _COGL_RETURN_VAL_IF_FAIL ((width - src_x) >= dst_width, FALSE); _COGL_RETURN_VAL_IF_FAIL ((height - src_y) >= dst_height, FALSE); @@ -675,13 +678,11 @@ cogl_texture_set_region (CoglTexture *texture, rowstride = _cogl_pixel_format_get_bytes_per_pixel (format) * width; /* Init source bitmap */ - source_bmp = _cogl_bitmap_new_from_data ((guint8 *) data, - format, - width, - height, - rowstride, - NULL, /* destroy_fn */ - NULL); /* destroy_fn_data */ + source_bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (guint8 *) data); ret = cogl_texture_set_region_from_bitmap (texture, src_x, src_y, @@ -712,7 +713,6 @@ do_texture_draw_and_read (CoglTexture *texture, CoglBitmap *target_bmp, float *viewport) { - int bpp; float rx1, ry1; float rx2, ry2; float tx1, ty1; @@ -721,7 +721,7 @@ do_texture_draw_and_read (CoglTexture *texture, CoglBitmap *rect_bmp; unsigned int tex_width, tex_height; - bpp = _cogl_pixel_format_get_bytes_per_pixel (COGL_PIXEL_FORMAT_RGBA_8888); + _COGL_GET_CONTEXT (ctx, NO_RETVAL); tex_width = cogl_texture_get_width (texture); tex_height = cogl_texture_get_height (texture); @@ -748,8 +748,6 @@ do_texture_draw_and_read (CoglTexture *texture, { int width; int height; - int rowstride; - guint8 *data; /* Rectangle X coords */ rx1 = rx2; @@ -757,7 +755,6 @@ do_texture_draw_and_read (CoglTexture *texture, width = rx2 - rx1; height = ry2 - ry1; - rowstride = width * bpp; /* Normalized texture X coords */ tx1 = tx2; @@ -770,24 +767,17 @@ do_texture_draw_and_read (CoglTexture *texture, tx1, ty1, tx2, ty2); - data = g_malloc (height * rowstride); - /* Read into a temporary bitmap */ - rect_bmp = - _cogl_bitmap_new_from_data (data, - COGL_PIXEL_FORMAT_RGBA_8888, - width, - height, - rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + rect_bmp = _cogl_bitmap_new_with_malloc_buffer + (ctx, + width, height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE); - cogl_read_pixels (viewport[0], viewport[1], - width, - height, - COGL_READ_PIXELS_COLOR_BUFFER, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - data); + cogl_framebuffer_read_pixels_into_bitmap + (cogl_get_draw_framebuffer (), + viewport[0], viewport[1], + COGL_READ_PIXELS_COLOR_BUFFER, + rect_bmp); /* Copy to target bitmap */ _cogl_bitmap_copy_subregion (rect_bmp, @@ -900,15 +890,12 @@ _cogl_texture_draw_and_read (CoglTexture *texture, COGL_BUFFER_MAP_HINT_DISCARD)) == NULL) return FALSE; - srcdata = g_malloc (alpha_rowstride * target_height); - /* Create temp bitmap for alpha values */ - alpha_bmp = _cogl_bitmap_new_from_data (srcdata, - COGL_PIXEL_FORMAT_RGBA_8888, - target_width, target_height, - alpha_rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + alpha_bmp = + _cogl_bitmap_new_with_malloc_buffer (ctx, + target_width, + target_height, + COGL_PIXEL_FORMAT_RGBA_8888); /* Draw alpha values into RGB channels */ cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, @@ -920,6 +907,10 @@ _cogl_texture_draw_and_read (CoglTexture *texture, /* Copy temp R to target A */ + srcdata = _cogl_bitmap_map (alpha_bmp, + COGL_BUFFER_ACCESS_READ, + 0 /* hints */); + for (y=0; ytexture_driver->find_best_gl_get_data_format (format, &closest_gl_format, &closest_gl_type); - closest_bpp = _cogl_pixel_format_get_bytes_per_pixel (closest_format); /* We can assume that whatever data GL gives us will have the premult status of the original texture */ @@ -1171,24 +1161,16 @@ cogl_texture_get_data (CoglTexture *texture, /* Is the requested format supported? */ if (closest_format == format) /* Target user data directly */ - target_bmp = _cogl_bitmap_new_from_data (data, - format, - tex_width, - tex_height, - rowstride, - NULL, NULL); + target_bmp = cogl_bitmap_new_for_data (ctx, + tex_width, + tex_height, + format, + rowstride, + data); else - { - int target_rowstride = tex_width * closest_bpp; - guint8 *target_data = g_malloc (tex_height * target_rowstride); - target_bmp = _cogl_bitmap_new_from_data (target_data, - closest_format, - tex_width, - tex_height, - target_rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); - } + target_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + tex_width, tex_height, + closest_format); tg_data.orig_width = tex_width; tg_data.orig_height = tex_height; @@ -1236,12 +1218,11 @@ cogl_texture_get_data (CoglTexture *texture, gboolean result; /* 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 */); + new_bmp = cogl_bitmap_new_for_data (ctx, + tex_width, tex_height, + format, + rowstride, + data); result = _cogl_bitmap_convert_into_bitmap (target_bmp, new_bmp); if (!result) diff --git a/cogl/cogl.c b/cogl/cogl.c index b60f838c7..95d8d5f04 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -376,12 +376,13 @@ cogl_read_pixels (int x, int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); CoglBitmap *bitmap; - bitmap = _cogl_bitmap_new_from_data (pixels, - format, - width, height, - bpp * width, /* rowstride */ - NULL, /* destroy_fn */ - NULL /* destroy_fn_data */); + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + bitmap = cogl_bitmap_new_for_data (ctx, + width, height, + format, + bpp * width, /* rowstride */ + pixels); cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (), x, y, source, diff --git a/cogl/driver/gles/cogl-texture-driver-gles.c b/cogl/driver/gles/cogl-texture-driver-gles.c index df7a39829..2bc596b32 100644 --- a/cogl/driver/gles/cogl-texture-driver-gles.c +++ b/cogl/driver/gles/cogl-texture-driver-gles.c @@ -151,15 +151,10 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, width != cogl_bitmap_get_width (source_bmp) || height != cogl_bitmap_get_height (source_bmp)) { - rowstride = bpp * width; - rowstride = (rowstride + 3) & ~3; slice_bmp = - _cogl_bitmap_new_from_data (g_malloc (height * rowstride), - source_format, - width, height, - rowstride, - (CoglBitmapDestroyNotify) g_free, - NULL); + _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + source_format); _cogl_bitmap_copy_subregion (source_bmp, slice_bmp, src_x, src_y, @@ -167,10 +162,9 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, width, height); } else - { - slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp); - rowstride = cogl_bitmap_get_rowstride (slice_bmp); - } + slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp); + + rowstride = cogl_bitmap_get_rowstride (slice_bmp); /* Setup gl alignment to match rowstride and top-left corner */ _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp); @@ -263,6 +257,7 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, { CoglBitmap *bmp; int image_height = bmp_height / depth; + CoglPixelFormat source_bmp_format = cogl_bitmap_get_format (source_bmp); int i; _cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp); @@ -281,13 +276,10 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, source_gl_type, NULL) ); - bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height), - cogl_bitmap_get_format (source_bmp), - bmp_width, - height, - bpp * bmp_width, - (CoglBitmapDestroyNotify) g_free, - NULL); + bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + bmp_width, + height, + source_bmp_format); for (i = 0; i < depth; i++) {