1/**************************************************************************** 2Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, and distribute this software and its 7documentation for any purpose and without fee is hereby granted, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Digital not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. 13 14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20SOFTWARE. 21 22****************************************************************************/ 23 24#include <stdio.h> 25#include <ctype.h> 26#include <signal.h> 27#include <stdint.h> 28 29#ifndef VMS 30#include <X11/Xatom.h> 31#include <X11/Xos.h> 32#else 33#include <decw$include/Xatom.h> 34#endif 35#include "x11perf.h" 36#include <X11/Xmu/SysUtil.h> 37 38#include <time.h> 39#define Time_t time_t 40#include <stdlib.h> 41 42/* Only for working on ``fake'' servers, for hardware that doesn't exist */ 43static Bool drawToFakeServer = False; 44static Bool falsePrecision = False; 45static Pixmap tileToQuery = None; 46static char *displayName; 47int abortTest; 48 49typedef struct _RopNames { const char *name; int rop; } RopNameRec, *RopNamePtr; 50 51static RopNameRec ropNames[] = { 52 { "clear", GXclear }, /* 0 */ 53 { "and", GXand }, /* src AND dst */ 54 { "andReverse", GXandReverse }, /* src AND NOT dst */ 55 { "copy", GXcopy }, /* src */ 56 { "andInverted", GXandInverted }, /* NOT src AND dst */ 57 { "noop", GXnoop }, /* dst */ 58 { "xor", GXxor }, /* src XOR dst */ 59 { "or", GXor }, /* src OR dst */ 60 { "nor", GXnor }, /* NOT src AND NOT dst */ 61 { "equiv", GXequiv }, /* NOT src XOR dst */ 62 { "invert", GXinvert }, /* NOT dst */ 63 { "orReverse", GXorReverse }, /* src OR NOT dst */ 64 { "copyInverted", GXcopyInverted }, /* NOT src */ 65 { "orInverted", GXorInverted }, /* NOT src OR dst */ 66 { "nand", GXnand }, /* NOT src OR NOT dst */ 67 { "set", GXset } /* 1 */ 68}; 69 70static RopNameRec popNames[] = { 71 { "Clear", PictOpClear }, 72 { "Src", PictOpSrc }, 73 { "Dst", PictOpDst }, 74 { "Over", PictOpOver }, 75 { "OverReverse", PictOpOverReverse }, 76 { "In", PictOpIn }, 77 { "InReverse", PictOpInReverse }, 78 { "Out", PictOpOut }, 79 { "OutReverse", PictOpOutReverse }, 80 { "Atop", PictOpAtop }, 81 { "AtopReverse", PictOpAtopReverse }, 82 { "Xor", PictOpXor }, 83 { "Add", PictOpAdd }, 84 { "Saturate", PictOpSaturate }, 85}; 86 87static RopNameRec formatNames[] = { 88 { "RGB24", PictStandardRGB24 }, 89 { "ARGB32", PictStandardARGB32 }, 90 { "A8", PictStandardA8 }, 91 { "A4", PictStandardA4 }, 92 { "A1", PictStandardA1 }, 93 { "NATIVE", PictStandardNative }, 94}; 95 96static const char *(visualClassNames)[] = { 97 "StaticGray", 98 "GrayScale", 99 "StaticColor", 100 "PseudoColor", 101 "TrueColor", 102 "DirectColor" 103}; 104 105static Bool labels = False; 106static int repeat = 5; 107static int seconds = 5; 108static int delay = 0; 109 110static Window status; /* Status window and GC */ 111static GC tgc; 112static int HSx, HSy; 113 114static double syncTime = 0.0; 115 116static int saveargc; 117static char **saveargv; 118 119#define NUM_ROPS 16 120static int numRops = 1; 121static int rops[NUM_ROPS] = { GXcopy }; 122#define NUM_POPS 14 123static int numPops = 1; 124static int pops[NUM_POPS] = { PictOpOver }; 125#define NUM_FORMATS 6 126static int numFormats = 1; 127static int formats[NUM_FORMATS] = { PictStandardNative }; 128static int numPlanemasks = 1; 129static unsigned long planemasks[256] = { (unsigned long)~0 }; 130 131static const char *foreground = NULL; 132static const char *background = NULL; 133static const char *ddbackground = NULL; 134static int clips = 0; 135 136static int numSubWindows = 7; 137static unsigned long subWindows[] = {4, 16, 25, 50, 75, 100, 200, 0}; 138 139static int fixedReps = 0; 140 141static Bool *doit; 142 143static XRectangle ws[] = { /* Clip rectangles */ 144 {195, 195, 120, 120}, 145 { 45, 145, 120, 120}, 146 {345, 245, 120, 120}, 147 { 45, 275, 120, 120}, 148 {345, 115, 120, 120}, 149 {195, 325, 120, 120} 150 151}; 152#define MAXCLIP (sizeof(ws) / sizeof(ws[0])) 153static Window clipWindows[MAXCLIP]; 154static Colormap cmap; 155static int depth = -1; /* -1 means use default depth */ 156static int vclass = -1; /* -1 means use CopyFromParent */ 157 158/* ScreenSaver state */ 159static XParmRec xparms; 160static int ssTimeout, ssInterval, ssPreferBlanking, ssAllowExposures; 161 162/* Static functions */ 163static int GetWords(int argi, int argc, char **argv, char **wordsp, int *nump); 164static int GetNumbers(int argi, int argc, char **argv, unsigned long *intsp, 165 int *nump); 166static int GetRops(int argi, int argc, char **argv, int *ropsp, int *nump); 167static int GetPops(int argi, int argc, char **argv, int *popsp, int *nump); 168static int GetFormats(int argi, int argc, char **argv, int *formatsp, int *nump); 169static int FormatFromName (char *name); 170static const char *NameFromFormat (int format); 171 172 173/************************************************ 174* time related stuff * 175************************************************/ 176 177#ifdef VMS 178 179typedef struct _vms_time { 180 unsigned long low; 181 unsigned long high; 182}vms_time; 183 184struct timeval { 185 long tv_sec; /* seconds since Jan. 1, 1970 */ 186 long tv_usec; /* and microseconds */ 187}; 188 189struct timezone { 190 int tz_minuteswest; /* of Greenwich */ 191 int tz_dsttime; /* type of dst correction to apply */ 192}; 193 194 195static int firsttime = True; 196static vms_time basetime; 197 198int gettimeofday(tp) 199 struct timeval *tp; 200{ 201 vms_time current_time, resultant; 202 unsigned long mumble, foo; 203 int status; 204 205 if (firsttime) { 206 sys$gettim(&basetime); 207 firsttime = False; 208 } 209 sys$gettim(¤t_time); 210 resultant.high = current_time.high - basetime.high; 211 resultant.low = current_time.low - basetime.low; 212 if (current_time.low < basetime.low) { 213 resultant.high -= 1; 214 } 215 status = lib$ediv( &(10000000), &resultant, &tp->tv_sec, &tp->tv_usec); 216 tp->tv_usec /= 10; 217 return 0; 218} 219 220#endif 221 222static struct timeval start; 223 224static void 225PrintTime(void) 226{ 227 Time_t t; 228 229 t = time((Time_t *)NULL); 230 printf("%s\n", ctime(&t)); 231} 232 233static void 234InitTimes(void) 235{ 236 X_GETTIMEOFDAY(&start); 237} 238 239static double 240ElapsedTime(double correction) 241{ 242 struct timeval stop; 243 244 X_GETTIMEOFDAY(&stop); 245 if (stop.tv_usec < start.tv_usec) { 246 stop.tv_usec += 1000000; 247 stop.tv_sec -= 1; 248 } 249 return (double)(stop.tv_usec - start.tv_usec) + 250 (1000000.0 * (double)(stop.tv_sec - start.tv_sec)) - correction; 251} 252 253static double 254RoundTo3Digits(double d) 255{ 256 /* It's kind of silly to print out things like ``193658.4/sec'' so just 257 junk all but 3 most significant digits. */ 258 double exponent, sign; 259 260 if (falsePrecision) 261 return d; 262 263 exponent = 1.0; 264 /* the code below won't work if d should happen to be non-positive. */ 265 if (d < 0.0) { 266 d = -d; 267 sign = -1.0; 268 } else 269 sign = 1.0; 270 if (d >= 1000.0) { 271 do { 272 exponent *= 10.0; 273 } while (d/exponent >= 1000.0); 274 d = (double)((int) (d/exponent + 0.5)); 275 d *= exponent; 276 } else { 277 if (d != 0.0) { 278 while (d*exponent < 100.0) { 279 exponent *= 10.0; 280 } 281 } 282 d = (double)((int) (d*exponent + 0.5)); 283 d /= exponent; 284 } 285 return d * sign; 286} 287 288 289static void 290ReportTimes(double usecs, int64_t n, char *str, int average) 291{ 292 if(usecs != 0.0) 293 { 294 double msecsperobj = usecs / (1000.0 * (double)n); 295 double objspersec = (double) n * 1000000.0 / usecs; 296 297 /* Round obj/sec to 3 significant digits. Leave msec untouched, to 298 allow averaging results from several repetitions. */ 299 objspersec = RoundTo3Digits(objspersec); 300 301 if (average) { 302 printf("%11lld trep @ %8.4f msec (%8.1f/sec): %s\n", 303 (long long) n, msecsperobj, objspersec, str); 304 } else { 305 printf("%11lld reps @ %8.4f msec (%8.1f/sec): %s\n", 306 (long long) n, msecsperobj, objspersec, str); 307 } 308 } else { 309 printf("%6lld %sreps @ 0.0 msec (unmeasurably fast): %s\n", 310 (long long) n, average ? "t" : "", str); 311 } 312 313} 314 315 316 317/************************************************ 318* Generic X stuff * 319************************************************/ 320 321static char *program_name; 322typedef enum { 323 USAGE_OPTIONS, 324 USAGE_TESTS, 325 USAGE_ALL 326} usage_contents; 327_X_NORETURN _X_COLD static void usage(usage_contents, int); 328 329_X_NORETURN _X_COLD static void 330missing_arg(const char *option) 331{ 332 fprintf(stderr, "Error: missing argument to %s\n", option); 333 usage(USAGE_OPTIONS, EXIT_FAILURE); 334} 335 336_X_NORETURN _X_COLD static void 337invalid_arg( const char *arg, const char *option) 338{ 339 fprintf(stderr, "Error: invalid argument '%s' to %s\n", arg, option); 340 usage(USAGE_OPTIONS, EXIT_FAILURE); 341} 342 343/* 344 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obsolete) 345 * If found, remove it from command line. Don't go past a lone -. 346 */ 347static char * 348Get_Display_Name(int *pargc, /* MODIFIED */ 349 char **argv) /* MODIFIED */ 350{ 351 int argc = *pargc; 352 char **pargv = argv+1; 353 char *displayname = NULL; 354 355 for (int i = 1; i != argc; i++) { 356 char *arg = argv[i]; 357 358 if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) { 359 if (++i >= argc) 360 missing_arg(arg); 361 362 displayname = argv[i]; 363 *pargc -= 2; 364 continue; 365 } 366 if (!strcmp(arg,"-")) { 367 while (i<argc) *pargv++ = argv[i++]; 368 break; 369 } 370 *pargv++ = arg; 371 } 372 373 *pargv = NULL; 374 return (displayname); 375} 376 377 378/* 379 * GetVersion (argc, argv) Look for -v followed by a version number. 380 * If found remove it from command line. Don't go past a lone -. 381 * Leave -v followed by non-numbers as it could be -vclass or -version. 382 */ 383 384static Version 385GetVersion(int *pargc, /* MODIFIED */ 386 char **argv) /* MODIFIED */ 387{ 388 int argc = *pargc; 389 char **pargv = argv+1; 390 Version version = VERSION1_7; 391 Bool found = False; 392 393 for (int i = 1; i != argc; i++) { 394 char *arg = argv[i]; 395 396 if (arg[0] == '-' && arg[1] == 'v') { 397 if (arg[2] == '1' && arg[3] == '.' && arg[5] == '\0') { 398 switch (arg[4]) { 399 case '2': 400 version = VERSION1_2; 401 break; 402 case '3': 403 version = VERSION1_3; 404 break; 405 case '4': 406 version = VERSION1_4; 407 break; 408 case '5': 409 version = VERSION1_5; 410 break; 411 case '6': 412 version = VERSION1_6; 413 break; 414 case '7': 415 version = VERSION1_7; 416 break; 417 default: 418 goto unknown_version; 419 } 420 421 if (found) { 422 fprintf(stderr, "Warning: multiple version specifications\n"); 423 } 424 found = True; 425 426 /* reduce arg count and skip copying this arg to pargv */ 427 *pargc -= 1; 428 continue; 429 } else if (isdigit(arg[2])) { 430 unknown_version: 431 fprintf(stderr, "Error: unknown version specification: %s\n", 432 arg); 433 exit(1); 434 } 435 } 436 else if (!strcmp(arg,"-")) { 437 while (i<argc) *pargv++ = argv[i++]; 438 break; 439 } 440 *pargv++ = arg; 441 } 442 443 *pargv = NULL; 444 return (version); 445} 446 447 448 449/* 450 * Open_Display: Routine to open a display with correct error handling. 451 */ 452static Display * 453Open_Display(char *display_name) 454{ 455 Display *d; 456 457 d = XOpenDisplay(display_name); 458 if (d == NULL) { 459 fprintf (stderr, "%s: unable to open display '%s'\n", 460 program_name, XDisplayName (display_name)); 461 exit(1); 462 } 463 464 return(d); 465} 466 467static void 468Cleanup(int sig) 469{ 470 abortTest = sig; 471} 472 473void 474AbortTest(void) 475{ 476 fflush(stdout); 477 478 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 479 ssAllowExposures); 480 XFlush(xparms.d); 481 exit (abortTest); 482} 483 484/************************************************ 485* Performance stuff * 486************************************************/ 487 488 489static void 490usage(usage_contents show, int exit_status) 491{ 492 int i = 0; 493 static const char *help_message = 494"where options include:\n" 495" -display <host:display> the X server to contact\n" 496" -sync do the tests in synchronous mode\n" 497" -pack pack rectangles right next to each other\n" 498" -repeat <n> do tests <n> times (default = 5)\n" 499" -time <s> do tests for <s> seconds each (default = 5)\n" 500" -pause <s> pause for <s> seconds between each run\n" 501/* 502" -draw draw after each test -- pmax only\n" 503*/ 504" -all do all tests\n" 505" -range <test1>[,<test2>] like all, but do <test1> to <test2>\n" 506" -labels generate test labels for use by fillblnk\n" 507" -fg <color-or-pixel> the foreground color to use\n" 508" -bg <color-or-pixel> the background color to use\n" 509" -clips <default> default number of clip windows per test\n" 510" -ddbg <color-or-pixel> the background color to use for DoubleDash\n" 511" -rop <rop0 rop1 ...> use the given rops to draw (default = GXcopy)\n" 512" -pm <pm0 pm1 ...> use the given planemasks to draw (default = ~0)\n" 513" -depth <depth> use a visual with <depth> planes per pixel\n" 514" -vclass <class> the visual class to use (default = root)\n" 515" -reps <n> fix the rep count (default = auto scale)\n" 516" -subs <s0 s1 ...> a list of the number of sub-windows to use\n" 517" -v1.2 perform only v1.2 tests using old semantics\n" 518" -v1.3 perform only v1.3 tests using old semantics\n" 519" -v1.4 perform only v1.4 tests using old semantics\n" 520" -v1.5 perform only v1.5 tests using old semantics\n" 521" -v1.6 perform only v1.6 tests using old semantics\n" 522" -v1.7 perform only v1.7 tests using old semantics\n" 523" -version print version and exit\n" 524" -su request save unders on windows\n" 525" -bs <backing_store_hint> WhenMapped or Always (default = NotUseful)\n" 526" -help [options|tests|all] list general options, test options, or both\n" 527; 528 529 fflush(stdout); 530 if (show == USAGE_OPTIONS || show == USAGE_ALL) { 531 fprintf(stderr, "usage: %s [-options ...]\n%s", 532 program_name, help_message); 533 } 534 if (show == USAGE_TESTS || show == USAGE_ALL) { 535 while (test[i].option != NULL) { 536 if (test[i].versions & xparms.version ) { 537 fprintf(stderr, " %-24s %s\n", 538 test[i].option, 539 test[i].label14 ? test[i].label14 : test[i].label); 540 } 541 i++; 542 } 543 } 544 fprintf(stderr, "\n"); 545 546 exit (exit_status); 547} 548 549void 550NullProc(XParms xp, Parms p) 551{ 552} 553 554int 555NullInitProc(XParms xp, Parms p, int64_t reps) 556{ 557 return reps; 558} 559 560static void 561HardwareSync(XParms xp) 562{ 563 /* 564 * Some graphics hardware allows the server to claim it is done, 565 * while in reality the hardware is busily working away. So fetch 566 * a pixel from the drawable that was drawn to, which should be 567 * enough to make the server wait for the graphics hardware. 568 */ 569 XImage *image; 570 571 image = XGetImage(xp->d, xp->p ? xp->p : xp->w, HSx, HSy, 572 1, 1, ~0, ZPixmap); 573 if (image) XDestroyImage(image); 574} 575 576static void 577DoHardwareSync(XParms xp, Parms p, int64_t reps) 578{ 579 for (int i = 0; i != reps; i++) { 580 HardwareSync(xp); 581 CheckAbort (); 582 } 583} 584 585static Test syncTest = { 586 "syncTime", "Internal test for finding how long HardwareSync takes", NULL, 587 NullInitProc, DoHardwareSync, NullProc, NullProc, 588 V1_2FEATURE, NONROP, 0, 589 {1} 590}; 591 592 593static Window 594CreatePerfWindow(XParms xp, int x, int y, int width, int height) 595{ 596 XSetWindowAttributes xswa; 597 Window w; 598/* 599 Screen *s; 600 int su; 601 602 s = DefaultScreenOfDisplay(xp->d); 603 su = XDoesBackingStore(s); 604 printf("Backing store of screen returns %d\n", su); 605 su = XDoesSaveUnders(s); 606 printf("Save unders of screen returns %d\n", su); 607 su = XPlanesOfScreen(s); 608 printf("Planes of screen returns %d\n", su); 609*/ 610 xswa.background_pixel = xp->background; 611 xswa.border_pixel = xp->foreground; 612 xswa.colormap = cmap; 613 xswa.override_redirect = True; 614 xswa.backing_store = xp->backing_store; 615 xswa.save_under = xp->save_under; 616 w = XCreateWindow(xp->d, DefaultRootWindow(xp->d), x, y, width, height, 1, 617 xp->vinfo.depth, CopyFromParent, xp->vinfo.visual, 618 CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect 619 | CWBackingStore | CWSaveUnder, &xswa); 620 XMapWindow (xp->d, w); 621 return w; 622} 623 624 625static void 626CreateClipWindows(XParms xp, int clips) 627{ 628 XWindowAttributes xwa; 629 630 (void) XGetWindowAttributes(xp->d, xp->w, &xwa); 631 if (clips > MAXCLIP) clips = MAXCLIP; 632 for (int j = 0; j != clips; j++) { 633 clipWindows[j] = CreatePerfWindow(xp, 634 xwa.x + ws[j].x, xwa.y + ws[j].y, ws[j].width, ws[j].height); 635 } 636} /* CreateClipWindows */ 637 638 639static void 640DestroyClipWindows(XParms xp, int clips) 641{ 642 if (clips > MAXCLIP) clips = MAXCLIP; 643 for (int j = 0; j != clips; j++) { 644 XDestroyWindow(xp->d, clipWindows[j]); 645 } 646} /* DestroyClipWindows */ 647 648 649static double 650DoTest(XParms xp, Test *test, int64_t reps) 651{ 652 double time; 653 unsigned int ret_width, ret_height; 654 655 /* Tell screen-saver to restart counting again. See comments below for the 656 XSetScreenSaver call. */ 657 XForceScreenSaver(xp->d, ScreenSaverReset); 658 HardwareSync (xp); 659 InitTimes (); 660 (*test->proc) (xp, &test->parms, reps); 661 HardwareSync(xp); 662 663 time = ElapsedTime(syncTime); 664 if (time < 0.0) time = 0.0; 665 CheckAbort (); 666 if (drawToFakeServer) 667 XQueryBestSize(xp->d, TileShape, tileToQuery, 668 32, 32, &ret_width, &ret_height); 669 (*test->passCleanup) (xp, &test->parms); 670 return time; 671} 672 673 674static int64_t 675CalibrateTest(XParms xp, Test *test, int seconds, double *usecperobj) 676{ 677#define goal 2500000.0 /* Try to get up to 2.5 seconds */ 678#define enough 2000000.0 /* But settle for 2.0 seconds */ 679#define tick 10000.0 /* Assume clock not faster than .01 seconds */ 680 681 double usecs; 682 int64_t reps, didreps; /* Reps desired, reps performed */ 683 int exponent; 684 685 /* Attempt to get an idea how long each rep lasts by getting enough 686 reps to last more tan enough. Then scale that up to the number of 687 seconds desired. 688 689 If init call to test ever fails, return False and test will be skipped. 690 */ 691 692 if (fixedReps != 0) { 693 return fixedReps; 694 } 695 reps = 1; 696 for (;;) { 697 XDestroySubwindows(xp->d, xp->w); 698 XClearWindow(xp->d, xp->w); 699 didreps = (*test->init) (xp, &test->parms, reps); 700 CheckAbort (); 701 if (didreps == 0) { 702 return 0; 703 } 704 if ( test->clips < clips ) 705 test->clips = clips ; 706 /* Create clip windows if requested */ 707 CreateClipWindows(xp, test->clips); 708 HardwareSync(xp); 709 InitTimes(); 710 (*test->proc) (xp, &test->parms, reps); 711 HardwareSync(xp); 712 usecs = ElapsedTime(syncTime); 713 (*test->passCleanup) (xp, &test->parms); 714 (*test->cleanup) (xp, &test->parms); 715 DestroyClipWindows(xp, test->clips); 716 CheckAbort (); 717 718 if (didreps != reps) { 719 /* The test can't do the number of reps as we asked for. 720 Give up */ 721 *usecperobj = 722 usecs / (double)(didreps * test->parms.objects); 723 return didreps; 724 } 725 /* Did we go long enough? */ 726 if (usecs >= enough) break; 727 728 /* Don't let too short a clock make new reps wildly high */ 729 if (usecs <= tick)reps = reps*10; 730 else{ 731 /* Try to get up to goal seconds. */ 732 reps = (int) (goal * (double)reps / usecs) + 1; 733 } 734 } 735 736 *usecperobj = usecs / (double) (reps * test->parms.objects); 737 reps = (int) ((double)seconds * 1000000.0 * (double)reps / usecs) + 1; 738 739 /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking 740 numbers of repetitions. */ 741 reps--; 742 exponent = 1; 743 while (reps > 9) { 744 reps /= 10; 745 exponent *= 10; 746 } 747 reps = (reps + 1) * exponent; 748 return reps; 749} /* CalibrateTest */ 750 751static void 752CreatePerfGCs(XParms xp, int func, unsigned long pm) 753{ 754 XGCValues gcvfg, gcvbg, gcvddbg,gcvddfg; 755 unsigned long fg, bg, ddbg; 756 757 fg = xp->foreground; 758 bg = xp->background; 759 ddbg = xp->ddbackground; 760 gcvfg.graphics_exposures = False; 761 gcvbg.graphics_exposures = False; 762 gcvddfg.graphics_exposures = False; 763 gcvddbg.graphics_exposures = False; 764 gcvfg.plane_mask = pm; 765 gcvbg.plane_mask = pm; 766 gcvddfg.plane_mask = pm; 767 gcvddbg.plane_mask = pm; 768 gcvfg.function = func; 769 gcvbg.function = func; 770 gcvddfg.function = func; 771 gcvddbg.function = func; 772 773 gcvfg.foreground = fg; 774 gcvfg.background = bg; 775 gcvbg.foreground = bg; 776 gcvbg.background = fg; 777 gcvddfg.foreground = fg; 778 gcvddfg.background = ddbg; 779 gcvddbg.foreground = ddbg; 780 gcvddbg.background = fg; 781 xp->fggc = XCreateGC(xp->d, xp->w, 782 GCForeground | GCBackground | GCGraphicsExposures 783 | GCFunction | GCPlaneMask, &gcvfg); 784 xp->bggc = XCreateGC(xp->d, xp->w, 785 GCForeground | GCBackground | GCGraphicsExposures 786 | GCFunction | GCPlaneMask, &gcvbg); 787 xp->ddfggc = XCreateGC(xp->d, xp->w, 788 GCForeground | GCBackground | GCGraphicsExposures 789 | GCFunction | GCPlaneMask, &gcvddfg); 790 xp->ddbggc = XCreateGC(xp->d, xp->w, 791 GCForeground | GCBackground | GCGraphicsExposures 792 | GCFunction | GCPlaneMask, &gcvddbg); 793} 794 795 796static void 797DestroyPerfGCs(XParms xp) 798{ 799 XFreeGC(xp->d, xp->fggc); 800 XFreeGC(xp->d, xp->bggc); 801 XFreeGC(xp->d, xp->ddfggc); 802 XFreeGC(xp->d, xp->ddbggc); 803} 804 805static unsigned long 806AllocateColor(Display *display, const char *name, unsigned long pixel) 807{ 808 XColor color; 809 810 if (name != NULL) { 811 /* Try to parse color name */ 812 if (XParseColor(display, cmap, name, &color)) { 813 if (XAllocColor(display, cmap, &color)) { 814 pixel = color.pixel; 815 } else { 816 (void) fprintf(stderr, 817 "Can't allocate colormap entry for color %s\n", name); 818 } 819 } else { 820 if(*name >= '0' && *name <= '9') 821 pixel = atoi(name); 822 else 823 (void) fprintf(stderr, "Can't parse color name %s\n", name); 824 } 825 } 826 return pixel; 827} /* AllocateColor */ 828 829 830static void 831DisplayStatus(Display *d, const char *message, const char *test, int try) 832{ 833 char s[500]; 834 835 XClearWindow(d, status); 836 sprintf(s, "%d %s %s", try, message, test); 837 /* We should really look at the height, descent of the font, etc. but 838 who cares. This works. */ 839 XDrawString(d, status, tgc, 10, 13, s, strlen(s)); 840} 841 842 843static void 844ProcessTest(XParms xp, Test *test, int func, unsigned long pm, char *label) 845{ 846 double time, totalTime; 847 long long reps; 848 849 xp->planemask = pm; 850 xp->func = func; 851 if (test->testType == COMP) 852 { 853 func = GXcopy; 854 pm = ~0L; 855 } 856 CreatePerfGCs(xp, func, pm); 857 DisplayStatus(xp->d, "Calibrating", label, 0); 858 reps = CalibrateTest(xp, test, seconds, &time); 859 if (reps != 0) { 860 XDestroySubwindows(xp->d, xp->w); 861 XClearWindow(xp->d, xp->w); 862 reps = (*test->init) (xp, &test->parms, reps); 863 if (abortTest) 864 AbortTest (); 865 /* 866 * if using fixedReps then will not have done CalibrateTest so must 867 * check result of init for 0 here 868 */ 869 if(reps == 0){ 870 DestroyPerfGCs(xp); 871 return; 872 } 873 /* Create clip windows if requested */ 874 CreateClipWindows(xp, test->clips); 875 876 totalTime = 0.0; 877 for (int j = 0; j != repeat; j++) { 878 DisplayStatus(xp->d, "Testing", label, j+1); 879 time = DoTest(xp, test, reps); 880 if (abortTest) 881 AbortTest (); 882 totalTime += time; 883 ReportTimes (time, reps * test->parms.objects, 884 label, False); 885 if (delay) 886 sleep(delay); 887 } 888 if (repeat > 1) { 889 ReportTimes(totalTime, 890 repeat * reps * test->parms.objects, 891 label, True); 892 } 893 (*test->cleanup) (xp, &test->parms); 894 DestroyClipWindows(xp, test->clips); 895 } else { 896 /* Test failed to initialize properly */ 897 } 898 printf ("\n"); 899 fflush(stdout); 900 DestroyPerfGCs(xp); 901} /* ProcessTest */ 902 903#define Strstr strstr 904 905#define LABELP(i) (test[i].label14 && (xparms.version >= VERSION1_4) \ 906 ? test[i].label14 : test[i].label) 907 908int 909main(int argc, char *argv[]) 910{ 911 int i, j, n, skip; 912 int numTests; /* Even though the linker knows, we don't. */ 913 char hostname[100]; 914 Bool foundOne = False; 915 Bool synchronous = False; 916 XGCValues tgcv; 917 int screen; 918 int rop, pm; 919 int pop, format; 920 int window_y, window_x; 921 XVisualInfo *vinfolist, vinfotempl; 922 unsigned long vmask; 923 924 /* Save away argv, argc, for usage to print out */ 925 saveargc = argc; 926 saveargv = malloc(argc * sizeof(char *)); 927 for (i = 0; i != argc; i++) { 928 saveargv[i] = argv[i]; 929 } 930 931 xparms.pack = False; 932 xparms.save_under = False; 933 xparms.backing_store = NotUseful; 934 935 /* Count number of tests */ 936 ForEachTest(numTests); 937 doit = calloc(numTests, sizeof(Bool)); 938 939 /* Parse arguments */ 940 program_name = argv[0]; 941 displayName = Get_Display_Name (&argc, argv); 942 xparms.version = GetVersion(&argc, argv); 943 for (i = 1; i != argc; i++) { 944 if (strcmp (argv[i], "-all") == 0) { 945 ForEachTest (j) 946 doit[j] = test[j].versions & xparms.version; 947 foundOne = True; 948 } else if (strcmp (argv[i], "-labels") == 0) { 949 labels = True; 950 } else if (strcmp(argv[i], "-range") == 0) { 951 char *cp1; 952 char *cp2; 953 954 if (argc <= ++i) 955 missing_arg(argv[i-1]); 956 cp1 = argv[i]; 957 if (*cp1 == '-') 958 cp1++; 959 for (cp2 = cp1; *cp2 != '\0' && *cp2 != ','; cp2++) {}; 960 if (*cp2 == ',') { 961 *cp2++ = '\0'; 962 if (*cp2 == '-') 963 cp2++; 964 } else { 965 cp2 = "-"; 966 } 967 ForEachTest (j) { 968 if (strcmp (cp1, (test[j].option) + 1) == 0 && 969 (test[j].versions & xparms.version)) { 970 int k = j; 971 do { 972 doit[k] = test[j].versions & xparms.version; 973 } while (!(strcmp(cp2, (test[k].option + 1)) == 0 && 974 (test[k].versions & xparms.version)) && 975 test[++k].option != NULL); 976 if (*cp2 != '-' && test[k].option == NULL) { 977 fprintf(stderr, "Error: unknown test %s listed for %s\n", 978 cp2, argv[i-1]); 979 usage(USAGE_OPTIONS, EXIT_FAILURE); 980 } 981 break; 982 } 983 } 984 if (test[j].option == NULL) { 985 fprintf(stderr, "Error: unknown test %s listed for %s\n", 986 argv[i], argv[i-1]); 987 usage(USAGE_OPTIONS, EXIT_FAILURE); 988 } 989 foundOne = True; 990 } else if (strcmp (argv[i], "-sync") == 0) { 991 synchronous = True; 992 } else if (strcmp (argv[i], "-pack") == 0) { 993 xparms.pack = True; 994 } else if (strcmp (argv[i], "-draw") == 0) { 995 drawToFakeServer = True; 996 } else if (strcmp (argv[i], "-falseprecision") == 0) { 997 falsePrecision = True; 998 } else if (strcmp (argv[i], "-repeat") == 0) { 999 i++; 1000 if (argc <= i) 1001 missing_arg(argv[i-1]); 1002 repeat = atoi (argv[i]); 1003 if (repeat <= 0) 1004 invalid_arg(argv[i], argv[i-1]); 1005 } else if (strcmp (argv[i], "-time") == 0) { 1006 i++; 1007 if (argc <= i) 1008 missing_arg(argv[i-1]); 1009 seconds = atoi (argv[i]); 1010 if (seconds <= 0) 1011 invalid_arg(argv[i], argv[i-1]); 1012 } else if (strcmp (argv[i], "-pause") == 0) { 1013 ++i; 1014 if (argc <= i) 1015 missing_arg(argv[i-1]); 1016 delay = atoi (argv[i]); 1017 if (delay < 0) 1018 invalid_arg(argv[i], argv[i-1]); 1019 } else if (strcmp(argv[i], "-fg") == 0) { 1020 i++; 1021 if (argc <= i) 1022 missing_arg(argv[i-1]); 1023 foreground = argv[i]; 1024 } else if (strcmp(argv[i], "-bg") == 0) { 1025 i++; 1026 if (argc <= i) 1027 missing_arg(argv[i-1]); 1028 background = argv[i]; 1029 if(ddbackground == NULL) 1030 ddbackground = argv[i]; 1031 } else if (strcmp(argv[i], "-clips") == 0 ) { 1032 i++; 1033 if (argc <= i) 1034 missing_arg(argv[i-1]); 1035 clips = atoi( argv[i] ); 1036 } else if (strcmp(argv[i], "-ddbg") == 0) { 1037 if (argc <= i) 1038 missing_arg(argv[i-1]); 1039 i++; 1040 ddbackground = argv[i]; 1041 } else if (strcmp(argv[i], "-rop") == 0) { 1042 skip = GetRops (i+1, argc, argv, rops, &numRops); 1043 i += skip; 1044 } else if (strcmp(argv[i], "-pop") == 0) { 1045 skip = GetPops (i+1, argc, argv, pops, &numPops); 1046 i += skip; 1047 } else if (strcmp(argv[i], "-format") == 0) { 1048 skip = GetFormats (i+1, argc, argv, formats, &numFormats); 1049 i += skip; 1050 } else if (strcmp(argv[i], "-pm") == 0) { 1051 skip = GetNumbers (i+1, argc, argv, planemasks, &numPlanemasks); 1052 i += skip; 1053 } else if (strcmp(argv[i], "-xor") == 0) { 1054 numRops = 1; 1055 rops[0] = GXxor; 1056 } else if (strcmp (argv[i], "-both") == 0) { 1057 numRops = 2; 1058 rops[0] = GXcopy; 1059 rops[1] = GXxor; 1060 } else if (strcmp(argv[i], "-reps") == 0) { 1061 i++; 1062 if (argc <= i) 1063 missing_arg(argv[i-1]); 1064 fixedReps = atoi (argv[i]); 1065 if (fixedReps <= 0) 1066 invalid_arg(argv[i], argv[i-1]); 1067 } else if (strcmp(argv[i], "-depth") == 0) { 1068 i++; 1069 if (argc <= i) 1070 missing_arg(argv[i-1]); 1071 depth = atoi(argv[i]); 1072 if (depth <= 0) 1073 invalid_arg(argv[i], argv[i-1]); 1074 } else if (strcmp(argv[i], "-vclass") == 0) { 1075 i++; 1076 if (argc <= i) 1077 missing_arg(argv[i-1]); 1078 for (j = StaticGray; j <= DirectColor; j++) { 1079 if (strcmp(argv[i], visualClassNames[j]) == 0) { 1080 vclass = j; 1081 break; 1082 } 1083 } 1084 if (vclass < 0) 1085 invalid_arg(argv[i], argv[i-1]); 1086 } else if (strcmp(argv[i], "-subs") == 0) { 1087 skip = GetNumbers (i+1, argc, argv, subWindows, &numSubWindows); 1088 i += skip; 1089 } else if (strcmp(argv[i], "-su") == 0) { 1090 xparms.save_under = True; 1091 } else if (strcmp(argv[i], "-bs") == 0) { 1092 i++; 1093 if (argc <= i) 1094 missing_arg(argv[i-1]); 1095 if (strcmp(argv[i], "WhenMapped") == 0) { 1096 xparms.backing_store = WhenMapped; 1097 } else if (strcmp(argv[i], "Always") == 0) { 1098 xparms.backing_store = Always; 1099 } else 1100 invalid_arg(argv[i], argv[i-1]); 1101 } else if ((strcmp(argv[i], "-version") == 0) || 1102 (strcmp(argv[i], "--version") == 0)) { 1103 puts(PACKAGE_STRING); 1104 exit(EXIT_SUCCESS); 1105 } else if ((strcmp(argv[i], "-help") == 0) || 1106 (strcmp(argv[i], "--help") == 0)) { 1107 i++; 1108 /* default is to just show general options */ 1109 if (argc <= i || (strcmp(argv[i], "options") == 0)) { 1110 usage (USAGE_OPTIONS, EXIT_SUCCESS); 1111 } 1112 else if (strcmp(argv[i], "tests") == 0) { 1113 usage (USAGE_TESTS, EXIT_SUCCESS); 1114 } 1115 else if (strcmp(argv[i], "all") == 0) { 1116 usage (USAGE_ALL, EXIT_SUCCESS); 1117 } 1118 else { 1119 invalid_arg(argv[i], argv[i-1]); 1120 } 1121 } else { 1122 int len,found; 1123 ForEachTest (j) { 1124 if (strcmp (argv[i], test[j].option) == 0 && 1125 (test[j].versions & xparms.version)) { 1126 doit[j] = True; 1127 goto LegalOption; 1128 } 1129 } 1130 found = False; 1131 len = strlen(argv[i]); 1132 if(len>=3) 1133 ForEachTest (j) { 1134 if (Strstr (test[j].option, argv[i]+1) != NULL) { 1135 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1136 doit[j] = found = True; 1137 } 1138 } 1139 if(!found) 1140 ForEachTest (j) { 1141 if (Strstr (LABELP(j), argv[i]+1) != NULL) { 1142 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1143 doit[j] = found = True; 1144 } 1145 } 1146 if (!found) { 1147 fprintf(stderr, 1148 "Error: unrecognized option %s\n", argv[i]); 1149 usage (USAGE_OPTIONS, EXIT_FAILURE); 1150 } 1151 LegalOption: 1152 foundOne = True; 1153 } 1154 } 1155 1156 if (labels) { 1157 /* Just print out list of tests for use with .sh programs that 1158 assemble data from different x11perf runs into a nice format */ 1159 ForEachTest (i) { 1160 if (doit[i]) { 1161 switch (test[i].testType) { 1162 case NONROP: 1163 printf ("%s\n", LABELP(i)); 1164 break; 1165 1166 case ROP: 1167 /* Run it through all specified rops and planemasks */ 1168 for (rop = 0; rop < numRops; rop++) { 1169 for (pm = 0; pm < numPlanemasks; pm++) { 1170 if (planemasks[pm] == ~0) { 1171 if (rops[rop] == GXcopy) { 1172 printf ("%s\n", LABELP(i)); 1173 } else { 1174 printf ("(%s) %s\n", 1175 ropNames[rops[rop]].name, 1176 LABELP(i)); 1177 } 1178 } else { 1179 printf ("(%s 0x%lx) %s\n", 1180 ropNames[rops[rop]].name, 1181 planemasks[pm], 1182 LABELP(i)); 1183 } 1184 } /* for pm */ 1185 } /* for rop */ 1186 break; 1187 1188 case PLANEMASK: 1189 /* Run it through all specified planemasks */ 1190 for (pm = 0; pm < numPlanemasks; pm++) { 1191 if (planemasks[pm] == ~0) { 1192 printf ("%s\n", LABELP(i)); 1193 } else { 1194 printf ("(0x%lx) %s\n", 1195 planemasks[pm], 1196 LABELP(i)); 1197 } 1198 } /* for pm */ 1199 break; 1200 1201 case WINDOW: 1202 for (int child = 0; child != numSubWindows; child++) { 1203 printf ("%s (%ld kids)\n", 1204 LABELP(i), subWindows[child]); 1205 } 1206 break; 1207 case COMP: 1208 /* Run it through all specified pops */ 1209 for (pop = 0; pop < numPops; pop++) { 1210 if (pops[pop] == PictOpOver) { 1211 printf ("%s\n", LABELP(i)); 1212 } else { 1213 printf ("(%s) %s\n", 1214 popNames[pops[pop]].name, 1215 LABELP(i)); 1216 } 1217 } /* for pop */ 1218 break; 1219 } /* switch */ 1220 } 1221 } 1222 exit(0); 1223 } 1224 1225 if (!foundOne) { 1226 fprintf(stderr, "Error: no argument found for which test(s) to run\n"); 1227 usage (USAGE_OPTIONS, EXIT_FAILURE); 1228 } 1229 xparms.d = Open_Display (displayName); 1230 screen = DefaultScreen(xparms.d); 1231 1232 /* get visual info of default visual */ 1233 vmask = VisualIDMask | VisualScreenMask; 1234 vinfotempl.visualid = XVisualIDFromVisual(XDefaultVisual(xparms.d, screen)); 1235 vinfotempl.screen = screen; 1236 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1237 if (!vinfolist || n != 1) { 1238 fprintf (stderr, "%s: can't get visual info of default visual\n", 1239 program_name); 1240 exit(1); 1241 } 1242 1243 if (depth == -1 && vclass == -1) { 1244 /* use the default visual and colormap */ 1245 xparms.vinfo = *vinfolist; 1246 cmap = XDefaultColormap(xparms.d, screen); 1247 } else { 1248 /* find the specified visual */ 1249 int errorDepth = vinfolist[0].depth; 1250 int errorClass = vinfolist[0].class; 1251 1252 vmask = VisualScreenMask; 1253 vinfotempl.screen = screen; 1254 if (depth >= 0) { 1255 vinfotempl.depth = depth; 1256 vmask |= VisualDepthMask; 1257 errorDepth = depth; 1258 } 1259 if (vclass >= 0) { 1260 vinfotempl.class = vclass; 1261 vmask |= VisualClassMask; 1262 errorClass = vclass; 1263 } 1264 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1265 if (!vinfolist) { 1266 fprintf (stderr, 1267 "%s: can't find a visual of depth %d and class %s\n", 1268 program_name, errorDepth, visualClassNames[errorClass]); 1269 exit(1); 1270 } 1271 xparms.vinfo = *vinfolist; /* use the first one in list */ 1272 if (xparms.vinfo.visualid == 1273 XVisualIDFromVisual(XDefaultVisual(xparms.d, screen))) { 1274 /* matched visual is same as default visual */ 1275 cmap = XDefaultColormap(xparms.d, screen); 1276 } else { 1277 cmap = XCreateColormap(xparms.d, DefaultRootWindow(xparms.d), 1278 xparms.vinfo.visual, AllocNone); 1279 /* since this is not default cmap, must force color allocation */ 1280 if (!foreground) foreground = "Black"; 1281 if (!background) background = "White"; 1282 XInstallColormap(xparms.d, cmap); 1283 } 1284 } 1285 xparms.cmap = cmap; 1286 1287 printf("x11perf - X11 performance program, version %s\n", 1288 xparms.version & VERSION1_5 ? "1.5" : 1289 xparms.version & VERSION1_4 ? "1.4" : 1290 xparms.version & VERSION1_3 ? "1.3" : 1291 "1.2" 1292 ); 1293 XmuGetHostname(hostname, 100); 1294 printf ("%s server version %d on %s\nfrom %s\n", 1295 ServerVendor (xparms.d), VendorRelease (xparms.d), 1296 DisplayString (xparms.d), hostname); 1297 PrintTime (); 1298 1299 /* Force screen out of screen-saver mode, grab current data, and set 1300 time to blank to 8 hours. We should just be able to turn the screen- 1301 saver off, but this causes problems on some servers. We also reset 1302 the screen-saver timer each test, as 8 hours is about the maximum time 1303 we can use, and that isn't long enough for some X terminals using a 1304 serial protocol to finish all the tests. As long as the tests run to 1305 completion, the old screen-saver values are restored. */ 1306 XForceScreenSaver(xparms.d, ScreenSaverReset); 1307 XGetScreenSaver(xparms.d, &ssTimeout, &ssInterval, &ssPreferBlanking, 1308 &ssAllowExposures); 1309 (void) signal(SIGINT, Cleanup); /* ^C */ 1310#ifdef SIGQUIT 1311 (void) signal(SIGQUIT, Cleanup); 1312#endif 1313 (void) signal(SIGTERM, Cleanup); 1314#ifdef SIGHUP 1315 (void) signal(SIGHUP, Cleanup); 1316#endif 1317 XSetScreenSaver(xparms.d, 8 * 3600, ssInterval, ssPreferBlanking, 1318 ssAllowExposures); 1319 1320 if (drawToFakeServer) { 1321 tileToQuery = 1322 XCreatePixmap(xparms.d, DefaultRootWindow (xparms.d), 32, 32, 1); 1323 } 1324 1325 1326 xparms.foreground = 1327 AllocateColor(xparms.d, foreground, BlackPixel(xparms.d, screen)); 1328 xparms.background = 1329 AllocateColor(xparms.d, background, WhitePixel(xparms.d, screen)); 1330 xparms.ddbackground = 1331 AllocateColor(xparms.d, ddbackground, WhitePixel(xparms.d, screen)); 1332 window_x = 2; 1333 if (DisplayWidth(xparms.d, screen) < WIDTH + window_x + 1) 1334 window_x = -1; 1335 window_y = 2; 1336 if (DisplayHeight(xparms.d, screen) < HEIGHT + window_y + 1) 1337 window_y = -1; 1338 xparms.w = CreatePerfWindow(&xparms, window_x, window_y, WIDTH, HEIGHT); 1339 HSx = WIDTH-1; 1340 if (window_x + 1 + WIDTH > DisplayWidth(xparms.d, screen)) 1341 HSx = DisplayWidth(xparms.d, screen) - (1 + window_x + 1); 1342 HSy = HEIGHT-1; 1343 if (window_y + 1 + HEIGHT > DisplayHeight(xparms.d, screen)) 1344 HSy = DisplayHeight(xparms.d, screen) - (1 + window_y + 1); 1345 status = CreatePerfWindow(&xparms, window_x, window_y + HEIGHT+3, WIDTH, 20); 1346 tgcv.foreground = 1347 AllocateColor(xparms.d, "black", BlackPixel(xparms.d, screen)); 1348 tgcv.background = 1349 AllocateColor(xparms.d, "white", WhitePixel(xparms.d, screen)); 1350 tgc = XCreateGC(xparms.d, status, GCForeground | GCBackground, &tgcv); 1351 1352 xparms.p = (Pixmap)0; 1353 1354 if (synchronous) 1355 XSynchronize (xparms.d, True); 1356 1357 /* Get mouse pointer out of the way of the performance window. On 1358 software cursor machines it will slow graphics performance. On 1359 all current MIT-derived servers it will slow window 1360 creation/configuration performance. */ 1361 XWarpPointer(xparms.d, None, status, 0, 0, 0, 0, WIDTH+32, 20+32); 1362 1363 /* Figure out how long to call HardwareSync, so we can adjust for that 1364 in our total elapsed time */ 1365 (void) CalibrateTest(&xparms, &syncTest, 1, &syncTime); 1366 printf("Sync time adjustment is %6.4f msecs.\n\n", syncTime/1000); 1367 1368 ForEachTest (i) { 1369 char label[200]; 1370 1371 if (doit[i] && (test[i].versions & xparms.version)) { 1372 switch (test[i].testType) { 1373 case NONROP: 1374 /* Simplest...just run it once */ 1375 strcpy (label, LABELP(i)); 1376 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1377 break; 1378 1379 case ROP: 1380 /* Run it through all specified rops and planemasks */ 1381 for (rop = 0; rop < numRops; rop++) { 1382 for (pm = 0; pm < numPlanemasks; pm++) { 1383 if (planemasks[pm] == ~0) { 1384 if (rops[rop] == GXcopy) { 1385 sprintf (label, "%s", LABELP(i)); 1386 } else { 1387 sprintf (label, "(%s) %s", 1388 ropNames[rops[rop]].name, 1389 LABELP(i)); 1390 } 1391 } else { 1392 sprintf (label, "(%s 0x%lx) %s", 1393 ropNames[rops[rop]].name, 1394 planemasks[pm], 1395 LABELP(i)); 1396 } 1397 ProcessTest(&xparms, &test[i], rops[rop], 1398 planemasks[pm], label); 1399 } /* for pm */ 1400 } /* for rop */ 1401 break; 1402 1403 case PLANEMASK: 1404 /* Run it through all specified planemasks */ 1405 for (pm = 0; pm < numPlanemasks; pm++) { 1406 if (planemasks[pm] == ~0) { 1407 sprintf (label, "%s", LABELP(i)); 1408 } else { 1409 sprintf (label, "(0x%lx) %s", 1410 planemasks[pm], 1411 LABELP(i)); 1412 } 1413 ProcessTest(&xparms, &test[i], GXcopy, 1414 planemasks[pm], label); 1415 } /* for pm */ 1416 break; 1417 1418 case WINDOW: 1419 /* Loop through number of children array */ 1420 for (int child = 0; child != numSubWindows; child++) { 1421 test[i].parms.objects = subWindows[child]; 1422 sprintf(label, "%s (%d kids)", 1423 LABELP(i), test[i].parms.objects); 1424 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1425 } 1426 break; 1427 case COMP: 1428 /* Loop through the composite operands */ 1429 for (pop = 0; pop < numPops; pop++) { 1430 for (format = 0; format < numFormats; format++) { 1431 if (formats[format] == PictStandardNative) { 1432 if (pops[pop] == PictOpOver) { 1433 sprintf (label, "%s", LABELP(i)); 1434 } else { 1435 sprintf (label, "(%s) %s", 1436 popNames[pops[pop]].name, 1437 LABELP(i)); 1438 } 1439 } else { 1440 const char *name = NameFromFormat (formats[format]); 1441 sprintf (label, "(%s %s) %s", 1442 popNames[pops[pop]].name, 1443 name, 1444 LABELP(i)); 1445 } 1446 ProcessTest (&xparms, &test[i], pops[pop], formats[format], label); 1447 } 1448 } 1449 break; 1450 } /* switch */ 1451 } /* if doit */ 1452 } /* ForEachTest */ 1453 1454 XFreeGC(xparms.d, tgc); 1455 XDestroyWindow(xparms.d, xparms.w); 1456 XFree(vinfolist); 1457 if (drawToFakeServer) 1458 XFreePixmap(xparms.d, tileToQuery); 1459 /* Restore ScreenSaver to original state. */ 1460 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 1461 ssAllowExposures); 1462 XCloseDisplay(xparms.d); 1463 free(saveargv); 1464 free(doit); 1465 exit(0); 1466} 1467 1468static int 1469GetWords (int argi, int argc, char **argv, char **wordsp, int *nump) 1470{ 1471 int count; 1472 1473 if (argc <= argi) 1474 missing_arg(argv[argi-1]); 1475 count = 0; 1476 while (argv[argi] && *(argv[argi]) != '-') { 1477 *wordsp++ = argv[argi]; 1478 ++argi; 1479 count++; 1480 } 1481 *nump = count; 1482 return count; 1483} 1484 1485static long 1486atox (char *s) 1487{ 1488 long v, c = 0; 1489 1490 v = 0; 1491 while (*s) { 1492 if ('0' <= *s && *s <= '9') 1493 c = *s - '0'; 1494 else if ('a' <= *s && *s <= 'f') 1495 c = *s - 'a' + 10; 1496 else if ('A' <= *s && *s <= 'F') 1497 c = *s - 'A' + 10; 1498 v = v * 16 + c; 1499 s++; 1500 } 1501 return v; 1502} 1503 1504static int 1505GetNumbers (int argi, int argc, char **argv, unsigned long *intsp, int *nump) 1506{ 1507 char *words[256]; 1508 int count; 1509 1510 count = GetWords (argi, argc, argv, words, nump); 1511 for (int i = 0; i < count; i++) { 1512 int flip = 0; 1513 if (!strncmp (words[i], "~", 1)) { 1514 words[i]++; 1515 flip = ~0; 1516 } 1517 if (!strncmp (words[i], "0x", 2)) 1518 intsp[i] = atox(words[i] + 2) ^ flip; 1519 else 1520 intsp[i] = atoi (words[i]) ^ flip; 1521 } 1522 return count; 1523} 1524 1525static int 1526GetRops (int argi, int argc, char **argv, int *ropsp, int *nump) 1527{ 1528 char *words[256]; 1529 int count; 1530 int rop; 1531 1532 count = GetWords (argi, argc, argv, words, nump); 1533 for (int i = 0; i < count; i++) { 1534 if (!strncmp (words[i], "GX", 2)) 1535 words[i] += 2; 1536 if (!strcmp (words[i], "all")) { 1537 for (i = 0; i < NUM_ROPS; i++) 1538 ropsp[i] = ropNames[i].rop; 1539 *nump = NUM_ROPS; 1540 break; 1541 } 1542 for (rop = 0; rop < NUM_ROPS; rop++) { 1543 if (!strcmp (words[i], ropNames[rop].name)) { 1544 ropsp[i] = ropNames[rop].rop; 1545 break; 1546 } 1547 } 1548 if (rop == NUM_ROPS) { 1549 usage (USAGE_OPTIONS, EXIT_FAILURE); 1550 fprintf (stderr, "unknown rop name %s\n", words[i]); 1551 } 1552 } 1553 return count; 1554} 1555 1556static int 1557GetPops (int argi, int argc, char **argv, int *popsp, int *nump) 1558{ 1559 char *words[256]; 1560 int count; 1561 int i; 1562 int pop; 1563 1564 count = GetWords (argi, argc, argv, words, nump); 1565 for (i = 0; i < count; i++) { 1566 if (!strncmp (words[i], "PictOp", 6)) 1567 words[i] += 6; 1568 if (!strcmp (words[i], "all")) { 1569 for (i = 0; i < NUM_POPS; i++) 1570 popsp[i] = popNames[i].rop; 1571 *nump = NUM_POPS; 1572 break; 1573 } 1574 for (pop = 0; pop < NUM_POPS; pop++) { 1575 if (!strcmp (words[i], popNames[pop].name)) { 1576 popsp[i] = popNames[pop].rop; 1577 break; 1578 } 1579 } 1580 if (pop == NUM_POPS) { 1581 usage (USAGE_OPTIONS, EXIT_FAILURE); 1582 fprintf (stderr, "unknown picture op name %s\n", words[i]); 1583 } 1584 } 1585 return count; 1586} 1587 1588static int 1589FormatFromName (char *name) 1590{ 1591 int i; 1592 for (i = 0; i < NUM_FORMATS; i++) 1593 if (!strcmp (name, formatNames[i].name)) 1594 return formatNames[i].rop; 1595 return -1; 1596} 1597 1598static const char * 1599NameFromFormat (int format) 1600{ 1601 for (int i = 0; i < NUM_FORMATS; i++) 1602 if (formatNames[i].rop == format) 1603 return formatNames[i].name; 1604 return NULL; 1605} 1606 1607static int 1608GetFormats (int argi, int argc, char **argv, int *formatsp, int *nump) 1609{ 1610 char *words[256]; 1611 int count; 1612 int i; 1613 1614 count = GetWords (argi, argc, argv, words, nump); 1615 for (i = 0; i < count; i++) { 1616 int format; 1617 1618 if (!strcmp (words[i], "all")) { 1619 for (i = 0; i < NUM_FORMATS; i++) 1620 formatsp[i] = formatNames[i].rop; 1621 *nump = NUM_FORMATS; 1622 break; 1623 } 1624 format = FormatFromName (words[i]); 1625 if (format < 0) { 1626 usage (USAGE_OPTIONS, EXIT_FAILURE); 1627 fprintf (stderr, "unknown format name %s\n", words[i]); 1628 } 1629 formatsp[i] = format; 1630 } 1631 return count; 1632} 1633