1 /*
2 * Copyright © 2015 RISC OS Open Ltd
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The copyright holders make no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
19 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
20 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 * SOFTWARE.
22 *
23 * Author: Ben Avison (bavison@riscosopen.org)
24 *
25 */
26
27 #include "utils.h"
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <stdio.h>
31
32 #define WIDTH 32
33 #define HEIGHT 32
34
35 static const pixman_op_t op_list[] = {
36 PIXMAN_OP_SRC,
37 PIXMAN_OP_OVER,
38 PIXMAN_OP_ADD,
39 PIXMAN_OP_CLEAR,
40 PIXMAN_OP_SRC,
41 PIXMAN_OP_DST,
42 PIXMAN_OP_OVER,
43 PIXMAN_OP_OVER_REVERSE,
44 PIXMAN_OP_IN,
45 PIXMAN_OP_IN_REVERSE,
46 PIXMAN_OP_OUT,
47 PIXMAN_OP_OUT_REVERSE,
48 PIXMAN_OP_ATOP,
49 PIXMAN_OP_ATOP_REVERSE,
50 PIXMAN_OP_XOR,
51 PIXMAN_OP_ADD,
52 PIXMAN_OP_MULTIPLY,
53 PIXMAN_OP_SCREEN,
54 PIXMAN_OP_OVERLAY,
55 PIXMAN_OP_DARKEN,
56 PIXMAN_OP_LIGHTEN,
57 PIXMAN_OP_HARD_LIGHT,
58 PIXMAN_OP_DIFFERENCE,
59 PIXMAN_OP_EXCLUSION,
60 #if 0 /* these use floating point math and are not always bitexact on different platforms */
61 PIXMAN_OP_SATURATE,
62 PIXMAN_OP_DISJOINT_CLEAR,
63 PIXMAN_OP_DISJOINT_SRC,
64 PIXMAN_OP_DISJOINT_DST,
65 PIXMAN_OP_DISJOINT_OVER,
66 PIXMAN_OP_DISJOINT_OVER_REVERSE,
67 PIXMAN_OP_DISJOINT_IN,
68 PIXMAN_OP_DISJOINT_IN_REVERSE,
69 PIXMAN_OP_DISJOINT_OUT,
70 PIXMAN_OP_DISJOINT_OUT_REVERSE,
71 PIXMAN_OP_DISJOINT_ATOP,
72 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
73 PIXMAN_OP_DISJOINT_XOR,
74 PIXMAN_OP_CONJOINT_CLEAR,
75 PIXMAN_OP_CONJOINT_SRC,
76 PIXMAN_OP_CONJOINT_DST,
77 PIXMAN_OP_CONJOINT_OVER,
78 PIXMAN_OP_CONJOINT_OVER_REVERSE,
79 PIXMAN_OP_CONJOINT_IN,
80 PIXMAN_OP_CONJOINT_IN_REVERSE,
81 PIXMAN_OP_CONJOINT_OUT,
82 PIXMAN_OP_CONJOINT_OUT_REVERSE,
83 PIXMAN_OP_CONJOINT_ATOP,
84 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
85 PIXMAN_OP_CONJOINT_XOR,
86 PIXMAN_OP_COLOR_DODGE,
87 PIXMAN_OP_COLOR_BURN,
88 PIXMAN_OP_SOFT_LIGHT,
89 PIXMAN_OP_HSL_HUE,
90 PIXMAN_OP_HSL_SATURATION,
91 PIXMAN_OP_HSL_COLOR,
92 PIXMAN_OP_HSL_LUMINOSITY,
93 #endif
94 };
95
96 /* The first eight format in the list are by far the most widely
97 * used formats, so we test those more than the others
98 */
99 #define N_MOST_LIKELY_FORMATS 8
100
101 static const pixman_format_code_t img_fmt_list[] = {
102 PIXMAN_a8r8g8b8,
103 PIXMAN_a8b8g8r8,
104 PIXMAN_x8r8g8b8,
105 PIXMAN_x8b8g8r8,
106 PIXMAN_r5g6b5,
107 PIXMAN_b5g6r5,
108 PIXMAN_a8,
109 PIXMAN_a1,
110 PIXMAN_r3g3b2,
111 PIXMAN_b8g8r8a8,
112 PIXMAN_b8g8r8x8,
113 PIXMAN_r8g8b8a8,
114 PIXMAN_r8g8b8x8,
115 PIXMAN_x14r6g6b6,
116 PIXMAN_r8g8b8,
117 PIXMAN_b8g8r8,
118 #if 0 /* These are going to use floating point in the near future */
119 PIXMAN_x2r10g10b10,
120 PIXMAN_a2r10g10b10,
121 PIXMAN_x2b10g10r10,
122 PIXMAN_a2b10g10r10,
123 #endif
124 PIXMAN_a1r5g5b5,
125 PIXMAN_x1r5g5b5,
126 PIXMAN_a1b5g5r5,
127 PIXMAN_x1b5g5r5,
128 PIXMAN_a4r4g4b4,
129 PIXMAN_x4r4g4b4,
130 PIXMAN_a4b4g4r4,
131 PIXMAN_x4b4g4r4,
132 PIXMAN_r3g3b2,
133 PIXMAN_b2g3r3,
134 PIXMAN_a2r2g2b2,
135 PIXMAN_a2b2g2r2,
136 PIXMAN_c8,
137 PIXMAN_g8,
138 PIXMAN_x4c4,
139 PIXMAN_x4g4,
140 PIXMAN_c4,
141 PIXMAN_g4,
142 PIXMAN_g1,
143 PIXMAN_x4a4,
144 PIXMAN_a4,
145 PIXMAN_r1g2b1,
146 PIXMAN_b1g2r1,
147 PIXMAN_a1r1g1b1,
148 PIXMAN_a1b1g1r1,
149 PIXMAN_null
150 };
151
152 static const pixman_format_code_t mask_fmt_list[] = {
153 PIXMAN_a8r8g8b8,
154 PIXMAN_a8,
155 PIXMAN_a4,
156 PIXMAN_a1,
157 PIXMAN_null
158 };
159
160 static pixman_indexed_t rgb_palette[9];
161 static pixman_indexed_t y_palette[9];
162
163 static pixman_format_code_t
random_format(const pixman_format_code_t * allowed_formats)164 random_format (const pixman_format_code_t *allowed_formats)
165 {
166 int n = 0;
167
168 while (allowed_formats[n] != PIXMAN_null)
169 n++;
170
171 if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0)
172 n = N_MOST_LIKELY_FORMATS;
173
174 return allowed_formats[prng_rand_n (n)];
175 }
176
177 static pixman_image_t *
create_multi_pixel_image(const pixman_format_code_t * allowed_formats,uint32_t * buffer,pixman_format_code_t * used_fmt)178 create_multi_pixel_image (const pixman_format_code_t *allowed_formats,
179 uint32_t *buffer,
180 pixman_format_code_t *used_fmt)
181 {
182 pixman_format_code_t fmt;
183 pixman_image_t *img;
184 int stride;
185
186 fmt = random_format (allowed_formats);
187 stride = (WIDTH * PIXMAN_FORMAT_BPP (fmt) + 31) / 32 * 4;
188 img = pixman_image_create_bits (fmt, WIDTH, HEIGHT, buffer, stride);
189
190 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR)
191 pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)]));
192 else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY)
193 pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)]));
194
195 prng_randmemset (buffer, WIDTH * HEIGHT * 4, 0);
196 image_endian_swap (img);
197
198 if (used_fmt)
199 *used_fmt = fmt;
200
201 return img;
202 }
203
204 static pixman_image_t *
create_solid_image(const pixman_format_code_t * allowed_formats,uint32_t * buffer,pixman_format_code_t * used_fmt)205 create_solid_image (const pixman_format_code_t *allowed_formats,
206 uint32_t *buffer,
207 pixman_format_code_t *used_fmt)
208 {
209 if (prng_rand_n (2))
210 {
211 /* Use a repeating 1x1 bitmap image for solid */
212 pixman_format_code_t fmt;
213 pixman_image_t *img, *dummy_img;
214 uint32_t bpp, dummy_buf;
215
216 fmt = random_format (allowed_formats);
217 bpp = PIXMAN_FORMAT_BPP (fmt);
218 img = pixman_image_create_bits (fmt, 1, 1, buffer, 4);
219 pixman_image_set_repeat (img, PIXMAN_REPEAT_NORMAL);
220
221 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR)
222 pixman_image_set_indexed (img, &(rgb_palette[bpp]));
223 else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY)
224 pixman_image_set_indexed (img, &(y_palette[bpp]));
225
226 /* Force the flags to be calculated for image with initial
227 * bitmap contents of 0 or 2^bpp-1 by plotting from it into a
228 * separate throwaway image. It is simplest to write all 0s
229 * or all 1s to the first word irrespective of the colour
230 * depth even though we actually only care about the first
231 * pixel since the stride has to be a whole number of words.
232 */
233 *buffer = prng_rand_n (2) ? 0xFFFFFFFFu : 0;
234 dummy_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, 1, 1,
235 &dummy_buf, 4);
236 pixman_image_composite (PIXMAN_OP_SRC, img, NULL, dummy_img,
237 0, 0, 0, 0, 0, 0, 1, 1);
238 pixman_image_unref (dummy_img);
239
240 /* Now set the bitmap contents to a random value */
241 prng_randmemset (buffer, 4, 0);
242 image_endian_swap (img);
243
244 if (used_fmt)
245 *used_fmt = fmt;
246
247 return img;
248 }
249 else
250 {
251 /* Use a native solid image */
252 pixman_color_t color;
253 pixman_image_t *img;
254
255 color.alpha = prng_rand_n (UINT16_MAX + 1);
256 color.red = prng_rand_n (UINT16_MAX + 1);
257 color.green = prng_rand_n (UINT16_MAX + 1);
258 color.blue = prng_rand_n (UINT16_MAX + 1);
259 img = pixman_image_create_solid_fill (&color);
260
261 if (used_fmt)
262 *used_fmt = PIXMAN_solid;
263
264 return img;
265 }
266 }
267
268 static uint32_t
test_solid(int testnum,int verbose)269 test_solid (int testnum, int verbose)
270 {
271 pixman_op_t op;
272 uint32_t src_buf[WIDTH * HEIGHT];
273 uint32_t dst_buf[WIDTH * HEIGHT];
274 uint32_t mask_buf[WIDTH * HEIGHT];
275 pixman_image_t *src_img;
276 pixman_image_t *dst_img;
277 pixman_image_t *mask_img = NULL;
278 pixman_format_code_t src_fmt, dst_fmt, mask_fmt = PIXMAN_null;
279 pixman_bool_t ca = 0;
280 uint32_t crc32;
281
282 prng_srand (testnum);
283
284 op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))];
285
286 dst_img = create_multi_pixel_image (img_fmt_list, dst_buf, &dst_fmt);
287 switch (prng_rand_n (3))
288 {
289 case 0: /* Solid source, no mask */
290 src_img = create_solid_image (img_fmt_list, src_buf, &src_fmt);
291 break;
292 case 1: /* Solid source, bitmap mask */
293 src_img = create_solid_image (img_fmt_list, src_buf, &src_fmt);
294 mask_img = create_multi_pixel_image (mask_fmt_list, mask_buf, &mask_fmt);
295 break;
296 case 2: /* Bitmap image, solid mask */
297 src_img = create_multi_pixel_image (img_fmt_list, src_buf, &src_fmt);
298 mask_img = create_solid_image (mask_fmt_list, mask_buf, &mask_fmt);
299 break;
300 default:
301 abort ();
302 }
303
304 if (mask_img)
305 {
306 ca = prng_rand_n (2);
307 pixman_image_set_component_alpha (mask_img, ca);
308 }
309
310 if (verbose)
311 {
312 printf ("op=%s\n", operator_name (op));
313 printf ("src_fmt=%s, dst_fmt=%s, mask_fmt=%s\n",
314 format_name (src_fmt), format_name (dst_fmt),
315 format_name (mask_fmt));
316 printf ("src_size=%u, mask_size=%u, component_alpha=%u\n",
317 src_fmt == PIXMAN_solid ? 1 : src_img->bits.width,
318 !mask_img || mask_fmt == PIXMAN_solid ? 1 : mask_img->bits.width,
319 ca);
320 }
321
322 pixman_image_composite (op, src_img, mask_img, dst_img,
323 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
324
325 if (verbose)
326 print_image (dst_img);
327
328 crc32 = compute_crc32_for_image (0, dst_img);
329
330 pixman_image_unref (src_img);
331 pixman_image_unref (dst_img);
332 if (mask_img)
333 pixman_image_unref (mask_img);
334
335 return crc32;
336 }
337
338 int
main(int argc,const char * argv[])339 main (int argc, const char *argv[])
340 {
341 int i;
342
343 prng_srand (0);
344
345 for (i = 1; i <= 8; i++)
346 {
347 initialize_palette (&(rgb_palette[i]), i, TRUE);
348 initialize_palette (&(y_palette[i]), i, FALSE);
349 }
350
351 return fuzzer_test_main ("solid", 500000,
352 0xC30FD380,
353 test_solid, argc, argv);
354 }
355