16ba797d6Smrg/* Based loosely on scaling-test */
26ba797d6Smrg
36ba797d6Smrg#include <stdlib.h>
46ba797d6Smrg#include <stdio.h>
56ba797d6Smrg#include "utils.h"
66ba797d6Smrg
76ba797d6Smrg#define MAX_SRC_WIDTH  48
86ba797d6Smrg#define MAX_SRC_HEIGHT 48
96ba797d6Smrg#define MAX_DST_WIDTH  48
106ba797d6Smrg#define MAX_DST_HEIGHT 48
116ba797d6Smrg#define MAX_STRIDE     4
126ba797d6Smrg
136ba797d6Smrgstatic pixman_format_code_t formats[] =
146ba797d6Smrg{
156ba797d6Smrg    PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_r5g6b5, PIXMAN_a1, PIXMAN_a4
166ba797d6Smrg};
176ba797d6Smrg
186ba797d6Smrgstatic pixman_format_code_t mask_formats[] =
196ba797d6Smrg{
206ba797d6Smrg    PIXMAN_a1, PIXMAN_a4, PIXMAN_a8,
216ba797d6Smrg};
226ba797d6Smrg
236ba797d6Smrgstatic pixman_op_t operators[] =
246ba797d6Smrg{
256ba797d6Smrg    PIXMAN_OP_OVER, PIXMAN_OP_ADD, PIXMAN_OP_SRC, PIXMAN_OP_IN
266ba797d6Smrg};
276ba797d6Smrg
286ba797d6Smrg#define RANDOM_ELT(array)						\
29f4f78bb6Smrg    ((array)[prng_rand_n(ARRAY_LENGTH((array)))])
306ba797d6Smrg
316ba797d6Smrgstatic void
326ba797d6Smrgdestroy_bits (pixman_image_t *image, void *data)
336ba797d6Smrg{
346ba797d6Smrg    fence_free (data);
356ba797d6Smrg}
366ba797d6Smrg
376ba797d6Smrgstatic pixman_fixed_t
386ba797d6Smrgrandom_fixed (int n)
396ba797d6Smrg{
40f4f78bb6Smrg    return prng_rand_n (n << 16);
416ba797d6Smrg}
426ba797d6Smrg
436ba797d6Smrg/*
446ba797d6Smrg * Composite operation with pseudorandom images
456ba797d6Smrg */
466ba797d6Smrguint32_t
476ba797d6Smrgtest_composite (int      testnum,
486ba797d6Smrg		int      verbose)
496ba797d6Smrg{
506ba797d6Smrg    int                i;
516ba797d6Smrg    pixman_image_t *   src_img;
526ba797d6Smrg    pixman_image_t *   dst_img;
536ba797d6Smrg    pixman_region16_t  clip;
546ba797d6Smrg    int                dst_width, dst_height;
556ba797d6Smrg    int                dst_stride;
566ba797d6Smrg    int                dst_x, dst_y;
576ba797d6Smrg    int                dst_bpp;
586ba797d6Smrg    pixman_op_t        op;
596ba797d6Smrg    uint32_t *         dst_bits;
606ba797d6Smrg    uint32_t           crc32;
616ba797d6Smrg    pixman_format_code_t mask_format, dst_format;
626ba797d6Smrg    pixman_trapezoid_t *traps;
636ba797d6Smrg    int src_x, src_y;
646ba797d6Smrg    int n_traps;
656ba797d6Smrg
666ba797d6Smrg    static pixman_color_t colors[] =
676ba797d6Smrg    {
686ba797d6Smrg	{ 0xffff, 0xffff, 0xffff, 0xffff },
696ba797d6Smrg	{ 0x0000, 0x0000, 0x0000, 0x0000 },
706ba797d6Smrg	{ 0xabcd, 0xabcd, 0x0000, 0xabcd },
716ba797d6Smrg	{ 0x0000, 0x0000, 0x0000, 0xffff },
726ba797d6Smrg	{ 0x0101, 0x0101, 0x0101, 0x0101 },
736ba797d6Smrg	{ 0x7777, 0x6666, 0x5555, 0x9999 },
746ba797d6Smrg    };
756ba797d6Smrg
766ba797d6Smrg    FLOAT_REGS_CORRUPTION_DETECTOR_START ();
776ba797d6Smrg
78f4f78bb6Smrg    prng_srand (testnum);
796ba797d6Smrg
806ba797d6Smrg    op = RANDOM_ELT (operators);
816ba797d6Smrg    mask_format = RANDOM_ELT (mask_formats);
826ba797d6Smrg
836ba797d6Smrg    /* Create source image */
846ba797d6Smrg
85f4f78bb6Smrg    if (prng_rand_n (4) == 0)
866ba797d6Smrg    {
876ba797d6Smrg	src_img = pixman_image_create_solid_fill (
88f4f78bb6Smrg	    &(colors[prng_rand_n (ARRAY_LENGTH (colors))]));
896ba797d6Smrg
906ba797d6Smrg	src_x = 10;
916ba797d6Smrg	src_y = 234;
926ba797d6Smrg    }
936ba797d6Smrg    else
946ba797d6Smrg    {
956ba797d6Smrg	pixman_format_code_t src_format = RANDOM_ELT(formats);
966ba797d6Smrg	int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8;
97f4f78bb6Smrg	int src_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
98f4f78bb6Smrg	int src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
99f4f78bb6Smrg	int src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp;
100de17ff4aSmrg	uint32_t *bits, *orig;
1016ba797d6Smrg
102f4f78bb6Smrg	src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2);
103f4f78bb6Smrg	src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2);
1046ba797d6Smrg
1056ba797d6Smrg	src_stride = (src_stride + 3) & ~3;
1066ba797d6Smrg
107de17ff4aSmrg	orig = bits = (uint32_t *)make_random_bytes (src_stride * src_height);
1086ba797d6Smrg
109de17ff4aSmrg	if (prng_rand_n (2) == 0)
110de17ff4aSmrg	{
111de17ff4aSmrg	    bits += (src_stride / 4) * (src_height - 1);
112de17ff4aSmrg	    src_stride = - src_stride;
113de17ff4aSmrg	}
114de17ff4aSmrg
1156ba797d6Smrg	src_img = pixman_image_create_bits (
1166ba797d6Smrg	    src_format, src_width, src_height, bits, src_stride);
1176ba797d6Smrg
118de17ff4aSmrg	pixman_image_set_destroy_function (src_img, destroy_bits, orig);
1196ba797d6Smrg
120f4f78bb6Smrg	if (prng_rand_n (8) == 0)
1216ba797d6Smrg	{
1226ba797d6Smrg	    pixman_box16_t clip_boxes[2];
123f4f78bb6Smrg	    int            n = prng_rand_n (2) + 1;
1246ba797d6Smrg
1256ba797d6Smrg	    for (i = 0; i < n; i++)
1266ba797d6Smrg	    {
127f4f78bb6Smrg		clip_boxes[i].x1 = prng_rand_n (src_width);
128f4f78bb6Smrg		clip_boxes[i].y1 = prng_rand_n (src_height);
1296ba797d6Smrg		clip_boxes[i].x2 =
130f4f78bb6Smrg		    clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1);
1316ba797d6Smrg		clip_boxes[i].y2 =
132f4f78bb6Smrg		    clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1);
1336ba797d6Smrg
1346ba797d6Smrg		if (verbose)
1356ba797d6Smrg		{
1366ba797d6Smrg		    printf ("source clip box: [%d,%d-%d,%d]\n",
1376ba797d6Smrg			    clip_boxes[i].x1, clip_boxes[i].y1,
1386ba797d6Smrg			    clip_boxes[i].x2, clip_boxes[i].y2);
1396ba797d6Smrg		}
1406ba797d6Smrg	    }
1416ba797d6Smrg
1426ba797d6Smrg	    pixman_region_init_rects (&clip, clip_boxes, n);
1436ba797d6Smrg	    pixman_image_set_clip_region (src_img, &clip);
1446ba797d6Smrg	    pixman_image_set_source_clipping (src_img, 1);
1456ba797d6Smrg	    pixman_region_fini (&clip);
1466ba797d6Smrg	}
1476ba797d6Smrg
1486ba797d6Smrg	image_endian_swap (src_img);
1496ba797d6Smrg    }
1506ba797d6Smrg
1516ba797d6Smrg    /* Create destination image */
1526ba797d6Smrg    {
1536ba797d6Smrg	dst_format = RANDOM_ELT(formats);
1546ba797d6Smrg	dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8;
155f4f78bb6Smrg	dst_width = prng_rand_n (MAX_DST_WIDTH) + 1;
156f4f78bb6Smrg	dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1;
157f4f78bb6Smrg	dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp;
1586ba797d6Smrg	dst_stride = (dst_stride + 3) & ~3;
1596ba797d6Smrg
1606ba797d6Smrg	dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height);
1616ba797d6Smrg
162de17ff4aSmrg	if (prng_rand_n (2) == 0)
163de17ff4aSmrg	{
164de17ff4aSmrg	    dst_bits += (dst_stride / 4) * (dst_height - 1);
165de17ff4aSmrg	    dst_stride = - dst_stride;
166de17ff4aSmrg	}
167de17ff4aSmrg
168f4f78bb6Smrg	dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2);
169f4f78bb6Smrg	dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2);
1706ba797d6Smrg
1716ba797d6Smrg	dst_img = pixman_image_create_bits (
1726ba797d6Smrg	    dst_format, dst_width, dst_height, dst_bits, dst_stride);
1736ba797d6Smrg
1746ba797d6Smrg	image_endian_swap (dst_img);
1756ba797d6Smrg    }
1766ba797d6Smrg
1776ba797d6Smrg    /* Create traps */
1786ba797d6Smrg    {
1796ba797d6Smrg	int i;
1806ba797d6Smrg
181f4f78bb6Smrg	n_traps = prng_rand_n (25);
1826ba797d6Smrg	traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t));
1836ba797d6Smrg
1846ba797d6Smrg	for (i = 0; i < n_traps; ++i)
1856ba797d6Smrg	{
1866ba797d6Smrg	    pixman_trapezoid_t *t = &(traps[i]);
1876ba797d6Smrg
1886ba797d6Smrg	    t->top = random_fixed (MAX_DST_HEIGHT) - MAX_DST_HEIGHT / 2;
1896ba797d6Smrg	    t->bottom = t->top + random_fixed (MAX_DST_HEIGHT);
1906ba797d6Smrg	    t->left.p1.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
1916ba797d6Smrg	    t->left.p1.y = t->top - random_fixed (50);
1926ba797d6Smrg	    t->left.p2.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
1936ba797d6Smrg	    t->left.p2.y = t->bottom + random_fixed (50);
1946ba797d6Smrg	    t->right.p1.x = t->left.p1.x + random_fixed (MAX_DST_WIDTH);
1956ba797d6Smrg	    t->right.p1.y = t->top - random_fixed (50);
1966ba797d6Smrg	    t->right.p2.x = t->left.p2.x + random_fixed (MAX_DST_WIDTH);
1976ba797d6Smrg	    t->right.p2.y = t->bottom - random_fixed (50);
1986ba797d6Smrg	}
1996ba797d6Smrg    }
2006ba797d6Smrg
201f4f78bb6Smrg    if (prng_rand_n (8) == 0)
2026ba797d6Smrg    {
2036ba797d6Smrg	pixman_box16_t clip_boxes[2];
204f4f78bb6Smrg	int            n = prng_rand_n (2) + 1;
2056ba797d6Smrg	for (i = 0; i < n; i++)
2066ba797d6Smrg	{
207f4f78bb6Smrg	    clip_boxes[i].x1 = prng_rand_n (dst_width);
208f4f78bb6Smrg	    clip_boxes[i].y1 = prng_rand_n (dst_height);
2096ba797d6Smrg	    clip_boxes[i].x2 =
210f4f78bb6Smrg		clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1);
2116ba797d6Smrg	    clip_boxes[i].y2 =
212f4f78bb6Smrg		clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1);
2136ba797d6Smrg
2146ba797d6Smrg	    if (verbose)
2156ba797d6Smrg	    {
2166ba797d6Smrg		printf ("destination clip box: [%d,%d-%d,%d]\n",
2176ba797d6Smrg		        clip_boxes[i].x1, clip_boxes[i].y1,
2186ba797d6Smrg		        clip_boxes[i].x2, clip_boxes[i].y2);
2196ba797d6Smrg	    }
2206ba797d6Smrg	}
2216ba797d6Smrg	pixman_region_init_rects (&clip, clip_boxes, n);
2226ba797d6Smrg	pixman_image_set_clip_region (dst_img, &clip);
2236ba797d6Smrg	pixman_region_fini (&clip);
2246ba797d6Smrg    }
2256ba797d6Smrg
2266ba797d6Smrg    pixman_composite_trapezoids (op, src_img, dst_img, mask_format,
2276ba797d6Smrg				 src_x, src_y, dst_x, dst_y, n_traps, traps);
2286ba797d6Smrg
229de17ff4aSmrg    crc32 = compute_crc32_for_image (0, dst_img);
2306ba797d6Smrg
2316ba797d6Smrg    if (verbose)
232de17ff4aSmrg	print_image (dst_img);
2336ba797d6Smrg
234de17ff4aSmrg    if (dst_stride < 0)
235de17ff4aSmrg	dst_bits += (dst_stride / 4) * (dst_height - 1);
236de17ff4aSmrg
2376ba797d6Smrg    fence_free (dst_bits);
2386ba797d6Smrg
2396ba797d6Smrg    pixman_image_unref (src_img);
2406ba797d6Smrg    pixman_image_unref (dst_img);
2416ba797d6Smrg    fence_free (traps);
2426ba797d6Smrg
2436ba797d6Smrg    FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
2446ba797d6Smrg    return crc32;
2456ba797d6Smrg}
2466ba797d6Smrg
2476ba797d6Smrgint
2486ba797d6Smrgmain (int argc, const char *argv[])
2496ba797d6Smrg{
250de17ff4aSmrg    return fuzzer_test_main("composite traps", 40000, 0xAF41D210,
2516ba797d6Smrg			    test_composite, argc, argv);
2526ba797d6Smrg}
253