diff --git a/cogl.h.in b/cogl.h.in index c1cc10f29..adc329288 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -691,6 +691,39 @@ void cogl_push_draw_buffer (void); */ void cogl_pop_draw_buffer (void); +/** + * CoglReadPixelsFlags: + * @COGL_READ_PIXELS_COLOR_BUFFER: Read from the color buffer + */ +typedef enum _CoglReadPixelsFlags +{ + COGL_READ_PIXELS_COLOR_BUFFER = 1L<<0 +} CoglReadPixelsFlags; + +/** + * cogl_read_pixels: + * @x: The window x position to start reading from + * @y: The window y position to start reading from + * @width: The width of the rectangle you want to read + * @height: The height of the rectangle you want to read + * @source: Identifies which auxillary buffer you want to read + * (only COGL_READ_PIXELS_COLOR_BUFFER supported currently) + * @format: The pixel format you want the result in + * (only COGL_PIXEL_FORMAT_RGBA_8888 supported currently) + * @pixels: The location to write the pixel data. + * + * This reads a rectangle of pixels from the current draw buffer where + * position (0, 0) is the top left. The pixel at (x, y) is the first + * read, and the data is returned with a rowstride of (width * 4) + */ +void cogl_read_pixels (int x, + int y, + int width, + int height, + CoglReadPixelsFlags source, + CoglPixelFormat format, + guint8 *pixels); + /* * Internal API available only to Clutter. diff --git a/common/cogl.c b/common/cogl.c index 5857db2d3..d06d8ddd9 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -572,6 +572,8 @@ void cogl_get_viewport (float v[4]) { /* FIXME: cogl_get_viewport should return a gint vec */ + /* FIXME: cogl_get_viewport should only return a width + height + * (I don't think we need to support offset viewports) */ #if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES) GLint viewport[4]; int i; @@ -676,3 +678,57 @@ cogl_flush_gl_state (int flags) } #endif +void +cogl_read_pixels (int x, + int y, + int width, + int height, + CoglReadPixelsFlags source, + CoglPixelFormat format, + guint8 *pixels) +{ + GLint viewport[4]; + GLint viewport_height; + int rowstride = width * 4; + guint8 temprow[rowstride]; + + g_return_if_fail (format == COGL_PIXEL_FORMAT_RGBA_8888); + g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER); + + glGetIntegerv (GL_VIEWPORT, viewport); + viewport_height = viewport[3]; + + /* The y co-ordinate should be given in OpenGL's coordinate system + so 0 is the bottom row */ + y = viewport_height - y - height; + + /* Setup the pixel store parameters that may have been changed by + Cogl */ + glPixelStorei (GL_PACK_ALIGNMENT, 4); +#ifdef HAVE_COGL_GL + glPixelStorei (GL_PACK_ROW_LENGTH, 0); + glPixelStorei (GL_PACK_SKIP_PIXELS, 0); + glPixelStorei (GL_PACK_SKIP_ROWS, 0); +#endif /* HAVE_COGL_GL */ + + glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + /* TODO: consider using the GL_MESA_pack_invert extension in the future + * to avoid this flip... */ + + /* 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); + } + } +} + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 623aa3e92..c28ab52f6 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -68,6 +68,10 @@ cogl_set_source_color4ub cogl_set_source_color4f cogl_set_source_texture + +CoglReadPixelsFlags +cogl_read_pixels + COGL_TYPE_ATTRIBUTE_TYPE COGL_TYPE_BUFFER_BIT