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 _render_copy(struct test_target *tt,
11428d7b3dSmrg			 int x, int y, int w, int h,
12428d7b3dSmrg			 uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
13428d7b3dSmrg{
14428d7b3dSmrg	XRenderColor color;
15428d7b3dSmrg	Picture src;
16428d7b3dSmrg	Pixmap tmp;
17428d7b3dSmrg
18428d7b3dSmrg	tmp = XCreatePixmap(tt->dpy->dpy, DefaultRootWindow(tt->dpy->dpy),
19428d7b3dSmrg			    10+w, 20+h, tt->format->depth);
20428d7b3dSmrg	src = XRenderCreatePicture(tt->dpy->dpy, tmp, tt->format, 0, NULL);
21428d7b3dSmrg
22428d7b3dSmrg	/* magenta border */
23428d7b3dSmrg	color.red = 0xffff;
24428d7b3dSmrg	color.green = 0;
25428d7b3dSmrg	color.blue = 0xffff;
26428d7b3dSmrg	color.alpha = 0xffff;
27428d7b3dSmrg	XRenderFillRectangle(tt->dpy->dpy, PictOpSrc, src, &color, 0, 0, w+10, h+20);
28428d7b3dSmrg
29428d7b3dSmrg	color.red = red * alpha;
30428d7b3dSmrg	color.green = green * alpha;
31428d7b3dSmrg	color.blue = blue * alpha;
32428d7b3dSmrg	color.alpha = alpha << 8 | alpha;
33428d7b3dSmrg	XRenderFillRectangle(tt->dpy->dpy, PictOpSrc, src, &color, 5, 10, w, h);
34428d7b3dSmrg
35428d7b3dSmrg	XRenderComposite(tt->dpy->dpy, PictOpSrc,
36428d7b3dSmrg			 src, 0, tt->picture,
37428d7b3dSmrg			 5, 10,
38428d7b3dSmrg			 0, 0,
39428d7b3dSmrg			 x, y,
40428d7b3dSmrg			 w, h);
41428d7b3dSmrg
42428d7b3dSmrg	XRenderFreePicture(tt->dpy->dpy, src);
43428d7b3dSmrg	XFreePixmap(tt->dpy->dpy, tmp);
44428d7b3dSmrg}
45428d7b3dSmrg
46428d7b3dSmrgstatic void render_copy(struct test_target *out,
47428d7b3dSmrg			struct test_target *ref)
48428d7b3dSmrg{
49428d7b3dSmrg	int x = rand() % (2*out->width) - out->width;
50428d7b3dSmrg	int y = rand() % (2*out->height) - out->height;
51428d7b3dSmrg	int w = rand() % (2*out->width);
52428d7b3dSmrg	int h = rand() % (2*out->height);
53428d7b3dSmrg	int red = rand() & 0xff;
54428d7b3dSmrg	int green = rand() & 0xff;
55428d7b3dSmrg	int blue = rand() & 0xff;
56428d7b3dSmrg	int alpha = rand() & 0xff;
57428d7b3dSmrg
58428d7b3dSmrg	_render_copy(out, x, y, w, h, red, green, blue, alpha);
59428d7b3dSmrg	_render_copy(ref, x, y, w, h, red, green, blue, alpha);
60428d7b3dSmrg}
61428d7b3dSmrg
62428d7b3dSmrgstatic void fill_rect(struct test_target *tt,
63428d7b3dSmrg		      int alu, int color,
64428d7b3dSmrg		      int x, int y, int w, int h)
65428d7b3dSmrg{
66428d7b3dSmrg	XGCValues val;
67428d7b3dSmrg
68428d7b3dSmrg	val.function = alu;
69428d7b3dSmrg	val.foreground = color;
70428d7b3dSmrg	XChangeGC(tt->dpy->dpy, tt->gc, GCFunction | GCForeground, &val);
71428d7b3dSmrg
72428d7b3dSmrg	XFillRectangle(tt->dpy->dpy, tt->draw, tt->gc, x, y, w, h);
73428d7b3dSmrg}
74428d7b3dSmrg
75428d7b3dSmrgstatic void clear(struct test_target *tt)
76428d7b3dSmrg{
77428d7b3dSmrg	fill_rect(tt,
78428d7b3dSmrg		  GXcopy, 0,
79428d7b3dSmrg		  0, 0, tt->width, tt->height);
80428d7b3dSmrg}
81428d7b3dSmrg
82428d7b3dSmrgstatic void basic_fill(struct test_target *out,
83428d7b3dSmrg		       struct test_target *ref)
84428d7b3dSmrg{
85428d7b3dSmrg	int x = rand() % (2*out->width) - out->width;
86428d7b3dSmrg	int y = rand() % (2*out->height) - out->height;
87428d7b3dSmrg	int w = rand() % (2*out->width);
88428d7b3dSmrg	int h = rand() % (2*out->height);
89428d7b3dSmrg	int color = rand();
90428d7b3dSmrg	int alu = rand() % 16;
91428d7b3dSmrg
92428d7b3dSmrg	fill_rect(out, alu, color, x, y, w, h);
93428d7b3dSmrg	fill_rect(ref, alu, color, x, y, w, h);
94428d7b3dSmrg}
95428d7b3dSmrg
96428d7b3dSmrgstatic void basic_copy(struct test_target *out,
97428d7b3dSmrg		       struct test_target *ref)
98428d7b3dSmrg{
99428d7b3dSmrg	int sx = rand() % (2*out->width) - ref->width;
100428d7b3dSmrg	int sy = rand() % (2*out->height) - ref->height;
101428d7b3dSmrg	int dx = rand() % (2*out->width) - ref->width;
102428d7b3dSmrg	int dy = rand() % (2*out->height) - ref->height;
103428d7b3dSmrg	int w = rand() % (2*out->width);
104428d7b3dSmrg	int h = rand() % (2*out->height);
105428d7b3dSmrg	XGCValues val;
106428d7b3dSmrg
107428d7b3dSmrg	val.function = rand() % 16;
108428d7b3dSmrg
109428d7b3dSmrg	XChangeGC(out->dpy->dpy, out->gc, GCFunction, &val);
110428d7b3dSmrg	XCopyArea(out->dpy->dpy,
111428d7b3dSmrg		  out->draw, out->draw, out->gc,
112428d7b3dSmrg		  sx, sy, w, h, dx, dy);
113428d7b3dSmrg
114428d7b3dSmrg	XChangeGC(ref->dpy->dpy, ref->gc, GCFunction, &val);
115428d7b3dSmrg	XCopyArea(ref->dpy->dpy,
116428d7b3dSmrg		  ref->draw, ref->draw, ref->gc,
117428d7b3dSmrg		  sx, sy, w, h, dx, dy);
118428d7b3dSmrg}
119428d7b3dSmrg
120428d7b3dSmrgstatic void _put(struct test_target *tt,
121428d7b3dSmrg		 int x, int y, int w,int h, int color, int alu)
122428d7b3dSmrg{
123428d7b3dSmrg	XImage image;
124428d7b3dSmrg	XGCValues val;
125428d7b3dSmrg
126428d7b3dSmrg	val.function = alu;
127428d7b3dSmrg
128428d7b3dSmrg	test_init_image(&image, &tt->dpy->shm, tt->format, w, h);
129428d7b3dSmrg	pixman_fill((uint32_t*)image.data,
130428d7b3dSmrg		    image.bytes_per_line/sizeof(uint32_t),
131428d7b3dSmrg		    image.bits_per_pixel,
132428d7b3dSmrg		    0, 0, w, h, color);
133428d7b3dSmrg
134428d7b3dSmrg	XChangeGC(tt->dpy->dpy, tt->gc, GCFunction, &val);
135428d7b3dSmrg	if (rand() & 1) {
136428d7b3dSmrg		XShmPutImage(tt->dpy->dpy, tt->draw, tt->gc, &image,
137428d7b3dSmrg			     0, 0, x, y, w, h, 0);
138428d7b3dSmrg		XSync(tt->dpy->dpy, 1);
139428d7b3dSmrg	} else {
140428d7b3dSmrg		XPutImage(tt->dpy->dpy, tt->draw, tt->gc, &image,
141428d7b3dSmrg			  0, 0, x, y, w, h);
142428d7b3dSmrg	}
143428d7b3dSmrg}
144428d7b3dSmrg
145428d7b3dSmrgstatic void basic_put(struct test_target *out,
146428d7b3dSmrg		      struct test_target *ref)
147428d7b3dSmrg{
148428d7b3dSmrg	int x = rand() % (2*out->width) - out->width;
149428d7b3dSmrg	int y = rand() % (2*out->height) - out->height;
150428d7b3dSmrg	int w = rand() % out->width;
151428d7b3dSmrg	int h = rand() % out->height;
152428d7b3dSmrg	int color = rand();
153428d7b3dSmrg	int alu = rand() % 16;
154428d7b3dSmrg
155428d7b3dSmrg	_put(out, x, y, w, h, color, alu);
156428d7b3dSmrg	_put(ref, x, y, w, h, color, alu);
157428d7b3dSmrg}
158428d7b3dSmrg
159428d7b3dSmrgstatic void rect_tests(struct test *test, int iterations, enum target target)
160428d7b3dSmrg{
161428d7b3dSmrg	struct test_target out, ref;
162428d7b3dSmrg	void (* const ops[])(struct test_target *, struct test_target *) = {
163428d7b3dSmrg		basic_copy,
164428d7b3dSmrg		basic_fill,
165428d7b3dSmrg		basic_put,
166428d7b3dSmrg		render_copy,
167428d7b3dSmrg	};
168428d7b3dSmrg	int n;
169428d7b3dSmrg
170428d7b3dSmrg	printf("Running mixed ops stress against %s: ",
171428d7b3dSmrg	       test_target_name(target));
172428d7b3dSmrg	fflush(stdout);
173428d7b3dSmrg
174428d7b3dSmrg	test_target_create_render(&test->out, target, &out);
175428d7b3dSmrg	test_target_create_render(&test->ref, target, &ref);
176428d7b3dSmrg
177428d7b3dSmrg	clear(&out);
178428d7b3dSmrg	clear(&ref);
179428d7b3dSmrg
180428d7b3dSmrg	for (n = 0; n < iterations; n++)
181428d7b3dSmrg		ops[rand() % ARRAY_SIZE(ops)](&out, &ref);
182428d7b3dSmrg
183428d7b3dSmrg	test_compare(test,
184428d7b3dSmrg		     out.draw, out.format,
185428d7b3dSmrg		     ref.draw, ref.format,
186428d7b3dSmrg		     0, 0, out.width, out.height,
187428d7b3dSmrg		     "");
188428d7b3dSmrg
189428d7b3dSmrg	printf("passed [%d iterations]\n", n);
190428d7b3dSmrg
191428d7b3dSmrg	test_target_destroy_render(&test->out, &out);
192428d7b3dSmrg	test_target_destroy_render(&test->ref, &ref);
193428d7b3dSmrg}
194428d7b3dSmrg
195428d7b3dSmrgint main(int argc, char **argv)
196428d7b3dSmrg{
197428d7b3dSmrg	struct test test;
198428d7b3dSmrg	int i;
199428d7b3dSmrg
200428d7b3dSmrg	test_init(&test, argc, argv);
201428d7b3dSmrg
202428d7b3dSmrg	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
203428d7b3dSmrg		int iterations = REPS(i);
204428d7b3dSmrg		rect_tests(&test, iterations, 0);
205428d7b3dSmrg		rect_tests(&test, iterations, 1);
206428d7b3dSmrg	}
207428d7b3dSmrg
208428d7b3dSmrg	return 0;
209428d7b3dSmrg}
210