103b705cfSriastradh#include <stdint.h> 203b705cfSriastradh#include <stdio.h> 303b705cfSriastradh#include <stdlib.h> 403b705cfSriastradh 503b705cfSriastradh#include <X11/Xutil.h> /* for XDestroyImage */ 603b705cfSriastradh#include <pixman.h> /* for pixman blt functions */ 703b705cfSriastradh 803b705cfSriastradh#include "test.h" 903b705cfSriastradh 1003b705cfSriastradhstatic const uint8_t ops[] = { 1103b705cfSriastradh PictOpClear, 1203b705cfSriastradh PictOpSrc, 1303b705cfSriastradh PictOpDst, 1403b705cfSriastradh}; 1503b705cfSriastradh 1603b705cfSriastradhstatic void fill_rect(struct test_display *dpy, 1703b705cfSriastradh Picture p, 1803b705cfSriastradh XRenderPictFormat *format, 1903b705cfSriastradh uint8_t op, int x, int y, int w, int h, 2003b705cfSriastradh uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) 2103b705cfSriastradh{ 2203b705cfSriastradh Display *d = dpy->dpy; 2303b705cfSriastradh XRenderColor render_color; 2403b705cfSriastradh Pixmap pixmap1, pixmap2; 2503b705cfSriastradh Picture tmp1, tmp2; 2603b705cfSriastradh XRenderPictureAttributes pa; 2703b705cfSriastradh GC gc; 2803b705cfSriastradh 2903b705cfSriastradh render_color.red = red * alpha; 3003b705cfSriastradh render_color.green = green * alpha; 3103b705cfSriastradh render_color.blue = blue * alpha; 3203b705cfSriastradh render_color.alpha = alpha << 8; 3303b705cfSriastradh 3403b705cfSriastradh pixmap1 = XCreatePixmap(d, dpy->root, 1, 1, format->depth); 3503b705cfSriastradh tmp1 = XRenderCreatePicture(d, pixmap1, format, 0, NULL); 3603b705cfSriastradh 3703b705cfSriastradh pixmap2 = XCreatePixmap(d, dpy->root, 1, 1, format->depth); 3803b705cfSriastradh pa.repeat = 1; 3903b705cfSriastradh tmp2 = XRenderCreatePicture(d, pixmap2, format, CPRepeat, &pa); 4003b705cfSriastradh 4103b705cfSriastradh gc = XCreateGC(d, pixmap1, 0, NULL); 4203b705cfSriastradh 4303b705cfSriastradh XRenderFillRectangle(d, PictOpSrc, tmp1, &render_color, 0, 0, 1,1); 4403b705cfSriastradh XCopyArea(d, pixmap1, pixmap2, gc, 0, 0, 1, 1, 0, 0); 4503b705cfSriastradh XRenderComposite(d, PictOpSrc, tmp2, 0, p, 0, 0, 0, 0, x, y, w,h); 4603b705cfSriastradh 4703b705cfSriastradh XFreeGC(d, gc); 4803b705cfSriastradh 4903b705cfSriastradh XRenderFreePicture(d, tmp2); 5003b705cfSriastradh XFreePixmap(d, pixmap2); 5103b705cfSriastradh 5203b705cfSriastradh XRenderFreePicture(d, tmp1); 5303b705cfSriastradh XFreePixmap(d, pixmap1); 5403b705cfSriastradh} 5503b705cfSriastradh 5603b705cfSriastradhstatic void pixel_tests(struct test *t, int reps, int sets, enum target target) 5703b705cfSriastradh{ 5803b705cfSriastradh struct test_target tt; 5903b705cfSriastradh XImage image; 6042542f5fSchristos uint32_t *cells = malloc(t->out.width*t->out.height*4); 6103b705cfSriastradh struct { 6203b705cfSriastradh uint16_t x, y; 6303b705cfSriastradh } *pixels = malloc(reps*sizeof(*pixels)); 6403b705cfSriastradh int r, s; 6503b705cfSriastradh 6642542f5fSchristos test_target_create_render(&t->out, target, &tt); 6703b705cfSriastradh 6803b705cfSriastradh printf("Testing setting of single pixels (%s): ", 6903b705cfSriastradh test_target_name(target)); 7003b705cfSriastradh fflush(stdout); 7103b705cfSriastradh 7203b705cfSriastradh for (s = 0; s < sets; s++) { 7303b705cfSriastradh for (r = 0; r < reps; r++) { 7403b705cfSriastradh int x = rand() % (tt.width - 1); 7503b705cfSriastradh int y = rand() % (tt.height - 1); 7603b705cfSriastradh int red = rand() % 0xff; 7703b705cfSriastradh int green = rand() % 0xff; 7803b705cfSriastradh int blue = rand() % 0xff; 7903b705cfSriastradh int alpha = rand() % 0xff; 8003b705cfSriastradh 8142542f5fSchristos fill_rect(&t->out, tt.picture, tt.format, 8203b705cfSriastradh PictOpSrc, x, y, 1, 1, 8303b705cfSriastradh red, green, blue, alpha); 8403b705cfSriastradh 8503b705cfSriastradh pixels[r].x = x; 8603b705cfSriastradh pixels[r].y = y; 8703b705cfSriastradh cells[y*tt.width+x] = color(red, green, blue, alpha); 8803b705cfSriastradh } 8903b705cfSriastradh 9042542f5fSchristos test_init_image(&image, &t->out.shm, tt.format, 1, 1); 9103b705cfSriastradh 9203b705cfSriastradh for (r = 0; r < reps; r++) { 9303b705cfSriastradh uint32_t result; 9403b705cfSriastradh uint32_t x = pixels[r].x; 9503b705cfSriastradh uint32_t y = pixels[r].y; 9603b705cfSriastradh 9742542f5fSchristos XShmGetImage(t->out.dpy, tt.draw, &image, 9803b705cfSriastradh x, y, AllPlanes); 9903b705cfSriastradh 10003b705cfSriastradh result = *(uint32_t *)image.data; 10103b705cfSriastradh if (!pixel_equal(image.depth, result, 10203b705cfSriastradh cells[y*tt.width+x])) { 10303b705cfSriastradh uint32_t mask; 10403b705cfSriastradh 10503b705cfSriastradh if (image.depth == 32) 10603b705cfSriastradh mask = 0xffffffff; 10703b705cfSriastradh else 10803b705cfSriastradh mask = (1 << image.depth) - 1; 10903b705cfSriastradh die("failed to set pixel (%d,%d) to %08x, found %08x instead\n", 11003b705cfSriastradh x, y, 11103b705cfSriastradh cells[y*tt.width+x] & mask, 11203b705cfSriastradh result & mask); 11303b705cfSriastradh } 11403b705cfSriastradh } 11503b705cfSriastradh } 11603b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 11703b705cfSriastradh 11842542f5fSchristos test_target_destroy_render(&t->out, &tt); 11903b705cfSriastradh free(pixels); 12003b705cfSriastradh free(cells); 12103b705cfSriastradh} 12203b705cfSriastradh 12303b705cfSriastradhstatic void clear(struct test_display *dpy, struct test_target *tt) 12403b705cfSriastradh{ 12503b705cfSriastradh XRenderColor render_color = {0}; 12603b705cfSriastradh XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color, 12703b705cfSriastradh 0, 0, tt->width, tt->height); 12803b705cfSriastradh} 12903b705cfSriastradh 13003b705cfSriastradhstatic void area_tests(struct test *t, int reps, int sets, enum target target) 13103b705cfSriastradh{ 13203b705cfSriastradh struct test_target tt; 13303b705cfSriastradh XImage image; 13442542f5fSchristos uint32_t *cells = calloc(sizeof(uint32_t), t->out.width*t->out.height); 13503b705cfSriastradh int r, s, x, y; 13603b705cfSriastradh 13703b705cfSriastradh printf("Testing area sets (%s): ", test_target_name(target)); 13803b705cfSriastradh fflush(stdout); 13903b705cfSriastradh 14042542f5fSchristos test_target_create_render(&t->out, target, &tt); 14142542f5fSchristos clear(&t->out, &tt); 14203b705cfSriastradh 14342542f5fSchristos test_init_image(&image, &t->out.shm, tt.format, tt.width, tt.height); 14403b705cfSriastradh 14503b705cfSriastradh for (s = 0; s < sets; s++) { 14603b705cfSriastradh for (r = 0; r < reps; r++) { 14703b705cfSriastradh int w = rand() % tt.width; 14803b705cfSriastradh int h = rand() % tt.height; 14903b705cfSriastradh int red = rand() % 0xff; 15003b705cfSriastradh int green = rand() % 0xff; 15103b705cfSriastradh int blue = rand() % 0xff; 15203b705cfSriastradh int alpha = rand() % 0xff; 15303b705cfSriastradh 15403b705cfSriastradh x = rand() % (2*tt.width) - tt.width; 15503b705cfSriastradh y = rand() % (2*tt.height) - tt.height; 15603b705cfSriastradh 15742542f5fSchristos fill_rect(&t->out, tt.picture, tt.format, 15803b705cfSriastradh PictOpSrc, x, y, w, h, 15903b705cfSriastradh red, green, blue, alpha); 16003b705cfSriastradh 16103b705cfSriastradh if (x < 0) 16203b705cfSriastradh w += x, x = 0; 16303b705cfSriastradh if (y < 0) 16403b705cfSriastradh h += y, y = 0; 16503b705cfSriastradh if (x >= tt.width || y >= tt.height) 16603b705cfSriastradh continue; 16703b705cfSriastradh 16803b705cfSriastradh if (x + w > tt.width) 16903b705cfSriastradh w = tt.width - x; 17003b705cfSriastradh if (y + h > tt.height) 17103b705cfSriastradh h = tt.height - y; 17203b705cfSriastradh if (w <= 0 || h <= 0) 17303b705cfSriastradh continue; 17403b705cfSriastradh 17503b705cfSriastradh pixman_fill(cells, tt.width, 32, x, y, w, h, 17603b705cfSriastradh color(red, green, blue, alpha)); 17703b705cfSriastradh } 17803b705cfSriastradh 17942542f5fSchristos XShmGetImage(t->out.dpy, tt.draw, &image, 0, 0, AllPlanes); 18003b705cfSriastradh 18103b705cfSriastradh for (y = 0; y < tt.height; y++) { 18203b705cfSriastradh for (x = 0; x < tt.width; x++) { 18303b705cfSriastradh uint32_t result = 18403b705cfSriastradh *(uint32_t *)(image.data + 18503b705cfSriastradh y*image.bytes_per_line + 18603b705cfSriastradh image.bits_per_pixel*x/8); 18703b705cfSriastradh if (!pixel_equal(image.depth, result, 18803b705cfSriastradh cells[y*tt.width+x])) { 18903b705cfSriastradh uint32_t mask; 19003b705cfSriastradh 19103b705cfSriastradh if (image.depth == 32) 19203b705cfSriastradh mask = 0xffffffff; 19303b705cfSriastradh else 19403b705cfSriastradh mask = (1 << image.depth) - 1; 19503b705cfSriastradh die("failed to set pixel (%d,%d) to %08x, found %08x instead\n", 19603b705cfSriastradh x, y, 19703b705cfSriastradh cells[y*tt.width+x] & mask, 19803b705cfSriastradh result & mask); 19903b705cfSriastradh } 20003b705cfSriastradh } 20103b705cfSriastradh } 20203b705cfSriastradh } 20303b705cfSriastradh 20403b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 20503b705cfSriastradh 20642542f5fSchristos test_target_destroy_render(&t->out, &tt); 20703b705cfSriastradh free(cells); 20803b705cfSriastradh} 20903b705cfSriastradh 21003b705cfSriastradhstatic void rect_tests(struct test *t, int reps, int sets, enum target target) 21103b705cfSriastradh{ 21242542f5fSchristos struct test_target out, ref; 21303b705cfSriastradh int r, s; 21403b705cfSriastradh 21503b705cfSriastradh printf("Testing area fills (%s): ", test_target_name(target)); 21603b705cfSriastradh fflush(stdout); 21703b705cfSriastradh 21842542f5fSchristos test_target_create_render(&t->out, target, &out); 21942542f5fSchristos clear(&t->out, &out); 22003b705cfSriastradh 22103b705cfSriastradh test_target_create_render(&t->ref, target, &ref); 22203b705cfSriastradh clear(&t->ref, &ref); 22303b705cfSriastradh 22403b705cfSriastradh for (s = 0; s < sets; s++) { 22503b705cfSriastradh for (r = 0; r < reps; r++) { 22642542f5fSchristos int x = rand() % (2*out.width) - out.width; 22742542f5fSchristos int y = rand() % (2*out.height) - out.height; 22842542f5fSchristos int w = rand() % out.width; 22942542f5fSchristos int h = rand() % out.height; 23003b705cfSriastradh int op = ops[rand() % sizeof(ops)]; 23103b705cfSriastradh int red = rand() % 0xff; 23203b705cfSriastradh int green = rand() % 0xff; 23303b705cfSriastradh int blue = rand() % 0xff; 23403b705cfSriastradh int alpha = rand() % 0xff; 23503b705cfSriastradh 23642542f5fSchristos fill_rect(&t->out, out.picture, out.format, 23703b705cfSriastradh op, x, y, w, h, 23803b705cfSriastradh red, green, blue, alpha); 23903b705cfSriastradh fill_rect(&t->ref, ref.picture, ref.format, 24003b705cfSriastradh op, x, y, w, h, 24103b705cfSriastradh red, green, blue, alpha); 24203b705cfSriastradh } 24303b705cfSriastradh 24403b705cfSriastradh test_compare(t, 24542542f5fSchristos out.draw, out.format, 24603b705cfSriastradh ref.draw, ref.format, 24742542f5fSchristos 0, 0, out.width, out.height, 24803b705cfSriastradh ""); 24903b705cfSriastradh } 25003b705cfSriastradh 25103b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 25203b705cfSriastradh 25342542f5fSchristos test_target_destroy_render(&t->out, &out); 25403b705cfSriastradh test_target_destroy_render(&t->ref, &ref); 25503b705cfSriastradh} 25603b705cfSriastradh 25703b705cfSriastradhint main(int argc, char **argv) 25803b705cfSriastradh{ 25903b705cfSriastradh struct test test; 26003b705cfSriastradh int i; 26103b705cfSriastradh 26203b705cfSriastradh test_init(&test, argc, argv); 26303b705cfSriastradh 26403b705cfSriastradh for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 26542542f5fSchristos int reps = REPS(i), sets = SETS(i); 26603b705cfSriastradh enum target t; 26703b705cfSriastradh 26803b705cfSriastradh for (t = TARGET_FIRST; t <= TARGET_LAST; t++) { 26903b705cfSriastradh pixel_tests(&test, reps, sets, t); 27003b705cfSriastradh area_tests(&test, reps, sets, t); 27103b705cfSriastradh rect_tests(&test, reps, sets, t); 27203b705cfSriastradh } 27303b705cfSriastradh } 27403b705cfSriastradh 27503b705cfSriastradh return 0; 27603b705cfSriastradh} 277