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