take two
[profile/ivi/xorg-x11-drv-intel.git] / test / render-trapezoid.c
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 #include <X11/Xutil.h> /* for XDestroyImage */
6 #include <pixman.h> /* for pixman blt functions */
7
8 #include "test.h"
9
10 enum trapezoid {
11         RECT_ALIGN,
12         RECT_UNALIGN,
13         GENERAL
14 };
15
16 static const uint8_t ops[] = {
17         PictOpClear,
18         PictOpSrc,
19         PictOpDst,
20 };
21
22 static XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
23 {
24         switch (mask) {
25         default:
26         case MASK_NONE: return NULL;
27         case MASK_A1: return  XRenderFindStandardFormat(dpy, PictStandardA1);
28         case MASK_A8: return  XRenderFindStandardFormat(dpy, PictStandardA8);
29         }
30 }
31
32 static const char *mask_name(enum mask mask)
33 {
34         switch (mask) {
35         default:
36         case MASK_NONE: return "none";
37         case MASK_A1: return "a1";
38         case MASK_A8: return "a8";
39         }
40 }
41
42 static const char *trapezoid_name(enum trapezoid trapezoid)
43 {
44         switch (trapezoid) {
45         default:
46         case RECT_ALIGN: return "pixel-aligned";
47         case RECT_UNALIGN: return "rectilinear";
48         case GENERAL: return "general";
49         }
50 }
51
52 static void fill_rect(struct test_display *dpy, Picture p, uint8_t op,
53                       int x, int y, int w, int h,
54                       int dx, int dy, enum mask mask,
55                       uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
56 {
57         XRenderColor render_color;
58         XTrapezoid trap;
59         Picture src;
60
61         render_color.red   = red * alpha;
62         render_color.green = green * alpha;
63         render_color.blue  = blue * alpha;
64         render_color.alpha = alpha << 8;
65
66         trap.left.p1.x = trap.left.p2.x = (x << 16) + dx;
67         trap.top = trap.left.p1.y = trap.right.p1.y = (y << 16) + dy;
68         trap.right.p1.x = trap.right.p2.x = ((x + w) << 16) + dx;
69         trap.bottom = trap.left.p2.y = trap.right.p2.y = ((y + h) << 16) + dy;
70
71         src = XRenderCreateSolidFill(dpy->dpy, &render_color);
72         XRenderCompositeTrapezoids(dpy->dpy,
73                                    op, src, p, mask_format(dpy->dpy, mask),
74                                    0, 0, &trap, 1);
75         XRenderFreePicture(dpy->dpy, src);
76 }
77
78 static void pixel_tests(struct test *t, int reps, int sets, enum target target)
79 {
80         struct test_target tt;
81         XImage image;
82         uint32_t *cells = malloc(t->real.width*t->real.height*4);
83         struct {
84                 uint16_t x, y;
85         } *pixels = malloc(reps*sizeof(*pixels));
86         int r, s;
87
88         printf("Testing setting of single pixels (%s): ", test_target_name(target));
89         fflush(stdout);
90
91         test_target_create_render(&t->real, target, &tt);
92
93         for (s = 0; s < sets; s++) {
94                 for (r = 0; r < reps; r++) {
95                         int x = rand() % (tt.width - 1);
96                         int y = rand() % (tt.height - 1);
97                         int red = rand() % 0xff;
98                         int green = rand() % 0xff;
99                         int blue = rand() % 0xff;
100                         int alpha = rand() % 0xff;
101
102                         fill_rect(&t->real, tt.picture, PictOpSrc,
103                                   x, y, 1, 1,
104                                   0, 0, MASK_NONE,
105                                   red, green, blue, alpha);
106
107                         pixels[r].x = x;
108                         pixels[r].y = y;
109                         cells[y*t->real.width+x] = color(red, green, blue, alpha);
110                 }
111
112                 test_init_image(&image, &t->real.shm, tt.format, 1, 1);
113
114                 for (r = 0; r < reps; r++) {
115                         uint32_t result;
116                         uint32_t x = pixels[r].x;
117                         uint32_t y = pixels[r].y;
118
119                         XShmGetImage(t->real.dpy, tt.draw, &image,
120                                      x, y, AllPlanes);
121
122                         result = *(uint32_t *)image.data;
123                         if (!pixel_equal(image.depth, result,
124                                          cells[y*tt.width+x])) {
125                                 uint32_t mask = depth_mask(image.depth);
126                                 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n",
127                                     x, y,
128                                     cells[y*tt.width+x] & mask,
129                                     cells[y*tt.width+x],
130                                     result & mask,
131                                     result);
132                         }
133                 }
134         }
135         printf("passed [%d iterations x %d]\n", reps, sets);
136
137         test_target_destroy_render(&t->real, &tt);
138
139         free(pixels);
140         free(cells);
141 }
142
143 static void clear(struct test_display *dpy, struct test_target *tt)
144 {
145         XRenderColor render_color = {0};
146         XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
147                              0, 0, tt->width, tt->height);
148 }
149
150 static void area_tests(struct test *t, int reps, int sets, enum target target)
151 {
152         struct test_target tt;
153         XImage image;
154         uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height);
155         int r, s, x, y;
156
157         printf("Testing area sets (%s): ", test_target_name(target));
158         fflush(stdout);
159
160         test_target_create_render(&t->real, target, &tt);
161         clear(&t->real, &tt);
162
163         test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height);
164
165         for (s = 0; s < sets; s++) {
166                 for (r = 0; r < reps; r++) {
167                         int w = rand() % tt.width;
168                         int h = rand() % tt.height;
169                         int red = rand() % 0xff;
170                         int green = rand() % 0xff;
171                         int blue = rand() % 0xff;
172                         int alpha = rand() % 0xff;
173
174                         x = rand() % (2*tt.width) - tt.width;
175                         y = rand() % (2*tt.height) - tt.height;
176
177                         fill_rect(&t->real, tt.picture, PictOpSrc,
178                                   x, y, w, h,
179                                   0, 0, MASK_NONE,
180                                   red, green, blue, alpha);
181
182                         if (x < 0)
183                                 w += x, x = 0;
184                         if (y < 0)
185                                 h += y, y = 0;
186                         if (x >= tt.width || y >= tt.height)
187                                 continue;
188
189                         if (x + w > tt.width)
190                                 w = tt.width - x;
191                         if (y + h > tt.height)
192                                 h = tt.height - y;
193                         if (w <= 0 || h <= 0)
194                                 continue;
195
196                         pixman_fill(cells, tt.width, 32, x, y, w, h,
197                                     color(red, green, blue, alpha));
198                 }
199
200                 XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes);
201
202                 for (y = 0; y < tt.height; y++) {
203                         for (x = 0; x < tt.width; x++) {
204                                 uint32_t result =
205                                         *(uint32_t *)(image.data +
206                                                       y*image.bytes_per_line +
207                                                       image.bits_per_pixel*x/8);
208                                 if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) {
209                                         uint32_t mask = depth_mask(image.depth);
210
211                                         die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n",
212                                             x, y,
213                                             cells[y*tt.width+x] & mask,
214                                             cells[y*tt.width+x],
215                                             result & mask,
216                                             result);
217                                 }
218                         }
219                 }
220         }
221
222         printf("passed [%d iterations x %d]\n", reps, sets);
223
224         test_target_destroy_render(&t->real, &tt);
225         free(cells);
226 }
227
228 static void rect_tests(struct test *t,
229                        int dx, int dy,
230                        enum mask mask,
231                        int reps, int sets,
232                        enum target target)
233 {
234         struct test_target real, ref;
235         int r, s;
236
237         printf("Testing area fills (offset %dx%d, mask %s) (%s): ",
238                dx, dy, mask_name(mask), test_target_name(target));
239         fflush(stdout);
240
241         test_target_create_render(&t->real, target, &real);
242         clear(&t->real, &real);
243
244         test_target_create_render(&t->ref, target, &ref);
245         clear(&t->ref, &ref);
246
247         for (s = 0; s < sets; s++) {
248                 for (r = 0; r < reps; r++) {
249                         int x = rand() % (2*real.width) - real.width;
250                         int y = rand() % (2*real.height) - real.height;
251                         int w = rand() % real.width;
252                         int h = rand() % real.height;
253                         int op = ops[rand() % sizeof(ops)];
254                         int red = rand() % 0xff;
255                         int green = rand() % 0xff;
256                         int blue = rand() % 0xff;
257                         int alpha = rand() % 0xff;
258
259                         fill_rect(&t->real, real.picture, op,
260                                   x, y, w, h, dx, dy, mask,
261                                   red, green, blue, alpha);
262                         fill_rect(&t->ref, ref.picture, op,
263                                   x, y, w, h, dx, dy, mask,
264                                   red, green, blue, alpha);
265                 }
266
267                 test_compare(t,
268                              real.draw, real.format,
269                              ref.draw, ref.format,
270                              0, 0, real.width, real.height,
271                              "");
272         }
273
274         printf("passed [%d iterations x %d]\n", reps, sets);
275
276         test_target_destroy_render(&t->real, &real);
277         test_target_destroy_render(&t->ref, &ref);
278 }
279
280 static void random_trapezoid(XTrapezoid *trap, enum trapezoid trapezoid,
281                              int x1, int y1, int x2, int y2)
282 {
283         switch (trapezoid) {
284         case RECT_ALIGN:
285                 x1 = x1 + rand() % (x2 - x1);
286                 x2 = x1 + rand() % (x2 - x1);
287                 y1 = y1 + rand() % (y2 - y1);
288                 y2 = y1 + rand() % (y2 - y1);
289
290                 trap->left.p1.x = trap->left.p2.x = x1 << 16;
291                 trap->top = trap->left.p1.y = trap->right.p1.y = y1 << 16;
292                 trap->right.p1.x = trap->right.p2.x = x2 << 16;
293                 trap->bottom = trap->left.p2.y = trap->right.p2.y = y2 << 16;
294                 break;
295
296         case RECT_UNALIGN:
297                 x1 <<= 16; x2 <<= 16;
298                 y1 <<= 16; y2 <<= 16;
299
300                 x1 = x1 + rand() % (x2 - x1);
301                 x2 = x1 + rand() % (x2 - x1);
302                 y1 = y1 + rand() % (y2 - y1);
303                 y2 = y1 + rand() % (y2 - y1);
304
305                 trap->left.p1.x = trap->left.p2.x = x1;
306                 trap->top = trap->left.p1.y = trap->right.p1.y = y1;
307                 trap->right.p1.x = trap->right.p2.x = x2;
308                 trap->bottom = trap->left.p2.y = trap->right.p2.y = y2;
309                 break;
310
311         case GENERAL:
312                 x1 <<= 16; x2 <<= 16;
313                 y1 <<= 16; y2 <<= 16;
314
315                 trap->top = y1 + rand() % (y2 - y1);
316                 trap->bottom = y1 + rand() % (y2 - y1);
317
318                 trap->left.p1.x = x1 + rand() % (x2 - x1);
319                 trap->left.p2.x = x1 + rand() % (x2 - x1);
320
321                 trap->right.p1.x = x1 + rand() % (x2 - x1);
322                 trap->right.p2.x = x1 + rand() % (x2 - x1);
323                 break;
324
325         }
326 }
327
328 static void trap_tests(struct test *t,
329                        enum mask mask,
330                        enum trapezoid trapezoid,
331                        int reps, int sets,
332                        enum target target)
333 {
334         struct test_target real, ref;
335         XTrapezoid *traps;
336         int max_traps = 65536;
337         int r, s, n;
338
339         traps = malloc(sizeof(*traps) * max_traps);
340         if (traps == NULL)
341                 return;
342
343         printf("Testing trapezoids (%s with mask %s) (%s): ",
344                trapezoid_name(trapezoid),
345                mask_name(mask),
346                test_target_name(target));
347         fflush(stdout);
348
349         test_target_create_render(&t->real, target, &real);
350         clear(&t->real, &real);
351
352         test_target_create_render(&t->ref, target, &ref);
353         clear(&t->ref, &ref);
354
355         for (s = 0; s < sets; s++) {
356                 for (r = 0; r < reps; r++) {
357                         XRenderColor render_color;
358                         int op = ops[rand() % sizeof(ops)];
359                         int red = rand() % 0xff;
360                         int green = rand() % 0xff;
361                         int blue = rand() % 0xff;
362                         int alpha = rand() % 0xff;
363                         int num_traps = rand() % max_traps;
364                         Picture src;
365
366                         for (n = 0; n < num_traps; n++)
367                                 random_trapezoid(&traps[n], 0,
368                                                  0, 0, real.width, real.height);
369
370                         render_color.red   = red * alpha;
371                         render_color.green = green * alpha;
372                         render_color.blue  = blue * alpha;
373                         render_color.alpha = alpha << 8;
374
375                         src = XRenderCreateSolidFill(t->real.dpy,
376                                                      &render_color);
377                         XRenderCompositeTrapezoids(t->real.dpy,
378                                                    op, src, real.picture,
379                                                    mask_format(t->real.dpy, mask),
380                                                    0, 0, traps, num_traps);
381                         XRenderFreePicture(t->real.dpy, src);
382
383                         src = XRenderCreateSolidFill(t->ref.dpy,
384                                                      &render_color);
385                         XRenderCompositeTrapezoids(t->ref.dpy,
386                                                    op, src, ref.picture,
387                                                    mask_format(t->ref.dpy, mask),
388                                                    0, 0, traps, num_traps);
389                         XRenderFreePicture(t->ref.dpy, src);
390                 }
391
392                 test_compare(t,
393                              real.draw, real.format,
394                              ref.draw, ref.format,
395                              0, 0, real.width, real.height,
396                              "");
397         }
398
399         printf("passed [%d iterations x %d]\n", reps, sets);
400
401         test_target_destroy_render(&t->real, &real);
402         test_target_destroy_render(&t->ref, &ref);
403         free(traps);
404 }
405
406 int main(int argc, char **argv)
407 {
408         struct test test;
409         int i, dx, dy;
410         enum target target;
411         enum mask mask;
412         enum trapezoid trapezoid;
413
414         test_init(&test, argc, argv);
415
416         for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
417                 int reps = 1 << i;
418                 int sets = 1 << (12 - i);
419
420                 if (sets < 2)
421                         sets = 2;
422
423                 for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
424                         pixel_tests(&test, reps, sets, target);
425                         area_tests(&test, reps, sets, target);
426                         for (dy = 0; dy < 1 << 16; dy += 1 << 14)
427                                 for (dx = 0; dx < 1 << 16; dx += 1 << 14)
428                                         for (mask = MASK_NONE; mask <= MASK_A8; mask++)
429                                                 rect_tests(&test, dx, dy, mask, reps, sets, target);
430                         for (trapezoid = RECT_ALIGN; trapezoid <= GENERAL; trapezoid++)
431                                 trap_tests(&test, mask, trapezoid, reps, sets, target);
432                 }
433         }
434
435         return 0;
436 }