• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2015 Samsung Electronics Co., Ltd
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 #include "config.h"
27 
28 #include <stdint.h>
29 #include <stdio.h>
30 
31 #include "weston-test-client-helper.h"
32 #include "weston-test-fixture-compositor.h"
33 #include "test-config.h"
34 
35 static enum test_result_code
fixture_setup(struct weston_test_harness * harness)36 fixture_setup(struct weston_test_harness *harness)
37 {
38 	struct compositor_setup setup;
39 
40 	compositor_setup_defaults(&setup);
41 	setup.renderer = RENDERER_PIXMAN;
42 	setup.width = 320;
43 	setup.height = 240;
44 	setup.shell = SHELL_DESKTOP;
45 	setup.config_file = TESTSUITE_INTERNAL_SCREENSHOT_CONFIG_PATH;
46 
47 	return weston_test_harness_execute_as_client(harness, &setup);
48 }
49 DECLARE_FIXTURE_SETUP(fixture_setup);
50 
51 static void
draw_stuff(pixman_image_t * image)52 draw_stuff(pixman_image_t *image)
53 {
54 	int w, h;
55 	int stride; /* bytes */
56 	int x, y;
57 	uint32_t r, g, b;
58 	uint32_t *pixels;
59 	uint32_t *pixel;
60 	pixman_format_code_t fmt;
61 
62 	fmt = pixman_image_get_format(image);
63 	w = pixman_image_get_width(image);
64 	h = pixman_image_get_height(image);
65 	stride = pixman_image_get_stride(image);
66 	pixels = pixman_image_get_data(image);
67 
68 	assert(PIXMAN_FORMAT_BPP(fmt) == 32);
69 
70 	for (x = 0; x < w; x++)
71 		for (y = 0; y < h; y++) {
72 			b = x;
73 			g = x + y;
74 			r = y;
75 			pixel = pixels + (y * stride / 4) + x;
76 			*pixel = (255U << 24) | (r << 16) | (g << 8) | b;
77 		}
78 }
79 
TEST(internal_screenshot)80 TEST(internal_screenshot)
81 {
82 	struct buffer *buf;
83 	struct client *client;
84 	struct wl_surface *surface;
85 	struct buffer *screenshot = NULL;
86 	pixman_image_t *reference_good = NULL;
87 	pixman_image_t *reference_bad = NULL;
88 	pixman_image_t *diffimg;
89 	struct rectangle clip;
90 	const char *fname;
91 	bool match = false;
92 	bool dump_all_images = true;
93 
94 	/* Create the client */
95 	testlog("Creating client for test\n");
96 	client = create_client_and_test_surface(100, 100, 100, 100);
97 	assert(client);
98 	surface = client->surface->wl_surface;
99 
100 	/*
101 	 * We are racing our screenshooting against weston-desktop-shell
102 	 * setting the cursor. If w-d-s wins, our screenshot will have a cursor
103 	 * shown, which makes the image comparison fail. Our window and the
104 	 * default pointer position are accidentally causing an overlap that
105 	 * intersects our test clip rectangle.
106 	 *
107 	 * w-d-s wins very rarely though, so the race is easy to miss. You can
108 	 * make it happen by putting a delay before the call to
109 	 * create_client_and_test_surface().
110 	 *
111 	 * The weston_test_move_pointer() below makes the race irrelevant, as
112 	 * the cursor won't overlap with anything we care about.
113 	 */
114 
115 	/* Move the pointer away from the screenshot area. */
116 	weston_test_move_pointer(client->test->weston_test, 0, 1, 0, 0, 0);
117 
118 	buf = create_shm_buffer_a8r8g8b8(client, 100, 100);
119 	draw_stuff(buf->image);
120 	wl_surface_attach(surface, buf->proxy, 0, 0);
121 	wl_surface_damage(surface, 0, 0, 100, 100);
122 	wl_surface_commit(surface);
123 
124 	/* Take a snapshot.  Result will be in screenshot->wl_buffer. */
125 	testlog("Taking a screenshot\n");
126 	screenshot = capture_screenshot_of_output(client);
127 	assert(screenshot);
128 
129 	/* Load good reference image */
130 	fname = screenshot_reference_filename("internal-screenshot-good", 0);
131 	testlog("Loading good reference image %s\n", fname);
132 	reference_good = load_image_from_png(fname);
133 	assert(reference_good);
134 
135 	/* Load bad reference image */
136 	fname = screenshot_reference_filename("internal-screenshot-bad", 0);
137 	testlog("Loading bad reference image %s\n", fname);
138 	reference_bad = load_image_from_png(fname);
139 	assert(reference_bad);
140 
141 	/* Test check_images_match() without a clip.
142 	 * We expect this to fail since we use a bad reference image
143 	 */
144 	match = check_images_match(screenshot->image, reference_bad, NULL, NULL);
145 	testlog("Screenshot %s reference image\n", match? "equal to" : "different from");
146 	assert(!match);
147 	pixman_image_unref(reference_bad);
148 
149 	/* Test check_images_match() with clip.
150 	 * Alpha-blending and other effects can cause irrelevant discrepancies, so look only
151 	 * at a small portion of the solid-colored background
152 	 */
153 	clip.x = 100;
154 	clip.y = 100;
155 	clip.width = 100;
156 	clip.height = 100;
157 	testlog("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
158 	match = check_images_match(screenshot->image, reference_good, &clip, NULL);
159 	testlog("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
160 	if (!match) {
161 		diffimg = visualize_image_difference(screenshot->image, reference_good, &clip, NULL);
162 		fname = screenshot_output_filename("internal-screenshot-error", 0);
163 		write_image_as_png(diffimg, fname);
164 		pixman_image_unref(diffimg);
165 	}
166 	pixman_image_unref(reference_good);
167 
168 	/* Test dumping of non-matching images */
169 	if (!match || dump_all_images) {
170 		fname = screenshot_output_filename("internal-screenshot", 0);
171 		write_image_as_png(screenshot->image, fname);
172 	}
173 
174 	buffer_destroy(screenshot);
175 
176 	testlog("Test complete\n");
177 	assert(match);
178 }
179