/* $Id: showaccel2.c,v 1.1.1.1 2001/05/12 23:03:32 cegger Exp $
******************************************************************************

   showaccel2.c - same as showaccel.c but uses fork() instead of
   		  "cooperative multitasking"

   Written in 1998 by Andreas Beck	[becka@ggi-project.org]

   This software is placed in the public domain and can be used freely
   for any purpose. It comes without any kind of warranty, either
   expressed or implied, including, but not limited to the implied
   warranties of merchantability or fitness for a particular purpose.
   Use it at your own risk. the author is not responsible for any damage
   or consequences raised by use or inability to use this program.

******************************************************************************

   This programs gives an estimate about the amount of acceleration in a
   target. It measures the speed of drawing lines using drawbox as compared
   to drawing them with multiple horizontal lines.

   As a rough guideline, here are values from to targets as measured on the
   authors system:

   GGI_DISPLAY="x"    ./showaccel  Ratio :   134479 :   114610 = 1.173362
   GGI_DISPLAY="xlib" ./showaccel  Ratio :   226929 :    23071 = 9.836115

   What you can derive from the above example is: 

   Ratios of up to around 1.2 are not indicating a significant drawing
   acceleration. This is just calling overhead
   Running over xlib _dramatically_ shows another kind of "calling overhead", 
   as the xlib target produces a network call for each primitive call.
   So be careful when interpreting the results.

******************************************************************************
*/

#include <stdlib.h>
#include <unistd.h>

#include <ggi/ggi.h>

#include "config.h"

ggi_visual_t vis;

/* wrapper function for easy porting. returns a number between
 * 0 and max-1 (including borders).
 */
int randnum(int max)
{ return (rand()%max); }


/* Draw a box from individual horizontal lines. This effectively disables
 * acceleration code for boxes to some extent. Depending on the underlying
 * implementation, this may not be a good solution.
 */

static inline int slow_drawbox(int x,int y,int w,int h)
{
	while(h--) ggiDrawHLine(vis,x,y++,w); 
	return 0;
}

/* The main function. Draw boxes with two different methods from two different
 * processes.
 */
int main(int argc, char *argv[])
{
	/* Loop counters and other helpers
	 */
	int c,y;

	/* The visible screen sizes
	 */
	int sx,sy;

	/* The palette and wanted color table.
	 */
	ggi_color pal[256];

	/* The color translation table.
	 */
	ggi_uint paletteval[256];

	/* Initialize GGI. Error out, if it fails.
	 */
	if (ggiInit() != 0) {
		fprintf(stderr, "%s: unable to initialize LibGGI, exiting.\n",
			argv[0]);
		exit(1);
	}
	/* Open the default GGI visual. Exit on error.
	 */
	if ((vis=ggiOpen(NULL)) == NULL) {
		ggiExit();
		fprintf(stderr,
			"%s: unable to open default visual, exiting.\n",
			argv[0]);
		exit(1);
	}

        /* If mode setup fails, fall through to the end.
         */
	if (ggiSetSimpleMode(vis, GGI_AUTO, GGI_AUTO, GGI_AUTO, GT_AUTO)
	    == 0) {
		/* We asked for automatic setup. So we better ask what we got.
		 * We will need the visible dimensions.
		 */
		{
			ggi_mode mode;
			ggiGetMode(vis,&mode);
			sx=mode.visible.x;
			sy=mode.visible.y;
		}

		/* Clear the screen
		 */
		ggiSetGCForeground(vis,0);
		ggiFillscreen(vis);

		/* Set up a colorful palette.
		 */
		for(c=0;c<256;c++) { 
			pal[c].r=c*256;
			pal[c].g=256*(255-c);
			pal[c].b=(128-abs(128-c))*7*64;
		}
		/* And send it to the visual. In case we are in a 
		 * non-palletized mode, this simply fails.
		 */
		ggiSetPalette(vis,0,256,pal);

		/* However this call ensures, that we always get a set of
		 * "handles" for the colors we want. This makes programs 
		 * designed for use with 8 bit palette mode run on the
		 * other graphtypes as well. You just get back the color
		 * value to use for the closest available color.
		 */
		for(c=0;c<256;c++)
			paletteval[c]=ggiMapColor(vis,&pal[c]);
     
		/* Set foreground to color 255 (red) and print the headlines.
		 */
		ggiSetGCForeground(vis,paletteval[255]);
		ggiPuts(vis,0,0,"Accelerated");
		ggiPuts(vis,sx/2,0,"Mundane");

		switch(fork()) {
			case 0:
				for(y=0;y<1000000;y++) {
					ggiSetGCForeground(vis,randnum(256));
					ggiDrawBox(vis, randnum(sx/4),randnum(sy/2),
							randnum(sx/4),randnum(sy/2));
				} 
				exit(0);
				break;
			default:
				for(y=0;y<1000000;y++) { 
					ggiSetGCForeground(vis,randnum(256));
				slow_drawbox(randnum(sx/4)+sx/2,randnum(sy/2),
					     randnum(sx/4)     ,randnum(sy/2));
				}
		}
	}

	/* Close down LibGGI.
	 */
	ggiClose(vis);
	ggiExit();
	return(0);
}
