summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/dimension/gl.h5
-rw-r--r--libdimension/gl.c40
2 files changed, 41 insertions, 4 deletions
diff --git a/libdimension/dimension/gl.h b/libdimension/dimension/gl.h
index e27c418..f7de782 100644
--- a/libdimension/dimension/gl.h
+++ b/libdimension/dimension/gl.h
@@ -28,10 +28,11 @@
#include <stdio.h>
-/* Write canvas to GL framebuffer. Returns 0 on success, nonzero on failure */
+/* Write canvas to GL framebuffer. Returns 0 on success, nonzero on failure. */
int dmnsn_gl_write_canvas(const dmnsn_canvas *canvas);
/* Read a canvas from a GL framebuffer. Returns NULL on failure. */
-dmnsn_canvas *dmnsn_gl_read_canvas();
+dmnsn_canvas *dmnsn_gl_read_canvas(unsigned int x0, unsigned int y0,
+ unsigned int width, unsigned int height);
#endif /* DIMENSION_GL_H */
diff --git a/libdimension/gl.c b/libdimension/gl.c
index 3542a2d..e67551b 100644
--- a/libdimension/gl.c
+++ b/libdimension/gl.c
@@ -85,7 +85,43 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas)
/* Read a canvas from a GL framebuffer. Returns NULL on failure. */
dmnsn_canvas *
-dmnsn_gl_read_canvas()
+dmnsn_gl_read_canvas(unsigned int x0, unsigned int y0,
+ unsigned int width, unsigned int height)
{
- return NULL;
+ dmnsn_canvas *canvas;
+ GLuint *pixels; /* Array of 32-bit ints in RGBA order */
+ GLuint *pixel;
+ dmnsn_sRGB sRGB;
+ dmnsn_color *color;
+ unsigned int x, y;
+
+ canvas = dmnsn_new_canvas(width, height);
+ if (!canvas) {
+ return NULL;
+ }
+
+ pixels = malloc(4*width*height*sizeof(GLuint));
+ if (!pixels) {
+ dmnsn_delete_canvas(canvas);
+ return NULL;
+ }
+
+ glReadPixels(x0, y0, width, height, GL_RGBA, GL_UNSIGNED_INT, pixels);
+
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ color = dmnsn_pixel_at(canvas, x, y);
+ pixel = pixels + 4*(y*width + x);
+
+ sRGB.R = ((double)pixel[0])/UINT32_MAX;
+ sRGB.G = ((double)pixel[1])/UINT32_MAX;
+ sRGB.B = ((double)pixel[2])/UINT32_MAX;
+
+ *color = dmnsn_color_from_sRGB(sRGB);
+ color->filter = ((double)pixel[3])/UINT32_MAX;
+ }
+ }
+
+ free(pixels);
+ return canvas;
}