int height,
int rowstride);
+/* This creates a cogl bitmap that internally references a pixel
+ array. The data is not copied. _cogl_bitmap_map will divert to
+ mapping the pixel array */
+CoglBitmap *
+_cogl_bitmap_new_from_buffer (CoglBuffer *buffer,
+ CoglPixelFormat format,
+ int width,
+ int height,
+ int rowstride,
+ int offset);
+
gboolean
_cogl_bitmap_can_convert (CoglPixelFormat src, CoglPixelFormat dst);
void
_cogl_bitmap_unmap (CoglBitmap *bitmap);
+/* These two are replacements for map and unmap that should used when
+ the pointer is going to be passed to GL for pixel packing or
+ unpacking. The address might not be valid for reading if the bitmap
+ was created with new_from_buffer but it will however be good to
+ pass to glTexImage2D for example. The access should be READ for
+ unpacking and WRITE for packing. It can not be both */
+guint8 *
+_cogl_bitmap_bind (CoglBitmap *bitmap,
+ CoglBufferAccess access,
+ CoglBufferMapHint hints);
+
+void
+_cogl_bitmap_unbind (CoglBitmap *bitmap);
+
#endif /* __COGL_BITMAP_H */
#include "cogl.h"
#include "cogl-internal.h"
#include "cogl-bitmap-private.h"
+#include "cogl-buffer-private.h"
#include <string.h>
void *destroy_fn_data;
gboolean mapped;
+ gboolean bound;
/* If this is non-null then 'data' is ignored and instead it is
fetched from this shared bitmap. */
CoglBitmap *shared_bmp;
+
+ /* If this is non-null then 'data' is treated as an offset into the
+ buffer and map will divert to mapping the buffer */
+ CoglBuffer *buffer;
};
static void _cogl_bitmap_free (CoglBitmap *bmp);
_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);
+ if (bmp->buffer)
+ cogl_object_unref (bmp->buffer);
+
g_slice_free (CoglBitmap, bmp);
}
bmp->destroy_fn = destroy_fn;
bmp->destroy_fn_data = destroy_fn_data;
bmp->mapped = FALSE;
+ bmp->bound = FALSE;
bmp->shared_bmp = NULL;
+ bmp->buffer = NULL;
return _cogl_bitmap_object_new (bmp);
}
return bmp;
}
+CoglBitmap *
+_cogl_bitmap_new_from_buffer (CoglBuffer *buffer,
+ CoglPixelFormat format,
+ int width,
+ int height,
+ int rowstride,
+ int offset)
+{
+ CoglBitmap *bmp;
+
+ g_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->buffer = cogl_object_ref (buffer);
+ bmp->data = GINT_TO_POINTER (offset);
+
+ return bmp;
+}
+
CoglPixelFormat
_cogl_bitmap_get_format (CoglBitmap *bitmap)
{
return _cogl_bitmap_map (bitmap->shared_bmp, access, hints);
g_assert (!bitmap->mapped);
- bitmap->mapped = TRUE;
- /* Currently the bitmap is always in regular memory so we can just
- directly return the pointer */
- return bitmap->data;
+ if (bitmap->buffer)
+ {
+ guint8 *data = cogl_buffer_map (bitmap->buffer,
+ access,
+ hints);
+
+ COGL_NOTE (BITMAP, "A pixel array is being mapped from a bitmap. This "
+ "usually means that some conversion on the pixel array is "
+ "needed so a sub-optimal format is being used.");
+
+ if (data)
+ {
+ bitmap->mapped = TRUE;
+
+ return data + GPOINTER_TO_INT (bitmap->data);
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ bitmap->mapped = TRUE;
+
+ return bitmap->data;
+ }
}
void
g_assert (bitmap->mapped);
bitmap->mapped = FALSE;
- /* Currently the bitmap is always in regular memory so we don't need
- to do anything */
+ if (bitmap->buffer)
+ cogl_buffer_unmap (bitmap->buffer);
+}
+
+guint8 *
+_cogl_bitmap_bind (CoglBitmap *bitmap,
+ CoglBufferAccess access,
+ CoglBufferMapHint hints)
+{
+ guint8 *ptr;
+
+ /* Divert to another bitmap if this data is shared */
+ if (bitmap->shared_bmp)
+ return _cogl_bitmap_bind (bitmap->shared_bmp, access, hints);
+
+ g_assert (!bitmap->bound);
+
+ /* If the bitmap wasn't created from a buffer then the
+ implementation of bind is the same as map */
+ if (bitmap->buffer == NULL)
+ {
+ guint8 *data = _cogl_bitmap_map (bitmap, access, hints);
+ if (data)
+ bitmap->bound = TRUE;
+ return data;
+ }
+
+ bitmap->bound = TRUE;
+
+ /* If buffer is using a malloc fallback then we'll just use the
+ pointer directly */
+ if (COGL_BUFFER_FLAG_IS_SET (bitmap->buffer, BUFFER_OBJECT))
+ {
+ ptr = NULL;
+
+ if (access == COGL_BUFFER_ACCESS_READ)
+ _cogl_buffer_bind (bitmap->buffer,
+ COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
+ else if (access == COGL_BUFFER_ACCESS_WRITE)
+ _cogl_buffer_bind (bitmap->buffer,
+ COGL_BUFFER_BIND_TARGET_PIXEL_PACK);
+ else
+ g_assert_not_reached ();
+ }
+ else
+ ptr = bitmap->buffer->data;
+
+ /* The data pointer actually stores the offset */
+ return GPOINTER_TO_INT (bitmap->data) + ptr;
+}
+
+void
+_cogl_bitmap_unbind (CoglBitmap *bitmap)
+{
+ /* Divert to another bitmap if this data is shared */
+ if (bitmap->shared_bmp)
+ return _cogl_bitmap_unbind (bitmap->shared_bmp);
+
+ g_assert (bitmap->bound);
+ bitmap->bound = FALSE;
+
+ /* If the bitmap wasn't created from a pixel array then the
+ implementation of unbind is the same as unmap */
+ if (bitmap->buffer)
+ {
+ if (COGL_BUFFER_FLAG_IS_SET (bitmap->buffer, BUFFER_OBJECT))
+ _cogl_buffer_unbind (bitmap->buffer);
+ }
+ else
+ _cogl_bitmap_unmap (bitmap);
}
CoglHandle texture;
CoglBuffer *cogl_buffer;
CoglPixelArray *pixel_array;
+ CoglBitmap *bmp;
g_return_val_if_fail (cogl_is_buffer (buffer), COGL_INVALID_HANDLE);
return COGL_INVALID_HANDLE;
}
-#if !defined (COGL_HAS_GLES)
- if (cogl_features_available (COGL_FEATURE_PBOS))
- {
- CoglBitmap *bmp;
+ /* Wrap the buffer into a bitmap */
+ bmp = _cogl_bitmap_new_from_buffer (cogl_buffer,
+ format,
+ width, height,
+ rowstride,
+ offset);
- /* Wrap the data into a bitmap */
- bmp = _cogl_bitmap_new_from_data (GUINT_TO_POINTER (offset),
- format,
- width, height,
- rowstride,
- NULL, NULL);
+ texture = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
- _cogl_buffer_bind (cogl_buffer,
- COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
- texture = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
- _cogl_buffer_unbind (cogl_buffer);
-
- cogl_object_unref (bmp);
- }
- else
-#endif
- {
- texture = cogl_texture_new_from_data (width,
- height,
- flags,
- format,
- internal_format,
- rowstride,
- cogl_buffer->data);
- }
+ cogl_object_unref (bmp);
return texture;
}
GLuint source_gl_type)
{
guint8 *data;
+ int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
- if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
+ data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- 0,
- src_x,
- src_y,
- bpp);
+ /* Setup gl alignment to match rowstride and top-left corner */
+ prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
+ 0,
+ src_x,
+ src_y,
+ bpp);
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
+ _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
- GE( glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data) );
+ GE( glTexSubImage2D (gl_target, 0,
+ dst_x, dst_y,
+ width, height,
+ source_gl_format,
+ source_gl_type,
+ data) );
- _cogl_bitmap_unmap (source_bmp);
- }
+ _cogl_bitmap_unbind (source_bmp);
}
void
GLuint source_gl_type)
{
guint8 *data;
+ int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
- if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
+ data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- 0, 0, 0, bpp);
+ /* Setup gl alignment to match rowstride and top-left corner */
+ prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
+ 0, 0, 0, bpp);
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
+ _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
- GE( glTexImage2D (gl_target, 0,
- internal_gl_format,
- _cogl_bitmap_get_width (source_bmp),
- _cogl_bitmap_get_height (source_bmp),
- 0,
- source_gl_format,
- source_gl_type,
- data) );
+ GE( glTexImage2D (gl_target, 0,
+ internal_gl_format,
+ _cogl_bitmap_get_width (source_bmp),
+ _cogl_bitmap_get_height (source_bmp),
+ 0,
+ source_gl_format,
+ source_gl_type,
+ data) );
- _cogl_bitmap_unmap (source_bmp);
- }
+ _cogl_bitmap_unbind (source_bmp);
}
void
GLuint source_gl_type)
{
guint8 *data;
+ int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
-
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- (_cogl_bitmap_get_height (source_bmp) /
- depth),
- 0, 0, bpp);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- GE( glTexImage3D (gl_target,
- 0, /* level */
- internal_gl_format,
- _cogl_bitmap_get_width (source_bmp),
- height,
- depth,
- 0,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unmap (source_bmp);
- }
+ data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
+
+ /* Setup gl alignment to match rowstride and top-left corner */
+ prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
+ (_cogl_bitmap_get_height (source_bmp) /
+ depth),
+ 0, 0, bpp);
+
+ _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
+
+ GE( glTexImage3D (gl_target,
+ 0, /* level */
+ internal_gl_format,
+ _cogl_bitmap_get_width (source_bmp),
+ height,
+ depth,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ data) );
+
+ _cogl_bitmap_unbind (source_bmp);
}
gboolean
0, 0,
width, height);
- if ((data = _cogl_bitmap_map (slice_bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
+ data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);
+
+ _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
- GE( glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data) );
+ GE( glTexSubImage2D (gl_target, 0,
+ dst_x, dst_y,
+ width, height,
+ source_gl_format,
+ source_gl_type,
+ data) );
- _cogl_bitmap_unmap (slice_bmp);
- }
+ _cogl_bitmap_unbind (slice_bmp);
cogl_object_unref (slice_bmp);
}
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
- if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- GE( glTexImage2D (gl_target, 0,
- internal_gl_format,
- bmp_width, bmp_height,
- 0,
- source_gl_format,
- source_gl_type,
- data) );
+ data = _cogl_bitmap_bind (bmp, COGL_BUFFER_ACCESS_READ, 0);
- _cogl_bitmap_unmap (bmp);
- }
+ GE( glTexImage2D (gl_target, 0,
+ internal_gl_format,
+ bmp_width, bmp_height,
+ 0,
+ source_gl_format,
+ source_gl_type,
+ data) );
+
+ _cogl_bitmap_unbind (bmp);
cogl_object_unref (bmp);
}
bmp_width,
bmp_height);
- if ((data = _cogl_bitmap_map (bmp,
- COGL_BUFFER_ACCESS_READ, 0)))
- {
- GE( glTexSubImage3D (gl_target,
- 0, /* level */
- 0, /* xoffset */
- 0, /* yoffset */
- i, /* zoffset */
- bmp_width, /* width */
- height, /* height */
- 1, /* depth */
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unmap (bmp);
- }
+ data = _cogl_bitmap_bind (bmp,
+ COGL_BUFFER_ACCESS_READ, 0);
+
+ GE( glTexSubImage3D (gl_target,
+ 0, /* level */
+ 0, /* xoffset */
+ 0, /* yoffset */
+ i, /* zoffset */
+ bmp_width, /* width */
+ height, /* height */
+ 1, /* depth */
+ source_gl_format,
+ source_gl_type,
+ data) );
+
+ _cogl_bitmap_unbind (bmp);
}
cogl_object_unref (bmp);
}
- else if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
+ else
{
+ data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
+
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
GE( glTexImage3D (gl_target,
source_gl_type,
data) );
- _cogl_bitmap_unmap (source_bmp);
+ _cogl_bitmap_unbind (source_bmp);
}
}