[PATCH v5 04/11] compositor: Add a renderer function to read out pixels and remove the GL calls from screenshooter.

John Kåre Alsaker john.kare.alsaker at gmail.com
Fri Nov 9 12:21:13 PST 2012


---
 src/compositor.h     |  6 ++++-
 src/gles2-renderer.c | 67 +++++++++++++++++++++++++++++++++++++++++++---------
 src/noop-renderer.c  | 10 ++++++++
 src/screenshooter.c  | 27 +++++++++++----------
 4 files changed, 86 insertions(+), 24 deletions(-)

diff --git a/src/compositor.h b/src/compositor.h
index 93dae28..0992231 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -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);
@@ -349,7 +353,7 @@ struct weston_compositor {
 	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
 
 	int has_unpack_subimage;
-	GLenum read_format;
+	pixman_format_code_t read_format;
 
 	PFNEGLBINDWAYLANDDISPLAYWL bind_display;
 	PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
index fb1d616..8fb4f21 100644
--- a/src/gles2-renderer.c
+++ b/src/gles2-renderer.c
@@ -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)
 {
@@ -1559,6 +1603,7 @@ gles2_renderer_init(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;
@@ -1713,9 +1758,9 @@ gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	}
 
 	if (strstr(extensions, "GL_EXT_read_format_bgra"))
-		ec->read_format = GL_BGRA_EXT;
+		ec->read_format = PIXMAN_a8r8g8b8;
 	else
-		ec->read_format = GL_RGBA;
+		ec->read_format = PIXMAN_a8b8g8r8;
 
 	if (strstr(extensions, "GL_EXT_unpack_subimage"))
 		ec->has_unpack_subimage = 1;
diff --git a/src/noop-renderer.c b/src/noop-renderer.c
index 116fc00..76f1e8f 100644
--- a/src/noop-renderer.c
+++ b/src/noop-renderer.c
@@ -26,6 +26,15 @@
 
 #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;
diff --git a/src/screenshooter.c b/src/screenshooter.c
index ffcc970..23181a2 100644
--- a/src/screenshooter.c
+++ b/src/screenshooter.c
@@ -112,10 +112,10 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
 		return;
 	}
 
-	glPixelStorei(GL_PACK_ALIGNMENT, 1);
-	glReadPixels(0, 0, output->current->width, output->current->height,
-		     output->compositor->read_format,
-		     GL_UNSIGNED_BYTE, pixels);
+	output->compositor->renderer->read_pixels(output,
+			     output->compositor->read_format, pixels,
+			     0, 0, output->current->width,
+			     output->current->height);
 
 	stride = wl_shm_buffer_get_stride(l->buffer);
 
@@ -123,10 +123,10 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
 	s = pixels + stride * (l->buffer->height - 1);
 
 	switch (output->compositor->read_format) {
-	case GL_BGRA_EXT:
+	case PIXMAN_a8r8g8b8:
 		copy_bgra_yflip(d, s, output->current->height, stride);
 		break;
-	case GL_RGBA:
+	case PIXMAN_a8b8g8r8:
 		copy_rgba_yflip(d, s, output->current->height, stride);
 		break;
 	default:
@@ -299,10 +299,10 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
 	for (i = 0; i < n; i++) {
 		width = r[i].x2 - r[i].x1;
 		height = r[i].y2 - r[i].y1;
-		glReadPixels(r[i].x1, output->current->height - r[i].y2,
-			     width, height,
-			     output->compositor->read_format,
-			     GL_UNSIGNED_BYTE, recorder->rect);
+		output->compositor->renderer->read_pixels(output,
+			     output->compositor->read_format, recorder->rect,
+			     r[i].x1, output->current->height - r[i].y2,
+			     width, height);
 
 		s = recorder->rect;
 		p = recorder->rect;
@@ -367,12 +367,15 @@ weston_recorder_create(struct weston_output *output, const char *filename)
 	header.magic = WCAP_HEADER_MAGIC;
 
 	switch (output->compositor->read_format) {
-	case GL_BGRA_EXT:
+	case PIXMAN_a8r8g8b8:
 		header.format = WCAP_FORMAT_XRGB8888;
 		break;
-	case GL_RGBA:
+	case PIXMAN_a8b8g8r8:
 		header.format = WCAP_FORMAT_XBGR8888;
 		break;
+	default:
+		weston_log("unknown recorder format\n");
+		break;
 	}
 
 	header.width = output->current->width;
-- 
1.8.0



More information about the wayland-devel mailing list