[cogl] Add a public cogl_bitmap_new_for_data



commit d18b59d9e67f6ec2dd747da91d8c1380e1730d3e
Author: Neil Roberts <neil linux intel com>
Date:   Tue Mar 13 14:46:18 2012 +0000

    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>

 cogl/cogl-atlas.c                           |   18 ++--
 cogl/cogl-bitmap-conversion.c               |   22 ++---
 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                      |   45 ++++++----
 cogl/cogl-texture.c                         |  129 +++++++++++---------------
 cogl/cogl.c                                 |   13 ++--
 cogl/driver/gles/cogl-texture-driver-gles.c |   30 +++----
 14 files changed, 276 insertions(+), 264 deletions(-)
---
diff --git a/cogl/cogl-atlas.c b/cogl/cogl-atlas.c
index 2a4e06e..bfa76dc 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 64ce8cc..6a57dbf 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 <string.h>
 
@@ -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 3f56631..ada8e54 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 <string.h>
 
@@ -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 ab80868..fc93406 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 4d26305..b0c6ec7 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 <string.h>
 
@@ -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;
@@ -211,19 +202,46 @@ _cogl_bitmap_new_from_data (guint8                  *data,
 }
 
 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,
                          int                      width,
                          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 3787d92..e2e2962 100644
--- a/cogl/cogl-bitmap.h
+++ b/cogl/cogl-bitmap.h
@@ -130,6 +130,34 @@ cogl_bitmap_new_with_size (CoglContext *context,
                            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 b3c404e..8b1ea2b 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 cdf5f8d..799f406 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 73ed348..836caaf 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 da57cb4..93bb07c 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 c2066f7..8662d5a 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 6d6a1f2..6b08ec5 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);
-
-          cogl_read_pixels (viewport[0], viewport[1],
-                            width,
-                            height,
-                            COGL_READ_PIXELS_COLOR_BUFFER,
-                            COGL_PIXEL_FORMAT_RGBA_8888_PRE,
-                            data);
+          rect_bmp = _cogl_bitmap_new_with_malloc_buffer
+                                              (ctx,
+                                               width, height,
+                                               COGL_PIXEL_FORMAT_RGBA_8888_PRE);
+
+          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; y<target_height; ++y)
         {
           for (x=0; x<target_width; ++x)
@@ -932,6 +923,8 @@ _cogl_texture_draw_and_read (CoglTexture *texture,
           dstdata += target_rowstride;
         }
 
+      _cogl_bitmap_unmap (alpha_bmp);
+
       _cogl_bitmap_unmap (target_bmp);
 
       cogl_object_unref (alpha_bmp);
@@ -976,12 +969,11 @@ get_texture_bits_via_offscreen (CoglTexture    *texture,
 
   framebuffer = COGL_FRAMEBUFFER (offscreen);
 
-  bitmap = _cogl_bitmap_new_from_data (dst_bits,
-                                       dst_format,
-                                       width, height,
-                                       dst_rowstride,
-                                       NULL, /* destroy_fn */
-                                       NULL /* destroy_fn_data */);
+  bitmap = cogl_bitmap_new_for_data (ctx,
+                                     width, height,
+                                     dst_format,
+                                     dst_rowstride,
+                                     dst_bits);
   cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
                                             x, y,
                                             COGL_READ_PIXELS_COLOR_BUFFER,
@@ -1125,7 +1117,6 @@ cogl_texture_get_data (CoglTexture     *texture,
   int              bpp;
   int              byte_size;
   CoglPixelFormat  closest_format;
-  int              closest_bpp;
   GLenum           closest_gl_format;
   GLenum           closest_gl_type;
   CoglBitmap      *target_bmp;
@@ -1160,7 +1151,6 @@ cogl_texture_get_data (CoglTexture     *texture,
     ctx->texture_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 b60f838..95d8d5f 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 df7a398..2bc596b 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++)
         {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]