summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-03-25 21:32:48 -0400
committerKristian Høgsberg <krh@bitplanet.net>2013-05-20 21:28:39 -0400
commitb0a19671c2329019fc03e8581bf9fbe6c3fbd8de (patch)
treedd7dd7b6a8d98506ed54a7f2afa4250cda6b4eb5
parenta496133d5a2c80b087a7de29a4b75df312e3fd30 (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.h3
-rw-r--r--src/gl-renderer.c50
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;