[cogl/wip/pbo-read-pixels: 12/18] Add a public cogl_framebuffer_read_pixels_into_bitmap
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/pbo-read-pixels: 12/18] Add a public cogl_framebuffer_read_pixels_into_bitmap
- Date: Fri, 2 Mar 2012 18:12:01 +0000 (UTC)
commit 91c85e13e758b1923b8a2f55fa6e228d8fe0e0c3
Author: Neil Roberts <neil linux intel com>
Date: Sat Feb 25 19:23:51 2012 +0000
Add a public cogl_framebuffer_read_pixels_into_bitmap
This adds a public function to read pixels from a framebuffer into a
CoglBitmap. This replaces the internal function
_cogl_read_pixels_with_rowstride because a CoglBitmap contains a
rowstride so it can be used for the same purpose. A CoglBitmap already
has public API to make one that points to a CoglPixelBuffer so this
function can be used to read pixels into a PBO. It also avoids the
need to push the framebuffer on to the context's stack so it provides
a function which can be used in the 2.0 API after the stack is
removed.
cogl/cogl-framebuffer-private.h | 8 -
cogl/cogl-framebuffer.c | 258 +++++++++++++++++++-
cogl/cogl-framebuffer.h | 34 +++
cogl/cogl-journal-private.h | 3 +-
cogl/cogl-journal.c | 15 +-
cogl/cogl-private.h | 10 -
cogl/cogl-texture.c | 25 +-
cogl/cogl.c | 200 +--------------
.../cogl-2.0-experimental-sections.txt | 1 +
9 files changed, 328 insertions(+), 226 deletions(-)
---
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 6685d31..0081a2f 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -244,14 +244,6 @@ _cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer);
void
_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer);
-gboolean
-_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
- int x,
- int y,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixel);
-
void
_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
CoglFramebuffer *read_buffer,
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 5a549ab..e3f1239 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -25,6 +25,8 @@
#include "config.h"
#endif
+#include <string.h>
+
#include "cogl-debug.h"
#include "cogl-internal.h"
#include "cogl-context-private.h"
@@ -43,6 +45,7 @@
#include "cogl-primitive-private.h"
#include "cogl-offscreen.h"
#include "cogl1-context.h"
+#include "cogl-private.h"
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER 0x8D40
@@ -1860,15 +1863,15 @@ cogl_framebuffer_get_context (CoglFramebuffer *framebuffer)
return framebuffer->context;
}
-gboolean
+static gboolean
_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
int x,
int y,
CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixel)
+ CoglBitmap *bitmap)
{
gboolean found_intersection;
+ CoglPixelFormat format;
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FAST_READ_PIXEL)))
return FALSE;
@@ -1876,12 +1879,14 @@ _cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
if (source != COGL_READ_PIXELS_COLOR_BUFFER)
return FALSE;
+ format = _cogl_bitmap_get_format (bitmap);
+
if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
format != COGL_PIXEL_FORMAT_RGBA_8888)
return FALSE;
if (!_cogl_journal_try_read_pixel (framebuffer->journal,
- x, y, format, pixel,
+ x, y, bitmap,
&found_intersection))
return FALSE;
@@ -1906,23 +1911,268 @@ _cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
y >= framebuffer->clear_clip_y0 &&
y < framebuffer->clear_clip_y1)
{
+ guint8 *pixel;
/* we currently only care about cases where the premultiplied or
* unpremultipled colors are equivalent... */
if (framebuffer->clear_color_alpha != 1.0)
return FALSE;
+ pixel = _cogl_bitmap_map (bitmap,
+ COGL_BUFFER_ACCESS_WRITE,
+ COGL_BUFFER_MAP_HINT_DISCARD);
+ if (pixel == NULL)
+ return FALSE;
+
pixel[0] = framebuffer->clear_color_red * 255.0;
pixel[1] = framebuffer->clear_color_green * 255.0;
pixel[2] = framebuffer->clear_color_blue * 255.0;
pixel[3] = framebuffer->clear_color_alpha * 255.0;
+ _cogl_bitmap_unmap (bitmap);
+
return TRUE;
}
return FALSE;
}
+gboolean
+cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
+ int x,
+ int y,
+ CoglReadPixelsFlags source,
+ CoglBitmap *bitmap)
+{
+ CoglContext *ctx;
+ int framebuffer_height;
+ CoglPixelFormat format;
+ CoglPixelFormat required_format;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+ gboolean pack_invert_set;
+ int width;
+ int height;
+
+ _COGL_RETURN_VAL_IF_FAIL (source == COGL_READ_PIXELS_COLOR_BUFFER, FALSE);
+ _COGL_RETURN_VAL_IF_FAIL (_cogl_is_framebuffer (framebuffer), FALSE);
+
+ ctx = cogl_framebuffer_get_context (framebuffer);
+
+ width = _cogl_bitmap_get_width (bitmap);
+ height = _cogl_bitmap_get_height (bitmap);
+
+ if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty)
+ {
+ /* If everything drawn so far for this frame is still in the
+ * Journal then if all of the rectangles only have a flat
+ * opaque color we have a fast-path for reading a single pixel
+ * that avoids the relatively high cost of flushing primitives
+ * to be drawn on the GPU (considering how simple the geometry
+ * is in this case) and then blocking on the long GPU pipelines
+ * for the result.
+ */
+ if (_cogl_framebuffer_try_fast_read_pixel (framebuffer,
+ x, y, source, bitmap))
+ return TRUE;
+ }
+
+ /* make sure any batched primitives get emitted to the GL driver
+ * before issuing our read pixels...
+ */
+ _cogl_framebuffer_flush_journal (framebuffer);
+
+ _cogl_framebuffer_flush_state (framebuffer,
+ framebuffer,
+ COGL_FRAMEBUFFER_STATE_BIND);
+
+ framebuffer_height = cogl_framebuffer_get_height (framebuffer);
+
+ /* The y co-ordinate should be given in OpenGL's coordinate system
+ * so 0 is the bottom row
+ *
+ * NB: all offscreen rendering is done upside down so no conversion
+ * is necissary in this case.
+ */
+ if (!cogl_is_offscreen (framebuffer))
+ y = framebuffer_height - y - height;
+
+ format = _cogl_bitmap_get_format (bitmap);
+
+ required_format = ctx->texture_driver->pixel_format_to_gl (format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type);
+
+ /* NB: All offscreen rendering is done upside down so there is no need
+ * to flip in this case... */
+ if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
+ !cogl_is_offscreen (framebuffer))
+ {
+ GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE));
+ pack_invert_set = TRUE;
+ }
+ else
+ pack_invert_set = FALSE;
+
+ /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
+ implementation specific format under
+ GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and
+ GL_IMPLEMENTATION_COLOR_READ_TYPE_OES is supported. We could try
+ to be more clever and check if the requested type matches that
+ but we would need some reliable functions to convert from GL
+ types to Cogl types. For now, lets just always read in
+ GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
+ to use this intermediate buffer if the rowstride has padding
+ because GLES does not support setting GL_ROW_LENGTH */
+ if ((ctx->driver != COGL_DRIVER_GL &&
+ (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
+ _cogl_bitmap_get_rowstride (bitmap) != 4 * width)) ||
+ (required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT))
+ {
+ CoglBitmap *tmp_bmp;
+ guint8 *tmp_data;
+ CoglPixelFormat read_format;
+ int bpp, rowstride;
+ int succeeded;
+
+ if (ctx->driver == COGL_DRIVER_GL)
+ read_format = required_format;
+ else
+ {
+ read_format = COGL_PIXEL_FORMAT_RGBA_8888;
+ gl_format = GL_RGBA;
+ gl_type = GL_UNSIGNED_BYTE;
+ }
+
+ if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (read_format))
+ read_format = ((read_format & ~COGL_PREMULT_BIT) |
+ (framebuffer->format & COGL_PREMULT_BIT));
+
+ 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);
+
+ ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);
+
+ GE( ctx, glReadPixels (x, y, width, height,
+ gl_format, gl_type,
+ tmp_data) );
+
+ succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap);
+
+ cogl_object_unref (tmp_bmp);
+
+ if (!succeeded)
+ return FALSE;
+ }
+ else
+ {
+ CoglBitmap *shared_bmp;
+ CoglPixelFormat bmp_format;
+ int bpp, rowstride;
+ gboolean succeeded = FALSE;
+ guint8 *pixels;
+
+ rowstride = _cogl_bitmap_get_rowstride (bitmap);
+
+ /* We match the premultiplied state of the target buffer to the
+ * premultiplied state of the framebuffer so that it will get
+ * converted to the right format below */
+ if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (format))
+ bmp_format = ((format & ~COGL_PREMULT_BIT) |
+ (framebuffer->format & COGL_PREMULT_BIT));
+ else
+ bmp_format = format;
+
+ if (bmp_format != format)
+ shared_bmp = _cogl_bitmap_new_shared (bitmap,
+ bmp_format,
+ width, height,
+ rowstride);
+ else
+ shared_bmp = cogl_object_ref (bitmap);
+
+ bpp = _cogl_pixel_format_get_bytes_per_pixel (bmp_format);
+
+ ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);
+
+ pixels = _cogl_bitmap_bind (shared_bmp,
+ COGL_BUFFER_ACCESS_WRITE,
+ 0 /* hints */);
+
+ GE( ctx, glReadPixels (x, y,
+ width, height,
+ gl_format, gl_type,
+ pixels) );
+
+ _cogl_bitmap_unbind (shared_bmp);
+
+ /* Convert to the premult format specified by the caller
+ in-place. This will do nothing if the premult status is already
+ correct. */
+ if (_cogl_bitmap_convert_premult_status (shared_bmp, format))
+ succeeded = TRUE;
+
+ cogl_object_unref (shared_bmp);
+
+ if (!succeeded)
+ return FALSE;
+ }
+
+ /* Currently this function owns the pack_invert state and we don't want this
+ * to interfere with other Cogl components so all other code can assume that
+ * we leave the pack_invert state off. */
+ if (pack_invert_set)
+ GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, FALSE));
+
+ /* NB: All offscreen rendering is done upside down so there is no need
+ * to flip in this case... */
+ if (!cogl_is_offscreen (framebuffer) && !pack_invert_set)
+ {
+ guint8 *temprow;
+ int rowstride;
+ guint8 *pixels;
+
+ rowstride = _cogl_bitmap_get_rowstride (bitmap);
+ pixels = _cogl_bitmap_map (bitmap,
+ COGL_BUFFER_ACCESS_READ |
+ COGL_BUFFER_ACCESS_WRITE,
+ 0 /* hints */);
+
+ if (pixels == NULL)
+ return FALSE;
+
+ temprow = g_alloca (rowstride * sizeof (guint8));
+
+ /* vertically flip the buffer in-place */
+ for (y = 0; y < height / 2; y++)
+ {
+ if (y != height - y - 1) /* skip center row */
+ {
+ memcpy (temprow,
+ pixels + y * rowstride, rowstride);
+ memcpy (pixels + y * rowstride,
+ pixels + (height - y - 1) * rowstride, rowstride);
+ memcpy (pixels + (height - y - 1) * rowstride,
+ temprow,
+ rowstride);
+ }
+ }
+
+ _cogl_bitmap_unmap (bitmap);
+ }
+
+ return TRUE;
+}
+
void
_cogl_blit_framebuffer (unsigned int src_x,
unsigned int src_y,
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index 1fbd23d..39dc543 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -46,6 +46,7 @@
#include <cogl/cogl-pipeline.h>
#include <cogl/cogl-indices.h>
+#include <cogl/cogl-bitmap.h>
G_BEGIN_DECLS
@@ -1246,6 +1247,39 @@ void
cogl_framebuffer_finish (CoglFramebuffer *framebuffer);
/**
+ * cogl_framebuffer_read_pixels_into_bitmap:
+ * @framebuffer: A #CoglFramebuffer
+ * @x: The x position to read from
+ * @y: The y position to read from
+ * @source: Identifies which auxillary buffer you want to read
+ * (only COGL_READ_PIXELS_COLOR_BUFFER supported currently)
+ * @bitmap: The bitmap to store the results in.
+ *
+ * This reads a rectangle of pixels from the given framebuffer where
+ * position (0, 0) is the top left. The pixel at (x, y) is the first
+ * read, and a rectangle of pixels with the same size as the bitmap is
+ * read left and downwards from that point.
+ *
+ * Currently Cogl assumes that the framebuffer is in a premultiplied
+ * format so if the format of @bitmap is non-premultiplied it will
+ * convert it. To read the pixel values without any conversion you
+ * should either specify a format that doesn't use an alpha channel or
+ * use one of the formats ending in PRE.
+ *
+ * Return value: %TRUE if the read succeeded or %FALSE otherwise. The
+ * function is only likely to fail if the bitmap points to a pixel
+ * buffer and it could not be mapped.
+ * Since: 1.10
+ * Stability: unstable
+ */
+gboolean
+cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
+ int x,
+ int y,
+ CoglReadPixelsFlags source,
+ CoglBitmap *bitmap);
+
+/**
* cogl_get_draw_framebuffer:
*
* Gets the current #CoglFramebuffer as set using
diff --git a/cogl/cogl-journal-private.h b/cogl/cogl-journal-private.h
index c561a10..e3dbaa8 100644
--- a/cogl/cogl-journal-private.h
+++ b/cogl/cogl-journal-private.h
@@ -105,8 +105,7 @@ gboolean
_cogl_journal_try_read_pixel (CoglJournal *journal,
int x,
int y,
- CoglPixelFormat format,
- guint8 *pixel,
+ CoglBitmap *bitmap,
gboolean *found_intersection);
#endif /* __COGL_JOURNAL_PRIVATE_H */
diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index bec9e6d..a581129 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -1791,10 +1791,10 @@ gboolean
_cogl_journal_try_read_pixel (CoglJournal *journal,
int x,
int y,
- CoglPixelFormat format,
- guint8 *pixel,
+ CoglBitmap *bitmap,
gboolean *found_intersection)
{
+ CoglPixelFormat format;
int i;
_COGL_GET_CONTEXT (ctx, FALSE);
@@ -1810,6 +1810,8 @@ _cogl_journal_try_read_pixel (CoglJournal *journal,
if (journal->fast_read_pixel_count > 50)
return FALSE;
+ format = _cogl_bitmap_get_format (bitmap);
+
if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
format != COGL_PIXEL_FORMAT_RGBA_8888)
return FALSE;
@@ -1832,6 +1834,7 @@ _cogl_journal_try_read_pixel (CoglJournal *journal,
float *vertices = (float *)color + 1;
float poly[16];
CoglFramebuffer *framebuffer = journal->framebuffer;
+ guint8 *pixel;
entry_to_screen_polygon (framebuffer, entry, vertices, poly);
@@ -1870,11 +1873,19 @@ _cogl_journal_try_read_pixel (CoglJournal *journal,
if (color[3] != 0xff)
return FALSE;
+ pixel = _cogl_bitmap_map (bitmap,
+ COGL_BUFFER_ACCESS_WRITE,
+ COGL_BUFFER_MAP_HINT_DISCARD);
+ if (pixel == NULL)
+ return FALSE;
+
pixel[0] = color[0];
pixel[1] = color[1];
pixel[2] = color[2];
pixel[3] = color[3];
+ _cogl_bitmap_unmap (bitmap);
+
goto success;
}
diff --git a/cogl/cogl-private.h b/cogl/cogl-private.h
index 41275fe..6130c11 100644
--- a/cogl/cogl-private.h
+++ b/cogl/cogl-private.h
@@ -45,16 +45,6 @@ void
_cogl_clear (const CoglColor *color, unsigned long buffers);
void
-_cogl_read_pixels_with_rowstride (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels,
- int rowstride);
-
-void
_cogl_init (void);
void
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 38e9232..254c2ff 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -1015,6 +1015,7 @@ get_texture_bits_via_offscreen (CoglTexture *texture,
{
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
+ CoglBitmap *bitmap;
_COGL_GET_CONTEXT (ctx, FALSE);
@@ -1031,19 +1032,17 @@ get_texture_bits_via_offscreen (CoglTexture *texture,
framebuffer = COGL_FRAMEBUFFER (offscreen);
- if (!cogl_framebuffer_allocate (framebuffer, NULL))
- {
- cogl_object_unref (framebuffer);
- return FALSE;
- }
-
- cogl_push_framebuffer (framebuffer);
-
- _cogl_read_pixels_with_rowstride (x, y, width, height,
- COGL_READ_PIXELS_COLOR_BUFFER,
- dst_format, dst_bits, dst_rowstride);
-
- cogl_pop_framebuffer ();
+ bitmap = _cogl_bitmap_new_from_data (dst_bits,
+ dst_format,
+ width, height,
+ dst_rowstride,
+ NULL, /* destroy_fn */
+ NULL /* destroy_fn_data */);
+ cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
+ x, y,
+ COGL_READ_PIXELS_COLOR_BUFFER,
+ bitmap);
+ cogl_object_unref (bitmap);
cogl_object_unref (framebuffer);
diff --git a/cogl/cogl.c b/cogl/cogl.c
index dffd5f7..bfd7ab5 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -369,189 +369,6 @@ cogl_flush (void)
}
void
-_cogl_read_pixels_with_rowstride (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels,
- int rowstride)
-{
- CoglFramebuffer *framebuffer = _cogl_get_read_framebuffer ();
- int framebuffer_height;
- int bpp;
- CoglBitmap *bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- CoglPixelFormat bmp_format;
- gboolean pack_invert_set;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _COGL_RETURN_IF_FAIL (source == COGL_READ_PIXELS_COLOR_BUFFER);
-
- if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty)
- {
- /* If everything drawn so far for this frame is still in the
- * Journal then if all of the rectangles only have a flat
- * opaque color we have a fast-path for reading a single pixel
- * that avoids the relatively high cost of flushing primitives
- * to be drawn on the GPU (considering how simple the geometry
- * is in this case) and then blocking on the long GPU pipelines
- * for the result.
- */
- if (_cogl_framebuffer_try_fast_read_pixel (framebuffer,
- x, y, source, format,
- pixels))
- return;
- }
-
- /* make sure any batched primitives get emitted to the GL driver
- * before issuing our read pixels...
- *
- * XXX: Note we currently use cogl_flush to ensure *all* journals
- * are flushed here and not _cogl_journal_flush because we don't
- * track the dependencies between framebuffers so we don't know if
- * the current framebuffer depends on the contents of other
- * framebuffers which could also have associated journal entries.
- */
- cogl_flush ();
-
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- framebuffer,
- COGL_FRAMEBUFFER_STATE_BIND);
-
- framebuffer_height = cogl_framebuffer_get_height (framebuffer);
-
- /* The y co-ordinate should be given in OpenGL's coordinate system
- * so 0 is the bottom row
- *
- * NB: all offscreen rendering is done upside down so no conversion
- * is necissary in this case.
- */
- if (!cogl_is_offscreen (framebuffer))
- y = framebuffer_height - y - height;
-
- /* Initialise the CoglBitmap */
- bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
- bmp_format = format;
-
- if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (format & COGL_A_BIT))
- {
- /* We match the premultiplied state of the target buffer to the
- * premultiplied state of the framebuffer so that it will get
- * converted to the right format below */
-
- if ((framebuffer->format & COGL_PREMULT_BIT))
- bmp_format |= COGL_PREMULT_BIT;
- else
- bmp_format &= ~COGL_PREMULT_BIT;
- }
-
- bmp = _cogl_bitmap_new_from_data (pixels,
- bmp_format, width, height, rowstride,
- NULL, NULL);
-
- ctx->texture_driver->pixel_format_to_gl (format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- /* NB: All offscreen rendering is done upside down so there is no need
- * to flip in this case... */
- if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
- !cogl_is_offscreen (framebuffer))
- {
- GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE));
- pack_invert_set = TRUE;
- }
- else
- pack_invert_set = FALSE;
-
- /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
- implementation specific format under
- GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and
- GL_IMPLEMENTATION_COLOR_READ_TYPE_OES is supported. We could try
- to be more clever and check if the requested type matches that
- but we would need some reliable functions to convert from GL
- types to Cogl types. For now, lets just always read in
- GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
- to use this intermediate buffer if the rowstride has padding
- because GLES does not support setting GL_ROW_LENGTH */
- if (ctx->driver != COGL_DRIVER_GL &&
- (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
- rowstride != 4 * width))
- {
- CoglBitmap *tmp_bmp;
- guint8 *tmp_data = g_malloc (width * height * 4);
-
- tmp_bmp = _cogl_bitmap_new_from_data (tmp_data,
- COGL_PIXEL_FORMAT_RGBA_8888 |
- (bmp_format & COGL_PREMULT_BIT),
- width, height, 4 * width,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- ctx->texture_driver->prep_gl_for_pixels_download (4 * width, 4);
-
- GE( ctx, glReadPixels (x, y, width, height,
- GL_RGBA, GL_UNSIGNED_BYTE,
- tmp_data) );
-
- if (!_cogl_bitmap_convert_into_bitmap (tmp_bmp, bmp))
- {
- /* FIXME: there's no way to report an error here so we'll
- just have to leave the data initialised */
- }
-
- cogl_object_unref (tmp_bmp);
- }
- else
- {
- ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);
-
- GE( ctx, glReadPixels (x, y, width, height, gl_format, gl_type, pixels) );
-
- /* Convert to the premult format specified by the caller
- in-place. This will do nothing if the premult status is already
- correct. */
- _cogl_bitmap_convert_premult_status (bmp, format);
- }
-
- /* Currently this function owns the pack_invert state and we don't want this
- * to interfere with other Cogl components so all other code can assume that
- * we leave the pack_invert state off. */
- if (pack_invert_set)
- GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, FALSE));
-
- /* NB: All offscreen rendering is done upside down so there is no need
- * to flip in this case... */
- if (!cogl_is_offscreen (framebuffer) && !pack_invert_set)
- {
- guint8 *temprow = g_alloca (rowstride * sizeof (guint8));
-
- /* vertically flip the buffer in-place */
- for (y = 0; y < height / 2; y++)
- {
- if (y != height - y - 1) /* skip center row */
- {
- memcpy (temprow,
- pixels + y * rowstride, rowstride);
- memcpy (pixels + y * rowstride,
- pixels + (height - y - 1) * rowstride, rowstride);
- memcpy (pixels + (height - y - 1) * rowstride,
- temprow,
- rowstride);
- }
- }
- }
-
- cogl_object_unref (bmp);
-}
-
-void
cogl_read_pixels (int x,
int y,
int width,
@@ -561,10 +378,19 @@ cogl_read_pixels (int x,
guint8 *pixels)
{
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
- _cogl_read_pixels_with_rowstride (x, y, width, height,
- source, format, pixels,
- /* rowstride */
- bpp * width);
+ CoglBitmap *bitmap;
+
+ bitmap = _cogl_bitmap_new_from_data (pixels,
+ format,
+ width, height,
+ bpp * width, /* rowstride */
+ NULL, /* destroy_fn */
+ NULL /* destroy_fn_data */);
+ cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (),
+ x, y,
+ source,
+ bitmap);
+ cogl_object_unref (bitmap);
}
void
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index 787e7d5..1cb8ae7 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -406,6 +406,7 @@ cogl_framebuffer_set_point_samples_per_pixel
cogl_framebuffer_get_context
cogl_framebuffer_clear
cogl_framebuffer_clear4f
+cogl_framebuffer_read_pixels_into_bitmap
<SUBSECTION>
cogl_framebuffer_draw_primitive
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]