5 #include <X11/Xutil.h> /* for XDestroyImage */
6 #include <pixman.h> /* for pixman blt functions */
16 static const uint8_t ops[] = {
22 static XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
30 return XRenderFindStandardFormat(dpy, PictStandardA1);
32 return XRenderFindStandardFormat(dpy, PictStandardA8);
36 static const char *mask_name(enum mask mask)
40 case MASK_NONE: return "none";
41 case MASK_NONE_AA: return "none/aa";
42 case MASK_A1: return "a1";
43 case MASK_A8: return "a8";
47 static const char *trapezoid_name(enum trapezoid trapezoid)
51 case RECT_ALIGN: return "pixel-aligned";
52 case RECT_UNALIGN: return "rectilinear";
53 case GENERAL: return "general";
59 const uint32_t *real, const uint32_t *ref,
60 int x, int y, int w, int h)
64 for (j = y - 2; j <= y + 2; j++) {
68 for (i = x - 2; i <= x + 2; i++) {
72 len += sprintf(buf+len, "%08x ", real[j*w+i]);
75 len += sprintf(buf+len, "\t");
77 for (i = x - 2; i <= x + 2; i++) {
81 len += sprintf(buf+len, "%08x ", ref[j*w+i]);
84 len += sprintf(buf+len, "\n");
89 static void fill_rect(struct test_display *t, Picture p, XRenderPictFormat *format,
90 uint8_t op, int x, int y, int w, int h,
91 int dx, int dy, enum mask mask,
92 int use_window, int tx, int ty,
93 uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
100 int h1 = h + (dy!=0);
103 XSetWindowAttributes attr;
105 attr.override_redirect = 1;
106 tmp = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy),
111 DefaultVisual(t->dpy,
112 DefaultScreen(t->dpy)),
113 CWOverrideRedirect, &attr);
114 XMapWindow(t->dpy, tmp);
116 tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy),
117 w1, h1, format->depth);
119 src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL);
120 color.red = red * alpha;
121 color.green = green * alpha;
122 color.blue = blue * alpha;
123 color.alpha = alpha << 8 | alpha;
124 XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, w1, h1);
126 trap.left.p1.x = trap.left.p2.x = (x << 16) + dx;
127 trap.top = trap.left.p1.y = trap.right.p1.y = (y << 16) + dy;
128 trap.right.p1.x = trap.right.p2.x = ((x + w) << 16) + dx;
129 trap.bottom = trap.left.p2.y = trap.right.p2.y = ((y + h) << 16) + dy;
131 XRenderCompositeTrapezoids(t->dpy,
132 op, src, p, mask_format(t->dpy, mask),
135 XRenderFreePicture(t->dpy, src);
137 XDestroyWindow(t->dpy, tmp);
139 XFreePixmap(t->dpy, tmp);
142 static void pixel_tests(struct test *t, int reps, int sets, enum target target, int use_window)
144 struct test_target tt;
146 uint32_t *cells = malloc(t->real.width*t->real.height*4);
149 } *pixels = malloc(reps*sizeof(*pixels));
152 printf("Testing setting of single pixels (%s using %s): ",
153 test_target_name(target),
154 use_window ? "window" : "pixmap");
157 test_target_create_render(&t->real, target, &tt);
159 for (s = 0; s < sets; s++) {
160 for (r = 0; r < reps; r++) {
161 int x = rand() % (tt.width - 1);
162 int y = rand() % (tt.height - 1);
163 int red = rand() % 0xff;
164 int green = rand() % 0xff;
165 int blue = rand() % 0xff;
166 int alpha = rand() % 0xff;
171 tx = rand() % (tt.width - 1);
172 ty = rand() % (tt.height - 1);
173 } while (tx == x && ty == y);
175 fill_rect(&t->real, tt.picture,
176 use_window ? t->real.format : tt.format,
177 PictOpSrc, x, y, 1, 1,
180 red, green, blue, alpha);
184 cells[y*t->real.width+x] = color(red, green, blue, alpha);
187 test_init_image(&image, &t->real.shm, tt.format, 1, 1);
189 for (r = 0; r < reps; r++) {
191 uint32_t x = pixels[r].x;
192 uint32_t y = pixels[r].y;
194 XShmGetImage(t->real.dpy, tt.draw, &image,
197 result = *(uint32_t *)image.data;
198 if (!pixel_equal(image.depth, result,
199 cells[y*tt.width+x])) {
200 uint32_t mask = depth_mask(image.depth);
201 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n",
203 cells[y*tt.width+x] & mask,
210 printf("passed [%d iterations x %d]\n", reps, sets);
212 test_target_destroy_render(&t->real, &tt);
218 static void clear(struct test_display *dpy, struct test_target *tt)
220 XRenderColor render_color = {0};
221 XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
222 0, 0, tt->width, tt->height);
225 static void set_mask(struct test_display *t, struct test_target *tt, enum mask mask)
227 XRenderPictureAttributes pa;
231 pa.poly_edge = PolyEdgeSharp;
234 pa.poly_edge = PolyEdgeSmooth;
238 XRenderChangePicture(t->dpy, tt->picture, CPPolyEdge, &pa);
241 static void fill(uint32_t *cells,
244 int max_width, int max_height,
251 if (x >= max_width || y >= max_height)
254 if (x + w > max_width)
256 if (y + h > max_height)
258 if (w <= 0 || h <= 0)
261 pixman_fill(cells, max_width, 32, x, y, w, h, pixel);
264 static void area_tests(struct test *t, int reps, int sets, enum target target, int use_window)
266 struct test_target tt;
268 uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height);
271 printf("Testing area sets (%s using %s source): ",
272 test_target_name(target),
273 use_window ? "window" : "pixmap");
276 test_target_create_render(&t->real, target, &tt);
277 clear(&t->real, &tt);
279 test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height);
281 for (s = 0; s < sets; s++) {
282 for (r = 0; r < reps; r++) {
283 int red = rand() % 0xff;
284 int green = rand() % 0xff;
285 int blue = rand() % 0xff;
286 int alpha = rand() % 0xff;
287 int tx, ty, try = 50;
290 x = rand() % (2*tt.width) - tt.width;
291 y = rand() % (2*tt.height) - tt.height;
294 w = 1 + rand() % (tt.width - 1);
295 h = 1 + rand() % (tt.height - 1);
297 tx = w == tt.width ? 0 : rand() % (tt.width - w);
298 ty = h == tt.height ? 0 : rand() % (tt.height - h);
299 } while (((tx+w > x && tx < x+w) &&
300 (ty+h > y && ty < y+h)) &&
306 w = 1 + rand() % (2*tt.width);
307 h = 1 + rand() % (2*tt.height);
311 fill_rect(&t->real, tt.picture,
312 use_window ? t->real.format : tt.format,
313 PictOpSrc, x, y, w, h,
316 red, green, blue, alpha);
319 fill(cells, tx, ty, w, h, tt.width, tt.height,
320 color(red, green, blue, alpha));
321 fill(cells, x, y, w, h, tt.width, tt.height,
322 color(red, green, blue, alpha));
326 XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes);
328 for (y = 0; y < tt.height; y++) {
329 for (x = 0; x < tt.width; x++) {
331 *(uint32_t *)(image.data +
332 y*image.bytes_per_line +
333 image.bits_per_pixel*x/8);
334 if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) {
336 uint32_t mask = depth_mask(image.depth);
338 (uint32_t*)image.data, cells,
339 x, y, tt.width, tt.height);
341 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s",
343 cells[y*tt.width+x] & mask,
352 printf("passed [%d iterations x %d]\n", reps, sets);
354 test_target_destroy_render(&t->real, &tt);
358 static void rect_tests(struct test *t,
365 struct test_target real, ref;
368 printf("Testing area fills (offset %dx%d, mask %s) (%s using %s source): ",
369 dx, dy, mask_name(mask), test_target_name(target),
370 use_window ? "window" : "pixmap");
373 test_target_create_render(&t->real, target, &real);
374 clear(&t->real, &real);
375 set_mask(&t->real, &real, mask);
377 test_target_create_render(&t->ref, target, &ref);
378 clear(&t->ref, &ref);
379 set_mask(&t->ref, &ref, mask);
381 for (s = 0; s < sets; s++) {
382 for (r = 0; r < reps; r++) {
384 int op = ops[rand() % sizeof(ops)];
385 int red = rand() % 0xff;
386 int green = rand() % 0xff;
387 int blue = rand() % 0xff;
388 int alpha = rand() % 0xff;
389 int tx, ty, try = 50;
392 x = rand() % (real.width - 1);
393 y = rand() % (real.height - 1);
394 w = 1 + rand() % (real.width - x - 1);
395 h = 1 + rand() % (real.height - y - 1);
396 tx = w == real.width ? 0 : rand() % (real.width - w);
397 ty = h == real.height ? 0 : rand() % (real.height - h);
398 } while (((tx+w > x && tx < x+w) &&
399 (ty+h > y && ty < y+h)) &&
403 fill_rect(&t->real, real.picture,
404 use_window ? t->real.format : real.format,
408 red, green, blue, alpha);
409 fill_rect(&t->ref, ref.picture,
410 use_window ? t->ref.format : ref.format,
414 red, green, blue, alpha);
419 real.draw, real.format,
420 ref.draw, ref.format,
421 0, 0, real.width, real.height,
425 printf("passed [%d iterations x %d]\n", reps, sets);
427 test_target_destroy_render(&t->real, &real);
428 test_target_destroy_render(&t->ref, &ref);
431 static void random_trapezoid(XTrapezoid *trap, enum trapezoid trapezoid,
432 int x1, int y1, int x2, int y2)
436 x1 = x1 + rand() % (x2 - x1);
437 x2 = x1 + rand() % (x2 - x1);
438 y1 = y1 + rand() % (y2 - y1);
439 y2 = y1 + rand() % (y2 - y1);
441 trap->left.p1.x = trap->left.p2.x = x1 << 16;
442 trap->top = trap->left.p1.y = trap->right.p1.y = y1 << 16;
443 trap->right.p1.x = trap->right.p2.x = x2 << 16;
444 trap->bottom = trap->left.p2.y = trap->right.p2.y = y2 << 16;
448 x1 <<= 16; x2 <<= 16;
449 y1 <<= 16; y2 <<= 16;
451 x1 = x1 + rand() % (x2 - x1);
452 x2 = x1 + rand() % (x2 - x1);
453 y1 = y1 + rand() % (y2 - y1);
454 y2 = y1 + rand() % (y2 - y1);
456 trap->left.p1.x = trap->left.p2.x = x1;
457 trap->top = trap->left.p1.y = trap->right.p1.y = y1;
458 trap->right.p1.x = trap->right.p2.x = x2;
459 trap->bottom = trap->left.p2.y = trap->right.p2.y = y2;
463 x1 <<= 16; x2 <<= 16;
464 y1 <<= 16; y2 <<= 16;
466 trap->top = y1 + rand() % (y2 - y1);
467 trap->bottom = y1 + rand() % (y2 - y1);
469 trap->left.p1.x = x1 + rand() % (x2 - x1);
470 trap->left.p2.x = x1 + rand() % (x2 - x1);
472 trap->right.p1.x = x1 + rand() % (x2 - x1);
473 trap->right.p2.x = x1 + rand() % (x2 - x1);
478 static void fill_traps(struct test_display *t, Picture p, XRenderPictFormat *format,
479 uint8_t op, XTrapezoid *traps, int ntraps, enum mask mask,
480 int srcx, int srcy, int srcw, int srch,
481 uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
487 tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy),
488 srcw, srch, format->depth);
490 src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL);
491 color.red = red * alpha;
492 color.green = green * alpha;
493 color.blue = blue * alpha;
494 color.alpha = alpha << 8 | alpha;
495 XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, srcw, srch);
497 XRenderCompositeTrapezoids(t->dpy,
498 op, src, p, mask_format(t->dpy, mask),
499 srcx, srcy, traps, ntraps);
501 XRenderFreePicture(t->dpy, src);
502 XFreePixmap(t->dpy, tmp);
505 static void trap_tests(struct test *t,
507 enum trapezoid trapezoid,
511 struct test_target real, ref;
513 int max_traps = 65536;
516 traps = malloc(sizeof(*traps) * max_traps);
520 printf("Testing trapezoids (%s with mask %s) (%s): ",
521 trapezoid_name(trapezoid),
523 test_target_name(target));
526 test_target_create_render(&t->real, target, &real);
527 clear(&t->real, &real);
528 set_mask(&t->real, &real, mask);
530 test_target_create_render(&t->ref, target, &ref);
531 clear(&t->ref, &ref);
532 set_mask(&t->ref, &ref, mask);
534 for (s = 0; s < sets; s++) {
535 for (r = 0; r < reps; r++) {
536 int op = ops[rand() % sizeof(ops)];
537 int red = rand() % 0xff;
538 int green = rand() % 0xff;
539 int blue = rand() % 0xff;
540 int alpha = rand() % 0xff;
541 int num_traps = rand() % max_traps;
542 int srcx = rand() % 2*real.width - real.width;
543 int srcy = rand() % 2*real.height - real.height;
544 int srcw = rand() % real.width;
545 int srch = rand() % real.height;
547 for (n = 0; n < num_traps; n++)
548 random_trapezoid(&traps[n], 0,
549 0, 0, real.width, real.height);
552 fill_traps(&t->real, real.picture, real.format,
553 op, traps, num_traps, mask,
554 srcx, srcy, srcw, srch,
555 red, green, blue, alpha);
557 fill_traps(&t->ref, ref.picture, ref.format,
558 op, traps, num_traps, mask,
559 srcx, srcy, srcw, srch,
560 red, green, blue, alpha);
564 real.draw, real.format,
565 ref.draw, ref.format,
566 0, 0, real.width, real.height,
570 printf("passed [%d iterations x %d]\n", reps, sets);
572 test_target_destroy_render(&t->real, &real);
573 test_target_destroy_render(&t->ref, &ref);
577 int main(int argc, char **argv)
583 enum trapezoid trapezoid;
585 test_init(&test, argc, argv);
587 for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
589 int sets = 1 << (12 - i);
594 for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
595 pixel_tests(&test, reps, sets, target, 0);
596 area_tests(&test, reps, sets, target, 0);
597 for (dy = 0; dy < 1 << 16; dy += 1 << 14)
598 for (dx = 0; dx < 1 << 16; dx += 1 << 14)
599 for (mask = MASK_NONE; mask <= MASK_A8; mask++)
600 rect_tests(&test, dx, dy, mask, reps, sets, target, 0);
601 if (target != CHILD) {
602 pixel_tests(&test, reps, sets, target, 1);
603 area_tests(&test, reps, sets, target, 1);
604 for (dy = 0; dy < 1 << 16; dy += 1 << 14)
605 for (dx = 0; dx < 1 << 16; dx += 1 << 14)
606 for (mask = MASK_NONE; mask <= MASK_A8; mask++)
607 rect_tests(&test, dx, dy, mask, reps, sets, target, 1);
611 for (target = TARGET_FIRST; target <= TARGET_LAST; target++)
612 for (trapezoid = RECT_ALIGN; trapezoid <= GENERAL; trapezoid++)
613 trap_tests(&test, mask, trapezoid, reps, sets, target);