[PATCH weston 4/7] surface-screenshot: a new manual test module
Pekka Paalanen
ppaalanen at gmail.com
Fri Feb 13 02:02:22 PST 2015
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Add a new Weston plugin under tests/ for manual testing of the
surface-shooting API.
The debug key binding 'h' triggers a surface shot from the surface that
currently has the pointer focus. The shot is written in PAM format into
a file. PAM format was chosen because it is dead-simple to write from
scratch and can carry an RGBA format.
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
Makefile.am | 17 ++++
tests/surface-screenshot.c | 207 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 224 insertions(+)
create mode 100644 tests/surface-screenshot.c
diff --git a/Makefile.am b/Makefile.am
index b391617..2caf6cd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1101,6 +1101,23 @@ EXTRA_DIST += \
protocol/ivi-application.xml \
protocol/ivi-hmi-controller.xml
+#
+# manual test modules in tests subdirectory
+#
+
+noinst_LTLIBRARIES += \
+ surface-screenshot.la
+
+surface_screenshot_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la
+surface_screenshot_la_LDFLAGS = $(test_module_ldflags)
+surface_screenshot_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
+surface_screenshot_la_SOURCES = tests/surface-screenshot.c
+
+
+#
+# Documentation
+#
+
man_MANS = weston.1 weston.ini.5
if ENABLE_DRM_COMPOSITOR
diff --git a/tests/surface-screenshot.c b/tests/surface-screenshot.c
new file mode 100644
index 0000000..901a3f6
--- /dev/null
+++ b/tests/surface-screenshot.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright © 2015 Collabora, Ltd.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/input.h>
+
+#include "compositor.h"
+#include "file-util.h"
+
+/*
+ * PAM image format:
+ * http://en.wikipedia.org/wiki/Netpbm#PAM_graphics_format
+ * RGBA is in byte address order.
+ *
+ * ImageMagick 'convert' can convert a PAM image to a more common format.
+ * To view the image metadata: $ head -n7 image.pam
+ */
+static int
+write_PAM_image_rgba(FILE *fp, int width, int height,
+ void *pixels, size_t size, const char *comment)
+{
+ assert(size == (size_t)4 * width * height);
+
+ fprintf(fp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
+ "TUPLTYPE RGB_ALPHA\n", width, height);
+
+ if (comment) {
+ size_t len = strlen(comment);
+ char *str = malloc(len + 3);
+ char *dst = str;
+ const char *src = comment;
+ const char *end = src + len;
+
+ *dst++ = '#';
+ *dst++ = ' ';
+ for (; src < end; src++, dst++) {
+ if (*src == '\n' || !isprint(*src))
+ *dst = '_';
+ else
+ *dst = *src;
+ }
+ *dst++ = '\n';
+
+ if (fwrite(str, 1, len + 3, fp) != len + 3)
+ return -1;
+ }
+
+ fprintf(fp, "ENDHDR\n");
+
+ if (fwrite(pixels, 1, size, fp) != size)
+ return -1;
+
+ if (ferror(fp))
+ return -1;
+
+ return 0;
+}
+
+static uint32_t
+unmult(uint32_t c, uint32_t a)
+{
+ return (c * 255 + a / 2) / a;
+}
+
+static void
+unpremultiply_and_swap(void *pixels, size_t size,
+ pixman_format_code_t in_format)
+{
+ uint32_t *p = pixels;
+ uint32_t *end;
+
+ assert(in_format == PIXMAN_a8b8g8r8);
+
+ for (end = p + size / 4; p < end; p++) {
+ uint32_t v = *p;
+ uint32_t a;
+
+ a = (v & 0xff000000) >> 24;
+ if (a == 0) {
+ *p = 0;
+ } else {
+ uint8_t *dst = (uint8_t *)p;
+
+ dst[0] = unmult((v & 0x000000ff) >> 0, a);
+ dst[1] = unmult((v & 0x0000ff00) >> 8, a);
+ dst[2] = unmult((v & 0x00ff0000) >> 16, a);
+ dst[3] = a;
+ }
+ }
+}
+
+static void
+trigger_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
+ void *data)
+{
+ const char *prefix = "surfaceshot-";
+ const char *suffix = ".pam";
+ char fname[1024];
+ const pixman_format_code_t format = PIXMAN_a8b8g8r8;
+ struct weston_surface *surface;
+ int width, height;
+ char desc[512];
+ void *pixels;
+ size_t stride;
+ size_t sz;
+ int ret;
+ FILE *fp;
+
+ if (seat->pointer_device_count == 0 ||
+ !seat->pointer ||
+ !seat->pointer->focus)
+ return;
+
+ surface = seat->pointer->focus->surface;
+
+ weston_surface_get_content_size(surface, &width, &height);
+
+ if (!surface->get_label ||
+ surface->get_label(surface, desc, sizeof(desc)) < 0)
+ snprintf(desc, sizeof(desc), "(unknown)");
+
+ weston_log("surface screenshot of %p: '%s', %dx%d\n",
+ surface, desc, width, height);
+
+ stride = width * 4;
+ sz = stride * height;
+ if (sz == 0) {
+ weston_log("no content for %p\n", surface);
+ return;
+ }
+
+ pixels = malloc(sz);
+ if (!pixels) {
+ weston_log("%s: failed to malloc %zu B\n", __func__, sz);
+ return;
+ }
+
+ ret = weston_surface_copy_content(surface, pixels, stride, sz,
+ 0, 0, width, height, format);
+ if (ret < 0) {
+ weston_log("shooting surface %p failed\n", surface);
+ goto out;
+ }
+
+ unpremultiply_and_swap(pixels, sz, format);
+
+ fp = file_create_dated(prefix, suffix, fname, sizeof(fname));
+ if (!fp) {
+ const char *msg;
+
+ switch (errno) {
+ case ETIME:
+ msg = "failure in datetime formatting";
+ break;
+ default:
+ msg = strerror(errno);
+ }
+
+ weston_log("Cannot open '%s*%s' for writing: %s\n",
+ prefix, suffix, msg);
+ goto out;
+ }
+
+ ret = write_PAM_image_rgba(fp, width, height, pixels, sz, desc);
+ if (fclose(fp) != 0 || ret < 0)
+ weston_log("writing surface %p screenshot failed.\n", surface);
+ else
+ weston_log("successfully shot surface %p into '%s'\n",
+ surface, fname);
+
+out:
+ free(pixels);
+}
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ weston_compositor_add_debug_binding(ec, KEY_H, trigger_binding, ec);
+
+ return 0;
+}
--
2.0.5
More information about the wayland-devel
mailing list