Add qemu 2.4.0
[kvmfornfv.git] / qemu / pixman / test / composite.c
1 /*
2  * Copyright © 2005 Eric Anholt
3  * Copyright © 2009 Chris Wilson
4  * Copyright © 2010 Soeren Sandmann
5  * Copyright © 2010 Red Hat, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Eric Anholt not be used in
12  * advertising or publicity pertaining to distribution of the software without
13  * specific, written prior permission.  Eric Anholt makes no
14  * representations about the suitability of this software for any purpose.  It
15  * is provided "as is" without express or implied warranty.
16  *
17  * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25 #include <stdio.h>
26 #include <stdlib.h> /* abort() */
27 #include <math.h>
28 #include <time.h>
29 #include "utils.h"
30
31 typedef struct image_t image_t;
32
33 static const color_t colors[] =
34 {
35     { 1.0, 1.0, 1.0, 1.0 },
36     { 1.0, 1.0, 1.0, 0.0 },
37     { 0.0, 0.0, 0.0, 1.0 },
38     { 0.0, 0.0, 0.0, 0.0 },
39     { 1.0, 0.0, 0.0, 1.0 },
40     { 0.0, 1.0, 0.0, 1.0 },
41     { 0.0, 0.0, 1.0, 1.0 },
42     { 0.5, 0.0, 0.0, 0.5 },
43 };
44
45 static uint16_t
46 _color_double_to_short (double d)
47 {
48     uint32_t i;
49
50     i = (uint32_t) (d * 65536);
51     i -= (i >> 16);
52
53     return i;
54 }
55
56 static void
57 compute_pixman_color (const color_t *color,
58                       pixman_color_t *out)
59 {
60     out->red   = _color_double_to_short (color->r);
61     out->green = _color_double_to_short (color->g);
62     out->blue  = _color_double_to_short (color->b);
63     out->alpha = _color_double_to_short (color->a);
64 }
65
66 #define REPEAT 0x01000000
67 #define FLAGS  0xff000000
68
69 static const int sizes[] =
70 {
71     0,
72     1,
73     1 | REPEAT,
74     10
75 };
76
77 static const pixman_format_code_t formats[] =
78 {
79     /* 32 bpp formats */
80     PIXMAN_a8r8g8b8,
81     PIXMAN_x8r8g8b8,
82     PIXMAN_a8b8g8r8,
83     PIXMAN_x8b8g8r8,
84     PIXMAN_b8g8r8a8,
85     PIXMAN_b8g8r8x8,
86     PIXMAN_r8g8b8a8,
87     PIXMAN_r8g8b8x8,
88     PIXMAN_x2r10g10b10,
89     PIXMAN_x2b10g10r10,
90     PIXMAN_a2r10g10b10,
91     PIXMAN_a2b10g10r10,
92     
93     /* sRGB formats */
94     PIXMAN_a8r8g8b8_sRGB,
95
96     /* 24 bpp formats */
97     PIXMAN_r8g8b8,
98     PIXMAN_b8g8r8,
99     PIXMAN_r5g6b5,
100     PIXMAN_b5g6r5,
101
102     /* 16 bpp formats */
103     PIXMAN_x1r5g5b5,
104     PIXMAN_x1b5g5r5,
105     PIXMAN_a1r5g5b5,
106     PIXMAN_a1b5g5r5,
107     PIXMAN_a4b4g4r4,
108     PIXMAN_x4b4g4r4,
109     PIXMAN_a4r4g4b4,
110     PIXMAN_x4r4g4b4,
111
112     /* 8 bpp formats */
113     PIXMAN_a8,
114     PIXMAN_r3g3b2,
115     PIXMAN_b2g3r3,
116     PIXMAN_a2r2g2b2,
117     PIXMAN_a2b2g2r2,
118     PIXMAN_x4a4,
119
120     /* 4 bpp formats */
121     PIXMAN_a4,
122     PIXMAN_r1g2b1,
123     PIXMAN_b1g2r1,
124     PIXMAN_a1r1g1b1,
125     PIXMAN_a1b1g1r1,
126
127     /* 1 bpp formats */
128     PIXMAN_a1,
129 };
130
131 struct image_t
132 {
133     pixman_image_t *image;
134     pixman_format_code_t format;
135     const color_t *color;
136     pixman_repeat_t repeat;
137     int size;
138 };
139
140 static const pixman_op_t operators[] =
141 {
142     PIXMAN_OP_CLEAR,
143     PIXMAN_OP_SRC,
144     PIXMAN_OP_DST,
145     PIXMAN_OP_OVER,
146     PIXMAN_OP_OVER_REVERSE,
147     PIXMAN_OP_IN,
148     PIXMAN_OP_IN_REVERSE,
149     PIXMAN_OP_OUT,
150     PIXMAN_OP_OUT_REVERSE,
151     PIXMAN_OP_ATOP,
152     PIXMAN_OP_ATOP_REVERSE,
153     PIXMAN_OP_XOR,
154     PIXMAN_OP_ADD,
155     PIXMAN_OP_SATURATE,
156
157     PIXMAN_OP_DISJOINT_CLEAR,
158     PIXMAN_OP_DISJOINT_SRC,
159     PIXMAN_OP_DISJOINT_DST,
160     PIXMAN_OP_DISJOINT_OVER,
161     PIXMAN_OP_DISJOINT_OVER_REVERSE,
162     PIXMAN_OP_DISJOINT_IN,
163     PIXMAN_OP_DISJOINT_IN_REVERSE,
164     PIXMAN_OP_DISJOINT_OUT,
165     PIXMAN_OP_DISJOINT_OUT_REVERSE,
166     PIXMAN_OP_DISJOINT_ATOP,
167     PIXMAN_OP_DISJOINT_ATOP_REVERSE,
168     PIXMAN_OP_DISJOINT_XOR,
169
170     PIXMAN_OP_CONJOINT_CLEAR,
171     PIXMAN_OP_CONJOINT_SRC,
172     PIXMAN_OP_CONJOINT_DST,
173     PIXMAN_OP_CONJOINT_OVER,
174     PIXMAN_OP_CONJOINT_OVER_REVERSE,
175     PIXMAN_OP_CONJOINT_IN,
176     PIXMAN_OP_CONJOINT_IN_REVERSE,
177     PIXMAN_OP_CONJOINT_OUT,
178     PIXMAN_OP_CONJOINT_OUT_REVERSE,
179     PIXMAN_OP_CONJOINT_ATOP,
180     PIXMAN_OP_CONJOINT_ATOP_REVERSE,
181     PIXMAN_OP_CONJOINT_XOR,
182 };
183
184 static uint32_t
185 get_value (pixman_image_t *image)
186 {
187     uint32_t value = *(uint32_t *)pixman_image_get_data (image);
188
189 #ifdef WORDS_BIGENDIAN
190     {
191         pixman_format_code_t format = pixman_image_get_format (image);
192         value >>= 8 * sizeof(value) - PIXMAN_FORMAT_BPP (format);
193     }
194 #endif
195
196     return value;
197 }
198
199 static char *
200 describe_image (image_t *info, char *buf)
201 {
202     if (info->size)
203     {
204         sprintf (buf, "%s, %dx%d%s",
205                  format_name (info->format),
206                  info->size, info->size,
207                  info->repeat ? " R" :"");
208     }
209     else
210     {
211         sprintf (buf, "solid");
212     }
213
214     return buf;
215 }
216
217 static char *
218 describe_color (const color_t *color, char *buf)
219 {
220     sprintf (buf, "%.3f %.3f %.3f %.3f",
221              color->r, color->g, color->b, color->a);
222
223     return buf;
224 }
225
226 static pixman_bool_t
227 composite_test (image_t *dst,
228                 pixman_op_t op,
229                 image_t *src,
230                 image_t *mask,
231                 pixman_bool_t component_alpha,
232                 int testno)
233 {
234     color_t expected, tdst, tsrc, tmsk;
235     pixel_checker_t checker;
236
237     if (mask)
238     {
239         pixman_image_set_component_alpha (mask->image, component_alpha);
240
241         pixman_image_composite (op, src->image, mask->image, dst->image,
242                                 0, 0, 0, 0, 0, 0, dst->size, dst->size);
243     }
244     else
245     {
246         pixman_image_composite (op, src->image, NULL, dst->image,
247                                 0, 0,
248                                 0, 0,
249                                 0, 0,
250                                 dst->size, dst->size);
251     }
252
253     tdst = *dst->color;
254     tsrc = *src->color;
255
256     if (mask)
257     {
258         tmsk = *mask->color;
259     }
260
261     /* It turns out that by construction all source, mask etc. colors are
262      * linear because they are made from fills, and fills are always in linear
263      * color space.  However, if they have been converted to bitmaps, we need
264      * to simulate the sRGB approximation to pass the test cases.
265      */
266     if (src->size)
267     {
268         if (PIXMAN_FORMAT_TYPE (src->format) == PIXMAN_TYPE_ARGB_SRGB)
269         {
270             tsrc.r = convert_linear_to_srgb (tsrc.r);
271             tsrc.g = convert_linear_to_srgb (tsrc.g);
272             tsrc.b = convert_linear_to_srgb (tsrc.b);
273             round_color (src->format, &tsrc);
274             tsrc.r = convert_srgb_to_linear (tsrc.r);
275             tsrc.g = convert_srgb_to_linear (tsrc.g);
276             tsrc.b = convert_srgb_to_linear (tsrc.b);
277         }
278         else
279         {
280             round_color (src->format, &tsrc);
281         }
282     }
283
284     if (mask && mask->size)
285     {
286         if (PIXMAN_FORMAT_TYPE (mask->format) == PIXMAN_TYPE_ARGB_SRGB)
287         {
288             tmsk.r = convert_linear_to_srgb (tmsk.r);
289             tmsk.g = convert_linear_to_srgb (tmsk.g);
290             tmsk.b = convert_linear_to_srgb (tmsk.b);
291             round_color (mask->format, &tmsk);
292             tmsk.r = convert_srgb_to_linear (tmsk.r);
293             tmsk.g = convert_srgb_to_linear (tmsk.g);
294             tmsk.b = convert_srgb_to_linear (tmsk.b);
295         }
296         else
297         {
298             round_color (mask->format, &tmsk);
299         }
300     }
301
302     if (mask)
303     {
304         if (component_alpha && PIXMAN_FORMAT_R (mask->format) == 0)
305         {
306             /* Ax component-alpha masks expand alpha into
307              * all color channels.
308              */
309             tmsk.r = tmsk.g = tmsk.b = tmsk.a;
310         }
311     }
312
313     if (PIXMAN_FORMAT_TYPE (dst->format) == PIXMAN_TYPE_ARGB_SRGB)
314     {
315         tdst.r = convert_linear_to_srgb (tdst.r);
316         tdst.g = convert_linear_to_srgb (tdst.g);
317         tdst.b = convert_linear_to_srgb (tdst.b);
318         round_color (dst->format, &tdst);
319         tdst.r = convert_srgb_to_linear (tdst.r);
320         tdst.g = convert_srgb_to_linear (tdst.g);
321         tdst.b = convert_srgb_to_linear (tdst.b);
322     }
323     else
324     {
325         round_color (dst->format, &tdst);
326     }
327
328     do_composite (op,
329                   &tsrc,
330                   mask? &tmsk : NULL,
331                   &tdst,
332                   &expected,
333                   component_alpha);
334
335     pixel_checker_init (&checker, dst->format);
336
337     if (!pixel_checker_check (&checker, get_value (dst->image), &expected))
338     {
339         char buf[40], buf2[40];
340         int a, r, g, b;
341         uint32_t pixel;
342
343         printf ("---- Test %d failed ----\n", testno);
344         printf ("Operator:      %s %s\n",
345                 operator_name (op), component_alpha ? "CA" : "");
346
347         printf ("Source:        %s\n", describe_image (src, buf));
348         if (mask != NULL)
349             printf ("Mask:          %s\n", describe_image (mask, buf));
350
351         printf ("Destination:   %s\n\n", describe_image (dst, buf));
352         printf ("               R     G     B     A         Rounded\n");
353         printf ("Source color:  %s     %s\n",
354                 describe_color (src->color, buf),
355                 describe_color (&tsrc, buf2));
356         if (mask)
357         {
358             printf ("Mask color:    %s     %s\n",
359                     describe_color (mask->color, buf),
360                     describe_color (&tmsk, buf2));
361         }
362         printf ("Dest. color:   %s     %s\n",
363                 describe_color (dst->color, buf),
364                 describe_color (&tdst, buf2));
365
366         pixel = get_value (dst->image);
367
368         printf ("Expected:      %s\n", describe_color (&expected, buf));
369
370         pixel_checker_split_pixel (&checker, pixel, &a, &r, &g, &b);
371
372         printf ("Got:           %5d %5d %5d %5d  [pixel: 0x%08x]\n", r, g, b, a, pixel);
373         pixel_checker_get_min (&checker, &expected, &a, &r, &g, &b);
374         printf ("Min accepted:  %5d %5d %5d %5d\n", r, g, b, a);
375         pixel_checker_get_max (&checker, &expected, &a, &r, &g, &b);
376         printf ("Max accepted:  %5d %5d %5d %5d\n", r, g, b, a);
377
378         return FALSE;
379     }
380     return TRUE;
381 }
382
383 static void
384 image_init (image_t *info,
385             int color,
386             int format,
387             int size)
388 {
389     pixman_color_t fill;
390
391     info->color = &colors[color];
392     compute_pixman_color (info->color, &fill);
393
394     info->format = formats[format];
395     info->size = sizes[size] & ~FLAGS;
396     info->repeat = PIXMAN_REPEAT_NONE;
397
398     if (info->size)
399     {
400         pixman_image_t *solid;
401
402         info->image = pixman_image_create_bits (info->format,
403                                                 info->size, info->size,
404                                                 NULL, 0);
405
406         solid = pixman_image_create_solid_fill (&fill);
407         pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, info->image,
408                                   0, 0, 0, 0, 0, 0, info->size, info->size);
409         pixman_image_unref (solid);
410
411         if (sizes[size] & REPEAT)
412         {
413             pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
414             info->repeat = PIXMAN_REPEAT_NORMAL;
415         }
416     }
417     else
418     {
419         info->image = pixman_image_create_solid_fill (&fill);
420     }
421 }
422
423 static void
424 image_fini (image_t *info)
425 {
426     pixman_image_unref (info->image);
427 }
428
429 static int
430 random_size (void)
431 {
432     return prng_rand_n (ARRAY_LENGTH (sizes));
433 }
434
435 static int
436 random_color (void)
437 {
438     return prng_rand_n (ARRAY_LENGTH (colors));
439 }
440
441 static int
442 random_format (void)
443 {
444     return prng_rand_n (ARRAY_LENGTH (formats));
445 }
446
447 static pixman_bool_t
448 run_test (uint32_t seed)
449 {
450     image_t src, mask, dst;
451     pixman_op_t op;
452     int ca;
453     int ok;
454
455     prng_srand (seed);
456
457     image_init (&dst, random_color(), random_format(), 1);
458     image_init (&src, random_color(), random_format(), random_size());
459     image_init (&mask, random_color(), random_format(), random_size());
460
461     op = operators [prng_rand_n (ARRAY_LENGTH (operators))];
462
463     ca = prng_rand_n (3);
464
465     switch (ca)
466     {
467     case 0:
468         ok = composite_test (&dst, op, &src, NULL, FALSE, seed);
469         break;
470     case 1:
471         ok = composite_test (&dst, op, &src, &mask, FALSE, seed);
472         break;
473     case 2:
474         ok = composite_test (&dst, op, &src, &mask,
475                              mask.size? TRUE : FALSE, seed);
476         break;
477     default:
478         ok = FALSE;
479         break;
480     }
481
482     image_fini (&src);
483     image_fini (&mask);
484     image_fini (&dst);
485
486     return ok;
487 }
488
489 int
490 main (int argc, char **argv)
491 {
492 #define N_TESTS (8 * 1024 * 1024)
493     int result = 0;
494     uint32_t seed;
495     int32_t i;
496
497     if (argc > 1)
498     {
499         char *end;
500
501         i = strtol (argv[1], &end, 0);
502
503         if (end != argv[1])
504         {
505             if (!run_test (i))
506                 return 1;
507             else
508                 return 0;
509         }
510         else
511         {
512             printf ("Usage:\n\n   %s <number>\n\n", argv[0]);
513             return -1;
514         }
515     }
516
517     if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
518         seed = get_random_seed();
519     else
520         seed = 1;
521
522 #ifdef USE_OPENMP
523 #   pragma omp parallel for default(none) shared(result, argv, seed)
524 #endif
525     for (i = 0; i <= N_TESTS; ++i)
526     {
527         if (!result && !run_test (i + seed))
528         {
529             printf ("Test 0x%08X failed.\n", seed + i);
530
531             result = seed + i;
532         }
533     }
534
535     return result;
536 }