This vfunc lets us read out a rectangle of pixels from the currently attached surface...
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 29 Jan 2014 06:55:09 +0000 (15:55 +0900)
committerBoram Park <boram1288.park@samsung.com>
Fri, 6 Nov 2015 05:06:48 +0000 (14:06 +0900)
Change-Id: Ia12d01fd0d157654602a2c46dd5874218252dd2f

src/compositor.h
src/gl-renderer.c

index 451ca5d90539d883bfe31f6f26d2d48dc0cead75..22ab9e12870177df46c6d9d4bfa6dc0623feb82d 100644 (file)
@@ -573,6 +573,9 @@ struct weston_renderer {
                               pixman_format_code_t format, void *pixels,
                               uint32_t x, uint32_t y,
                               uint32_t width, uint32_t height);
+       int (*read_surface_pixels)(struct weston_surface *es,
+                                  pixman_format_code_t format, void *pixels,
+                                  int x, int y, int width, int height);
        void (*repaint_output)(struct weston_output *output,
                               pixman_region32_t *output_damage);
        void (*flush_damage)(struct weston_surface *surface);
index d18e1245b0e55b8fb07f15e87bc41bf7a97cef9d..42859107196ea16ba5f1401f8144c57663094adf 100644 (file)
@@ -128,6 +128,8 @@ struct gl_renderer {
        EGLContext egl_context;
        EGLConfig egl_config;
 
+       GLuint fbo;
+
        struct wl_array vertices;
        struct wl_array vtxcnt;
 
@@ -693,6 +695,54 @@ out:
        pixman_region32_fini(&repaint);
 }
 
+static int
+gl_renderer_read_surface_pixels(struct weston_surface *es,
+                               pixman_format_code_t format, void *pixels,
+                               int x, int y, int width, int height)
+{
+       struct weston_buffer *buffer = es->buffer_ref.buffer;
+       struct weston_compositor *ec = es->compositor;
+       struct gl_renderer *gr = get_renderer(ec);
+       struct gl_surface_state *gs = get_surface_state(es);
+       GLenum gl_format;
+       int size;
+       struct wl_shm_buffer *shm_buffer = NULL;
+
+       switch (format) {
+       case PIXMAN_a8r8g8b8:
+               gl_format = GL_BGRA_EXT;
+               break;
+       case PIXMAN_a8b8g8r8:
+               gl_format = GL_RGBA;
+               break;
+       default:
+               return -1;
+       }
+
+        if (buffer) {
+               shm_buffer = wl_shm_buffer_get(buffer->resource);
+       }
+       if (shm_buffer) {
+               size = buffer->width * 4 * buffer->height;
+               memcpy(pixels, wl_shm_buffer_get_data(shm_buffer), size);
+       } else {
+               if (gr->fbo == 0)
+                       glGenFramebuffers(1, &gr->fbo);
+               glBindFramebuffer(GL_FRAMEBUFFER, gr->fbo);
+               glFramebufferTexture2D(GL_FRAMEBUFFER,
+                                      GL_COLOR_ATTACHMENT0,
+                                      GL_TEXTURE_2D,
+                                      gs->textures[0], 0);
+
+               glReadPixels(x, y, width, height,
+                            gl_format, GL_UNSIGNED_BYTE, pixels);
+
+               glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       }
+
+       return 0;
+}
+
 static void
 repaint_views(struct weston_output *output, pixman_region32_t *damage)
 {
@@ -2100,6 +2150,9 @@ gl_renderer_destroy(struct weston_compositor *ec)
 
        wl_signal_emit(&gr->destroy_signal, gr);
 
+       if (gr->fbo)
+               glDeleteFramebuffers(1, &gr->fbo);
+
        if (gr->has_bind_display)
                gr->unbind_display(gr->egl_display, ec->wl_display);
 
@@ -2314,6 +2367,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLenum platform,
                return -1;
 
        gr->base.read_pixels = gl_renderer_read_pixels;
+       gr->base.read_surface_pixels = gl_renderer_read_surface_pixels;
        gr->base.repaint_output = gl_renderer_repaint_output;
        gr->base.flush_damage = gl_renderer_flush_damage;
        gr->base.attach = gl_renderer_attach;