1#include <stdint.h>
2#include <stdio.h>
3#include <stdlib.h>
4
5#include "test.h"
6
7static unsigned char bitmap4x4[] = {
8	   0x03, 0x06, 0x0c, 0x09
9};
10
11static unsigned char bitmap8x8[3][8] = {
12	{ 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 },
13	{ 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe },
14	{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
15};
16
17static void fill_rect(struct test_target *t, uint8_t alu,
18		      XRectangle *clip, int nclip,
19		      uint8_t stipple, uint8_t opaque, int tx, int ty,
20		      int x, int y, int w, int h,
21		      uint32_t fg, uint32_t bg)
22{
23	Display *dpy = t->dpy->dpy;
24	XGCValues val;
25	GC gc;
26
27	val.function = alu;
28	val.foreground = fg;
29	val.background = bg;
30	val.fill_style = opaque ? FillOpaqueStippled : FillStippled;
31	val.ts_x_origin = tx;
32	val.ts_y_origin = ty;
33	if (stipple == 0) {
34		val.stipple = XCreateBitmapFromData(dpy, t->draw, (char *)bitmap4x4, 4, 4);
35	} else {
36		char *b = (char *)bitmap8x8[stipple-1];
37		val.stipple = XCreateBitmapFromData(dpy, t->draw, b, 8, 8);
38	}
39
40	gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCStipple | GCForeground | GCBackground | GCFunction, &val);
41	if (nclip)
42		XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted);
43	XFillRectangle(dpy, t->draw, gc, x, y, w, h);
44	XFreeGC(dpy, gc);
45	XFreePixmap(dpy, val.stipple);
46}
47
48static void clear(struct test_target *tt)
49{
50	XRenderColor render_color = {0};
51	XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color,
52			     0, 0, tt->width, tt->height);
53}
54
55static void unclipped_tests(struct test *t, int reps, int sets, enum target target)
56{
57	struct test_target out, ref;
58	int r, s;
59
60	printf("Testing unclipped stippled fills (%s): ", test_target_name(target));
61	fflush(stdout);
62
63	test_target_create_render(&t->out, target, &out);
64	clear(&out);
65
66	test_target_create_render(&t->ref, target, &ref);
67	clear(&ref);
68
69	for (s = 0; s < sets; s++) {
70		for (r = 0; r < reps; r++) {
71			int x = rand() % out.width;
72			int y = rand() % out.height;
73			int w = rand() % (out.width - x);
74			int h = rand() % (out.height - y);
75			int tx = rand() % (2*out.width) - out.width;
76			int ty = rand() % (2*out.height) - out.height;
77			uint8_t stipple = rand() % 4;
78			uint8_t opaque = rand() % 1;
79			uint8_t alu = rand() % (GXset + 1);
80			uint32_t fg = rand();
81			uint32_t bg = rand();
82
83			fill_rect(&out, alu, NULL, 0,
84				  stipple, opaque, tx, ty,
85				  x, y, w, h,
86				  fg, bg);
87			fill_rect(&ref, alu, NULL, 0,
88				  stipple, opaque, tx, ty,
89				  x, y, w, h,
90				  fg, bg);
91		}
92
93		test_compare(t,
94			     out.draw, out.format,
95			     ref.draw, ref.format,
96			     0, 0, out.width, out.height,
97			     "");
98	}
99
100	printf("passed [%d iterations x %d]\n", reps, sets);
101
102	test_target_destroy_render(&t->out, &out);
103	test_target_destroy_render(&t->ref, &ref);
104}
105
106static void simple_clip_tests(struct test *t, int reps, int sets, enum target target)
107{
108	struct test_target out, ref;
109	int r, s;
110
111	printf("Testing simple clipped stippled fills (%s): ", test_target_name(target));
112	fflush(stdout);
113
114	test_target_create_render(&t->out, target, &out);
115	clear(&out);
116
117	test_target_create_render(&t->ref, target, &ref);
118	clear(&ref);
119
120	for (s = 0; s < sets; s++) {
121		for (r = 0; r < reps; r++) {
122			int x = rand() % (2*out.width) - out.width;
123			int y = rand() % (2*out.height) - out.height;
124			int w = rand() % (2*out.width);
125			int h = rand() % (2*out.height);
126			int tx = rand() % (2*out.width) - out.width;
127			int ty = rand() % (2*out.height) - out.height;
128			uint8_t stipple = rand() % 4;
129			uint8_t opaque = rand() % 1;
130			uint8_t alu = rand() % (GXset + 1);
131			uint32_t fg = rand();
132			uint32_t bg = rand();
133
134			fill_rect(&out, alu, NULL, 0,
135				  stipple, opaque, tx, ty,
136				  x, y, w, h,
137				  fg, bg);
138			fill_rect(&ref, alu, NULL, 0,
139				  stipple, opaque, tx, ty,
140				  x, y, w, h,
141				  fg, bg);
142		}
143
144		test_compare(t,
145			     out.draw, out.format,
146			     ref.draw, ref.format,
147			     0, 0, out.width, out.height,
148			     "");
149	}
150
151	printf("passed [%d iterations x %d]\n", reps, sets);
152
153	test_target_destroy_render(&t->out, &out);
154	test_target_destroy_render(&t->ref, &ref);
155}
156
157static void complex_clip_tests(struct test *t, int reps, int sets, enum target target)
158{
159	struct test_target out, ref;
160	XRectangle *clip;
161	int nclip, r, s;
162
163	printf("Testing complex clipped stippled fills (%s): ", test_target_name(target));
164	fflush(stdout);
165
166	test_target_create_render(&t->out, target, &out);
167	clear(&out);
168
169	test_target_create_render(&t->ref, target, &ref);
170	clear(&ref);
171
172	for (s = 0; s < sets; s++) {
173		nclip = (rand() % 16) + 2;
174		clip = malloc(sizeof(XRectangle)*nclip);
175		for (r = 0; r < nclip; r++) {
176			clip[r].x = rand() % out.width;
177			clip[r].y = rand() % out.height;
178			clip[r].width = rand() % (out.width - clip[r].x);
179			clip[r].height = rand() % (out.height - clip[r].y);
180		}
181
182		for (r = 0; r < reps; r++) {
183			int x = rand() % (2*out.width) - out.width;
184			int y = rand() % (2*out.height) - out.height;
185			int w = rand() % (2*out.width);
186			int h = rand() % (2*out.height);
187			int tx = rand() % (2*out.width) - out.width;
188			int ty = rand() % (2*out.height) - out.height;
189			uint8_t stipple = rand() % 4;
190			uint8_t opaque = rand() % 1;
191			uint8_t alu = rand() % (GXset + 1);
192			uint32_t fg = rand();
193			uint32_t bg = rand();
194
195			fill_rect(&out, alu, clip, nclip,
196				  stipple, opaque, tx, ty,
197				  x, y, w, h,
198				  fg, bg);
199			fill_rect(&ref, alu, clip, nclip,
200				  stipple, opaque, tx, ty,
201				  x, y, w, h,
202				  fg, bg);
203		}
204
205		test_compare(t,
206			     out.draw, out.format,
207			     ref.draw, ref.format,
208			     0, 0, out.width, out.height,
209			     "");
210
211		free(clip);
212	}
213
214	printf("passed [%d iterations x %d]\n", reps, sets);
215
216	test_target_destroy_render(&t->out, &out);
217	test_target_destroy_render(&t->ref, &ref);
218}
219
220int main(int argc, char **argv)
221{
222	struct test test;
223	int i;
224
225	test_init(&test, argc, argv);
226
227	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
228		int reps = REPS(i), sets = SETS(i);
229		enum target t;
230
231		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
232			unclipped_tests(&test, reps, sets, t);
233			simple_clip_tests(&test, reps, sets, t);
234			complex_clip_tests(&test, reps, sets, t);
235		}
236	}
237
238	return 0;
239}
240