static char SCCSID[] = "@(#)dobenches.c	1.6 89/02/22";
/*
 * Copyright 1989 Siemens
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Siemens not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  Siemens makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * Author:  Claus Gittinger, Siemens Munich, unido!sinix!claus@uunet.uu.net
 */

#include <stdio.h>
#include <signal.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "benches.h"
#include "externals.h"

int benchRunning;

static stopBench() {
	benchRunning = 0;
}

doBenches(dpy, win, ask, nruns, timeGoal, level, onlyList, exclList)
Display *dpy;
Window win;
char *onlyList[], *exclList[];
{
	int     index;
	long    startTime;
	long    endTime;
	long    deltaT;
	FUNCPTR setupFunc, benchFunc, cleanupFunc, messageFunc;
	int     benchArg;
	int     benchCount, maxBenchCount, maxDeltaT;
	int     error, run;
	int     exclude;
	XImage  img;
	unsigned allplanes = 0xFFFFFFFF;
	double   perf;
	char     buffer[80];
	int	 savSync;

	index = 0;

	savSync = sync;
	for ( ;benchList[index].benchFunc != NOFUNC; index++) {
	    sync = savSync;
	    exclude = 0;
	    if (onlyList[0] != NULL) {
		if (! isInList(benchList[index].name, onlyList))
		    exclude = 1;
	    }
	    if (exclList[0] != NULL) {
		if (isInList(benchList[index].name, exclList))
		    exclude = 1;
	    }

	    if (benchList[index].level <= level) {
		if (! exclude) {
		    if (ask) {
			int c;

			XSync(dpy, 0);
			fprintf(stderr, "next bench: %s wanted? (y/s/n) ",
						benchList[index].name);
			do {
			    c = getchar();
			    if (c == '!') {
			        while (c != '\n') c = getchar();
			    }
			} while ((c != 'y') && (c != 'n') && (c != 's'));

			if (c == 'n')
			    exclude = 1;
			if (c == 's')
			    sync = 1;
			XSync(dpy, 0);
		    }

		    if (! exclude) {
			setupFunc = benchList[index].setupFunc;
			benchFunc = benchList[index].benchFunc;
			cleanupFunc = benchList[index].cleanupFunc;
			messageFunc = benchList[index].messageFunc;
			benchArg = benchList[index].benchArg;

			XMapWindow(dpy, win);
			XClearWindow(dpy, win);

			if (setupFunc != NOFUNC)
			    error = (*setupFunc)(dpy, win, benchArg);

			if (! error) {
			    maxBenchCount = 0;
			    for (run=1; run <= nruns; run++) {
			        sprintf(buffer, "%s run %d", 
						benchList[index].name, run);
			        XDrawImageString(dpy, win, 
						 DefaultGC(dpy, 
							   DefaultScreen(dpy)),
						 0, screenHeight-10,
						 buffer, strlen(buffer));

				XSync(dpy, 1);
				sleep(1);
				benchRunning = 1;
				signal(SIGALRM, stopBench);
				alarm(timeGoal, stopBench);
				startTime = time(0);
				benchCount = (*benchFunc)(dpy, win, benchArg);

				XSync(dpy, 0);
				/*
				 * sorry about this ...
				 * since there are servers with (big)
				 * command queues to the display hardware
				 * and I want to know, when the picture is on
				 * the screen - (not in the server)
				 * Im doing a small get image to really sync
				 * I hope, the getimage on the tested
				 * server is not too slow to make the whole
				 * benchmark data unusable.
				 */
				XGetImage(dpy, win, 0, 0, 1, 1,
						    XAllPlanes(), ZPixmap);

				endTime = time(0);
				deltaT = endTime - startTime;
				if (benchCount > maxBenchCount) {
				    maxBenchCount = benchCount;
				    maxDeltaT = deltaT;
				}
			    }

			    if (cleanupFunc != NOFUNC)
				(*cleanupFunc)(dpy, win, benchArg);
			    XSync(dpy, 1);
			}
			XUnmapWindow(dpy, win);
		    }
		}

		printf("========= %s ========= %s\n",
			benchList[index].name,
			sync ? "sync" : "");

		if (exclude || error) {
		    printf("TEST NOT RUN\n");
		} else {
		    perf = (double)(maxBenchCount)/(double)(maxDeltaT);
		    (*messageFunc)(maxDeltaT, maxBenchCount, benchArg, perf);
		}
		fflush(stdout);
	    }
	}
	printf("==================================================\n");
	printf("\n");
}

#define LINELEN 79
listBenches()
{
	int     col, index;
	char lineBuffer[LINELEN+1];

	printf("available benches:\n");
	printf("\n");
	col = 0;
	strblank(lineBuffer, LINELEN);
	for (index=0; benchList[index].benchFunc != NOFUNC; index++) {
	    strinsert(lineBuffer, benchList[index].name, col*19);
	    col++;
	    if (col == 4) {
		printf("%s\n", lineBuffer);
		col = 0;
		strblank(lineBuffer, LINELEN);
	    }
	}
	printf("%s\n", lineBuffer);
}

static strblank(s, n)
char *s;
{
	while (n--) *s++ = ' ';
	*s++ = '\0';
}

static strinsert(s1, s2, pos)
char *s1, *s2;
{
	s1 += pos;
	while (*s2) {
	    *s1++ = *s2++;
	}
}

static isInList(s, l)
char *s;
char *l[];
{
	int index;

	for (index=0; l[index] != NULL; index++) {
	    if (strcmp(s, l[index])==0) return 1;
	}
	return 0;
}
