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

     FONCTION :
     ----------
        file OpenGl_togl_redraw.c :
 

     REMARQUES:
     ---------- 
      

     HISTORIQUE DES MODIFICATIONS   :
     --------------------------------
       xx-xx-xx : CAL ; Creation.
       23-01-97 : CAL : Ajout pour mettre des traces facilement
			apres lancement de Designer
       05-02-97 : FMN ; Suppression de OpenGl_tgl_vis.h
       03-03-97 : FMN ; (PRO4063) Ajout displaylist pour le mode transient
       07-10-97 : FMN ; Simplification WNT
       08-08-98 : FMN ; ajout PRINT debug
       18-11-98 : CAL ; S4062. Ajout des layers.
       15-11-99 : GG  ; Add call_togl_redraw_area()
       15-11-99 : VKH ; G004 redrawing view to a large pixmap
       02.01.100 : JR : = 0 for Integer and = NULL for pointers
       02.02.100   "    #include <GL/glu.h> for declaration of gluErrorString
       07-03-00 : GG : G004 use the already created pixmap.
		       Enable two side lighting before redrawing in pixmap.

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

#define G004	/* VKH 15-11-99 redrawing view to a large pixmap
*/

#define IMP100701	/* GG Enable to display the view in
			a pixamp with the required depth.
*/

#define RIC120302	/* GG Enable to use the application display
//			callback at end of traversal
*/

/*----------------------------------------------------------------------*/
/*
 * Includes
 */

#include <OpenGl_tgl_all.h>
#include <InterfaceGraphic_Graphic3d.hxx>
#include <InterfaceGraphic_Visual3d.hxx>
#include <OpenGl_tsm_ws.h>
#include <OpenGl_tgl.h>
#include <OpenGl_txgl.h>
#include <OpenGl_tgl_tox.h>
#include <OpenGl_tgl_funcs.h>
#include <OpenGl_tgl_subrvis.h>
#include <GL/gl.h>
#include <GL/glu.h>

/*
   call_togl_redraw (aview, anunderlayer, anoverlayer)
   CALL_DEF_VIEW * aview,
   CALL_DEF_LAYER * anunderlayer,
   CALL_DEF_LAYER * anoverlayer

	Redraws all the structures displayed in the specified view.

   call_togl_redraw_area (aview, anunderlayer, anoverlayer, x, y, width, height)
   CALL_DEF_VIEW * aview,
   CALL_DEF_LAYER * anunderlayer,
   CALL_DEF_LAYER * anoverlayer,
   int x,y,width,height

	Redraws all the structures displayed in the specified view area
	defined by it upper-left corner and pixel size.
*/

#ifdef G004
#ifndef WNT
  #define CALL_DEF_STRING_LENGTH 132
#else
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <stdio.h>
#endif
GLboolean g_fBitmap;
#endif	/*G004*/


void EXPORT
call_togl_redraw
(
	CALL_DEF_VIEW * aview,
	CALL_DEF_LAYER * anunderlayer,
	CALL_DEF_LAYER * anoverlayer
)
{
CMN_KEY_DATA data;
Tint swap = 1; /* swap buffers ? yes */

      if ( TsmGetWSAttri (aview->WsId, WSWindow, &data) != TSuccess ) return;
#ifdef G004
      if ( !aview->DefBitmap.bitmap ) {	/* redrawing view to the window */
#endif
	if (TxglWinset (call_thedisplay, (Window) data.ldata) == TSuccess) {
	    call_func_redraw_all_structs_begin (aview->WsId);
	    if (anunderlayer->ptrLayer)
		call_togl_redraw_layer2d (aview, anunderlayer);
	    call_func_redraw_all_structs_proc (aview->WsId);
	    if (anoverlayer->ptrLayer)
		call_togl_redraw_layer2d (aview, anoverlayer);
#ifdef RIC120302
	    call_subr_displayCB(aview,OCC_REDRAW_WINDOW);
#endif
	    call_func_redraw_all_structs_end (aview->WsId, swap);
	    call_togl_redraw_immediat_mode (aview);
	}
#ifdef G004
      }	else {
	  CMN_KEY_DATA          pixdata;
	  GLenum                errorcode = 0;
#ifndef WNT
  	  int  n,sdesc[11];
  	  XVisualInfo*        XVInfo = NULL;
  	  XWindowAttributes   wattr;
  	  GLXPixmap           theGLXPixmap = 0;
  	  GLXContext          theContext = NULL;

          XGetWindowAttributes ( call_thedisplay, (Window)data.ldata , &wattr );
#ifdef IMP100701
 	  if( aview->DefBitmap.depth > 0 )
		wattr.depth = aview->DefBitmap.depth;
#endif
          n = 0;
          sdesc[n] = GLX_RGBA; n++;
          sdesc[n] = GLX_DEPTH_SIZE; n++;
#ifdef IMP100701
          sdesc[n] = wattr.depth; n++;
#else
          sdesc[n] = 1; n++;
#endif
          sdesc[n] = GLX_RED_SIZE; n++;
          sdesc[n] = ( wattr.depth <= 8 ) ? 0 : 1; n++;
          sdesc[n] = GLX_GREEN_SIZE; n++;
          sdesc[n] = ( wattr.depth <= 8 ) ? 0 : 1; n++;
          sdesc[n] = GLX_BLUE_SIZE; n++;
          sdesc[n] = ( wattr.depth <= 8 ) ? 0 : 1; n++;
#ifdef BUG	/* Redraw always in single buffer mode and don't swap ! */
  	  char                string[CALL_DEF_STRING_LENGTH];
          if ( !call_util_osd_getenv ("CALL_OPENGL_NO_DBF", string, CALL_DEF_STRING_LENGTH) )
          { sdesc[n] = GLX_DOUBLEBUFFER; n++; }
#endif
          sdesc[n] = None; n++;

          XVInfo = glXChooseVisual ( call_thedisplay, DefaultScreen(call_thedisplay), sdesc );
          if ( !XVInfo ) {
             fprintf ( stderr, "Visual not available\n" );
             return;
          }

          theContext = glXCreateContext ( call_thedisplay, XVInfo, NULL, GL_FALSE );

          theGLXPixmap = glXCreateGLXPixmap ( call_thedisplay, XVInfo, aview->DefBitmap.bitmap );

          if ( ! glXMakeCurrent (call_thedisplay, theGLXPixmap, theContext) )
          {
             errorcode = glGetError ();
             fprintf ( stderr, "glXMakeCurrent failed: %d %s\n", errorcode, gluErrorString(errorcode) );
             return;
          }
#else /* WindowsXX code here */
  	  HGLRC               hglrc_old = wglGetCurrentContext ();
  	  HDC                 hdc_old = wglGetCurrentDC ();
	  HDC		      hdc = (HDC) aview->DefBitmap.bitmap;
  	  HGLRC               hglrc = wglCreateContext (hdc);

          if ( !hglrc || !wglMakeCurrent (hdc, hglrc) )
          {
             errorcode = glGetError ();
             printf ( "wglMakeCurrent failed: %d %s\n", errorcode, gluErrorString(errorcode) );
             return;
          }
#endif
          pixdata.ldata = aview->DefBitmap.width;
          if ( TsmSetWSAttri (aview->WsId, WSWidth, &pixdata) != TSuccess ) return;
          pixdata.ldata = aview->DefBitmap.height;
          if ( TsmSetWSAttri (aview->WsId, WSHeight, &pixdata) != TSuccess ) return;

          /* generate new display lists */
          TsmInitAttributes();

          glLightModeli((GLenum)GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

          glMatrixMode ( GL_MODELVIEW );
          glViewport ( 0, 0, aview->DefBitmap.width, aview->DefBitmap.height );

          glDrawBuffer ( GL_FRONT );

          /* redrawing ... */
          g_fBitmap = GL_TRUE;
          call_func_redraw_all_structs_begin (aview->WsId);
          if (anunderlayer->ptrLayer)
          	call_togl_redraw_layer2d (aview, anunderlayer);
          call_func_redraw_all_structs_proc (aview->WsId);
          if (anoverlayer->ptrLayer)
          	call_togl_redraw_layer2d (aview, anoverlayer);
#ifdef RIC120302
	  call_subr_displayCB(aview,OCC_REDRAW_BITMAP);
#endif
          call_func_redraw_all_structs_end (aview->WsId, 0);

          call_togl_redraw_immediat_mode (aview);
          g_fBitmap = GL_FALSE;

          glFinish();

          /* cleaning up ... */
#ifndef WNT
          glXMakeCurrent ( call_thedisplay, None, NULL );
          glXDestroyContext ( call_thedisplay, theContext );
          glXDestroyGLXPixmap ( call_thedisplay, theGLXPixmap );
#else
          wglMakeCurrent ( hdc_old, hglrc_old );
          wglDeleteContext ( hglrc );
#endif
	}
#endif	/*G004*/

	return;
}

void EXPORT
call_togl_redraw_area
(
	CALL_DEF_VIEW * aview,
	CALL_DEF_LAYER * anunderlayer,
	CALL_DEF_LAYER * anoverlayer,
	int x, int y, int width, int height
)
{
CMN_KEY_DATA data;

/*
  When the exposure area size is > window size / 2 do a full redraw.
*/
	if( width*height > 
		(int)(aview->DefWindow.dx*aview->DefWindow.dy)/2 ) {
	  call_togl_redraw(aview,anunderlayer,anoverlayer);
	  return;
	}
/*
  Or redraw only the area in the front buffer
*/
	TsmGetWSAttri (aview->WsId, WSWindow, &data);
	if (TxglWinset (call_thedisplay, (Window) data.ldata) == TSuccess) {
	    GLint buffer;
	    glGetIntegerv(GL_DRAW_BUFFER,&buffer);
	    if( buffer != GL_FRONT ) glDrawBuffer (GL_FRONT);
	    glEnable( GL_SCISSOR_TEST );
	    glScissor( (GLint)x, 
		(GLint)((int)aview->DefWindow.dy - (y+height)), 
				(GLsizei)width, (GLsizei)height);
	    call_func_redraw_all_structs_begin (aview->WsId);
	    if (anunderlayer->ptrLayer)
		call_togl_redraw_layer2d (aview, anunderlayer);
	    call_func_redraw_all_structs_proc (aview->WsId);
	    if (anoverlayer->ptrLayer)
		call_togl_redraw_layer2d (aview, anoverlayer);
#ifdef RIC120302
	    call_subr_displayCB(aview,OCC_REDRAW_WINDOWAREA);
#endif
	    call_func_redraw_all_structs_end (aview->WsId, 0);
	    call_togl_redraw_immediat_mode (aview);
	    glFlush();
	    glDisable( GL_SCISSOR_TEST );
	    if( buffer != GL_FRONT ) glDrawBuffer (buffer);
	}
}
