1#include <stdint.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5#include <X11/Xlib.h> 6#include <X11/Xutil.h> 7#include <X11/extensions/Xfixes.h> 8#include <X11/extensions/Xcomposite.h> 9#include <X11/Xlib-xcb.h> 10#include <xcb/xcb.h> 11#include <xcb/xcbext.h> 12#include <xcb/dri2.h> 13#include <unistd.h> 14#include <fcntl.h> 15#include <string.h> 16#include <time.h> 17 18#include <xf86drm.h> 19#include <drm.h> 20#include <setjmp.h> 21 22#include "dri2.h" 23 24#define COUNT 60 25 26#define N_DIVISORS 3 27static const int divisors[N_DIVISORS] = { 0, 1, 16 }; 28 29static jmp_buf error_handler[4]; 30static int have_error_handler; 31 32#define error_get() \ 33 setjmp(error_handler[have_error_handler++]) 34 35#define error_put() \ 36 have_error_handler-- 37 38static int (*saved_io_error)(Display *dpy); 39 40static int io_error(Display *dpy) 41{ 42 if (have_error_handler) 43 longjmp(error_handler[--have_error_handler], 0); 44 45 return saved_io_error(dpy); 46} 47 48static int x_error(Display *dpy, XErrorEvent *e) 49{ 50 return Success; 51} 52 53static uint32_t upper_32_bits(uint64_t val) 54{ 55 return val >> 32; 56} 57 58static uint32_t lower_32_bits(uint64_t val) 59{ 60 return val & 0xffffffff; 61} 62 63static int dri2_open(Display *dpy) 64{ 65 drm_auth_t auth; 66 char *driver, *device; 67 int fd; 68 69 if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device)) 70 return -1; 71 72 printf ("Connecting to %s driver on %s\n", driver, device); 73 74 fd = open(device, O_RDWR); 75 if (fd < 0) 76 return -1; 77 78 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 79 return -1; 80 81 if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic)) 82 return -1; 83 84 return fd; 85} 86 87static void swap_buffers(Display *dpy, Window win, int divisor, 88 unsigned int *attachments, int nattachments) 89{ 90 xcb_connection_t *c = XGetXCBConnection(dpy); 91 unsigned int seq[2]; 92 93 seq[0] = xcb_dri2_swap_buffers_unchecked(c, win, 94 0, 0, 0, divisor, 0, 0).sequence; 95 96 97 seq[1] = xcb_dri2_get_buffers_unchecked(c, win, 98 nattachments, nattachments, 99 attachments).sequence; 100 101 xcb_flush(c); 102 xcb_discard_reply(c, seq[0]); 103 xcb_discard_reply(c, seq[1]); 104} 105 106#define COMPOSITE 1 107 108static int has_composite(Display *dpy) 109{ 110 Display *dummy = NULL; 111 int event, error; 112 int major = -1, minor = -1; 113 114 if (dpy == NULL) 115 dummy = dpy = XOpenDisplay(NULL); 116 117 if (XCompositeQueryExtension(dpy, &event, &error)) 118 XCompositeQueryVersion(dpy, &major, &minor); 119 120 if (dummy) 121 XCloseDisplay(dummy); 122 123 return major > 0 || minor >= 4; 124} 125 126static void race_window(Display *dpy, int width, int height, 127 unsigned int *attachments, int nattachments, 128 unsigned flags, const char *name) 129{ 130 Window win; 131 XSetWindowAttributes attr; 132 int count, loop, n; 133 DRI2Buffer *buffers; 134 135 if (flags & COMPOSITE && !has_composite(dpy)) 136 return; 137 138 printf("%s(%s)\n", __func__, name); 139 140 /* Be nasty and install a fullscreen window on top so that we 141 * can guarantee we do not get clipped by children. 142 */ 143 attr.override_redirect = 1; 144 for (n = 0; n < N_DIVISORS; n++) { 145 loop = 256 >> ffs(divisors[n]); 146 printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop); 147 fflush(stdout); 148 do { 149 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 150 0, 0, width, height, 0, 151 DefaultDepth(dpy, DefaultScreen(dpy)), 152 InputOutput, 153 DefaultVisual(dpy, DefaultScreen(dpy)), 154 CWOverrideRedirect, &attr); 155 if (flags & COMPOSITE) 156 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 157 XMapWindow(dpy, win); 158 159 DRI2CreateDrawable(dpy, win); 160 161 buffers = DRI2GetBuffers(dpy, win, &width, &height, 162 attachments, nattachments, &count); 163 if (count != nattachments) 164 return; 165 166 free(buffers); 167 for (count = 0; count < loop; count++) 168 DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1)); 169 XDestroyWindow(dpy, win); 170 printf("."); fflush(stdout); 171 } while (--loop); 172 printf("*\n"); 173 } 174 175 for (n = 0; n < N_DIVISORS; n++) { 176 loop = 256 >> ffs(divisors[n]); 177 printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop); 178 fflush(stdout); 179 do { 180 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 181 0, 0, width, height, 0, 182 DefaultDepth(dpy, DefaultScreen(dpy)), 183 InputOutput, 184 DefaultVisual(dpy, DefaultScreen(dpy)), 185 CWOverrideRedirect, &attr); 186 if (flags & COMPOSITE) 187 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 188 XMapWindow(dpy, win); 189 190 DRI2CreateDrawable(dpy, win); 191 192 buffers = DRI2GetBuffers(dpy, win, &width, &height, 193 attachments, nattachments, &count); 194 if (count != nattachments) 195 return; 196 197 free(buffers); 198 for (count = 0; count < loop; count++) 199 swap_buffers(dpy, win, divisors[n], attachments, nattachments); 200 XDestroyWindow(dpy, win); 201 printf("."); fflush(stdout); 202 } while (--loop); 203 printf("*\n"); 204 } 205 206 for (n = 0; n < N_DIVISORS; n++) { 207 loop = 256 >> ffs(divisors[n]); 208 printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop); 209 fflush(stdout); 210 do { 211 uint64_t ignore, msc; 212 xcb_connection_t *c = XGetXCBConnection(dpy); 213 214 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 215 0, 0, width, height, 0, 216 DefaultDepth(dpy, DefaultScreen(dpy)), 217 InputOutput, 218 DefaultVisual(dpy, DefaultScreen(dpy)), 219 CWOverrideRedirect, &attr); 220 if (flags & COMPOSITE) 221 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 222 XMapWindow(dpy, win); 223 224 DRI2CreateDrawable(dpy, win); 225 DRI2GetMSC(dpy, win, &ignore, &msc, &ignore); 226 msc++; 227 for (count = 0; count < loop; count++) { 228 xcb_discard_reply(c, 229 xcb_dri2_wait_msc(c, win, 230 upper_32_bits(msc), 231 lower_32_bits(msc), 232 0, 0, 0, 0).sequence); 233 msc += divisors[n]; 234 } 235 XFlush(dpy); 236 XDestroyWindow(dpy, win); 237 printf("."); fflush(stdout); 238 } while (--loop); 239 printf("*\n"); 240 } 241 242 XSync(dpy, 1); 243 sleep(2); 244 XSync(dpy, 1); 245} 246 247static int rand_size(int max) 248{ 249 return 1 + (rand() % (max - 1)); 250} 251 252static void race_resize(Display *dpy, int width, int height, 253 unsigned int *attachments, int nattachments, 254 unsigned flags, const char *name) 255{ 256 Window win; 257 XSetWindowAttributes attr; 258 int count, loop, n; 259 DRI2Buffer *buffers; 260 261 if (flags & COMPOSITE && !has_composite(dpy)) 262 return; 263 264 printf("%s(%s)\n", __func__, name); 265 266 attr.override_redirect = 1; 267 for (n = 0; n < N_DIVISORS; n++) { 268 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 269 0, 0, width, height, 0, 270 DefaultDepth(dpy, DefaultScreen(dpy)), 271 InputOutput, 272 DefaultVisual(dpy, DefaultScreen(dpy)), 273 CWOverrideRedirect, &attr); 274 if (flags & COMPOSITE) 275 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 276 XMapWindow(dpy, win); 277 278 DRI2CreateDrawable(dpy, win); 279 280 loop = 256 >> ffs(divisors[n]); 281 printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop); 282 fflush(stdout); 283 do { 284 int w, h; 285 286 buffers = DRI2GetBuffers(dpy, win, &w, &h, 287 attachments, nattachments, &count); 288 if (count != nattachments) 289 return; 290 291 free(buffers); 292 for (count = 0; count < loop; count++) 293 DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1)); 294 XResizeWindow(dpy, win, rand_size(width), rand_size(height)); 295 printf("."); fflush(stdout); 296 } while (--loop); 297 XDestroyWindow(dpy, win); 298 XSync(dpy, True); 299 printf("*\n"); 300 } 301 302 for (n = 0; n < N_DIVISORS; n++) { 303 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 304 0, 0, width, height, 0, 305 DefaultDepth(dpy, DefaultScreen(dpy)), 306 InputOutput, 307 DefaultVisual(dpy, DefaultScreen(dpy)), 308 CWOverrideRedirect, &attr); 309 if (flags & COMPOSITE) 310 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 311 XMapWindow(dpy, win); 312 313 DRI2CreateDrawable(dpy, win); 314 315 loop = 256 >> ffs(divisors[n]); 316 printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop); 317 fflush(stdout); 318 do { 319 int w, h; 320 321 buffers = DRI2GetBuffers(dpy, win, &w, &h, 322 attachments, nattachments, &count); 323 if (count != nattachments) 324 return; 325 326 free(buffers); 327 for (count = 0; count < loop; count++) 328 swap_buffers(dpy, win, divisors[n], attachments, nattachments); 329 XResizeWindow(dpy, win, rand_size(width), rand_size(height)); 330 printf("."); fflush(stdout); 331 } while (--loop); 332 XDestroyWindow(dpy, win); 333 XSync(dpy, True); 334 printf("*\n"); 335 } 336 337 for (n = 0; n < N_DIVISORS; n++) { 338 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 339 0, 0, width, height, 0, 340 DefaultDepth(dpy, DefaultScreen(dpy)), 341 InputOutput, 342 DefaultVisual(dpy, DefaultScreen(dpy)), 343 CWOverrideRedirect, &attr); 344 if (flags & COMPOSITE) 345 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 346 XMapWindow(dpy, win); 347 348 DRI2CreateDrawable(dpy, win); 349 350 loop = 256 >> ffs(divisors[n]); 351 printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop); 352 fflush(stdout); 353 do { 354 uint64_t ignore, msc; 355 xcb_connection_t *c = XGetXCBConnection(dpy); 356 357 DRI2GetMSC(dpy, win, &ignore, &msc, &ignore); 358 msc++; 359 for (count = 0; count < loop; count++) { 360 xcb_discard_reply(c, 361 xcb_dri2_wait_msc(c, win, 362 upper_32_bits(msc), 363 lower_32_bits(msc), 364 0, 0, 0, 0).sequence); 365 msc += divisors[n]; 366 } 367 XFlush(dpy); 368 XResizeWindow(dpy, win, rand_size(width), rand_size(height)); 369 printf("."); fflush(stdout); 370 } while (--loop); 371 XDestroyWindow(dpy, win); 372 XSync(dpy, True); 373 printf("*\n"); 374 } 375 376 XSync(dpy, 1); 377 sleep(2); 378 XSync(dpy, 1); 379} 380 381static void race_manager(Display *dpy, int width, int height, 382 unsigned int *attachments, int nattachments, 383 unsigned flags, const char *name) 384{ 385 Display *mgr = XOpenDisplay(NULL); 386 Window win; 387 XSetWindowAttributes attr; 388 int count, loop, n; 389 DRI2Buffer *buffers; 390 391 if (flags & COMPOSITE && !has_composite(dpy)) 392 return; 393 394 printf("%s(%s)\n", __func__, name); 395 396 /* Be nasty and install a fullscreen window on top so that we 397 * can guarantee we do not get clipped by children. 398 */ 399 attr.override_redirect = 1; 400 for (n = 0; n < N_DIVISORS; n++) { 401 printf("DRI2SwapBuffers(divisor=%d)", divisors[n]); 402 fflush(stdout); 403 loop = 256 >> ffs(divisors[n]); 404 do { 405 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 406 0, 0, width, height, 0, 407 DefaultDepth(dpy, DefaultScreen(dpy)), 408 InputOutput, 409 DefaultVisual(dpy, DefaultScreen(dpy)), 410 CWOverrideRedirect, &attr); 411 if (flags & COMPOSITE) 412 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 413 XMapWindow(dpy, win); 414 415 DRI2CreateDrawable(dpy, win); 416 417 buffers = DRI2GetBuffers(dpy, win, &width, &height, 418 attachments, nattachments, &count); 419 if (count != nattachments) 420 return; 421 422 free(buffers); 423 for (count = 0; count < loop; count++) 424 DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1)); 425 XFlush(dpy); 426 XDestroyWindow(mgr, win); 427 XFlush(mgr); 428 printf("."); fflush(stdout); 429 } while (--loop); 430 printf("*\n"); 431 } 432 433 for (n = 0; n < N_DIVISORS; n++) { 434 printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]); 435 fflush(stdout); 436 loop = 256 >> ffs(divisors[n]); 437 do { 438 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 439 0, 0, width, height, 0, 440 DefaultDepth(dpy, DefaultScreen(dpy)), 441 InputOutput, 442 DefaultVisual(dpy, DefaultScreen(dpy)), 443 CWOverrideRedirect, &attr); 444 if (flags & COMPOSITE) 445 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 446 XMapWindow(dpy, win); 447 448 DRI2CreateDrawable(dpy, win); 449 450 buffers = DRI2GetBuffers(dpy, win, &width, &height, 451 attachments, nattachments, &count); 452 if (count != nattachments) 453 return; 454 455 free(buffers); 456 for (count = 0; count < loop; count++) 457 swap_buffers(dpy, win, divisors[n], attachments, nattachments); 458 XFlush(dpy); 459 XDestroyWindow(mgr, win); 460 XFlush(mgr); 461 printf("."); fflush(stdout); 462 } while (--loop); 463 printf("*\n"); 464 } 465 466 for (n = 0; n < N_DIVISORS; n++) { 467 printf("DRI2WaitMsc(divisor=%d)", divisors[n]); 468 fflush(stdout); 469 loop = 256 >> ffs(divisors[n]); 470 do { 471 uint64_t ignore, msc; 472 xcb_connection_t *c = XGetXCBConnection(dpy); 473 474 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 475 0, 0, width, height, 0, 476 DefaultDepth(dpy, DefaultScreen(dpy)), 477 InputOutput, 478 DefaultVisual(dpy, DefaultScreen(dpy)), 479 CWOverrideRedirect, &attr); 480 if (flags & COMPOSITE) 481 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 482 XMapWindow(dpy, win); 483 484 DRI2CreateDrawable(dpy, win); 485 DRI2GetMSC(dpy, win, &ignore, &msc, &ignore); 486 msc++; 487 for (count = 0; count < loop; count++) { 488 xcb_discard_reply(c, 489 xcb_dri2_wait_msc(c, win, 490 upper_32_bits(msc), 491 lower_32_bits(msc), 492 0, 0, 0, 0).sequence); 493 msc += divisors[n]; 494 } 495 XFlush(dpy); 496 XDestroyWindow(mgr, win); 497 XFlush(mgr); 498 printf("."); fflush(stdout); 499 } while (--loop); 500 printf("*\n"); 501 } 502 503 XSync(dpy, 1); 504 XSync(mgr, 1); 505 sleep(2); 506 XSync(dpy, 1); 507 XSync(mgr, 1); 508 509 XCloseDisplay(mgr); 510} 511 512static void race_close(int width, int height, 513 unsigned int *attachments, int nattachments, 514 unsigned flags, const char *name) 515{ 516 XSetWindowAttributes attr; 517 int count, loop, n; 518 519 if (flags & COMPOSITE && !has_composite(NULL)) 520 return; 521 522 printf("%s(%s)\n", __func__, name); 523 524 /* Be nasty and install a fullscreen window on top so that we 525 * can guarantee we do not get clipped by children. 526 */ 527 attr.override_redirect = 1; 528 for (n = 0; n < N_DIVISORS; n++) { 529 printf("DRI2SwapBuffers(divisor=%d)", divisors[n]); 530 fflush(stdout); 531 loop = 256 >> ffs(divisors[n]); 532 do { 533 Display *dpy = XOpenDisplay(NULL); 534 Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 535 0, 0, width, height, 0, 536 DefaultDepth(dpy, DefaultScreen(dpy)), 537 InputOutput, 538 DefaultVisual(dpy, DefaultScreen(dpy)), 539 CWOverrideRedirect, &attr); 540 if (flags & COMPOSITE) 541 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 542 XMapWindow(dpy, win); 543 544 DRI2CreateDrawable(dpy, win); 545 free(DRI2GetBuffers(dpy, win, &width, &height, 546 attachments, nattachments, &count)); 547 if (count != nattachments) 548 return; 549 550 for (count = 0; count < loop; count++) 551 DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1)); 552 XCloseDisplay(dpy); 553 printf("."); fflush(stdout); 554 } while (--loop); 555 printf("*\n"); 556 } 557 558 for (n = 0; n < N_DIVISORS; n++) { 559 printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]); 560 fflush(stdout); 561 loop = 256 >> ffs(divisors[n]); 562 do { 563 Display *dpy = XOpenDisplay(NULL); 564 Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 565 0, 0, width, height, 0, 566 DefaultDepth(dpy, DefaultScreen(dpy)), 567 InputOutput, 568 DefaultVisual(dpy, DefaultScreen(dpy)), 569 CWOverrideRedirect, &attr); 570 if (flags & COMPOSITE) 571 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 572 XMapWindow(dpy, win); 573 574 DRI2CreateDrawable(dpy, win); 575 free(DRI2GetBuffers(dpy, win, &width, &height, 576 attachments, nattachments, &count)); 577 if (count != nattachments) 578 return; 579 580 for (count = 0; count < loop; count++) 581 swap_buffers(dpy, win, divisors[n], attachments, nattachments); 582 XCloseDisplay(dpy); 583 printf("."); fflush(stdout); 584 } while (--loop); 585 printf("*\n"); 586 } 587 588 for (n = 0; n < N_DIVISORS; n++) { 589 printf("DRI2WaitMsc(divisor=%d)", divisors[n]); 590 fflush(stdout); 591 loop = 256 >> ffs(divisors[n]); 592 do { 593 uint64_t ignore, msc; 594 Display *dpy = XOpenDisplay(NULL); 595 xcb_connection_t *c = XGetXCBConnection(dpy); 596 Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 597 0, 0, width, height, 0, 598 DefaultDepth(dpy, DefaultScreen(dpy)), 599 InputOutput, 600 DefaultVisual(dpy, DefaultScreen(dpy)), 601 CWOverrideRedirect, &attr); 602 if (flags & COMPOSITE) 603 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 604 XMapWindow(dpy, win); 605 606 DRI2CreateDrawable(dpy, win); 607 DRI2GetMSC(dpy, win, &ignore, &msc, &ignore); 608 msc++; 609 for (count = 0; count < loop; count++) { 610 xcb_discard_reply(c, 611 xcb_dri2_wait_msc(c, win, 612 upper_32_bits(msc), 613 lower_32_bits(msc), 614 0, 0, 0, 0).sequence); 615 msc += divisors[n]; 616 } 617 XFlush(dpy); 618 XCloseDisplay(dpy); 619 printf("."); fflush(stdout); 620 } while (--loop); 621 printf("*\n"); 622 } 623} 624 625static void race_client(int width, int height, 626 unsigned int *attachments, int nattachments, 627 unsigned flags, const char *name) 628{ 629 Display *mgr = XOpenDisplay(NULL); 630 XSetWindowAttributes attr; 631 int count, loop, n; 632 633 if (flags & COMPOSITE && !has_composite(NULL)) 634 return; 635 636 printf("%s(%s)\n", __func__, name); 637 638 /* Be nasty and install a fullscreen window on top so that we 639 * can guarantee we do not get clipped by children. 640 */ 641 attr.override_redirect = 1; 642 for (n = 0; n < N_DIVISORS; n++) { 643 printf("DRI2SwapBuffers(divisor=%d)", divisors[n]); 644 fflush(stdout); 645 loop = 256 >> ffs(divisors[n]); 646 do { 647 Display *dpy = XOpenDisplay(NULL); 648 Window win; 649 650 if (error_get()) { 651 XCloseDisplay(dpy); 652 printf("+"); fflush(stdout); 653 continue; 654 } 655 656 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 657 0, 0, width, height, 0, 658 DefaultDepth(dpy, DefaultScreen(dpy)), 659 InputOutput, 660 DefaultVisual(dpy, DefaultScreen(dpy)), 661 CWOverrideRedirect, &attr); 662 if (flags & COMPOSITE) 663 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 664 XMapWindow(dpy, win); 665 666 DRI2CreateDrawable(dpy, win); 667 free(DRI2GetBuffers(dpy, win, &width, &height, 668 attachments, nattachments, &count)); 669 if (count == nattachments) { 670 for (count = 0; count < loop; count++) 671 DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1)); 672 } 673 674 XFlush(dpy); 675 XKillClient(mgr, win); 676 XFlush(mgr); 677 678 XCloseDisplay(dpy); 679 printf("."); fflush(stdout); 680 681 error_put(); 682 } while (--loop); 683 printf("*\n"); 684 } 685 686 for (n = 0; n < N_DIVISORS; n++) { 687 printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]); 688 fflush(stdout); 689 loop = 256 >> ffs(divisors[n]); 690 do { 691 Display *dpy = XOpenDisplay(NULL); 692 Window win; 693 694 if (error_get()) { 695 XCloseDisplay(dpy); 696 printf("+"); fflush(stdout); 697 continue; 698 } 699 700 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 701 0, 0, width, height, 0, 702 DefaultDepth(dpy, DefaultScreen(dpy)), 703 InputOutput, 704 DefaultVisual(dpy, DefaultScreen(dpy)), 705 CWOverrideRedirect, &attr); 706 if (flags & COMPOSITE) 707 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 708 XMapWindow(dpy, win); 709 710 DRI2CreateDrawable(dpy, win); 711 free(DRI2GetBuffers(dpy, win, &width, &height, 712 attachments, nattachments, &count)); 713 if (count == nattachments) { 714 for (count = 0; count < loop; count++) 715 swap_buffers(dpy, win, divisors[n], attachments, nattachments); 716 } 717 718 XFlush(dpy); 719 XKillClient(mgr, win); 720 XFlush(mgr); 721 722 XCloseDisplay(dpy); 723 printf("."); fflush(stdout); 724 725 error_put(); 726 } while (--loop); 727 printf("*\n"); 728 } 729 730 for (n = 0; n < N_DIVISORS; n++) { 731 printf("DRI2WaitMsc(divisor=%d)", divisors[n]); 732 fflush(stdout); 733 loop = 256 >> ffs(divisors[n]); 734 do { 735 Display *dpy = XOpenDisplay(NULL); 736 uint64_t ignore, msc; 737 xcb_connection_t *c; 738 Window win; 739 740 if (error_get()) { 741 XCloseDisplay(dpy); 742 printf("+"); fflush(stdout); 743 continue; 744 } 745 746 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 747 0, 0, width, height, 0, 748 DefaultDepth(dpy, DefaultScreen(dpy)), 749 InputOutput, 750 DefaultVisual(dpy, DefaultScreen(dpy)), 751 CWOverrideRedirect, &attr); 752 if (flags & COMPOSITE) 753 XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); 754 XMapWindow(dpy, win); 755 756 DRI2CreateDrawable(dpy, win); 757 DRI2GetMSC(dpy, win, &ignore, &msc, &ignore); 758 c = XGetXCBConnection(dpy); 759 msc++; 760 for (count = 0; count < loop; count++) { 761 xcb_discard_reply(c, 762 xcb_dri2_wait_msc(c, win, 763 upper_32_bits(msc), 764 lower_32_bits(msc), 765 0, 0, 0, 0).sequence); 766 msc += divisors[n]; 767 } 768 769 XFlush(dpy); 770 XKillClient(mgr, win); 771 XFlush(mgr); 772 773 XCloseDisplay(dpy); 774 printf("."); fflush(stdout); 775 776 error_put(); 777 } while (--loop); 778 printf("*\n"); 779 } 780 781 XCloseDisplay(mgr); 782} 783 784int main(void) 785{ 786 Display *dpy; 787 int width, height, fd; 788 unsigned int attachments[] = { 789 DRI2BufferBackLeft, 790 DRI2BufferFrontLeft, 791 }; 792 793 saved_io_error = XSetIOErrorHandler(io_error); 794 XSetErrorHandler(x_error); 795 796 dpy = XOpenDisplay(NULL); 797 if (dpy == NULL) 798 return 77; 799 800 fd = dri2_open(dpy); 801 if (fd < 0) 802 return 1; 803 804 width = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 805 height = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 806 race_window(dpy, width, height, attachments, 1, 0, "fullscreen"); 807 race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen"); 808 race_window(dpy, width, height, attachments, 2, 0, "fullscreen (with front)"); 809 race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)"); 810 811 race_resize(dpy, width, height, attachments, 1, 0, ""); 812 race_resize(dpy, width, height, attachments, 1, COMPOSITE, "composite"); 813 race_resize(dpy, width, height, attachments, 2, 0, "with front"); 814 race_resize(dpy, width, height, attachments, 2, COMPOSITE, "composite with front"); 815 816 race_manager(dpy, width, height, attachments, 1, 0, "fullscreen"); 817 race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen"); 818 race_manager(dpy, width, height, attachments, 2, 0, "fullscreen (with front)"); 819 race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)"); 820 821 race_close(width, height, attachments, 1, 0, "fullscreen"); 822 race_close(width, height, attachments, 1, COMPOSITE, "composite fullscreen"); 823 race_close(width, height, attachments, 2, 0, "fullscreen (with front)"); 824 race_close(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)"); 825 826 race_client(width, height, attachments, 1, 0, "fullscreen"); 827 race_client(width, height, attachments, 1, COMPOSITE, "composite fullscreen"); 828 race_client(width, height, attachments, 2, 0, "fullscreen (with front)"); 829 race_client(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)"); 830 831 width /= 2; 832 height /= 2; 833 race_window(dpy, width, height, attachments, 1, 0, "windowed"); 834 race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed"); 835 race_window(dpy, width, height, attachments, 2, 0, "windowed (with front)"); 836 race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)"); 837 838 race_manager(dpy, width, height, attachments, 1, 0, "windowed"); 839 race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed"); 840 race_manager(dpy, width, height, attachments, 2, 0, "windowed (with front)"); 841 race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)"); 842 843 race_close(width, height, attachments, 1, 0, "windowed"); 844 race_close(width, height, attachments, 1, COMPOSITE, "composite windowed"); 845 race_close(width, height, attachments, 2, 0, "windowed (with front)"); 846 race_close(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)"); 847 848 race_client(width, height, attachments, 1, 0, "windowed"); 849 race_client(width, height, attachments, 1, COMPOSITE, "composite windowed"); 850 race_client(width, height, attachments, 2, 0, "windowed (with front)"); 851 race_client(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)"); 852 853 return 0; 854} 855