1#include <stdint.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5#include <X11/Xutil.h> /* for XDestroyImage */ 6#include <pixman.h> /* for pixman blt functions */ 7 8#include "test.h" 9 10static void 11show_cells(char *buf, 12 const uint32_t *out, const uint32_t *ref, 13 int x, int y, int w, int h) 14{ 15 int i, j, len = 0; 16 17 for (j = y - 2; j <= y + 2; j++) { 18 if (j < 0 || j >= h) 19 continue; 20 21 for (i = x - 2; i <= x + 2; i++) { 22 if (i < 0 || i >= w) 23 continue; 24 25 len += sprintf(buf+len, "%08x ", out[j*w+i]); 26 } 27 28 len += sprintf(buf+len, "\t"); 29 30 for (i = x - 2; i <= x + 2; i++) { 31 if (i < 0 || i >= w) 32 continue; 33 34 len += sprintf(buf+len, "%08x ", ref[j*w+i]); 35 } 36 37 len += sprintf(buf+len, "\n"); 38 } 39} 40 41static void fill_rect(struct test_display *t, Drawable d, uint8_t alu, 42 int x, int y, int w, int h, uint32_t fg) 43{ 44 XGCValues val; 45 GC gc; 46 47 val.function = alu; 48 val.foreground = fg; 49 50 gc = XCreateGC(t->dpy, d, GCForeground | GCFunction, &val); 51 XFillRectangle(t->dpy, d, gc, x, y, w, h); 52 XFreeGC(t->dpy, gc); 53} 54 55static void pixel_tests(struct test *t, int reps, int sets, enum target target) 56{ 57 struct test_target tt; 58 XImage image; 59 uint32_t *cells = malloc(t->out.width*t->out.height*4); 60 struct { 61 uint16_t x, y; 62 } *pixels = malloc(reps*sizeof(*pixels)); 63 int r, s; 64 65 test_target_create_render(&t->out, target, &tt); 66 67 printf("Testing setting of single pixels (%s): ", 68 test_target_name(target)); 69 fflush(stdout); 70 71 for (s = 0; s < sets; s++) { 72 for (r = 0; r < reps; r++) { 73 int x = rand() % (tt.width - 1); 74 int y = rand() % (tt.height - 1); 75 uint32_t fg = rand(); 76 77 fill_rect(&t->out, tt.draw, GXcopy, 78 x, y, 1, 1, fg); 79 80 pixels[r].x = x; 81 pixels[r].y = y; 82 cells[y*tt.width+x] = fg; 83 } 84 85 test_init_image(&image, &t->out.shm, tt.format, 1, 1); 86 87 for (r = 0; r < reps; r++) { 88 uint32_t x = pixels[r].x; 89 uint32_t y = pixels[r].y; 90 uint32_t result; 91 92 XShmGetImage(t->out.dpy, tt.draw, &image, 93 x, y, AllPlanes); 94 95 result = *(uint32_t *)image.data; 96 if (!pixel_equal(image.depth, result, 97 cells[y*tt.width+x])) { 98 uint32_t mask = depth_mask(image.depth); 99 100 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n", 101 x, y, 102 cells[y*tt.width+x] & mask, 103 cells[y*tt.width+x], 104 result & mask, 105 result); 106 } 107 } 108 } 109 printf("passed [%d iterations x %d]\n", reps, sets); 110 111 test_target_destroy_render(&t->out, &tt); 112 free(pixels); 113 free(cells); 114} 115 116static void clear(struct test_display *dpy, struct test_target *tt) 117{ 118 XRenderColor render_color = {0}; 119 XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color, 120 0, 0, tt->width, tt->height); 121} 122 123static void area_tests(struct test *t, int reps, int sets, enum target target) 124{ 125 struct test_target tt; 126 XImage image; 127 uint32_t *cells = calloc(sizeof(uint32_t), t->out.width*t->out.height); 128 int r, s, x, y; 129 130 printf("Testing area sets (%s): ", test_target_name(target)); 131 fflush(stdout); 132 133 test_target_create_render(&t->out, target, &tt); 134 clear(&t->out, &tt); 135 136 test_init_image(&image, &t->out.shm, tt.format, tt.width, tt.height); 137 138 for (s = 0; s < sets; s++) { 139 for (r = 0; r < reps; r++) { 140 int w = rand() % tt.width; 141 int h = rand() % tt.height; 142 uint32_t fg = rand(); 143 144 x = rand() % (2*tt.width) - tt.width; 145 y = rand() % (2*tt.height) - tt.height; 146 147 fill_rect(&t->out, tt.draw, GXcopy, 148 x, y, w, h, fg); 149 150 if (x < 0) 151 w += x, x = 0; 152 if (y < 0) 153 h += y, y = 0; 154 if (x >= tt.width || y >= tt.height) 155 continue; 156 157 if (x + w > tt.width) 158 w = tt.width - x; 159 if (y + h > tt.height) 160 h = tt.height - y; 161 if (w <= 0 || h <= 0) 162 continue; 163 164 pixman_fill(cells, tt.width, 32, x, y, w, h, fg); 165 } 166 167 XShmGetImage(t->out.dpy, tt.draw, &image, 0, 0, AllPlanes); 168 169 for (y = 0; y < tt.height; y++) { 170 for (x = 0; x < tt.width; x++) { 171 uint32_t result = *(uint32_t *) 172 (image.data + 173 y*image.bytes_per_line + 174 x*image.bits_per_pixel/8); 175 if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { 176 char buf[600]; 177 uint32_t mask = depth_mask(image.depth); 178 show_cells(buf, 179 (uint32_t*)image.data, cells, 180 x, y, tt.width, tt.height); 181 182 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s", 183 x, y, 184 cells[y*tt.width+x] & mask, 185 cells[y*tt.width+x], 186 result & mask, 187 result, buf); 188 } 189 } 190 } 191 } 192 193 printf("passed [%d iterations x %d]\n", reps, sets); 194 195 test_target_destroy_render(&t->out, &tt); 196 free(cells); 197} 198 199static void rect_tests(struct test *t, int reps, int sets, enum target target) 200{ 201 struct test_target out, ref; 202 int r, s; 203 204 printf("Testing area fills (%s): ", test_target_name(target)); 205 fflush(stdout); 206 207 test_target_create_render(&t->out, target, &out); 208 clear(&t->out, &out); 209 210 test_target_create_render(&t->ref, target, &ref); 211 clear(&t->ref, &ref); 212 213 for (s = 0; s < sets; s++) { 214 for (r = 0; r < reps; r++) { 215 int x = rand() % (2*out.width) - out.width; 216 int y = rand() % (2*out.height) - out.height; 217 int w = rand() % (2*out.width); 218 int h = rand() % (2*out.height); 219 uint8_t alu = rand() % (GXset + 1); 220 uint32_t fg = rand(); 221 222 fill_rect(&t->out, out.draw, alu, 223 x, y, w, h, fg); 224 fill_rect(&t->ref, ref.draw, alu, 225 x, y, w, h, fg); 226 } 227 228 test_compare(t, 229 out.draw, out.format, 230 ref.draw, ref.format, 231 0, 0, out.width, out.height, 232 ""); 233 } 234 235 printf("passed [%d iterations x %d]\n", reps, sets); 236 237 test_target_destroy_render(&t->out, &out); 238 test_target_destroy_render(&t->ref, &ref); 239} 240 241int main(int argc, char **argv) 242{ 243 struct test test; 244 int i; 245 246 test_init(&test, argc, argv); 247 248 for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 249 int reps = REPS(i), sets = SETS(i); 250 enum target t; 251 252 for (t = TARGET_FIRST; t <= TARGET_LAST; t++) { 253 pixel_tests(&test, reps, sets, t); 254 area_tests(&test, reps, sets, t); 255 rect_tests(&test, reps, sets, t); 256 } 257 } 258 259 return 0; 260} 261