From 1879608d1a9ed722be1702687df46883275b6802 Mon Sep 17 00:00:00 2001 From: hujianwei Date: Fri, 4 Nov 2022 12:21:39 +0000 Subject: [PATCH] Check in new viewporter test files * tests/imgview.c: * tests/viewport_dest_200_150_1.dump: * tests/viewport_dest_200_150_2.dump: * tests/viewport_src_50_50_200_200_1.dump: * tests/viewport_src_50_50_200_200_2.dump: * tests/viewport_src_50_50_200_200_dest_500_500_1.dump: * tests/viewport_src_50_50_200_200_dest_500_500_2.dump: * tests/viewporter_test.c: * tests/viewporter_test.png: * tests/viewporter_test_1.png: New files. --- tests/Imakefile | 11 +- tests/README | 3 + tests/imgview.c | 203 +++++++++++++ tests/run_tests.sh | 2 +- tests/svnignore.txt | 5 + tests/test_harness.c | 99 +++--- tests/test_harness.h | 30 +- tests/viewport_dest_200_150_1.dump | Bin 0 -> 120012 bytes tests/viewport_dest_200_150_2.dump | Bin 0 -> 120012 bytes tests/viewport_src_50_50_200_200_1.dump | Bin 0 -> 160012 bytes tests/viewport_src_50_50_200_200_2.dump | Bin 0 -> 160012 bytes ...port_src_50_50_200_200_dest_500_500_1.dump | Bin 0 -> 1000012 bytes ...port_src_50_50_200_200_dest_500_500_2.dump | Bin 0 -> 1000012 bytes tests/viewporter_test.c | 286 ++++++++++++++++++ tests/viewporter_test.png | Bin 0 -> 1970 bytes tests/viewporter_test_1.png | Bin 0 -> 4430 bytes 16 files changed, 581 insertions(+), 58 deletions(-) create mode 100644 tests/imgview.c create mode 100644 tests/viewport_dest_200_150_1.dump create mode 100644 tests/viewport_dest_200_150_2.dump create mode 100644 tests/viewport_src_50_50_200_200_1.dump create mode 100644 tests/viewport_src_50_50_200_200_2.dump create mode 100644 tests/viewport_src_50_50_200_200_dest_500_500_1.dump create mode 100644 tests/viewport_src_50_50_200_200_dest_500_500_2.dump create mode 100644 tests/viewporter_test.c create mode 100644 tests/viewporter_test.png create mode 100644 tests/viewporter_test_1.png 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 0000000000000000000000000000000000000000..4614a504e62544119f3cb3fb7b634ccf28432af2 GIT binary patch literal 120012 zcmeI)QA#U86a>%_H{z;Yle^M<1&a9!eGyXks1GF24ON~pAk6!?ey;E9y1qWI>-X{H zpAHycfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_2I>s_`Z#L9^9J3|TO8qVxbF9*z31K$KWl)e^wieJnGUDhJjj!KC;Y4dp3+lW zA7?t8Zu1~d?w#A0PK{0H+decmp3w-?$x z$dh{?_W0U59?uiK`v*_ysjZJ;pZ4Jy!m4Lt?BlF~w%?cX=NxX|*oS@C$88pSU-0*y{CiJZAA4obByaN| zPwst2$=+LdN>6Ql?3F!}yv>6=x%U|*dvD<>J+<|*SN2TuHV^XT-e;8Ty@jXr)Yivd z*)z%8Jjj!KpHZ^+7M{{mTOWI6&m?d2AW!anM#O!77l^5ouUldu7igZ}T8e?tMnd-dlJ|Pi=kdl|7TZ&4WC-_ZcO7Z{aCD zwe_)A_Du3N5Ax*RXO!%{g{Sn?*2iAiGs)XL$dh}YQL^_Ip3+lWAA4obByaN|Pwst2 z$=+LdN>6Ql?3F!}yv>6=-Fx@*_48$b0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;= zV1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~ z0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz z7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg zfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_ z1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|XgfB^;=V1NMz7+`<_1{h#~0R|Xg;NK1W E0onlyO#lD@ literal 0 HcmV?d00001 diff --git a/tests/viewport_dest_200_150_2.dump b/tests/viewport_dest_200_150_2.dump new file mode 100644 index 0000000000000000000000000000000000000000..2cd2a77eef4abf9394a7659ec3a4efb33f7d784d GIT binary patch literal 120012 zcmeI(-%r(b9LMp~y3dSsJF?DPAUIRVG6xH_Es{E9i3iV4w6{C>Ajz4ml?!}k5Y_j>K|I#-;B3V#)D6bgmy z4;Ko$|HFSezyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOc zzyJm?fB_6(00S7n00uCC0XqZYU#155zJd4mEi&QYVY|;u_8#{R@oWv?DSC42BbyGM zcJn}%>#Mj-g5@|=%15n`g>XJzkaOU-`~)V^)J+3U(|`wOBy?VL4$uxYv_kL-JAPN zKTfd^{yzRc{++U%_wh*Om`bnrt8rsS+paEY=lFu28oQ{b=>@f)oz&2qOX|P-p?)8p z)z7D9bH1M7b$s5&&s(=XawfIq%xN`Ndeyo%qT)LfDv!6&^kt!Q-lir!sW)ycK5 zRGIox?=9a}{oKWzuP1mNo}wqWK5{0t?YW~W9XzQmT?1;^J*dr}UsZc`N&~IO^mWgO zKA5iS{QPAt4ozvbr$6WG30~*sfjn{VIg_fN{!ZKX^r@+{riLdgDpqFI-uu3~+eY+4 z>3PjR)2DA=9M(5I1G?6AJm>2PUWcdX$*qr^Nj=eWSj}yn+Ed)8U5|BX$EE`+ZF)%^ z%~c)TxmUHlujp*~Wi21=)P+OkoUbQ%otp>p#J%TCs<^pB&0E{FtGHh$8aq@icB}gM zt7>UDtk+te)y7-_QyRt9m>j_?mr|8M8j|8NwPP%y@Pu#l|)&ybj6g|21 zk${xdNjDGViF>!gnjj3Gq9?aL5|FYw>E?kvaqm`G6NJH2^yJn@0#a5d-8_&d?%fJ& zf-rcBp4|FKK+5W*n+Nj5y<1^T5C%`tlUpANNLih9^FW@scPp$3!r&=-a_b`jDXWui z9>^2-ZiO{L7(7K!Zha&mWp&cc19{@!t*|BtgQw`pt&aqxtWLUlAWz)871jh{@Dx3{ z^^t&-)k!xGn-C*3@dC+^(} zYl1L%ik{s1NI=T!q?-rw#JyW#O%Mi8(UV&r2}oI;bn`%-xOXe83BuqhdUER{0V%7K zZXU=J_ilwXK^QzmPi}oAAZ2yZ%>#Mj-mS1E2!p5S$*qqBq^wT5c_2^RyA{?1Vek|^ zx%H8Nl+{T$59En^x5Anr44$GV`k)UCU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n z1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q z7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJ zU;qOczyJm?fB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm? zfB_6(00S7n00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n z00uCC0SsUO0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?fB_6(00S7n00uCC0SsUO j0~o*n1~7mD3}65Q7{CAqFn|FJU;qOczyJm?5DfeaOD7f$ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..843bea129b144bd1ab8a6b4a2e9f0b26919cbd5a GIT binary patch literal 160012 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 N5|DrdB=G+V{4X?93uyoV literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b08261caf0ee6fc450a150010b55fb7800d458b3 GIT binary patch literal 1000012 zcmeIzu?+(;3WnD0L;ut-Dj>{f+z62N<&``mNBpL1T1009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfWVl*dHqyi>@ zuyz~fB|v}xfgXW8%~bYmRi^|95FoH7Afrm|0Ds#Hq1+a009C$0(qLL?AfYL2@oJa zU`;?u=K^cDVO|0R2oUHI$kR+^&sKFxfB*pkYXVX_7g)Ou^AaFHfIyExo@Oe0wyIMC z1PBmV6Ohumz}jt?mjD3*1bPJWG*j8LRh<$bK!CuSfRxS!)^5YR1PBly&?AtinaZB6 z>XZNh0tD6sq;xK@b{pm;K!5;&9)Uc~RQ7CDrvwNPAh0GNrE`I`+b}Ny0t5*32;^y| zvS+J0B|v}xfi(dsoeQkphIt7PAV8o;AWt)uJzLc&0RjXFtO-czTwv`s%u9d(0RlY& zd77#0*{V(n5FkKcO+ZTL0&BNnUIGLN5afB=Ct0V$metlfrr2@oJaphqB2GnGAC z)hPi21PH7NNa5rB7ndjj|8fnr=#|!&T0JGR;H5iOpys+;}0S1b-fP$h5ihV1ffMVZ`jd#ax zZ{s8#CmlQE#68^|MNwv28IMNlcO%Vz(eLj$cbW66yy$v=&|Hu7(c_%h(xXd1>8o>8 zRp1z5o56zxTax5g>&N>`XRmLK>{!Q8mq0B6ATSK!5;&S{0~ndEV{$t1RfrN zvHx~2s!jjhTaneb9x65N-5c4~eT}7cTlYk^_*zF-U*C?!mA2pBSz7()v(efAYKzqm zdg1?Ek8FD7->tUp>i)=@_HQq3JF_>k^S^^{1PBly(4Bxi_x`-Qv*C3D1PBm#cmy8%_H_0h;$-f!vZlVj0RX~!4srMiE)64``b-7Ya{A_aDwjcJiB!(w=`h z8CmPS^QG7KUWn}X2X2)9{^+g9zHGfyx_{_;WG(^(2oNAps{++6&$~Up(YfXJyjD-E z=ORFW0DO4@NfNf3}rI{Oje&hW+_M>8Z+l?rg&EZ+7+d-I!2m>@VLa zjr{OlWKZ0Gy)^RGcOn~dx2p;59g!_Qeyp_V@WJS8@0r;2pbcA(MAp3aSn0$o*CX4u z?^LPbkH@34|8X`N9<=jUrz5+1=zQt72QNkT_3772UmbiavVS;yxAf`0+mX2l5FkK+ zK&=W?w>sR?4zS@v~JrUW6Kb|g)`{$0xMt*a@H0mGTjcnwHACyMj|0uE{cRni( zzWqsLLvFoa8g%JSWV6qlEH#`s5ZSJ#Q>BLbQ;{9raILid=I+Sqzd2so`Cm>%_ST-$ zrQcURYtOzscfa)2q5F}2ap=|3&yTzonTr4c0t5)usz7zi^KQ?-+j4tetEbg-5g z?#l0`RjU8+bZO@=&O~;nxvlhd)A`7L-~M{(oAx&&`=atQa@Bry`d(x%0t5&UAW*9U z)h*AvJ%7D(%k6oso>tFAfB*pk-3i!p@6WqC8(t?sfB=DqN8quQYopqr74?w~UDefq zb!#FUab$IA*hejq_4-X)X;9@mRalo#bhh$H^mx$V`YVwQ z-F3axula0rw)If-d(ev;H%7Mg;I7iT^G%U$YOVa9`hyOxz7pB`vu8^6U!0BX`0;b4 z-|T3M?8`mvrQe*o8QCw+-zfe3*rmu^1PBlyK%iCys#~6Sd*0r;<@UT*Ppju5K!5;& z?gakR_WG#yNZsnl2CZIH8nR+dWc{|RERDUnHL`)9pD6YG<(0?=+`Cxnv9hJ|9=s)f zxaxRm%>MI{J$0n3r<+ej_T>Jy(lZB7M>gX4`O<*1=OUYM;9zM>+s?=u&KxT3+;}mv zO_jd|S8dH_7a}`&xuf*aj>D1t^RBkiZ!7QDJKJ8lKj^C+?UA_%5FkK+K&=W?w>ba`9)VuyzWMdCrElt{dD6$2+k9BpjBNkLzapqcS z-kBSbjc&P88nESRWPSHuDb<~8jI5=txzyBnDYEqk&z07_cO|mJS2{}X?l~0MKkhkM z`a|QX$o{nFZ0TS2wnye7K!5-N0<|ho-SWKK^OK!hZqIA=w0bTA1PBo5PN3J(T~Y0C z_BBTKgH6jz!|GNtFAfB*pk-3j!l?0BhRP4uYLd&T_H@U<)ByVg|h-_>{T z>dNnnRsNp)>7Aus3!5Sv*mATqef#mq4lF%bTDH3_vURV$Ug|i~9@*iGU9G-yAhKC) zO{G;w8zQSev8%NG+VRNh54DxHUTBZ(&}(-}2ivbjcC!6m>0HOVk)3Y8UwZBM&B$J@ ze1B`TE8F%)<|06V009EEDp0mOcioHkEqL-xFE?reme4mG3#p8W-#> zZC!OBvX?GhFKv1A-N>$2zRR@Q@s7%On^tPNd872oy{nOJx^=0vzwK;ftrstp4!wRm zvZfn%ORZOa8rimsAC?+AK8&on@_Mz)=k7&z>ENl-xrXM*Tm%RZAV8p21*%(~cYFTR z&Mmj+wR&1T7XbnU2y`d#$nr%|ZOF1Ekv&pi3vbFT+#-_*yHtZ|)n%fvz zpRI>VlPbR(mMve}Tv|VIePo;0>?S^^{1PBly(4Bxi_x`-Qv*C3D1PBm#cm#&8T2}e_x9=Lg zaz$h#>eiHoY~32!WA%HwdgW+5R%y`2uKLW~9a;ZZ4wME}zUL&Hw)JS~mFIUw*7)qk zQtO=Uk!`F$QmSjc8QHQ^@03=YdpEK*XWuDpJo#>P)_N;8K4|;yE0HyAIak_Wef2H|b<42VqnZ2phb6S05eV(oSw+|Y$?oed?D}U#$+7lP=L^fshkCCyi zk+rqmDjnN*I&v|u6jPVJvtlP5Ir9>_~n+!2An%rdi>3M zkqx_Ww=`kh;mGE^u&1hfjb2?kKXr3t?=NU9y)l1NWNlmal+GP*kL<*m%cUb{ zuS9mB{bK3l(esgY>^xk$w0d)7*B7iQeX_bKG8X{?1PBnQRe`eQx$E}4bIa{{t)5oT zMSuVS0^JGNbMMc)I~!gnK!5;&heu%3`ioI*{FF_R4V}EEG;r#=$ex(CzBF>`rpS6v z++2EWT2o|?j@eimIHNhTKKoCUhQ4+uvSHV*ltyhj6xoZ*PLx(o-W%DxvD->>1}}>2 z+_M`>UoYGf*{@&TQo6r*b7Yq{HkLZJ?2hcphFzuGE4N4X#-a_S_ZF^>?8D0I)xKD} zKQb2q0t5&Us8xaLmgn7`Z|K}|dtR%j)pHRbK!8AZ0v-E4iE4*;z8~4RNgGQe#&3#j z%%ruY(bMZ98!>HHX~5*B$Q~WNuGD{gLu7p_e-Ex&ul=VZ>)+5;8n^yLWYZS6mX=Oy zjBL@wZKavR7e}^m;EdAQXIDk`>xGS_uNLi!?3W9-mp)sxJ+hxI+)?^@<#+J1pDnAr z_Mk87_C@yP%9hg4mhOtoMSuVS0t9MRpt|LGx92-Lx7?oB>S^^{1PBly(4Bxi_x`-Q zv*C3D1PBm#cm!_l`!K4tH~k{A~hp2O=( zy@tFJ*?_snOa1FApR-pQy|$|fOO8f1cJ|)V%hMYpn>)U%nWO6>dvVB&(vtq;BHJ|l z`O?{EDxbkudVlt|($DAYitMv_U41ftTVx+sez(5bJC(nAm%To7ZRzfem65p!5FkK+ zK&=W?w>TvzJbYei(eM{h3;pVk`LxR;KU#!hXGY}mwIrDrE^i)_~TtzA96 zI%ZXRVbrYBoDmZuTiN&N(yBhsMz*@|^QHBJXGFGT=$z8_5pyDI82)l;>)@9o+dQbN z#xYAGa}gjwfB=D76{v1`-tGB!TW-&5^|X2}0t5&U=uW_%dw<^D+3-360t5&=JOU^8 zd>+*{Y`z}Zkn!_MBcEIu*{F##OJkp(9NCkjUnq^~zap|>ed|gi`mTzsNAIPjKE0Mi z*0cZW($K-%A{#Ptd+F)XYa^REesyWq)AK8zx6h9kpL)JDd*p=37W5raS~~Rk$kvWs zT-rUeF0y@dyE?RRRb)pObk#Crab!D(&o8a*KRq%R0RjXF5U5pw>Xzr-p0DcMa(iB@ zr`2;2AV7dXcLH;k?2BrHN6nAyiScv(s_B(~o*rYLo!Zst@iDg2xc*a0PxqJ|*;74c zmY)3E>5+~6o9DWEbXJV4G~$t$N<$v4d>&A#e~%@l5rZqg3s>p6C)Sl_Oq>@kx{ za|cd{Z0Vq>rS+2*RlaL=Q8c``taM=U!pP1nf4Ovi<&4NKubf`GzHDY>$6i=m+CApw z$Xo;n5FkLHRt2hCo_Bjby>rX$d99vS&qaU$0Rr6#*mLjCyE_|RCqRGzfrm$6_|prc z+Q{(>A{+eV^#|iH}a}>hakz zF?;mI(wNF;@7dtTE1&m2sCVUO=CaWPmX&6Xofp~MC&rgn4tgfCb(0p9_P)3zvi9Zk zO0RBsF|xng`dsOw%~K-#czsvzFP|9M&BfD87iPW`nTr4c0t5)usz7zi^KQ?lbZ)sl zuhrA)xd;#-K%hH;(W4ebwLt@)i)_fyv85-*jEZdJPo5|Z?Kw6&dvtsZebA_$VQ+zk&Sp3J+i|uEhxRQ?4`(lUO%(+(U#{T`+V*E z(g#akj_l2O&z0U;IyJHnHjXRZTQMy%7XbnU2oR`Mf$Em$-JUB6|AKCDpBTIvNKNZ5?TKd&z1%bofg@k z{u4_>22YOc=|1C1OZrZZY{P&TO7(-6MYi_wsig&vPL1rv%4hS{UV3D9WDEK(EzRgR zKe9nR=9WebS`yj3VUtShM$eAy>cTmtUv8Nm*{83}D1BBpKeF3XW|i(fIXAL*Cd?_l zJ#|8Kwq|_1{h-&^Oo_}zfB*pk1Zq{Fy5)Jd=X1W>^4xTLUaLpea}gjwfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U PAV7cs0RjXbT7mxuO2|lc literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..892f39ccc01024cecd158145a4a13d1598453db7 GIT binary patch literal 1970 zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y985qFmn|N5ft;31XXgM_iqWrYXoKyw| zjfu4rZ9NVLh_w1&_UaCkd86=X!a}P^0o_L{LN%OP1GKliO8E4P+gECmh`9T~tq&fY zPr7>WXk<8hxTC-y#=?@KppuC~@4dNnllFY5kbi!+xZ=H?Lq^!lEH*WU(9Jz1Mv7_0 ztCK#6)^Z$Zw{S8t{%Yyzb#U{(cPl5q(mS?!&+mV0{?!~zY4BH>m%1xaFkiqwKg#NP z?IRBD)0K~k9~Cz1dHgw1di1IJIn{R7d6I@kFDoB$Y>ar7w6r_&WzFL7PkpUl%^>-wlrC3tvKY=Q`RdYoN47>@uOXKzl&aL zjHp48&H^^kO^@0CH{aiE+8sPOFUW%N%bpwGj%x_qVU6Ow{m*XO+iRQ;>e<$9>Dzye zCC$z=zhuh`L4ysvF)`&Psr)yBT^8Ksp>~&R(x@SpTX$M9NXMsm#F#`j)FbFd;%$g$s z6l5>)^mS!_#?8X1CU$1Q&t{;Ic8P05iF1B#Zfaf$gL6@8Vo7R>LV0FMhJw4NZ-7El zr9wbzc6OpdKw@G}VqR*VhrsC@3=FJYo-U3d6}R4AJILAKAi#1ka_665Ipz|J-Dr2()PoeIhr~T;O{*Zi{<+<;(W%}l(`VWfO9quq5k!2_Z(E{ZRU?z-) z2%$)!t47iVWO_{FJeQrtg5*uqpg?yDTA1cBQOO-Z51_aj)k8;QQC&?n?^Ds*hW)da zgfSHC1SMKn+JezwAyNXCW=R`=e2!X+JGY}0MEJ`Ongz1LJ2eK>oIysWskq0dGmraa U#FcjsfrUAPr>mdKI;Vst0CtVjl>h($ literal 0 HcmV?d00001 diff --git a/tests/viewporter_test_1.png b/tests/viewporter_test_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7faabb537011e5258c96f16b711ceb2b78deccf7 GIT binary patch literal 4430 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