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