x11perf.c revision 736a7e2c
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 28#ifndef VMS 29#include <X11/Xatom.h> 30#include <X11/Xos.h> 31#else 32#include <decw$include/Xatom.h> 33#endif 34#include "x11perf.h" 35#include <X11/Xmu/SysUtil.h> 36 37#include <time.h> 38#define Time_t time_t 39#include <stdlib.h> 40 41/* Only for working on ``fake'' servers, for hardware that doesn't exist */ 42static Bool drawToFakeServer = False; 43static Bool falsePrecision = False; 44static Pixmap tileToQuery = None; 45static char *displayName; 46int abortTest; 47 48typedef struct _RopNames { char *name; int rop; } RopNameRec, *RopNamePtr; 49 50static RopNameRec ropNames[] = { 51 { "clear", GXclear }, /* 0 */ 52 { "and", GXand }, /* src AND dst */ 53 { "andReverse", GXandReverse }, /* src AND NOT dst */ 54 { "copy", GXcopy }, /* src */ 55 { "andInverted", GXandInverted }, /* NOT src AND dst */ 56 { "noop", GXnoop }, /* dst */ 57 { "xor", GXxor }, /* src XOR dst */ 58 { "or", GXor }, /* src OR dst */ 59 { "nor", GXnor }, /* NOT src AND NOT dst */ 60 { "equiv", GXequiv }, /* NOT src XOR dst */ 61 { "invert", GXinvert }, /* NOT dst */ 62 { "orReverse", GXorReverse }, /* src OR NOT dst */ 63 { "copyInverted", GXcopyInverted }, /* NOT src */ 64 { "orInverted", GXorInverted }, /* NOT src OR dst */ 65 { "nand", GXnand }, /* NOT src OR NOT dst */ 66 { "set", GXset } /* 1 */ 67}; 68 69static RopNameRec popNames[] = { 70 { "Clear", PictOpClear }, 71 { "Src", PictOpSrc }, 72 { "Dst", PictOpDst }, 73 { "Over", PictOpOver }, 74 { "OverReverse", PictOpOverReverse }, 75 { "In", PictOpIn }, 76 { "InReverse", PictOpInReverse }, 77 { "Out", PictOpOut }, 78 { "OutReverse", PictOpOutReverse }, 79 { "Atop", PictOpAtop }, 80 { "AtopReverse", PictOpAtopReverse }, 81 { "Xor", PictOpXor }, 82 { "Add", PictOpAdd }, 83 { "Saturate", PictOpSaturate }, 84}; 85 86static RopNameRec formatNames[] = { 87 { "RGB24", PictStandardRGB24 }, 88 { "ARGB32", PictStandardARGB32 }, 89 { "A8", PictStandardA8 }, 90 { "A4", PictStandardA4 }, 91 { "A1", PictStandardA1 }, 92 { "NATIVE", PictStandardNative }, 93}; 94 95static char *(visualClassNames)[] = { 96 "StaticGray", 97 "GrayScale", 98 "StaticColor", 99 "PseudoColor", 100 "TrueColor", 101 "DirectColor" 102}; 103 104static Bool labels = False; 105static int repeat = 5; 106static int seconds = 5; 107 108static Window status; /* Status window and GC */ 109static GC tgc; 110static int HSx, HSy; 111 112static double syncTime = 0.0; 113 114static int saveargc; 115static char **saveargv; 116 117#define NUM_ROPS 16 118static int numRops = 1; 119static int rops[NUM_ROPS] = { GXcopy }; 120#define NUM_POPS 14 121static int numPops = 1; 122static int pops[NUM_POPS] = { PictOpOver }; 123#define NUM_FORMATS 6 124static int numFormats = 1; 125static int formats[NUM_FORMATS] = { PictStandardNative }; 126static int numPlanemasks = 1; 127static unsigned long planemasks[256] = { (unsigned long)~0 }; 128 129static char *foreground = NULL; 130static char *background = NULL; 131static char *ddbackground = NULL; 132static int clips = 0; 133 134static int numSubWindows = 7; 135static unsigned long subWindows[] = {4, 16, 25, 50, 75, 100, 200, 0}; 136 137static int fixedReps = 0; 138 139static Bool *doit; 140 141static XRectangle ws[] = { /* Clip rectangles */ 142 {195, 195, 120, 120}, 143 { 45, 145, 120, 120}, 144 {345, 245, 120, 120}, 145 { 45, 275, 120, 120}, 146 {345, 115, 120, 120}, 147 {195, 325, 120, 120} 148 149}; 150#define MAXCLIP (sizeof(ws) / sizeof(ws[0])) 151static Window clipWindows[MAXCLIP]; 152static Colormap cmap; 153static int depth = -1; /* -1 means use default depth */ 154static int vclass = -1; /* -1 means use CopyFromParent */ 155 156/* ScreenSaver state */ 157static XParmRec xparms; 158static int ssTimeout, ssInterval, ssPreferBlanking, ssAllowExposures; 159 160/* Static functions */ 161static int GetWords(int argi, int argc, char **argv, char **wordsp, int *nump); 162static int GetNumbers(int argi, int argc, char **argv, unsigned long *intsp, 163 int *nump); 164static int GetRops(int argi, int argc, char **argv, int *ropsp, int *nump); 165static int GetPops(int argi, int argc, char **argv, int *popsp, int *nump); 166static int GetFormats(int argi, int argc, char **argv, int *formatsp, int *nump); 167 168/************************************************ 169* time related stuff * 170************************************************/ 171 172#ifdef VMS 173 174typedef struct _vms_time { 175 unsigned long low; 176 unsigned long high; 177}vms_time; 178 179struct timeval { 180 long tv_sec; /* seconds since Jan. 1, 1970 */ 181 long tv_usec; /* and microseconds */ 182}; 183 184struct timezone { 185 int tz_minuteswest; /* of Greenwich */ 186 int tz_dsttime; /* type of dst correction to apply */ 187}; 188 189 190static int firsttime = True; 191static vms_time basetime; 192 193int gettimeofday(tp) 194 struct timeval *tp; 195{ 196 vms_time current_time, resultant; 197 unsigned long mumble, foo; 198 int status; 199 200 if (firsttime) { 201 sys$gettim(&basetime); 202 firsttime = False; 203 } 204 sys$gettim(¤t_time); 205 resultant.high = current_time.high - basetime.high; 206 resultant.low = current_time.low - basetime.low; 207 if (current_time.low < basetime.low) { 208 resultant.high -= 1; 209 } 210 status = lib$ediv( &(10000000), &resultant, &tp->tv_sec, &tp->tv_usec); 211 tp->tv_usec /= 10; 212 return 0; 213} 214 215#endif 216 217static struct timeval start; 218 219static void 220PrintTime(void) 221{ 222 Time_t t; 223 224 t = time((Time_t *)NULL); 225 printf("%s\n", ctime(&t)); 226} 227 228static void 229InitTimes(void) 230{ 231 X_GETTIMEOFDAY(&start); 232} 233 234static double 235ElapsedTime(double correction) 236{ 237 struct timeval stop; 238 239 X_GETTIMEOFDAY(&stop); 240 if (stop.tv_usec < start.tv_usec) { 241 stop.tv_usec += 1000000; 242 stop.tv_sec -= 1; 243 } 244 return (double)(stop.tv_usec - start.tv_usec) + 245 (1000000.0 * (double)(stop.tv_sec - start.tv_sec)) - correction; 246} 247 248static double 249RoundTo3Digits(double d) 250{ 251 /* It's kind of silly to print out things like ``193658.4/sec'' so just 252 junk all but 3 most significant digits. */ 253 double exponent, sign; 254 255 if (falsePrecision) 256 return d; 257 258 exponent = 1.0; 259 /* the code below won't work if d should happen to be non-positive. */ 260 if (d < 0.0) { 261 d = -d; 262 sign = -1.0; 263 } else 264 sign = 1.0; 265 if (d >= 1000.0) { 266 do { 267 exponent *= 10.0; 268 } while (d/exponent >= 1000.0); 269 d = (double)((int) (d/exponent + 0.5)); 270 d *= exponent; 271 } else { 272 if (d != 0.0) { 273 while (d*exponent < 100.0) { 274 exponent *= 10.0; 275 } 276 } 277 d = (double)((int) (d*exponent + 0.5)); 278 d /= exponent; 279 } 280 return d * sign; 281} 282 283 284static void 285ReportTimes(double usecs, long long n, char *str, int average) 286{ 287 double msecsperobj, objspersec; 288 289 if(usecs != 0.0) 290 { 291 msecsperobj = usecs / (1000.0 * (double)n); 292 objspersec = (double) n * 1000000.0 / usecs; 293 294 /* Round obj/sec to 3 significant digits. Leave msec untouched, to 295 allow averaging results from several repetitions. */ 296 objspersec = RoundTo3Digits(objspersec); 297 298 if (average) { 299 printf("%7lld trep @ %8.4f msec (%8.1f/sec): %s\n", 300 n, msecsperobj, objspersec, str); 301 } else { 302 printf("%7lld reps @ %8.4f msec (%8.1f/sec): %s\n", 303 n, msecsperobj, objspersec, str); 304 } 305 } else { 306 printf("%6lld %sreps @ 0.0 msec (unmeasurably fast): %s\n", 307 n, average ? "t" : "", str); 308 } 309 310} 311 312 313 314/************************************************ 315* Generic X stuff * 316************************************************/ 317 318static char *program_name; 319static void usage(void); 320 321/* 322 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete) 323 * If found, remove it from command line. Don't go past a lone -. 324 */ 325static char * 326Get_Display_Name(int *pargc, /* MODIFIED */ 327 char **argv) /* MODIFIED */ 328{ 329 int argc = *pargc; 330 char **pargv = argv+1; 331 char *displayname = NULL; 332 int i; 333 334 for (i = 1; i != argc; i++) { 335 char *arg = argv[i]; 336 337 if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) { 338 if (++i >= argc) usage (); 339 340 displayname = argv[i]; 341 *pargc -= 2; 342 continue; 343 } 344 if (!strcmp(arg,"-")) { 345 while (i<argc) *pargv++ = argv[i++]; 346 break; 347 } 348 *pargv++ = arg; 349 } 350 351 *pargv = NULL; 352 return (displayname); 353} 354 355 356/* 357 * GetVersion (argc, argv) Look for -v1.2, -v1.3, or -v1.4. 358 * If found remove it from command line. Don't go past a lone -. 359 */ 360 361static Version 362GetVersion(int *pargc, /* MODIFIED */ 363 char **argv) /* MODIFIED */ 364{ 365 int argc = *pargc; 366 char **pargv = argv+1; 367 Version version = VERSION1_6; 368 int i; 369 Bool found = False; 370 371 for (i = 1; i != argc; i++) { 372 char *arg = argv[i]; 373 374 if (!strcmp (arg, "-v1.2")) { 375 version = VERSION1_2; 376 *pargc -= 1; 377 if (found) { 378 fprintf(stderr, "Warning: multiple version specifications\n"); 379 } 380 found = True; 381 continue; 382 } 383 if (!strcmp (arg, "-v1.3")) { 384 version = VERSION1_3; 385 *pargc -= 1; 386 if (found) { 387 fprintf(stderr, "Warning: multiple version specifications\n"); 388 } 389 found = True; 390 continue; 391 } 392 if (!strcmp (arg, "-v1.4")) { 393 version = VERSION1_4; 394 *pargc -= 1; 395 if (found) { 396 fprintf(stderr, "Warning: multiple version specifications\n"); 397 } 398 found = True; 399 continue; 400 } 401 if (!strcmp (arg, "-v1.5")) { 402 version = VERSION1_5; 403 *pargc -= 1; 404 if (found) { 405 fprintf(stderr, "Warning: multiple version specifications\n"); 406 } 407 found = True; 408 continue; 409 } 410 if (!strcmp(arg,"-")) { 411 while (i<argc) *pargv++ = argv[i++]; 412 break; 413 } 414 *pargv++ = arg; 415 } 416 417 *pargv = NULL; 418 return (version); 419} 420 421 422 423/* 424 * Open_Display: Routine to open a display with correct error handling. 425 */ 426static Display * 427Open_Display(char *display_name) 428{ 429 Display *d; 430 431 d = XOpenDisplay(display_name); 432 if (d == NULL) { 433 fprintf (stderr, "%s: unable to open display '%s'\n", 434 program_name, XDisplayName (display_name)); 435 exit(1); 436 } 437 438 return(d); 439} 440 441 442/* defined by autoconf AC_TYPE_SIGNAL, need to define for Imake */ 443#ifndef RETSIGTYPE 444# ifdef SIGNALRETURNSINT 445# define RETSIGTYPE int 446# else 447# define RETSIGTYPE void 448# endif 449#endif 450 451static RETSIGTYPE 452Cleanup(int sig) 453{ 454 abortTest = sig; 455} 456 457void 458AbortTest(void) 459{ 460 fflush(stdout); 461 462 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 463 ssAllowExposures); 464 XFlush(xparms.d); 465 exit (abortTest); 466} 467 468/************************************************ 469* Performance stuff * 470************************************************/ 471 472 473static void 474usage(void) 475{ 476 char **cpp; 477 int i = 0; 478 static char *help_message[] = { 479"where options include:", 480" -display <host:display> the X server to contact", 481" -sync do the tests in synchronous mode", 482" -pack pack rectangles right next to each other", 483" -repeat <n> do tests <n> times (default = 5)", 484" -time <s> do tests for <s> seconds each (default = 5)", 485/* 486" -draw draw after each test -- pmax only", 487*/ 488" -all do all tests", 489" -range <test1>[,<test2>] like all, but do <test1> to <test2>", 490" -labels generate test labels for use by fillblnk", 491" -fg the foreground color to use", 492" -bg the background color to use", 493" -clips <default> default number of clip windows per test", 494" -ddbg the background color to use for DoubleDash", 495" -rop <rop0 rop1 ...> use the given rops to draw (default = GXcopy)", 496" -pm <pm0 pm1 ...> use the given planemasks to draw (default = ~0)", 497" -depth <depth> use a visual with <depth> planes per pixel", 498" -vclass <class> the visual class to use (default = root)", 499" -reps <n> fix the rep count (default = auto scale)", 500" -subs <s0 s1 ...> a list of the number of sub-windows to use", 501" -v1.2 perform only v1.2 tests using old semantics", 502" -v1.3 perform only v1.3 tests using old semantics", 503" -su request save unders on windows", 504" -bs <backing_store_hint> WhenMapped or Always (default = NotUseful)", 505NULL}; 506 507 fflush(stdout); 508 fprintf(stderr, "usage: %s [-options ...]\n", program_name); 509 for (cpp = help_message; *cpp; cpp++) { 510 fprintf(stderr, "%s\n", *cpp); 511 } 512 while (test[i].option != NULL) { 513 if (test[i].versions & xparms.version ) { 514 fprintf(stderr, " %-24s %s\n", 515 test[i].option, 516 test[i].label14 ? test[i].label14 : test[i].label); 517 } 518 i++; 519 } 520 fprintf(stderr, "\n"); 521 522 /* Print out original command line as the above usage message is so long */ 523 for (i = 0; i != saveargc; i++) { 524 fprintf(stderr, "%s ", saveargv[i]); 525 } 526 fprintf(stderr, "\n\n"); 527 exit (1); 528} 529 530void 531NullProc(XParms xp, Parms p) 532{ 533} 534 535int 536NullInitProc(XParms xp, Parms p, int reps) 537{ 538 return reps; 539} 540 541static void 542HardwareSync(XParms xp) 543{ 544 /* 545 * Some graphics hardware allows the server to claim it is done, 546 * while in reality the hardware is busily working away. So fetch 547 * a pixel from the drawable that was drawn to, which should be 548 * enough to make the server wait for the graphics hardware. 549 */ 550 XImage *image; 551 552 image = XGetImage(xp->d, xp->p ? xp->p : xp->w, HSx, HSy, 553 1, 1, ~0, ZPixmap); 554 if (image) XDestroyImage(image); 555} 556 557static void 558DoHardwareSync(XParms xp, Parms p, int reps) 559{ 560 int i; 561 562 for (i = 0; i != reps; i++) { 563 HardwareSync(xp); 564 CheckAbort (); 565 } 566} 567 568static Test syncTest = { 569 "syncTime", "Internal test for finding how long HardwareSync takes", NULL, 570 NullInitProc, DoHardwareSync, NullProc, NullProc, 571 V1_2FEATURE, NONROP, 0, 572 {1} 573}; 574 575 576static Window 577CreatePerfWindow(XParms xp, int x, int y, int width, int height) 578{ 579 XSetWindowAttributes xswa; 580 Window w; 581/* 582 Screen *s; 583 int su; 584 585 s = DefaultScreenOfDisplay(xp->d); 586 su = XDoesBackingStore(s); 587 printf("Backing store of screen returns %d\n", su); 588 su = XDoesSaveUnders(s); 589 printf("Save unders of screen returns %d\n", su); 590 su = XPlanesOfScreen(s); 591 printf("Planes of screen returns %d\n", su); 592*/ 593 xswa.background_pixel = xp->background; 594 xswa.border_pixel = xp->foreground; 595 xswa.colormap = cmap; 596 xswa.override_redirect = True; 597 xswa.backing_store = xp->backing_store; 598 xswa.save_under = xp->save_under; 599 w = XCreateWindow(xp->d, DefaultRootWindow(xp->d), x, y, width, height, 1, 600 xp->vinfo.depth, CopyFromParent, xp->vinfo.visual, 601 CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect 602 | CWBackingStore | CWSaveUnder, &xswa); 603 XMapWindow (xp->d, w); 604 return w; 605} 606 607 608static void 609CreateClipWindows(XParms xp, int clips) 610{ 611 int j; 612 XWindowAttributes xwa; 613 614 (void) XGetWindowAttributes(xp->d, xp->w, &xwa); 615 if (clips > MAXCLIP) clips = MAXCLIP; 616 for (j = 0; j != clips; j++) { 617 clipWindows[j] = CreatePerfWindow(xp, 618 xwa.x + ws[j].x, xwa.y + ws[j].y, ws[j].width, ws[j].height); 619 } 620} /* CreateClipWindows */ 621 622 623static void 624DestroyClipWindows(XParms xp, int clips) 625{ 626 int j; 627 628 if (clips > MAXCLIP) clips = MAXCLIP; 629 for (j = 0; j != clips; j++) { 630 XDestroyWindow(xp->d, clipWindows[j]); 631 } 632} /* DestroyClipWindows */ 633 634 635static double 636DoTest(XParms xp, Test *test, int reps) 637{ 638 double time; 639 unsigned int ret_width, ret_height; 640 641 /* Tell screen-saver to restart counting again. See comments below for the 642 XSetScreenSaver call. */ 643 XForceScreenSaver(xp->d, ScreenSaverReset); 644 HardwareSync (xp); 645 InitTimes (); 646 (*test->proc) (xp, &test->parms, reps); 647 HardwareSync(xp); 648 649 time = ElapsedTime(syncTime); 650 if (time < 0.0) time = 0.0; 651 CheckAbort (); 652 if (drawToFakeServer) 653 XQueryBestSize(xp->d, TileShape, tileToQuery, 654 32, 32, &ret_width, &ret_height); 655 (*test->passCleanup) (xp, &test->parms); 656 return time; 657} 658 659 660static int 661CalibrateTest(XParms xp, Test *test, int seconds, double *usecperobj) 662{ 663#define goal 2500000.0 /* Try to get up to 2.5 seconds */ 664#define enough 2000000.0 /* But settle for 2.0 seconds */ 665#define tick 10000.0 /* Assume clock not faster than .01 seconds */ 666 667 double usecs; 668 int reps, didreps; /* Reps desired, reps performed */ 669 int exponent; 670 671 /* Attempt to get an idea how long each rep lasts by getting enough 672 reps to last more tan enough. Then scale that up to the number of 673 seconds desired. 674 675 If init call to test ever fails, return False and test will be skipped. 676 */ 677 678 if (fixedReps != 0) { 679 return fixedReps; 680 } 681 reps = 1; 682 for (;;) { 683 XDestroySubwindows(xp->d, xp->w); 684 XClearWindow(xp->d, xp->w); 685 didreps = (*test->init) (xp, &test->parms, reps); 686 CheckAbort (); 687 if (didreps == 0) { 688 return 0; 689 } 690 if ( test->clips < clips ) 691 test->clips = clips ; 692 /* Create clip windows if requested */ 693 CreateClipWindows(xp, test->clips); 694 HardwareSync(xp); 695 InitTimes(); 696 (*test->proc) (xp, &test->parms, reps); 697 HardwareSync(xp); 698 usecs = ElapsedTime(syncTime); 699 (*test->passCleanup) (xp, &test->parms); 700 (*test->cleanup) (xp, &test->parms); 701 DestroyClipWindows(xp, test->clips); 702 CheckAbort (); 703 704 if (didreps != reps) { 705 /* The test can't do the number of reps as we asked for. 706 Give up */ 707 *usecperobj = 708 usecs / (double)(didreps * test->parms.objects); 709 return didreps; 710 } 711 /* Did we go long enough? */ 712 if (usecs >= enough) break; 713 714 /* Don't let too short a clock make new reps wildly high */ 715 if (usecs <= tick)reps = reps*10; 716 else{ 717 /* Try to get up to goal seconds. */ 718 reps = (int) (goal * (double)reps / usecs) + 1; 719 } 720 } 721 722 *usecperobj = usecs / (double) (reps * test->parms.objects); 723 reps = (int) ((double)seconds * 1000000.0 * (double)reps / usecs) + 1; 724 725 /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking 726 numbers of repetitions. */ 727 reps--; 728 exponent = 1; 729 while (reps > 9) { 730 reps /= 10; 731 exponent *= 10; 732 } 733 reps = (reps + 1) * exponent; 734 return reps; 735} /* CalibrateTest */ 736 737static void 738CreatePerfGCs(XParms xp, int func, unsigned long pm) 739{ 740 XGCValues gcvfg, gcvbg, gcvddbg,gcvddfg; 741 unsigned long fg, bg, ddbg; 742 743 fg = xp->foreground; 744 bg = xp->background; 745 ddbg = xp->ddbackground; 746 gcvfg.graphics_exposures = False; 747 gcvbg.graphics_exposures = False; 748 gcvddfg.graphics_exposures = False; 749 gcvddbg.graphics_exposures = False; 750 gcvfg.plane_mask = pm; 751 gcvbg.plane_mask = pm; 752 gcvddfg.plane_mask = pm; 753 gcvddbg.plane_mask = pm; 754 gcvfg.function = func; 755 gcvbg.function = func; 756 gcvddfg.function = func; 757 gcvddbg.function = func; 758 759 if (func == GXxor) { 760 /* Make test look good visually if possible */ 761 gcvbg.foreground = gcvfg.foreground = bg ^ fg; 762 gcvbg.background = gcvfg.background = bg; 763 /* Double Dash GCs (This doesn't make a huge amount of sense) */ 764 gcvddbg.foreground = gcvddfg.foreground = bg ^ fg; 765 gcvddbg.background = gcvddfg.foreground = bg ^ ddbg; 766 } else { 767 gcvfg.foreground = fg; 768 gcvfg.background = bg; 769 gcvbg.foreground = bg; 770 gcvbg.background = fg; 771 gcvddfg.foreground = fg; 772 gcvddfg.background = ddbg; 773 gcvddbg.foreground = ddbg; 774 gcvddbg.background = fg; 775 } 776 xp->fggc = XCreateGC(xp->d, xp->w, 777 GCForeground | GCBackground | GCGraphicsExposures 778 | GCFunction | GCPlaneMask, &gcvfg); 779 xp->bggc = XCreateGC(xp->d, xp->w, 780 GCForeground | GCBackground | GCGraphicsExposures 781 | GCFunction | GCPlaneMask, &gcvbg); 782 xp->ddfggc = XCreateGC(xp->d, xp->w, 783 GCForeground | GCBackground | GCGraphicsExposures 784 | GCFunction | GCPlaneMask, &gcvddfg); 785 xp->ddbggc = XCreateGC(xp->d, xp->w, 786 GCForeground | GCBackground | GCGraphicsExposures 787 | GCFunction | GCPlaneMask, &gcvddbg); 788} 789 790 791static void 792DestroyPerfGCs(XParms xp) 793{ 794 XFreeGC(xp->d, xp->fggc); 795 XFreeGC(xp->d, xp->bggc); 796 XFreeGC(xp->d, xp->ddfggc); 797 XFreeGC(xp->d, xp->ddbggc); 798} 799 800static unsigned long 801AllocateColor(Display *display, char *name, unsigned long pixel) 802{ 803 XColor color; 804 805 if (name != NULL) { 806 /* Try to parse color name */ 807 if (XParseColor(display, cmap, name, &color)) { 808 if (XAllocColor(display, cmap, &color)) { 809 pixel = color.pixel; 810 } else { 811 (void) fprintf(stderr, 812 "Can't allocate colormap entry for color %s\n", name); 813 } 814 } else { 815 if(*name >= '0' && *name <= '9') 816 pixel = atoi(name); 817 else 818 (void) fprintf(stderr, "Can't parse color name %s\n", name); 819 } 820 } 821 return pixel; 822} /* AllocateColor */ 823 824 825static void 826DisplayStatus(Display *d, char *message, char *test, int try) 827{ 828 char s[500]; 829 830 XClearWindow(d, status); 831 sprintf(s, "%d %s %s", try, message, test); 832 /* We should really look at the height, descent of the font, etc. but 833 who cares. This works. */ 834 XDrawString(d, status, tgc, 10, 13, s, strlen(s)); 835} 836 837 838static void 839ProcessTest(XParms xp, Test *test, int func, unsigned long pm, char *label) 840{ 841 double time, totalTime; 842 long long reps; 843 int j; 844 845 xp->planemask = pm; 846 xp->func = func; 847 if (test->testType == COMP) 848 { 849 func = GXcopy; 850 pm = ~0L; 851 } 852 CreatePerfGCs(xp, func, pm); 853 DisplayStatus(xp->d, "Calibrating", label, 0); 854 reps = CalibrateTest(xp, test, seconds, &time); 855 if (reps != 0) { 856 srand(1); /* allow reproducible results */ 857 XDestroySubwindows(xp->d, xp->w); 858 XClearWindow(xp->d, xp->w); 859 reps = (*test->init) (xp, &test->parms, reps); 860 if (abortTest) 861 AbortTest (); 862 /* 863 * if using fixedReps then will not have done CalibrateTest so must 864 * check result of init for 0 here 865 */ 866 if(reps == 0){ 867 DestroyPerfGCs(xp); 868 return; 869 } 870 /* Create clip windows if requested */ 871 CreateClipWindows(xp, test->clips); 872 873 totalTime = 0.0; 874 for (j = 0; j != repeat; j++) { 875 DisplayStatus(xp->d, "Testing", label, j+1); 876 time = DoTest(xp, test, reps); 877 if (abortTest) 878 AbortTest (); 879 totalTime += time; 880 ReportTimes (time, reps * test->parms.objects, 881 label, False); 882 } 883 if (repeat > 1) { 884 ReportTimes(totalTime, 885 repeat * reps * test->parms.objects, 886 label, True); 887 } 888 (*test->cleanup) (xp, &test->parms); 889 DestroyClipWindows(xp, test->clips); 890 } else { 891 /* Test failed to initialize properly */ 892 } 893 printf ("\n"); 894 fflush(stdout); 895 DestroyPerfGCs(xp); 896} /* ProcessTest */ 897 898#define Strstr strstr 899 900#define LABELP(i) (test[i].label14 && (xparms.version >= VERSION1_4) \ 901 ? test[i].label14 : test[i].label) 902 903int 904main(int argc, char *argv[]) 905{ 906 int i, j, n, skip; 907 int numTests; /* Even though the linker knows, we don't. */ 908 char hostname[100]; 909 Bool foundOne = False; 910 Bool synchronous = False; 911 XGCValues tgcv; 912 int screen; 913 int rop, pm; 914 int pop, format; 915 int window_y, window_x; 916 XVisualInfo *vinfolist, vinfotempl; 917 unsigned long vmask; 918 919 /* Save away argv, argc, for usage to print out */ 920 saveargc = argc; 921 saveargv = (char **) malloc(argc * sizeof(char *)); 922 for (i = 0; i != argc; i++) { 923 saveargv[i] = argv[i]; 924 } 925 926 xparms.pack = False; 927 xparms.save_under = False; 928 xparms.backing_store = NotUseful; 929 930 /* Count number of tests */ 931 ForEachTest(numTests); 932 doit = (Bool *)calloc(numTests, sizeof(Bool)); 933 934 /* Parse arguments */ 935 program_name = argv[0]; 936 displayName = Get_Display_Name (&argc, argv); 937 xparms.version = GetVersion(&argc, argv); 938 for (i = 1; i != argc; i++) { 939 if (strcmp (argv[i], "-all") == 0) { 940 ForEachTest (j) 941 doit[j] = test[j].versions & xparms.version; 942 foundOne = True; 943 } else if (strcmp (argv[i], "-labels") == 0) { 944 labels = True; 945 } else if (strcmp(argv[i], "-range") == 0) { 946 char *cp1; 947 char *cp2; 948 949 if (argc <= ++i) 950 usage(); 951 cp1 = argv[i]; 952 if (*cp1 == '-') 953 cp1++; 954 for (cp2 = cp1; *cp2 != '\0' && *cp2 != ','; cp2++) {}; 955 if (*cp2 == ',') { 956 *cp2++ = '\0'; 957 if (*cp2 == '-') 958 cp2++; 959 } else { 960 cp2 = "-"; 961 } 962 ForEachTest (j) { 963 if (strcmp (cp1, (test[j].option) + 1) == 0 && 964 (test[j].versions & xparms.version)) { 965 int k = j; 966 do { 967 doit[k] = test[j].versions & xparms.version; 968 } while (!(strcmp(cp2, (test[k].option + 1)) == 0 && 969 (test[k].versions & xparms.version)) && 970 test[++k].option != NULL); 971 if (*cp2 != '-' && test[k].option == NULL) 972 usage(); 973 break; 974 } 975 } 976 if (test[j].option == NULL) 977 usage(); 978 foundOne = True; 979 } else if (strcmp (argv[i], "-sync") == 0) { 980 synchronous = True; 981 } else if (strcmp (argv[i], "-pack") == 0) { 982 xparms.pack = True; 983 } else if (strcmp (argv[i], "-draw") == 0) { 984 drawToFakeServer = True; 985 } else if (strcmp (argv[i], "-falseprecision") == 0) { 986 falsePrecision = True; 987 } else if (strcmp (argv[i], "-repeat") == 0) { 988 i++; 989 if (argc <= i) 990 usage (); 991 repeat = atoi (argv[i]); 992 if (repeat <= 0) 993 usage (); 994 } else if (strcmp (argv[i], "-time") == 0) { 995 i++; 996 if (argc <= i) 997 usage (); 998 seconds = atoi (argv[i]); 999 if (seconds <= 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 sprintf (label, "(%s %s) %s", 1403 popNames[pops[pop]].name, 1404 formatNames[formats[format]].name, 1405 LABELP(i)); 1406 } 1407 ProcessTest (&xparms, &test[i], pops[pop], formats[format], label); 1408 } 1409 } 1410 break; 1411 } /* switch */ 1412 } /* if doit */ 1413 } /* ForEachTest */ 1414 1415 XFreeGC(xparms.d, tgc); 1416 XDestroyWindow(xparms.d, xparms.w); 1417 XFree(vinfolist); 1418 if (drawToFakeServer) 1419 XFreePixmap(xparms.d, tileToQuery); 1420 /* Restore ScreenSaver to original state. */ 1421 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 1422 ssAllowExposures); 1423 XCloseDisplay(xparms.d); 1424 free(saveargv); 1425 free(doit); 1426 exit(0); 1427} 1428 1429static int 1430GetWords (int argi, int argc, char **argv, char **wordsp, int *nump) 1431{ 1432 int count; 1433 1434 if (argc <= argi) 1435 usage(); 1436 count = 0; 1437 while (argv[argi] && *(argv[argi]) != '-') { 1438 *wordsp++ = argv[argi]; 1439 ++argi; 1440 count++; 1441 } 1442 *nump = count; 1443 return count; 1444} 1445 1446static long 1447atox (char *s) 1448{ 1449 long v, c = 0; 1450 1451 v = 0; 1452 while (*s) { 1453 if ('0' <= *s && *s <= '9') 1454 c = *s - '0'; 1455 else if ('a' <= *s && *s <= 'f') 1456 c = *s - 'a' + 10; 1457 else if ('A' <= *s && *s <= 'F') 1458 c = *s - 'A' + 10; 1459 v = v * 16 + c; 1460 s++; 1461 } 1462 return v; 1463} 1464 1465static int 1466GetNumbers (int argi, int argc, char **argv, unsigned long *intsp, int *nump) 1467{ 1468 char *words[256]; 1469 int count; 1470 int i; 1471 int flip; 1472 1473 count = GetWords (argi, argc, argv, words, nump); 1474 for (i = 0; i < count; i++) { 1475 flip = 0; 1476 if (!strncmp (words[i], "~", 1)) { 1477 words[i]++; 1478 flip = ~0; 1479 } 1480 if (!strncmp (words[i], "0x", 2)) 1481 intsp[i] = atox(words[i] + 2) ^ flip; 1482 else 1483 intsp[i] = atoi (words[i]) ^ flip; 1484 } 1485 return count; 1486} 1487 1488static int 1489GetRops (int argi, int argc, char **argv, int *ropsp, int *nump) 1490{ 1491 char *words[256]; 1492 int count; 1493 int i; 1494 int rop; 1495 1496 count = GetWords (argi, argc, argv, words, nump); 1497 for (i = 0; i < count; i++) { 1498 if (!strncmp (words[i], "GX", 2)) 1499 words[i] += 2; 1500 if (!strcmp (words[i], "all")) { 1501 for (i = 0; i < NUM_ROPS; i++) 1502 ropsp[i] = ropNames[i].rop; 1503 *nump = NUM_ROPS; 1504 break; 1505 } 1506 for (rop = 0; rop < NUM_ROPS; rop++) { 1507 if (!strcmp (words[i], ropNames[rop].name)) { 1508 ropsp[i] = ropNames[rop].rop; 1509 break; 1510 } 1511 } 1512 if (rop == NUM_ROPS) { 1513 usage (); 1514 fprintf (stderr, "unknown rop name %s\n", words[i]); 1515 } 1516 } 1517 return count; 1518} 1519 1520static int 1521GetPops (int argi, int argc, char **argv, int *popsp, int *nump) 1522{ 1523 char *words[256]; 1524 int count; 1525 int i; 1526 int pop; 1527 1528 count = GetWords (argi, argc, argv, words, nump); 1529 for (i = 0; i < count; i++) { 1530 if (!strncmp (words[i], "PictOp", 6)) 1531 words[i] += 6; 1532 if (!strcmp (words[i], "all")) { 1533 for (i = 0; i < NUM_POPS; i++) 1534 popsp[i] = popNames[i].rop; 1535 *nump = NUM_POPS; 1536 break; 1537 } 1538 for (pop = 0; pop < NUM_POPS; pop++) { 1539 if (!strcmp (words[i], popNames[pop].name)) { 1540 popsp[i] = popNames[pop].rop; 1541 break; 1542 } 1543 } 1544 if (pop == NUM_POPS) { 1545 usage (); 1546 fprintf (stderr, "unknown picture op name %s\n", words[i]); 1547 } 1548 } 1549 return count; 1550} 1551 1552static int 1553GetFormats (int argi, int argc, char **argv, int *formatsp, int *nump) 1554{ 1555 char *words[256]; 1556 int count; 1557 int i; 1558 int format; 1559 1560 count = GetWords (argi, argc, argv, words, nump); 1561 for (i = 0; i < count; i++) { 1562 if (!strcmp (words[i], "all")) { 1563 for (i = 0; i < NUM_FORMATS; i++) 1564 formatsp[i] = formatNames[i].rop; 1565 *nump = NUM_FORMATS; 1566 break; 1567 } 1568 for (format = 0; format < NUM_FORMATS; format++) { 1569 if (!strcmp (words[i], formatNames[format].name)) { 1570 formatsp[i] = formatNames[format].rop; 1571 break; 1572 } 1573 } 1574 if (format == NUM_FORMATS) { 1575 usage (); 1576 fprintf (stderr, "unknown format name %s\n", words[i]); 1577 } 1578 } 1579 return count; 1580} 1581