home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / x / x11p-13.zip / x11perf.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  31KB  |  1,196 lines

  1. /*****************************************************************************
  2. Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
  3.  
  4.                         All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute this software and its 
  7. documentation for any purpose and without fee is hereby granted, 
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in 
  10. supporting documentation, and that the name of Digital not be
  11. used in advertising or publicity pertaining to distribution of the
  12. software without specific, written prior permission.  
  13.  
  14. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  15. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  16. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  17. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  18. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  19. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  20. SOFTWARE.
  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.  
  36. /* Only for working on ``fake'' servers, for hardware that doesn't exist */
  37. static Bool     drawToFakeServer = False;
  38. static Pixmap   tileToQuery     = None;
  39.  
  40. typedef struct _RopNames { char    *name; int  rop; } RopNameRec, *RopNamePtr;
  41.  
  42. RopNameRec ropNames[] = {
  43.     "clear",        GXclear,    /* 0 */
  44.     "and",        GXand,        /* src AND dst */
  45.     "andReverse",    GXandReverse,    /* src AND NOT dst */
  46.     "copy",        GXcopy,        /* src */
  47.     "andInverted",    GXandInverted,    /* NOT src AND dst */
  48.     "noop",        GXnoop,        /* dst */
  49.     "xor",        GXxor,        /* src XOR dst */
  50.     "or",        GXor,        /* src OR dst */
  51.     "nor",        GXnor,        /* NOT src AND NOT dst */
  52.     "equiv",    GXequiv,    /* NOT src XOR dst */
  53.     "invert",    GXinvert,    /* NOT dst */
  54.     "orReverse",    GXorReverse,    /* src OR NOT dst */
  55.     "copyInverted",    GXcopyInverted,    /* NOT src */
  56.     "orInverted",    GXorInverted,    /* NOT src OR dst */
  57.     "nand",        GXnand,        /* NOT src OR NOT dst */
  58.     "set",        GXset,        /* 1 */
  59. };
  60.  
  61. static Bool     labels        = False;
  62. static int      repeat        = 5;
  63. static int    seconds        = 5;
  64.  
  65. static Window   status;     /* Status window and GC */
  66. static GC       tgc;
  67.  
  68. static double syncTime = 0.0;
  69.  
  70. static int saveargc;
  71. static char **saveargv;
  72.  
  73. static int  numRops = 1;
  74. static int  rops[16] = { GXcopy };
  75. static int  numPlanemasks = 1;
  76. static unsigned long planemasks[256] = { (unsigned long)~0 };
  77.  
  78. static char *foreground = NULL;
  79. static char *background = NULL;
  80.  
  81. static int numSubWindows = 7;
  82. static int subWindows[] = {4, 16, 25, 50, 75, 100, 200, 0};
  83.  
  84. static int  fixedReps = 0;
  85.  
  86. static Bool *doit;
  87.  
  88. static XRectangle ws[] = {  /* Clip rectangles */
  89.     {195, 195, 120, 120},
  90.     { 45, 145, 120, 120},
  91.     {345, 245, 120, 120}
  92.  
  93. };
  94. #define MAXCLIP     (sizeof(ws) / sizeof(ws[0]))
  95. static Window clipWindows[MAXCLIP];
  96. static Colormap cmap;
  97. static int depth = -1;  /* -1 means use default depth */
  98.  
  99. /* ScreenSaver state */
  100. static XParmRec    xparms;
  101. static int ssTimeout, ssInterval, ssPreferBlanking, ssAllowExposures;
  102.  
  103.  
  104. /************************************************
  105. *        time related stuff            *
  106. ************************************************/
  107.  
  108. #ifdef VMS
  109.  
  110. typedef struct _vms_time {
  111.     unsigned long low;
  112.     unsigned long high;
  113. }vms_time;
  114.  
  115. struct timeval {
  116.     long tv_sec;        /* seconds since Jan. 1, 1970 */
  117.     long tv_usec;  /* and microseconds */
  118. };
  119.  
  120. struct timezone {
  121.     int  tz_minuteswest;     /* of Greenwich */
  122.     int  tz_dsttime;    /* type of dst correction to apply */
  123. };
  124.  
  125.  
  126. static int firsttime = True;
  127. static vms_time basetime;
  128.  
  129. int gettimeofday(tp, tzp)
  130.     struct timeval *tp;
  131.     struct timezone *tzp;
  132. {
  133.     vms_time current_time, resultant;
  134.     unsigned long mumble, foo;
  135.     int status;
  136.  
  137.     if (firsttime) {
  138.         sys$gettim(&basetime);
  139.         firsttime = False;
  140.     }
  141.     sys$gettim(¤t_time);
  142.     resultant.high = current_time.high - basetime.high;
  143.     resultant.low = current_time.low - basetime.low;
  144.     if (current_time.low < basetime.low) {
  145.         resultant.high -= 1;
  146.     }
  147.     status = lib$ediv( &(10000000), &resultant, &tp->tv_sec, &tp->tv_usec);
  148.     tp->tv_usec /= 10;
  149.     return 0;
  150. }
  151.  
  152. #endif
  153.  
  154. static struct  timeval start;
  155.  
  156. void PrintTime()
  157. {
  158.     time_t t;
  159.  
  160.     t = time((long *)NULL);
  161.     printf("%s\n", ctime(&t));
  162. }
  163.  
  164. void InitTimes ()
  165. {
  166.     struct timezone foo;
  167.     gettimeofday(&start, &foo);
  168. }
  169.  
  170. double ElapsedTime(correction)
  171.     double correction;
  172. {
  173.     struct timeval stop;
  174.     struct timezone foo;
  175.     
  176.     gettimeofday(&stop, &foo);
  177.     if (stop.tv_usec < start.tv_usec) {
  178.         stop.tv_usec += 1000000;
  179.     stop.tv_sec -= 1;
  180.     }
  181.     return  (double)(stop.tv_usec - start.tv_usec) +
  182.             (1000000.0 * (double)(stop.tv_sec - start.tv_sec)) - correction;
  183. }
  184.  
  185. double RoundTo3Digits(d)
  186.     double d;
  187. {
  188.     /* It's kind of silly to print out things like ``193658.4/sec'' so just
  189.        junk all but 3 most significant digits. */
  190.  
  191.     double exponent;
  192.  
  193.     exponent = 1.0;
  194.     if (d >= 1000.0) {
  195.     do {
  196.         exponent *= 10.0;
  197.     } while (d/exponent >= 1000.0);
  198.     d = (double)((int) (d/exponent + 0.5));
  199.     d *= exponent;
  200.     } else {
  201.     while (d*exponent < 100.0) {
  202.         exponent *= 10.0;
  203.     }
  204.     d = (double)((int) (d*exponent + 0.5));
  205.     d /= exponent;
  206.     }
  207.     return d;
  208. }
  209.  
  210.  
  211. void ReportTimes(usecs, n, str, average)
  212.     double  usecs;
  213.     int     n;
  214.     char    *str;
  215. {
  216.     double msecsperobj, objspersec;
  217.  
  218.     msecsperobj = usecs / (1000.0 * (double)n);
  219.     objspersec = (double) n * 1000000.0 / usecs;
  220.  
  221.     /* Round obj/sec to 3 significant digits.  Leave msec untouched, to allow
  222.     averaging results from several repetitions. */
  223.     objspersec =  RoundTo3Digits(objspersec);
  224.  
  225.     if (average) {
  226.     printf("%6d trep @ %7.4f msec (%6.1f/sec): %s\n", 
  227.         n, msecsperobj, objspersec, str);
  228.     } else {
  229.     printf("%6d reps @ %7.4f msec (%6.1f/sec): %s\n", 
  230.         n, msecsperobj, objspersec, str);
  231.     }
  232. }
  233.  
  234.  
  235.  
  236. /************************************************
  237. *        Generic X stuff            *
  238. ************************************************/
  239.  
  240. static char *program_name;
  241. void usage();
  242.  
  243. /*
  244.  * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
  245.  * If found, remove it from command line.  Don't go past a lone -.
  246.  */
  247. char *Get_Display_Name(pargc, argv)
  248.     int     *pargc;  /* MODIFIED */
  249.     char    **argv; /* MODIFIED */
  250. {
  251.     int     argc = *pargc;
  252.     char    **pargv = argv+1;
  253.     char    *displayname = NULL;
  254.     int     i;
  255.  
  256.     for (i = 1; i != argc; i++) {
  257.     char *arg = argv[i];
  258.  
  259.     if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
  260.         if (++i >= argc) usage ();
  261.  
  262.         displayname = argv[i];
  263.         *pargc -= 2;
  264.         continue;
  265.     }
  266.     if (!strcmp(arg,"-")) {
  267.         while (i<argc)  *pargv++ = argv[i++];
  268.         break;
  269.     }
  270.     *pargv++ = arg;
  271.     }
  272.  
  273.     *pargv = NULL;
  274.     return (displayname);
  275. }
  276.  
  277.  
  278. /* 
  279.  * GetVersion (argc, argv) Look for -v1.2.
  280.  * If found remove it from command line.  Don't go past a lone _.
  281.  */
  282.  
  283. Version GetVersion(pargc, argv)
  284.     int     *pargc;  /* MODIFIED */
  285.     char    **argv; /* MODIFIED */
  286. {
  287.     int     argc = *pargc;
  288.     char    **pargv = argv+1;
  289.     Version version = VERSION1_3;
  290.     int     i;
  291.  
  292.     for (i = 1; i != argc; i++) {
  293.     char *arg = argv[i];
  294.  
  295.     if (!strcmp (arg, "-v1.2")) {
  296.         version = VERSION1_2;
  297.         *pargc -= 1;
  298.         continue;
  299.     }
  300.     if (!strcmp(arg,"-")) {
  301.         while (i<argc)  *pargv++ = argv[i++];
  302.         break;
  303.     }
  304.     *pargv++ = arg;
  305.     }
  306.  
  307.     *pargv = NULL;
  308.     return (version);
  309. }
  310.  
  311.  
  312.  
  313. /*
  314.  * Open_Display: Routine to open a display with correct error handling.
  315.  */
  316. Display *Open_Display(display_name)
  317.     char *display_name;
  318. {
  319.     Display *d;
  320.  
  321.     d = XOpenDisplay(display_name);
  322.     if (d == NULL) {
  323.     fprintf (stderr, "%s:  unable to open display '%s'\n",
  324.          program_name, XDisplayName (display_name));
  325.     usage ();
  326.     /* doesn't return */
  327.     }
  328.  
  329.     return(d);
  330. }
  331.  
  332.  
  333. void Cleanup(sig, code, context) {
  334.     int sig, code;
  335.     struct sigcontext *scp;
  336.  
  337.     fflush(stdout);
  338.     XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking,
  339.     ssAllowExposures);
  340.     exit(sig);
  341. }
  342.  
  343.  
  344. /************************************************
  345. *        Performance stuff        *
  346. ************************************************/
  347.  
  348.  
  349. void usage()
  350. {
  351.     char    **cpp;
  352.     int     i = 0;
  353.     static char *help_message[] = {
  354. "where options include:",
  355. "    -v1.2                     perform only v1.2 tests using old semantics",
  356. "    -display <host:display>   the X server to contact",
  357. "    -sync                     do the tests in synchronous mode",
  358. "    -pack                     pack rectangles right next to each other",
  359. "    -repeat <n>               do tests <n> times (default = 5)",
  360. "    -time <s>                 do tests for <s> seconds each (default = 5)",
  361. /*
  362. "    -draw                     draw after each test -- pmax only",
  363. */
  364. "    -all                      do all tests",
  365. "    -range <test1>[,<test2>]  like all, but do <test1> to <test2>",
  366. "    -labels                   generate test labels for use by fillblnk",
  367. "    -fg                       the foreground color to use",
  368. "    -bg                       the background color to use",
  369. "    -rop <rop0 rop1 ...>      use the given rops to draw (default = GXcopy)",
  370. "    -pm <pm0 pm1 ...>         use the given planemasks to draw (default = ~0)",
  371. "    -depth <depth>            use a visual with <depth> planes per pixel",
  372. "    -reps <n>                 fix the rep count (default = auto scale)",
  373. "    -subs <s0 s1 ...>         a list of the number of sub-windows to use",
  374. NULL};
  375.  
  376.     fflush(stdout);
  377.     fprintf(stderr, "usage: %s [-options ...]\n", program_name);
  378.     for (cpp = help_message; *cpp; cpp++) {
  379.     fprintf(stderr, "%s\n", *cpp);
  380.     }
  381.     while (test[i].option != NULL) {
  382.     if (test[i].versions & xparms.version ) {
  383.         fprintf(stderr, "    %-24s   %s\n",    test[i].option, test[i].label);
  384.     }
  385.     i++;
  386.     }
  387.     fprintf(stderr, "\n");
  388.     
  389.     /* Print out original command line as the above usage message is so long */
  390.     for (i = 0; i != saveargc; i++) {
  391.     fprintf(stderr, "%s ", saveargv[i]);
  392.     }
  393.     fprintf(stderr, "\n\n");
  394.     exit (1);
  395. }
  396.  
  397. void NullProc(xp, p)
  398.     XParms  xp;
  399.     Parms   p;
  400. {
  401. }
  402.  
  403. Bool NullInitProc(xp, p, reps)
  404.     XParms  xp;
  405.     Parms   p;
  406.     int reps;
  407. {
  408.     return reps;
  409. }
  410.  
  411.  
  412. void HardwareSync(xp)
  413.     XParms  xp;
  414. {
  415.     /*
  416.      * Some graphics hardware allows the server to claim it is done,
  417.      * while in reality the hardware is busily working away.  So fetch
  418.      * a pixel from the window that was drawn to, which should be
  419.      * enough to make the server wait for the graphics hardware.
  420.      */
  421.     XImage *image;
  422.  
  423.     image = XGetImage(xp->d, xp->w, WIDTH-1, HEIGHT-1, 1, 1, ~0, ZPixmap);
  424.     XDestroyImage(image);
  425. }
  426.  
  427. void DoHardwareSync(xp, p, reps)
  428.     XParms  xp;
  429.     Parms   p;
  430.     int     reps;
  431. {
  432.     int i;
  433.     
  434.     for (i = 0; i != reps; i++) {
  435.     HardwareSync(xp);
  436.     }
  437. }
  438.  
  439. static Test syncTest = {
  440.     "syncTime", "Internal test for finding how long HardwareSync takes",
  441.     NullInitProc, DoHardwareSync, NullProc, NullProc, 
  442.     VALL, NONROP, 0,
  443.     {1}
  444. };
  445.  
  446.  
  447. static Window CreatePerfWindow(xp, x, y, width, height)
  448.     XParms  xp;
  449.     int     width, height, x, y;
  450. {
  451.     XSetWindowAttributes xswa;
  452.     Window w;
  453.     Screen *s;
  454.     int su;
  455.  
  456. /*
  457.     s = DefaultScreenOfDisplay(xp->d);
  458.     su = XDoesBackingStore(s);
  459.     printf("Backing store of screen returns %d\n", su);
  460.     su = XDoesSaveUnders(s);
  461.     printf("Save unders of screen returns %d\n", su);
  462.     su = XPlanesOfScreen(s);
  463.     printf("Planes of screen returns %d\n", su);
  464. */
  465.     xswa.background_pixel = xp->background;
  466.     xswa.border_pixel = xp->foreground;
  467.     xswa.colormap = cmap;
  468.     xswa.override_redirect = True;
  469.     xswa.backing_store = False;
  470.     xswa.save_under = False;
  471.     w = XCreateWindow(xp->d, DefaultRootWindow(xp->d), x, y, width, height, 1,
  472.         xp->vinfo.depth, CopyFromParent, xp->vinfo.visual,
  473.     CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect 
  474.     | CWBackingStore | CWSaveUnder, &xswa);
  475.     XMapWindow (xp->d, w);
  476.     return w;
  477. }
  478.  
  479.  
  480. void CreateClipWindows(xp, clips)
  481.     XParms  xp;
  482.     int     clips;
  483. {
  484.     int j;
  485.     XWindowAttributes    xwa;
  486.  
  487.     (void) XGetWindowAttributes(xp->d, xp->w, &xwa);
  488.     if (clips > MAXCLIP) clips = MAXCLIP;
  489.     for (j = 0; j != clips; j++) {
  490.     clipWindows[j] = CreatePerfWindow(xp,
  491.         xwa.x + ws[j].x, xwa.y + ws[j].y, ws[j].width, ws[j].height);
  492.     }
  493. } /* CreateClipWindows */
  494.  
  495.  
  496. void DestroyClipWindows(xp, clips)
  497.     XParms  xp;
  498.     int     clips;
  499. {
  500.     int j;
  501.  
  502.     if (clips > MAXCLIP) clips = MAXCLIP;
  503.     for (j = 0; j != clips; j++) {
  504.     XDestroyWindow(xp->d, clipWindows[j]);
  505.     }
  506. } /* DestroyClipWindows */
  507.  
  508.  
  509. double DoTest(xp, test, reps)
  510.     XParms  xp;
  511.     Test    *test;
  512.     int     reps;
  513. {
  514.     double  time;
  515.     unsigned int ret_width, ret_height;
  516.  
  517.     /* Tell screen-saver to restart counting again.  See comments below for the
  518.        XSetScreenSaver call. */
  519.     XForceScreenSaver(xp->d, ScreenSaverReset);
  520.     HardwareSync (xp); 
  521.     InitTimes ();
  522.     (*test->proc) (xp, &test->parms, reps);
  523.     HardwareSync(xp);
  524.  
  525.     time = ElapsedTime(syncTime);
  526.     if (drawToFakeServer)
  527.         XQueryBestSize(xp->d, TileShape, tileToQuery,
  528.                32, 32, &ret_width, &ret_height);
  529.     (*test->passCleanup) (xp, &test->parms);
  530.     return time;
  531. }
  532.  
  533.  
  534. int CalibrateTest(xp, test, seconds, usecperobj)
  535.     XParms  xp;
  536.     Test    *test;
  537.     int     seconds;
  538.     double  *usecperobj;
  539. {
  540. #define goal    2500000.0   /* Try to get up to 2.5 seconds            */
  541. #define enough  2000000.0   /* But settle for 2.0 seconds            */
  542. #define tick      10000.0   /* Assume clock not faster than .01 seconds     */
  543.  
  544.     double  usecs;
  545.     int     reps, didreps;  /* Reps desired, reps performed            */
  546.     int     exponent;
  547.  
  548.     /* Attempt to get an idea how long each rep lasts by getting enough
  549.        reps to last more tan enough.  Then scale that up to the number of
  550.        seconds desired.
  551.  
  552.        If init call to test ever fails, return False and test will be skipped.
  553.     */
  554.  
  555.     if (fixedReps != 0) {
  556.     return fixedReps;
  557.     }
  558.     reps = 1;
  559.     for (;;) {
  560.     XDestroySubwindows(xp->d, xp->w);
  561.     XClearWindow(xp->d, xp->w);
  562.     didreps = (*test->init) (xp, &test->parms, reps);
  563.     if (didreps == 0) {
  564.         return 0;
  565.     }
  566.     /* Create clip windows if requested */
  567.     CreateClipWindows(xp, test->clips);
  568.     HardwareSync(xp);
  569.     InitTimes();
  570.     (*test->proc) (xp, &test->parms, reps);
  571.     HardwareSync(xp);
  572.     usecs = ElapsedTime(syncTime);
  573.     (*test->cleanup) (xp, &test->parms);
  574.     DestroyClipWindows(xp, test->clips);
  575.  
  576.     if (didreps != reps) {
  577.         /* The test can't do the number of reps as we asked for.  
  578.            Give up */
  579.         *usecperobj = 
  580.         usecs / (double)(didreps * test->parms.objects);
  581.         return didreps;
  582.     }
  583.     /* Did we go long enough? */
  584.     if (usecs >= enough) break;
  585.  
  586.     /* Don't let too short a clock make new reps wildly high */
  587.     if (usecs < tick) usecs = tick;
  588.  
  589.     /* Try to get up to goal seconds. */
  590.     reps = (int) (goal * (double)reps / usecs) + 1;
  591.     }
  592.  
  593.     *usecperobj = usecs / (double) (reps * test->parms.objects);
  594.     reps = (int) ((double)seconds * 1000000.0 * (double)reps / usecs) + 1;
  595.  
  596.     /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking
  597.        numbers of repetitions. */
  598.     reps--;
  599.     exponent = 1;
  600.     while (reps > 9) {
  601.     reps /= 10;
  602.     exponent *= 10;
  603.     }
  604.     reps = (reps + 1) * exponent;
  605.     return reps;
  606. } /* CalibrateTest */
  607.  
  608. void CreatePerfGCs(xp, func, pm)
  609.     XParms  xp;
  610.     int     func;
  611.     unsigned long   pm;
  612. {
  613.     XGCValues gcvfg, gcvbg;
  614.     unsigned long    fg, bg;
  615.  
  616.     fg = xp->foreground;
  617.     bg = xp->background;
  618.     gcvfg.graphics_exposures = False;
  619.     gcvbg.graphics_exposures = False;
  620.     gcvfg.plane_mask = pm;
  621.     gcvbg.plane_mask = pm;
  622.     gcvfg.function = func;
  623.     gcvbg.function = func;
  624.     
  625.     if (func == GXxor) {
  626.     /* Make test look good visually if possible */
  627.     gcvbg.foreground = gcvfg.foreground = bg ^ fg;
  628.     gcvbg.background = gcvfg.background = bg;
  629.     } else {
  630.     gcvfg.foreground = fg;
  631.     gcvfg.background = bg;
  632.     gcvbg.foreground = bg;
  633.     gcvbg.background = fg;
  634.     }
  635.     xp->fggc = XCreateGC(xp->d, xp->w,
  636.     GCForeground | GCBackground | GCGraphicsExposures
  637.       | GCFunction | GCPlaneMask, &gcvfg);
  638.     xp->bggc = XCreateGC(xp->d, xp->w, 
  639.     GCForeground | GCBackground | GCGraphicsExposures
  640.       | GCFunction | GCPlaneMask, &gcvbg);
  641. }
  642.  
  643.  
  644. void DestroyPerfGCs(xp)
  645.     XParms(xp);
  646. {
  647.     XFreeGC(xp->d, xp->fggc);
  648.     XFreeGC(xp->d, xp->bggc);
  649. }
  650.  
  651. int AllocateColor(display, name, pixel)
  652.     Display     *display;
  653.     char    *name;
  654.     int        pixel;
  655. {
  656.     XColor      color;
  657.  
  658.     if (name != NULL) {
  659.     /* Try to parse color name */
  660.     if (XParseColor(display, cmap, name, &color)) {
  661.         if (XAllocColor(display, cmap, &color)) {
  662.         pixel = color.pixel;
  663.         } else {
  664.         (void) fprintf(stderr,
  665.             "Can't allocate colormap entry for color %s\n", name);
  666.         }
  667.     } else {
  668.         (void) fprintf(stderr, "Can't parse color name %s\n", name);
  669.     }
  670.     }
  671.     return pixel;
  672. } /* AllocateColor */
  673.  
  674.  
  675. void DisplayStatus(d, message, test)
  676.     Display *d;
  677.     char    *message;
  678.     char    *test;
  679. {
  680.     char    s[500];
  681.  
  682.     XClearWindow(d, status);
  683.     sprintf(s, "%s %s", message, test);
  684.     /* We should really look at the height, descent of the font, etc. but
  685.        who cares.  This works. */
  686.     XDrawString(d, status, tgc, 10, 13, s, strlen(s));
  687. }
  688.  
  689.  
  690. void ProcessTest(xp, test, func, pm, label)
  691.     XParms  xp;
  692.     Test    *test;
  693.     int     func;
  694.     unsigned long   pm;
  695.     char    *label;
  696. {
  697.     double  time, totalTime;
  698.     int     reps, fooreps;
  699.     int     j;
  700.  
  701.     CreatePerfGCs(xp, func, pm);
  702.     DisplayStatus(xp->d, "Calibrating", label);
  703.     reps = CalibrateTest(xp, test, seconds, &time);
  704.     if (reps != 0) {
  705.     DisplayStatus(xp->d, "Testing", label);
  706.     XDestroySubwindows(xp->d, xp->w);
  707.     XClearWindow(xp->d, xp->w);
  708.     reps = (*test->init) (xp, &test->parms, reps);
  709.     /* Create clip windows if requested */
  710.     CreateClipWindows(xp, test->clips);
  711.  
  712.     totalTime = 0.0;
  713.     for (j = 0; j != repeat; j++) {
  714.         time = DoTest(xp, test, reps);
  715.         totalTime += time;
  716.         ReportTimes (time, reps * test->parms.objects,
  717.             label, False);
  718.     }
  719.     if (repeat > 1) {
  720.         ReportTimes(totalTime,
  721.         repeat * reps * test->parms.objects,
  722.         label, True);
  723.     }
  724.     (*test->cleanup) (xp, &test->parms);
  725.     DestroyClipWindows(xp, test->clips);
  726.     } else {
  727.     /* Test failed to initialize properly */
  728.     }
  729.     printf ("\n");
  730.     fflush(stdout);
  731.     DestroyPerfGCs(xp);
  732. } /* ProcessTest */
  733.  
  734.  
  735. main(argc, argv)
  736.     int argc;
  737.     char **argv;
  738.  
  739. {
  740.     int        i, j, n, skip;
  741.     int        numTests;       /* Even though the linker knows, we don't. */
  742.     char    hostname[100];
  743.     char    *displayName;
  744.     Bool    foundOne = False;
  745.     Bool    synchronous = False;
  746.     XGCValues    tgcv;
  747.     int        screen;
  748.     int        rop, pm;
  749.     XVisualInfo *vinfolist, vinfotempl;
  750.     unsigned long vmask;
  751.  
  752.     /* Save away argv, argc, for usage to print out */
  753.     saveargc = argc;
  754.     saveargv = (char **) malloc(argc * sizeof(char *));
  755.     for (i = 0; i != argc; i++) {
  756.     saveargv[i] = argv[i];
  757.     }
  758.  
  759.     xparms.pack = False;
  760.     xparms.version = VERSION1_3;
  761.  
  762.     /* Count number of tests */
  763.     ForEachTest(numTests);
  764.     doit = (Bool *)calloc(numTests, sizeof(Bool));
  765.  
  766.     /* Parse arguments */
  767.     program_name = argv[0];
  768.     displayName = Get_Display_Name (&argc, argv);
  769.     xparms.version = GetVersion(&argc, argv);
  770.     for (i = 1; i != argc; i++) {
  771.     if (strcmp (argv[i], "-all") == 0) {
  772.         ForEachTest (j)
  773.         doit[j] = True;
  774.         foundOne = True;
  775.     } else if (strcmp (argv[i], "-labels") == 0) {
  776.         labels = True;
  777.     } else if (strcmp(argv[i], "-range") == 0) {
  778.         char *cp1;
  779.         char *cp2;
  780.         
  781.         if (argc <= ++i)
  782.         usage();
  783.         cp1 = argv[i];
  784.         if (*cp1 == '-')
  785.         *cp1++;
  786.         for (cp2 = cp1; *cp2 != '\0' && *cp2 != ','; cp2++) {};
  787.         if (*cp2 == ',') {
  788.         *cp2++ = '\0';
  789.         if (*cp2 == '-')
  790.             *cp2++;
  791.         } else {
  792.         cp2 = "-";
  793.         }
  794.         ForEachTest (j) {
  795.         if (strcmp (cp1, (test[j].option) + 1) == 0 &&
  796.             (test[j].versions & xparms.version)) {
  797.             int k = j;
  798.             do {
  799.             doit[k] = True;
  800.             } while (strcmp(cp2, (test[k].option + 1)) != 0 &&
  801.                  (test[k].versions & xparms.version) &&
  802.                  test[++k].option != NULL);
  803.             if (*cp2 != '-' && test[k].option == NULL)
  804.             usage();
  805.             break;
  806.         }
  807.         }
  808.         if (test[j].option == NULL)
  809.         usage();
  810.         foundOne = True;
  811.     } else if (strcmp (argv[i], "-sync") == 0) {
  812.         synchronous = True;
  813.     } else if (strcmp(argv[i], "-pack") == 0) {
  814.         xparms.pack = True;
  815.     } else if (strcmp (argv[i], "-draw") == 0) {
  816.         drawToFakeServer = True;
  817.     } else if (strcmp (argv[i], "-repeat") == 0) {
  818.         i++;
  819.         if (argc <= i)
  820.         usage ();
  821.         repeat = atoi (argv[i]);
  822.         if (repeat <= 0)
  823.            usage ();
  824.     } else if (strcmp (argv[i], "-time") == 0) {
  825.         i++;
  826.         if (argc <= i)
  827.         usage ();
  828.         seconds = atoi (argv[i]);
  829.         if (seconds <= 0)
  830.            usage ();
  831.     } else if (strcmp(argv[i], "-fg") == 0) {
  832.         i++;
  833.         if (argc <= i)
  834.         usage ();
  835.         foreground = argv[i];
  836.         } else if (strcmp(argv[i], "-bg") == 0) {
  837.         i++;
  838.         if (argc <= i)
  839.         usage ();
  840.         background = argv[i];
  841.     } else if (strcmp(argv[i], "-rop") == 0) {
  842.         skip = GetRops (i+1, argc, argv, rops, &numRops);
  843.         i += skip;
  844.     } else if (strcmp(argv[i], "-pm") == 0) {
  845.         skip = GetNumbers (i+1, argc, argv, planemasks, &numPlanemasks);
  846.         i += skip;
  847.     } else if (strcmp(argv[i], "-xor") == 0) {
  848.         numRops = 1;
  849.         rops[0] = GXxor;
  850.     } else if (strcmp (argv[i], "-both") == 0) {
  851.         numRops = 2;
  852.         rops[0] = GXcopy;
  853.         rops[1] = GXxor;
  854.     } else if (strcmp(argv[i], "-reps") == 0) {
  855.         i++;
  856.         if (argc <= i)
  857.         usage ();
  858.         fixedReps = atoi (argv[i]);
  859.         if (fixedReps <= 0)
  860.         usage ();
  861.         } else if (strcmp(argv[i], "-depth") == 0) {
  862.         i++;
  863.         if (argc <= i)
  864.                 usage ();
  865.             depth = atoi(argv[i]);
  866.             if (depth <= 0)
  867.         usage ();
  868.     } else if (strcmp(argv[i], "-subs") == 0) {
  869.         skip = GetNumbers (i+1, argc, argv, subWindows, &numSubWindows);
  870.         i += skip;
  871. /*    } else if (strcmp(argv[i], "-v1.2") == 0) {
  872.         xparms.version = VERSION1_2;
  873. */    } else {
  874.         ForEachTest (j) {
  875.         if (strcmp (argv[i], test[j].option) == 0 &&
  876.             (test[j].versions & xparms.version)) {
  877.             doit[j] = True;
  878.             goto LegalOption;
  879.         }
  880.         }
  881.         usage ();
  882.     LegalOption: 
  883.         foundOne = True;
  884.     }
  885.     }
  886.  
  887.     if (labels) {
  888.     /* Just print out list of tests for use with .sh programs that
  889.        assemble data from different x11perf runs into a nice format */
  890.     ForEachTest (i) {
  891.         int child;
  892.         if (doit[i] && (test[i].versions & xparms.version)) {
  893.         switch (test[i].testType) {
  894.             case NONROP:
  895.             printf ("%s\n", test[i].label);
  896.             break;
  897.     
  898.             case ROP:
  899.             /* Run it through all specified rops and planemasks */
  900.             for (rop = 0; rop < numRops; rop++) {
  901.                 for (pm = 0; pm < numPlanemasks; pm++) {
  902.                 if (planemasks[pm] == ~0) {
  903.                     if (rops[rop] == GXcopy) {
  904.                     printf ("%s\n", test[i].label);
  905.                     } else {
  906.                     printf ("(%s) %s\n",
  907.                         ropNames[rops[rop]].name,
  908.                         test[i].label);
  909.                     }
  910.                 } else {
  911.                     printf ("(%s 0x%x) %s\n",
  912.                         ropNames[rops[rop]].name,
  913.                         planemasks[pm],
  914.                         test[i].label);
  915.                 }
  916.                 } /* for pm */
  917.             } /* for rop */
  918.             break;
  919.             
  920.             case WINDOW:
  921.             for (child = 0; child != numSubWindows; child++) {
  922.                 printf ("%s (%d kids)\n",
  923.                 test[i].label, subWindows[child]);
  924.             }
  925.             break;
  926.         } /* switch */
  927.         }
  928.     }
  929.     exit(0);
  930.     }
  931.  
  932.     if (!foundOne)
  933.     usage ();
  934.     xparms.d = Open_Display (displayName);
  935.     screen = DefaultScreen(xparms.d);
  936.  
  937.     /* get visual info of default visual */
  938.     vmask = VisualIDMask | VisualScreenMask;
  939.     vinfotempl.visualid = XVisualIDFromVisual(XDefaultVisual(xparms.d, screen));
  940.     vinfotempl.screen = screen;
  941.     vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n);
  942.     if (!vinfolist || n != 1) {
  943.     fprintf (stderr, "%s: can't get visual info of default visual\n",
  944.         program_name);
  945.     exit(1);
  946.     }
  947.  
  948.     if (depth == -1) {
  949.     /* use the default visual and colormap */
  950.     xparms.vinfo = *vinfolist;
  951.     cmap = XDefaultColormap(xparms.d, screen);
  952.     } else {
  953.     /* find the specified visual */
  954.     vmask = VisualDepthMask | VisualScreenMask;
  955.     vinfotempl.depth = depth;
  956.     vinfotempl.screen = screen;
  957.     vinfolist = XGetVisualInfo(xparms.d, vmask, &vinfotempl, &n);
  958.     if (!vinfolist) {
  959.         fprintf (stderr, "%s: can't find a visual of depth %d\n",
  960.         program_name, depth);
  961.         exit(1);
  962.     }
  963.     xparms.vinfo = *vinfolist;  /* use the first one in list */
  964.     if (xparms.vinfo.visualid ==
  965.         XVisualIDFromVisual(XDefaultVisual(xparms.d, screen))) {
  966.         /* matched visual is same as default visual */
  967.         cmap = XDefaultColormap(xparms.d, screen);
  968.     } else {
  969.         cmap = XCreateColormap(xparms.d, DefaultRootWindow(xparms.d),
  970.         xparms.vinfo.visual, AllocNone);
  971.         /* since this is not default cmap, must force color allocation */
  972.         if (!foreground) foreground = "Black";
  973.         if (!background) background = "White";
  974.     }
  975.     }
  976.  
  977.     printf("x11perf - X11 performance program, version 1.3\n");
  978. #ifndef VMS
  979.     gethostname (hostname, 100);
  980.     printf ("%s server on %s\nfrom %s\n",
  981.         ServerVendor (xparms.d), DisplayString (xparms.d), hostname);
  982. #else
  983.     printf ("%s server on %s\n",
  984.         ServerVendor (xparms.d), DisplayString (xparms.d));
  985. #endif
  986.     PrintTime ();
  987.  
  988.     /* Force screen out of screen-saver mode, grab current data, and set
  989.        time to blank to 8 hours.  We should just be able to turn the screen-
  990.        saver off, but this causes problems on some servers.  We also reset
  991.        the screen-saver timer each test, as 8 hours is about the maximum time
  992.        we can use, and that isn't long enough for some X terminals using a
  993.        serial protocol to finish all the tests.  As long as the tests run to 
  994.        completion, the old screen-saver values are restored. */
  995.     XForceScreenSaver(xparms.d, ScreenSaverReset);
  996.     XGetScreenSaver(xparms.d, &ssTimeout, &ssInterval, &ssPreferBlanking,
  997.     &ssAllowExposures);
  998.     (void) signal(SIGINT, Cleanup); /* ^C */
  999.     (void) signal(SIGQUIT, Cleanup);
  1000.     (void) signal(SIGTERM, Cleanup);
  1001.     (void) signal(SIGHUP, Cleanup);
  1002.     XSetScreenSaver(xparms.d, 8 * 3600, ssInterval, ssPreferBlanking, 
  1003.     ssAllowExposures);
  1004.  
  1005.     if (drawToFakeServer) {
  1006.         tileToQuery =
  1007.         XCreatePixmap(xparms.d, DefaultRootWindow (xparms.d), 32, 32, 1);
  1008.     }
  1009.  
  1010.  
  1011.     xparms.foreground =
  1012.     AllocateColor(xparms.d, foreground, BlackPixel(xparms.d, screen));
  1013.     xparms.background =
  1014.     AllocateColor(xparms.d, background, WhitePixel(xparms.d, screen));
  1015.     xparms.w = CreatePerfWindow(&xparms, 2, 2, WIDTH, HEIGHT);
  1016.     status = CreatePerfWindow(&xparms, 2, HEIGHT+5, WIDTH, 20);
  1017.     tgcv.foreground = BlackPixel(xparms.d, screen);
  1018.     tgcv.background = WhitePixel(xparms.d, screen);
  1019.     tgc = XCreateGC(xparms.d, status, GCForeground | GCBackground, &tgcv);
  1020.    
  1021.  
  1022.     if (synchronous)
  1023.     XSynchronize (xparms.d, True);
  1024.  
  1025.     /* Get mouse pointer out of the way of the performance window.  On
  1026.        software cursor machines it will slow graphics performance.  On
  1027.        all current MIT-derived servers it will slow window 
  1028.        creation/configuration performance. */
  1029.     XWarpPointer(xparms.d, None, status, 0, 0, 0, 0, WIDTH, 20);
  1030.  
  1031.     /* Figure out how long to call HardwareSync, so we can adjust for that
  1032.        in our total elapsed time */
  1033.     (void) CalibrateTest(&xparms, &syncTest, 1, &syncTime);
  1034.     printf("Sync time adjustment is %6.4f msecs.\n\n", syncTime/1000);
  1035.  
  1036.     ForEachTest (i) {
  1037.     int child;
  1038.     char label[200];
  1039.  
  1040.     if (doit[i] && (test[i].versions & xparms.version)) {
  1041.         switch (test[i].testType) {
  1042.             case NONROP:
  1043.             /* Simplest...just run it once */
  1044.             strcpy (label, test[i].label);
  1045.             ProcessTest(&xparms, &test[i], GXcopy, ~0, label);
  1046.             break;
  1047.  
  1048.         case ROP:
  1049.             /* Run it through all specified rops and planemasks */
  1050.             for (rop = 0; rop < numRops; rop++) {
  1051.             for (pm = 0; pm < numPlanemasks; pm++) {
  1052.                 if (planemasks[pm] == ~0) {
  1053.                 if (rops[rop] == GXcopy) {
  1054.                     sprintf (label, "%s", test[i].label);
  1055.                 } else {
  1056.                     sprintf (label, "(%s) %s",
  1057.                     ropNames[rops[rop]].name,
  1058.                     test[i].label);
  1059.                 }
  1060.                 } else {
  1061.                 sprintf (label, "(%s 0x%x) %s",
  1062.                     ropNames[rops[rop]].name,
  1063.                     planemasks[pm],
  1064.                     test[i].label);
  1065.                 }
  1066.                 ProcessTest(&xparms, &test[i], rops[rop],
  1067.                         planemasks[pm], label);
  1068.             } /* for pm */
  1069.             } /* for rop */
  1070.             break;
  1071.         
  1072.         case WINDOW:
  1073.             /* Loop through number of children array */
  1074.             for (child = 0; child != numSubWindows; child++) {
  1075.             test[i].parms.objects = subWindows[child];
  1076.             sprintf(label, "%s (%d kids)",
  1077.                 test[i].label, test[i].parms.objects);
  1078.             ProcessTest(&xparms, &test[i], GXcopy, ~0, label);
  1079.             }
  1080.             break;
  1081.         } /* switch */
  1082.     } /* if doit */
  1083.     } /* ForEachTest */
  1084.  
  1085.     XDestroyWindow(xparms.d, xparms.w);
  1086.  
  1087.     /* Restore ScreenSaver to original state. */
  1088.     XSetScreenSaver(xparms.d, ssTimeout, ssInterval, ssPreferBlanking,
  1089.     ssAllowExposures);
  1090.     XCloseDisplay(xparms.d);
  1091. }
  1092.  
  1093. int
  1094. GetWords (argi, argc, argv, wordsp, nump)
  1095.     int     argi;
  1096.     int     argc;
  1097.     char    **argv;
  1098.     char    **wordsp;
  1099.     int     *nump;
  1100. {
  1101.     int        count;
  1102.  
  1103.     if (argc <= argi)
  1104.     usage();
  1105.     count = 0;
  1106.     while (argv[argi] && *(argv[argi]) != '-') {
  1107.     *wordsp++ = argv[argi];
  1108.     ++argi;
  1109.     count++;
  1110.     }
  1111.     *nump = count;
  1112.     return count;
  1113. }
  1114.  
  1115. int atox (s)
  1116.     char    *s;
  1117. {
  1118.     int     v, c;
  1119.  
  1120.     v = 0;
  1121.     while (*s) {
  1122.     if ('0' <= *s && *s <= '9')
  1123.         c = *s - '0';
  1124.     else if ('a' <= *s && *s <= 'f')
  1125.         c = *s - 'a' + 10;
  1126.     else if ('A' <= *s && *s <= 'F')
  1127.         c = *s - 'A' + 10;
  1128.     v = v * 16 + c;
  1129.     s++;
  1130.     }
  1131.     return v;
  1132. }
  1133.  
  1134. int GetNumbers (argi, argc, argv, intsp, nump)
  1135.     int     argi;
  1136.     int     argc;
  1137.     char    **argv;
  1138.     int     *intsp;
  1139.     int     *nump;
  1140. {
  1141.     char    *words[256];
  1142.     int        count;
  1143.     int        i;
  1144.     int        flip;
  1145.  
  1146.     count = GetWords (argi, argc, argv, words, nump);
  1147.     for (i = 0; i < count; i++) {
  1148.     flip = 0;
  1149.     if (!strncmp (words[i], "~", 1)) {
  1150.         words[i]++;
  1151.         flip = ~0;
  1152.     }
  1153.     if (!strncmp (words[i], "0x", 2))
  1154.         intsp[i] = atox(words[i] + 2) ^ flip;
  1155.     else
  1156.         intsp[i] = atoi (words[i]) ^ flip;
  1157.     }
  1158.     return count;
  1159. }
  1160.  
  1161. GetRops (argi, argc, argv, ropsp, nump)
  1162.     int     argi;
  1163.     int     argc;
  1164.     char    **argv;
  1165.     int     *ropsp;
  1166.     int     *nump;
  1167. {
  1168.     char    *words[256];
  1169.     int        count;
  1170.     int        i;
  1171.     int        rop;
  1172.  
  1173.     count = GetWords (argi, argc, argv, words, nump);
  1174.     for (i = 0; i < count; i++) {
  1175.     if (!strncmp (words[i], "GX", 2))
  1176.         words[i] += 2;
  1177.     if (!strcmp (words[i], "all")) {
  1178.         for (i = 0; i < 16; i++)
  1179.         ropsp[i] = ropNames[i].rop;
  1180.         *nump = 16;
  1181.         break;
  1182.     }
  1183.     for (rop = 0; rop < 16; rop++) {
  1184.         if (!strcmp (words[i], ropNames[rop].name)) {
  1185.         ropsp[i] = ropNames[rop].rop;
  1186.         break;
  1187.         }
  1188.     }
  1189.     if (rop == 16) {
  1190.         fprintf (stderr, "unknown rop name %s\n", words[i]);
  1191.         usage ();
  1192.     }
  1193.     }
  1194.     return count;
  1195. }
  1196.