x11perf.c revision c37a63b8
1/* $Xorg: x11perf.c,v 1.4 2000/08/17 19:54:10 cpqbld Exp $ */ 2/* $XdotOrg: app/x11perf/x11perf.c,v 1.3 2005/07/26 18:55:42 alanc Exp $ */ 3/**************************************************************************** 4Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 5 6 All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and its 9documentation for any purpose and without fee is hereby granted, 10provided that the above copyright notice appear in all copies and that 11both that copyright notice and this permission notice appear in 12supporting documentation, and that the name of Digital not be 13used in advertising or publicity pertaining to distribution of the 14software without specific, written prior permission. 15 16DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 17ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 18DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 19ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 20WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 22SOFTWARE. 23 24****************************************************************************/ 25/* $XFree86: xc/programs/x11perf/x11perf.c,v 3.6 2001/11/03 21:59:20 dawes Exp $ */ 26 27#include <stdio.h> 28#include <ctype.h> 29#include <signal.h> 30 31#ifndef VMS 32#include <X11/Xatom.h> 33#include <X11/Xos.h> 34#else 35#include <decw$include/Xatom.h> 36#endif 37#include "x11perf.h" 38#include <X11/Xmu/SysUtil.h> 39 40#include <time.h> 41#define Time_t time_t 42#include <stdlib.h> 43 44/* Only for working on ``fake'' servers, for hardware that doesn't exist */ 45static Bool drawToFakeServer = False; 46static Pixmap tileToQuery = None; 47static char *displayName; 48int abortTest; 49 50typedef struct _RopNames { char *name; int rop; } RopNameRec, *RopNamePtr; 51 52static RopNameRec ropNames[] = { 53 { "clear", GXclear }, /* 0 */ 54 { "and", GXand }, /* src AND dst */ 55 { "andReverse", GXandReverse }, /* src AND NOT dst */ 56 { "copy", GXcopy }, /* src */ 57 { "andInverted", GXandInverted }, /* NOT src AND dst */ 58 { "noop", GXnoop }, /* dst */ 59 { "xor", GXxor }, /* src XOR dst */ 60 { "or", GXor }, /* src OR dst */ 61 { "nor", GXnor }, /* NOT src AND NOT dst */ 62 { "equiv", GXequiv }, /* NOT src XOR dst */ 63 { "invert", GXinvert }, /* NOT dst */ 64 { "orReverse", GXorReverse }, /* src OR NOT dst */ 65 { "copyInverted", GXcopyInverted }, /* NOT src */ 66 { "orInverted", GXorInverted }, /* NOT src OR dst */ 67 { "nand", GXnand }, /* NOT src OR NOT dst */ 68 { "set", GXset } /* 1 */ 69}; 70 71static RopNameRec popNames[] = { 72 { "Clear", PictOpClear }, 73 { "Src", PictOpSrc }, 74 { "Dst", PictOpDst }, 75 { "Over", PictOpOver }, 76 { "OverReverse", PictOpOverReverse }, 77 { "In", PictOpIn }, 78 { "InReverse", PictOpInReverse }, 79 { "Out", PictOpOut }, 80 { "OutReverse", PictOpOutReverse }, 81 { "Atop", PictOpAtop }, 82 { "AtopReverse", PictOpAtopReverse }, 83 { "Xor", PictOpXor }, 84 { "Add", PictOpAdd }, 85 { "Saturate", PictOpSaturate }, 86}; 87 88static RopNameRec formatNames[] = { 89 { "RGB24", PictStandardRGB24 }, 90 { "ARGB32", PictStandardARGB32 }, 91 { "A8", PictStandardA8 }, 92 { "A4", PictStandardA4 }, 93 { "A1", PictStandardA1 }, 94 { "NATIVE", PictStandardNative }, 95}; 96 97static char *(visualClassNames)[] = { 98 "StaticGray", 99 "GrayScale", 100 "StaticColor", 101 "PseudoColor", 102 "TrueColor", 103 "DirectColor" 104}; 105 106static Bool labels = False; 107static int repeat = 5; 108static int seconds = 5; 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 char *foreground = NULL; 132static char *background = NULL; 133static 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); 169 170/************************************************ 171* time related stuff * 172************************************************/ 173 174#ifdef VMS 175 176typedef struct _vms_time { 177 unsigned long low; 178 unsigned long high; 179}vms_time; 180 181struct timeval { 182 long tv_sec; /* seconds since Jan. 1, 1970 */ 183 long tv_usec; /* and microseconds */ 184}; 185 186struct timezone { 187 int tz_minuteswest; /* of Greenwich */ 188 int tz_dsttime; /* type of dst correction to apply */ 189}; 190 191 192static int firsttime = True; 193static vms_time basetime; 194 195int gettimeofday(tp) 196 struct timeval *tp; 197{ 198 vms_time current_time, resultant; 199 unsigned long mumble, foo; 200 int status; 201 202 if (firsttime) { 203 sys$gettim(&basetime); 204 firsttime = False; 205 } 206 sys$gettim(¤t_time); 207 resultant.high = current_time.high - basetime.high; 208 resultant.low = current_time.low - basetime.low; 209 if (current_time.low < basetime.low) { 210 resultant.high -= 1; 211 } 212 status = lib$ediv( &(10000000), &resultant, &tp->tv_sec, &tp->tv_usec); 213 tp->tv_usec /= 10; 214 return 0; 215} 216 217#endif 218 219static struct timeval start; 220 221static void 222PrintTime(void) 223{ 224 Time_t t; 225 226 t = time((Time_t *)NULL); 227 printf("%s\n", ctime(&t)); 228} 229 230static void 231InitTimes(void) 232{ 233 X_GETTIMEOFDAY(&start); 234} 235 236static double 237ElapsedTime(double correction) 238{ 239 struct timeval stop; 240 241 X_GETTIMEOFDAY(&stop); 242 if (stop.tv_usec < start.tv_usec) { 243 stop.tv_usec += 1000000; 244 stop.tv_sec -= 1; 245 } 246 return (double)(stop.tv_usec - start.tv_usec) + 247 (1000000.0 * (double)(stop.tv_sec - start.tv_sec)) - correction; 248} 249 250static double 251RoundTo3Digits(double d) 252{ 253 /* It's kind of silly to print out things like ``193658.4/sec'' so just 254 junk all but 3 most significant digits. */ 255 256 double exponent, sign; 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, int 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("%7d trep @ %8.4f msec (%8.1f/sec): %s\n", 300 n, msecsperobj, objspersec, str); 301 } else { 302 printf("%7d reps @ %8.4f msec (%8.1f/sec): %s\n", 303 n, msecsperobj, objspersec, str); 304 } 305 } else { 306 printf("%6d %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 CheckAbort (); 651 if (drawToFakeServer) 652 XQueryBestSize(xp->d, TileShape, tileToQuery, 653 32, 32, &ret_width, &ret_height); 654 (*test->passCleanup) (xp, &test->parms); 655 return time; 656} 657 658 659static int 660CalibrateTest(XParms xp, Test *test, int seconds, double *usecperobj) 661{ 662#define goal 2500000.0 /* Try to get up to 2.5 seconds */ 663#define enough 2000000.0 /* But settle for 2.0 seconds */ 664#define tick 10000.0 /* Assume clock not faster than .01 seconds */ 665 666 double usecs; 667 int reps, didreps; /* Reps desired, reps performed */ 668 int exponent; 669 670 /* Attempt to get an idea how long each rep lasts by getting enough 671 reps to last more tan enough. Then scale that up to the number of 672 seconds desired. 673 674 If init call to test ever fails, return False and test will be skipped. 675 */ 676 677 if (fixedReps != 0) { 678 return fixedReps; 679 } 680 reps = 1; 681 for (;;) { 682 XDestroySubwindows(xp->d, xp->w); 683 XClearWindow(xp->d, xp->w); 684 didreps = (*test->init) (xp, &test->parms, reps); 685 CheckAbort (); 686 if (didreps == 0) { 687 return 0; 688 } 689 if ( test->clips < clips ) 690 test->clips = clips ; 691 /* Create clip windows if requested */ 692 CreateClipWindows(xp, test->clips); 693 HardwareSync(xp); 694 InitTimes(); 695 (*test->proc) (xp, &test->parms, reps); 696 HardwareSync(xp); 697 usecs = ElapsedTime(syncTime); 698 (*test->passCleanup) (xp, &test->parms); 699 (*test->cleanup) (xp, &test->parms); 700 DestroyClipWindows(xp, test->clips); 701 CheckAbort (); 702 703 if (didreps != reps) { 704 /* The test can't do the number of reps as we asked for. 705 Give up */ 706 *usecperobj = 707 usecs / (double)(didreps * test->parms.objects); 708 return didreps; 709 } 710 /* Did we go long enough? */ 711 if (usecs >= enough) break; 712 713 /* Don't let too short a clock make new reps wildly high */ 714 if (usecs <= tick)reps = reps*10; 715 else{ 716 /* Try to get up to goal seconds. */ 717 reps = (int) (goal * (double)reps / usecs) + 1; 718 } 719 } 720 721 *usecperobj = usecs / (double) (reps * test->parms.objects); 722 reps = (int) ((double)seconds * 1000000.0 * (double)reps / usecs) + 1; 723 724 /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking 725 numbers of repetitions. */ 726 reps--; 727 exponent = 1; 728 while (reps > 9) { 729 reps /= 10; 730 exponent *= 10; 731 } 732 reps = (reps + 1) * exponent; 733 return reps; 734} /* CalibrateTest */ 735 736static void 737CreatePerfGCs(XParms xp, int func, unsigned long pm) 738{ 739 XGCValues gcvfg, gcvbg, gcvddbg,gcvddfg; 740 unsigned long fg, bg, ddbg; 741 742 fg = xp->foreground; 743 bg = xp->background; 744 ddbg = xp->ddbackground; 745 gcvfg.graphics_exposures = False; 746 gcvbg.graphics_exposures = False; 747 gcvddfg.graphics_exposures = False; 748 gcvddbg.graphics_exposures = False; 749 gcvfg.plane_mask = pm; 750 gcvbg.plane_mask = pm; 751 gcvddfg.plane_mask = pm; 752 gcvddbg.plane_mask = pm; 753 gcvfg.function = func; 754 gcvbg.function = func; 755 gcvddfg.function = func; 756 gcvddbg.function = func; 757 758 if (func == GXxor) { 759 /* Make test look good visually if possible */ 760 gcvbg.foreground = gcvfg.foreground = bg ^ fg; 761 gcvbg.background = gcvfg.background = bg; 762 /* Double Dash GCs (This doesn't make a huge amount of sense) */ 763 gcvddbg.foreground = gcvddfg.foreground = bg ^ fg; 764 gcvddbg.background = gcvddfg.foreground = bg ^ ddbg; 765 } else { 766 gcvfg.foreground = fg; 767 gcvfg.background = bg; 768 gcvbg.foreground = bg; 769 gcvbg.background = fg; 770 gcvddfg.foreground = fg; 771 gcvddfg.background = ddbg; 772 gcvddbg.foreground = ddbg; 773 gcvddbg.background = fg; 774 } 775 xp->fggc = XCreateGC(xp->d, xp->w, 776 GCForeground | GCBackground | GCGraphicsExposures 777 | GCFunction | GCPlaneMask, &gcvfg); 778 xp->bggc = XCreateGC(xp->d, xp->w, 779 GCForeground | GCBackground | GCGraphicsExposures 780 | GCFunction | GCPlaneMask, &gcvbg); 781 xp->ddfggc = XCreateGC(xp->d, xp->w, 782 GCForeground | GCBackground | GCGraphicsExposures 783 | GCFunction | GCPlaneMask, &gcvddfg); 784 xp->ddbggc = XCreateGC(xp->d, xp->w, 785 GCForeground | GCBackground | GCGraphicsExposures 786 | GCFunction | GCPlaneMask, &gcvddbg); 787} 788 789 790static void 791DestroyPerfGCs(XParms xp) 792{ 793 XFreeGC(xp->d, xp->fggc); 794 XFreeGC(xp->d, xp->bggc); 795 XFreeGC(xp->d, xp->ddfggc); 796 XFreeGC(xp->d, xp->ddbggc); 797} 798 799static unsigned long 800AllocateColor(Display *display, char *name, unsigned long pixel) 801{ 802 XColor color; 803 804 if (name != NULL) { 805 /* Try to parse color name */ 806 if (XParseColor(display, cmap, name, &color)) { 807 if (XAllocColor(display, cmap, &color)) { 808 pixel = color.pixel; 809 } else { 810 (void) fprintf(stderr, 811 "Can't allocate colormap entry for color %s\n", name); 812 } 813 } else { 814 if(*name >= '0' && *name <= '9') 815 pixel = atoi(name); 816 else 817 (void) fprintf(stderr, "Can't parse color name %s\n", name); 818 } 819 } 820 return pixel; 821} /* AllocateColor */ 822 823 824static void 825DisplayStatus(Display *d, char *message, char *test, int try) 826{ 827 char s[500]; 828 829 XClearWindow(d, status); 830 sprintf(s, "%d %s %s", try, message, test); 831 /* We should really look at the height, descent of the font, etc. but 832 who cares. This works. */ 833 XDrawString(d, status, tgc, 10, 13, s, strlen(s)); 834} 835 836 837static void 838ProcessTest(XParms xp, Test *test, int func, unsigned long pm, char *label) 839{ 840 double time, totalTime; 841 int reps; 842 int j; 843 844 xp->planemask = pm; 845 xp->func = func; 846 if (test->testType == COMP) 847 { 848 func = GXcopy; 849 pm = ~0L; 850 } 851 CreatePerfGCs(xp, func, pm); 852 DisplayStatus(xp->d, "Calibrating", label, 0); 853 reps = CalibrateTest(xp, test, seconds, &time); 854 if (reps != 0) { 855 srand(1); /* allow reproducible results */ 856 XDestroySubwindows(xp->d, xp->w); 857 XClearWindow(xp->d, xp->w); 858 reps = (*test->init) (xp, &test->parms, reps); 859 if (abortTest) 860 AbortTest (); 861 /* 862 * if using fixedReps then will not have done CalibrateTest so must 863 * check result of init for 0 here 864 */ 865 if(reps == 0){ 866 DestroyPerfGCs(xp); 867 return; 868 } 869 /* Create clip windows if requested */ 870 CreateClipWindows(xp, test->clips); 871 872 totalTime = 0.0; 873 for (j = 0; j != repeat; j++) { 874 DisplayStatus(xp->d, "Testing", label, j+1); 875 time = DoTest(xp, test, reps); 876 if (abortTest) 877 AbortTest (); 878 totalTime += time; 879 ReportTimes (time, reps * test->parms.objects, 880 label, False); 881 } 882 if (repeat > 1) { 883 ReportTimes(totalTime, 884 repeat * reps * test->parms.objects, 885 label, True); 886 } 887 (*test->cleanup) (xp, &test->parms); 888 DestroyClipWindows(xp, test->clips); 889 } else { 890 /* Test failed to initialize properly */ 891 } 892 printf ("\n"); 893 fflush(stdout); 894 DestroyPerfGCs(xp); 895} /* ProcessTest */ 896 897#define Strstr strstr 898 899#define LABELP(i) (test[i].label14 && (xparms.version >= VERSION1_4) \ 900 ? test[i].label14 : test[i].label) 901 902int 903main(int argc, char *argv[]) 904{ 905 int i, j, n, skip; 906 int numTests; /* Even though the linker knows, we don't. */ 907 char hostname[100]; 908 Bool foundOne = False; 909 Bool synchronous = False; 910 XGCValues tgcv; 911 int screen; 912 int rop, pm; 913 int pop, format; 914 int window_y, window_x; 915 XVisualInfo *vinfolist, vinfotempl; 916 unsigned long vmask; 917 918 /* Save away argv, argc, for usage to print out */ 919 saveargc = argc; 920 saveargv = (char **) malloc(argc * sizeof(char *)); 921 for (i = 0; i != argc; i++) { 922 saveargv[i] = argv[i]; 923 } 924 925 xparms.pack = False; 926 xparms.save_under = False; 927 xparms.backing_store = NotUseful; 928 929 /* Count number of tests */ 930 ForEachTest(numTests); 931 doit = (Bool *)calloc(numTests, sizeof(Bool)); 932 933 /* Parse arguments */ 934 program_name = argv[0]; 935 displayName = Get_Display_Name (&argc, argv); 936 xparms.version = GetVersion(&argc, argv); 937 for (i = 1; i != argc; i++) { 938 if (strcmp (argv[i], "-all") == 0) { 939 ForEachTest (j) 940 doit[j] = test[j].versions & xparms.version; 941 foundOne = True; 942 } else if (strcmp (argv[i], "-labels") == 0) { 943 labels = True; 944 } else if (strcmp(argv[i], "-range") == 0) { 945 char *cp1; 946 char *cp2; 947 948 if (argc <= ++i) 949 usage(); 950 cp1 = argv[i]; 951 if (*cp1 == '-') 952 cp1++; 953 for (cp2 = cp1; *cp2 != '\0' && *cp2 != ','; cp2++) {}; 954 if (*cp2 == ',') { 955 *cp2++ = '\0'; 956 if (*cp2 == '-') 957 cp2++; 958 } else { 959 cp2 = "-"; 960 } 961 ForEachTest (j) { 962 if (strcmp (cp1, (test[j].option) + 1) == 0 && 963 (test[j].versions & xparms.version)) { 964 int k = j; 965 do { 966 doit[k] = test[j].versions & xparms.version; 967 } while (!(strcmp(cp2, (test[k].option + 1)) == 0 && 968 (test[k].versions & xparms.version)) && 969 test[++k].option != NULL); 970 if (*cp2 != '-' && test[k].option == NULL) 971 usage(); 972 break; 973 } 974 } 975 if (test[j].option == NULL) 976 usage(); 977 foundOne = True; 978 } else if (strcmp (argv[i], "-sync") == 0) { 979 synchronous = True; 980 } else if (strcmp(argv[i], "-pack") == 0) { 981 xparms.pack = True; 982 } else if (strcmp (argv[i], "-draw") == 0) { 983 drawToFakeServer = True; 984 } else if (strcmp (argv[i], "-repeat") == 0) { 985 i++; 986 if (argc <= i) 987 usage (); 988 repeat = atoi (argv[i]); 989 if (repeat <= 0) 990 usage (); 991 } else if (strcmp (argv[i], "-time") == 0) { 992 i++; 993 if (argc <= i) 994 usage (); 995 seconds = atoi (argv[i]); 996 if (seconds <= 0) 997 usage (); 998 } else if (strcmp(argv[i], "-fg") == 0) { 999 i++; 1000 if (argc <= i) 1001 usage (); 1002 foreground = argv[i]; 1003 } else if (strcmp(argv[i], "-bg") == 0) { 1004 i++; 1005 if (argc <= i) 1006 usage (); 1007 background = argv[i]; 1008 if(ddbackground == NULL) 1009 ddbackground = argv[i]; 1010 } else if (strcmp(argv[i], "-clips") == 0 ) { 1011 i++; 1012 if (argc <= i) 1013 usage (); 1014 clips = atoi( argv[i] ); 1015 } else if (strcmp(argv[i], "-ddbg") == 0) { 1016 if (argc <= i) 1017 usage (); 1018 i++; 1019 ddbackground = argv[i]; 1020 } else if (strcmp(argv[i], "-rop") == 0) { 1021 skip = GetRops (i+1, argc, argv, rops, &numRops); 1022 i += skip; 1023 } else if (strcmp(argv[i], "-pop") == 0) { 1024 skip = GetPops (i+1, argc, argv, pops, &numPops); 1025 i += skip; 1026 } else if (strcmp(argv[i], "-format") == 0) { 1027 skip = GetFormats (i+1, argc, argv, formats, &numFormats); 1028 i += skip; 1029 } else if (strcmp(argv[i], "-pm") == 0) { 1030 skip = GetNumbers (i+1, argc, argv, planemasks, &numPlanemasks); 1031 i += skip; 1032 } else if (strcmp(argv[i], "-xor") == 0) { 1033 numRops = 1; 1034 rops[0] = GXxor; 1035 } else if (strcmp (argv[i], "-both") == 0) { 1036 numRops = 2; 1037 rops[0] = GXcopy; 1038 rops[1] = GXxor; 1039 } else if (strcmp(argv[i], "-reps") == 0) { 1040 i++; 1041 if (argc <= i) 1042 usage (); 1043 fixedReps = atoi (argv[i]); 1044 if (fixedReps <= 0) 1045 usage (); 1046 } else if (strcmp(argv[i], "-depth") == 0) { 1047 i++; 1048 if (argc <= i) 1049 usage (); 1050 depth = atoi(argv[i]); 1051 if (depth <= 0) 1052 usage (); 1053 } else if (strcmp(argv[i], "-vclass") == 0) { 1054 i++; 1055 if (argc <= i) 1056 usage (); 1057 for (j = StaticGray; j <= DirectColor; j++) { 1058 if (strcmp(argv[i], visualClassNames[j]) == 0) { 1059 vclass = j; 1060 break; 1061 } 1062 } 1063 if (vclass < 0) 1064 usage (); 1065 } else if (strcmp(argv[i], "-subs") == 0) { 1066 skip = GetNumbers (i+1, argc, argv, subWindows, &numSubWindows); 1067 i += skip; 1068 } else if (strcmp(argv[i], "-v1.2") == 0) { 1069 xparms.version = VERSION1_2; 1070 } else if (strcmp(argv[i], "-v1.3") == 0) { 1071 xparms.version = VERSION1_3; 1072 } else if (strcmp(argv[i], "-su") == 0) { 1073 xparms.save_under = True; 1074 } else if (strcmp(argv[i], "-bs") == 0) { 1075 i++; 1076 if (argc <= i) 1077 usage (); 1078 if (strcmp(argv[i], "WhenMapped") == 0) { 1079 xparms.backing_store = WhenMapped; 1080 } else if (strcmp(argv[i], "Always") == 0) { 1081 xparms.backing_store = Always; 1082 } else usage (); 1083 } else { 1084 int len,found; 1085 ForEachTest (j) { 1086 if (strcmp (argv[i], test[j].option) == 0 && 1087 (test[j].versions & xparms.version)) { 1088 doit[j] = True; 1089 goto LegalOption; 1090 } 1091 } 1092 found = False; 1093 len = strlen(argv[i]); 1094 if(len>=3) 1095 ForEachTest (j) { 1096 if (Strstr (test[j].option, argv[i]+1) != NULL) { 1097 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1098 doit[j] = found = True; 1099 } 1100 } 1101 if(!found) 1102 ForEachTest (j) { 1103 if (Strstr (LABELP(j), argv[i]+1) != NULL) { 1104 fprintf(stderr," -> %s %s\n", test[j].option, LABELP(j)); 1105 doit[j] = found = True; 1106 } 1107 } 1108 if(!found) 1109 usage (); 1110 LegalOption: 1111 foundOne = True; 1112 } 1113 } 1114 1115 if (labels) { 1116 /* Just print out list of tests for use with .sh programs that 1117 assemble data from different x11perf runs into a nice format */ 1118 ForEachTest (i) { 1119 int child; 1120 if (doit[i]) { 1121 switch (test[i].testType) { 1122 case NONROP: 1123 printf ("%s\n", LABELP(i)); 1124 break; 1125 1126 case ROP: 1127 /* Run it through all specified rops and planemasks */ 1128 for (rop = 0; rop < numRops; rop++) { 1129 for (pm = 0; pm < numPlanemasks; pm++) { 1130 if (planemasks[pm] == ~0) { 1131 if (rops[rop] == GXcopy) { 1132 printf ("%s\n", LABELP(i)); 1133 } else { 1134 printf ("(%s) %s\n", 1135 ropNames[rops[rop]].name, 1136 LABELP(i)); 1137 } 1138 } else { 1139 printf ("(%s 0x%lx) %s\n", 1140 ropNames[rops[rop]].name, 1141 planemasks[pm], 1142 LABELP(i)); 1143 } 1144 } /* for pm */ 1145 } /* for rop */ 1146 break; 1147 1148 case PLANEMASK: 1149 /* Run it through all specified planemasks */ 1150 for (pm = 0; pm < numPlanemasks; pm++) { 1151 if (planemasks[pm] == ~0) { 1152 printf ("%s\n", LABELP(i)); 1153 } else { 1154 printf ("(0x%lx) %s\n", 1155 planemasks[pm], 1156 LABELP(i)); 1157 } 1158 } /* for pm */ 1159 break; 1160 1161 case WINDOW: 1162 for (child = 0; child != numSubWindows; child++) { 1163 printf ("%s (%ld kids)\n", 1164 LABELP(i), subWindows[child]); 1165 } 1166 break; 1167 case COMP: 1168 /* Run it through all specified pops */ 1169 for (pop = 0; pop < numPops; pop++) { 1170 if (pops[pop] == PictOpOver) { 1171 printf ("%s\n", LABELP(i)); 1172 } else { 1173 printf ("(%s) %s\n", 1174 popNames[pops[pop]].name, 1175 LABELP(i)); 1176 } 1177 } /* for pop */ 1178 break; 1179 } /* switch */ 1180 } 1181 } 1182 exit(0); 1183 } 1184 1185 if (!foundOne) 1186 usage (); 1187 xparms.d = Open_Display (displayName); 1188 screen = DefaultScreen(xparms.d); 1189 1190 /* get visual info of default visual */ 1191 vmask = VisualIDMask | VisualScreenMask; 1192 vinfotempl.visualid = XVisualIDFromVisual(XDefaultVisual(xparms.d, screen)); 1193 vinfotempl.screen = screen; 1194 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1195 if (!vinfolist || n != 1) { 1196 fprintf (stderr, "%s: can't get visual info of default visual\n", 1197 program_name); 1198 exit(1); 1199 } 1200 1201 if (depth == -1 && vclass == -1) { 1202 /* use the default visual and colormap */ 1203 xparms.vinfo = *vinfolist; 1204 cmap = XDefaultColormap(xparms.d, screen); 1205 } else { 1206 /* find the specified visual */ 1207 int errorDepth = vinfolist[0].depth; 1208 int errorClass = vinfolist[0].class; 1209 1210 vmask = VisualScreenMask; 1211 vinfotempl.screen = screen; 1212 if (depth >= 0) { 1213 vinfotempl.depth = depth; 1214 vmask |= VisualDepthMask; 1215 errorDepth = depth; 1216 } 1217 if (vclass >= 0) { 1218 vinfotempl.class = vclass; 1219 vmask |= VisualClassMask; 1220 errorClass = vclass; 1221 } 1222 vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n); 1223 if (!vinfolist) { 1224 fprintf (stderr, 1225 "%s: can't find a visual of depth %d and class %s\n", 1226 program_name, errorDepth, visualClassNames[errorClass]); 1227 exit(1); 1228 } 1229 xparms.vinfo = *vinfolist; /* use the first one in list */ 1230 if (xparms.vinfo.visualid == 1231 XVisualIDFromVisual(XDefaultVisual(xparms.d, screen))) { 1232 /* matched visual is same as default visual */ 1233 cmap = XDefaultColormap(xparms.d, screen); 1234 } else { 1235 cmap = XCreateColormap(xparms.d, DefaultRootWindow(xparms.d), 1236 xparms.vinfo.visual, AllocNone); 1237 /* since this is not default cmap, must force color allocation */ 1238 if (!foreground) foreground = "Black"; 1239 if (!background) background = "White"; 1240 XInstallColormap(xparms.d, cmap); 1241 } 1242 } 1243 xparms.cmap = cmap; 1244 1245 printf("x11perf - X11 performance program, version %s\n", 1246 xparms.version & VERSION1_5 ? "1.5" : 1247 xparms.version & VERSION1_4 ? "1.4" : 1248 xparms.version & VERSION1_3 ? "1.3" : 1249 "1.2" 1250 ); 1251 XmuGetHostname(hostname, 100); 1252 printf ("%s server version %d on %s\nfrom %s\n", 1253 ServerVendor (xparms.d), VendorRelease (xparms.d), 1254 DisplayString (xparms.d), hostname); 1255 PrintTime (); 1256 1257 /* Force screen out of screen-saver mode, grab current data, and set 1258 time to blank to 8 hours. We should just be able to turn the screen- 1259 saver off, but this causes problems on some servers. We also reset 1260 the screen-saver timer each test, as 8 hours is about the maximum time 1261 we can use, and that isn't long enough for some X terminals using a 1262 serial protocol to finish all the tests. As long as the tests run to 1263 completion, the old screen-saver values are restored. */ 1264 XForceScreenSaver(xparms.d, ScreenSaverReset); 1265 XGetScreenSaver(xparms.d, &ssTimeout, &ssInterval, &ssPreferBlanking, 1266 &ssAllowExposures); 1267 (void) signal(SIGINT, Cleanup); /* ^C */ 1268#ifdef SIGQUIT 1269 (void) signal(SIGQUIT, Cleanup); 1270#endif 1271 (void) signal(SIGTERM, Cleanup); 1272#ifdef SIGHUP 1273 (void) signal(SIGHUP, Cleanup); 1274#endif 1275 XSetScreenSaver(xparms.d, 8 * 3600, ssInterval, ssPreferBlanking, 1276 ssAllowExposures); 1277 1278 if (drawToFakeServer) { 1279 tileToQuery = 1280 XCreatePixmap(xparms.d, DefaultRootWindow (xparms.d), 32, 32, 1); 1281 } 1282 1283 1284 xparms.foreground = 1285 AllocateColor(xparms.d, foreground, BlackPixel(xparms.d, screen)); 1286 xparms.background = 1287 AllocateColor(xparms.d, background, WhitePixel(xparms.d, screen)); 1288 xparms.ddbackground = 1289 AllocateColor(xparms.d, ddbackground, WhitePixel(xparms.d, screen)); 1290 window_x = 2; 1291 if (DisplayWidth(xparms.d, screen) < WIDTH + window_x + 1) 1292 window_x = -1; 1293 window_y = 2; 1294 if (DisplayHeight(xparms.d, screen) < HEIGHT + window_y + 1) 1295 window_y = -1; 1296 xparms.w = CreatePerfWindow(&xparms, window_x, window_y, WIDTH, HEIGHT); 1297 HSx = WIDTH-1; 1298 if (window_x + 1 + WIDTH > DisplayWidth(xparms.d, screen)) 1299 HSx = DisplayWidth(xparms.d, screen) - (1 + window_x + 1); 1300 HSy = HEIGHT-1; 1301 if (window_y + 1 + HEIGHT > DisplayHeight(xparms.d, screen)) 1302 HSy = DisplayHeight(xparms.d, screen) - (1 + window_y + 1); 1303 status = CreatePerfWindow(&xparms, window_x, HEIGHT+5, WIDTH, 20); 1304 tgcv.foreground = 1305 AllocateColor(xparms.d, "black", BlackPixel(xparms.d, screen)); 1306 tgcv.background = 1307 AllocateColor(xparms.d, "white", WhitePixel(xparms.d, screen)); 1308 tgc = XCreateGC(xparms.d, status, GCForeground | GCBackground, &tgcv); 1309 1310 xparms.p = (Pixmap)0; 1311 1312 if (synchronous) 1313 XSynchronize (xparms.d, True); 1314 1315 /* Get mouse pointer out of the way of the performance window. On 1316 software cursor machines it will slow graphics performance. On 1317 all current MIT-derived servers it will slow window 1318 creation/configuration performance. */ 1319 XWarpPointer(xparms.d, None, status, 0, 0, 0, 0, WIDTH+32, 20+32); 1320 1321 /* Figure out how long to call HardwareSync, so we can adjust for that 1322 in our total elapsed time */ 1323 (void) CalibrateTest(&xparms, &syncTest, 1, &syncTime); 1324 printf("Sync time adjustment is %6.4f msecs.\n\n", syncTime/1000); 1325 1326 ForEachTest (i) { 1327 int child; 1328 char label[200]; 1329 1330 if (doit[i] && (test[i].versions & xparms.version)) { 1331 switch (test[i].testType) { 1332 case NONROP: 1333 /* Simplest...just run it once */ 1334 strcpy (label, LABELP(i)); 1335 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1336 break; 1337 1338 case ROP: 1339 /* Run it through all specified rops and planemasks */ 1340 for (rop = 0; rop < numRops; rop++) { 1341 for (pm = 0; pm < numPlanemasks; pm++) { 1342 if (planemasks[pm] == ~0) { 1343 if (rops[rop] == GXcopy) { 1344 sprintf (label, "%s", LABELP(i)); 1345 } else { 1346 sprintf (label, "(%s) %s", 1347 ropNames[rops[rop]].name, 1348 LABELP(i)); 1349 } 1350 } else { 1351 sprintf (label, "(%s 0x%lx) %s", 1352 ropNames[rops[rop]].name, 1353 planemasks[pm], 1354 LABELP(i)); 1355 } 1356 ProcessTest(&xparms, &test[i], rops[rop], 1357 planemasks[pm], label); 1358 } /* for pm */ 1359 } /* for rop */ 1360 break; 1361 1362 case PLANEMASK: 1363 /* Run it through all specified planemasks */ 1364 for (pm = 0; pm < numPlanemasks; pm++) { 1365 if (planemasks[pm] == ~0) { 1366 sprintf (label, "%s", LABELP(i)); 1367 } else { 1368 sprintf (label, "(0x%lx) %s", 1369 planemasks[pm], 1370 LABELP(i)); 1371 } 1372 ProcessTest(&xparms, &test[i], GXcopy, 1373 planemasks[pm], label); 1374 } /* for pm */ 1375 break; 1376 1377 case WINDOW: 1378 /* Loop through number of children array */ 1379 for (child = 0; child != numSubWindows; child++) { 1380 test[i].parms.objects = subWindows[child]; 1381 sprintf(label, "%s (%d kids)", 1382 LABELP(i), test[i].parms.objects); 1383 ProcessTest(&xparms, &test[i], GXcopy, ~0L, label); 1384 } 1385 break; 1386 case COMP: 1387 /* Loop through the composite operands */ 1388 for (pop = 0; pop < numPops; pop++) { 1389 for (format = 0; format < numFormats; format++) { 1390 if (formats[format] == PictStandardNative) { 1391 if (pops[pop] == PictOpOver) { 1392 sprintf (label, "%s", LABELP(i)); 1393 } else { 1394 sprintf (label, "(%s) %s", 1395 popNames[pops[pop]].name, 1396 LABELP(i)); 1397 } 1398 } else { 1399 sprintf (label, "(%s %s) %s", 1400 popNames[pops[pop]].name, 1401 formatNames[formats[format]].name, 1402 LABELP(i)); 1403 } 1404 ProcessTest (&xparms, &test[i], pops[pop], formats[format], label); 1405 } 1406 } 1407 break; 1408 } /* switch */ 1409 } /* if doit */ 1410 } /* ForEachTest */ 1411 1412 XFreeGC(xparms.d, tgc); 1413 XDestroyWindow(xparms.d, xparms.w); 1414 XFree(vinfolist); 1415 if (drawToFakeServer) 1416 XFreePixmap(xparms.d, tileToQuery); 1417 /* Restore ScreenSaver to original state. */ 1418 XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking, 1419 ssAllowExposures); 1420 XCloseDisplay(xparms.d); 1421 free(saveargv); 1422 free(doit); 1423 exit(0); 1424} 1425 1426static int 1427GetWords (int argi, int argc, char **argv, char **wordsp, int *nump) 1428{ 1429 int count; 1430 1431 if (argc <= argi) 1432 usage(); 1433 count = 0; 1434 while (argv[argi] && *(argv[argi]) != '-') { 1435 *wordsp++ = argv[argi]; 1436 ++argi; 1437 count++; 1438 } 1439 *nump = count; 1440 return count; 1441} 1442 1443static long 1444atox (char *s) 1445{ 1446 long v, c = 0; 1447 1448 v = 0; 1449 while (*s) { 1450 if ('0' <= *s && *s <= '9') 1451 c = *s - '0'; 1452 else if ('a' <= *s && *s <= 'f') 1453 c = *s - 'a' + 10; 1454 else if ('A' <= *s && *s <= 'F') 1455 c = *s - 'A' + 10; 1456 v = v * 16 + c; 1457 s++; 1458 } 1459 return v; 1460} 1461 1462static int 1463GetNumbers (int argi, int argc, char **argv, unsigned long *intsp, int *nump) 1464{ 1465 char *words[256]; 1466 int count; 1467 int i; 1468 int flip; 1469 1470 count = GetWords (argi, argc, argv, words, nump); 1471 for (i = 0; i < count; i++) { 1472 flip = 0; 1473 if (!strncmp (words[i], "~", 1)) { 1474 words[i]++; 1475 flip = ~0; 1476 } 1477 if (!strncmp (words[i], "0x", 2)) 1478 intsp[i] = atox(words[i] + 2) ^ flip; 1479 else 1480 intsp[i] = atoi (words[i]) ^ flip; 1481 } 1482 return count; 1483} 1484 1485static int 1486GetRops (int argi, int argc, char **argv, int *ropsp, int *nump) 1487{ 1488 char *words[256]; 1489 int count; 1490 int i; 1491 int rop; 1492 1493 count = GetWords (argi, argc, argv, words, nump); 1494 for (i = 0; i < count; i++) { 1495 if (!strncmp (words[i], "GX", 2)) 1496 words[i] += 2; 1497 if (!strcmp (words[i], "all")) { 1498 for (i = 0; i < NUM_ROPS; i++) 1499 ropsp[i] = ropNames[i].rop; 1500 *nump = NUM_ROPS; 1501 break; 1502 } 1503 for (rop = 0; rop < NUM_ROPS; rop++) { 1504 if (!strcmp (words[i], ropNames[rop].name)) { 1505 ropsp[i] = ropNames[rop].rop; 1506 break; 1507 } 1508 } 1509 if (rop == NUM_ROPS) { 1510 usage (); 1511 fprintf (stderr, "unknown rop name %s\n", words[i]); 1512 } 1513 } 1514 return count; 1515} 1516 1517static int 1518GetPops (int argi, int argc, char **argv, int *popsp, int *nump) 1519{ 1520 char *words[256]; 1521 int count; 1522 int i; 1523 int pop; 1524 1525 count = GetWords (argi, argc, argv, words, nump); 1526 for (i = 0; i < count; i++) { 1527 if (!strncmp (words[i], "PictOp", 6)) 1528 words[i] += 6; 1529 if (!strcmp (words[i], "all")) { 1530 for (i = 0; i < NUM_POPS; i++) 1531 popsp[i] = popNames[i].rop; 1532 *nump = NUM_POPS; 1533 break; 1534 } 1535 for (pop = 0; pop < NUM_POPS; pop++) { 1536 if (!strcmp (words[i], popNames[pop].name)) { 1537 popsp[i] = popNames[pop].rop; 1538 break; 1539 } 1540 } 1541 if (pop == NUM_POPS) { 1542 usage (); 1543 fprintf (stderr, "unknown picture op name %s\n", words[i]); 1544 } 1545 } 1546 return count; 1547} 1548 1549static int 1550GetFormats (int argi, int argc, char **argv, int *formatsp, int *nump) 1551{ 1552 char *words[256]; 1553 int count; 1554 int i; 1555 int format; 1556 1557 count = GetWords (argi, argc, argv, words, nump); 1558 for (i = 0; i < count; i++) { 1559 if (!strcmp (words[i], "all")) { 1560 for (i = 0; i < NUM_FORMATS; i++) 1561 formatsp[i] = formatNames[i].rop; 1562 *nump = NUM_FORMATS; 1563 break; 1564 } 1565 for (format = 0; format < NUM_FORMATS; format++) { 1566 if (!strcmp (words[i], formatNames[format].name)) { 1567 formatsp[i] = formatNames[format].rop; 1568 break; 1569 } 1570 } 1571 if (format == NUM_FORMATS) { 1572 usage (); 1573 fprintf (stderr, "unknown format name %s\n", words[i]); 1574 } 1575 } 1576 return count; 1577} 1578