From fbd416047497af628cf70f46e9977d60572158a2 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 4 Dec 2020 15:20:11 +0200 Subject: [PATCH] tests: add output damage test This test ensures that client submitted damage goes to the screen correctly, regardless of output scale or transform. The added quirk is explained in the test that uses it. Signed-off-by: Pekka Paalanen --- include/libweston/libweston.h | 2 + libweston/renderer-gl/gl-renderer.c | 4 +- tests/meson.build | 1 + tests/output-damage-test.c | 204 ++++++++++++++++++ tests/reference/output-damage_1-180-01.png | Bin 0 -> 860 bytes tests/reference/output-damage_1-180-02.png | Bin 0 -> 888 bytes tests/reference/output-damage_1-270-01.png | Bin 0 -> 860 bytes tests/reference/output-damage_1-270-02.png | Bin 0 -> 884 bytes tests/reference/output-damage_1-90-01.png | Bin 0 -> 861 bytes tests/reference/output-damage_1-90-02.png | Bin 0 -> 883 bytes .../reference/output-damage_1-FLIPPED-01.png | Bin 0 -> 861 bytes .../reference/output-damage_1-FLIPPED-02.png | Bin 0 -> 888 bytes .../output-damage_1-FLIPPED_180-01.png | Bin 0 -> 857 bytes .../output-damage_1-FLIPPED_180-02.png | Bin 0 -> 887 bytes .../output-damage_1-FLIPPED_270-01.png | Bin 0 -> 860 bytes .../output-damage_1-FLIPPED_270-02.png | Bin 0 -> 885 bytes .../output-damage_1-FLIPPED_90-01.png | Bin 0 -> 861 bytes .../output-damage_1-FLIPPED_90-02.png | Bin 0 -> 883 bytes tests/reference/output-damage_1-NORMAL-01.png | Bin 0 -> 858 bytes tests/reference/output-damage_1-NORMAL-02.png | Bin 0 -> 889 bytes tests/reference/output-damage_2-180-01.png | Bin 0 -> 856 bytes tests/reference/output-damage_2-180-02.png | Bin 0 -> 884 bytes tests/reference/output-damage_2-90-01.png | Bin 0 -> 861 bytes tests/reference/output-damage_2-90-02.png | Bin 0 -> 886 bytes .../reference/output-damage_2-FLIPPED-01.png | Bin 0 -> 852 bytes .../reference/output-damage_2-FLIPPED-02.png | Bin 0 -> 879 bytes tests/reference/output-damage_2-NORMAL-01.png | Bin 0 -> 851 bytes tests/reference/output-damage_2-NORMAL-02.png | Bin 0 -> 876 bytes .../output-damage_3-FLIPPED_270-01.png | Bin 0 -> 842 bytes .../output-damage_3-FLIPPED_270-02.png | Bin 0 -> 863 bytes tests/reference/output-damage_3-NORMAL-01.png | Bin 0 -> 842 bytes tests/reference/output-damage_3-NORMAL-02.png | Bin 0 -> 859 bytes 32 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 tests/output-damage-test.c create mode 100644 tests/reference/output-damage_1-180-01.png create mode 100644 tests/reference/output-damage_1-180-02.png create mode 100644 tests/reference/output-damage_1-270-01.png create mode 100644 tests/reference/output-damage_1-270-02.png create mode 100644 tests/reference/output-damage_1-90-01.png create mode 100644 tests/reference/output-damage_1-90-02.png create mode 100644 tests/reference/output-damage_1-FLIPPED-01.png create mode 100644 tests/reference/output-damage_1-FLIPPED-02.png create mode 100644 tests/reference/output-damage_1-FLIPPED_180-01.png create mode 100644 tests/reference/output-damage_1-FLIPPED_180-02.png create mode 100644 tests/reference/output-damage_1-FLIPPED_270-01.png create mode 100644 tests/reference/output-damage_1-FLIPPED_270-02.png create mode 100644 tests/reference/output-damage_1-FLIPPED_90-01.png create mode 100644 tests/reference/output-damage_1-FLIPPED_90-02.png create mode 100644 tests/reference/output-damage_1-NORMAL-01.png create mode 100644 tests/reference/output-damage_1-NORMAL-02.png create mode 100644 tests/reference/output-damage_2-180-01.png create mode 100644 tests/reference/output-damage_2-180-02.png create mode 100644 tests/reference/output-damage_2-90-01.png create mode 100644 tests/reference/output-damage_2-90-02.png create mode 100644 tests/reference/output-damage_2-FLIPPED-01.png create mode 100644 tests/reference/output-damage_2-FLIPPED-02.png create mode 100644 tests/reference/output-damage_2-NORMAL-01.png create mode 100644 tests/reference/output-damage_2-NORMAL-02.png create mode 100644 tests/reference/output-damage_3-FLIPPED_270-01.png create mode 100644 tests/reference/output-damage_3-FLIPPED_270-02.png create mode 100644 tests/reference/output-damage_3-NORMAL-01.png create mode 100644 tests/reference/output-damage_3-NORMAL-02.png diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 21c210cb..a7b1dbaf 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -194,6 +194,8 @@ enum weston_hdcp_protection { * \ingroup testharness */ struct weston_testsuite_quirks { + /** Force GL-renderer to do a full upload of wl_shm buffers. */ + bool gl_force_full_upload; }; /** Weston test suite data that is given to compositor diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 4e9d54a4..0abcddde 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -1572,6 +1572,8 @@ static GLenum gl_format_from_internal(GLenum internal_format) static void gl_renderer_flush_damage(struct weston_surface *surface) { + const struct weston_testsuite_quirks *quirks = + &surface->compositor->test_data.test_quirks; struct gl_surface_state *gs = get_surface_state(surface); struct weston_buffer *buffer = gs->buffer_ref.buffer; struct weston_view *view; @@ -1607,7 +1609,7 @@ gl_renderer_flush_damage(struct weston_surface *surface) data = wl_shm_buffer_get_data(buffer->shm_buffer); - if (gs->needs_full_upload) { + if (gs->needs_full_upload || quirks->gl_force_full_upload) { glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); wl_shm_buffer_begin_access(buffer->shm_buffer); diff --git a/tests/meson.build b/tests/meson.build index 6012a460..0193308d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -142,6 +142,7 @@ tests = [ linux_explicit_synchronization_unstable_v1_protocol_c, ], }, + { 'name': 'output-damage', }, { 'name': 'output-transforms', }, { 'name': 'plugin-registry', }, { diff --git a/tests/output-damage-test.c b/tests/output-damage-test.c new file mode 100644 index 00000000..aa3557c0 --- /dev/null +++ b/tests/output-damage-test.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2020 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + +#include "weston-test-client-helper.h" +#include "weston-test-fixture-compositor.h" + +#define RENDERERS(s, t) \ + { \ + .renderer = RENDERER_PIXMAN, \ + .scale = s, \ + .transform = WL_OUTPUT_TRANSFORM_ ## t, \ + .transform_name = #t, \ + .meta.name = "pixman " #s " " #t, \ + }, \ + { \ + .renderer = RENDERER_GL, \ + .scale = s, \ + .transform = WL_OUTPUT_TRANSFORM_ ## t, \ + .transform_name = #t, \ + .meta.name = "GL " #s " " #t, \ + } + +struct setup_args { + struct fixture_metadata meta; + enum renderer_type renderer; + int scale; + enum wl_output_transform transform; + const char *transform_name; +}; + +static const struct setup_args my_setup_args[] = { + RENDERERS(1, NORMAL), + RENDERERS(1, 90), + RENDERERS(1, 180), + RENDERERS(1, 270), + RENDERERS(1, FLIPPED), + RENDERERS(1, FLIPPED_90), + RENDERERS(1, FLIPPED_180), + RENDERERS(1, FLIPPED_270), + RENDERERS(2, NORMAL), + RENDERERS(3, NORMAL), + RENDERERS(2, 90), + RENDERERS(2, 180), + RENDERERS(2, FLIPPED), + RENDERERS(3, FLIPPED_270), +}; + +static enum test_result_code +fixture_setup(struct weston_test_harness *harness, const struct setup_args *arg) +{ + struct compositor_setup setup; + + /* + * The width and height are chosen to produce 324x240 framebuffer, to + * emulate keeping the video mode constant. + * This resolution is divisible by 2 and 3. + * Headless multiplies the given size by scale. + */ + + compositor_setup_defaults(&setup); + setup.renderer = arg->renderer; + setup.width = 324 / arg->scale; + setup.height = 240 / arg->scale; + setup.scale = arg->scale; + setup.transform = arg->transform; + setup.shell = SHELL_TEST_DESKTOP; + + /* + * The test here works by swapping the whole wl_surface into a + * different color but lying that there is only a small damage area. + * Then the test checks that only the damage area gets the new color + * on screen. + * + * The following quirk forces GL-renderer to update the whole texture + * even for partial damage. Otherwise, GL-renderer would only copy the + * damaged area from the wl_shm buffer into a GL texture. + * + * Those output_damage tests where the surface is scaled up by the + * compositor will use bilinear texture sampling due to the policy + * in the renderers. + * + * Pixman renderer never makes copies of wl_shm buffers, so bilinear + * sampling there will always produce the expected result. However, + * with GL-renderer if the texture is not updated beyond the strict + * damage region, bilinear sampling will result in a blend of the old + * and new colors at the edges of the damage rectangles. This blend + * would be detrimental to testing the damage regions and would cause + * test failures due to reference image mismatch. What we actually + * want to see is the crisp outline of the damage rectangles. + */ + setup.test_quirks.gl_force_full_upload = true; + + return weston_test_harness_execute_as_client(harness, &setup); +} +DECLARE_FIXTURE_SETUP_WITH_ARG(fixture_setup, my_setup_args, meta); + +static void +commit_buffer_with_damage(struct surface *surface, + struct buffer *buffer, + struct rectangle damage) +{ + wl_surface_attach(surface->wl_surface, buffer->proxy, 0, 0); + wl_surface_damage(surface->wl_surface, damage.x, damage.y, + damage.width, damage.height); + wl_surface_commit(surface->wl_surface); +} + +/* + * Test that Weston repaints exactly the damage a client sends to it. + * + * NOTE: This relies on the Weston implementation detail that Weston actually + * will repaint exactly the client's damage and nothing more. This is not + * generally true of Wayland compositors. + */ +TEST(output_damage) +{ +#define COUNT_BUFS 3 + const struct setup_args *oargs; + struct client *client; + bool match = true; + char *refname; + int ret; + struct buffer *buf[COUNT_BUFS]; + pixman_color_t colors[COUNT_BUFS]; + static const struct rectangle damages[COUNT_BUFS] = { + { 0 /* full damage */ }, + { .x = 10, .y = 10, .width = 20, .height = 10 }, + { .x = 43, .y = 47, .width = 5, .height = 50 }, + }; + int i; + const int width = 140; + const int height = 110; + + color_rgb888(&colors[0], 100, 100, 100); /* grey */ + color_rgb888(&colors[1], 0, 255, 255); /* cyan */ + color_rgb888(&colors[2], 0, 255, 0); /* green */ + + oargs = &my_setup_args[get_test_fixture_index()]; + + ret = asprintf(&refname, "output-damage_%d-%s", + oargs->scale, oargs->transform_name); + assert(ret); + + testlog("%s: %s\n", get_test_name(), refname); + + client = create_client(); + client->surface = create_test_surface(client); + client->surface->width = width; + client->surface->height = height; + + for (i = 0; i < COUNT_BUFS; i++) { + buf[i] = create_shm_buffer_a8r8g8b8(client, width, height); + fill_image_with_color(buf[i]->image, &colors[i]); + } + + client->surface->buffer = buf[0]; + move_client(client, 19, 19); + + /* + * Each time we commit a buffer with a different color, the damage box + * should color just the box on the output. + */ + for (i = 1; i < COUNT_BUFS; i++) { + commit_buffer_with_damage(client->surface, buf[i], damages[i]); + if (!verify_screen_content(client, refname, i, NULL, i)) + match = false; + } + + assert(match); + + for (i = 0; i < COUNT_BUFS; i++) + buffer_destroy(buf[i]); + + client->surface->buffer = NULL; + client_destroy(client); +} diff --git a/tests/reference/output-damage_1-180-01.png b/tests/reference/output-damage_1-180-01.png new file mode 100644 index 0000000000000000000000000000000000000000..d8124622be090a80b4e9ebe305c77923b417c7cd GIT binary patch literal 860 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ow9 zPZ!6KiaBp@o#kzGlyD1lVHYyha1yRsz_~V{FH5Cr!{(_qb!zL1zfHE8J-gia^VxS6 z%ysvZzA!wnJ;EcH)W%`x+%iMa>5PD4T8DtKONXS=s4$^0*(hV%u>RJ%b&J(M9C^BJ z-nR>>BRd#7p1xrGF!|i_%TKodKK!uPTP_A?TKd4uv+TzO{dM6xaHhD2>^JIn-nj-0 fTunVP66Cw*7Tg#5CETt7vkQZ#tDnm{r-UW|*?Ao{ literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-180-02.png b/tests/reference/output-damage_1-180-02.png new file mode 100644 index 0000000000000000000000000000000000000000..8078d03bd9a2a6cdce9621e0d7b886dc9ec11d41 GIT binary patch literal 888 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owb zPZ!6KiaBrZ9?U%KAmDIOWk+*EwufNmAzKgMC88^3!jlX5ch0=Sv}um&{r7iEB4(UU z*W3N#>*Ft9nf}!0FJ@=>rkK_tVC>Q%sdR)#FsY5h(79!XqSG0HQDH)1(sB3&{?PsT>yEbz&Jqm4L(bgu?(SM+Z@;`!%Jk&ioWT_K7CmwdY_p$be&P7NVJ6j* zz{Bq*8;ZgX&_Zn1ku#ku3} z^={$R_mJNp;@;!B{{>ZZmzmmS8IxiQ+)WR8frfakuc=KVPd`z9g4;GMRljlPcQ{gP m*C+Sz{!N^bHJp6@h&O5q_k{_cr*i_c3xlVtpUXO@geCx3ycqrf literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-270-02.png b/tests/reference/output-damage_1-270-02.png new file mode 100644 index 0000000000000000000000000000000000000000..a57fce64475f16a1163044a2b138243519a7bc90 GIT binary patch literal 884 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owL zPZ!6KiaBrZT+BR_AmMN^>dt}(JhF#W?@ zSK0mk@=xX;zwO-l8FHM@2q>m?2pGF`NGcuS5lm|1Fm!I2q3DEDc%!^6gW&P?uU`l% z>1{uJK5xrRT#64#Cv4bT8aXd!?z5kw{9AFV!)+JPWgqwrZrtns_v!1Lvjkmts9kK& z)m>{AyH_O4T7FSE=Rg|5HxC(lwr9zh{`E5>-m9bq%#c$3`y#VI;Z9k%{tx$W;*9Dc fbP0l+XkKM{y@O literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-90-01.png b/tests/reference/output-damage_1-90-01.png new file mode 100644 index 0000000000000000000000000000000000000000..e3960685dd3f24b8bd01ca8bf74443f1b6395acf GIT binary patch literal 861 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ov! zPZ!6KiaBrZIPx9}5MgjsuuxdZ=90j~pTMN;%9rKwijiGrLF@GzCHcE&6{_|=RTg#yZqs; zpvH!o!`#C(i@$B$wcoA!{O8R(_q_EVcm3%!vJy(tO6vo6KC#ND8RJTOM_#KR$h&Ot iSmwa&95T|S4TJkh?hE&>vaAH=7Y0vPKbLh*2~7ZfAQsgC literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-90-02.png b/tests/reference/output-damage_1-90-02.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6305e9c4169ef9495dd1ff8e75e1e911397db GIT binary patch literal 883 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ovg zPZ!6KiaBrZT+D1vkZ`!TEv4Bh?S(+BlJyIrSl8nxO&Z@^V0DrYdh5Ub`JS#Hdt>Z= z1jgIz#p@sV|J|&LAwfE+jlQaBPPAGPN6 zr^8n>=apCK$xJ&-R?0aN_n+bObp0R6W;m0d&40EVU+eA_@I9EGLq;;KVb0|eU_6vM S-wK$E7(8A5T-G@yGywo{0wZPs literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-FLIPPED-01.png b/tests/reference/output-damage_1-FLIPPED-01.png new file mode 100644 index 0000000000000000000000000000000000000000..3853b20277c08fd82d83090c007b3513a34d0595 GIT binary patch literal 861 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ov! zPZ!6KiaBp@?dEiH6mbm{wH8=&P$}n-+!oI0i$!bPDr{%W2aln1%M3-QGXjcf9RkKK9g<2%cm$K$IB*IdsrtfDm$iRq|GWd-+cT}- zFFcJ?eO<#rnd_%hzukWP^2^p`$vYU+#ea-DPiI raMpC=4p)59Gj#k)RB9vBI~5EK0o)h#zwfXG<`)J}S3j3^P6*Ft9nf}!0FJ@=>rkK_tVC>Q%sdR)#FsY5h(79!XqSF}x+`<+;at-!hf7VIb zGVQmB@4wA=3#aObY!W#e^-e$AeA(u`#mU~YIBm#lI4H)y>u4$eY~tNP$klcJhc`!0 z|N8v7iT`4?os)4}PL!_+*+!Zn?H8F3BwV)Xl}nU2BOLhry7Nx|tdg;1>Q6Ez7(LW= gC~4jr+^Y96rhOG)EHi5o0%j!!Pgg&ebxsLQ08xM>hyVZp literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-FLIPPED_180-01.png b/tests/reference/output-damage_1-FLIPPED_180-01.png new file mode 100644 index 0000000000000000000000000000000000000000..775f79fb85eefbcd5ddef83af46350d28d53cacf GIT binary patch literal 857 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ow6 zPZ!6KiaBp@Ir1KI5O4@oD0OIJb4g(0PhiqkU^i9y+R%P!+K0;b`)2R_b0&4$@z1%; zfA-zo&d%^mF|9+u*rh{K=?ITtQX7Y%bIS}xr!xYh!i2)4Bk|Me%l}Lt%ji6`l-p;^ z^m^mWksWYJ5ijl^|7-X2?bE8cg+f1s&2T0wol?eUUEE=5#<&vOkuTgEo>$B$FY6N zPp|i%zRvyO``%tTh8yiO6rIipD5iA?7`t>xDjnewOlspWbZ!|HCKM)qv;FJ#)xWo3 zci(aE++z0!g*k)+@wR*v&vw1n@6Tt>bMs|7e;{oTg>}c}7mV9xKg;~W@xg@%uMnF| zWWH9mFJuCf4>pTi@28hjf43HQrycld|WN%?pr_kEWxyKs9nt9 z-oD)Ob$YLVb+q3?GK7S5^@Cla=lg>FHFwjEaVA6a0}_vGY|qI(ym^xhOMbA4unI7~ TKjxAK%ts8Ku6{1-oD!M&;Kl1fK-1aS&?ynQnH_}%1Vmj7IQlkdCGI7(Sm8ubFWckF#*-9Tf&e?8dn@ lpX}bH&ta~ZJTk&?-T^=E3*D{%7=ihP!PC{xWt~$(69DeQ7?J=0 literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-FLIPPED_90-02.png b/tests/reference/output-damage_1-FLIPPED_90-02.png new file mode 100644 index 0000000000000000000000000000000000000000..8efc3ae0937b38516338c0338f611a0dc57b2656 GIT binary patch literal 883 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ovg zPZ!6KiaBrZT+D1v5NWu$Ev4Bh?S(+BlJyIrSl8nxO&Z@^V0DsP4;So$~<1ln?nW5-(MgX_4h3>x3zdvt#B;#JT zcm8*|MyA;~^-kN*`0b93um3u}$2%?-KirT*s$CG5ZTrPOV}H%T?wk0W1yg$A(a~p_ z_o`di+X`<~v+x~BL-m0m0*uu>dK|!9#Ng@b=d#Wzp$P!Xw<=Nq literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-NORMAL-01.png b/tests/reference/output-damage_1-NORMAL-01.png new file mode 100644 index 0000000000000000000000000000000000000000..be723e0329a89bf8f8e1070ed4b7b5c6a95642a6 GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ow+ zPZ!6KiaBp@9pq(X6mST1VHYyha1yRsz`1r!QHb(QxsnGPruDwx`&*^>=giY<_?N%t z`cXT3sW`(k#k39qW0wv|r6W9oNo^d4&Mh+(oz4j07QW#(&*q(+@wmdKI;Vst0E^lf(f|Me literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_1-NORMAL-02.png b/tests/reference/output-damage_1-NORMAL-02.png new file mode 100644 index 0000000000000000000000000000000000000000..fad5f1d31815c45388c0795afc6174ff0c8b469c GIT binary patch literal 889 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ow5 zPZ!6KiaBrZ?)5z!Akq-%aFapP*nq`5g}s_HY~%5hCKER?=W201p8uiH@A)Io?LSLq ze}8hl|MYe458wC7+A?h5Gjwj5q3Co*KryXDz}TfjQt1efU{V_gPT?b&A5WhDe!Hu9 zL+k6mHD5U198bfgy5p(&fjTq)%a1l6wpeGu`A66crv*8s%x84yI=p^^GN1^ n{!QXz3faB^@Z#XJvLjz-kpSbdv&HVfyu{$?>gTe~DWM4fQ^qNB literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_2-180-01.png b/tests/reference/output-damage_2-180-01.png new file mode 100644 index 0000000000000000000000000000000000000000..9bf6871efe9ae77254c309ff97c320c066514357 GIT binary patch literal 856 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owc zPZ!6KiaBrZIC3&E3OEFcN^_(cw5Yy$Fl|HEF~i;svNqgJ4<6~&-P1NG{&^<%TKnbH zudjAguW879_qgs^=j@r!8SRzQIs}YeIwX~j@CYWgaTq$c%usYXBcM1cJoLh3V{8@U zk2hs|^^CsT@N}Q~+jpA0IF(QM)A;|_(XArW$x0R-=Jp4G3GAP3LuU-#l2M2Hr#0N? UjxBmA4a_PGp00i_>zopr07StUvH$=8 literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_2-180-02.png b/tests/reference/output-damage_2-180-02.png new file mode 100644 index 0000000000000000000000000000000000000000..7afa848134df3a824c09a4ca281a35d786ddd2fd GIT binary patch literal 884 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owL zPZ!6KiaBrZ9P~UAAmVT_@KU3JX+(?f4d+WOYgL~5m@;2(<_>3G^dP}*=bX)dyT6-F z-~QWw{d@W4)%p6@g+I(V{dUjiBhTkPXZ-JSMnEyGL%`UjLsIDok6=<;N9GqMnXB9K z?Dw2Iz2~-CP2o&MCv-I&hR!WBMupQlX1M7e2t0e*ri%65j=>s8mtU|xD8IdnZ>F{W z=?OdQ9~+SscMtgu_#Q;m7xq3PPyffW@(I&#SN^wcVBbll)qjt@`+3X$ViYK Z=CiH2&%M8*rVh+644$rjF6*2UngI8;8G--+ literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_2-90-02.png b/tests/reference/output-damage_2-90-02.png new file mode 100644 index 0000000000000000000000000000000000000000..073390716841c935e108961501b51041a1ea7d78 GIT binary patch literal 886 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owr zPZ!6KiaBrZZuC8zAmJM5aFapP*nq`5g}s_HY~%5hCKER?r&_5T`1C$z?q&D7vsbT2 zoO^xz>Fd<^`R}*SozG#v``-D*>NyW`zc3_7C$(`HI=9SFbUGuTnARa+?9w5rbc9E6 zR2VZ%mS1G9h?rjbrDeI{*~>3D+aDX@3^?-xd`F^v|FoZ`Qb_uL>lb^y>CeyYmu>QQ zu=E{ErE{$LEoT37&IFih4mj>4FQM@KV7u|P?%w}}6Q1J^Hfkrs8s>N6{QtFFBJzM4 OiNVv=&t;ucLK6TW%qkB6 literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_2-FLIPPED-01.png b/tests/reference/output-damage_2-FLIPPED-01.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc416d4385aa328fe52382a37a4f0234c6827c1 GIT binary patch literal 852 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owM zPZ!6KiaBrZ81gbX3OEERSSUC$D;YGhpJNGg;LGy((7>>QW9QSld)nJ)=GHBn{q=O0OlspWbZ(iU=yXOvF|9+u*rh{KiQ2+RzyFoov3>TR{m7m9zh|o7 zBG0Ot9gJ-MpOx+9n^`??nPTz&WMi`2{g6$9d&8ROn8i29a|R8>ku$@>5x=9!Xrp+;f*zazkI5&t>^Ek ztgg4JTy&Z&D~_1wHyo@le)D_6&ez*`Xa2UwH8=&P$}n-+#a=@r#i>8SgH-gSsZsBJzxD$ZS%?WO_B0` z(?vi0H(PAa@TYBtqSF}x#k39qW0wv|r6W9oNo^d4&Mnjy&Y3P>dFSqQc`n24$NxP& znnso-Ne6g019J(3r>mdKI;Vst04MVhP5=M^ literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_2-NORMAL-02.png b/tests/reference/output-damage_2-NORMAL-02.png new file mode 100644 index 0000000000000000000000000000000000000000..3c19eda8773917e172ca4cfdab5fefc34907ec28 GIT binary patch literal 876 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_owD zPZ!6KiaBrZ9P~ZxAm9+_@J>O+h(cnBCcx|KdjOt&$;E_*k)|s@j#zU?bHq%jBr0{)Q=AgJ87Q;Xk#TftW2&MRwAo6mWG^Sk2gKyh_Y6o1I@n;o*U_LyNr}p2x@ivO2bdAz$YF?^m4j zcdeCUsA->}=yXOvF|9+u*rh{K=?ITtQX7Y%bIZsQz7fX%px@@(-zBG$&rR0*FED?o zghWT~SB8HlW)y#IF`|K+ldR``zbf6J|6%4JPb5dUC6u|&85i-W0W$}Kr>mdKI;Vst E00a08MF0Q* literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_3-FLIPPED_270-02.png b/tests/reference/output-damage_3-FLIPPED_270-02.png new file mode 100644 index 0000000000000000000000000000000000000000..01319b2a97652ebcd310bb91723bf09dce7ad7e8 GIT binary patch literal 863 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ovk zPZ!6KiaBp@AIv>$Aj0Zs9l*P4!kSZh?r&GLEooA)yP>dYmS#i6^rQA4?T+nW+;4HN z_G?Rc?OHj8J?%3Toz4g-rgaDyyL3n@9pMp7YU40;ZlQtjyY26<3a`sLv$2Y)-Wu$J zokZH)an{`?qhKc8TnY?@+pid7PJI6OuzdAmVzl@d1Ny#{m|(6`X5CT30wY3!m6x{#>JC_U!$CmfwDC+VI%= zyd1-ywi${}X9N_}Is}YeIwX~j@CYWgaTq$c3=ZLr({C81@2sDHQ#fIN4E5dEppAb(2OE}^cj(-T8$TEGqXDYZP{&pRQLsZJY9AM^P@O1Ta JS?83{1OTVz4`~1Z literal 0 HcmV?d00001 diff --git a/tests/reference/output-damage_3-NORMAL-02.png b/tests/reference/output-damage_3-NORMAL-02.png new file mode 100644 index 0000000000000000000000000000000000000000..d72b4485e7dc5d8d83fd602fdfec95593f29cd77 GIT binary patch literal 859 zcmeAS@N?(olHy`uVBq!ia0y~yU~~bpKX5Ps$?r?L+<+8YlDE4H!+#K5uy^@n1_ovU zPZ!6KiaBrZI`STJ5OKZeRM5cblEB2jmUGP(uE0hHvk4Au_vUP#cl7q1KTl=!w*O{% zbHDHl!vpIhJc3DW9EQ#m?2pGF`NGc5y;W=*nKMs8TBVo(