/* single_double.c   command line argument  s  for single only  */
/*                   there are a few old or misconfigured       */
/*                   systems that do not support double buffer  */
/*  This program demonstrates double buffering for              */
/*  flicker-free animation.  The left and right mouse           */
/*  buttons start and stop the spinning motion of the square.   */
/* E. Angel, Interactive Computer Graphics */

#include <GL/glut.h>
#include <stdlib.h>

static GLfloat spin = 0.0;
static int singleb, doubleb;  /* window "handles" */
static int so=0;              /* signle only for old systems */

void displayd(void) /* double buffered */
{
  glClear (GL_COLOR_BUFFER_BIT);
  glRectf (-25.0, -25.0, 25.0, 25.0);
  glFlush();
  if(!so)glutSwapBuffers (); /* only for double buffered */
}

void displays(void) /* single buffered */
{
  glClear (GL_COLOR_BUFFER_BIT);
  glRectf (-25.0, -25.0, 25.0, 25.0);
  glFlush();
}

void spinDisplay(void) /* shared */
{
  spin = spin + 0.25;
  if (spin > 360.0)
     spin = spin - 360.0;
  glutSetWindow(singleb);  /* draw to single buffer */
  glLoadIdentity();
  glRotatef (spin, 0.0, 0.0, 1.0);
  glutPostRedisplay(); 
  glutSetWindow(doubleb);  /* draw to double buffer */
  glLoadIdentity();
  glRotatef (spin, 0.0, 0.0, 1.0);
  glutPostRedisplay();
}

void myinit(void) /* shared */
{
  glClearColor (0.0, 0.0, 0.0, 1.0);
  glColor3f (1.0, 1.0, 1.0);
  glShadeModel (GL_FLAT);
}

void mouse(int btn, int state, int x, int y) /* shared */
{
  if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
    glutIdleFunc(spinDisplay);
  if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
    glutIdleFunc(NULL);
}

void myReshape(int w, int h) /* shared */
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if (w <= h) 
    glOrtho (-50.0, 50.0, -50.0*(GLfloat)h/(GLfloat)w, 
             50.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0);
  else 
    glOrtho (-50.0*(GLfloat)w/(GLfloat)h, 
              50.0*(GLfloat)w/(GLfloat)h, -50.0, 50.0, -1.0, 1.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity ();
}

/*  Main Loop                                        */
/*  Open window with initial window size, title bar, */
/*  RGBA display mode, and handle input events.      */

int main(int argc, char* argv[])
{
  glutInit(&argc,argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
  glutInitWindowPosition(50,50);
  singleb=glutCreateWindow("single buffered");
  myinit ();
  glutDisplayFunc(displays); 
  glutReshapeFunc (myReshape);
  glutIdleFunc (spinDisplay);
  glutMouseFunc (mouse);
  if(argc>1) if(argv[1][0]=='s') so=0; /* user select single only */
  if(!so) glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
  if(so)  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
  glutInitWindowPosition(350,50);
  if(!so) doubleb=glutCreateWindow("double buffered");
  if(so)  doubleb=glutCreateWindow("fake double buffered");
  myinit ();
  glutDisplayFunc(displayd);
  glutReshapeFunc (myReshape);
  glutIdleFunc (spinDisplay);
  glutMouseFunc (mouse);
  glutMainLoop();
  return 0;
}

