Line data Source code
1 : /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 : /*
3 : Copyright (C) 2009 Red Hat, Inc.
4 :
5 : This library is free software; you can redistribute it and/or
6 : modify it under the terms of the GNU Lesser General Public
7 : License as published by the Free Software Foundation; either
8 : version 2.1 of the License, or (at your option) any later version.
9 :
10 : This library is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public
16 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 : */
18 : #include <config.h>
19 :
20 : #include <stdio.h>
21 : #include <string.h>
22 : #include <stdlib.h>
23 : #include <spice/macros.h>
24 :
25 : #include <common/region.h>
26 :
27 700000 : static int slow_region_test(const QRegion *rgn, const QRegion *other_rgn, int query)
28 : {
29 : pixman_region32_t intersection;
30 : int res;
31 :
32 700000 : pixman_region32_init(&intersection);
33 700000 : pixman_region32_intersect(&intersection,
34 : (pixman_region32_t *)rgn,
35 : (pixman_region32_t *)other_rgn);
36 :
37 700000 : res = 0;
38 :
39 1100000 : if (query & REGION_TEST_SHARED &&
40 400000 : pixman_region32_not_empty(&intersection)) {
41 356824 : res |= REGION_TEST_SHARED;
42 : }
43 :
44 1100000 : if (query & REGION_TEST_LEFT_EXCLUSIVE &&
45 400000 : !pixman_region32_equal(&intersection, (pixman_region32_t *)rgn)) {
46 373704 : res |= REGION_TEST_LEFT_EXCLUSIVE;
47 : }
48 :
49 1100000 : if (query & REGION_TEST_RIGHT_EXCLUSIVE &&
50 400000 : !pixman_region32_equal(&intersection, (pixman_region32_t *)other_rgn)) {
51 374408 : res |= REGION_TEST_RIGHT_EXCLUSIVE;
52 : }
53 :
54 700000 : pixman_region32_fini(&intersection);
55 :
56 700000 : return res;
57 : }
58 :
59 :
60 1902195 : static int rect_is_valid(const SpiceRect *r)
61 : {
62 1902195 : if (r->top > r->bottom || r->left > r->right) {
63 0 : return FALSE;
64 : }
65 1902195 : return TRUE;
66 : }
67 :
68 1902195 : static void rect_set(SpiceRect *r, int32_t top, int32_t left, int32_t bottom, int32_t right)
69 : {
70 1902195 : r->top = top;
71 1902195 : r->left = left;
72 1902195 : r->bottom = bottom;
73 1902195 : r->right = right;
74 1902195 : g_assert_true(rect_is_valid(r));
75 1902195 : }
76 :
77 200000 : static void random_region(QRegion *reg)
78 : {
79 : int i;
80 : int num_rects;
81 : int x, y, w, h;
82 : SpiceRect _r;
83 200000 : SpiceRect *r = &_r;
84 :
85 200000 : region_clear(reg);
86 :
87 200000 : num_rects = rand() % 20;
88 2102181 : for (i = 0; i < num_rects; i++) {
89 1902181 : x = rand()%100;
90 1902181 : y = rand()%100;
91 1902181 : w = rand()%100;
92 1902181 : h = rand()%100;
93 1902181 : rect_set(r,
94 : x, y,
95 : x+w, y+h);
96 1902181 : region_add(reg, r);
97 : }
98 200000 : }
99 :
100 17 : static void test(const QRegion *r1, const QRegion *r2, int *expected)
101 : {
102 17 : g_debug("r1 is_empty %s [%s]",
103 : region_is_empty(r1) ? "TRUE" : "FALSE",
104 : (region_is_empty(r1) == *expected) ? "OK" : "ERR");
105 17 : g_assert_cmpint(region_is_empty(r1), ==, *expected);
106 17 : expected++;
107 17 : g_debug("r2 is_empty %s [%s]",
108 : region_is_empty(r2) ? "TRUE" : "FALSE",
109 : (region_is_empty(r2) == *expected) ? "OK" : "ERR");
110 17 : g_assert_cmpint(region_is_empty(r2), ==, *expected);
111 17 : expected++;
112 17 : g_debug("is_equal %s [%s]",
113 : region_is_equal(r1, r2) ? "TRUE" : "FALSE",
114 : (region_is_equal(r1, r2) == *expected) ? "OK" : "ERR");
115 17 : g_assert_cmpint(region_is_equal(r1, r2), ==, *expected);
116 17 : expected++;
117 17 : g_debug("intersects %s [%s]",
118 : region_intersects(r1, r2) ? "TRUE" : "FALSE",
119 : (region_intersects(r1, r2) == *expected) ? "OK" : "ERR");
120 17 : g_assert_cmpint(region_intersects(r1, r2), ==, *expected);
121 17 : expected++;
122 17 : g_debug("contains %s [%s]",
123 : region_contains(r1, r2) ? "TRUE" : "FALSE",
124 : (region_contains(r1, r2) == *expected) ? "OK" : "ERR");
125 17 : g_assert_cmpint(region_contains(r1, r2), ==, *expected);
126 17 : expected++;
127 17 : }
128 :
129 : enum {
130 : EXPECT_R1_EMPTY,
131 : EXPECT_R2_EMPTY,
132 : EXPECT_EQUAL,
133 : EXPECT_SECT,
134 : EXPECT_CONT,
135 : };
136 :
137 1 : static void test_region(void)
138 : {
139 : QRegion _r1, _r2, _r3;
140 1 : QRegion *r1 = &_r1;
141 1 : QRegion *r2 = &_r2;
142 1 : QRegion *r3 = &_r3;
143 : SpiceRect _r;
144 1 : SpiceRect *r = &_r;
145 : int expected[5];
146 : int i, j;
147 :
148 1 : region_init(r1);
149 1 : region_init(r2);
150 :
151 1 : g_debug("dump r1 empty rgn [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
152 : //region_dump(r1, "");
153 1 : expected[EXPECT_R1_EMPTY] = TRUE;
154 1 : expected[EXPECT_R2_EMPTY] = TRUE;
155 1 : expected[EXPECT_EQUAL] = TRUE;
156 1 : expected[EXPECT_SECT] = FALSE;
157 1 : expected[EXPECT_CONT] = TRUE;
158 1 : test(r1, r2, expected);
159 1 : g_debug("\n");
160 :
161 1 : region_clone(r3, r1);
162 1 : g_debug("dump r3 clone rgn [%s]", region_is_valid(r3) ? "VALID" : "INVALID");
163 : //region_dump(r3, "");
164 1 : expected[EXPECT_R1_EMPTY] = TRUE;
165 1 : expected[EXPECT_R2_EMPTY] = TRUE;
166 1 : expected[EXPECT_EQUAL] = TRUE;
167 1 : expected[EXPECT_SECT] = FALSE;
168 1 : expected[EXPECT_CONT] = TRUE;
169 1 : test(r1, r3, expected);
170 1 : region_destroy(r3);
171 1 : g_debug("\n");
172 :
173 1 : rect_set(r, 0, 0, 100, 100);
174 1 : region_add(r1, r);
175 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
176 : //region_dump(r1, "");
177 1 : expected[EXPECT_R1_EMPTY] = FALSE;
178 1 : expected[EXPECT_R2_EMPTY] = TRUE;
179 1 : expected[EXPECT_EQUAL] = FALSE;
180 1 : expected[EXPECT_SECT] = FALSE;
181 1 : expected[EXPECT_CONT] = TRUE;
182 1 : test(r1, r2, expected);
183 1 : g_debug("\n");
184 :
185 1 : region_clear(r1);
186 1 : rect_set(r, 0, 0, 0, 0);
187 1 : region_add(r1, r);
188 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
189 : //region_dump(r1, "");
190 1 : expected[EXPECT_R1_EMPTY] = TRUE;
191 1 : expected[EXPECT_R2_EMPTY] = TRUE;
192 1 : expected[EXPECT_EQUAL] = TRUE;
193 1 : expected[EXPECT_SECT] = FALSE;
194 1 : expected[EXPECT_CONT] = TRUE;
195 1 : test(r1, r2, expected);
196 1 : g_debug("\n");
197 :
198 1 : rect_set(r, -100, -100, 0, 0);
199 1 : region_add(r1, r);
200 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
201 : //region_dump(r1, "");
202 1 : expected[EXPECT_R1_EMPTY] = FALSE;
203 1 : expected[EXPECT_R2_EMPTY] = TRUE;
204 1 : expected[EXPECT_EQUAL] = FALSE;
205 1 : expected[EXPECT_SECT] = FALSE;
206 1 : expected[EXPECT_CONT] = TRUE;
207 1 : test(r1, r2, expected);
208 1 : g_debug("\n");
209 :
210 1 : region_clear(r1);
211 1 : rect_set(r, -100, -100, 100, 100);
212 1 : region_add(r1, r);
213 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
214 : //region_dump(r1, "");
215 1 : expected[EXPECT_R1_EMPTY] = FALSE;
216 1 : expected[EXPECT_R2_EMPTY] = TRUE;
217 1 : expected[EXPECT_EQUAL] = FALSE;
218 1 : expected[EXPECT_SECT] = FALSE;
219 1 : expected[EXPECT_CONT] = TRUE;
220 1 : test(r1, r2, expected);
221 1 : g_debug("\n");
222 :
223 :
224 1 : region_clear(r1);
225 1 : region_clear(r2);
226 :
227 1 : rect_set(r, 100, 100, 200, 200);
228 1 : region_add(r1, r);
229 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
230 : //region_dump(r1, "");
231 1 : expected[EXPECT_R1_EMPTY] = FALSE;
232 1 : expected[EXPECT_R2_EMPTY] = TRUE;
233 1 : expected[EXPECT_EQUAL] = FALSE;
234 1 : expected[EXPECT_SECT] = FALSE;
235 1 : expected[EXPECT_CONT] = TRUE;
236 1 : test(r1, r2, expected);
237 1 : g_debug("\n");
238 :
239 1 : rect_set(r, 300, 300, 400, 400);
240 1 : region_add(r1, r);
241 1 : g_debug("dump r1 [%s]", region_is_valid(r1) ? "VALID" : "INVALID");
242 : //region_dump(r1, "");
243 1 : expected[EXPECT_R1_EMPTY] = FALSE;
244 1 : expected[EXPECT_R2_EMPTY] = TRUE;
245 1 : expected[EXPECT_EQUAL] = FALSE;
246 1 : expected[EXPECT_SECT] = FALSE;
247 1 : expected[EXPECT_CONT] = TRUE;
248 1 : test(r1, r2, expected);
249 1 : g_debug("\n");
250 :
251 1 : rect_set(r, 500, 500, 600, 600);
252 1 : region_add(r2, r);
253 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
254 : //region_dump(r2, "");
255 1 : expected[EXPECT_R1_EMPTY] = FALSE;
256 1 : expected[EXPECT_R2_EMPTY] = FALSE;
257 1 : expected[EXPECT_EQUAL] = FALSE;
258 1 : expected[EXPECT_SECT] = FALSE;
259 1 : expected[EXPECT_CONT] = FALSE;
260 1 : test(r1, r2, expected);
261 1 : g_debug("\n");
262 :
263 1 : region_clear(r2);
264 :
265 1 : rect_set(r, 100, 100, 200, 200);
266 1 : region_add(r2, r);
267 1 : rect_set(r, 300, 300, 400, 400);
268 1 : region_add(r2, r);
269 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
270 : //region_dump(r2, "");
271 1 : expected[EXPECT_R1_EMPTY] = FALSE;
272 1 : expected[EXPECT_R2_EMPTY] = FALSE;
273 1 : expected[EXPECT_EQUAL] = TRUE;
274 1 : expected[EXPECT_SECT] = TRUE;
275 1 : expected[EXPECT_CONT] = TRUE;
276 1 : test(r1, r2, expected);
277 1 : g_debug("\n");
278 :
279 1 : region_clear(r2);
280 :
281 1 : rect_set(r, 100, 100, 200, 200);
282 1 : region_add(r2, r);
283 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
284 : //region_dump(r2, "");
285 1 : expected[EXPECT_R1_EMPTY] = FALSE;
286 1 : expected[EXPECT_R2_EMPTY] = FALSE;
287 1 : expected[EXPECT_EQUAL] = FALSE;
288 1 : expected[EXPECT_SECT] = TRUE;
289 1 : expected[EXPECT_CONT] = TRUE;
290 1 : test(r1, r2, expected);
291 1 : g_debug("\n");
292 :
293 1 : region_clear(r2);
294 :
295 1 : rect_set(r, -2000, -2000, -1000, -1000);
296 1 : region_add(r2, r);
297 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
298 : //region_dump(r2, "");
299 1 : expected[EXPECT_R1_EMPTY] = FALSE;
300 1 : expected[EXPECT_R2_EMPTY] = FALSE;
301 1 : expected[EXPECT_EQUAL] = FALSE;
302 1 : expected[EXPECT_SECT] = FALSE;
303 1 : expected[EXPECT_CONT] = FALSE;
304 1 : test(r1, r2, expected);
305 1 : g_debug("\n");
306 :
307 1 : region_clear(r2);
308 :
309 1 : rect_set(r, -2000, -2000, 1000, 1000);
310 1 : region_add(r2, r);
311 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
312 : //region_dump(r2, "");
313 1 : expected[EXPECT_R1_EMPTY] = FALSE;
314 1 : expected[EXPECT_R2_EMPTY] = FALSE;
315 1 : expected[EXPECT_EQUAL] = FALSE;
316 1 : expected[EXPECT_SECT] = TRUE;
317 1 : expected[EXPECT_CONT] = FALSE;
318 1 : test(r1, r2, expected);
319 1 : g_debug("\n");
320 :
321 1 : region_clear(r2);
322 :
323 1 : rect_set(r, 150, 150, 175, 175);
324 1 : region_add(r2, r);
325 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
326 : //region_dump(r2, "");
327 1 : expected[EXPECT_R1_EMPTY] = FALSE;
328 1 : expected[EXPECT_R2_EMPTY] = FALSE;
329 1 : expected[EXPECT_EQUAL] = FALSE;
330 1 : expected[EXPECT_SECT] = TRUE;
331 1 : expected[EXPECT_CONT] = TRUE;
332 1 : test(r1, r2, expected);
333 1 : g_debug("\n");
334 :
335 1 : region_clear(r2);
336 :
337 1 : rect_set(r, 150, 150, 350, 350);
338 1 : region_add(r2, r);
339 1 : g_debug("dump r2 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
340 : //region_dump(r2, "");
341 1 : expected[EXPECT_R1_EMPTY] = FALSE;
342 1 : expected[EXPECT_R2_EMPTY] = FALSE;
343 1 : expected[EXPECT_EQUAL] = FALSE;
344 1 : expected[EXPECT_SECT] = TRUE;
345 1 : expected[EXPECT_CONT] = FALSE;
346 1 : test(r1, r2, expected);
347 1 : g_debug("\n");
348 :
349 1 : region_and(r2, r1);
350 1 : g_debug("dump r2 and r1 [%s]", region_is_valid(r2) ? "VALID" : "INVALID");
351 : //region_dump(r2, "");
352 1 : expected[EXPECT_R1_EMPTY] = FALSE;
353 1 : expected[EXPECT_R2_EMPTY] = FALSE;
354 1 : expected[EXPECT_EQUAL] = FALSE;
355 1 : expected[EXPECT_SECT] = TRUE;
356 1 : expected[EXPECT_CONT] = FALSE;
357 1 : test(r2, r1, expected);
358 1 : g_debug("\n");
359 :
360 :
361 1 : region_clone(r3, r1);
362 1 : g_debug("dump r3 clone rgn [%s]", region_is_valid(r3) ? "VALID" : "INVALID");
363 : //region_dump(r3, "");
364 1 : expected[EXPECT_R1_EMPTY] = FALSE;
365 1 : expected[EXPECT_R2_EMPTY] = FALSE;
366 1 : expected[EXPECT_EQUAL] = TRUE;
367 1 : expected[EXPECT_SECT] = TRUE;
368 1 : expected[EXPECT_CONT] = TRUE;
369 1 : test(r1, r3, expected);
370 1 : g_debug("\n");
371 :
372 1 : j = 0;
373 100001 : for (i = 0; i < 100000; i++) {
374 : int res1, res2, test;
375 100000 : int tests[] = {
376 : REGION_TEST_LEFT_EXCLUSIVE,
377 : REGION_TEST_RIGHT_EXCLUSIVE,
378 : REGION_TEST_SHARED,
379 : REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE,
380 : REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_SHARED,
381 : REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED,
382 : REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED
383 : };
384 :
385 100000 : random_region(r1);
386 100000 : random_region(r2);
387 :
388 800000 : for (test = 0; test < 7; test++) {
389 700000 : res1 = region_test(r1, r2, tests[test]);
390 700000 : res2 = slow_region_test(r1, r2, tests[test]);
391 700000 : if (res1 != res2) {
392 0 : g_warning("Error in region_test %d, got %d, expected %d, query=%d",
393 : j, res1, res2, tests[test]);
394 0 : g_debug("r1:");
395 0 : region_dump(r1, "");
396 0 : g_debug("r2:");
397 0 : region_dump(r2, "");
398 : }
399 700000 : g_assert_cmpint(res1, ==, res2);
400 700000 : j++;
401 : }
402 : }
403 :
404 1 : region_destroy(r3);
405 1 : region_destroy(r1);
406 1 : region_destroy(r2);
407 1 : }
408 :
409 1 : int main(int argc, char **argv)
410 : {
411 1 : g_test_init(&argc, &argv, NULL);
412 :
413 1 : g_test_add_func("/spice-common/region", test_region);
414 :
415 1 : return g_test_run();
416 : }
|