Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 Collabora, Ltd. |
Vitaly Prosyak | 15d7546 | 2021-11-09 14:02:01 -0500 | [diff] [blame] | 3 | * Copyright 2021 Advanced Micro Devices, Inc. |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining |
| 6 | * a copy of this software and associated documentation files (the |
| 7 | * "Software"), to deal in the Software without restriction, including |
| 8 | * without limitation the rights to use, copy, modify, merge, publish, |
| 9 | * distribute, sublicense, and/or sell copies of the Software, and to |
| 10 | * permit persons to whom the Software is furnished to do so, subject to |
| 11 | * the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice (including the |
| 14 | * next paragraph) shall be included in all copies or substantial |
| 15 | * portions of the Software. |
| 16 | * |
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 24 | * SOFTWARE. |
| 25 | */ |
| 26 | |
| 27 | #include "config.h" |
| 28 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 29 | #include <math.h> |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 30 | |
| 31 | #include "weston-test-client-helper.h" |
| 32 | #include "weston-test-fixture-compositor.h" |
Vitaly Prosyak | 15d7546 | 2021-11-09 14:02:01 -0500 | [diff] [blame] | 33 | #include "color_util.h" |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 34 | |
| 35 | struct setup_args { |
Pekka Paalanen | ef81388 | 2021-02-15 13:46:42 +0200 | [diff] [blame] | 36 | struct fixture_metadata meta; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 37 | enum renderer_type renderer; |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 38 | bool color_management; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 39 | }; |
| 40 | |
| 41 | static const int ALPHA_STEPS = 256; |
| 42 | static const int BLOCK_WIDTH = 3; |
| 43 | |
| 44 | static const struct setup_args my_setup_args[] = { |
Pekka Paalanen | ef81388 | 2021-02-15 13:46:42 +0200 | [diff] [blame] | 45 | { |
| 46 | .renderer = RENDERER_PIXMAN, |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 47 | .color_management = false, |
Pekka Paalanen | ef81388 | 2021-02-15 13:46:42 +0200 | [diff] [blame] | 48 | .meta.name = "pixman" |
| 49 | }, |
| 50 | { |
| 51 | .renderer = RENDERER_GL, |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 52 | .color_management = false, |
Pekka Paalanen | ef81388 | 2021-02-15 13:46:42 +0200 | [diff] [blame] | 53 | .meta.name = "GL" |
| 54 | }, |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 55 | { |
| 56 | .renderer = RENDERER_GL, |
| 57 | .color_management = true, |
| 58 | .meta.name = "GL sRGB EOTF" |
| 59 | }, |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 60 | }; |
| 61 | |
| 62 | static enum test_result_code |
| 63 | fixture_setup(struct weston_test_harness *harness, const struct setup_args *arg) |
| 64 | { |
| 65 | struct compositor_setup setup; |
| 66 | |
| 67 | compositor_setup_defaults(&setup); |
| 68 | setup.renderer = arg->renderer; |
| 69 | setup.width = BLOCK_WIDTH * ALPHA_STEPS; |
| 70 | setup.height = 16; |
| 71 | setup.shell = SHELL_TEST_DESKTOP; |
| 72 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 73 | if (arg->color_management) { |
| 74 | weston_ini_setup(&setup, |
| 75 | cfgln("[core]"), |
| 76 | cfgln("color-management=true")); |
| 77 | } |
| 78 | |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 79 | return weston_test_harness_execute_as_client(harness, &setup); |
| 80 | } |
Pekka Paalanen | ef81388 | 2021-02-15 13:46:42 +0200 | [diff] [blame] | 81 | DECLARE_FIXTURE_SETUP_WITH_ARG(fixture_setup, my_setup_args, meta); |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 82 | |
| 83 | static void |
| 84 | set_opaque_rect(struct client *client, |
| 85 | struct surface *surface, |
| 86 | const struct rectangle *rect) |
| 87 | { |
| 88 | struct wl_region *region; |
| 89 | |
| 90 | region = wl_compositor_create_region(client->wl_compositor); |
| 91 | wl_region_add(region, rect->x, rect->y, rect->width, rect->height); |
| 92 | wl_surface_set_opaque_region(surface->wl_surface, region); |
| 93 | wl_region_destroy(region); |
| 94 | } |
| 95 | |
| 96 | static uint32_t |
| 97 | premult_color(uint32_t a, uint32_t r, uint32_t g, uint32_t b) |
| 98 | { |
| 99 | uint32_t c = 0; |
| 100 | |
| 101 | c |= a << 24; |
| 102 | c |= (a * r / 255) << 16; |
| 103 | c |= (a * g / 255) << 8; |
| 104 | c |= a * b / 255; |
| 105 | |
| 106 | return c; |
| 107 | } |
| 108 | |
| 109 | static void |
Vitaly Prosyak | 15d7546 | 2021-11-09 14:02:01 -0500 | [diff] [blame] | 110 | unpremult_float(struct color_float *cf) |
| 111 | { |
| 112 | if (cf->a == 0.0f) { |
| 113 | cf->r = 0.0f; |
| 114 | cf->g = 0.0f; |
| 115 | cf->b = 0.0f; |
| 116 | } else { |
| 117 | cf->r /= cf->a; |
| 118 | cf->g /= cf->a; |
| 119 | cf->b /= cf->a; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | static void |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 124 | fill_alpha_pattern(struct buffer *buf) |
| 125 | { |
| 126 | void *pixels; |
| 127 | int stride_bytes; |
| 128 | int w, h; |
| 129 | int y; |
| 130 | |
| 131 | assert(pixman_image_get_format(buf->image) == PIXMAN_a8r8g8b8); |
| 132 | |
| 133 | pixels = pixman_image_get_data(buf->image); |
| 134 | stride_bytes = pixman_image_get_stride(buf->image); |
| 135 | w = pixman_image_get_width(buf->image); |
| 136 | h = pixman_image_get_height(buf->image); |
| 137 | |
| 138 | assert(w == BLOCK_WIDTH * ALPHA_STEPS); |
| 139 | |
| 140 | for (y = 0; y < h; y++) { |
| 141 | uint32_t *row = pixels + y * stride_bytes; |
| 142 | uint32_t step; |
| 143 | |
| 144 | for (step = 0; step < (uint32_t)ALPHA_STEPS; step++) { |
| 145 | uint32_t alpha = step * 255 / (ALPHA_STEPS - 1); |
| 146 | uint32_t color; |
| 147 | int i; |
| 148 | |
| 149 | color = premult_color(alpha, 0, 255 - alpha, 255); |
| 150 | for (i = 0; i < BLOCK_WIDTH; i++) |
| 151 | *row++ = color; |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 156 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 157 | static bool |
| 158 | compare_float(float ref, float dst, int x, const char *chan, float *max_diff) |
| 159 | { |
| 160 | #if 0 |
| 161 | /* |
| 162 | * This file can be loaded in Octave for visualization. |
| 163 | * |
| 164 | * S = load('compare_float_dump.txt'); |
| 165 | * |
| 166 | * rvec = S(S(:,1)==114, 2:3); |
| 167 | * gvec = S(S(:,1)==103, 2:3); |
| 168 | * bvec = S(S(:,1)==98, 2:3); |
| 169 | * |
| 170 | * figure |
| 171 | * subplot(3, 1, 1); |
| 172 | * plot(rvec(:,1), rvec(:,2) .* 255, 'r'); |
| 173 | * subplot(3, 1, 2); |
| 174 | * plot(gvec(:,1), gvec(:,2) .* 255, 'g'); |
| 175 | * subplot(3, 1, 3); |
| 176 | * plot(bvec(:,1), bvec(:,2) .* 255, 'b'); |
| 177 | */ |
| 178 | static FILE *fp = NULL; |
| 179 | |
| 180 | if (!fp) |
| 181 | fp = fopen("compare_float_dump.txt", "w"); |
| 182 | fprintf(fp, "%d %d %f\n", chan[0], x, dst - ref); |
| 183 | fflush(fp); |
| 184 | #endif |
| 185 | |
| 186 | float diff = fabsf(ref - dst); |
| 187 | |
| 188 | if (diff > *max_diff) |
| 189 | *max_diff = diff; |
| 190 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 191 | /* |
| 192 | * Allow for +/- 1.5 code points of error in non-linear 8-bit channel |
| 193 | * value. This is necessary for the BLEND_LINEAR case. |
| 194 | * |
| 195 | * With llvmpipe, we could go as low as +/- 0.65 code points of error |
| 196 | * and still pass. |
| 197 | * |
| 198 | * AMD Polaris 11 would be ok with +/- 1.0 code points error threshold |
| 199 | * if not for one particular case of blending (a=254, r=0) into r=255, |
| 200 | * which results in error of 1.29 code points. |
| 201 | */ |
| 202 | if (diff < 1.5f / 255.f) |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 203 | return true; |
| 204 | |
| 205 | testlog("x=%d %s: ref %f != dst %f, delta %f\n", |
| 206 | x, chan, ref, dst, dst - ref); |
| 207 | |
| 208 | return false; |
| 209 | } |
| 210 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 211 | enum blend_space { |
| 212 | BLEND_NONLINEAR, |
| 213 | BLEND_LINEAR, |
| 214 | }; |
| 215 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 216 | static bool |
| 217 | verify_sRGB_blend_a8r8g8b8(uint32_t bg32, uint32_t fg32, uint32_t dst32, |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 218 | int x, struct color_float *max_diff, |
| 219 | enum blend_space space) |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 220 | { |
| 221 | struct color_float bg = a8r8g8b8_to_float(bg32); |
| 222 | struct color_float fg = a8r8g8b8_to_float(fg32); |
| 223 | struct color_float dst = a8r8g8b8_to_float(dst32); |
| 224 | struct color_float ref; |
| 225 | bool ok = true; |
| 226 | |
| 227 | unpremult_float(&bg); |
| 228 | unpremult_float(&fg); |
| 229 | unpremult_float(&dst); |
| 230 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 231 | if (space == BLEND_LINEAR) { |
| 232 | sRGB_linearize(&bg); |
| 233 | sRGB_linearize(&fg); |
| 234 | } |
| 235 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 236 | ref.r = (1.0f - fg.a) * bg.r + fg.a * fg.r; |
| 237 | ref.g = (1.0f - fg.a) * bg.g + fg.a * fg.g; |
| 238 | ref.b = (1.0f - fg.a) * bg.b + fg.a * fg.b; |
| 239 | |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 240 | if (space == BLEND_LINEAR) |
| 241 | sRGB_delinearize(&ref); |
| 242 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 243 | ok = compare_float(ref.r, dst.r, x, "r", &max_diff->r) && ok; |
| 244 | ok = compare_float(ref.g, dst.g, x, "g", &max_diff->g) && ok; |
| 245 | ok = compare_float(ref.b, dst.b, x, "b", &max_diff->b) && ok; |
| 246 | |
| 247 | return ok; |
| 248 | } |
| 249 | |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 250 | static uint8_t |
| 251 | red(uint32_t v) |
| 252 | { |
| 253 | return (v >> 16) & 0xff; |
| 254 | } |
| 255 | |
| 256 | static uint8_t |
| 257 | blue(uint32_t v) |
| 258 | { |
| 259 | return v & 0xff; |
| 260 | } |
| 261 | |
| 262 | static bool |
| 263 | pixels_monotonic(const uint32_t *row, int x) |
| 264 | { |
| 265 | bool ret = true; |
| 266 | |
| 267 | if (red(row[x + 1]) > red(row[x])) { |
| 268 | testlog("pixel %d -> next: red value increases\n", x); |
| 269 | ret = false; |
| 270 | } |
| 271 | |
| 272 | if (blue(row[x + 1]) < blue(row[x])) { |
| 273 | testlog("pixel %d -> next: blue value decreases\n", x); |
| 274 | ret = false; |
| 275 | } |
| 276 | |
| 277 | return ret; |
| 278 | } |
| 279 | |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 280 | static void * |
| 281 | get_middle_row(struct buffer *buf) |
| 282 | { |
| 283 | const int y = (BLOCK_WIDTH - 1) / 2; /* middle row */ |
| 284 | void *pixels; |
| 285 | int stride_bytes; |
| 286 | |
| 287 | assert(pixman_image_get_width(buf->image) >= BLOCK_WIDTH * ALPHA_STEPS); |
| 288 | assert(pixman_image_get_height(buf->image) >= BLOCK_WIDTH); |
| 289 | |
| 290 | pixels = pixman_image_get_data(buf->image); |
| 291 | stride_bytes = pixman_image_get_stride(buf->image); |
| 292 | return pixels + y * stride_bytes; |
| 293 | } |
| 294 | |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 295 | static bool |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 296 | check_blend_pattern(struct buffer *bg, struct buffer *fg, struct buffer *shot, |
| 297 | enum blend_space space) |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 298 | { |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 299 | uint32_t *bg_row = get_middle_row(bg); |
| 300 | uint32_t *fg_row = get_middle_row(fg); |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 301 | uint32_t *shot_row = get_middle_row(shot); |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 302 | struct color_float max_diff = { 0.0f, 0.0f, 0.0f, 0.0f }; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 303 | bool ret = true; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 304 | int x; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 305 | |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 306 | for (x = 0; x < BLOCK_WIDTH * ALPHA_STEPS - 1; x++) { |
| 307 | if (!pixels_monotonic(shot_row, x)) |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 308 | ret = false; |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 309 | |
| 310 | if (!verify_sRGB_blend_a8r8g8b8(bg_row[x], fg_row[x], |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 311 | shot_row[x], x, &max_diff, |
| 312 | space)) |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 313 | ret = false; |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 314 | } |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 315 | |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 316 | testlog("%s max diff: r=%f, g=%f, b=%f\n", |
| 317 | __func__, max_diff.r, max_diff.g, max_diff.b); |
| 318 | |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 319 | return ret; |
| 320 | } |
| 321 | |
| 322 | /* |
| 323 | * Test that alpha blending is roughly correct, and that an alpha ramp |
Maxime Roussin-Bélanger | 4e8ea1f | 2020-12-17 17:07:49 -0500 | [diff] [blame] | 324 | * results in a strictly monotonic color ramp. This should ensure that any |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 325 | * animation that varies alpha never goes "backwards" as that is easily |
| 326 | * noticeable. |
| 327 | * |
| 328 | * The background is a constant color. On top of that, there is an |
| 329 | * alpha-blended gradient with ramps in both alpha and color. Sub-surface |
| 330 | * ensures the correct positioning and stacking. |
| 331 | * |
| 332 | * The gradient consists of ALPHA_STEPS number of blocks. Block size is |
| 333 | * BLOCK_WIDTH x BLOCK_WIDTH and a block has a uniform color. |
| 334 | * |
| 335 | * In the blending result over x axis: |
| 336 | * - red goes from 1.0 to 0.0, monotonic |
| 337 | * - green is not monotonic |
| 338 | * - blue goes from 0.0 to 1.0, monotonic |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 339 | * |
| 340 | * This test has two modes: BLEND_NONLINEAR and BLEND_LINEAR. |
| 341 | * |
| 342 | * BLEND_NONLINEAR does blending with pixel values as is, which are non-linear, |
| 343 | * and therefore result in "physically incorrect" blending result. Yet, people |
| 344 | * have accustomed to seeing this effect. This mode hits pipeline_premult() |
| 345 | * in fragment.glsl. |
| 346 | * |
| 347 | * BLEND_LINEAR has sRGB encoded pixels (non-linear). These are converted to |
| 348 | * linear light (optical) values, blended, and converted back to non-linear |
| 349 | * (electrical) values. This results in "physically more correct" blending |
| 350 | * result for some value of "physical". This mode hits pipeline_straight() |
| 351 | * in fragment.glsl, and tests even more things: |
| 352 | * - gl-renderer implementation of 1D LUT is correct |
| 353 | * - color-lcms instantiates the correct sRGB EOTF and inverse LUTs |
| 354 | * - color space conversions do not happen when both content and output are |
| 355 | * using their default color spaces |
| 356 | * - blending through gl-renderer shadow framebuffer |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 357 | */ |
Pekka Paalanen | e70aa1f | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 358 | TEST(alpha_blend) |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 359 | { |
| 360 | const int width = BLOCK_WIDTH * ALPHA_STEPS; |
| 361 | const int height = BLOCK_WIDTH; |
| 362 | const pixman_color_t background_color = { |
| 363 | .red = 0xffff, |
| 364 | .green = 0x8080, |
| 365 | .blue = 0x0000, |
| 366 | .alpha = 0xffff |
| 367 | }; |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 368 | const struct setup_args *args; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 369 | struct client *client; |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 370 | struct buffer *bg; |
| 371 | struct buffer *fg; |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 372 | struct wl_subcompositor *subco; |
| 373 | struct wl_surface *surf; |
| 374 | struct wl_subsurface *sub; |
| 375 | struct buffer *shot; |
| 376 | bool match; |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 377 | int seq_no; |
| 378 | enum blend_space space; |
| 379 | |
| 380 | args = &my_setup_args[get_test_fixture_index()]; |
| 381 | if (args->color_management) { |
| 382 | seq_no = 1; |
| 383 | space = BLEND_LINEAR; |
| 384 | } else { |
| 385 | seq_no = 0; |
| 386 | space = BLEND_NONLINEAR; |
| 387 | } |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 388 | |
| 389 | client = create_client(); |
| 390 | subco = bind_to_singleton_global(client, &wl_subcompositor_interface, 1); |
| 391 | |
| 392 | /* background window content */ |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 393 | bg = create_shm_buffer_a8r8g8b8(client, width, height); |
| 394 | fill_image_with_color(bg->image, &background_color); |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 395 | |
| 396 | /* background window, main surface */ |
| 397 | client->surface = create_test_surface(client); |
| 398 | client->surface->width = width; |
| 399 | client->surface->height = height; |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 400 | client->surface->buffer = bg; /* pass ownership */ |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 401 | set_opaque_rect(client, client->surface, |
| 402 | &(struct rectangle){ 0, 0, width, height }); |
| 403 | |
| 404 | /* foreground blended content */ |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 405 | fg = create_shm_buffer_a8r8g8b8(client, width, height); |
| 406 | fill_alpha_pattern(fg); |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 407 | |
| 408 | /* foreground window, sub-surface */ |
| 409 | surf = wl_compositor_create_surface(client->wl_compositor); |
| 410 | sub = wl_subcompositor_get_subsurface(subco, surf, client->surface->wl_surface); |
| 411 | /* sub-surface defaults to position 0, 0, top-most, synchronized */ |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 412 | wl_surface_attach(surf, fg->proxy, 0, 0); |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 413 | wl_surface_damage(surf, 0, 0, width, height); |
| 414 | wl_surface_commit(surf); |
| 415 | |
| 416 | /* attach, damage, commit background window */ |
| 417 | move_client(client, 0, 0); |
| 418 | |
| 419 | shot = capture_screenshot_of_output(client); |
| 420 | assert(shot); |
Pekka Paalanen | 35cae56 | 2021-04-16 17:42:40 +0300 | [diff] [blame] | 421 | match = verify_image(shot, "alpha_blend", seq_no, NULL, seq_no); |
| 422 | assert(check_blend_pattern(bg, fg, shot, space)); |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 423 | assert(match); |
| 424 | |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 425 | buffer_destroy(shot); |
| 426 | |
| 427 | wl_subsurface_destroy(sub); |
| 428 | wl_surface_destroy(surf); |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 429 | buffer_destroy(fg); |
Pekka Paalanen | 681db34 | 2021-05-14 17:06:27 +0300 | [diff] [blame] | 430 | wl_subcompositor_destroy(subco); |
Pekka Paalanen | 129bef5 | 2021-04-19 14:05:59 +0300 | [diff] [blame] | 431 | client_destroy(client); /* destroys bg */ |
Pekka Paalanen | 2625881 | 2020-11-12 14:15:43 +0200 | [diff] [blame] | 432 | } |