Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=83981
Signed-off-by: Bryce Harrington <br...@osg.samsung.com>
---
 Makefile.am         |   4 +-
 tests/weston-test.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 245 insertions(+), 3 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index fb3152e..023b7e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -995,7 +995,7 @@ noinst_PROGRAMS +=                  \
        matrix-test
 
 test_module_ldflags = \
-       -module -avoid-version -rpath $(libdir) $(COMPOSITOR_LIBS)
+       -module -avoid-version -rpath $(libdir) $(COMPOSITOR_LIBS) $(CAIRO_LIBS)
 
 surface_global_test_la_SOURCES = tests/surface-global-test.c
 surface_global_test_la_LDFLAGS = $(test_module_ldflags)
@@ -1007,7 +1007,7 @@ surface_test_la_CFLAGS = $(GCC_CFLAGS) 
$(COMPOSITOR_CFLAGS)
 
 weston_test_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
 weston_test_la_LDFLAGS = $(test_module_ldflags)
-weston_test_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
+weston_test_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(CAIRO_CFLAGS)
 weston_test_la_SOURCES = tests/weston-test.c
 nodist_weston_test_la_SOURCES =                        \
        protocol/weston-test-protocol.c \
diff --git a/tests/weston-test.c b/tests/weston-test.c
index 9f1f49b..1d6d264 100644
--- a/tests/weston-test.c
+++ b/tests/weston-test.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <string.h>
+#include <cairo.h>
 
 #include "../src/compositor.h"
 #include "weston-test-server-protocol.h"
@@ -269,6 +270,247 @@ get_n_buffers(struct wl_client *client, struct 
wl_resource *resource)
        weston_test_send_n_egl_buffers(resource, n_buffers);
 }
 
+enum weston_test_screenshot_outcome {
+       WESTON_TEST_SCREENSHOT_SUCCESS,
+       WESTON_TEST_SCREENSHOT_NO_MEMORY,
+       WESTON_TEST_SCREENSHOT_BAD_BUFFER
+       };
+
+typedef void (*weston_test_screenshot_done_func_t)(void *data,
+                                                  enum 
weston_test_screenshot_outcome outcome);
+
+struct test_screenshot {
+       struct weston_compositor *ec;
+       struct wl_global *global;
+       struct wl_client *client;
+       struct weston_process process;
+       struct wl_listener destroy_listener;
+};
+
+struct test_screenshot_frame_listener {
+       struct wl_listener listener;
+       struct weston_buffer *buffer;
+       weston_test_screenshot_done_func_t done;
+       void *data;
+};
+
+static void
+copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
+{
+       uint8_t *end;
+
+       end = dst + height * stride;
+       while (dst < end) {
+               memcpy(dst, src, stride);
+               dst += stride;
+               src -= stride;
+       }
+}
+
+
+static void
+copy_bgra(uint8_t *dst, uint8_t *src, int height, int stride)
+{
+       /* TODO: optimize this out */
+       memcpy(dst, src, height * stride);
+}
+
+static void
+copy_row_swap_RB(void *vdst, void *vsrc, int bytes)
+{
+       uint32_t *dst = vdst;
+       uint32_t *src = vsrc;
+       uint32_t *end = dst + bytes / 4;
+
+       while (dst < end) {
+               uint32_t v = *src++;
+               /*                    A R G B */
+               uint32_t tmp = v & 0xff00ff00;
+               tmp |= (v >> 16) & 0x000000ff;
+               tmp |= (v << 16) & 0x00ff0000;
+               *dst++ = tmp;
+       }
+}
+
+static void
+copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
+{
+       uint8_t *end;
+
+       end = dst + height * stride;
+       while (dst < end) {
+               copy_row_swap_RB(dst, src, stride);
+               dst += stride;
+               src -= stride;
+       }
+}
+
+static void
+copy_rgba(uint8_t *dst, uint8_t *src, int height, int stride)
+{
+       uint8_t *end;
+
+       end = dst + height * stride;
+       while (dst < end) {
+               copy_row_swap_RB(dst, src, stride);
+               dst += stride;
+               src += stride;
+       }
+}
+
+static void
+test_screenshot_frame_notify(struct wl_listener *listener, void *data)
+{
+       struct test_screenshot_frame_listener *l =
+               container_of(listener,
+                            struct test_screenshot_frame_listener, listener);
+       struct weston_output *output = data;
+       struct weston_compositor *compositor = output->compositor;
+       int32_t stride;
+       uint8_t *pixels, *d, *s;
+
+       output->disable_planes--;
+       wl_list_remove(&listener->link);
+       stride = l->buffer->width * (PIXMAN_FORMAT_BPP(compositor->read_format) 
/ 8);
+       pixels = malloc(stride * l->buffer->height);
+
+       if (pixels == NULL) {
+               l->done(l->data, WESTON_TEST_SCREENSHOT_NO_MEMORY);
+               free(l);
+               return;
+       }
+
+       // FIXME: Needs to handle output transformations
+
+       compositor->renderer->read_pixels(output,
+                                         compositor->read_format,
+                                         pixels,
+                                         0, 0,
+                                         output->current_mode->width,
+                                         output->current_mode->height);
+
+       stride = wl_shm_buffer_get_stride(l->buffer->shm_buffer);
+
+       d = wl_shm_buffer_get_data(l->buffer->shm_buffer);
+       s = pixels + stride * (l->buffer->height - 1);
+
+       wl_shm_buffer_begin_access(l->buffer->shm_buffer);
+
+       switch (compositor->read_format) {
+       case PIXMAN_a8r8g8b8:
+       case PIXMAN_x8r8g8b8:
+               if (compositor->capabilities & WESTON_CAP_CAPTURE_YFLIP)
+                       copy_bgra_yflip(d, s, output->current_mode->height, 
stride);
+               else
+                       copy_bgra(d, pixels, output->current_mode->height, 
stride);
+               break;
+       case PIXMAN_x8b8g8r8:
+       case PIXMAN_a8b8g8r8:
+               if (compositor->capabilities & WESTON_CAP_CAPTURE_YFLIP)
+                       copy_rgba_yflip(d, s, output->current_mode->height, 
stride);
+               else
+                       copy_rgba(d, pixels, output->current_mode->height, 
stride);
+               break;
+       default:
+               break;
+       }
+
+       wl_shm_buffer_end_access(l->buffer->shm_buffer);
+
+       l->done(l->data, WESTON_TEST_SCREENSHOT_SUCCESS);
+       free(pixels);
+       free(l);
+}
+
+static bool
+weston_test_screenshot_shoot(struct weston_output *output,
+                            struct weston_buffer *buffer,
+                            weston_test_screenshot_done_func_t done,
+                            void *data)
+{
+       struct test_screenshot_frame_listener *l;
+
+       /* Get the shm buffer resource the client created */
+       if (!wl_shm_buffer_get(buffer->resource)) {
+               done(data, WESTON_TEST_SCREENSHOT_BAD_BUFFER);
+               return false;
+       }
+
+       buffer->shm_buffer = wl_shm_buffer_get(buffer->resource);
+       buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer);
+       buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer);
+
+       /* Verify buffer is big enough */
+       if (buffer->width < output->current_mode->width ||
+               buffer->height < output->current_mode->height) {
+               done(data, WESTON_TEST_SCREENSHOT_BAD_BUFFER);
+               return false;
+       }
+
+       /* allocate the frame listener */
+       l = malloc(sizeof *l);
+       if (l == NULL) {
+               done(data, WESTON_TEST_SCREENSHOT_NO_MEMORY);
+               return false;
+       }
+
+       /* Set up the listener */
+       l->buffer = buffer;
+       l->done = done;
+       l->data = data;
+       l->listener.notify = test_screenshot_frame_notify;
+       wl_signal_add(&output->frame_signal, &l->listener);
+
+       /* Fire off a repaint */
+       output->disable_planes++;
+       weston_output_schedule_repaint(output);
+
+       return true;
+}
+
+static void
+capture_screenshot_done(void *data, enum weston_test_screenshot_outcome 
outcome)
+{
+       struct wl_resource *resource = data;
+
+       switch (outcome) {
+       case WESTON_TEST_SCREENSHOT_SUCCESS:
+               weston_test_send_capture_screenshot_done(resource);
+               break;
+       case WESTON_TEST_SCREENSHOT_NO_MEMORY:
+               wl_resource_post_no_memory(resource);
+               break;
+       default:
+               break;
+       }
+}
+
+
+/**
+ * Grabs a snapshot of the screen.
+ */
+static void
+capture_screenshot(struct wl_client *client,
+                  struct wl_resource *resource,
+                  struct wl_resource *output_resource,
+                  struct wl_resource *buffer_resource)
+{
+//     struct weston_test *test =
+//             wl_resource_get_user_data(resource);
+       struct weston_output *output =
+               wl_resource_get_user_data(output_resource);
+       struct weston_buffer *buffer =
+               weston_buffer_from_resource(buffer_resource);
+
+       if (buffer == NULL) {
+               wl_resource_post_no_memory(resource);
+               return;
+       }
+
+       weston_test_screenshot_shoot(output, buffer,
+                                    capture_screenshot_done, resource);
+}
+
 static const struct weston_test_interface test_implementation = {
        move_surface,
        move_pointer,
@@ -278,6 +520,7 @@ static const struct weston_test_interface 
test_implementation = {
        device_release,
        device_add,
        get_n_buffers,
+       capture_screenshot,
 };
 
 static void
@@ -316,7 +559,6 @@ idle_launch_client(void *data)
                sigfillset(&allsigs);
                sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
                execl(path, path, NULL);
-               weston_log("compositor: executing '%s' failed: %m\n", path);
                exit(EXIT_FAILURE);
        }
 
-- 
1.9.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to