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