x11perf.c revision 9321e1b7
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 double msecsperobj, objspersec; 293 294 if(usecs != 0.0) 295 { 296 msecsperobj = usecs / (1000.0 * (double)n); 297 objspersec = (double) n * 1000000.0 / usecs; 298 299 /* Round obj/sec to 3 significant digits. Leave msec untouched, to 300 allow averaging results from several repetitions. */ 301 objspersec = RoundTo3Digits(objspersec); 302 303 if (average) { 304 printf("%11lld trep @ %8.4f msec (%8.1f/sec): %s\n", 305 (long long) n, msecsperobj, objspersec, str); 306 } else { 307 printf("%11lld reps @ %8.4f msec (%8.1f/sec): %s\n", 308 (long long) n, msecsperobj, objspersec, str); 309 } 310 } else { 311 printf("%6lld %sreps @ 0.0 msec (unmeasurably fast): %s\n", 312 (long long) n, average ? "t" : "", str); 313 } 314 315} 316 317 318 319/************************************************ 320* Generic X stuff * 321************************************************/ 322 323static char *program_name; 324static void usage(void) _X_NORETURN; 325 326/* 327 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete) 328 * If found, remove it from command line. Don't go past a lone -. 329 */ 330static char * 331Get_Display_Name(int *pargc, /* MODIFIED */ 332 char **argv) /* MODIFIED */ 333{ 334 int argc = *pargc; 335 char **pargv = argv+1; 336 char *displayname = NULL; 337 int i; 338 339 for (i = 1; i != argc; i++) { 340 char *arg = argv[i]; 341 342 if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) { 343 if (++i >= argc) usage (); 344 345 displayname = argv[i]; 346 *pargc -= 2; 347 continue; 348 } 349 if (!strcmp(arg,"-")) { 350 while (i<argc) *pargv++ = argv[i++]; 351 break; 352 } 353 *pargv++ = arg; 354 } 355 356 *pargv = NULL; 357 return (displayname); 358} 359 360 361/* 362 * GetVersion (argc, argv) Look for -v1.2, -v1.3, or -v1.4. 363 * If found remove it from command line. Don't go past a lone -. 364 */ 365 366static Version 367GetVersion(int *pargc, /* MODIFIED */ 368 char **argv) /* MODIFIED */ 369{ 370 int argc = *pargc; 371 char **pargv = argv+1; 372 Version version = VERSION1_6; 373 int i; 374 Bool found = False; 375 376 for (i = 1; i != argc; i++) { 377 char *arg = argv[i]; 378 379 if (!strcmp (arg, "-v1.2")) { 380 version = VERSION1_2; 381 *pargc -= 1; 382 if (found) { 383 fprintf(stderr, "Warning: multiple version specifications\n"); 384 } 385 found = True; 386 continue; 387 } 388 if (!strcmp (arg, "-v1.3")) { 389 version = VERSION1_3; 390 *pargc -= 1; 391 if (found) { 392 fprintf(stderr, "Warning: multiple version specifications\n"); 393 } 394 found = True; 395 continue; 396 } 397 if (!strcmp (arg, "-v1.4")) { 398 version = VERSION1_4; 399 *pargc -= 1; 400 if (found) { 401 fprintf(stderr, "Warning: multiple version specifications\n"); 402 } 403 found = True; 404 continue; 405 } 406 if (!strcmp (arg, "-v1.5")) { 407 version = VERSION1_5; 408 *pargc -= 1; 409 if (found) { 410 fprintf(stderr, "Warning: multiple version specifications\n"); 411 } 412 found = True; 413 continue; 414 } 415 if (!strcmp(arg,"-")) { 416 while (i<argc) *pargv++ = argv[i++]; 417 break; 418 } 419 *pargv++ = arg; 420 } 421 422 *pargv = NULL; 423 return (version); 424} 425 426 427 428/* 429 * Open_Display: Routine to open a display with correct error handling. 430 */ 431static Display * 432Open_Display(char *display_name) 433{ 434 Display *d; 435 436 d = XOpenDisplay(display_name); 437 if (d == NULL) { 438 fprintf (stderr, "%s: unable to open display '%s'\n", 439 program_name, XDisplayName (display_name)); 440 exit(1); 441 } 442 443 return(d); 444} 445 446static void 447Cleanup(int sig) 448{ 449 abortTest = sig; 450} 451 452void 453AbortTest(void) 454{ 455 fflush(stdout); 456 457 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 458 ssAllowExposures); 459 XFlush(xparms.d); 460 exit (abortTest); 461} 462 463/************************************************ 464* Performance stuff * 465************************************************/ 466 467 468static void 469usage(void) 470{ 471 int i = 0; 472 static const char *help_message = 473"where options include:\n" 474" -display <host:display> the X server to contact\n" 475" -sync do the tests in synchronous mode\n" 476" -pack pack rectangles right next to each other\n" 477" -repeat <n> do tests <n> times (default = 5)\n" 478" -time <s> do tests for <s> seconds each (default = 5)\n" 479" -pause <s> pause for <s> seconds between each run\n" 480/* 481" -draw draw after each test -- pmax only\n" 482*/ 483" -all do all tests\n" 484" -range <test1>[,<test2>] like all, but do <test1> to <test2>\n" 485" -labels generate test labels for use by fillblnk\n" 486" -fg the foreground color to use\n" 487" -bg the background color to use\n" 488" -clips <default> default number of clip windows per test\n" 489" -ddbg the background color to use for DoubleDash\n" 490" -rop <rop0 rop1 ...> use the given rops to draw (default = GXcopy)\n" 491" -pm <pm0 pm1 ...> use the given planemasks to draw (default = ~0)\n" 492" -depth <depth> use a visual with <depth> planes per pixel\n" 493" -vclass <class> the visual class to use (default = root)\n" 494" -reps <n> fix the rep count (default = auto scale)\n" 495" -subs <s0 s1 ...> a list of the number of sub-windows to use\n" 496" -v1.2 perform only v1.2 tests using old semantics\n" 497" -v1.3 perform only v1.3 tests using old semantics\n" 498" -su request save unders on windows\n" 499" -bs <backing_store_hint> WhenMapped or Always (default = NotUseful)\n" 500; 501 502 fflush(stdout); 503 fprintf(stderr, "usage: %s [-options ...]\n%s", program_name, help_message); 504 while (test[i].option != NULL) { 505 if (test[i].versions & xparms.version ) { 506 fprintf(stderr, " %-24s %s\n", 507 test[i].option, 508 test[i].label14 ? test[i].label14 : test[i].label); 509 } 510 i++; 511 } 512 fprintf(stderr, "\n"); 513 514 /* Print out original command line as the above usage message is so long */ 515 for (i = 0; i != saveargc; i++) { 516 fprintf(stderr, "%s ", saveargv[i]); 517 } 518 fprintf(stderr, "\n\n"); 519 exit (1); 520} 521 522void 523NullProc(XParms xp, Parms p) 524{ 525} 526 527int 528NullInitProc(XParms xp, Parms p, int64_t reps) 529{ 530 return reps; 531} 532 533static void 534HardwareSync(XParms xp) 535{ 536 /* 537 * Some graphics hardware allows the server to claim it is done, 538 * while in reality the hardware is busily working away. So fetch 539 * a pixel from the drawable that was drawn to, which should be 540 * enough to make the server wait for the graphics hardware. 541 */ 542 XImage *image; 543 544 image = XGetImage(xp->d, xp->p ? xp->p : xp->w, HSx, HSy, 545 1, 1, ~0, ZPixmap); 546 if (image) XDestroyImage(image); 547} 548 549static void 550DoHardwareSync(XParms xp, Parms p, int64_t reps) 551{ 552 int i; 553 554 for (i = 0; i != reps; i++) { 555 HardwareSync(xp); 556 CheckAbort (); 557 } 558} 559 560static Test syncTest = { 561 "syncTime", "Internal test for finding how long HardwareSync takes", NULL, 562 NullInitProc, DoHardwareSync, NullProc, NullProc, 563 V1_2FEATURE, NONROP, 0, 564 {1} 565}; 566 567 568static Window 569CreatePerfWindow(XParms xp, int x, int y, int width, int height) 570{ 571 XSetWindowAttributes xswa; 572 Window w; 573/* 574 Screen *s; 575 int su; 576 577 s = DefaultScreenOfDisplay(xp->d); 578 su = XDoesBackingStore(s); 579 printf("Backing store of screen returns %d\n", su); 580 su = XDoesSaveUnders(s); 581 printf("Save unders of screen returns %d\n", su); 582 su = XPlanesOfScreen(s); 583 printf("Planes of screen returns %d\n", su); 584*/ 585 xswa.background_pixel = xp->background; 586 xswa.border_pixel = xp->foreground; 587 xswa.colormap = cmap; 588 xswa.override_redirect = True; 589 xswa.backing_store = xp->backing_store; 590 xswa.save_under = xp->save_under; 591 w = XCreateWindow(xp->d, DefaultRootWindow(xp->d), x, y, width, height, 1, 592 xp->vinfo.depth, CopyFromParent, xp->vinfo.visual, 593 CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect 594 | CWBackingStore | CWSaveUnder, &xswa); 595 XMapWindow (xp->d, w); 596 return w; 597} 598 599 600static void 601CreateClipWindows(XParms xp, int clips) 602{ 603 int j; 604 XWindowAttributes xwa; 605 606 (void) XGetWindowAttributes(xp->d, xp->w, &xwa); 607 if (clips > MAXCLIP) clips = MAXCLIP; 608 for (j = 0; j != clips; j++) { 609 clipWindows[j] = CreatePerfWindow(xp, 610 xwa.x + ws[j].x, xwa.y + ws[j].y, ws[j].width, ws[j].height); 611 } 612} /* CreateClipWindows */ 613 614 615static void 616DestroyClipWindows(XParms xp, int clips) 617{ 618 int j; 619 620 if (clips > MAXCLIP) clips = MAXCLIP; 621 for (j = 0; j != clips; j++) { 622 XDestroyWindow(xp->d, clipWindows[j]); 623 } 624} /* DestroyClipWindows */ 625 626 627static double 628DoTest(XParms xp, Test *test, int64_t reps) 629{ 630 double time; 631 unsigned int ret_width, ret_height; 632 633 /* Tell screen-saver to restart counting again. See comments below for the 634 XSetScreenSaver call. */ 635 XForceScreenSaver(xp->d, ScreenSaverReset); 636 HardwareSync (xp); 637 InitTimes (); 638 (*test->proc) (xp, &test->parms, reps); 639 HardwareSync(xp); 640 641 time = ElapsedTime(syncTime); 642 if (time < 0.0) time = 0.0; 643 CheckAbort (); 644 if (drawToFakeServer) 645 XQueryBestSize(xp->d, TileShape, tileToQuery, 646 32, 32, &ret_width, &ret_height); 647 (*test->passCleanup) (xp, &test->parms); 648 return time; 649} 650 651 652static int64_t 653CalibrateTest(XParms xp, Test *test, int seconds, double *usecperobj) 654{ 655#define goal 2500000.0 /* Try to get up to 2.5 seconds */ 656#define enough 2000000.0 /* But settle for 2.0 seconds */ 657#define tick 10000.0 /* Assume clock not faster than .01 seconds */ 658 659 double usecs; 660 int64_t reps, didreps; /* Reps desired, reps performed */ 661 int exponent; 662 663 /* Attempt to get an idea how long each rep lasts by getting enough 664 reps to last more tan enough. Then scale that up to the number of 665 seconds desired. 666 667 If init call to test ever fails, return False and test will be skipped. 668 */ 669 670 if (fixedReps != 0) { 671 return fixedReps; 672 } 673 reps = 1; 674 for (;;) { 675 XDestroySubwindows(xp->d, xp->w); 676 XClearWindow(xp->d, xp->w); 677 didreps = (*test->init) (xp, &test->parms, reps); 678 CheckAbort (); 679 if (didreps == 0) { 680 return 0; 681 } 682 if ( test->clips < clips ) 683 test->clips = clips ; 684 /* Create clip windows if requested */ 685 CreateClipWindows(xp, test->clips); 686 HardwareSync(xp); 687 InitTimes(); 688 (*test->proc) (xp, &test->parms, reps); 689 HardwareSync(xp); 690 usecs = ElapsedTime(syncTime); 691 (*test->passCleanup) (xp, &test->parms); 692 (*test->cleanup) (xp, &test->parms); 693 DestroyClipWindows(xp, test->clips); 694 CheckAbort (); 695 696 if (didreps != reps) { 697 /* The test can't do the number of reps as we asked for. 698 Give up */ 699 *usecperobj = 700 usecs / (double)(didreps * test->parms.objects); 701 return didreps; 702 } 703 /* Did we go long enough? */ 704 if (usecs >= enough) break; 705 706 /* Don't let too short a clock make new reps wildly high */ 707 if (usecs <= tick)reps = reps*10; 708 else{ 709 /* Try to get up to goal seconds. */ 710 reps = (int) (goal * (double)reps / usecs) + 1; 711 } 712 } 713 714 *usecperobj = usecs / (double) (reps * test->parms.objects); 715 reps = (int) ((double)seconds * 1000000.0 * (double)reps / usecs) + 1; 716 717 /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking 718 numbers of repetitions. */ 719 reps--; 720 exponent = 1; 721 while (reps > 9) { 722 reps /= 10; 723 exponent *= 10; 724 } 725 reps = (reps + 1) * exponent; 726 return reps; 727} /* CalibrateTest */ 728 729static void 730CreatePerfGCs(XParms xp, int func, unsigned long pm) 731{ 732 XGCValues gcvfg, gcvbg, gcvddbg,gcvddfg; 733 unsigned long fg, bg, ddbg; 734 735 fg = xp->foreground; 736 bg = xp->background; 737 ddbg = xp->ddbackground; 738 gcvfg.graphics_exposures = False; 739 gcvbg.graphics_exposures = False; 740 gcvddfg.graphics_exposures = False; 741 gcvddbg.graphics_exposures = False; 742 gcvfg.plane_mask = pm; 743 gcvbg.plane_mask = pm; 744 gcvddfg.plane_mask = pm; 745 gcvddbg.plane_mask = pm; 746 gcvfg.function = func; 747 gcvbg.function = func; 748 gcvddfg.function = func; 749 gcvddbg.function = func; 750 751 if (func == GXxor) { 752 /* Make test look good visually if possible */ 753 gcvbg.foreground = gcvfg.foreground = bg ^ fg; 754 gcvbg.background = gcvfg.background = bg; 755 /* Double Dash GCs (This doesn't make a huge amount of sense) */ 756 gcvddbg.foreground = gcvddfg.foreground = bg ^ fg; 757 gcvddbg.background = gcvddfg.foreground = bg ^ ddbg; 758 } else { 759 gcvfg.foreground = fg; 760 gcvfg.background = bg; 761 gcvbg.foreground = bg; 762 gcvbg.background = fg; 763 gcvddfg.foreground = fg; 764 gcvddfg.background = ddbg; 765 gcvddbg.foreground = ddbg; 766 gcvddbg.background = fg; 767 } 768 xp->fggc = XCreateGC(xp->d, xp->w, 769 GCForeground | GCBackground | GCGraphicsExposures 770 | GCFunction | GCPlaneMask, &gcvfg); 771 xp->bggc = XCreateGC(xp->d, xp->w, 772 GCForeground | GCBackground | GCGraphicsExposures 773 | GCFunction | GCPlaneMask, &gcvbg); 774 xp->ddfggc = XCreateGC(xp->d, xp->w, 775 GCForeground | GCBackground | GCGraphicsExposures 776 | GCFunction | GCPlaneMask, &gcvddfg); 777 xp->ddbggc = XCreateGC(xp->d, xp->w, 778 GCForeground | GCBackground | GCGraphicsExposures 779 | GCFunction | GCPlaneMask, &gcvddbg); 780} 781 782 783static void 784DestroyPerfGCs(XParms xp) 785{ 786 XFreeGC(xp->d, xp->fggc); 787 XFreeGC(xp->d, xp->bggc); 788 XFreeGC(xp->d, xp->ddfggc); 789 XFreeGC(xp->d, xp->ddbggc); 790} 791 792static unsigned long 793AllocateColor(Display *display, const char *name, unsigned long pixel) 794{ 795 XColor color; 796 797 if (name != NULL) { 798 /* Try to parse color name */ 799 if (XParseColor(display, cmap, name, &color)) { 800 if (XAllocColor(display, cmap, &color)) { 801 pixel = color.pixel; 802 } else { 803 (void) fprintf(stderr, 804 "Can't allocate colormap entry for color %s\n", name); 805 } 806 } else { 807 if(*name >= '0' && *name <= '9') 808 pixel = atoi(name); 809 else 810 (void) fprintf(stderr, "Can't parse color name %s\n", name); 811 } 812 } 813 return pixel; 814} /* AllocateColor */ 815 816 817static void 818DisplayStatus(Display *d, const char *message, const char *test, int try) 819{ 820 char s[500]; 821 822 XClearWindow(d, status); 823 sprintf(s, "%d %s %s", try, message, test); 824 /* We should really look at the height, descent of the font, etc. but 825 who cares. This works. */ 826 XDrawString(d, status, tgc, 10, 13, s, strlen(s)); 827} 828 829 830static void 831ProcessTest(XParms xp, Test *test, int func, unsigned long pm, char *label) 832{ 833 double time, totalTime; 834 long long reps; 835 int j; 836 837 xp->planemask = pm; 838 xp->func = func; 839 if (test->testType == COMP) 840 { 841 func = GXcopy; 842 pm = ~0L; 843 } 844 CreatePerfGCs(xp, func, pm); 845 DisplayStatus(xp->d, "Calibrating", label, 0); 846 reps = CalibrateTest(xp, test, seconds, &time); 847 if (reps != 0) { 848 XDestroySubwindows(xp->d, xp->w); 849 XClearWindow(xp->d, xp->w); 850 reps = (*test->init) (xp, &test->parms, reps); 851 if (abortTest) 852 AbortTest (); 853 /* 854 * if using fixedReps then will not have done CalibrateTest so must 855 * check result of init for 0 here 856 */ 857 if(reps == 0){ 858 DestroyPerfGCs(xp); 859 return; 860 } 861 /* Create clip windows if requested */ 862 CreateClipWindows(xp, test->clips); 863 864 totalTime = 0.0; 865 for (j = 0; j != repeat; j++) { 866 DisplayStatus(xp->d, "Testing", label, j+1); 867 time = DoTest(xp, test, reps); 868 if (abortTest) 869 AbortTest (); 870 totalTime += time; 871 ReportTimes (time, reps * test->parms.objects, 872 label, False); 873 if (delay) 874 sleep(delay); 875 } 876 if (repeat > 1) { 877 ReportTimes(totalTime, 878 repeat * reps * test->parms.objects, 879 label, True); 880 } 881 (*test->cleanup) (xp, &test->parms); 882 DestroyClipWindows(xp, test->clips); 883 } else { 884 /* Test failed to initialize properly */ 885 } 886 printf ("\n"); 887 fflush(stdout); 888 DestroyPerfGCs(xp); 889} /* ProcessTest */ 890 891#define Strstr strstr 892 893#define LABELP(i) (test[i].label14 && (xparms.version >= VERSION1_4) \ 894 ? test[i].label14 : test[i].label) 895 896int 897main(int argc, char *argv[]) 898{ 899 int i, j, n, skip; 900 int numTests; /* Even though the linker knows, we don't. */ 901 char hostname[100]; 902 Bool foundOne = False; 903 Bool synchronous = False; 904 XGCValues tgcv; 905 int screen; 906 int rop, pm; 907 int pop, format; 908 int window_y, window_x; 909 XVisualInfo *vinfolist, vinfotempl; 910 unsigned long vmask; 911 912 /* Save away argv, argc, for usage to print out */ 913 saveargc = argc; 914 saveargv = (char **) malloc(argc * sizeof(char *)); 915 for (i = 0; i != argc; i++) { 916 saveargv[i] = argv[i]; 917 } 918 919 xparms.pack = False; 920 xparms.save_under = False; 921 xparms.backing_store = NotUseful; 922 923 /* Count number of tests */ 924 ForEachTest(numTests); 925 doit = (Bool *)calloc(numTests, sizeof(Bool)); 926 927 /* Parse arguments */ 928 program_name = argv[0]; 929 displayName = Get_Display_Name (&argc, argv); 930 xparms.version = GetVersion(&argc, argv); 931 for (i = 1; i != argc; i++) { 932 if (strcmp (argv[i], "-all") == 0) { 933 ForEachTest (j) 934 doit[j] = test[j].versions & xparms.version; 935 foundOne = True; 936 } else if (strcmp (argv[i], "-labels") == 0) { 937 labels = True; 938 } else if (strcmp(argv[i], "-range") == 0) { 939 char *cp1; 940 char *cp2; 941 942 if (argc <= ++i) 943 usage(); 944 cp1 = argv[i]; 945 if (*cp1 == '-') 946 cp1++; 947 for (cp2 = cp1; *cp2 != '\0' && *cp2 != ','; cp2++) {}; 948 if (*cp2 == ',') { 949 *cp2++ = '\0'; 950 if (*cp2 == '-') 951 cp2++; 952 } else { 953 cp2 = "-"; 954 } 955 ForEachTest (j) { 956 if (strcmp (cp1, (test[j].option) + 1) == 0 && 957 (test[j].versions & xparms.version)) { 958 int k = j; 959 do { 960 doit[k] = test[j].versions & xparms.version; 961 } while (!(strcmp(cp2, (test[k].option + 1)) == 0 && 962 (test[k].versions & xparms.version)) && 963 test[++k].option != NULL); 964 if (*cp2 != '-' && test[k].option == NULL) 965 usage(); 966 break; 967 } 968 } 969 if (test[j].option == NULL) 970 usage(); 971 foundOne = True; 972 } else if (strcmp (argv[i], "-sync") == 0) { 973 synchronous = True; 974 } else if (strcmp (argv[i], "-pack") == 0) { 975 xparms.pack = True; 976 } else if (strcmp (argv[i], "-draw") == 0) { 977 drawToFakeServer = True; 978 } else if (strcmp (argv[i], "-falseprecision") == 0) { 979 falsePrecision = True; 980 } else if (strcmp (argv[i], "-repeat") == 0) { 981 i++; 982 if (argc <= i) 983 usage (); 984 repeat = atoi (argv[i]); 985 if (repeat <= 0) 986 usage (); 987 } else if (strcmp (argv[i], "-time") == 0) { 988 i++; 989 if (argc <= i) 990 usage (); 991 seconds = atoi (argv[i]); 992 if (seconds <= 0) 993 usage (); 994 } else if (strcmp (argv[i], "-pause") == 0) { 995 ++i; 996 if (argc <= i) 997 usage (); 998 delay = atoi (argv[i]); 999 if (delay < 0) 1000 usage (); 1001 } else if (strcmp(argv[i], "-fg") == 0) { 1002 i++; 1003 if (argc <= i) 1004 usage (); 1005 foreground = argv[i]; 1006 } else if (strcmp(argv[i], "-bg") == 0) { 1007 i++; 1008 if (argc <= i) 1009 usage (); 1010 background = argv[i]; 1011 if(ddbackground == NULL) 1012 ddbackground = argv[i]; 1013 } else if (strcmp(argv[i], "-clips") == 0 ) { 1014 i++; 1015 if (argc <= i) 1016 usage (); 1017 clips = atoi( argv[i] ); 1018 } else if (strcmp(argv[i], "-ddbg") == 0) { 1019 if (argc <= i) 1020 usage (); 1021 i++; 1022 ddbackground = argv[i]; 1023 } else if (strcmp(argv[i], "-rop") == 0) { 1024 skip = GetRops (i+1, argc, argv, rops, &numRops); 1025 i += skip; 1026 } else if (strcmp(argv[i], "-pop") == 0) { 1027 skip = GetPops (i+1, argc, argv, pops, &numPops); 1028 i += skip; 1029 } else if (strcmp(argv[i], "-format") == 0) { 1030 skip = GetFormats (i+1, argc, argv, formats, &numFormats); 1031 i += skip; 1032 } else if (strcmp(argv[i], "-pm") == 0) { 1033 skip = GetNumbers (i+1, argc, argv, planemasks, &numPlanemasks); 1034 i += skip; 1035 } else if (strcmp(argv[i], "-xor") == 0) { 1036 numRops = 1; 1037 rops[0] = GXxor; 1038 } else if (strcmp (argv[i], "-both") == 0) { 1039 numRops = 2; 1040 rops[0] = GXcopy; 1041 rops[1] = GXxor; 1042 } else if (strcmp(argv[i], "-reps") == 0) { 1043 i++; 1044 if (argc <= i) 1045 usage (); 1046 fixedReps = atoi (argv[i]); 1047 if (fixedReps <= 0) 1048 usage (); 1049 } else if (strcmp(argv[i], "-depth") == 0) { 1050 i++; 1051 if (argc <= i) 1052 usage (); 1053 depth = atoi(argv[i]); 1054 if (depth <= 0) 1055 usage (); 1056 } else if (strcmp(argv[i], "-vclass") == 0) { 1057 i++; 1058 if (argc <= i) 1059 usage (); 1060 for (j = StaticGray; j <= DirectColor; j++) { 1061 if (strcmp(argv[i], visualClassNames[j]) == 0) { 1062 vclass = j; 1063 break; 1064 } 1065 } 1066 if (vclass < 0) 1067 usage (); 1068 } else if (strcmp(argv[i], "-subs") == 0) { 1069 skip = GetNumbers (i+1, argc, argv, subWindows, &numSubWindows); 1070 i += skip; 1071 } else if (strcmp(argv[i], "-v1.2") == 0) { 1072 xparms.version = VERSION1_2; 1073 } else if (strcmp(argv[i], "-v1.3") == 0) { 1074 xparms.version = VERSION1_3; 1075 } else if (strcmp(argv[i], "-su") == 0) { 1076 xparms.save_under = True; 1077 } else if (strcmp(argv[i], "-bs") == 0) { 1078 i++; 1079 if (argc <= i) 1080 usage (); 1081 if (strcmp(argv[i], "WhenMapped") == 0) { 1082 xparms.backing_store = WhenMapped; 1083 } else if (strcmp(argv[i], "Always") == 0) { 1084 xparms.backing_store = Always; 1085 } else usage (); 1086 } else { 1087 int len,found; 1088 ForEachTest (j) { 1089 if (strcmp (argv[i], test[j].option) == 0 && 1090 (test[j].versions & xparms.version)) { 1091 doit[j] = True; 1092 goto LegalOption; 1093 } 1094 } 1095 found = False; 1096 len = strlen(argv[i]); 1097 if(len>=3) 1098 ForEachTest (j) { 1099 if (Strstr (test[j].option, argv[i]+1) != NULL) { 1100 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1101 doit[j] = found = True; 1102 } 1103 } 1104 if(!found) 1105 ForEachTest (j) { 1106 if (Strstr (LABELP(j), argv[i]+1) != NULL) { 1107 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1108 doit[j] = found = True; 1109 } 1110 } 1111 if(!found) 1112 usage (); 1113 LegalOption: 1114 foundOne = True; 1115 } 1116 } 1117 1118 if (labels) { 1119 /* Just print out list of tests for use with .sh programs that 1120 assemble data from different x11perf runs into a nice format */ 1121 ForEachTest (i) { 1122 int child; 1123 if (doit[i]) { 1124 switch (test[i].testType) { 1125 case NONROP: 1126 printf ("%s\n", LABELP(i)); 1127 break; 1128 1129 case ROP: 1130 /* Run it through all specified rops and planemasks */ 1131 for (rop = 0; rop < numRops; rop++) { 1132 for (pm = 0; pm < numPlanemasks; pm++) { 1133 if (planemasks[pm] == ~0) { 1134 if (rops[rop] == GXcopy) { 1135 printf ("%s\n", LABELP(i)); 1136 } else { 1137 printf ("(%s) %s\n", 1138 ropNames[rops[rop]].name, 1139 LABELP(i)); 1140 } 1141 } else { 1142 printf ("(%s 0x%lx) %s\n", 1143 ropNames[rops[rop]].name, 1144 planemasks[pm], 1145 LABELP(i)); 1146 } 1147 } /* for pm */ 1148 } /* for rop */ 1149 break; 1150 1151 case PLANEMASK: 1152 /* Run it through all specified planemasks */ 1153 for (pm = 0; pm < numPlanemasks; pm++) { 1154 if (planemasks[pm] == ~0) { 1155 printf ("%s\n", LABELP(i)); 1156 } else { 1157 printf ("(0x%lx) %s\n", 1158 planemasks[pm], 1159 LABELP(i)); 1160 } 1161 } /* for pm */ 1162 break; 1163 1164 case WINDOW: 1165 for (child = 0; child != numSubWindows; child++) { 1166 printf ("%s (%ld kids)\n", 1167 LABELP(i), subWindows[child]); 1168 } 1169 break; 1170 case COMP: 1171 /* Run it through all specified pops */ 1172 for (pop = 0; pop < numPops; pop++) { 1173 if (pops[pop] == PictOpOver) { 1174 printf ("%s\n", LABELP(i)); 1175 } else { 1176 printf ("(%s) %s\n", 1177 popNames[pops[pop]].name, 1178 LABELP(i)); 1179 } 1180 } /* for pop */ 1181 break; 1182 } /* switch */ 1183 } 1184 } 1185 exit(0); 1186 } 1187 1188 if (!foundOne) 1189 usage (); 1190 xparms.d = Open_Display (displayName); 1191 screen = DefaultScreen(xparms.d); 1192 1193 /* get visual info of default visual */ 1194 vmask = VisualIDMask | VisualScreenMask; 1195 vinfotempl.visualid = XVisualIDFromVisual(XDefaultVisual(xparms.d, screen)); 1196 vinfotempl.screen = screen; 1197 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1198 if (!vinfolist || n != 1) { 1199 fprintf (stderr, "%s: can't get visual info of default visual\n", 1200 program_name); 1201 exit(1); 1202 } 1203 1204 if (depth == -1 && vclass == -1) { 1205 /* use the default visual and colormap */ 1206 xparms.vinfo = *vinfolist; 1207 cmap = XDefaultColormap(xparms.d, screen); 1208 } else { 1209 /* find the specified visual */ 1210 int errorDepth = vinfolist[0].depth; 1211 int errorClass = vinfolist[0].class; 1212 1213 vmask = VisualScreenMask; 1214 vinfotempl.screen = screen; 1215 if (depth >= 0) { 1216 vinfotempl.depth = depth; 1217 vmask |= VisualDepthMask; 1218 errorDepth = depth; 1219 } 1220 if (vclass >= 0) { 1221 vinfotempl.class = vclass; 1222 vmask |= VisualClassMask; 1223 errorClass = vclass; 1224 } 1225 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1226 if (!vinfolist) { 1227 fprintf (stderr, 1228 "%s: can't find a visual of depth %d and class %s\n", 1229 program_name, errorDepth, visualClassNames[errorClass]); 1230 exit(1); 1231 } 1232 xparms.vinfo = *vinfolist; /* use the first one in list */ 1233 if (xparms.vinfo.visualid == 1234 XVisualIDFromVisual(XDefaultVisual(xparms.d, screen))) { 1235 /* matched visual is same as default visual */ 1236 cmap = XDefaultColormap(xparms.d, screen); 1237 } else { 1238 cmap = XCreateColormap(xparms.d, DefaultRootWindow(xparms.d), 1239 xparms.vinfo.visual, AllocNone); 1240 /* since this is not default cmap, must force color allocation */ 1241 if (!foreground) foreground = "Black"; 1242 if (!background) background = "White"; 1243 XInstallColormap(xparms.d, cmap); 1244 } 1245 } 1246 xparms.cmap = cmap; 1247 1248 printf("x11perf - X11 performance program, version %s\n", 1249 xparms.version & VERSION1_5 ? "1.5" : 1250 xparms.version & VERSION1_4 ? "1.4" : 1251 xparms.version & VERSION1_3 ? "1.3" : 1252 "1.2" 1253 ); 1254 XmuGetHostname(hostname, 100); 1255 printf ("%s server version %d on %s\nfrom %s\n", 1256 ServerVendor (xparms.d), VendorRelease (xparms.d), 1257 DisplayString (xparms.d), hostname); 1258 PrintTime (); 1259 1260 /* Force screen out of screen-saver mode, grab current data, and set 1261 time to blank to 8 hours. We should just be able to turn the screen- 1262 saver off, but this causes problems on some servers. We also reset 1263 the screen-saver timer each test, as 8 hours is about the maximum time 1264 we can use, and that isn't long enough for some X terminals using a 1265 serial protocol to finish all the tests. As long as the tests run to 1266 completion, the old screen-saver values are restored. */ 1267 XForceScreenSaver(xparms.d, ScreenSaverReset); 1268 XGetScreenSaver(xparms.d, &ssTimeout, &ssInterval, &ssPreferBlanking, 1269 &ssAllowExposures); 1270 (void) signal(SIGINT, Cleanup); /* ^C */ 1271#ifdef SIGQUIT 1272 (void) signal(SIGQUIT, Cleanup); 1273#endif 1274 (void) signal(SIGTERM, Cleanup); 1275#ifdef SIGHUP 1276 (void) signal(SIGHUP, Cleanup); 1277#endif 1278 XSetScreenSaver(xparms.d, 8 * 3600, ssInterval, ssPreferBlanking, 1279 ssAllowExposures); 1280 1281 if (drawToFakeServer) { 1282 tileToQuery = 1283 XCreatePixmap(xparms.d, DefaultRootWindow (xparms.d), 32, 32, 1); 1284 } 1285 1286 1287 xparms.foreground = 1288 AllocateColor(xparms.d, foreground, BlackPixel(xparms.d, screen)); 1289 xparms.background = 1290 AllocateColor(xparms.d, background, WhitePixel(xparms.d, screen)); 1291 xparms.ddbackground = 1292 AllocateColor(xparms.d, ddbackground, WhitePixel(xparms.d, screen)); 1293 window_x = 2; 1294 if (DisplayWidth(xparms.d, screen) < WIDTH + window_x + 1) 1295 window_x = -1; 1296 window_y = 2; 1297 if (DisplayHeight(xparms.d, screen) < HEIGHT + window_y + 1) 1298 window_y = -1; 1299 xparms.w = CreatePerfWindow(&xparms, window_x, window_y, WIDTH, HEIGHT); 1300 HSx = WIDTH-1; 1301 if (window_x + 1 + WIDTH > DisplayWidth(xparms.d, screen)) 1302 HSx = DisplayWidth(xparms.d, screen) - (1 + window_x + 1); 1303 HSy = HEIGHT-1; 1304 if (window_y + 1 + HEIGHT > DisplayHeight(xparms.d, screen)) 1305 HSy = DisplayHeight(xparms.d, screen) - (1 + window_y + 1); 1306 status = CreatePerfWindow(&xparms, window_x, HEIGHT+5, WIDTH, 20); 1307 tgcv.foreground = 1308 AllocateColor(xparms.d, "black", BlackPixel(xparms.d, screen)); 1309 tgcv.background = 1310 AllocateColor(xparms.d, "white", WhitePixel(xparms.d, screen)); 1311 tgc = XCreateGC(xparms.d, status, GCForeground | GCBackground, &tgcv); 1312 1313 xparms.p = (Pixmap)0; 1314 1315 if (synchronous) 1316 XSynchronize (xparms.d, True); 1317 1318 /* Get mouse pointer out of the way of the performance window. On 1319 software cursor machines it will slow graphics performance. On 1320 all current MIT-derived servers it will slow window 1321 creation/configuration performance. */ 1322 XWarpPointer(xparms.d, None, status, 0, 0, 0, 0, WIDTH+32, 20+32); 1323 1324 /* Figure out how long to call HardwareSync, so we can adjust for that 1325 in our total elapsed time */ 1326 (void) CalibrateTest(&xparms, &syncTest, 1, &syncTime); 1327 printf("Sync time adjustment is %6.4f msecs.\n\n", syncTime/1000); 1328 1329 ForEachTest (i) { 1330 int child; 1331 char label[200]; 1332 1333 if (doit[i] && (test[i].versions & xparms.version)) { 1334 switch (test[i].testType) { 1335 case NONROP: 1336 /* Simplest...just run it once */ 1337 strcpy (label, LABELP(i)); 1338 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1339 break; 1340 1341 case ROP: 1342 /* Run it through all specified rops and planemasks */ 1343 for (rop = 0; rop < numRops; rop++) { 1344 for (pm = 0; pm < numPlanemasks; pm++) { 1345 if (planemasks[pm] == ~0) { 1346 if (rops[rop] == GXcopy) { 1347 sprintf (label, "%s", LABELP(i)); 1348 } else { 1349 sprintf (label, "(%s) %s", 1350 ropNames[rops[rop]].name, 1351 LABELP(i)); 1352 } 1353 } else { 1354 sprintf (label, "(%s 0x%lx) %s", 1355 ropNames[rops[rop]].name, 1356 planemasks[pm], 1357 LABELP(i)); 1358 } 1359 ProcessTest(&xparms, &test[i], rops[rop], 1360 planemasks[pm], label); 1361 } /* for pm */ 1362 } /* for rop */ 1363 break; 1364 1365 case PLANEMASK: 1366 /* Run it through all specified planemasks */ 1367 for (pm = 0; pm < numPlanemasks; pm++) { 1368 if (planemasks[pm] == ~0) { 1369 sprintf (label, "%s", LABELP(i)); 1370 } else { 1371 sprintf (label, "(0x%lx) %s", 1372 planemasks[pm], 1373 LABELP(i)); 1374 } 1375 ProcessTest(&xparms, &test[i], GXcopy, 1376 planemasks[pm], label); 1377 } /* for pm */ 1378 break; 1379 1380 case WINDOW: 1381 /* Loop through number of children array */ 1382 for (child = 0; child != numSubWindows; child++) { 1383 test[i].parms.objects = subWindows[child]; 1384 sprintf(label, "%s (%d kids)", 1385 LABELP(i), test[i].parms.objects); 1386 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1387 } 1388 break; 1389 case COMP: 1390 /* Loop through the composite operands */ 1391 for (pop = 0; pop < numPops; pop++) { 1392 for (format = 0; format < numFormats; format++) { 1393 if (formats[format] == PictStandardNative) { 1394 if (pops[pop] == PictOpOver) { 1395 sprintf (label, "%s", LABELP(i)); 1396 } else { 1397 sprintf (label, "(%s) %s", 1398 popNames[pops[pop]].name, 1399 LABELP(i)); 1400 } 1401 } else { 1402 const char *name = NameFromFormat (formats[format]); 1403 sprintf (label, "(%s %s) %s", 1404 popNames[pops[pop]].name, 1405 name, 1406 LABELP(i)); 1407 } 1408 ProcessTest (&xparms, &test[i], pops[pop], formats[format], label); 1409 } 1410 } 1411 break; 1412 } /* switch */ 1413 } /* if doit */ 1414 } /* ForEachTest */ 1415 1416 XFreeGC(xparms.d, tgc); 1417 XDestroyWindow(xparms.d, xparms.w); 1418 XFree(vinfolist); 1419 if (drawToFakeServer) 1420 XFreePixmap(xparms.d, tileToQuery); 1421 /* Restore ScreenSaver to original state. */ 1422 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 1423 ssAllowExposures); 1424 XCloseDisplay(xparms.d); 1425 free(saveargv); 1426 free(doit); 1427 exit(0); 1428} 1429 1430static int 1431GetWords (int argi, int argc, char **argv, char **wordsp, int *nump) 1432{ 1433 int count; 1434 1435 if (argc <= argi) 1436 usage(); 1437 count = 0; 1438 while (argv[argi] && *(argv[argi]) != '-') { 1439 *wordsp++ = argv[argi]; 1440 ++argi; 1441 count++; 1442 } 1443 *nump = count; 1444 return count; 1445} 1446 1447static long 1448atox (char *s) 1449{ 1450 long v, c = 0; 1451 1452 v = 0; 1453 while (*s) { 1454 if ('0' <= *s && *s <= '9') 1455 c = *s - '0'; 1456 else if ('a' <= *s && *s <= 'f') 1457 c = *s - 'a' + 10; 1458 else if ('A' <= *s && *s <= 'F') 1459 c = *s - 'A' + 10; 1460 v = v * 16 + c; 1461 s++; 1462 } 1463 return v; 1464} 1465 1466static int 1467GetNumbers (int argi, int argc, char **argv, unsigned long *intsp, int *nump) 1468{ 1469 char *words[256]; 1470 int count; 1471 int i; 1472 int flip; 1473 1474 count = GetWords (argi, argc, argv, words, nump); 1475 for (i = 0; i < count; i++) { 1476 flip = 0; 1477 if (!strncmp (words[i], "~", 1)) { 1478 words[i]++; 1479 flip = ~0; 1480 } 1481 if (!strncmp (words[i], "0x", 2)) 1482 intsp[i] = atox(words[i] + 2) ^ flip; 1483 else 1484 intsp[i] = atoi (words[i]) ^ flip; 1485 } 1486 return count; 1487} 1488 1489static int 1490GetRops (int argi, int argc, char **argv, int *ropsp, int *nump) 1491{ 1492 char *words[256]; 1493 int count; 1494 int i; 1495 int rop; 1496 1497 count = GetWords (argi, argc, argv, words, nump); 1498 for (i = 0; i < count; i++) { 1499 if (!strncmp (words[i], "GX", 2)) 1500 words[i] += 2; 1501 if (!strcmp (words[i], "all")) { 1502 for (i = 0; i < NUM_ROPS; i++) 1503 ropsp[i] = ropNames[i].rop; 1504 *nump = NUM_ROPS; 1505 break; 1506 } 1507 for (rop = 0; rop < NUM_ROPS; rop++) { 1508 if (!strcmp (words[i], ropNames[rop].name)) { 1509 ropsp[i] = ropNames[rop].rop; 1510 break; 1511 } 1512 } 1513 if (rop == NUM_ROPS) { 1514 usage (); 1515 fprintf (stderr, "unknown rop name %s\n", words[i]); 1516 } 1517 } 1518 return count; 1519} 1520 1521static int 1522GetPops (int argi, int argc, char **argv, int *popsp, int *nump) 1523{ 1524 char *words[256]; 1525 int count; 1526 int i; 1527 int pop; 1528 1529 count = GetWords (argi, argc, argv, words, nump); 1530 for (i = 0; i < count; i++) { 1531 if (!strncmp (words[i], "PictOp", 6)) 1532 words[i] += 6; 1533 if (!strcmp (words[i], "all")) { 1534 for (i = 0; i < NUM_POPS; i++) 1535 popsp[i] = popNames[i].rop; 1536 *nump = NUM_POPS; 1537 break; 1538 } 1539 for (pop = 0; pop < NUM_POPS; pop++) { 1540 if (!strcmp (words[i], popNames[pop].name)) { 1541 popsp[i] = popNames[pop].rop; 1542 break; 1543 } 1544 } 1545 if (pop == NUM_POPS) { 1546 usage (); 1547 fprintf (stderr, "unknown picture op name %s\n", words[i]); 1548 } 1549 } 1550 return count; 1551} 1552 1553static int 1554FormatFromName (char *name) 1555{ 1556 int i; 1557 for (i = 0; i < NUM_FORMATS; i++) 1558 if (!strcmp (name, formatNames[i].name)) 1559 return formatNames[i].rop; 1560 return -1; 1561} 1562 1563static const char * 1564NameFromFormat (int format) 1565{ 1566 int i; 1567 for (i = 0; i < NUM_FORMATS; i++) 1568 if (formatNames[i].rop == format) 1569 return formatNames[i].name; 1570 return NULL; 1571} 1572 1573static int 1574GetFormats (int argi, int argc, char **argv, int *formatsp, int *nump) 1575{ 1576 char *words[256]; 1577 int count; 1578 int i; 1579 int format; 1580 1581 count = GetWords (argi, argc, argv, words, nump); 1582 for (i = 0; i < count; i++) { 1583 if (!strcmp (words[i], "all")) { 1584 for (i = 0; i < NUM_FORMATS; i++) 1585 formatsp[i] = formatNames[i].rop; 1586 *nump = NUM_FORMATS; 1587 break; 1588 } 1589 format = FormatFromName (words[i]); 1590 if (format < 0) { 1591 usage (); 1592 fprintf (stderr, "unknown format name %s\n", words[i]); 1593 } 1594 formatsp[i] = format; 1595 } 1596 return count; 1597} 1598