142542f5fSchristos#include <stdint.h>
242542f5fSchristos#include <stdio.h>
342542f5fSchristos#include <stdlib.h>
442542f5fSchristos
542542f5fSchristos#include "test.h"
642542f5fSchristos
742542f5fSchristosstatic unsigned char bitmap4x4[] = {
842542f5fSchristos	   0x03, 0x06, 0x0c, 0x09
942542f5fSchristos};
1042542f5fSchristos
1142542f5fSchristosstatic unsigned char bitmap8x8[3][8] = {
1242542f5fSchristos	{ 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 },
1342542f5fSchristos	{ 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe },
1442542f5fSchristos	{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa },
1542542f5fSchristos};
1642542f5fSchristos
1742542f5fSchristosstatic void fill_rect(struct test_target *t, uint8_t alu,
1842542f5fSchristos		      XRectangle *clip, int nclip,
1942542f5fSchristos		      uint8_t stipple, uint8_t opaque, int tx, int ty,
2042542f5fSchristos		      int x, int y, int w, int h,
2142542f5fSchristos		      uint32_t fg, uint32_t bg)
2242542f5fSchristos{
2342542f5fSchristos	Display *dpy = t->dpy->dpy;
2442542f5fSchristos	XGCValues val;
2542542f5fSchristos	GC gc;
2642542f5fSchristos
2742542f5fSchristos	val.function = alu;
2842542f5fSchristos	val.foreground = fg;
2942542f5fSchristos	val.background = bg;
3042542f5fSchristos	val.fill_style = opaque ? FillOpaqueStippled : FillStippled;
3142542f5fSchristos	val.ts_x_origin = tx;
3242542f5fSchristos	val.ts_y_origin = ty;
3342542f5fSchristos	if (stipple == 0) {
3442542f5fSchristos		val.stipple = XCreateBitmapFromData(dpy, t->draw, (char *)bitmap4x4, 4, 4);
3542542f5fSchristos	} else {
3642542f5fSchristos		char *b = (char *)bitmap8x8[stipple-1];
3742542f5fSchristos		val.stipple = XCreateBitmapFromData(dpy, t->draw, b, 8, 8);
3842542f5fSchristos	}
3942542f5fSchristos
4042542f5fSchristos	gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCStipple | GCForeground | GCBackground | GCFunction, &val);
4142542f5fSchristos	if (nclip)
4242542f5fSchristos		XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted);
4342542f5fSchristos	XFillRectangle(dpy, t->draw, gc, x, y, w, h);
4442542f5fSchristos	XFreeGC(dpy, gc);
4542542f5fSchristos	XFreePixmap(dpy, val.stipple);
4642542f5fSchristos}
4742542f5fSchristos
4842542f5fSchristosstatic void clear(struct test_target *tt)
4942542f5fSchristos{
5042542f5fSchristos	XRenderColor render_color = {0};
5142542f5fSchristos	XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color,
5242542f5fSchristos			     0, 0, tt->width, tt->height);
5342542f5fSchristos}
5442542f5fSchristos
5542542f5fSchristosstatic void unclipped_tests(struct test *t, int reps, int sets, enum target target)
5642542f5fSchristos{
5742542f5fSchristos	struct test_target out, ref;
5842542f5fSchristos	int r, s;
5942542f5fSchristos
6042542f5fSchristos	printf("Testing unclipped stippled fills (%s): ", test_target_name(target));
6142542f5fSchristos	fflush(stdout);
6242542f5fSchristos
6342542f5fSchristos	test_target_create_render(&t->out, target, &out);
6442542f5fSchristos	clear(&out);
6542542f5fSchristos
6642542f5fSchristos	test_target_create_render(&t->ref, target, &ref);
6742542f5fSchristos	clear(&ref);
6842542f5fSchristos
6942542f5fSchristos	for (s = 0; s < sets; s++) {
7042542f5fSchristos		for (r = 0; r < reps; r++) {
7142542f5fSchristos			int x = rand() % out.width;
7242542f5fSchristos			int y = rand() % out.height;
7342542f5fSchristos			int w = rand() % (out.width - x);
7442542f5fSchristos			int h = rand() % (out.height - y);
7542542f5fSchristos			int tx = rand() % (2*out.width) - out.width;
7642542f5fSchristos			int ty = rand() % (2*out.height) - out.height;
7742542f5fSchristos			uint8_t stipple = rand() % 4;
7842542f5fSchristos			uint8_t opaque = rand() % 1;
7942542f5fSchristos			uint8_t alu = rand() % (GXset + 1);
8042542f5fSchristos			uint32_t fg = rand();
8142542f5fSchristos			uint32_t bg = rand();
8242542f5fSchristos
8342542f5fSchristos			fill_rect(&out, alu, NULL, 0,
8442542f5fSchristos				  stipple, opaque, tx, ty,
8542542f5fSchristos				  x, y, w, h,
8642542f5fSchristos				  fg, bg);
8742542f5fSchristos			fill_rect(&ref, alu, NULL, 0,
8842542f5fSchristos				  stipple, opaque, tx, ty,
8942542f5fSchristos				  x, y, w, h,
9042542f5fSchristos				  fg, bg);
9142542f5fSchristos		}
9242542f5fSchristos
9342542f5fSchristos		test_compare(t,
9442542f5fSchristos			     out.draw, out.format,
9542542f5fSchristos			     ref.draw, ref.format,
9642542f5fSchristos			     0, 0, out.width, out.height,
9742542f5fSchristos			     "");
9842542f5fSchristos	}
9942542f5fSchristos
10042542f5fSchristos	printf("passed [%d iterations x %d]\n", reps, sets);
10142542f5fSchristos
10242542f5fSchristos	test_target_destroy_render(&t->out, &out);
10342542f5fSchristos	test_target_destroy_render(&t->ref, &ref);
10442542f5fSchristos}
10542542f5fSchristos
10642542f5fSchristosstatic void simple_clip_tests(struct test *t, int reps, int sets, enum target target)
10742542f5fSchristos{
10842542f5fSchristos	struct test_target out, ref;
10942542f5fSchristos	int r, s;
11042542f5fSchristos
11142542f5fSchristos	printf("Testing simple clipped stippled fills (%s): ", test_target_name(target));
11242542f5fSchristos	fflush(stdout);
11342542f5fSchristos
11442542f5fSchristos	test_target_create_render(&t->out, target, &out);
11542542f5fSchristos	clear(&out);
11642542f5fSchristos
11742542f5fSchristos	test_target_create_render(&t->ref, target, &ref);
11842542f5fSchristos	clear(&ref);
11942542f5fSchristos
12042542f5fSchristos	for (s = 0; s < sets; s++) {
12142542f5fSchristos		for (r = 0; r < reps; r++) {
12242542f5fSchristos			int x = rand() % (2*out.width) - out.width;
12342542f5fSchristos			int y = rand() % (2*out.height) - out.height;
12442542f5fSchristos			int w = rand() % (2*out.width);
12542542f5fSchristos			int h = rand() % (2*out.height);
12642542f5fSchristos			int tx = rand() % (2*out.width) - out.width;
12742542f5fSchristos			int ty = rand() % (2*out.height) - out.height;
12842542f5fSchristos			uint8_t stipple = rand() % 4;
12942542f5fSchristos			uint8_t opaque = rand() % 1;
13042542f5fSchristos			uint8_t alu = rand() % (GXset + 1);
13142542f5fSchristos			uint32_t fg = rand();
13242542f5fSchristos			uint32_t bg = rand();
13342542f5fSchristos
13442542f5fSchristos			fill_rect(&out, alu, NULL, 0,
13542542f5fSchristos				  stipple, opaque, tx, ty,
13642542f5fSchristos				  x, y, w, h,
13742542f5fSchristos				  fg, bg);
13842542f5fSchristos			fill_rect(&ref, alu, NULL, 0,
13942542f5fSchristos				  stipple, opaque, tx, ty,
14042542f5fSchristos				  x, y, w, h,
14142542f5fSchristos				  fg, bg);
14242542f5fSchristos		}
14342542f5fSchristos
14442542f5fSchristos		test_compare(t,
14542542f5fSchristos			     out.draw, out.format,
14642542f5fSchristos			     ref.draw, ref.format,
14742542f5fSchristos			     0, 0, out.width, out.height,
14842542f5fSchristos			     "");
14942542f5fSchristos	}
15042542f5fSchristos
15142542f5fSchristos	printf("passed [%d iterations x %d]\n", reps, sets);
15242542f5fSchristos
15342542f5fSchristos	test_target_destroy_render(&t->out, &out);
15442542f5fSchristos	test_target_destroy_render(&t->ref, &ref);
15542542f5fSchristos}
15642542f5fSchristos
15742542f5fSchristosstatic void complex_clip_tests(struct test *t, int reps, int sets, enum target target)
15842542f5fSchristos{
15942542f5fSchristos	struct test_target out, ref;
16042542f5fSchristos	XRectangle *clip;
16142542f5fSchristos	int nclip, r, s;
16242542f5fSchristos
16342542f5fSchristos	printf("Testing complex clipped stippled fills (%s): ", test_target_name(target));
16442542f5fSchristos	fflush(stdout);
16542542f5fSchristos
16642542f5fSchristos	test_target_create_render(&t->out, target, &out);
16742542f5fSchristos	clear(&out);
16842542f5fSchristos
16942542f5fSchristos	test_target_create_render(&t->ref, target, &ref);
17042542f5fSchristos	clear(&ref);
17142542f5fSchristos
17242542f5fSchristos	for (s = 0; s < sets; s++) {
17342542f5fSchristos		nclip = (rand() % 16) + 2;
17442542f5fSchristos		clip = malloc(sizeof(XRectangle)*nclip);
17542542f5fSchristos		for (r = 0; r < nclip; r++) {
17642542f5fSchristos			clip[r].x = rand() % out.width;
17742542f5fSchristos			clip[r].y = rand() % out.height;
17842542f5fSchristos			clip[r].width = rand() % (out.width - clip[r].x);
17942542f5fSchristos			clip[r].height = rand() % (out.height - clip[r].y);
18042542f5fSchristos		}
18142542f5fSchristos
18242542f5fSchristos		for (r = 0; r < reps; r++) {
18342542f5fSchristos			int x = rand() % (2*out.width) - out.width;
18442542f5fSchristos			int y = rand() % (2*out.height) - out.height;
18542542f5fSchristos			int w = rand() % (2*out.width);
18642542f5fSchristos			int h = rand() % (2*out.height);
18742542f5fSchristos			int tx = rand() % (2*out.width) - out.width;
18842542f5fSchristos			int ty = rand() % (2*out.height) - out.height;
18942542f5fSchristos			uint8_t stipple = rand() % 4;
19042542f5fSchristos			uint8_t opaque = rand() % 1;
19142542f5fSchristos			uint8_t alu = rand() % (GXset + 1);
19242542f5fSchristos			uint32_t fg = rand();
19342542f5fSchristos			uint32_t bg = rand();
19442542f5fSchristos
19542542f5fSchristos			fill_rect(&out, alu, clip, nclip,
19642542f5fSchristos				  stipple, opaque, tx, ty,
19742542f5fSchristos				  x, y, w, h,
19842542f5fSchristos				  fg, bg);
19942542f5fSchristos			fill_rect(&ref, alu, clip, nclip,
20042542f5fSchristos				  stipple, opaque, tx, ty,
20142542f5fSchristos				  x, y, w, h,
20242542f5fSchristos				  fg, bg);
20342542f5fSchristos		}
20442542f5fSchristos
20542542f5fSchristos		test_compare(t,
20642542f5fSchristos			     out.draw, out.format,
20742542f5fSchristos			     ref.draw, ref.format,
20842542f5fSchristos			     0, 0, out.width, out.height,
20942542f5fSchristos			     "");
21042542f5fSchristos
21142542f5fSchristos		free(clip);
21242542f5fSchristos	}
21342542f5fSchristos
21442542f5fSchristos	printf("passed [%d iterations x %d]\n", reps, sets);
21542542f5fSchristos
21642542f5fSchristos	test_target_destroy_render(&t->out, &out);
21742542f5fSchristos	test_target_destroy_render(&t->ref, &ref);
21842542f5fSchristos}
21942542f5fSchristos
22042542f5fSchristosint main(int argc, char **argv)
22142542f5fSchristos{
22242542f5fSchristos	struct test test;
22342542f5fSchristos	int i;
22442542f5fSchristos
22542542f5fSchristos	test_init(&test, argc, argv);
22642542f5fSchristos
22742542f5fSchristos	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
22842542f5fSchristos		int reps = REPS(i), sets = SETS(i);
22942542f5fSchristos		enum target t;
23042542f5fSchristos
23142542f5fSchristos		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
23242542f5fSchristos			unclipped_tests(&test, reps, sets, t);
23342542f5fSchristos			simple_clip_tests(&test, reps, sets, t);
23442542f5fSchristos			complex_clip_tests(&test, reps, sets, t);
23542542f5fSchristos		}
23642542f5fSchristos	}
23742542f5fSchristos
23842542f5fSchristos	return 0;
23942542f5fSchristos}
240