compositor: Add a renderer function to read out pixels
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Tue, 13 Nov 2012 18:10:21 +0000 (19:10 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 13 Nov 2012 22:00:06 +0000 (17:00 -0500)
src/compositor.h
src/gles2-renderer.c
src/noop-renderer.c

index e4ba19c..e2dbd0d 100644 (file)
@@ -276,6 +276,10 @@ struct weston_plane {
 };
 
 struct weston_renderer {
+       int (*read_pixels)(struct weston_output *output,
+                              pixman_format_code_t format, void *pixels,
+                              uint32_t x, uint32_t y,
+                              uint32_t width, uint32_t height);
        void (*repaint_output)(struct weston_output *output,
                               pixman_region32_t *output_damage);
        void (*flush_damage)(struct weston_surface *surface);
index 818a1a3..27c23eb 100644 (file)
@@ -608,6 +608,29 @@ repaint_region(struct weston_surface *es, pixman_region32_t *region,
        ec->vtxcnt.size = 0;
 }
 
+static int
+use_output(struct weston_output *output)
+{
+       static int errored;
+       struct gles2_output_state *go = get_output_state(output);
+       struct gles2_renderer *gr = get_renderer(output->compositor);
+       EGLBoolean ret;
+
+       ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
+                            go->egl_surface, gr->egl_context);
+
+       if (ret == EGL_FALSE) {
+               if (errored)
+                       return -1;
+               errored = 1;
+               weston_log("Failed to make EGL context current.\n");
+               print_egl_error_state();
+               return -1;
+       }
+
+       return 0;
+}
+
 static void
 weston_compositor_use_shader(struct weston_compositor *compositor,
                             struct weston_shader *shader)
@@ -863,16 +886,8 @@ gles2_renderer_repaint_output(struct weston_output *output,
 
        glViewport(0, 0, width, height);
 
-       ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
-                            go->egl_surface, gr->egl_context);
-       if (ret == EGL_FALSE) {
-               if (errored)
-                       return;
-               errored = 1;
-               weston_log("Failed to make EGL context current.\n");
-               print_egl_error_state();
+       if (use_output(output) < 0)
                return;
-       }
 
        /* if debugging, redraw everything outside the damage to clean up
         * debug lines from the previous draw on this buffer:
@@ -914,6 +929,35 @@ gles2_renderer_repaint_output(struct weston_output *output,
 
 }
 
+static int
+gles2_renderer_read_pixels(struct weston_output *output,
+                              pixman_format_code_t format, void *pixels,
+                              uint32_t x, uint32_t y,
+                              uint32_t width, uint32_t height)
+{
+       GLenum gl_format;
+
+       switch (format) {
+       case PIXMAN_a8r8g8b8:
+               gl_format = GL_BGRA_EXT;
+               break;
+       case PIXMAN_a8b8g8r8:
+               gl_format = GL_RGBA;
+               break;
+       default:
+               return -1;
+       }
+
+       if (use_output(output) < 0)
+               return -1;
+
+       glPixelStorei(GL_PACK_ALIGNMENT, 1);
+       glReadPixels(x, y, width, height, gl_format,
+                    GL_UNSIGNED_BYTE, pixels);
+
+       return 0;
+}
+
 static void
 gles2_renderer_flush_damage(struct weston_surface *surface)
 {
@@ -1552,6 +1596,7 @@ gles2_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display
        if (gr == NULL)
                return -1;
 
+       gr->base.read_pixels = gles2_renderer_read_pixels;
        gr->base.repaint_output = gles2_renderer_repaint_output;
        gr->base.flush_damage = gles2_renderer_flush_damage;
        gr->base.attach = gles2_renderer_attach;
index 116fc00..76f1e8f 100644 (file)
 
 #include "compositor.h"
 
+static int
+noop_renderer_read_pixels(struct weston_output *output,
+                              pixman_format_code_t format, void *pixels,
+                              uint32_t x, uint32_t y,
+                              uint32_t width, uint32_t height)
+{
+       return 0;
+}
+
 static void
 noop_renderer_repaint_output(struct weston_output *output,
                             pixman_region32_t *output_damage)
@@ -64,6 +73,7 @@ noop_renderer_init(struct weston_compositor *ec)
        if (renderer == NULL)
                return -1;
 
+       renderer->read_pixels = noop_renderer_read_pixels;
        renderer->repaint_output = noop_renderer_repaint_output;
        renderer->flush_damage = noop_renderer_flush_damage;
        renderer->attach = noop_renderer_attach;