diff --git a/tests/Imakefile b/tests/Imakefile
index 7194905..643bf94 100644
--- a/tests/Imakefile
+++ b/tests/Imakefile
@@ -20,6 +20,7 @@ name.c: $(12TO11ROOT)/name.xml name.h @@\
HEADER := $(HEADER) name.h @@\
ScannerTarget(12to11-test)
+ScannerTarget(viewporter)
SRCS1 = $(COMMONSRCS) simple_test.c
OBJS1 = $(COMMONOBJS) simple_test.o
@@ -27,7 +28,12 @@ ScannerTarget(12to11-test)
OBJS2 = $(COMMONOBJS) damage_test.o
SRCS3 = $(COMMONSRCS) transform_test.c
OBJS3 = $(COMMONSRCS) transform_test.o
- PROGRAMS = simple_test damage_test transform_test
+ SRCS4 = $(COMMONSRCS) viewporter_test.c
+ OBJS4 = $(COMMONSRCS) viewporter_test.o
+ /* Not actually a test. */
+ SRCS5 = $(COMMONSRCS) imgview.c
+ OBJS5 = $(COMMONSRCS) imgview.o
+ PROGRAMS = simple_test damage_test transform_test viewporter_test imgview
/* Make all objects depend on HEADER. */
$(OBJS1): $(HEADER)
@@ -38,6 +44,9 @@ depend:: $(HEADER) $(SRCS1)
NormalProgramTarget(simple_test,$(OBJS1),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
NormalProgramTarget(damage_test,$(OBJS2),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
NormalProgramTarget(transform_test,$(OBJS3),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
+NormalProgramTarget(viewporter_test,$(OBJS4),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
+NormalProgramTarget(imgview,$(OBJS5),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
DependTarget3($(SRCS1),$(SRCS2),$(SRCS3))
+DependTarget3($(SRCS4),$(SRCS5),NullParameter)
all:: $(PROGRAMS)
diff --git a/tests/README b/tests/README
index 3ba59b7..ade44f3 100644
--- a/tests/README
+++ b/tests/README
@@ -19,3 +19,6 @@ would be ``integration tests''.
Most likely, you do not want to run these tests manually, as the
`run_tests.sh' script does all the setup for you.
+
+Please note that the EGL renderer currently does not pass the
+viewporter test, which is expected behavior.
diff --git a/tests/imgview.c b/tests/imgview.c
new file mode 100644
index 0000000..9d6ef00
--- /dev/null
+++ b/tests/imgview.c
@@ -0,0 +1,203 @@
+/* Tests for the Wayland compositor running on the X server.
+
+Copyright (C) 2022 to various contributors.
+
+This file is part of 12to11.
+
+12to11 is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+12to11 is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with 12to11. If not, see . */
+
+#include
+
+#include "test_harness.h"
+
+/* imgview -- simple viewer for .dump files. It opens each file as an
+ argument and displays it in a window. */
+
+/* The display imgview is connected to. */
+static Display *display;
+
+/* The visual being used. */
+static Visual *visual;
+
+/* Various image parameters. */
+static int width, height, depth;
+
+static int
+get_depth_for_format (struct image_data_header *header)
+{
+ switch (header->format)
+ {
+ case IMAGE_DATA_ARGB8888_LE:
+ return 32;
+
+ case IMAGE_DATA_XRGB8888_LE:
+ return 24;
+ }
+
+ return 0;
+}
+
+static Visual *
+get_visual_for_format (struct image_data_header *header)
+{
+ XVisualInfo template, *visuals;
+ Visual *visual;
+ unsigned long mask;
+ int n_visuals;
+
+ /* This isn't right if the pixel layout differs, but the program
+ assumes that all 24-depth visuals are XRGB8888 and all 32-bit
+ ones are ARGB8888. */
+
+ template.screen = DefaultScreen (display);
+ template.class = TrueColor;
+
+ switch (header->format)
+ {
+ case IMAGE_DATA_ARGB8888_LE:
+ template.depth = 32;
+ break;
+
+ case IMAGE_DATA_XRGB8888_LE:
+ template.depth = 24;
+ break;
+ }
+
+ mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+ visuals = XGetVisualInfo (display, mask, &template, &n_visuals);
+
+ if (!n_visuals)
+ {
+ if (visuals)
+ XFree (visuals);
+
+ return NULL;
+ }
+
+ visual = visuals[0].visual;
+ XFree (visuals);
+ return visual;
+}
+
+static Pixmap
+get_image (const char *filename)
+{
+ unsigned char *data;
+ struct image_data_header header;
+ XImage *image;
+ Pixmap pixmap;
+ GC gc;
+
+ data = load_image_data (filename, &header);
+
+ if (!data)
+ return None;
+
+ visual = get_visual_for_format (&header);
+ depth = get_depth_for_format (&header);
+
+ if (!depth || !visual)
+ {
+ free (data);
+ return None;
+ }
+
+ image = XCreateImage (display, visual, depth, ZPixmap, 0,
+ (char *) data, header.width,
+ header.height, 8, header.stride);
+ image->data = (char *) data;
+
+ pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+ header.width, header.height, depth);
+ gc = XCreateGC (display, pixmap, 0, NULL);
+
+ /* Upload the image to the pixmap and free the GC. */
+ XPutImage (display, pixmap, gc, image, 0, 0,
+ 0, 0, header.width, header.height);
+ XFreeGC (display, gc);
+
+ /* Destroy the XImage data. */
+ free (image->data);
+ image->data = NULL;
+
+ /* Destroy the XImage. */
+ XDestroyImage (image);
+
+ /* Set image params. */
+ width = header.width;
+ height = header.height;
+ depth = depth;
+
+ return pixmap;
+}
+
+static void
+loop_for_events (void)
+{
+ XEvent event;
+
+ while (true)
+ XNextEvent (display, &event);
+}
+
+static void
+open_window (Pixmap image)
+{
+ Window window;
+ XSetWindowAttributes attrs;
+ unsigned long flags;
+
+ attrs.colormap = XCreateColormap (display,
+ DefaultRootWindow (display),
+ visual, AllocNone);
+ /* This should be valid on any TrueColor visual. */
+ attrs.border_pixel = 0;
+ attrs.background_pixmap = image;
+ attrs.cursor = None;
+ flags = (CWColormap | CWBorderPixel | CWBackPixmap | CWCursor);
+
+ window = XCreateWindow (display,
+ DefaultRootWindow (display),
+ 0, 0, width, height, 0, depth,
+ InputOutput, visual, flags,
+ &attrs);
+ XMapRaised (display, window);
+}
+
+int
+main (int argc, char **argv)
+{
+ Pixmap image;
+ int i;
+
+ if (argc < 2)
+ return 1;
+
+ display = XOpenDisplay (NULL);
+
+ if (!display)
+ return 1;
+
+ for (i = 1; i < argc; ++i)
+ {
+ image = get_image (argv[i]);
+
+ if (!image)
+ continue;
+
+ open_window (image);
+ }
+
+ loop_for_events ();
+}
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index b5c18d1..2dc4173 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -18,7 +18,7 @@
# along with 12to11. If not, see .
pushd "$(dirname $0)"
-declare -a standard_tests=( simple_test damage_test transform_test )
+declare -a standard_tests=( simple_test damage_test transform_test viewporter_test )
make -C . "${standard_tests[@]}"
diff --git a/tests/svnignore.txt b/tests/svnignore.txt
index 87e34f0..6ef7a4e 100644
--- a/tests/svnignore.txt
+++ b/tests/svnignore.txt
@@ -4,5 +4,10 @@ vgcore*
simple_test
damage_test
transform_test
+viewporter_test
+imgview
+reject.dump
Makefile
Makefile.bak
+viewporter.h
+viewporter.c
diff --git a/tests/test_harness.c b/tests/test_harness.c
index 7910bfb..f2c4177 100644
--- a/tests/test_harness.c
+++ b/tests/test_harness.c
@@ -35,32 +35,6 @@ along with 12to11. If not, see . */
#define BIG_ENDIAN_BYTE_ORDER (1 << 8)
-struct image_data_header
-{
- /* Currently 1. High bit is byte order. */
- unsigned char version;
-
- /* The data format. Currently always 0. */
- unsigned char format;
-
- /* The width and height. */
- unsigned short width, height;
-
- /* Padding. */
- unsigned short pad1;
-
- /* The stride. */
- unsigned int stride;
-};
-
-enum image_data_format
- {
- /* Little-endian ARGB8888. */
- IMAGE_DATA_ARGB8888_LE,
- /* Little-endian XRGB8888. */
- IMAGE_DATA_XRGB8888_LE,
- };
-
#if PNG_LIBPNG_VER < 10500
#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
# else
@@ -560,7 +534,7 @@ byte_order_for_format (enum image_data_format format)
/* Load image data from a file. */
-static unsigned char *
+unsigned char *
load_image_data (const char *filename, struct image_data_header *header)
{
int fd;
@@ -614,38 +588,11 @@ load_image_data (const char *filename, struct image_data_header *header)
}
static void
-compare_single_row (unsigned char *data, int row_no,
- struct image_data_header *header, XImage *image)
-{
- char *xdata;
- unsigned short bytes_per_pixel;
-
- bytes_per_pixel = bytes_per_pixel_for_format (header->format);
- data = data + header->stride * row_no;
- xdata = image->data + image->bytes_per_line * row_no;
-
- if (memcmp (data, xdata, bytes_per_pixel * header->width))
- report_test_failure ("row %d differs", row_no);
-}
-
-static void
-write_image_data (struct test_display *display, Window window,
- const char *filename)
+write_image_data_1 (XImage *image, const char *filename)
{
struct image_data_header header;
- XImage *image;
struct iovec iovecs[2];
int fd;
- XWindowAttributes attrs;
-
- test_log ("writing contents of drawable to reference %s", filename);
-
- XGetWindowAttributes (display->x_display, window, &attrs);
- image = XGetImage (display->x_display, window, 0, 0, attrs.width,
- attrs.height, ~0, ZPixmap);
-
- if (!image)
- report_test_failure ("failed to load from drawable 0x%lx", window);
memset (&header, 0, sizeof header);
header.version = 1;
@@ -685,6 +632,46 @@ write_image_data (struct test_display *display, Window window,
report_test_failure ("failed to write to output file %s", filename);
close (fd);
+}
+
+static void
+compare_single_row (unsigned char *data, int row_no,
+ struct image_data_header *header, XImage *image)
+{
+ char *xdata;
+ unsigned short bytes_per_pixel;
+
+ bytes_per_pixel = bytes_per_pixel_for_format (header->format);
+ data = data + header->stride * row_no;
+ xdata = image->data + image->bytes_per_line * row_no;
+
+ if (memcmp (data, xdata, bytes_per_pixel * header->width))
+ {
+ /* Write the reject to a file. */
+ test_log ("writing reject to reject.dump");
+ write_image_data_1 (image, "reject.dump");
+
+ report_test_failure ("row %d differs", row_no);
+ }
+}
+
+static void
+write_image_data (struct test_display *display, Window window,
+ const char *filename)
+{
+ XImage *image;
+ XWindowAttributes attrs;
+
+ test_log ("writing contents of drawable to reference %s", filename);
+
+ XGetWindowAttributes (display->x_display, window, &attrs);
+ image = XGetImage (display->x_display, window, 0, 0, attrs.width,
+ attrs.height, ~0, ZPixmap);
+
+ if (!image)
+ report_test_failure ("failed to load from drawable 0x%lx", window);
+
+ write_image_data_1 (image, filename);
XDestroyImage (image);
test_log ("image data written to %s", filename);
@@ -715,6 +702,8 @@ verify_image_data (struct test_display *display, Window window,
image = XGetImage (display->x_display, window, 0, 0, attrs.width,
attrs.height, ~0, ZPixmap);
+ test_log ("verifying image data from: %s", filename);
+
if (!image)
report_test_failure ("failed to load from drawable 0x%lx", window);
diff --git a/tests/test_harness.h b/tests/test_harness.h
index 98d201c..90d5ab4 100644
--- a/tests/test_harness.h
+++ b/tests/test_harness.h
@@ -65,12 +65,38 @@ struct test_interface
void *data;
/* Pointer to the interface. */
- struct wl_interface *c_interface;
+ const struct wl_interface *c_interface;
/* The wanted version. */
uint32_t version;
};
+struct image_data_header
+{
+ /* Currently 1. High bit is byte order. */
+ unsigned char version;
+
+ /* The data format. Currently always 0. */
+ unsigned char format;
+
+ /* The width and height. */
+ unsigned short width, height;
+
+ /* Padding. */
+ unsigned short pad1;
+
+ /* The stride. */
+ unsigned int stride;
+};
+
+enum image_data_format
+ {
+ /* Little-endian ARGB8888. */
+ IMAGE_DATA_ARGB8888_LE,
+ /* Little-endian XRGB8888. */
+ IMAGE_DATA_XRGB8888_LE,
+ };
+
extern void die (const char *) __attribute__ ((noreturn));
extern struct test_display *open_test_display (struct test_interface *, int);
extern int get_shm_file_descriptor (void);
@@ -86,6 +112,8 @@ extern void test_log (const char *, ...)
extern bool make_test_surface (struct test_display *, struct wl_surface **,
struct test_surface **);
extern struct wl_buffer *load_png_image (struct test_display *, const char *);
+extern unsigned char *load_image_data (const char *,
+ struct image_data_header *);
extern void verify_image_data (struct test_display *, Window, const char *);
extern void test_init (void);
extern void test_complete (void) __attribute__ ((noreturn));
diff --git a/tests/viewport_dest_200_150_1.dump b/tests/viewport_dest_200_150_1.dump
new file mode 100644
index 0000000..4614a50
Binary files /dev/null and b/tests/viewport_dest_200_150_1.dump differ
diff --git a/tests/viewport_dest_200_150_2.dump b/tests/viewport_dest_200_150_2.dump
new file mode 100644
index 0000000..2cd2a77
Binary files /dev/null and b/tests/viewport_dest_200_150_2.dump differ
diff --git a/tests/viewport_src_50_50_200_200_1.dump b/tests/viewport_src_50_50_200_200_1.dump
new file mode 100644
index 0000000..843bea1
Binary files /dev/null and b/tests/viewport_src_50_50_200_200_1.dump differ
diff --git a/tests/viewport_src_50_50_200_200_2.dump b/tests/viewport_src_50_50_200_200_2.dump
new file mode 100644
index 0000000..6451159
Binary files /dev/null and b/tests/viewport_src_50_50_200_200_2.dump differ
diff --git a/tests/viewport_src_50_50_200_200_dest_500_500_1.dump b/tests/viewport_src_50_50_200_200_dest_500_500_1.dump
new file mode 100644
index 0000000..b08261c
Binary files /dev/null and b/tests/viewport_src_50_50_200_200_dest_500_500_1.dump differ
diff --git a/tests/viewport_src_50_50_200_200_dest_500_500_2.dump b/tests/viewport_src_50_50_200_200_dest_500_500_2.dump
new file mode 100644
index 0000000..5747944
Binary files /dev/null and b/tests/viewport_src_50_50_200_200_dest_500_500_2.dump differ
diff --git a/tests/viewporter_test.c b/tests/viewporter_test.c
new file mode 100644
index 0000000..ad614f7
--- /dev/null
+++ b/tests/viewporter_test.c
@@ -0,0 +1,286 @@
+/* Tests for the Wayland compositor running on the X server.
+
+Copyright (C) 2022 to various contributors.
+
+This file is part of 12to11.
+
+12to11 is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+12to11 is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with 12to11. If not, see . */
+
+#include "test_harness.h"
+#include "viewporter.h"
+
+/* Tests for wp_viewporter. The relevant requests tested are:
+
+ wp_viewporter.set_source (-1, -1, -1, -1)
+ wp_viewporter.set_destination (200, 150)
+
+ wp_viewporter.set_source (50, 50, 200, 200)
+ wp_viewporter.set_destination (-1, -1)
+
+ wp_viewporter.set_source (50, 50, 200, 200)
+ wp_viewporter.set_destination (500, 500)
+
+ Each test is run in order, with both damage_buffer and damage being
+ used to compute buffer damage. */
+
+enum test_kind
+ {
+ MAP_WINDOW_KIND,
+ VIEWPORT_DEST_200_150_KIND,
+ VIEWPORT_SRC_50_50_200_200_KIND,
+ VIEWPORT_SRC_50_50_200_200_DEST_500_500_KIND,
+ };
+
+static const char *test_names[] =
+ {
+ "map_window",
+ "viewport_dest_250_150",
+ "viewport_src_50_50_200_200",
+ "viewport_src_50_50_200_200_dest_500_500",
+ };
+
+#define LAST_TEST VIEWPORT_SRC_50_50_200_200_DEST_500_500_KIND
+
+/* The display. */
+static struct test_display *display;
+
+/* The viewporter interface. */
+static struct wp_viewporter *viewporter;
+
+/* Test interfaces. */
+static struct test_interface test_interfaces[] =
+ {
+ { "wp_viewporter", &viewporter, &wp_viewporter_interface, 1, },
+ };
+
+/* The test surface window. */
+static Window test_surface_window;
+
+/* The test surface and Wayland surface. */
+static struct test_surface *test_surface;
+static struct wl_surface *wayland_surface;
+
+/* The surface viewport. */
+static struct wp_viewport *viewport;
+
+
+
+/* Forward declarations. */
+static void wait_frame_callback (struct wl_surface *);
+
+
+
+static void
+do_viewport_damage_test (double src_x, double src_y, double src_width,
+ double src_height, int dest_width,
+ int dest_height, const char *dump_1_name,
+ const char *dump_2_name)
+{
+ struct wl_buffer *buffer, *damaged_buffer;
+
+ buffer = load_png_image (display, "viewporter_test.png");
+
+ if (!buffer)
+ report_test_failure ("failed to load viewporter_test.png");
+
+ damaged_buffer = load_png_image (display, "viewporter_test_1.png");
+
+ if (!damaged_buffer)
+ report_test_failure ("failed to load viewporter_test_1.png");
+
+ /* Set the viewport. */
+ wp_viewport_set_source (viewport,
+ wl_fixed_from_double (src_x),
+ wl_fixed_from_double (src_y),
+ wl_fixed_from_double (src_width),
+ wl_fixed_from_double (src_height));
+ wp_viewport_set_destination (viewport, dest_width, dest_height);
+
+ wl_surface_attach (wayland_surface, buffer, 0, 0);
+ wl_surface_damage (wayland_surface, 0, 0, INT_MAX, INT_MAX);
+ wait_frame_callback (wayland_surface);
+
+ /* Verify the image without any damage applied. */
+ verify_image_data (display, test_surface_window, dump_1_name);
+
+ /* Now, load the damaged buffer and apply buffer damage. */
+ wl_surface_attach (wayland_surface, damaged_buffer, 0, 0);
+ wl_surface_damage_buffer (wayland_surface, 100, 100, 30, 30);
+ wait_frame_callback (wayland_surface);
+
+ /* Verify the image with damage applied. */
+ verify_image_data (display, test_surface_window, dump_2_name);
+
+ /* Now, load the untransformed buffer and apply surface damage. */
+ wl_surface_attach (wayland_surface, buffer, 0, 0);
+ wl_surface_damage_buffer (wayland_surface, 100, 100, 30, 30);
+ wait_frame_callback (wayland_surface);
+
+ /* Verify that the surface with the damage reverted is the same
+ as the initial contents of the surface. */
+ verify_image_data (display, test_surface_window, dump_1_name);
+
+ /* Free both buffers. */
+ wl_buffer_destroy (buffer);
+ wl_buffer_destroy (damaged_buffer);
+}
+
+static void
+test_single_step (enum test_kind kind)
+{
+ struct wl_buffer *buffer;
+
+ test_log ("running test step: %s", test_names[kind]);
+
+ switch (kind)
+ {
+ case MAP_WINDOW_KIND:
+ buffer = load_png_image (display, "blue.png");
+
+ if (!buffer)
+ report_test_failure ("failed to load blue.png");
+
+ wl_surface_attach (wayland_surface, buffer, 0, 0);
+ wl_surface_damage (wayland_surface, 0, 0, INT_MAX, INT_MAX);
+ wl_surface_commit (wayland_surface);
+ wl_buffer_destroy (buffer);
+ break;
+
+ case VIEWPORT_DEST_200_150_KIND:
+ do_viewport_damage_test (-1, -1, -1, -1, 200, 150,
+ "viewport_dest_200_150_1.dump",
+ "viewport_dest_200_150_2.dump");
+ test_single_step (VIEWPORT_SRC_50_50_200_200_KIND);
+ break;
+
+ case VIEWPORT_SRC_50_50_200_200_KIND:
+ do_viewport_damage_test (50, 50, 200, 200, -1, -1,
+ "viewport_src_50_50_200_200_1.dump",
+ "viewport_src_50_50_200_200_2.dump");
+ test_single_step (VIEWPORT_SRC_50_50_200_200_DEST_500_500_KIND);
+ break;
+
+ case VIEWPORT_SRC_50_50_200_200_DEST_500_500_KIND:
+ do_viewport_damage_test (50, 50, 200, 200, 500, 500,
+ "viewport_src_50_50_200_200_dest_500_500_1.dump",
+ "viewport_src_50_50_200_200_dest_500_500_2.dump");
+ break;
+ }
+
+ if (kind == LAST_TEST)
+ test_complete ();
+}
+
+
+
+static void
+handle_test_surface_mapped (void *data, struct test_surface *surface,
+ uint32_t xid, const char *display_string)
+{
+ /* Sleep for 1 second to ensure that the window is exposed and
+ redirected. */
+ sleep (1);
+
+ /* Start the test. */
+ test_surface_window = xid;
+
+ /* Run the test again. */
+ test_single_step (VIEWPORT_DEST_200_150_KIND);
+}
+
+static const struct test_surface_listener test_surface_listener =
+ {
+ handle_test_surface_mapped,
+ };
+
+
+
+static void
+handle_wl_callback_done (void *data, struct wl_callback *callback,
+ uint32_t callback_data)
+{
+ bool *flag;
+
+ wl_callback_destroy (callback);
+
+ /* Now tell wait_frame_callback to break out of the loop. */
+ flag = data;
+ *flag = true;
+}
+
+static const struct wl_callback_listener wl_callback_listener =
+ {
+ handle_wl_callback_done,
+ };
+
+
+
+static void
+wait_frame_callback (struct wl_surface *surface)
+{
+ struct wl_callback *callback;
+ bool flag;
+
+ /* Commit surface and wait for a frame callback. */
+
+ callback = wl_surface_frame (surface);
+ flag = false;
+
+ wl_callback_add_listener (callback, &wl_callback_listener,
+ &flag);
+ wl_surface_commit (surface);
+
+ while (!flag)
+ {
+ if (wl_display_dispatch (display->display) == -1)
+ die ("wl_display_dispatch");
+ }
+}
+
+static void
+run_test (void)
+{
+ if (!make_test_surface (display, &wayland_surface,
+ &test_surface))
+ report_test_failure ("failed to create test surface");
+
+ viewport = wp_viewporter_get_viewport (viewporter,
+ wayland_surface);
+
+ if (!viewport)
+ report_test_failure ("failed to create viewport");
+
+ test_surface_add_listener (test_surface, &test_surface_listener,
+ NULL);
+ test_single_step (MAP_WINDOW_KIND);
+
+ while (true)
+ {
+ if (wl_display_dispatch (display->display) == -1)
+ die ("wl_display_dispatch");
+ }
+}
+
+int
+main (void)
+{
+ test_init ();
+ display = open_test_display (test_interfaces,
+ ARRAYELTS (test_interfaces));
+
+ if (!display)
+ report_test_failure ("failed to open display");
+
+ run_test ();
+}
diff --git a/tests/viewporter_test.png b/tests/viewporter_test.png
new file mode 100644
index 0000000..892f39c
Binary files /dev/null and b/tests/viewporter_test.png differ
diff --git a/tests/viewporter_test_1.png b/tests/viewporter_test_1.png
new file mode 100644
index 0000000..7faabb5
Binary files /dev/null and b/tests/viewporter_test_1.png differ