1#include <stdint.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5#include "test.h" 6 7static const unsigned char data[] = { 8 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 9 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 10 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 11 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 12}; 13 14static struct bitmap { 15 int width, height; 16 struct cache { 17 Display *dpy; 18 Pixmap pixmap; 19 } cached[2]; 20} bitmaps[] = { 21 { 1, 1, }, 22 { 1, 2, }, 23 { 2, 3, }, 24 { 3, 2, }, 25 { 4, 4, }, 26 { 6, 6, }, 27 { 8, 8, }, 28 { 8, 4, }, 29 { 8, 2, }, 30 { 8, 1, }, 31 { 4, 8, }, 32 { 2, 8, }, 33 { 1, 8, }, 34 { 16, 16, }, 35 { 15, 17, }, 36 { 24, 24, }, 37 { 32, 32, }, 38 { 16, 8, }, 39 { 16, 4, }, 40 { 16, 2, }, 41 { 16, 1, }, 42 { 8, 16, }, 43 { 4, 16, }, 44 { 2, 16, }, 45 { 1, 16, }, 46}; 47 48static void reset_cache(void) 49{ 50 int n, m; 51 52 for (n = 0; n < sizeof(bitmaps)/sizeof(bitmaps[0]); n++) { 53 for (m = 0; m < 2; m++) { 54 if (bitmaps[n].cached[m].dpy) { 55 XFreePixmap(bitmaps[n].cached[m].dpy, bitmaps[n].cached[m].pixmap); 56 bitmaps[n].cached[m].dpy = NULL; 57 } 58 } 59 } 60} 61 62static void fill_rect(struct test_target *t, uint8_t alu, 63 XRectangle *clip, int nclip, 64 uint8_t tile, int tx, int ty, 65 int x, int y, int w, int h, 66 uint32_t fg, uint32_t bg) 67{ 68 Display *dpy = t->dpy->dpy; 69 struct bitmap *b = &bitmaps[(tile >> 1) % (sizeof(bitmaps)/sizeof(bitmaps[0]))]; 70 XGCValues val; 71 GC gc; 72 int n; 73 74 val.function = alu; 75 val.function = GXcopy; 76 val.fill_style = FillTiled; 77 val.ts_x_origin = tx; 78 val.ts_y_origin = ty; 79 if (tile & 1) { 80 val.tile = 0; 81 for (n = 0; n < 2; n++) { 82 if (b->cached[n].dpy == dpy) { 83 val.tile = b->cached[n].pixmap; 84 break; 85 } 86 } 87 if (val.tile == 0) { 88 val.tile = XCreatePixmapFromBitmapData(dpy, t->draw, 89 (char *)data, b->width, b->height, 90 fg, bg, t->depth); 91 for (n = 0; n < 2; n++) { 92 if (b->cached[n].dpy == NULL) { 93 b->cached[n].dpy = dpy; 94 b->cached[n].pixmap = val.tile; 95 break; 96 } 97 } 98 } 99 } else 100 val.tile = XCreatePixmapFromBitmapData(dpy, t->draw, 101 (char *)data, b->width, b->height, 102 fg, bg, t->depth); 103 104 gc = XCreateGC(dpy, t->draw, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCTile | GCFunction, &val); 105 if (nclip) 106 XSetClipRectangles(dpy, gc, 0, 0, clip, nclip, Unsorted); 107 XFillRectangle(dpy, t->draw, gc, x, y, w, h); 108 XFreeGC(dpy, gc); 109 if ((tile & 1) == 0) 110 XFreePixmap(dpy, val.tile); 111} 112 113static void clear(struct test_target *tt) 114{ 115 XRenderColor render_color = {0}; 116 XRenderFillRectangle(tt->dpy->dpy, PictOpClear, tt->picture, &render_color, 117 0, 0, tt->width, tt->height); 118} 119 120static void small_tests(struct test *t, int reps, int sets, enum target target) 121{ 122 struct test_target out, ref; 123 int r, s; 124 125 printf("Testing small tiled fills (%s): ", test_target_name(target)); 126 fflush(stdout); 127 128 test_target_create_render(&t->out, target, &out); 129 clear(&out); 130 131 test_target_create_render(&t->ref, target, &ref); 132 clear(&ref); 133 134 for (s = 0; s < sets; s++) { 135 for (r = 0; r < reps; r++) { 136 int x = rand() % out.width; 137 int y = rand() % out.height; 138 int w = rand() % out.width; 139 int h = rand() % 8; 140 int tx = rand() % (2*out.width) - out.width; 141 int ty = rand() % (2*out.height) - out.height; 142 uint8_t tile = rand(); 143 uint8_t alu = rand() % (GXset + 1); 144 uint32_t fg = rand(); 145 uint32_t bg = rand(); 146 147 fill_rect(&out, alu, NULL, 0, 148 tile, tx, ty, 149 x, y, w, h, 150 fg, bg); 151 fill_rect(&ref, alu, NULL, 0, 152 tile, tx, ty, 153 x, y, w, h, 154 fg, bg); 155 156 fill_rect(&out, alu, NULL, 0, 157 tile, tx, ty, 158 x, y, h, w, 159 fg, bg); 160 fill_rect(&ref, alu, NULL, 0, 161 tile, tx, ty, 162 x, y, h, w, 163 fg, bg); 164 } 165 166 test_compare(t, 167 out.draw, out.format, 168 ref.draw, ref.format, 169 0, 0, out.width, out.height, 170 ""); 171 172 if (target == CHILD) { 173 int x = rand() % (t->out.width-out.width); 174 int y = rand() % (t->out.height-out.height); 175 176 clear(&out); 177 clear(&ref); 178 179 XMoveWindow(out.dpy->dpy, out.draw, x, y); 180 XMoveWindow(ref.dpy->dpy, ref.draw, x, y); 181 182 clear(&out); 183 clear(&ref); 184 } 185 } 186 187 printf("passed [%d iterations x %d]\n", reps, sets); 188 189 test_target_destroy_render(&t->out, &out); 190 test_target_destroy_render(&t->ref, &ref); 191} 192 193static void unclipped_tests(struct test *t, int reps, int sets, enum target target) 194{ 195 struct test_target out, ref; 196 int r, s; 197 198 printf("Testing unclipped tiled fills (%s): ", test_target_name(target)); 199 fflush(stdout); 200 201 test_target_create_render(&t->out, target, &out); 202 clear(&out); 203 204 test_target_create_render(&t->ref, target, &ref); 205 clear(&ref); 206 207 for (s = 0; s < sets; s++) { 208 for (r = 0; r < reps; r++) { 209 int x = rand() % out.width; 210 int y = rand() % out.height; 211 int w = rand() % (out.width - x); 212 int h = rand() % (out.height - y); 213 int tx = rand() % (2*out.width) - out.width; 214 int ty = rand() % (2*out.height) - out.height; 215 uint8_t tile = rand(); 216 uint8_t alu = rand() % (GXset + 1); 217 uint32_t fg = rand(); 218 uint32_t bg = rand(); 219 220 fill_rect(&out, alu, NULL, 0, 221 tile, tx, ty, 222 x, y, w, h, 223 fg, bg); 224 fill_rect(&ref, alu, NULL, 0, 225 tile, tx, ty, 226 x, y, w, h, 227 fg, bg); 228 } 229 230 test_compare(t, 231 out.draw, out.format, 232 ref.draw, ref.format, 233 0, 0, out.width, out.height, 234 ""); 235 236 if (target == CHILD) { 237 int x = rand() % (t->out.width-out.width); 238 int y = rand() % (t->out.height-out.height); 239 240 clear(&out); 241 clear(&ref); 242 243 XMoveWindow(out.dpy->dpy, out.draw, x, y); 244 XMoveWindow(ref.dpy->dpy, ref.draw, x, y); 245 246 clear(&out); 247 clear(&ref); 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 257static void simple_clip_tests(struct test *t, int reps, int sets, enum target target) 258{ 259 struct test_target out, ref; 260 int r, s; 261 262 printf("Testing simple clipped tiled fills (%s): ", test_target_name(target)); 263 fflush(stdout); 264 265 test_target_create_render(&t->out, target, &out); 266 clear(&out); 267 268 test_target_create_render(&t->ref, target, &ref); 269 clear(&ref); 270 271 for (s = 0; s < sets; s++) { 272 for (r = 0; r < reps; r++) { 273 int x = rand() % (2*out.width) - out.width; 274 int y = rand() % (2*out.height) - out.height; 275 int w = rand() % (2*out.width); 276 int h = rand() % (2*out.height); 277 int tx = rand() % (2*out.width) - out.width; 278 int ty = rand() % (2*out.height) - out.height; 279 uint8_t tile = rand(); 280 uint8_t alu = rand() % (GXset + 1); 281 uint32_t fg = rand(); 282 uint32_t bg = rand(); 283 284 fill_rect(&out, alu, NULL, 0, 285 tile, tx, ty, 286 x, y, w, h, 287 fg, bg); 288 fill_rect(&ref, alu, NULL, 0, 289 tile, tx, ty, 290 x, y, w, h, 291 fg, bg); 292 } 293 294 test_compare(t, 295 out.draw, out.format, 296 ref.draw, ref.format, 297 0, 0, out.width, out.height, 298 ""); 299 300 if (target == CHILD) { 301 int x = rand() % (t->out.width-out.width); 302 int y = rand() % (t->out.height-out.height); 303 304 clear(&out); 305 clear(&ref); 306 307 XMoveWindow(out.dpy->dpy, out.draw, x, y); 308 XMoveWindow(ref.dpy->dpy, ref.draw, x, y); 309 310 clear(&out); 311 clear(&ref); 312 } 313 } 314 315 printf("passed [%d iterations x %d]\n", reps, sets); 316 317 test_target_destroy_render(&t->out, &out); 318 test_target_destroy_render(&t->ref, &ref); 319} 320 321static void complex_clip_tests(struct test *t, int reps, int sets, enum target target) 322{ 323 struct test_target out, ref; 324 XRectangle *clip; 325 int nclip, r, s; 326 327 printf("Testing complex clipped tiled fills (%s): ", test_target_name(target)); 328 fflush(stdout); 329 330 test_target_create_render(&t->out, target, &out); 331 clear(&out); 332 333 test_target_create_render(&t->ref, target, &ref); 334 clear(&ref); 335 336 for (s = 0; s < sets; s++) { 337 nclip = (rand() % 16) + 2; 338 clip = malloc(sizeof(XRectangle)*nclip); 339 for (r = 0; r < nclip; r++) { 340 clip[r].x = rand() % out.width; 341 clip[r].y = rand() % out.height; 342 clip[r].width = rand() % (out.width - clip[r].x); 343 clip[r].height = rand() % (out.height - clip[r].y); 344 } 345 346 for (r = 0; r < reps; r++) { 347 int x = rand() % (2*out.width) - out.width; 348 int y = rand() % (2*out.height) - out.height; 349 int w = rand() % (2*out.width); 350 int h = rand() % (2*out.height); 351 int tx = rand() % (2*out.width) - out.width; 352 int ty = rand() % (2*out.height) - out.height; 353 uint8_t tile = rand(); 354 uint8_t alu = rand() % (GXset + 1); 355 uint32_t fg = rand(); 356 uint32_t bg = rand(); 357 358 fill_rect(&out, alu, clip, nclip, 359 tile, tx, ty, 360 x, y, w, h, 361 fg, bg); 362 fill_rect(&ref, alu, clip, nclip, 363 tile, tx, ty, 364 x, y, w, h, 365 fg, bg); 366 } 367 368 test_compare(t, 369 out.draw, out.format, 370 ref.draw, ref.format, 371 0, 0, out.width, out.height, 372 ""); 373 374 free(clip); 375 376 if (target == CHILD) { 377 int x = rand() % (t->out.width-out.width); 378 int y = rand() % (t->out.height-out.height); 379 380 clear(&out); 381 clear(&ref); 382 383 XMoveWindow(out.dpy->dpy, out.draw, x, y); 384 XMoveWindow(ref.dpy->dpy, ref.draw, x, y); 385 386 clear(&out); 387 clear(&ref); 388 } 389 } 390 391 printf("passed [%d iterations x %d]\n", reps, sets); 392 393 test_target_destroy_render(&t->out, &out); 394 test_target_destroy_render(&t->ref, &ref); 395} 396 397int main(int argc, char **argv) 398{ 399 struct test test; 400 int i; 401 402 test_init(&test, argc, argv); 403 404 for (i = 0; i <= DEFAULT_ITERATIONS; i++) { 405 int reps = REPS(i), sets = SETS(i); 406 enum target t; 407 408 for (t = TARGET_FIRST; t <= TARGET_LAST; t++) { 409 small_tests(&test, reps, sets, t); 410 unclipped_tests(&test, reps, sets, t); 411 simple_clip_tests(&test, reps, sets, t); 412 complex_clip_tests(&test, reps, sets, t); 413 reset_cache(); 414 } 415 } 416 417 return 0; 418} 419