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 <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2012-03-13 14:46:18 +00:00
parent f65a895b4f
commit d18b59d9e6
14 changed files with 273 additions and 261 deletions

View File

@ -272,6 +272,8 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
{ {
CoglHandle tex; CoglHandle tex;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE)) if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE))
{ {
guint8 *clear_data; guint8 *clear_data;
@ -280,22 +282,22 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
/* Create a buffer of zeroes to initially clear the texture */ /* Create a buffer of zeroes to initially clear the texture */
clear_data = g_malloc0 (width * height * bpp); clear_data = g_malloc0 (width * height * bpp);
clear_bmp = _cogl_bitmap_new_from_data (clear_data, clear_bmp = cogl_bitmap_new_for_data (ctx,
atlas->texture_format,
width, width,
height, height,
atlas->texture_format,
width * bpp, width * bpp,
(CoglBitmapDestroyNotify) g_free, clear_data);
NULL);
tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE, tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE,
atlas->texture_format, atlas->texture_format,
NULL); NULL);
cogl_object_unref (clear_bmp); cogl_object_unref (clear_bmp);
g_free (clear_data);
} }
else else
{ {
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
tex = cogl_texture_2d_new_with_size (ctx, tex = cogl_texture_2d_new_with_size (ctx,
width, height, width, height,
atlas->texture_format, atlas->texture_format,

View File

@ -27,6 +27,7 @@
#include "cogl-private.h" #include "cogl-private.h"
#include "cogl-bitmap-private.h" #include "cogl-bitmap-private.h"
#include "cogl-context-private.h"
#include <string.h> #include <string.h>
@ -470,26 +471,17 @@ CoglBitmap *
_cogl_bitmap_convert (CoglBitmap *src_bmp, _cogl_bitmap_convert (CoglBitmap *src_bmp,
CoglPixelFormat dst_format) CoglPixelFormat dst_format)
{ {
int dst_bpp;
int dst_rowstride;
guint8 *dst_data;
CoglBitmap *dst_bmp; CoglBitmap *dst_bmp;
int width, height; int width, height;
_COGL_GET_CONTEXT (ctx, NULL);
width = cogl_bitmap_get_width (src_bmp); width = cogl_bitmap_get_width (src_bmp);
height = cogl_bitmap_get_height (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_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx,
dst_data = g_malloc (height * dst_rowstride);
dst_bmp = _cogl_bitmap_new_from_data (dst_data,
dst_format,
width, height, width, height,
dst_rowstride, dst_format);
(CoglBitmapDestroyNotify) g_free,
NULL);
if (!_cogl_bitmap_convert_into_bitmap (src_bmp, dst_bmp)) if (!_cogl_bitmap_convert_into_bitmap (src_bmp, dst_bmp))
{ {

View File

@ -28,6 +28,7 @@
#include "cogl-util.h" #include "cogl-util.h"
#include "cogl-internal.h" #include "cogl-internal.h"
#include "cogl-bitmap-private.h" #include "cogl-bitmap-private.h"
#include "cogl-context-private.h"
#include <string.h> #include <string.h>
@ -166,17 +167,11 @@ _cogl_bitmap_get_size_from_file (const char *filename,
return FALSE; return FALSE;
} }
static void
_cogl_bitmap_unref_pixbuf (guint8 *pixels,
void *pixbuf)
{
g_object_unref (pixbuf);
}
CoglBitmap * CoglBitmap *
_cogl_bitmap_from_file (const char *filename, _cogl_bitmap_from_file (const char *filename,
GError **error) GError **error)
{ {
static CoglUserDataKey pixbuf_key;
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
gboolean has_alpha; gboolean has_alpha;
GdkColorspace color_space; GdkColorspace color_space;
@ -186,6 +181,9 @@ _cogl_bitmap_from_file (const char *filename,
int rowstride; int rowstride;
int bits_per_sample; int bits_per_sample;
int n_channels; int n_channels;
CoglBitmap *bmp;
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE); _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 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 rowstride is much larger so we don't need to worry about
GdkPixbuf's semantics that it may under-allocate the buffer. */ GdkPixbuf's semantics that it may under-allocate the buffer. */
return _cogl_bitmap_new_from_data (gdk_pixbuf_get_pixels (pixbuf), bmp = cogl_bitmap_new_for_data (ctx,
pixel_format,
width, width,
height, height,
pixel_format,
rowstride, rowstride,
_cogl_bitmap_unref_pixbuf, gdk_pixbuf_get_pixels (pixbuf));
pixbuf);
cogl_object_set_user_data (COGL_OBJECT (bmp),
&pixbuf_key,
pixbuf,
g_object_unref);
return bmp;
} }
#else #else

View File

@ -33,43 +33,27 @@
#include "cogl-bitmap.h" #include "cogl-bitmap.h"
/* /*
* CoglBitmapDestroyNotify: * _cogl_bitmap_new_with_malloc_buffer:
* @data: The image data * @context: A #CoglContext
* @destroy_data: The callback closure data that was given to * @width: width of the bitmap in pixels
* _cogl_bitmap_new_from_data(). * @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 * This is equivalent to cogl_bitmap_new_with_size() except that it
* _cogl_bitmap_new_from_data() is called. * allocated the buffer using g_malloc() instead of creating a
*/ * #CoglPixelBuffer. The buffer will be automatically destroyed when
typedef void (* CoglBitmapDestroyNotify) (guint8 *data, void *destroy_data); * the bitmap is freed.
/*
* _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.
* *
* Creates a bitmap using some existing data. The data is not copied * Return value: a #CoglPixelBuffer representing the newly created array
* 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 new %CoglBitmap. * Since: 1.10
* Stability: Unstable
*/ */
CoglBitmap * CoglBitmap *
_cogl_bitmap_new_from_data (guint8 *data, _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
CoglPixelFormat format, unsigned int width,
int width, unsigned int height,
int height, CoglPixelFormat format);
int rowstride,
CoglBitmapDestroyNotify destroy_fn,
gpointer destroy_fn_data);
/* The idea of this function is that it will create a bitmap that /* 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 shares the actual data with another bitmap. This is needed for the

View File

@ -31,6 +31,7 @@
#include "cogl-bitmap-private.h" #include "cogl-bitmap-private.h"
#include "cogl-buffer-private.h" #include "cogl-buffer-private.h"
#include "cogl-pixel-buffer.h" #include "cogl-pixel-buffer.h"
#include "cogl-context-private.h"
#include <string.h> #include <string.h>
@ -43,8 +44,6 @@ struct _CoglBitmap
int rowstride; int rowstride;
guint8 *data; guint8 *data;
CoglBitmapDestroyNotify destroy_fn;
void *destroy_fn_data;
gboolean mapped; gboolean mapped;
gboolean bound; gboolean bound;
@ -68,9 +67,6 @@ _cogl_bitmap_free (CoglBitmap *bmp)
g_assert (!bmp->mapped); g_assert (!bmp->mapped);
g_assert (!bmp->bound); g_assert (!bmp->bound);
if (bmp->destroy_fn)
bmp->destroy_fn (bmp->data, bmp->destroy_fn_data);
if (bmp->shared_bmp) if (bmp->shared_bmp)
cogl_object_unref (bmp->shared_bmp); cogl_object_unref (bmp->shared_bmp);
@ -105,20 +101,15 @@ _cogl_bitmap_copy (CoglBitmap *src_bmp)
{ {
CoglBitmap *dst_bmp; CoglBitmap *dst_bmp;
CoglPixelFormat src_format = cogl_bitmap_get_format (src_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 width = cogl_bitmap_get_width (src_bmp);
int height = cogl_bitmap_get_height (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 */ _COGL_GET_CONTEXT (ctx, NULL);
dst_rowstride = (dst_rowstride + 3) & ~3;
dst_bmp = _cogl_bitmap_new_from_data (g_malloc (dst_rowstride * height), dst_bmp =
src_format, _cogl_bitmap_new_with_malloc_buffer (ctx,
width, height, width, height,
dst_rowstride, src_format);
(CoglBitmapDestroyNotify) g_free,
NULL);
_cogl_bitmap_copy_subregion (src_bmp, _cogl_bitmap_copy_subregion (src_bmp,
dst_bmp, dst_bmp,
@ -185,23 +176,23 @@ cogl_bitmap_get_size_from_file (const char *filename,
} }
CoglBitmap * CoglBitmap *
_cogl_bitmap_new_from_data (guint8 *data, cogl_bitmap_new_for_data (CoglContext *context,
CoglPixelFormat format,
int width, int width,
int height, int height,
CoglPixelFormat format,
int rowstride, int rowstride,
CoglBitmapDestroyNotify destroy_fn, guint8 *data)
void *destroy_fn_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->format = format;
bmp->width = width; bmp->width = width;
bmp->height = height; bmp->height = height;
bmp->rowstride = rowstride; bmp->rowstride = rowstride;
bmp->data = data; bmp->data = data;
bmp->destroy_fn = destroy_fn;
bmp->destroy_fn_data = destroy_fn_data;
bmp->mapped = FALSE; bmp->mapped = FALSE;
bmp->bound = FALSE; bmp->bound = FALSE;
bmp->shared_bmp = NULL; bmp->shared_bmp = NULL;
@ -210,6 +201,31 @@ _cogl_bitmap_new_from_data (guint8 *data,
return _cogl_bitmap_object_new (bmp); 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 * CoglBitmap *
_cogl_bitmap_new_shared (CoglBitmap *shared_bmp, _cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
CoglPixelFormat format, CoglPixelFormat format,
@ -217,13 +233,15 @@ _cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
int height, int height,
int rowstride) int rowstride)
{ {
CoglBitmap *bmp = _cogl_bitmap_new_from_data (NULL, /* data */ CoglBitmap *bmp;
_COGL_GET_CONTEXT (ctx, NULL);
bmp = cogl_bitmap_new_for_data (ctx,
width, height,
format, format,
width,
height,
rowstride, rowstride,
NULL, /* destroy_fn */ NULL /* data */);
NULL /* destroy_fn_data */);
bmp->shared_bmp = cogl_object_ref (shared_bmp); 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); _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL);
bmp = _cogl_bitmap_new_from_data (NULL, /* data */ bmp = cogl_bitmap_new_for_data (buffer->context,
width, height,
format, format,
width,
height,
rowstride, rowstride,
NULL, /* destroy_fn */ NULL /* data */);
NULL /* destroy_fn_data */);
bmp->buffer = cogl_object_ref (buffer); bmp->buffer = cogl_object_ref (buffer);
bmp->data = GINT_TO_POINTER (offset); bmp->data = GINT_TO_POINTER (offset);

View File

@ -129,6 +129,34 @@ cogl_bitmap_new_with_size (CoglContext *context,
unsigned int height, unsigned int height,
CoglPixelFormat format); 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: * cogl_bitmap_get_format:
* @bitmap: A #CoglBitmap * @bitmap: A #CoglBitmap

View File

@ -158,6 +158,11 @@ cogl_context_new (CoglDisplay *display,
/* Allocate context memory */ /* Allocate context memory */
context = g_malloc (sizeof (CoglContext)); 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! /* XXX: Gross hack!
* Currently everything in Cogl just assumes there is a default * Currently everything in Cogl just assumes there is a default
* context which it can access via _COGL_GET_CONTEXT() including * 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); _cogl_matrix_stack_init_cache (&_context->builtin_flushed_modelview);
default_texture_bitmap = default_texture_bitmap =
_cogl_bitmap_new_from_data (default_texture_data, cogl_bitmap_new_for_data (_context,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
1, 1, /* width/height */ 1, 1, /* width/height */
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
4, /* rowstride */ 4, /* rowstride */
NULL, /* destroy function */ default_texture_data);
NULL /* destroy function data */);
/* Create default textures used for fall backs */ /* Create default textures used for fall backs */
context->default_gl_texture_2d_tex = context->default_gl_texture_2d_tex =
@ -430,7 +434,7 @@ cogl_context_new (CoglDisplay *display,
cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE)) cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
GE (context, glEnable (GL_POINT_SPRITE)); GE (context, glEnable (GL_POINT_SPRITE));
return _cogl_context_object_new (context); return context;
} }
static void static void

View File

@ -2036,9 +2036,9 @@ cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
(required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT)) (required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT))
{ {
CoglBitmap *tmp_bmp; CoglBitmap *tmp_bmp;
guint8 *tmp_data;
CoglPixelFormat read_format; CoglPixelFormat read_format;
int bpp, rowstride; int bpp, rowstride;
guint8 *tmp_data;
int succeeded; int succeeded;
if (ctx->driver == COGL_DRIVER_GL) 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) | read_format = ((read_format & ~COGL_PREMULT_BIT) |
(framebuffer->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); bpp = _cogl_pixel_format_get_bytes_per_pixel (read_format);
rowstride = (width * bpp + 3) & ~3; rowstride = cogl_bitmap_get_rowstride (tmp_bmp);
tmp_data = g_malloc (rowstride * height);
tmp_bmp = _cogl_bitmap_new_from_data (tmp_data,
read_format,
width, height, rowstride,
(CoglBitmapDestroyNotify) g_free,
NULL);
ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); 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, GE( ctx, glReadPixels (x, y, width, height,
gl_format, gl_type, gl_format, gl_type,
tmp_data) ); tmp_data) );
_cogl_bitmap_unbind (tmp_bmp);
succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap); succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap);
cogl_object_unref (tmp_bmp); cogl_object_unref (tmp_bmp);

View File

@ -175,6 +175,8 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
{ {
gboolean need_x, need_y; gboolean need_x, need_y;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* If the x_span is sliced and the upload touches the /* If the x_span is sliced and the upload touches the
rightmost pixels then fill the waste with copies of the rightmost pixels then fill the waste with copies of the
pixels */ pixels */
@ -222,15 +224,13 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
src += bmp_rowstride; src += bmp_rowstride;
} }
waste_bmp = waste_bmp = cogl_bitmap_new_for_data (ctx,
_cogl_bitmap_new_from_data (waste_buf,
source_format,
x_span->waste, x_span->waste,
y_iter->intersect_end - y_iter->intersect_end -
y_iter->intersect_start, y_iter->intersect_start,
source_format,
x_span->waste * bpp, x_span->waste * bpp,
NULL, waste_buf);
NULL);
cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex),
0, /* src_x */ 0, /* src_x */
@ -279,14 +279,12 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
} }
} }
waste_bmp = waste_bmp = cogl_bitmap_new_for_data (ctx,
_cogl_bitmap_new_from_data (waste_buf,
source_format,
copy_width, copy_width,
y_span->waste, y_span->waste,
source_format,
copy_width * bpp, copy_width * bpp,
NULL, waste_buf);
NULL);
cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex),
0, /* src_x */ 0, /* src_x */

View File

@ -313,12 +313,11 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = _cogl_bitmap_new_from_data ((guint8 *)data, bmp = cogl_bitmap_new_for_data (ctx,
width, height,
format, format,
width,
height,
rowstride, rowstride,
NULL, NULL); (guint8 *) data);
tex =_cogl_texture_2d_new_from_bitmap (bmp, COGL_TEXTURE_NONE, tex =_cogl_texture_2d_new_from_bitmap (bmp, COGL_TEXTURE_NONE,
internal_format, internal_format,

View File

@ -353,18 +353,26 @@ cogl_texture_3d_new_from_data (CoglContext *context,
recommends avoiding this situation. */ recommends avoiding this situation. */
if (image_stride % rowstride != 0) if (image_stride % rowstride != 0)
{ {
guint8 *bmp_data;
int bmp_rowstride;
int z, y; 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, bitmap = _cogl_bitmap_new_with_malloc_buffer (context,
format,
width, width,
depth * height, depth * height,
bmp_rowstride, format);
(CoglBitmapDestroyNotify) g_free,
NULL /* destroy_fn_data */); 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 */ /* Copy all of the images in */
for (z = 0; z < depth; z++) for (z = 0; z < depth; z++)
@ -373,15 +381,16 @@ cogl_texture_3d_new_from_data (CoglContext *context,
bmp_rowstride * y), bmp_rowstride * y),
data + z * image_stride + rowstride * y, data + z * image_stride + rowstride * y,
bmp_rowstride); bmp_rowstride);
_cogl_bitmap_unmap (bitmap);
} }
else else
bitmap = _cogl_bitmap_new_from_data ((guint8 *) data, bitmap = cogl_bitmap_new_for_data (context,
format,
width, width,
image_stride / rowstride * depth, image_stride / rowstride * depth,
format,
rowstride, rowstride,
NULL, /* destroy_fn */ (guint8 *) data);
NULL /* destroy_fn_data */);
ret = _cogl_texture_3d_new_from_bitmap (context, ret = _cogl_texture_3d_new_from_bitmap (context,
bitmap, bitmap,

View File

@ -329,6 +329,8 @@ cogl_texture_new_from_data (unsigned int width,
CoglBitmap *bmp; CoglBitmap *bmp;
CoglTexture *tex; CoglTexture *tex;
_COGL_GET_CONTEXT (ctx, NULL);
if (format == COGL_PIXEL_FORMAT_ANY) if (format == COGL_PIXEL_FORMAT_ANY)
return NULL; return NULL;
@ -340,12 +342,11 @@ cogl_texture_new_from_data (unsigned int width,
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = _cogl_bitmap_new_from_data ((guint8 *) data, bmp = cogl_bitmap_new_for_data (ctx,
width, height,
format, format,
width,
height,
rowstride, rowstride,
NULL, NULL); (guint8 *) data);
tex = cogl_texture_new_from_bitmap (bmp, flags, internal_format); tex = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
@ -663,6 +664,8 @@ cogl_texture_set_region (CoglTexture *texture,
CoglBitmap *source_bmp; CoglBitmap *source_bmp;
gboolean ret; gboolean ret;
_COGL_GET_CONTEXT (ctx, FALSE);
_COGL_RETURN_VAL_IF_FAIL ((width - src_x) >= dst_width, FALSE); _COGL_RETURN_VAL_IF_FAIL ((width - src_x) >= dst_width, FALSE);
_COGL_RETURN_VAL_IF_FAIL ((height - src_y) >= dst_height, 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; rowstride = _cogl_pixel_format_get_bytes_per_pixel (format) * width;
/* Init source bitmap */ /* Init source bitmap */
source_bmp = _cogl_bitmap_new_from_data ((guint8 *) data, source_bmp = cogl_bitmap_new_for_data (ctx,
width, height,
format, format,
width,
height,
rowstride, rowstride,
NULL, /* destroy_fn */ (guint8 *) data);
NULL); /* destroy_fn_data */
ret = cogl_texture_set_region_from_bitmap (texture, ret = cogl_texture_set_region_from_bitmap (texture,
src_x, src_y, src_x, src_y,
@ -712,7 +713,6 @@ do_texture_draw_and_read (CoglTexture *texture,
CoglBitmap *target_bmp, CoglBitmap *target_bmp,
float *viewport) float *viewport)
{ {
int bpp;
float rx1, ry1; float rx1, ry1;
float rx2, ry2; float rx2, ry2;
float tx1, ty1; float tx1, ty1;
@ -721,7 +721,7 @@ do_texture_draw_and_read (CoglTexture *texture,
CoglBitmap *rect_bmp; CoglBitmap *rect_bmp;
unsigned int tex_width, tex_height; 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_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture); tex_height = cogl_texture_get_height (texture);
@ -748,8 +748,6 @@ do_texture_draw_and_read (CoglTexture *texture,
{ {
int width; int width;
int height; int height;
int rowstride;
guint8 *data;
/* Rectangle X coords */ /* Rectangle X coords */
rx1 = rx2; rx1 = rx2;
@ -757,7 +755,6 @@ do_texture_draw_and_read (CoglTexture *texture,
width = rx2 - rx1; width = rx2 - rx1;
height = ry2 - ry1; height = ry2 - ry1;
rowstride = width * bpp;
/* Normalized texture X coords */ /* Normalized texture X coords */
tx1 = tx2; tx1 = tx2;
@ -770,24 +767,17 @@ do_texture_draw_and_read (CoglTexture *texture,
tx1, ty1, tx1, ty1,
tx2, ty2); tx2, ty2);
data = g_malloc (height * rowstride);
/* Read into a temporary bitmap */ /* Read into a temporary bitmap */
rect_bmp = rect_bmp = _cogl_bitmap_new_with_malloc_buffer
_cogl_bitmap_new_from_data (data, (ctx,
COGL_PIXEL_FORMAT_RGBA_8888, width, height,
width, COGL_PIXEL_FORMAT_RGBA_8888_PRE);
height,
rowstride,
(CoglBitmapDestroyNotify) g_free,
NULL);
cogl_read_pixels (viewport[0], viewport[1], cogl_framebuffer_read_pixels_into_bitmap
width, (cogl_get_draw_framebuffer (),
height, viewport[0], viewport[1],
COGL_READ_PIXELS_COLOR_BUFFER, COGL_READ_PIXELS_COLOR_BUFFER,
COGL_PIXEL_FORMAT_RGBA_8888_PRE, rect_bmp);
data);
/* Copy to target bitmap */ /* Copy to target bitmap */
_cogl_bitmap_copy_subregion (rect_bmp, _cogl_bitmap_copy_subregion (rect_bmp,
@ -900,15 +890,12 @@ _cogl_texture_draw_and_read (CoglTexture *texture,
COGL_BUFFER_MAP_HINT_DISCARD)) == NULL) COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
return FALSE; return FALSE;
srcdata = g_malloc (alpha_rowstride * target_height);
/* Create temp bitmap for alpha values */ /* Create temp bitmap for alpha values */
alpha_bmp = _cogl_bitmap_new_from_data (srcdata, alpha_bmp =
COGL_PIXEL_FORMAT_RGBA_8888, _cogl_bitmap_new_with_malloc_buffer (ctx,
target_width, target_height, target_width,
alpha_rowstride, target_height,
(CoglBitmapDestroyNotify) g_free, COGL_PIXEL_FORMAT_RGBA_8888);
NULL);
/* Draw alpha values into RGB channels */ /* Draw alpha values into RGB channels */
cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, 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 */ /* Copy temp R to target A */
srcdata = _cogl_bitmap_map (alpha_bmp,
COGL_BUFFER_ACCESS_READ,
0 /* hints */);
for (y=0; y<target_height; ++y) for (y=0; y<target_height; ++y)
{ {
for (x=0; x<target_width; ++x) for (x=0; x<target_width; ++x)
@ -932,6 +923,8 @@ _cogl_texture_draw_and_read (CoglTexture *texture,
dstdata += target_rowstride; dstdata += target_rowstride;
} }
_cogl_bitmap_unmap (alpha_bmp);
_cogl_bitmap_unmap (target_bmp); _cogl_bitmap_unmap (target_bmp);
cogl_object_unref (alpha_bmp); cogl_object_unref (alpha_bmp);
@ -976,12 +969,11 @@ get_texture_bits_via_offscreen (CoglTexture *texture,
framebuffer = COGL_FRAMEBUFFER (offscreen); framebuffer = COGL_FRAMEBUFFER (offscreen);
bitmap = _cogl_bitmap_new_from_data (dst_bits, bitmap = cogl_bitmap_new_for_data (ctx,
dst_format,
width, height, width, height,
dst_format,
dst_rowstride, dst_rowstride,
NULL, /* destroy_fn */ dst_bits);
NULL /* destroy_fn_data */);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer, cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
x, y, x, y,
COGL_READ_PIXELS_COLOR_BUFFER, COGL_READ_PIXELS_COLOR_BUFFER,
@ -1125,7 +1117,6 @@ cogl_texture_get_data (CoglTexture *texture,
int bpp; int bpp;
int byte_size; int byte_size;
CoglPixelFormat closest_format; CoglPixelFormat closest_format;
int closest_bpp;
GLenum closest_gl_format; GLenum closest_gl_format;
GLenum closest_gl_type; GLenum closest_gl_type;
CoglBitmap *target_bmp; CoglBitmap *target_bmp;
@ -1160,7 +1151,6 @@ cogl_texture_get_data (CoglTexture *texture,
ctx->texture_driver->find_best_gl_get_data_format (format, ctx->texture_driver->find_best_gl_get_data_format (format,
&closest_gl_format, &closest_gl_format,
&closest_gl_type); &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 /* We can assume that whatever data GL gives us will have the
premult status of the original texture */ premult status of the original texture */
@ -1171,24 +1161,16 @@ cogl_texture_get_data (CoglTexture *texture,
/* Is the requested format supported? */ /* Is the requested format supported? */
if (closest_format == format) if (closest_format == format)
/* Target user data directly */ /* Target user data directly */
target_bmp = _cogl_bitmap_new_from_data (data, target_bmp = cogl_bitmap_new_for_data (ctx,
tex_width,
tex_height,
format, format,
tex_width,
tex_height,
rowstride, rowstride,
NULL, NULL); data);
else else
{ target_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx,
int target_rowstride = tex_width * closest_bpp; tex_width, tex_height,
guint8 *target_data = g_malloc (tex_height * target_rowstride); closest_format);
target_bmp = _cogl_bitmap_new_from_data (target_data,
closest_format,
tex_width,
tex_height,
target_rowstride,
(CoglBitmapDestroyNotify) g_free,
NULL);
}
tg_data.orig_width = tex_width; tg_data.orig_width = tex_width;
tg_data.orig_height = tex_height; tg_data.orig_height = tex_height;
@ -1236,12 +1218,11 @@ cogl_texture_get_data (CoglTexture *texture,
gboolean result; gboolean result;
/* Convert to requested format directly into the user's buffer */ /* Convert to requested format directly into the user's buffer */
new_bmp = _cogl_bitmap_new_from_data (data, new_bmp = cogl_bitmap_new_for_data (ctx,
format,
tex_width, tex_height, tex_width, tex_height,
format,
rowstride, rowstride,
NULL, /* destroy_fn */ data);
NULL /* destroy_fn_data */);
result = _cogl_bitmap_convert_into_bitmap (target_bmp, new_bmp); result = _cogl_bitmap_convert_into_bitmap (target_bmp, new_bmp);
if (!result) if (!result)

View File

@ -376,12 +376,13 @@ cogl_read_pixels (int x,
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
CoglBitmap *bitmap; CoglBitmap *bitmap;
bitmap = _cogl_bitmap_new_from_data (pixels, _COGL_GET_CONTEXT (ctx, NO_RETVAL);
format,
bitmap = cogl_bitmap_new_for_data (ctx,
width, height, width, height,
format,
bpp * width, /* rowstride */ bpp * width, /* rowstride */
NULL, /* destroy_fn */ pixels);
NULL /* destroy_fn_data */);
cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (), cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (),
x, y, x, y,
source, source,

View File

@ -151,15 +151,10 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
width != cogl_bitmap_get_width (source_bmp) || width != cogl_bitmap_get_width (source_bmp) ||
height != cogl_bitmap_get_height (source_bmp)) height != cogl_bitmap_get_height (source_bmp))
{ {
rowstride = bpp * width;
rowstride = (rowstride + 3) & ~3;
slice_bmp = slice_bmp =
_cogl_bitmap_new_from_data (g_malloc (height * rowstride), _cogl_bitmap_new_with_malloc_buffer (ctx,
source_format,
width, height, width, height,
rowstride, source_format);
(CoglBitmapDestroyNotify) g_free,
NULL);
_cogl_bitmap_copy_subregion (source_bmp, _cogl_bitmap_copy_subregion (source_bmp,
slice_bmp, slice_bmp,
src_x, src_y, src_x, src_y,
@ -167,10 +162,9 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
width, height); width, height);
} }
else else
{
slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp); slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp);
rowstride = cogl_bitmap_get_rowstride (slice_bmp); rowstride = cogl_bitmap_get_rowstride (slice_bmp);
}
/* Setup gl alignment to match rowstride and top-left corner */ /* Setup gl alignment to match rowstride and top-left corner */
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp); _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; CoglBitmap *bmp;
int image_height = bmp_height / depth; int image_height = bmp_height / depth;
CoglPixelFormat source_bmp_format = cogl_bitmap_get_format (source_bmp);
int i; int i;
_cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp); _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, source_gl_type,
NULL) ); NULL) );
bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height), bmp = _cogl_bitmap_new_with_malloc_buffer (ctx,
cogl_bitmap_get_format (source_bmp),
bmp_width, bmp_width,
height, height,
bpp * bmp_width, source_bmp_format);
(CoglBitmapDestroyNotify) g_free,
NULL);
for (i = 0; i < depth; i++) for (i = 0; i < depth; i++)
{ {