1428d7b3dSmrg#include <stdint.h>
2428d7b3dSmrg#include <stdio.h>
3428d7b3dSmrg#include <stdlib.h>
4428d7b3dSmrg
5428d7b3dSmrg#include <X11/Xutil.h> /* for XDestroyImage */
6428d7b3dSmrg#include <pixman.h>
7428d7b3dSmrg
8428d7b3dSmrg#include "test.h"
9428d7b3dSmrg
10428d7b3dSmrgstatic void fill_rect(struct test_target *tt,
11428d7b3dSmrg		      int alu, int color,
12428d7b3dSmrg		      int x, int y, int w, int h)
13428d7b3dSmrg{
14428d7b3dSmrg	XGCValues val;
15428d7b3dSmrg
16428d7b3dSmrg	val.function = alu;
17428d7b3dSmrg	val.foreground = color;
18428d7b3dSmrg	XChangeGC(tt->dpy->dpy, tt->gc, GCFunction | GCForeground, &val);
19428d7b3dSmrg
20428d7b3dSmrg	XFillRectangle(tt->dpy->dpy, tt->draw, tt->gc, x, y, w, h);
21428d7b3dSmrg}
22428d7b3dSmrg
23428d7b3dSmrgstatic void clear(struct test_target *tt)
24428d7b3dSmrg{
25428d7b3dSmrg	fill_rect(tt,
26428d7b3dSmrg		  GXcopy, 0,
27428d7b3dSmrg		  0, 0, tt->width, tt->height);
28428d7b3dSmrg}
29428d7b3dSmrg
30428d7b3dSmrgstatic void fill(struct test_target *out,
31428d7b3dSmrg		 struct test_target *ref)
32428d7b3dSmrg{
33428d7b3dSmrg	int x = rand() % (2*out->width) - out->width;
34428d7b3dSmrg	int y = rand() % (2*out->height) - out->height;
35428d7b3dSmrg	int w = rand() % (2*out->width);
36428d7b3dSmrg	int h = rand() % (2*out->height);
37428d7b3dSmrg	int color = rand();
38428d7b3dSmrg	int alu = rand() % 16;
39428d7b3dSmrg
40428d7b3dSmrg	fill_rect(out, alu, color, x, y, w, h);
41428d7b3dSmrg	fill_rect(ref, alu, color, x, y, w, h);
42428d7b3dSmrg}
43428d7b3dSmrg
44428d7b3dSmrgstatic void copy(struct test_target *out,
45428d7b3dSmrg		 struct test_target *ref)
46428d7b3dSmrg{
47428d7b3dSmrg	int sx = rand() % (2*out->width) - ref->width;
48428d7b3dSmrg	int sy = rand() % (2*out->height) - ref->height;
49428d7b3dSmrg	int dx = rand() % (2*out->width) - ref->width;
50428d7b3dSmrg	int dy = rand() % (2*out->height) - ref->height;
51428d7b3dSmrg	int w = rand() % (2*out->width);
52428d7b3dSmrg	int h = rand() % (2*out->height);
53428d7b3dSmrg	XGCValues val;
54428d7b3dSmrg
55428d7b3dSmrg	val.function = rand() % 16;
56428d7b3dSmrg
57428d7b3dSmrg	XChangeGC(out->dpy->dpy, out->gc, GCFunction, &val);
58428d7b3dSmrg	XCopyArea(out->dpy->dpy,
59428d7b3dSmrg		  out->draw, out->draw, out->gc,
60428d7b3dSmrg		  sx, sy, w, h, dx, dy);
61428d7b3dSmrg
62428d7b3dSmrg	XChangeGC(ref->dpy->dpy, ref->gc, GCFunction, &val);
63428d7b3dSmrg	XCopyArea(ref->dpy->dpy,
64428d7b3dSmrg		  ref->draw, ref->draw, ref->gc,
65428d7b3dSmrg		  sx, sy, w, h, dx, dy);
66428d7b3dSmrg}
67428d7b3dSmrg
68428d7b3dSmrgstatic void _put(struct test_target *tt,
69428d7b3dSmrg		 int x, int y, int w,int h, int color, int alu)
70428d7b3dSmrg{
71428d7b3dSmrg	XImage image;
72428d7b3dSmrg	XGCValues val;
73428d7b3dSmrg
74428d7b3dSmrg	val.function = alu;
75428d7b3dSmrg
76428d7b3dSmrg	test_init_image(&image, &tt->dpy->shm, tt->format, w, h);
77428d7b3dSmrg	pixman_fill((uint32_t*)image.data,
78428d7b3dSmrg		    image.bytes_per_line/sizeof(uint32_t),
79428d7b3dSmrg		    image.bits_per_pixel,
80428d7b3dSmrg		    0, 0, w, h, color);
81428d7b3dSmrg
82428d7b3dSmrg	XChangeGC(tt->dpy->dpy, tt->gc, GCFunction, &val);
83428d7b3dSmrg	if (rand() & 1) {
84428d7b3dSmrg		XShmPutImage(tt->dpy->dpy, tt->draw, tt->gc, &image,
85428d7b3dSmrg			     0, 0, x, y, w, h, 0);
86428d7b3dSmrg		XSync(tt->dpy->dpy, 1);
87428d7b3dSmrg	} else {
88428d7b3dSmrg		XPutImage(tt->dpy->dpy, tt->draw, tt->gc, &image,
89428d7b3dSmrg			  0, 0, x, y, w, h);
90428d7b3dSmrg	}
91428d7b3dSmrg}
92428d7b3dSmrg
93428d7b3dSmrgstatic void put(struct test_target *out,
94428d7b3dSmrg		struct test_target *ref)
95428d7b3dSmrg{
96428d7b3dSmrg	int x = rand() % (2*out->width) - out->width;
97428d7b3dSmrg	int y = rand() % (2*out->height) - out->height;
98428d7b3dSmrg	int w = rand() % out->width;
99428d7b3dSmrg	int h = rand() % out->height;
100428d7b3dSmrg	int color = rand();
101428d7b3dSmrg	int alu = rand() % 16;
102428d7b3dSmrg
103428d7b3dSmrg	_put(out, x, y, w, h, color, alu);
104428d7b3dSmrg	_put(ref, x, y, w, h, color, alu);
105428d7b3dSmrg}
106428d7b3dSmrg
107428d7b3dSmrgstatic void rect_tests(struct test *test, int iterations, enum target target)
108428d7b3dSmrg{
109428d7b3dSmrg	struct test_target out, ref;
110428d7b3dSmrg	void (* const ops[])(struct test_target *, struct test_target *) = {
111428d7b3dSmrg		copy,
112428d7b3dSmrg		fill,
113428d7b3dSmrg		put,
114428d7b3dSmrg	};
115428d7b3dSmrg	int n;
116428d7b3dSmrg
117428d7b3dSmrg	printf("Running mixed ops stress against %s: ",
118428d7b3dSmrg	       test_target_name(target));
119428d7b3dSmrg	fflush(stdout);
120428d7b3dSmrg
121428d7b3dSmrg	test_target_create_render(&test->out, target, &out);
122428d7b3dSmrg	test_target_create_render(&test->ref, target, &ref);
123428d7b3dSmrg
124428d7b3dSmrg	clear(&out);
125428d7b3dSmrg	clear(&ref);
126428d7b3dSmrg
127428d7b3dSmrg	for (n = 0; n < iterations; n++)
128428d7b3dSmrg		ops[rand() % ARRAY_SIZE(ops)](&out, &ref);
129428d7b3dSmrg
130428d7b3dSmrg	test_compare(test,
131428d7b3dSmrg		     out.draw, out.format,
132428d7b3dSmrg		     ref.draw, ref.format,
133428d7b3dSmrg		     0, 0, out.width, out.height,
134428d7b3dSmrg		     "");
135428d7b3dSmrg
136428d7b3dSmrg	printf("passed [%d iterations]\n", n);
137428d7b3dSmrg
138428d7b3dSmrg	test_target_destroy_render(&test->out, &out);
139428d7b3dSmrg	test_target_destroy_render(&test->ref, &ref);
140428d7b3dSmrg}
141428d7b3dSmrg
142428d7b3dSmrgint main(int argc, char **argv)
143428d7b3dSmrg{
144428d7b3dSmrg	struct test test;
145428d7b3dSmrg	int i;
146428d7b3dSmrg
147428d7b3dSmrg	test_init(&test, argc, argv);
148428d7b3dSmrg
149428d7b3dSmrg	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
150428d7b3dSmrg		int iterations = REPS(i);
151428d7b3dSmrg		rect_tests(&test, iterations, 0);
152428d7b3dSmrg		rect_tests(&test, iterations, 1);
153428d7b3dSmrg	}
154428d7b3dSmrg
155428d7b3dSmrg	return 0;
156428d7b3dSmrg}
157