render-copyarea.c revision 03b705cf
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 *real, 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 ", real[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, 42 Picture p, 43 XRenderPictFormat *format, 44 int use_window, int tx, int ty, 45 uint8_t op, int x, int y, int w, int h, 46 uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) 47{ 48 Drawable tmp; 49 XRenderColor color; 50 Picture src; 51 52 if (use_window) { 53 XSetWindowAttributes attr; 54 55 attr.override_redirect = 1; 56 tmp = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 57 tx, ty, 58 w, h, 59 0, format->depth, 60 InputOutput, 61 DefaultVisual(t->dpy, 62 DefaultScreen(t->dpy)), 63 CWOverrideRedirect, &attr); 64 XMapWindow(t->dpy, tmp); 65 } else 66 tmp = XCreatePixmap(t->dpy, DefaultRootWindow(t->dpy), 67 w, h, format->depth); 68 69 src = XRenderCreatePicture(t->dpy, tmp, format, 0, NULL); 70 color.red = red * alpha; 71 color.green = green * alpha; 72 color.blue = blue * alpha; 73 color.alpha = alpha << 8 | alpha; 74 XRenderFillRectangle(t->dpy, PictOpSrc, src, &color, 0, 0, w, h); 75 XRenderComposite(t->dpy, op, src, 0, p, 0, 0, 0, 0, x, y, w, h); 76 77 XRenderFreePicture(t->dpy, src); 78 if (use_window) 79 XDestroyWindow(t->dpy, tmp); 80 else 81 XFreePixmap(t->dpy, tmp); 82} 83 84static void pixel_tests(struct test *t, int reps, int sets, enum target target) 85{ 86 struct test_target tt; 87 XImage image; 88 uint32_t *cells = malloc(t->real.width*t->real.height*4); 89 struct { 90 uint16_t x, y; 91 } *pixels = malloc(reps*sizeof(*pixels)); 92 int r, s; 93 94 test_target_create_render(&t->real, target, &tt); 95 96 printf("Testing setting of single pixels (%s): ", 97 test_target_name(target)); 98 fflush(stdout); 99 100 for (s = 0; s < sets; s++) { 101 for (r = 0; r < reps; r++) { 102 int x = rand() % (tt.width - 1); 103 int y = rand() % (tt.height - 1); 104 uint8_t red = rand(); 105 uint8_t green = rand(); 106 uint8_t blue = rand(); 107 uint8_t alpha = rand(); 108 109 fill_rect(&t->real, tt.picture, tt.format, 110 0, 0, 0, 111 PictOpSrc, x, y, 1, 1, 112 red, green, blue, alpha); 113 114 pixels[r].x = x; 115 pixels[r].y = y; 116 cells[y*tt.width+x] = color(red, green, blue, alpha); 117 } 118 119 test_init_image(&image, &t->real.shm, tt.format, 1, 1); 120 121 for (r = 0; r < reps; r++) { 122 uint32_t x = pixels[r].x; 123 uint32_t y = pixels[r].y; 124 uint32_t result; 125 126 XShmGetImage(t->real.dpy, tt.draw, &image, 127 x, y, AllPlanes); 128 129 result = *(uint32_t *)image.data; 130 if (!pixel_equal(image.depth, result, 131 cells[y*tt.width+x])) { 132 uint32_t mask = depth_mask(image.depth); 133 134 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n", 135 x, y, 136 cells[y*tt.width+x] & mask, 137 cells[y*tt.width+x], 138 result & mask, 139 result); 140 } 141 } 142 } 143 printf("passed [%d iterations x %d]\n", reps, sets); 144 145 test_target_destroy_render(&t->real, &tt); 146 free(pixels); 147 free(cells); 148} 149 150static void clear(struct test_display *dpy, struct test_target *tt) 151{ 152 XRenderColor render_color = {0}; 153 XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color, 154 0, 0, tt->width, tt->height); 155} 156 157static void area_tests(struct test *t, int reps, int sets, enum target target) 158{ 159 struct test_target tt; 160 XImage image; 161 uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height); 162 int r, s, x, y; 163 164 printf("Testing area sets (%s): ", test_target_name(target)); 165 fflush(stdout); 166 167 test_target_create_render(&t->real, target, &tt); 168 clear(&t->real, &tt); 169 170 test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height); 171 172 for (s = 0; s < sets; s++) { 173 for (r = 0; r < reps; r++) { 174 int w = 1 + rand() % (tt.width - 1); 175 int h = 1 + rand() % (tt.height - 1); 176 uint8_t red = rand(); 177 uint8_t green = rand(); 178 uint8_t blue = rand(); 179 uint8_t alpha = rand(); 180 181 x = rand() % (2*tt.width) - tt.width; 182 y = rand() % (2*tt.height) - tt.height; 183 184 fill_rect(&t->real, tt.picture, tt.format, 185 0, 0, 0, 186 PictOpSrc, x, y, w, h, 187 red, green, blue, alpha); 188 189 if (x < 0) 190 w += x, x = 0; 191 if (y < 0) 192 h += y, y = 0; 193 if (x >= tt.width || y >= tt.height) 194 continue; 195 196 if (x + w > tt.width) 197 w = tt.width - x; 198 if (y + h > tt.height) 199 h = tt.height - y; 200 if (w <= 0 || h <= 0) 201 continue; 202 203 pixman_fill(cells, tt.width, 32, x, y, w, h, 204 color(red, green, blue, alpha)); 205 } 206 207 XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes); 208 209 for (y = 0; y < tt.height; y++) { 210 for (x = 0; x < tt.width; x++) { 211 uint32_t result = *(uint32_t *) 212 (image.data + 213 y*image.bytes_per_line + 214 x*image.bits_per_pixel/8); 215 if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { 216 char buf[600]; 217 uint32_t mask = depth_mask(image.depth); 218 show_cells(buf, 219 (uint32_t*)image.data, cells, 220 x, y, tt.width, tt.height); 221 222 die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s", 223 x, y, 224 cells[y*tt.width+x] & mask, 225 cells[y*tt.width+x], 226 result & mask, 227 result, buf); 228 } 229 } 230 } 231 } 232 233 printf("passed [%d iterations x %d]\n", reps, sets); 234 235 test_target_destroy_render(&t->real, &tt); 236 free(cells); 237} 238 239static void rect_tests(struct test *t, int reps, int sets, enum target target, int use_window) 240{ 241 struct test_target real, ref; 242 int r, s; 243 printf("Testing area fills (%s, using %s source): ", 244 test_target_name(target), use_window ? "window" : "pixmap"); 245 fflush(stdout); 246 247 test_target_create_render(&t->real, target, &real); 248 clear(&t->real, &real); 249 250 test_target_create_render(&t->ref, target, &ref); 251 clear(&t->ref, &ref); 252 253 for (s = 0; s < sets; s++) { 254 for (r = 0; r < reps; r++) { 255 int x, y, w, h; 256 int tmpx, tmpy; 257 uint8_t red = rand(); 258 uint8_t green = rand(); 259 uint8_t blue = rand(); 260 uint8_t alpha = rand(); 261 int try = 50; 262 263 do { 264 x = rand() % (real.width - 1); 265 y = rand() % (real.height - 1); 266 w = 1 + rand() % (real.width - x - 1); 267 h = 1 + rand() % (real.height - y - 1); 268 tmpx = w == real.width ? 0 : rand() % (real.width - w); 269 tmpy = h == real.height ? 0 : rand() % (real.height - h); 270 } while (((tmpx+w > x && tmpx < x+w) || 271 (tmpy+h > y && tmpy < y+h)) && 272 --try); 273 274 275 if (try) { 276 fill_rect(&t->real, real.picture, real.format, 277 use_window, tmpx, tmpy, 278 PictOpSrc, x, y, w, h, 279 red, green, blue, alpha); 280 fill_rect(&t->ref, ref.picture, ref.format, 281 use_window, tmpx, tmpy, 282 PictOpSrc, x, y, w, h, 283 red, green, blue, alpha); 284 } 285 } 286 287 test_compare(t, 288 real.draw, real.format, 289 ref.draw, ref.format, 290 0, 0, real.width, real.height, 291 ""); 292 } 293 294 printf("passed [%d iterations x %d]\n", reps, sets); 295 296 test_target_destroy_render(&t->real, &real); 297 test_target_destroy_render(&t->ref, &ref); 298} 299 300int main(int argc, char **argv) 301{ 302 struct test test; 303 int i; 304 305 test_init(&test, argc, argv); 306 307 for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 308 int reps = 1 << i; 309 int sets = 1 << (12 - i); 310 enum target t; 311 312 if (sets < 2) 313 sets = 2; 314 315 for (t = TARGET_FIRST; t <= TARGET_LAST; t++) { 316 pixel_tests(&test, reps, sets, t); 317 area_tests(&test, reps, sets, t); 318 rect_tests(&test, reps, sets, t, 0); 319 if (t != PIXMAP) 320 rect_tests(&test, reps, sets, t, 1); 321 } 322 } 323 324 return 0; 325} 326