142542f5fSchristos#include <stdint.h>
242542f5fSchristos#include <stdio.h>
342542f5fSchristos#include <stdlib.h>
442542f5fSchristos
542542f5fSchristos#include <X11/Xutil.h> /* for XDestroyImage */
642542f5fSchristos
742542f5fSchristos#include "test.h"
842542f5fSchristos
942542f5fSchristosstatic void fill_rect(struct test_display *t,
1042542f5fSchristos		      Picture p,
1142542f5fSchristos		      XRenderPictFormat *format,
1242542f5fSchristos		      int use_window, int tx, int ty,
1342542f5fSchristos		      uint8_t op, int x, int y, int w, int h,
1442542f5fSchristos		      int mask_x, int mask_y, int mask_w, int mask_h,
1542542f5fSchristos		      uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
1642542f5fSchristos{
1742542f5fSchristos	Drawable tmp;
1842542f5fSchristos	Pixmap pixmask;
1942542f5fSchristos	XRenderColor c;
2042542f5fSchristos	Picture src, mask;
2142542f5fSchristos
2242542f5fSchristos	if (use_window) {
2342542f5fSchristos		XSetWindowAttributes attr;
2442542f5fSchristos
2542542f5fSchristos		attr.override_redirect = 1;
2642542f5fSchristos		tmp = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy),
2742542f5fSchristos				    tx, ty,
2842542f5fSchristos				    w, h,
2942542f5fSchristos				    0, format->depth,
3042542f5fSchristos				    InputOutput,
3142542f5fSchristos				    DefaultVisual(t->dpy,
3242542f5fSchristos						  DefaultScreen(t->dpy)),
3342542f5fSchristos				    CWOverrideRedirect, &attr);
3442542f5fSchristos		XMapWindow(t->dpy, tmp);
3542542f5fSchristos	} else
3642542f5fSchristos		tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy),
3742542f5fSchristos				    w, h, format->depth);
3842542f5fSchristos
3942542f5fSchristos	pixmask = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy), w, h, 8);
4042542f5fSchristos	mask = XRenderCreatePicture(t->dpy, pixmask,
4142542f5fSchristos				    XRenderFindStandardFormat(t->dpy, PictStandardA8),
4242542f5fSchristos				    0, NULL);
4342542f5fSchristos	c.red = c.green = c.blue = c.alpha = 0;
4442542f5fSchristos	XRenderFillRectangle(t->dpy, PictOpSrc, mask, &c,
4542542f5fSchristos			     0, 0, w, h);
4642542f5fSchristos	c.red = c.green = c.blue = c.alpha = 0xffff;
4742542f5fSchristos	XRenderFillRectangle(t->dpy, PictOpSrc, mask, &c,
4842542f5fSchristos			     mask_x, mask_y, mask_w, mask_h);
4942542f5fSchristos
5042542f5fSchristos	src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL);
5142542f5fSchristos	c.red = red * alpha;
5242542f5fSchristos	c.green = green * alpha;
5342542f5fSchristos	c.blue = blue * alpha;
5442542f5fSchristos	c.alpha = alpha << 8 | alpha;
5542542f5fSchristos	XRenderFillRectangle(t->dpy, PictOpSrc, src, &c, 0, 0, w, h);
5642542f5fSchristos
5742542f5fSchristos	XRenderComposite(t->dpy, op, src, mask, p, 0, 0, 0, 0, x, y, w, h);
5842542f5fSchristos
5942542f5fSchristos	XRenderFreePicture(t->dpy, src);
6042542f5fSchristos	if (use_window)
6142542f5fSchristos		XDestroyWindow(t->dpy, tmp);
6242542f5fSchristos	else
6342542f5fSchristos		XFreePixmap(t->dpy, tmp);
6442542f5fSchristos
6542542f5fSchristos	XRenderFreePicture(t->dpy, mask);
6642542f5fSchristos	XFreePixmap(t->dpy, pixmask);
6742542f5fSchristos}
6842542f5fSchristos
6942542f5fSchristosstatic void clear(struct test_display *dpy, struct test_target *tt)
7042542f5fSchristos{
7142542f5fSchristos	XRenderColor render_color = {0};
7242542f5fSchristos	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
7342542f5fSchristos			     0, 0, tt->width, tt->height);
7442542f5fSchristos}
7542542f5fSchristos
7642542f5fSchristosstatic void rect_tests(struct test *t, int reps, int sets, enum target target, int use_window)
7742542f5fSchristos{
7842542f5fSchristos	struct test_target out, ref;
7942542f5fSchristos	int r, s;
8042542f5fSchristos	printf("Testing area fills (%s, using %s source): ",
8142542f5fSchristos	       test_target_name(target), use_window ? "window" : "pixmap");
8242542f5fSchristos	fflush(stdout);
8342542f5fSchristos
8442542f5fSchristos	test_target_create_render(&t->out, target, &out);
8542542f5fSchristos	clear(&t->out, &out);
8642542f5fSchristos
8742542f5fSchristos	test_target_create_render(&t->ref, target, &ref);
8842542f5fSchristos	clear(&t->ref, &ref);
8942542f5fSchristos
9042542f5fSchristos	for (s = 0; s < sets; s++) {
9142542f5fSchristos		for (r = 0; r < reps; r++) {
9242542f5fSchristos			int x, y, w, h;
9342542f5fSchristos			int mask_x, mask_y, mask_w, mask_h;
9442542f5fSchristos			int tmpx, tmpy;
9542542f5fSchristos			uint8_t red = rand();
9642542f5fSchristos			uint8_t green = rand();
9742542f5fSchristos			uint8_t blue = rand();
9842542f5fSchristos			uint8_t alpha = rand();
9942542f5fSchristos			int try = 50;
10042542f5fSchristos
10142542f5fSchristos			do {
10242542f5fSchristos				x = rand() % (out.width - 1);
10342542f5fSchristos				y = rand() % (out.height - 1);
10442542f5fSchristos				w = 1 + rand() % (out.width - x - 1);
10542542f5fSchristos				h = 1 + rand() % (out.height - y - 1);
10642542f5fSchristos				tmpx = w == out.width ? 0 : rand() % (out.width - w);
10742542f5fSchristos				tmpy = h == out.height ? 0 : rand() % (out.height - h);
10842542f5fSchristos			} while (((tmpx+w > x && tmpx < x+w) ||
10942542f5fSchristos				  (tmpy+h > y && tmpy < y+h)) &&
11042542f5fSchristos				 --try);
11142542f5fSchristos
11242542f5fSchristos			mask_x = (rand() % (2*w)) - w;
11342542f5fSchristos			mask_y = (rand() % (2*h)) - h;
11442542f5fSchristos			mask_w = rand() % w;
11542542f5fSchristos			mask_h = rand() % h;
11642542f5fSchristos
11742542f5fSchristos			if (try) {
11842542f5fSchristos				fill_rect(&t->out, out.picture, out.format,
11942542f5fSchristos					  use_window, tmpx, tmpy,
12042542f5fSchristos					  PictOpSrc, x, y, w, h,
12142542f5fSchristos					  mask_x, mask_y, mask_w, mask_h,
12242542f5fSchristos					  red, green, blue, alpha);
12342542f5fSchristos				fill_rect(&t->ref, ref.picture, ref.format,
12442542f5fSchristos					  use_window, tmpx, tmpy,
12542542f5fSchristos					  PictOpSrc, x, y, w, h,
12642542f5fSchristos					  mask_x, mask_y, mask_w, mask_h,
12742542f5fSchristos					  red, green, blue, alpha);
12842542f5fSchristos			}
12942542f5fSchristos		}
13042542f5fSchristos
13142542f5fSchristos		test_compare(t,
13242542f5fSchristos			     out.draw, out.format,
13342542f5fSchristos			     ref.draw, ref.format,
13442542f5fSchristos			     0, 0, out.width, out.height,
13542542f5fSchristos			     "");
13642542f5fSchristos	}
13742542f5fSchristos
13842542f5fSchristos	printf("passed [%d iterations x %d]\n", reps, sets);
13942542f5fSchristos
14042542f5fSchristos	test_target_destroy_render(&t->out, &out);
14142542f5fSchristos	test_target_destroy_render(&t->ref, &ref);
14242542f5fSchristos}
14342542f5fSchristos
14442542f5fSchristosint main(int argc, char **argv)
14542542f5fSchristos{
14642542f5fSchristos	struct test test;
14742542f5fSchristos	int i;
14842542f5fSchristos
14942542f5fSchristos	test_init(&test, argc, argv);
15042542f5fSchristos
15142542f5fSchristos	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
15242542f5fSchristos		int reps = REPS(i), sets = SETS(i);
15342542f5fSchristos		enum target t;
15442542f5fSchristos
15542542f5fSchristos		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
15642542f5fSchristos			rect_tests(&test, reps, sets, t, 0);
15742542f5fSchristos			if (t != PIXMAP)
15842542f5fSchristos			    rect_tests(&test, reps, sets, t, 1);
15942542f5fSchristos		}
16042542f5fSchristos	}
16142542f5fSchristos
16242542f5fSchristos	return 0;
16342542f5fSchristos}
164