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 void 1103b705cfSriastradhshow_cells(char *buf, 1242542f5fSchristos const uint32_t *out, const uint32_t *ref, 1303b705cfSriastradh int x, int y, int w, int h) 1403b705cfSriastradh{ 1503b705cfSriastradh int i, j, len = 0; 1603b705cfSriastradh 1703b705cfSriastradh for (j = y - 2; j <= y + 2; j++) { 1803b705cfSriastradh if (j < 0 || j >= h) 1903b705cfSriastradh continue; 2003b705cfSriastradh 2103b705cfSriastradh for (i = x - 2; i <= x + 2; i++) { 2203b705cfSriastradh if (i < 0 || i >= w) 2303b705cfSriastradh continue; 2403b705cfSriastradh 2542542f5fSchristos len += sprintf(buf+len, "%08x ", out[j*w+i]); 2603b705cfSriastradh } 2703b705cfSriastradh 2803b705cfSriastradh len += sprintf(buf+len, "\t"); 2903b705cfSriastradh 3003b705cfSriastradh for (i = x - 2; i <= x + 2; i++) { 3103b705cfSriastradh if (i < 0 || i >= w) 3203b705cfSriastradh continue; 3303b705cfSriastradh 3403b705cfSriastradh len += sprintf(buf+len, "%08x ", ref[j*w+i]); 3503b705cfSriastradh } 3603b705cfSriastradh 3703b705cfSriastradh len += sprintf(buf+len, "\n"); 3803b705cfSriastradh } 3903b705cfSriastradh} 4003b705cfSriastradh 4103b705cfSriastradhstatic void fill_rect(struct test_display *t, 4203b705cfSriastradh Picture p, 4303b705cfSriastradh XRenderPictFormat *format, 4403b705cfSriastradh int use_window, int tx, int ty, 4503b705cfSriastradh uint8_t op, int x, int y, int w, int h, 4603b705cfSriastradh uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) 4703b705cfSriastradh{ 4803b705cfSriastradh Drawable tmp; 4903b705cfSriastradh XRenderColor color; 5003b705cfSriastradh Picture src; 5103b705cfSriastradh 5203b705cfSriastradh if (use_window) { 5303b705cfSriastradh XSetWindowAttributes attr; 5403b705cfSriastradh 5503b705cfSriastradh attr.override_redirect = 1; 5603b705cfSriastradh tmp = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 5703b705cfSriastradh tx, ty, 5803b705cfSriastradh w, h, 5903b705cfSriastradh 0, format->depth, 6003b705cfSriastradh InputOutput, 6103b705cfSriastradh DefaultVisual(t->dpy, 6203b705cfSriastradh DefaultScreen(t->dpy)), 6303b705cfSriastradh CWOverrideRedirect, &attr); 6403b705cfSriastradh XMapWindow(t->dpy, tmp); 6503b705cfSriastradh } else 6603b705cfSriastradh tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy), 6703b705cfSriastradh w, h, format->depth); 6803b705cfSriastradh 6903b705cfSriastradh src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL); 7003b705cfSriastradh color.red = red * alpha; 7103b705cfSriastradh color.green = green * alpha; 7203b705cfSriastradh color.blue = blue * alpha; 7303b705cfSriastradh color.alpha = alpha << 8 | alpha; 7403b705cfSriastradh XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, w, h); 7503b705cfSriastradh XRenderComposite(t->dpy, op, src, 0, p, 0, 0, 0, 0, x, y, w, h); 7603b705cfSriastradh 7703b705cfSriastradh XRenderFreePicture(t->dpy, src); 7803b705cfSriastradh if (use_window) 7903b705cfSriastradh XDestroyWindow(t->dpy, tmp); 8003b705cfSriastradh else 8103b705cfSriastradh XFreePixmap(t->dpy, tmp); 8203b705cfSriastradh} 8303b705cfSriastradh 8403b705cfSriastradhstatic void pixel_tests(struct test *t, int reps, int sets, enum target target) 8503b705cfSriastradh{ 8603b705cfSriastradh struct test_target tt; 8703b705cfSriastradh XImage image; 8842542f5fSchristos uint32_t *cells = malloc(t->out.width*t->out.height*4); 8903b705cfSriastradh struct { 9003b705cfSriastradh uint16_t x, y; 9103b705cfSriastradh } *pixels = malloc(reps*sizeof(*pixels)); 9203b705cfSriastradh int r, s; 9303b705cfSriastradh 9442542f5fSchristos test_target_create_render(&t->out, target, &tt); 9503b705cfSriastradh 9603b705cfSriastradh printf("Testing setting of single pixels (%s): ", 9703b705cfSriastradh test_target_name(target)); 9803b705cfSriastradh fflush(stdout); 9903b705cfSriastradh 10003b705cfSriastradh for (s = 0; s < sets; s++) { 10103b705cfSriastradh for (r = 0; r < reps; r++) { 10203b705cfSriastradh int x = rand() % (tt.width - 1); 10303b705cfSriastradh int y = rand() % (tt.height - 1); 10403b705cfSriastradh uint8_t red = rand(); 10503b705cfSriastradh uint8_t green = rand(); 10603b705cfSriastradh uint8_t blue = rand(); 10703b705cfSriastradh uint8_t alpha = rand(); 10803b705cfSriastradh 10942542f5fSchristos fill_rect(&t->out, tt.picture, tt.format, 11003b705cfSriastradh 0, 0, 0, 11103b705cfSriastradh PictOpSrc, x, y, 1, 1, 11203b705cfSriastradh red, green, blue, alpha); 11303b705cfSriastradh 11403b705cfSriastradh pixels[r].x = x; 11503b705cfSriastradh pixels[r].y = y; 11603b705cfSriastradh cells[y*tt.width+x] = color(red, green, blue, alpha); 11703b705cfSriastradh } 11803b705cfSriastradh 11942542f5fSchristos test_init_image(&image, &t->out.shm, tt.format, 1, 1); 12003b705cfSriastradh 12103b705cfSriastradh for (r = 0; r < reps; r++) { 12203b705cfSriastradh uint32_t x = pixels[r].x; 12303b705cfSriastradh uint32_t y = pixels[r].y; 12403b705cfSriastradh uint32_t result; 12503b705cfSriastradh 12642542f5fSchristos XShmGetImage(t->out.dpy, tt.draw, &image, 12703b705cfSriastradh x, y, AllPlanes); 12803b705cfSriastradh 12903b705cfSriastradh result = *(uint32_t *)image.data; 13003b705cfSriastradh if (!pixel_equal(image.depth, result, 13103b705cfSriastradh cells[y*tt.width+x])) { 13203b705cfSriastradh uint32_t mask = depth_mask(image.depth); 13303b705cfSriastradh 13403b705cfSriastradh die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n", 13503b705cfSriastradh x, y, 13603b705cfSriastradh cells[y*tt.width+x] & mask, 13703b705cfSriastradh cells[y*tt.width+x], 13803b705cfSriastradh result & mask, 13903b705cfSriastradh result); 14003b705cfSriastradh } 14103b705cfSriastradh } 14203b705cfSriastradh } 14303b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 14403b705cfSriastradh 14542542f5fSchristos test_target_destroy_render(&t->out, &tt); 14603b705cfSriastradh free(pixels); 14703b705cfSriastradh free(cells); 14803b705cfSriastradh} 14903b705cfSriastradh 15003b705cfSriastradhstatic void clear(struct test_display *dpy, struct test_target *tt) 15103b705cfSriastradh{ 15203b705cfSriastradh XRenderColor render_color = {0}; 15303b705cfSriastradh XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color, 15403b705cfSriastradh 0, 0, tt->width, tt->height); 15503b705cfSriastradh} 15603b705cfSriastradh 15703b705cfSriastradhstatic void area_tests(struct test *t, int reps, int sets, enum target target) 15803b705cfSriastradh{ 15903b705cfSriastradh struct test_target tt; 16003b705cfSriastradh XImage image; 16142542f5fSchristos uint32_t *cells = calloc(sizeof(uint32_t), t->out.width*t->out.height); 16203b705cfSriastradh int r, s, x, y; 16303b705cfSriastradh 16403b705cfSriastradh printf("Testing area sets (%s): ", test_target_name(target)); 16503b705cfSriastradh fflush(stdout); 16603b705cfSriastradh 16742542f5fSchristos test_target_create_render(&t->out, target, &tt); 16842542f5fSchristos clear(&t->out, &tt); 16903b705cfSriastradh 17042542f5fSchristos test_init_image(&image, &t->out.shm, tt.format, tt.width, tt.height); 17103b705cfSriastradh 17203b705cfSriastradh for (s = 0; s < sets; s++) { 17303b705cfSriastradh for (r = 0; r < reps; r++) { 17403b705cfSriastradh int w = 1 + rand() % (tt.width - 1); 17503b705cfSriastradh int h = 1 + rand() % (tt.height - 1); 17603b705cfSriastradh uint8_t red = rand(); 17703b705cfSriastradh uint8_t green = rand(); 17803b705cfSriastradh uint8_t blue = rand(); 17903b705cfSriastradh uint8_t alpha = rand(); 18003b705cfSriastradh 18103b705cfSriastradh x = rand() % (2*tt.width) - tt.width; 18203b705cfSriastradh y = rand() % (2*tt.height) - tt.height; 18303b705cfSriastradh 18442542f5fSchristos fill_rect(&t->out, tt.picture, tt.format, 18503b705cfSriastradh 0, 0, 0, 18603b705cfSriastradh PictOpSrc, x, y, w, h, 18703b705cfSriastradh red, green, blue, alpha); 18803b705cfSriastradh 18903b705cfSriastradh if (x < 0) 19003b705cfSriastradh w += x, x = 0; 19103b705cfSriastradh if (y < 0) 19203b705cfSriastradh h += y, y = 0; 19303b705cfSriastradh if (x >= tt.width || y >= tt.height) 19403b705cfSriastradh continue; 19503b705cfSriastradh 19603b705cfSriastradh if (x + w > tt.width) 19703b705cfSriastradh w = tt.width - x; 19803b705cfSriastradh if (y + h > tt.height) 19903b705cfSriastradh h = tt.height - y; 20003b705cfSriastradh if (w <= 0 || h <= 0) 20103b705cfSriastradh continue; 20203b705cfSriastradh 20303b705cfSriastradh pixman_fill(cells, tt.width, 32, x, y, w, h, 20403b705cfSriastradh color(red, green, blue, alpha)); 20503b705cfSriastradh } 20603b705cfSriastradh 20742542f5fSchristos XShmGetImage(t->out.dpy, tt.draw, &image, 0, 0, AllPlanes); 20803b705cfSriastradh 20903b705cfSriastradh for (y = 0; y < tt.height; y++) { 21003b705cfSriastradh for (x = 0; x < tt.width; x++) { 21103b705cfSriastradh uint32_t result = *(uint32_t *) 21203b705cfSriastradh (image.data + 21303b705cfSriastradh y*image.bytes_per_line + 21403b705cfSriastradh x*image.bits_per_pixel/8); 21503b705cfSriastradh if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { 21603b705cfSriastradh char buf[600]; 21703b705cfSriastradh uint32_t mask = depth_mask(image.depth); 21803b705cfSriastradh show_cells(buf, 21903b705cfSriastradh (uint32_t*)image.data, cells, 22003b705cfSriastradh x, y, tt.width, tt.height); 22103b705cfSriastradh 22203b705cfSriastradh die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s", 22303b705cfSriastradh x, y, 22403b705cfSriastradh cells[y*tt.width+x] & mask, 22503b705cfSriastradh cells[y*tt.width+x], 22603b705cfSriastradh result & mask, 22703b705cfSriastradh result, buf); 22803b705cfSriastradh } 22903b705cfSriastradh } 23003b705cfSriastradh } 23103b705cfSriastradh } 23203b705cfSriastradh 23303b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 23403b705cfSriastradh 23542542f5fSchristos test_target_destroy_render(&t->out, &tt); 23603b705cfSriastradh free(cells); 23703b705cfSriastradh} 23803b705cfSriastradh 23903b705cfSriastradhstatic void rect_tests(struct test *t, int reps, int sets, enum target target, int use_window) 24003b705cfSriastradh{ 24142542f5fSchristos struct test_target out, ref; 24203b705cfSriastradh int r, s; 24303b705cfSriastradh printf("Testing area fills (%s, using %s source): ", 24403b705cfSriastradh test_target_name(target), use_window ? "window" : "pixmap"); 24503b705cfSriastradh fflush(stdout); 24603b705cfSriastradh 24742542f5fSchristos test_target_create_render(&t->out, target, &out); 24842542f5fSchristos clear(&t->out, &out); 24903b705cfSriastradh 25003b705cfSriastradh test_target_create_render(&t->ref, target, &ref); 25103b705cfSriastradh clear(&t->ref, &ref); 25203b705cfSriastradh 25303b705cfSriastradh for (s = 0; s < sets; s++) { 25403b705cfSriastradh for (r = 0; r < reps; r++) { 25503b705cfSriastradh int x, y, w, h; 25603b705cfSriastradh int tmpx, tmpy; 25703b705cfSriastradh uint8_t red = rand(); 25803b705cfSriastradh uint8_t green = rand(); 25903b705cfSriastradh uint8_t blue = rand(); 26003b705cfSriastradh uint8_t alpha = rand(); 26103b705cfSriastradh int try = 50; 26203b705cfSriastradh 26303b705cfSriastradh do { 26442542f5fSchristos x = rand() % (out.width - 1); 26542542f5fSchristos y = rand() % (out.height - 1); 26642542f5fSchristos w = 1 + rand() % (out.width - x - 1); 26742542f5fSchristos h = 1 + rand() % (out.height - y - 1); 26842542f5fSchristos tmpx = w == out.width ? 0 : rand() % (out.width - w); 26942542f5fSchristos tmpy = h == out.height ? 0 : rand() % (out.height - h); 27003b705cfSriastradh } while (((tmpx+w > x && tmpx < x+w) || 27103b705cfSriastradh (tmpy+h > y && tmpy < y+h)) && 27203b705cfSriastradh --try); 27303b705cfSriastradh 27403b705cfSriastradh 27503b705cfSriastradh if (try) { 27642542f5fSchristos fill_rect(&t->out, out.picture, out.format, 27703b705cfSriastradh use_window, tmpx, tmpy, 27803b705cfSriastradh PictOpSrc, x, y, w, h, 27903b705cfSriastradh red, green, blue, alpha); 28003b705cfSriastradh fill_rect(&t->ref, ref.picture, ref.format, 28103b705cfSriastradh use_window, tmpx, tmpy, 28203b705cfSriastradh PictOpSrc, x, y, w, h, 28303b705cfSriastradh red, green, blue, alpha); 28403b705cfSriastradh } 28503b705cfSriastradh } 28603b705cfSriastradh 28703b705cfSriastradh test_compare(t, 28842542f5fSchristos out.draw, out.format, 28903b705cfSriastradh ref.draw, ref.format, 29042542f5fSchristos 0, 0, out.width, out.height, 29103b705cfSriastradh ""); 29203b705cfSriastradh } 29303b705cfSriastradh 29403b705cfSriastradh printf("passed [%d iterations x %d]\n", reps, sets); 29503b705cfSriastradh 29642542f5fSchristos test_target_destroy_render(&t->out, &out); 29703b705cfSriastradh test_target_destroy_render(&t->ref, &ref); 29803b705cfSriastradh} 29903b705cfSriastradh 30003b705cfSriastradhint main(int argc, char **argv) 30103b705cfSriastradh{ 30203b705cfSriastradh struct test test; 30303b705cfSriastradh int i; 30403b705cfSriastradh 30503b705cfSriastradh test_init(&test, argc, argv); 30603b705cfSriastradh 30703b705cfSriastradh for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 30842542f5fSchristos int reps = REPS(i), sets = SETS(i); 30903b705cfSriastradh enum target t; 31003b705cfSriastradh 31103b705cfSriastradh for (t = TARGET_FIRST; t <= TARGET_LAST; t++) { 31203b705cfSriastradh pixel_tests(&test, reps, sets, t); 31303b705cfSriastradh area_tests(&test, reps, sets, t); 31403b705cfSriastradh rect_tests(&test, reps, sets, t, 0); 31503b705cfSriastradh if (t != PIXMAP) 31603b705cfSriastradh rect_tests(&test, reps, sets, t, 1); 31703b705cfSriastradh } 31803b705cfSriastradh } 31903b705cfSriastradh 32003b705cfSriastradh return 0; 32103b705cfSriastradh} 322