1428d7b3dSmrg#include <stdint.h>
2428d7b3dSmrg#include <stdio.h>
3428d7b3dSmrg#include <stdlib.h>
4428d7b3dSmrg
5428d7b3dSmrg#include "test.h"
6428d7b3dSmrg
7428d7b3dSmrgstatic const unsigned char data[] = {
8428d7b3dSmrg	0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
9428d7b3dSmrg	0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
10428d7b3dSmrg	0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
11428d7b3dSmrg	0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
12428d7b3dSmrg};
13428d7b3dSmrg
14428d7b3dSmrgstatic struct bitmap {
15428d7b3dSmrg	int width, height;
16428d7b3dSmrg	struct cache {
17428d7b3dSmrg		Display *dpy;
18428d7b3dSmrg		Pixmap pixmap;
19428d7b3dSmrg	} cached[2];
20428d7b3dSmrg} bitmaps[] = {
21428d7b3dSmrg	{ 1, 1, },
22428d7b3dSmrg	{ 1, 2, },
23428d7b3dSmrg	{ 2, 3, },
24428d7b3dSmrg	{ 3, 2, },
25428d7b3dSmrg	{ 4, 4, },
26428d7b3dSmrg	{ 6, 6, },
27428d7b3dSmrg	{ 8, 8, },
28428d7b3dSmrg	{ 8, 4, },
29428d7b3dSmrg	{ 8, 2, },
30428d7b3dSmrg	{ 8, 1, },
31428d7b3dSmrg	{ 4, 8, },
32428d7b3dSmrg	{ 2, 8, },
33428d7b3dSmrg	{ 1, 8, },
34428d7b3dSmrg	{ 16, 16, },
35428d7b3dSmrg	{ 15, 17, },
36428d7b3dSmrg	{ 24, 24, },
37428d7b3dSmrg	{ 32, 32, },
38428d7b3dSmrg	{ 16, 8, },
39428d7b3dSmrg	{ 16, 4, },
40428d7b3dSmrg	{ 16, 2, },
41428d7b3dSmrg	{ 16, 1, },
42428d7b3dSmrg	{ 8, 16, },
43428d7b3dSmrg	{ 4, 16, },
44428d7b3dSmrg	{ 2, 16, },
45428d7b3dSmrg	{ 1, 16, },
46428d7b3dSmrg};
47428d7b3dSmrg
48428d7b3dSmrgstatic void reset_cache(void)
49428d7b3dSmrg{
50428d7b3dSmrg	int n, m;
51428d7b3dSmrg
52428d7b3dSmrg	for (n = 0; n < sizeof(bitmaps)/sizeof(bitmaps[0]); n++) {
53428d7b3dSmrg		for (m = 0; m < 2; m++) {
54428d7b3dSmrg			if (bitmaps[n].cached[m].dpy) {
55428d7b3dSmrg				XFreePixmap(bitmaps[n].cached[m].dpy, bitmaps[n].cached[m].pixmap);
56428d7b3dSmrg				bitmaps[n].cached[m].dpy = NULL;
57428d7b3dSmrg			}
58428d7b3dSmrg		}
59428d7b3dSmrg	}
60428d7b3dSmrg}
61428d7b3dSmrg
62428d7b3dSmrgstatic void fill_rect(struct test_target *t, uint8_t alu,
63428d7b3dSmrg		      XRectangle *clip, int nclip,
64428d7b3dSmrg		      uint8_t tile, int tx, int ty,
65428d7b3dSmrg		      int x, int y, int w, int h,
66428d7b3dSmrg		      uint32_t fg, uint32_t bg)
67428d7b3dSmrg{
68428d7b3dSmrg	Display *dpy = t->dpy->dpy;
69428d7b3dSmrg	struct bitmap *b = &bitmaps[(tile >> 1) % (sizeof(bitmaps)/sizeof(bitmaps[0]))];
70428d7b3dSmrg	XGCValues val;
71428d7b3dSmrg	GC gc;
72428d7b3dSmrg	int n;
73428d7b3dSmrg
74428d7b3dSmrg	val.function = alu;
75428d7b3dSmrg	val.function = GXcopy;
76428d7b3dSmrg	val.fill_style = FillTiled;
77428d7b3dSmrg	val.ts_x_origin = tx;
78428d7b3dSmrg	val.ts_y_origin = ty;
79428d7b3dSmrg	if (tile & 1) {
80428d7b3dSmrg		val.tile = 0;
81428d7b3dSmrg		for (n = 0; n < 2; n++) {
82428d7b3dSmrg			if (b->cached[n].dpy == dpy) {
83428d7b3dSmrg				val.tile = b->cached[n].pixmap;
84428d7b3dSmrg				break;
85428d7b3dSmrg			}
86428d7b3dSmrg		}
87428d7b3dSmrg		if (val.tile == 0) {
88428d7b3dSmrg			val.tile = XCreatePixmapFromBitmapData(dpy, t->draw,
89428d7b3dSmrg							       (char *)data, b->width, b->height,
90428d7b3dSmrg							       fg, bg, t->depth);
91428d7b3dSmrg			for (n = 0; n < 2; n++) {
92428d7b3dSmrg				if (b->cached[n].dpy == NULL) {
93428d7b3dSmrg					b->cached[n].dpy = dpy;
94428d7b3dSmrg					b->cached[n].pixmap = val.tile;
95428d7b3dSmrg					break;
96428d7b3dSmrg				}
97428d7b3dSmrg			}
98428d7b3dSmrg		}
99428d7b3dSmrg	} else
100428d7b3dSmrg		val.tile = XCreatePixmapFromBitmapData(dpy, t->draw,
101428d7b3dSmrg						       (char *)data, b->width, b->height,
102428d7b3dSmrg						       fg, bg, t->depth);
103428d7b3dSmrg
104428d7b3dSmrg	gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCTile | GCFunction, &val);
105428d7b3dSmrg	if (nclip)
106428d7b3dSmrg		XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted);
107428d7b3dSmrg	XFillRectangle(dpy, t->draw, gc, x, y, w, h);
108428d7b3dSmrg	XFreeGC(dpy, gc);
109428d7b3dSmrg	if ((tile & 1) == 0)
110428d7b3dSmrg		XFreePixmap(dpy, val.tile);
111428d7b3dSmrg}
112428d7b3dSmrg
113428d7b3dSmrgstatic void clear(struct test_target *tt)
114428d7b3dSmrg{
115428d7b3dSmrg	XRenderColor render_color = {0};
116428d7b3dSmrg	XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color,
117428d7b3dSmrg			     0, 0, tt->width, tt->height);
118428d7b3dSmrg}
119428d7b3dSmrg
120428d7b3dSmrgstatic void small_tests(struct test *t, int reps, int sets, enum target target)
121428d7b3dSmrg{
122428d7b3dSmrg	struct test_target out, ref;
123428d7b3dSmrg	int r, s;
124428d7b3dSmrg
125428d7b3dSmrg	printf("Testing small tiled fills (%s): ", test_target_name(target));
126428d7b3dSmrg	fflush(stdout);
127428d7b3dSmrg
128428d7b3dSmrg	test_target_create_render(&t->out, target, &out);
129428d7b3dSmrg	clear(&out);
130428d7b3dSmrg
131428d7b3dSmrg	test_target_create_render(&t->ref, target, &ref);
132428d7b3dSmrg	clear(&ref);
133428d7b3dSmrg
134428d7b3dSmrg	for (s = 0; s < sets; s++) {
135428d7b3dSmrg		for (r = 0; r < reps; r++) {
136428d7b3dSmrg			int x = rand() % out.width;
137428d7b3dSmrg			int y = rand() % out.height;
138428d7b3dSmrg			int w = rand() % out.width;
139428d7b3dSmrg			int h = rand() % 8;
140428d7b3dSmrg			int tx = rand() % (2*out.width) - out.width;
141428d7b3dSmrg			int ty = rand() % (2*out.height) - out.height;
142428d7b3dSmrg			uint8_t tile = rand();
143428d7b3dSmrg			uint8_t alu = rand() % (GXset + 1);
144428d7b3dSmrg			uint32_t fg = rand();
145428d7b3dSmrg			uint32_t bg = rand();
146428d7b3dSmrg
147428d7b3dSmrg			fill_rect(&out, alu, NULL, 0,
148428d7b3dSmrg				  tile, tx, ty,
149428d7b3dSmrg				  x, y, w, h,
150428d7b3dSmrg				  fg, bg);
151428d7b3dSmrg			fill_rect(&ref, alu, NULL, 0,
152428d7b3dSmrg				  tile, tx, ty,
153428d7b3dSmrg				  x, y, w, h,
154428d7b3dSmrg				  fg, bg);
155428d7b3dSmrg
156428d7b3dSmrg			fill_rect(&out, alu, NULL, 0,
157428d7b3dSmrg				  tile, tx, ty,
158428d7b3dSmrg				  x, y, h, w,
159428d7b3dSmrg				  fg, bg);
160428d7b3dSmrg			fill_rect(&ref, alu, NULL, 0,
161428d7b3dSmrg				  tile, tx, ty,
162428d7b3dSmrg				  x, y, h, w,
163428d7b3dSmrg				  fg, bg);
164428d7b3dSmrg		}
165428d7b3dSmrg
166428d7b3dSmrg		test_compare(t,
167428d7b3dSmrg			     out.draw, out.format,
168428d7b3dSmrg			     ref.draw, ref.format,
169428d7b3dSmrg			     0, 0, out.width, out.height,
170428d7b3dSmrg			     "");
171428d7b3dSmrg
172428d7b3dSmrg		if (target == CHILD) {
173428d7b3dSmrg			int x = rand() % (t->out.width-out.width);
174428d7b3dSmrg			int y = rand() % (t->out.height-out.height);
175428d7b3dSmrg
176428d7b3dSmrg			clear(&out);
177428d7b3dSmrg			clear(&ref);
178428d7b3dSmrg
179428d7b3dSmrg			XMoveWindow(out.dpy->dpy, out.draw, x, y);
180428d7b3dSmrg			XMoveWindow(ref.dpy->dpy, ref.draw, x, y);
181428d7b3dSmrg
182428d7b3dSmrg			clear(&out);
183428d7b3dSmrg			clear(&ref);
184428d7b3dSmrg		}
185428d7b3dSmrg	}
186428d7b3dSmrg
187428d7b3dSmrg	printf("passed [%d iterations x %d]\n", reps, sets);
188428d7b3dSmrg
189428d7b3dSmrg	test_target_destroy_render(&t->out, &out);
190428d7b3dSmrg	test_target_destroy_render(&t->ref, &ref);
191428d7b3dSmrg}
192428d7b3dSmrg
193428d7b3dSmrgstatic void unclipped_tests(struct test *t, int reps, int sets, enum target target)
194428d7b3dSmrg{
195428d7b3dSmrg	struct test_target out, ref;
196428d7b3dSmrg	int r, s;
197428d7b3dSmrg
198428d7b3dSmrg	printf("Testing unclipped tiled fills (%s): ", test_target_name(target));
199428d7b3dSmrg	fflush(stdout);
200428d7b3dSmrg
201428d7b3dSmrg	test_target_create_render(&t->out, target, &out);
202428d7b3dSmrg	clear(&out);
203428d7b3dSmrg
204428d7b3dSmrg	test_target_create_render(&t->ref, target, &ref);
205428d7b3dSmrg	clear(&ref);
206428d7b3dSmrg
207428d7b3dSmrg	for (s = 0; s < sets; s++) {
208428d7b3dSmrg		for (r = 0; r < reps; r++) {
209428d7b3dSmrg			int x = rand() % out.width;
210428d7b3dSmrg			int y = rand() % out.height;
211428d7b3dSmrg			int w = rand() % (out.width - x);
212428d7b3dSmrg			int h = rand() % (out.height - y);
213428d7b3dSmrg			int tx = rand() % (2*out.width) - out.width;
214428d7b3dSmrg			int ty = rand() % (2*out.height) - out.height;
215428d7b3dSmrg			uint8_t tile = rand();
216428d7b3dSmrg			uint8_t alu = rand() % (GXset + 1);
217428d7b3dSmrg			uint32_t fg = rand();
218428d7b3dSmrg			uint32_t bg = rand();
219428d7b3dSmrg
220428d7b3dSmrg			fill_rect(&out, alu, NULL, 0,
221428d7b3dSmrg				  tile, tx, ty,
222428d7b3dSmrg				  x, y, w, h,
223428d7b3dSmrg				  fg, bg);
224428d7b3dSmrg			fill_rect(&ref, alu, NULL, 0,
225428d7b3dSmrg				  tile, tx, ty,
226428d7b3dSmrg				  x, y, w, h,
227428d7b3dSmrg				  fg, bg);
228428d7b3dSmrg		}
229428d7b3dSmrg
230428d7b3dSmrg		test_compare(t,
231428d7b3dSmrg			     out.draw, out.format,
232428d7b3dSmrg			     ref.draw, ref.format,
233428d7b3dSmrg			     0, 0, out.width, out.height,
234428d7b3dSmrg			     "");
235428d7b3dSmrg
236428d7b3dSmrg		if (target == CHILD) {
237428d7b3dSmrg			int x = rand() % (t->out.width-out.width);
238428d7b3dSmrg			int y = rand() % (t->out.height-out.height);
239428d7b3dSmrg
240428d7b3dSmrg			clear(&out);
241428d7b3dSmrg			clear(&ref);
242428d7b3dSmrg
243428d7b3dSmrg			XMoveWindow(out.dpy->dpy, out.draw, x, y);
244428d7b3dSmrg			XMoveWindow(ref.dpy->dpy, ref.draw, x, y);
245428d7b3dSmrg
246428d7b3dSmrg			clear(&out);
247428d7b3dSmrg			clear(&ref);
248428d7b3dSmrg		}
249428d7b3dSmrg	}
250428d7b3dSmrg
251428d7b3dSmrg	printf("passed [%d iterations x %d]\n", reps, sets);
252428d7b3dSmrg
253428d7b3dSmrg	test_target_destroy_render(&t->out, &out);
254428d7b3dSmrg	test_target_destroy_render(&t->ref, &ref);
255428d7b3dSmrg}
256428d7b3dSmrg
257428d7b3dSmrgstatic void simple_clip_tests(struct test *t, int reps, int sets, enum target target)
258428d7b3dSmrg{
259428d7b3dSmrg	struct test_target out, ref;
260428d7b3dSmrg	int r, s;
261428d7b3dSmrg
262428d7b3dSmrg	printf("Testing simple clipped tiled fills (%s): ", test_target_name(target));
263428d7b3dSmrg	fflush(stdout);
264428d7b3dSmrg
265428d7b3dSmrg	test_target_create_render(&t->out, target, &out);
266428d7b3dSmrg	clear(&out);
267428d7b3dSmrg
268428d7b3dSmrg	test_target_create_render(&t->ref, target, &ref);
269428d7b3dSmrg	clear(&ref);
270428d7b3dSmrg
271428d7b3dSmrg	for (s = 0; s < sets; s++) {
272428d7b3dSmrg		for (r = 0; r < reps; r++) {
273428d7b3dSmrg			int x = rand() % (2*out.width) - out.width;
274428d7b3dSmrg			int y = rand() % (2*out.height) - out.height;
275428d7b3dSmrg			int w = rand() % (2*out.width);
276428d7b3dSmrg			int h = rand() % (2*out.height);
277428d7b3dSmrg			int tx = rand() % (2*out.width) - out.width;
278428d7b3dSmrg			int ty = rand() % (2*out.height) - out.height;
279428d7b3dSmrg			uint8_t tile = rand();
280428d7b3dSmrg			uint8_t alu = rand() % (GXset + 1);
281428d7b3dSmrg			uint32_t fg = rand();
282428d7b3dSmrg			uint32_t bg = rand();
283428d7b3dSmrg
284428d7b3dSmrg			fill_rect(&out, alu, NULL, 0,
285428d7b3dSmrg				  tile, tx, ty,
286428d7b3dSmrg				  x, y, w, h,
287428d7b3dSmrg				  fg, bg);
288428d7b3dSmrg			fill_rect(&ref, alu, NULL, 0,
289428d7b3dSmrg				  tile, tx, ty,
290428d7b3dSmrg				  x, y, w, h,
291428d7b3dSmrg				  fg, bg);
292428d7b3dSmrg		}
293428d7b3dSmrg
294428d7b3dSmrg		test_compare(t,
295428d7b3dSmrg			     out.draw, out.format,
296428d7b3dSmrg			     ref.draw, ref.format,
297428d7b3dSmrg			     0, 0, out.width, out.height,
298428d7b3dSmrg			     "");
299428d7b3dSmrg
300428d7b3dSmrg		if (target == CHILD) {
301428d7b3dSmrg			int x = rand() % (t->out.width-out.width);
302428d7b3dSmrg			int y = rand() % (t->out.height-out.height);
303428d7b3dSmrg
304428d7b3dSmrg			clear(&out);
305428d7b3dSmrg			clear(&ref);
306428d7b3dSmrg
307428d7b3dSmrg			XMoveWindow(out.dpy->dpy, out.draw, x, y);
308428d7b3dSmrg			XMoveWindow(ref.dpy->dpy, ref.draw, x, y);
309428d7b3dSmrg
310428d7b3dSmrg			clear(&out);
311428d7b3dSmrg			clear(&ref);
312428d7b3dSmrg		}
313428d7b3dSmrg	}
314428d7b3dSmrg
315428d7b3dSmrg	printf("passed [%d iterations x %d]\n", reps, sets);
316428d7b3dSmrg
317428d7b3dSmrg	test_target_destroy_render(&t->out, &out);
318428d7b3dSmrg	test_target_destroy_render(&t->ref, &ref);
319428d7b3dSmrg}
320428d7b3dSmrg
321428d7b3dSmrgstatic void complex_clip_tests(struct test *t, int reps, int sets, enum target target)
322428d7b3dSmrg{
323428d7b3dSmrg	struct test_target out, ref;
324428d7b3dSmrg	XRectangle *clip;
325428d7b3dSmrg	int nclip, r, s;
326428d7b3dSmrg
327428d7b3dSmrg	printf("Testing complex clipped tiled fills (%s): ", test_target_name(target));
328428d7b3dSmrg	fflush(stdout);
329428d7b3dSmrg
330428d7b3dSmrg	test_target_create_render(&t->out, target, &out);
331428d7b3dSmrg	clear(&out);
332428d7b3dSmrg
333428d7b3dSmrg	test_target_create_render(&t->ref, target, &ref);
334428d7b3dSmrg	clear(&ref);
335428d7b3dSmrg
336428d7b3dSmrg	for (s = 0; s < sets; s++) {
337428d7b3dSmrg		nclip = (rand() % 16) + 2;
338428d7b3dSmrg		clip = malloc(sizeof(XRectangle)*nclip);
339428d7b3dSmrg		for (r = 0; r < nclip; r++) {
340428d7b3dSmrg			clip[r].x = rand() % out.width;
341428d7b3dSmrg			clip[r].y = rand() % out.height;
342428d7b3dSmrg			clip[r].width = rand() % (out.width - clip[r].x);
343428d7b3dSmrg			clip[r].height = rand() % (out.height - clip[r].y);
344428d7b3dSmrg		}
345428d7b3dSmrg
346428d7b3dSmrg		for (r = 0; r < reps; r++) {
347428d7b3dSmrg			int x = rand() % (2*out.width) - out.width;
348428d7b3dSmrg			int y = rand() % (2*out.height) - out.height;
349428d7b3dSmrg			int w = rand() % (2*out.width);
350428d7b3dSmrg			int h = rand() % (2*out.height);
351428d7b3dSmrg			int tx = rand() % (2*out.width) - out.width;
352428d7b3dSmrg			int ty = rand() % (2*out.height) - out.height;
353428d7b3dSmrg			uint8_t tile = rand();
354428d7b3dSmrg			uint8_t alu = rand() % (GXset + 1);
355428d7b3dSmrg			uint32_t fg = rand();
356428d7b3dSmrg			uint32_t bg = rand();
357428d7b3dSmrg
358428d7b3dSmrg			fill_rect(&out, alu, clip, nclip,
359428d7b3dSmrg				  tile, tx, ty,
360428d7b3dSmrg				  x, y, w, h,
361428d7b3dSmrg				  fg, bg);
362428d7b3dSmrg			fill_rect(&ref, alu, clip, nclip,
363428d7b3dSmrg				  tile, tx, ty,
364428d7b3dSmrg				  x, y, w, h,
365428d7b3dSmrg				  fg, bg);
366428d7b3dSmrg		}
367428d7b3dSmrg
368428d7b3dSmrg		test_compare(t,
369428d7b3dSmrg			     out.draw, out.format,
370428d7b3dSmrg			     ref.draw, ref.format,
371428d7b3dSmrg			     0, 0, out.width, out.height,
372428d7b3dSmrg			     "");
373428d7b3dSmrg
374428d7b3dSmrg		free(clip);
375428d7b3dSmrg
376428d7b3dSmrg		if (target == CHILD) {
377428d7b3dSmrg			int x = rand() % (t->out.width-out.width);
378428d7b3dSmrg			int y = rand() % (t->out.height-out.height);
379428d7b3dSmrg
380428d7b3dSmrg			clear(&out);
381428d7b3dSmrg			clear(&ref);
382428d7b3dSmrg
383428d7b3dSmrg			XMoveWindow(out.dpy->dpy, out.draw, x, y);
384428d7b3dSmrg			XMoveWindow(ref.dpy->dpy, ref.draw, x, y);
385428d7b3dSmrg
386428d7b3dSmrg			clear(&out);
387428d7b3dSmrg			clear(&ref);
388428d7b3dSmrg		}
389428d7b3dSmrg	}
390428d7b3dSmrg
391428d7b3dSmrg	printf("passed [%d iterations x %d]\n", reps, sets);
392428d7b3dSmrg
393428d7b3dSmrg	test_target_destroy_render(&t->out, &out);
394428d7b3dSmrg	test_target_destroy_render(&t->ref, &ref);
395428d7b3dSmrg}
396428d7b3dSmrg
397428d7b3dSmrgint main(int argc, char **argv)
398428d7b3dSmrg{
399428d7b3dSmrg	struct test test;
400428d7b3dSmrg	int i;
401428d7b3dSmrg
402428d7b3dSmrg	test_init(&test, argc, argv);
403428d7b3dSmrg
404428d7b3dSmrg	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
405428d7b3dSmrg		int reps = REPS(i), sets = SETS(i);
406428d7b3dSmrg		enum target t;
407428d7b3dSmrg
408428d7b3dSmrg		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
409428d7b3dSmrg			small_tests(&test, reps, sets, t);
410428d7b3dSmrg			unclipped_tests(&test, reps, sets, t);
411428d7b3dSmrg			simple_clip_tests(&test, reps, sets, t);
412428d7b3dSmrg			complex_clip_tests(&test, reps, sets, t);
413428d7b3dSmrg			reset_cache();
414428d7b3dSmrg		}
415428d7b3dSmrg	}
416428d7b3dSmrg
417428d7b3dSmrg	return 0;
418428d7b3dSmrg}
419