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