From: Pekka Paalanen <[email protected]> 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 <[email protected]> --- 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 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
