1428d7b3dSmrg#include <stdint.h> 2428d7b3dSmrg#include <stdio.h> 3428d7b3dSmrg#include <stdlib.h> 4428d7b3dSmrg 5428d7b3dSmrg#include <X11/Xutil.h> /* for XDestroyImage */ 6428d7b3dSmrg#include <pixman.h> /* for pixman blt functions */ 7428d7b3dSmrg 8428d7b3dSmrg#include "test.h" 9428d7b3dSmrg 10428d7b3dSmrgenum trapezoid { 11428d7b3dSmrg RECT_ALIGN, 12428d7b3dSmrg RECT_UNALIGN, 13428d7b3dSmrg GENERAL 14428d7b3dSmrg}; 15428d7b3dSmrg 16428d7b3dSmrgstatic const uint8_t ops[] = { 17428d7b3dSmrg PictOpClear, 18428d7b3dSmrg PictOpSrc, 19428d7b3dSmrg PictOpDst, 20428d7b3dSmrg}; 21428d7b3dSmrg 22428d7b3dSmrgstatic XRenderPictFormat *mask_format(Display *dpy, enum mask mask) 23428d7b3dSmrg{ 24428d7b3dSmrg switch (mask) { 25428d7b3dSmrg default: 26428d7b3dSmrg case MASK_NONE: 27428d7b3dSmrg case MASK_NONE_AA: 28428d7b3dSmrg return NULL; 29428d7b3dSmrg case MASK_A1: 30428d7b3dSmrg return XRenderFindStandardFormat(dpy, PictStandardA1); 31428d7b3dSmrg case MASK_A8: 32428d7b3dSmrg return XRenderFindStandardFormat(dpy, PictStandardA8); 33428d7b3dSmrg } 34428d7b3dSmrg} 35428d7b3dSmrg 36428d7b3dSmrgstatic const char *mask_name(enum mask mask) 37428d7b3dSmrg{ 38428d7b3dSmrg switch (mask) { 39428d7b3dSmrg default: 40428d7b3dSmrg case MASK_NONE: return "none"; 41428d7b3dSmrg case MASK_NONE_AA: return "none/aa"; 42428d7b3dSmrg case MASK_A1: return "a1"; 43428d7b3dSmrg case MASK_A8: return "a8"; 44428d7b3dSmrg } 45428d7b3dSmrg} 46428d7b3dSmrg 47428d7b3dSmrgstatic const char *trapezoid_name(enum trapezoid trapezoid) 48428d7b3dSmrg{ 49428d7b3dSmrg switch (trapezoid) { 50428d7b3dSmrg default: 51428d7b3dSmrg case RECT_ALIGN: return "pixel-aligned"; 52428d7b3dSmrg case RECT_UNALIGN: return "rectilinear"; 53428d7b3dSmrg case GENERAL: return "general"; 54428d7b3dSmrg } 55428d7b3dSmrg} 56428d7b3dSmrg 57428d7b3dSmrgstatic void 58428d7b3dSmrgshow_cells(char *buf, 59428d7b3dSmrg const uint32_t *out, const uint32_t *ref, 60428d7b3dSmrg int x, int y, int w, int h) 61428d7b3dSmrg{ 62428d7b3dSmrg int i, j, len = 0; 63428d7b3dSmrg 64428d7b3dSmrg for (j = y - 2; j <= y + 2; j++) { 65428d7b3dSmrg if (j < 0 || j >= h) 66428d7b3dSmrg continue; 67428d7b3dSmrg 68428d7b3dSmrg for (i = x - 2; i <= x + 2; i++) { 69428d7b3dSmrg if (i < 0 || i >= w) 70428d7b3dSmrg continue; 71428d7b3dSmrg 72428d7b3dSmrg len += sprintf(buf+len, "%08x ", out[j*w+i]); 73428d7b3dSmrg } 74428d7b3dSmrg 75428d7b3dSmrg len += sprintf(buf+len, "\t"); 76428d7b3dSmrg 77428d7b3dSmrg for (i = x - 2; i <= x + 2; i++) { 78428d7b3dSmrg if (i < 0 || i >= w) 79428d7b3dSmrg continue; 80428d7b3dSmrg 81428d7b3dSmrg len += sprintf(buf+len, "%08x ", ref[j*w+i]); 82428d7b3dSmrg } 83428d7b3dSmrg 84428d7b3dSmrg len += sprintf(buf+len, "\n"); 85428d7b3dSmrg } 86428d7b3dSmrg} 87428d7b3dSmrg 88428d7b3dSmrg 89428d7b3dSmrgstatic void fill_rect(struct test_display *t, Picture p, XRenderPictFormat *format, 90428d7b3dSmrg uint8_t op, int x, int y, int w, int h, 91428d7b3dSmrg int dx, int dy, enum mask mask, 92428d7b3dSmrg int use_window, int tx, int ty, 93428d7b3dSmrg uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) 94428d7b3dSmrg{ 95428d7b3dSmrg XRenderColor color; 96428d7b3dSmrg XTrapezoid trap; 97428d7b3dSmrg Drawable tmp; 98428d7b3dSmrg Picture src; 99428d7b3dSmrg int w1 = w + (dx!=0); 100428d7b3dSmrg int h1 = h + (dy!=0); 101428d7b3dSmrg 102428d7b3dSmrg if (use_window) { 103428d7b3dSmrg XSetWindowAttributes attr; 104428d7b3dSmrg 105428d7b3dSmrg attr.override_redirect = 1; 106428d7b3dSmrg tmp = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 107428d7b3dSmrg tx, ty, 108428d7b3dSmrg w1, h1, 109428d7b3dSmrg 0, format->depth, 110428d7b3dSmrg InputOutput, 111428d7b3dSmrg DefaultVisual(t->dpy, 112428d7b3dSmrg DefaultScreen(t->dpy)), 113428d7b3dSmrg CWOverrideRedirect, &attr); 114428d7b3dSmrg XMapWindow(t->dpy, tmp); 115428d7b3dSmrg } else 116428d7b3dSmrg tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy), 117428d7b3dSmrg w1, h1, format->depth); 118428d7b3dSmrg 119428d7b3dSmrg src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL); 120428d7b3dSmrg color.red = red * alpha; 121428d7b3dSmrg color.green = green * alpha; 122428d7b3dSmrg color.blue = blue * alpha; 123428d7b3dSmrg color.alpha = alpha << 8 | alpha; 124428d7b3dSmrg XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, w1, h1); 125428d7b3dSmrg 126428d7b3dSmrg trap.left.p1.x = trap.left.p2.x = (x << 16) + dx; 127428d7b3dSmrg trap.top = trap.left.p1.y = trap.right.p1.y = (y << 16) + dy; 128428d7b3dSmrg trap.right.p1.x = trap.right.p2.x = ((x + w) << 16) + dx; 129428d7b3dSmrg trap.bottom = trap.left.p2.y = trap.right.p2.y = ((y + h) << 16) + dy; 130428d7b3dSmrg 131428d7b3dSmrg XRenderCompositeTrapezoids(t->dpy, 132428d7b3dSmrg op, src, p, mask_format(t->dpy, mask), 133428d7b3dSmrg 0, 0, &trap, 1); 134428d7b3dSmrg 135428d7b3dSmrg XRenderFreePicture(t->dpy, src); 136428d7b3dSmrg if (use_window) 137428d7b3dSmrg XDestroyWindow(t->dpy, tmp); 138428d7b3dSmrg else 139428d7b3dSmrg XFreePixmap(t->dpy, tmp); 140428d7b3dSmrg} 141428d7b3dSmrg 142428d7b3dSmrgstatic void pixel_tests(struct test *t, int reps, int sets, enum target target, int use_window) 143428d7b3dSmrg{ 144428d7b3dSmrg struct test_target tt; 145428d7b3dSmrg XImage image; 146428d7b3dSmrg uint32_t *cells = malloc(t->out.width*t->out.height*4); 147428d7b3dSmrg struct { 148428d7b3dSmrg uint16_t x, y; 149428d7b3dSmrg } *pixels = malloc(reps*sizeof(*pixels)); 150428d7b3dSmrg int r, s; 151428d7b3dSmrg 152428d7b3dSmrg printf("Testing setting of single pixels (%s using %s): ", 153428d7b3dSmrg test_target_name(target), 154428d7b3dSmrg use_window ? "window" : "pixmap"); 155428d7b3dSmrg fflush(stdout); 156428d7b3dSmrg 157428d7b3dSmrg test_target_create_render(&t->out, target, &tt); 158428d7b3dSmrg 159428d7b3dSmrg for (s = 0; s < sets; s++) { 160428d7b3dSmrg for (r = 0; r < reps; r++) { 161428d7b3dSmrg int x = rand() % (tt.width - 1); 162428d7b3dSmrg int y = rand() % (tt.height - 1); 163428d7b3dSmrg int red = rand() % 0xff; 164428d7b3dSmrg int green = rand() % 0xff; 165428d7b3dSmrg int blue = rand() % 0xff; 166428d7b3dSmrg int alpha = rand() % 0xff; 167428d7b3dSmrg 168428d7b3dSmrg int tx, ty; 169428d7b3dSmrg 170428d7b3dSmrg do { 171428d7b3dSmrg tx = rand() % (tt.width - 1); 172428d7b3dSmrg ty = rand() % (tt.height - 1); 173428d7b3dSmrg } while (tx == x && ty == y); 174428d7b3dSmrg 175428d7b3dSmrg fill_rect(&t->out, tt.picture, 176428d7b3dSmrg use_window ? t->out.format : tt.format, 177428d7b3dSmrg PictOpSrc, x, y, 1, 1, 178428d7b3dSmrg 0, 0, MASK_NONE, 179428d7b3dSmrg use_window, tx, ty, 180428d7b3dSmrg red, green, blue, alpha); 181428d7b3dSmrg 182428d7b3dSmrg pixels[r].x = x; 183428d7b3dSmrg pixels[r].y = y; 184428d7b3dSmrg cells[y*t->out.width+x] = color(red, green, blue, alpha); 185428d7b3dSmrg } 186428d7b3dSmrg 187428d7b3dSmrg test_init_image(&image, &t->out.shm, tt.format, 1, 1); 188428d7b3dSmrg 189428d7b3dSmrg for (r = 0; r < reps; r++) { 190428d7b3dSmrg uint32_t result; 191428d7b3dSmrg uint32_t x = pixels[r].x; 192428d7b3dSmrg uint32_t y = pixels[r].y; 193428d7b3dSmrg 194428d7b3dSmrg XShmGetImage(t->out.dpy, tt.draw, &image, 195428d7b3dSmrg x, y, AllPlanes); 196428d7b3dSmrg 197428d7b3dSmrg result = *(uint32_t *)image.data; 198428d7b3dSmrg if (!pixel_equal(image.depth, result, 199428d7b3dSmrg cells[y*tt.width+x])) { 200428d7b3dSmrg uint32_t mask = depth_mask(image.depth); 201428d7b3dSmrg die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n", 202428d7b3dSmrg x, y, 203428d7b3dSmrg cells[y*tt.width+x] & mask, 204428d7b3dSmrg cells[y*tt.width+x], 205428d7b3dSmrg result & mask, 206428d7b3dSmrg result); 207428d7b3dSmrg } 208428d7b3dSmrg } 209428d7b3dSmrg } 210428d7b3dSmrg printf("passed [%d iterations x %d]\n", reps, sets); 211428d7b3dSmrg 212428d7b3dSmrg test_target_destroy_render(&t->out, &tt); 213428d7b3dSmrg 214428d7b3dSmrg free(pixels); 215428d7b3dSmrg free(cells); 216428d7b3dSmrg} 217428d7b3dSmrg 218428d7b3dSmrgstatic void clear(struct test_display *dpy, struct test_target *tt) 219428d7b3dSmrg{ 220428d7b3dSmrg XRenderColor render_color = {0}; 221428d7b3dSmrg XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color, 222428d7b3dSmrg 0, 0, tt->width, tt->height); 223428d7b3dSmrg} 224428d7b3dSmrg 225428d7b3dSmrgstatic void set_mask(struct test_display *t, struct test_target *tt, enum mask mask) 226428d7b3dSmrg{ 227428d7b3dSmrg XRenderPictureAttributes pa; 228428d7b3dSmrg 229428d7b3dSmrg switch (mask) { 230428d7b3dSmrg case MASK_NONE: 231428d7b3dSmrg pa.poly_edge = PolyEdgeSharp; 232428d7b3dSmrg break; 233428d7b3dSmrg default: 234428d7b3dSmrg pa.poly_edge = PolyEdgeSmooth; 235428d7b3dSmrg break; 236428d7b3dSmrg } 237428d7b3dSmrg 238428d7b3dSmrg XRenderChangePicture(t->dpy, tt->picture, CPPolyEdge, &pa); 239428d7b3dSmrg} 240428d7b3dSmrg 241428d7b3dSmrgstatic void fill(uint32_t *cells, 242428d7b3dSmrg int x, int y, 243428d7b3dSmrg int w, int h, 244428d7b3dSmrg int max_width, int max_height, 245428d7b3dSmrg uint32_t pixel) 246428d7b3dSmrg{ 247428d7b3dSmrg if (x < 0) 248428d7b3dSmrg w += x, x = 0; 249428d7b3dSmrg if (y < 0) 250428d7b3dSmrg h += y, y = 0; 251428d7b3dSmrg if (x >= max_width || y >= max_height) 252428d7b3dSmrg return; 253428d7b3dSmrg 254428d7b3dSmrg if (x + w > max_width) 255428d7b3dSmrg w = max_width - x; 256428d7b3dSmrg if (y + h > max_height) 257428d7b3dSmrg h = max_height - y; 258428d7b3dSmrg if (w <= 0 || h <= 0) 259428d7b3dSmrg return; 260428d7b3dSmrg 261428d7b3dSmrg pixman_fill(cells, max_width, 32, x, y, w, h, pixel); 262428d7b3dSmrg} 263428d7b3dSmrg 264428d7b3dSmrgstatic void area_tests(struct test *t, int reps, int sets, enum target target, int use_window) 265428d7b3dSmrg{ 266428d7b3dSmrg struct test_target tt; 267428d7b3dSmrg XImage image; 268428d7b3dSmrg uint32_t *cells = calloc(sizeof(uint32_t), t->out.width*t->out.height); 269428d7b3dSmrg int r, s, x, y; 270428d7b3dSmrg 271428d7b3dSmrg printf("Testing area sets (%s using %s source): ", 272428d7b3dSmrg test_target_name(target), 273428d7b3dSmrg use_window ? "window" : "pixmap"); 274428d7b3dSmrg fflush(stdout); 275428d7b3dSmrg 276428d7b3dSmrg test_target_create_render(&t->out, target, &tt); 277428d7b3dSmrg clear(&t->out, &tt); 278428d7b3dSmrg 279428d7b3dSmrg test_init_image(&image, &t->out.shm, tt.format, tt.width, tt.height); 280428d7b3dSmrg 281428d7b3dSmrg for (s = 0; s < sets; s++) { 282428d7b3dSmrg for (r = 0; r < reps; r++) { 283428d7b3dSmrg int red = rand() % 0xff; 284428d7b3dSmrg int green = rand() % 0xff; 285428d7b3dSmrg int blue = rand() % 0xff; 286428d7b3dSmrg int alpha = rand() % 0xff; 287428d7b3dSmrg int tx, ty, try = 50; 288428d7b3dSmrg int w, h; 289428d7b3dSmrg 290428d7b3dSmrg x = rand() % (2*tt.width) - tt.width; 291428d7b3dSmrg y = rand() % (2*tt.height) - tt.height; 292428d7b3dSmrg if (use_window) { 293428d7b3dSmrg do { 294428d7b3dSmrg w = 1 + rand() % (tt.width - 1); 295428d7b3dSmrg h = 1 + rand() % (tt.height - 1); 296428d7b3dSmrg 297428d7b3dSmrg tx = w == tt.width ? 0 : rand() % (tt.width - w); 298428d7b3dSmrg ty = h == tt.height ? 0 : rand() % (tt.height - h); 299428d7b3dSmrg } while (((tx+w > x && tx < x+w) && 300428d7b3dSmrg (ty+h > y && ty < y+h)) && 301428d7b3dSmrg --try); 302428d7b3dSmrg 303428d7b3dSmrg if (!try) 304428d7b3dSmrg continue; 305428d7b3dSmrg } else { 306428d7b3dSmrg w = 1 + rand() % (2*tt.width); 307428d7b3dSmrg h = 1 + rand() % (2*tt.height); 308428d7b3dSmrg tx = ty = 0; 309428d7b3dSmrg } 310428d7b3dSmrg 311428d7b3dSmrg fill_rect(&t->out, tt.picture, 312428d7b3dSmrg use_window ? t->out.format : tt.format, 313428d7b3dSmrg PictOpSrc, x, y, w, h, 314428d7b3dSmrg 0, 0, MASK_NONE, 315428d7b3dSmrg use_window, tx, ty, 316428d7b3dSmrg red, green, blue, alpha); 317428d7b3dSmrg 318428d7b3dSmrg if (use_window) 319428d7b3dSmrg fill(cells, tx, ty, w, h, tt.width, tt.height, 320428d7b3dSmrg color(red, green, blue, alpha)); 321428d7b3dSmrg fill(cells, x, y, w, h, tt.width, tt.height, 322428d7b3dSmrg color(red, green, blue, alpha)); 323428d7b3dSmrg 324428d7b3dSmrg } 325428d7b3dSmrg 326428d7b3dSmrg XShmGetImage(t->out.dpy, tt.draw, &image, 0, 0, AllPlanes); 327428d7b3dSmrg 328428d7b3dSmrg for (y = 0; y < tt.height; y++) { 329428d7b3dSmrg for (x = 0; x < tt.width; x++) { 330428d7b3dSmrg uint32_t result = 331428d7b3dSmrg *(uint32_t *)(image.data + 332428d7b3dSmrg y*image.bytes_per_line + 333428d7b3dSmrg image.bits_per_pixel*x/8); 334428d7b3dSmrg if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { 335428d7b3dSmrg char buf[600]; 336428d7b3dSmrg uint32_t mask = depth_mask(image.depth); 337428d7b3dSmrg show_cells(buf, 338428d7b3dSmrg (uint32_t*)image.data, cells, 339428d7b3dSmrg x, y, tt.width, tt.height); 340428d7b3dSmrg 341428d7b3dSmrg die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s", 342428d7b3dSmrg x, y, 343428d7b3dSmrg cells[y*tt.width+x] & mask, 344428d7b3dSmrg cells[y*tt.width+x], 345428d7b3dSmrg result & mask, 346428d7b3dSmrg result, buf); 347428d7b3dSmrg } 348428d7b3dSmrg } 349428d7b3dSmrg } 350428d7b3dSmrg } 351428d7b3dSmrg 352428d7b3dSmrg printf("passed [%d iterations x %d]\n", reps, sets); 353428d7b3dSmrg 354428d7b3dSmrg test_target_destroy_render(&t->out, &tt); 355428d7b3dSmrg free(cells); 356428d7b3dSmrg} 357428d7b3dSmrg 358428d7b3dSmrgstatic void rect_tests(struct test *t, 359428d7b3dSmrg int dx, int dy, 360428d7b3dSmrg enum mask mask, 361428d7b3dSmrg int reps, int sets, 362428d7b3dSmrg enum target target, 363428d7b3dSmrg int use_window) 364428d7b3dSmrg{ 365428d7b3dSmrg struct test_target out, ref; 366428d7b3dSmrg int r, s; 367428d7b3dSmrg 368428d7b3dSmrg printf("Testing area fills (offset %dx%d, mask %s) (%s using %s source): ", 369428d7b3dSmrg dx, dy, mask_name(mask), test_target_name(target), 370428d7b3dSmrg use_window ? "window" : "pixmap"); 371428d7b3dSmrg fflush(stdout); 372428d7b3dSmrg 373428d7b3dSmrg test_target_create_render(&t->out, target, &out); 374428d7b3dSmrg clear(&t->out, &out); 375428d7b3dSmrg set_mask(&t->out, &out, mask); 376428d7b3dSmrg 377428d7b3dSmrg test_target_create_render(&t->ref, target, &ref); 378428d7b3dSmrg clear(&t->ref, &ref); 379428d7b3dSmrg set_mask(&t->ref, &ref, mask); 380428d7b3dSmrg 381428d7b3dSmrg for (s = 0; s < sets; s++) { 382428d7b3dSmrg for (r = 0; r < reps; r++) { 383428d7b3dSmrg int x, y, w, h; 384428d7b3dSmrg int op = ops[rand() % sizeof(ops)]; 385428d7b3dSmrg int red = rand() % 0xff; 386428d7b3dSmrg int green = rand() % 0xff; 387428d7b3dSmrg int blue = rand() % 0xff; 388428d7b3dSmrg int alpha = rand() % 0xff; 389428d7b3dSmrg int tx, ty, try = 50; 390428d7b3dSmrg 391428d7b3dSmrg do { 392428d7b3dSmrg x = rand() % (out.width - 1); 393428d7b3dSmrg y = rand() % (out.height - 1); 394428d7b3dSmrg w = 1 + rand() % (out.width - x - 1); 395428d7b3dSmrg h = 1 + rand() % (out.height - y - 1); 396428d7b3dSmrg tx = w == out.width ? 0 : rand() % (out.width - w); 397428d7b3dSmrg ty = h == out.height ? 0 : rand() % (out.height - h); 398428d7b3dSmrg } while (((tx+w > x && tx < x+w) && 399428d7b3dSmrg (ty+h > y && ty < y+h)) && 400428d7b3dSmrg --try); 401428d7b3dSmrg 402428d7b3dSmrg if (try) { 403428d7b3dSmrg fill_rect(&t->out, out.picture, 404428d7b3dSmrg use_window ? t->out.format : out.format, 405428d7b3dSmrg op, x, y, w, h, 406428d7b3dSmrg dx, dy, mask, 407428d7b3dSmrg use_window, tx, ty, 408428d7b3dSmrg red, green, blue, alpha); 409428d7b3dSmrg fill_rect(&t->ref, ref.picture, 410428d7b3dSmrg use_window ? t->ref.format : ref.format, 411428d7b3dSmrg op, x, y, w, h, 412428d7b3dSmrg dx, dy, mask, 413428d7b3dSmrg use_window, tx, ty, 414428d7b3dSmrg red, green, blue, alpha); 415428d7b3dSmrg } 416428d7b3dSmrg } 417428d7b3dSmrg 418428d7b3dSmrg test_compare(t, 419428d7b3dSmrg out.draw, out.format, 420428d7b3dSmrg ref.draw, ref.format, 421428d7b3dSmrg 0, 0, out.width, out.height, 422428d7b3dSmrg ""); 423428d7b3dSmrg } 424428d7b3dSmrg 425428d7b3dSmrg printf("passed [%d iterations x %d]\n", reps, sets); 426428d7b3dSmrg 427428d7b3dSmrg test_target_destroy_render(&t->out, &out); 428428d7b3dSmrg test_target_destroy_render(&t->ref, &ref); 429428d7b3dSmrg} 430428d7b3dSmrg 431428d7b3dSmrgstatic void random_trapezoid(XTrapezoid *trap, enum trapezoid trapezoid, 432428d7b3dSmrg int x1, int y1, int x2, int y2) 433428d7b3dSmrg{ 434428d7b3dSmrg switch (trapezoid) { 435428d7b3dSmrg case RECT_ALIGN: 436428d7b3dSmrg x1 = x1 + rand() % (x2 - x1); 437428d7b3dSmrg x2 = x1 + rand() % (x2 - x1); 438428d7b3dSmrg y1 = y1 + rand() % (y2 - y1); 439428d7b3dSmrg y2 = y1 + rand() % (y2 - y1); 440428d7b3dSmrg 441428d7b3dSmrg trap->left.p1.x = trap->left.p2.x = x1 << 16; 442428d7b3dSmrg trap->top = trap->left.p1.y = trap->right.p1.y = y1 << 16; 443428d7b3dSmrg trap->right.p1.x = trap->right.p2.x = x2 << 16; 444428d7b3dSmrg trap->bottom = trap->left.p2.y = trap->right.p2.y = y2 << 16; 445428d7b3dSmrg break; 446428d7b3dSmrg 447428d7b3dSmrg case RECT_UNALIGN: 448428d7b3dSmrg x1 <<= 16; x2 <<= 16; 449428d7b3dSmrg y1 <<= 16; y2 <<= 16; 450428d7b3dSmrg 451428d7b3dSmrg x1 = x1 + rand() % (x2 - x1); 452428d7b3dSmrg x2 = x1 + rand() % (x2 - x1); 453428d7b3dSmrg y1 = y1 + rand() % (y2 - y1); 454428d7b3dSmrg y2 = y1 + rand() % (y2 - y1); 455428d7b3dSmrg 456428d7b3dSmrg trap->left.p1.x = trap->left.p2.x = x1; 457428d7b3dSmrg trap->top = trap->left.p1.y = trap->right.p1.y = y1; 458428d7b3dSmrg trap->right.p1.x = trap->right.p2.x = x2; 459428d7b3dSmrg trap->bottom = trap->left.p2.y = trap->right.p2.y = y2; 460428d7b3dSmrg break; 461428d7b3dSmrg 462428d7b3dSmrg case GENERAL: 463428d7b3dSmrg x1 <<= 16; x2 <<= 16; 464428d7b3dSmrg y1 <<= 16; y2 <<= 16; 465428d7b3dSmrg 466428d7b3dSmrg trap->top = y1 + rand() % (y2 - y1); 467428d7b3dSmrg trap->bottom = y1 + rand() % (y2 - y1); 468428d7b3dSmrg 469428d7b3dSmrg trap->left.p1.x = x1 + rand() % (x2 - x1); 470428d7b3dSmrg trap->left.p2.x = x1 + rand() % (x2 - x1); 471428d7b3dSmrg 472428d7b3dSmrg trap->right.p1.x = x1 + rand() % (x2 - x1); 473428d7b3dSmrg trap->right.p2.x = x1 + rand() % (x2 - x1); 474428d7b3dSmrg break; 475428d7b3dSmrg } 476428d7b3dSmrg} 477428d7b3dSmrg 478428d7b3dSmrgstatic void fill_traps(struct test_display *t, Picture p, XRenderPictFormat *format, 479428d7b3dSmrg uint8_t op, XTrapezoid *traps, int ntraps, enum mask mask, 480428d7b3dSmrg int srcx, int srcy, int srcw, int srch, 481428d7b3dSmrg uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) 482428d7b3dSmrg{ 483428d7b3dSmrg XRenderColor color; 484428d7b3dSmrg Drawable tmp; 485428d7b3dSmrg Picture src; 486428d7b3dSmrg 487428d7b3dSmrg tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy), 488428d7b3dSmrg srcw, srch, format->depth); 489428d7b3dSmrg 490428d7b3dSmrg src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL); 491428d7b3dSmrg color.red = red * alpha; 492428d7b3dSmrg color.green = green * alpha; 493428d7b3dSmrg color.blue = blue * alpha; 494428d7b3dSmrg color.alpha = alpha << 8 | alpha; 495428d7b3dSmrg XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, srcw, srch); 496428d7b3dSmrg 497428d7b3dSmrg XRenderCompositeTrapezoids(t->dpy, 498428d7b3dSmrg op, src, p, mask_format(t->dpy, mask), 499428d7b3dSmrg srcx, srcy, traps, ntraps); 500428d7b3dSmrg 501428d7b3dSmrg XRenderFreePicture(t->dpy, src); 502428d7b3dSmrg XFreePixmap(t->dpy, tmp); 503428d7b3dSmrg} 504428d7b3dSmrg 505428d7b3dSmrgstatic void trap_tests(struct test *t, 506428d7b3dSmrg enum mask mask, 507428d7b3dSmrg enum trapezoid trapezoid, 508428d7b3dSmrg int reps, int sets, 509428d7b3dSmrg enum target target) 510428d7b3dSmrg{ 511428d7b3dSmrg struct test_target out, ref; 512428d7b3dSmrg XTrapezoid *traps; 513428d7b3dSmrg int max_traps = 65536; 514428d7b3dSmrg int r, s, n; 515428d7b3dSmrg 516428d7b3dSmrg traps = malloc(sizeof(*traps) * max_traps); 517428d7b3dSmrg if (traps == NULL) 518428d7b3dSmrg return; 519428d7b3dSmrg 520428d7b3dSmrg printf("Testing trapezoids (%s with mask %s) (%s): ", 521428d7b3dSmrg trapezoid_name(trapezoid), 522428d7b3dSmrg mask_name(mask), 523428d7b3dSmrg test_target_name(target)); 524428d7b3dSmrg fflush(stdout); 525428d7b3dSmrg 526428d7b3dSmrg test_target_create_render(&t->out, target, &out); 527428d7b3dSmrg clear(&t->out, &out); 528428d7b3dSmrg set_mask(&t->out, &out, mask); 529428d7b3dSmrg 530428d7b3dSmrg test_target_create_render(&t->ref, target, &ref); 531428d7b3dSmrg clear(&t->ref, &ref); 532428d7b3dSmrg set_mask(&t->ref, &ref, mask); 533428d7b3dSmrg 534428d7b3dSmrg for (s = 0; s < sets; s++) { 535428d7b3dSmrg for (r = 0; r < reps; r++) { 536428d7b3dSmrg int op = ops[rand() % sizeof(ops)]; 537428d7b3dSmrg int red = rand() % 0xff; 538428d7b3dSmrg int green = rand() % 0xff; 539428d7b3dSmrg int blue = rand() % 0xff; 540428d7b3dSmrg int alpha = rand() % 0xff; 541428d7b3dSmrg int num_traps = rand() % max_traps; 542428d7b3dSmrg int srcx = rand() % 2*out.width - out.width; 543428d7b3dSmrg int srcy = rand() % 2*out.height - out.height; 544428d7b3dSmrg int srcw = rand() % out.width; 545428d7b3dSmrg int srch = rand() % out.height; 546428d7b3dSmrg 547428d7b3dSmrg for (n = 0; n < num_traps; n++) 548428d7b3dSmrg random_trapezoid(&traps[n], 0, 549428d7b3dSmrg 0, 0, out.width, out.height); 550428d7b3dSmrg 551428d7b3dSmrg 552428d7b3dSmrg fill_traps(&t->out, out.picture, out.format, 553428d7b3dSmrg op, traps, num_traps, mask, 554428d7b3dSmrg srcx, srcy, srcw, srch, 555428d7b3dSmrg red, green, blue, alpha); 556428d7b3dSmrg 557428d7b3dSmrg fill_traps(&t->ref, ref.picture, ref.format, 558428d7b3dSmrg op, traps, num_traps, mask, 559428d7b3dSmrg srcx, srcy, srcw, srch, 560428d7b3dSmrg red, green, blue, alpha); 561428d7b3dSmrg } 562428d7b3dSmrg 563428d7b3dSmrg test_compare(t, 564428d7b3dSmrg out.draw, out.format, 565428d7b3dSmrg ref.draw, ref.format, 566428d7b3dSmrg 0, 0, out.width, out.height, 567428d7b3dSmrg ""); 568428d7b3dSmrg } 569428d7b3dSmrg 570428d7b3dSmrg printf("passed [%d iterations x %d]\n", reps, sets); 571428d7b3dSmrg 572428d7b3dSmrg test_target_destroy_render(&t->out, &out); 573428d7b3dSmrg test_target_destroy_render(&t->ref, &ref); 574428d7b3dSmrg free(traps); 575428d7b3dSmrg} 576428d7b3dSmrg 577428d7b3dSmrgint main(int argc, char **argv) 578428d7b3dSmrg{ 579428d7b3dSmrg struct test test; 580428d7b3dSmrg int i, dx, dy; 581428d7b3dSmrg enum target target; 582428d7b3dSmrg enum mask mask; 583428d7b3dSmrg enum trapezoid trapezoid; 584428d7b3dSmrg 585428d7b3dSmrg test_init(&test, argc, argv); 586428d7b3dSmrg 587428d7b3dSmrg for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 588428d7b3dSmrg int reps = REPS(i), sets = SETS(i); 589428d7b3dSmrg 590428d7b3dSmrg for (target = TARGET_FIRST; target <= TARGET_LAST; target++) { 591428d7b3dSmrg pixel_tests(&test, reps, sets, target, 0); 592428d7b3dSmrg area_tests(&test, reps, sets, target, 0); 593428d7b3dSmrg for (dy = 0; dy < 1 << 16; dy += 1 << 14) 594428d7b3dSmrg for (dx = 0; dx < 1 << 16; dx += 1 << 14) 595428d7b3dSmrg for (mask = MASK_NONE; mask <= MASK_A8; mask++) 596428d7b3dSmrg rect_tests(&test, dx, dy, mask, reps, sets, target, 0); 597428d7b3dSmrg if (target != CHILD) { 598428d7b3dSmrg pixel_tests(&test, reps, sets, target, 1); 599428d7b3dSmrg area_tests(&test, reps, sets, target, 1); 600428d7b3dSmrg for (dy = 0; dy < 1 << 16; dy += 1 << 14) 601428d7b3dSmrg for (dx = 0; dx < 1 << 16; dx += 1 << 14) 602428d7b3dSmrg for (mask = MASK_NONE; mask <= MASK_A8; mask++) 603428d7b3dSmrg rect_tests(&test, dx, dy, mask, reps, sets, target, 1); 604428d7b3dSmrg } 605428d7b3dSmrg } 606428d7b3dSmrg 607428d7b3dSmrg for (target = TARGET_FIRST; target <= TARGET_LAST; target++) 608428d7b3dSmrg for (trapezoid = RECT_ALIGN; trapezoid <= GENERAL; trapezoid++) 609428d7b3dSmrg trap_tests(&test, mask, trapezoid, reps, sets, target); 610428d7b3dSmrg } 611428d7b3dSmrg 612428d7b3dSmrg return 0; 613428d7b3dSmrg} 614