diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2013-03-25 21:32:48 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-05-20 21:28:39 -0400 |
commit | b0a19671c2329019fc03e8581bf9fbe6c3fbd8de (patch) | |
tree | dd7dd7b6a8d98506ed54a7f2afa4250cda6b4eb5 | |
parent | a496133d5a2c80b087a7de29a4b75df312e3fd30 (diff) |
renderer: Add new read_surface_pixels vfunc
This vfunc lets us read out a rectangle of pixels from the currently
attached surface buffer.
-rw-r--r-- | src/compositor.h | 3 | ||||
-rw-r--r-- | src/gl-renderer.c | 50 |
2 files changed, 53 insertions, 0 deletions
diff --git a/src/compositor.h b/src/compositor.h index c32ced1b..ee516265 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -474,6 +474,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); diff --git a/src/gl-renderer.c b/src/gl-renderer.c index be74eba3..4734ee40 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -89,6 +89,8 @@ struct gl_renderer { struct wl_array indices; /* only used in compositor-wayland */ struct wl_array vtxcnt; + GLuint fbo; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; PFNEGLCREATEIMAGEKHRPROC create_image; PFNEGLDESTROYIMAGEKHRPROC destroy_image; @@ -1104,6 +1106,50 @@ gl_renderer_read_pixels(struct weston_output *output, return 0; } +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 wl_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; + + switch (format) { + case PIXMAN_a8r8g8b8: + gl_format = GL_BGRA_EXT; + break; + case PIXMAN_a8b8g8r8: + gl_format = GL_RGBA; + break; + default: + return -1; + } + + if (buffer && wl_buffer_is_shm(buffer)) { + size = buffer->width * 4 * buffer->height; + memcpy(pixels, wl_shm_buffer_get_data(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 gl_renderer_flush_damage(struct weston_surface *surface) { @@ -1328,6 +1374,9 @@ gl_renderer_destroy_surface(struct weston_surface *surface) struct gl_renderer *gr = get_renderer(surface->compositor); int i; + if (gr->fbo) + glDeleteFramebuffers(1, &gr->fbo); + glDeleteTextures(gs->num_textures, gs->textures); for (i = 0; i < gs->num_images; i++) @@ -1812,6 +1861,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display, 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; |