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

     FONCTION :
     ----------
        File OpenGl_txgl :
 

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

     HISTORIQUE DES MODIFICATIONS   :
     --------------------------------
       xx-xx-xx : xxx ; Creation.
       07-02-96 : FMN ; Suppression code inutile:
			- TxglLink() et TxglUnlink()
       08-03-96 : FMN ; Suppression variables globales
			Ajout cmn_delete_from_htbl() dans TxglDestroyWindow()
       21-03-96 : CAL ; test sur previous_ctx dans TxglDestroyWindow()
			et dans TxglSetDbuff()
       01-04-96 : CAL ; Integration MINSK portage WNT
       15-04-96 : CAL ; Integration travail PIXMAP de Jim ROTH
       26-04-96 : FMN ; Correction warning de compilation
       20-06-96 : CAL ; Retrait du XDestroyWindow dans TxglDestroyWindow
       18-07-96 : FMN ; Suppression code inutile: TxglSetWindow().
       27-09-96 : CAL ; Portage WNT
       16-10-96 : GG  ; Coder le parametre de GLX_DEPTH_SIZE a 1 plutot
                        que 0 si l'on souhaite accroitre les performances
                        de 50% en utilisant le ZBuffer hardware !!!
                        Si la fenetre fournie a deja le bon visual pas
                        la peine de creer une sous-fenetre.
       16-10-96 : GG  ; Le dithering doit etre active aussi avec 12 plans
                        de maniere a ameliorer la qualite
       17-10-96 : FMN ; Ajout fonction printVisualInfo()
       06-11-96 : CAL ; Remise a True du BackDitherProp pour < 12 plans
       12-11-96 : CAL ; BackDitherProp = True pour <= 8 plans
			BackDitherProp = False pour > 8 plans
       29-01-97 : FMN ; Amelioration du tests pour le dithering
			DitherProp = True pour <= 8 plans red
			DitherProp = False pour > 8 plans red
			Suppression de TxglSetDbuff()
       06-06-97 : FMN ; Meilleure gestion glXMakeCurrent (pb avec LightWoks)
			Suppression de previous_win
       02-07-97 : FMN ; Suppression variable ESSAI
       07-10-97 : FMN ; Simplification WNT 
       13-10-97 : FMN ; Ajout wglShareLists
       06-02-98 : FMN ; PRO11674: Suppression XSetErrorHandler(0) inutile
       23-11-98 : CAL ; PRO16603: previous_ctx jamais remis a 0 pour eviter
			la perte des lists.
       07-12-98 : CAL ; PRO 16311 et PRO 11821
       02.14.100 : JR : Warnings on WNT
       14.07.06 : SAN : OCC12977: update previous_ctx properly in TxglDestroyWindow.
                        Old code resulted in crashes on some ATI Radeon cards under Linux.

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

#define BUC60691	/*GG 06/06/00 Due to a severe bug in secondary 
//			table hash-code computation not yet solve,
//			It's necessary to compute the primary hash-key key
//			correctly under WNT/W98. The actual method is wrong
//			because a size 4 is used for this table instead
//			a conventional prime number as under UNIX system (23).
//			 Under W98 sometimes the function wglMakeContext() does
//			not work for an UNKNOWN reason, the number of DC
//			seems limited to 5 but nothing tell that the limit is
//			reached !
//			We try right now to recover this error by creating a new DC.
*/

#define RIC120303	/*GG Add new function TxglSetWindow using
//			the GLXContext defined by the user
//			Add new function TxglGetContext.
*/

#define OCC954  /*SAV: 13/11/02 - check GLRC before deleting it*/

/*----------------------------------------------------------------------*/
/*
 * Includes
 */
 
#include <stdio.h>

#include <OpenGl_tgl_all.h>

#include <GL/gl.h>
#include <GL/glu.h>

#ifndef WNT
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <GL/glx.h>
# include <OpenGl_telem_util.h>
#else
# include <OpenGl_cmn_memory.h>
# define STRICT
# include <InterfaceGraphic_WNT.hxx>
# include <windows.h>

typedef struct htbl_entry {
	HDC   hDC;
	HGLRC hGLRC;
	int   nUsed;

       } HTBL_ENTRY;
	       
int call_util_osd_getenv ( char*, char*, int );
#endif  /* WNT */

#include <OpenGl_cmn_htbl.h>
#include <OpenGl_txgl.h>
int call_util_osd_getenv( char * , char * , int ) ;

/*----------------------------------------------------------------------*/
/*
 * Variables statiques
 */

static  cmn_htbl  txgltbl;		/* Hash table pour le GLXContext */

#ifndef WNT
static  int BackDitherProp = False;	/* Dithering pour le background */
static  int DitherProp = True;		/* Dithering pour le trace	*/
static	GLXContext previous_ctx = 0;	/* Use for share display list	*/
#else
static  int BackDitherProp = FALSE;	/* Dithering pour le background */
static  int DitherProp = TRUE;		/* Dithering pour le trace	*/
static  BOOL s_sysPalInUse;             /* Flag to check system colors usage */ 
static  HGLRC previous_ctx = 0;		/* Use for share display list	*/
#endif /* WNT */

/*----------------------------------------------------------------------*/
/*
 * Constantes
 */

#define NO_TRACE

#define CALL_DEF_STRING_LENGTH 132

#define WIN_HTBL_SIZE 23

/*----------------------------------------------------------------------*/
/*
 * Fonctions statiques
 */

#ifndef WNT
#ifdef TRACE
static GLvoid printVisualInfo( Display *, XVisualInfo *glxVisual );
#endif
#else
#ifdef BUC60691
static BOOL win95 = FALSE;
#endif
__declspec( dllexport ) int __fastcall __OpenGl_INIT__ ( 
                                        unsigned hInstance, unsigned long reason_for_call
                                       ) {
 if ( reason_for_call == DLL_PROCESS_ATTACH ) {

 }
 return 1;

}  /* end __OpenGl_INIT__ */
#endif  /* WNT */

/*----------------------------------------------------------------------*/

Window
TxglCreateWindow( Display  *disp, Window par,
	Tint x, Tint y, Tint w, Tint h, Tint bw,
	Tfloat bgcolr, Tfloat bgcolg, Tfloat bgcolb )
{

#ifndef WNT

    GLXContext ctx;
    static int sdesc[11];
    Colormap cmap;
    XVisualInfo* vis=NULL;
/*    XVisualInfo tmplt;*/
    XSetWindowAttributes cwa;
    XColor color;
/*    Tint i, n, nret;*/
    Tint n;
    Tint scr;
    int value;
    char string[CALL_DEF_STRING_LENGTH];
    int DBuffer = True;
    XWindowAttributes wattr;

    Window win;

    unsigned long mask = 0;
/*    unsigned long background_pixel = 0;*/

    if (call_util_osd_getenv("CALL_OPENGL_NO_DBF", string, CALL_DEF_STRING_LENGTH))
        DBuffer    = False;

    if (call_util_osd_getenv("JWR_PIXMAP_DB", string, CALL_DEF_STRING_LENGTH))
        TelSetPixmapDB(1);

    XGetWindowAttributes( disp , par , &wattr );

    n = 0;
    sdesc[n] = GLX_RGBA;n++;

    sdesc[n] = GLX_DEPTH_SIZE;n++;
    sdesc[n] = 1;n++;

    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++;

    if (DBuffer) {
      sdesc[n] = GLX_DOUBLEBUFFER;n++;
    }

    sdesc[n] = None;n++;

    scr = DefaultScreen( disp );

#if defined(__linux) || defined(Linux)
    {
      XVisualInfo vinfo;
      int ninfo;
      unsigned long vmask = VisualIDMask |  VisualScreenMask;
      vinfo.visualid = wattr.visual->visualid;
      vinfo.screen = DefaultScreen( disp );
      vis = XGetVisualInfo( disp, vmask, &vinfo, &ninfo);
    }
#endif

    if( !vis )
    	vis = glXChooseVisual( disp, scr, sdesc );
    if( !vis) return TFailure;

#ifdef TRACE
    printf ("TxglCreateWindow \n");
    printf ("Informations sur le visual\n");
    printf ("par visualid %x%x %d\n", wattr.visual->visualid, wattr.visual->visualid);
    printf ("vis visualid 0x%x %d\n", vis->visualid, vis->visualid);
    printf ("vis depth %d\n", vis->depth);
    printf ("vis class %d\n", vis->class);
    printf ("vis red_mask %ld\n", vis->red_mask);
    printf ("vis green_mask %ld\n", vis->green_mask);
    printf ("vis blue_mask %ld\n", vis->blue_mask);
    printf ("vis colormap_size %d\n", vis->colormap_size);
    printf ("vis bits_per_rgb %d\n", vis->bits_per_rgb);
    printVisualInfo( disp, vis );
#endif

    /*
     * Le BackDitherProp est utilise pour le clear du background
     * Pour eviter une difference de couleurs avec la couleur choisie
     * par l'application (XWindow) il faut desactiver le dithering
     * au dessus de 8 plans.
     * 
     * Pour le DitherProp:
     * On cherchera a activer le Dithering que si le Visual a au moins
     * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
     * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
     * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
     */

    glXGetConfig( disp, vis, GLX_RED_SIZE, &value );

    if ( value < 8 ) {
        DitherProp = True;
    }
    else
    {
        DitherProp = False;
    }

    if ( vis->depth <= 8 ) {
        BackDitherProp = True;
    }
    else
    {
        BackDitherProp = False;
    }

#ifdef TRACE
    printf("Dithering %d BackDithering %d \n",DitherProp,BackDitherProp);
#endif

    if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
        DitherProp = False;

    if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
        BackDitherProp = False;

    if (previous_ctx == 0) {
        ctx = glXCreateContext( disp, vis, NULL, GL_TRUE );
        previous_ctx = ctx;
    } else {
	/* ctx est une copie du previous */
    	ctx = glXCreateContext( disp, vis, previous_ctx, GL_TRUE );
    }

    if( !ctx) return TFailure;

    cmap = XCreateColormap( disp,  par, vis->visual, AllocNone );

    color.red	= (unsigned short) (bgcolr * 0xFFFF);
    color.green	= (unsigned short) (bgcolg * 0xFFFF);
    color.blue	= (unsigned short) (bgcolb * 0xFFFF);
    color.flags	= DoRed | DoGreen | DoBlue;
    XAllocColor( disp, cmap, &color );

    cwa.colormap	= cmap;
    cwa.event_mask	= StructureNotifyMask;
    cwa.border_pixel	= color.pixel;
    cwa.background_pixel = color.pixel;

    mask = CWBackPixel | CWColormap | CWBorderPixel | CWEventMask;

    if( vis->visualid == wattr.visual->visualid ) {
      win = par;
    } 
    else 
    {
      win = XCreateWindow( disp, par, x, y, w, h, bw,
                         vis->depth, InputOutput, vis->visual,
                         mask, &cwa );
    }

#ifdef TRACE
    printf ("TxglCreateWindow win %x par %x \n", win, par);
#endif

    XSetWindowBackground( disp, win, cwa.background_pixel );
    XClearWindow( disp, win );

    /* if in Pixmap double buffering mode, set up pixmap */

    if (TelTestPixmapDB())
    {
        GC gc;
        Pixmap pixmap;
        GLXPixmap glxpixmap;

        printf("setting up pixmap double buffering\n");

        gc = XCreateGC(disp, win, 0, NULL);

        pixmap = XCreatePixmap(disp, win, w, h, vis->depth);

        glxpixmap = glXCreateGLXPixmap(disp, vis, pixmap);

        glXMakeCurrent(disp, glxpixmap, ctx);

        glDrawBuffer(GL_FRONT);

        TelSetPixmapDBParams(disp, win, w, h, vis->depth, gc, pixmap, glxpixmap, ctx);
    }

    XFree((char*)vis);  

    if( !txgltbl )
    {
	/*
	 * PRO 16311 et PRO 11821
	 * txgltbl = cmn_create_htbl(  sizeof( GLXContext)+1 );
	 */
	txgltbl = cmn_create_htbl( WIN_HTBL_SIZE );
	if( !txgltbl ) return 0;
    }
    cmn_add_in_htbl( txgltbl, win, ctx );

    return win;

#else /* WNT */

    cmn_htbl_elem         rec;
    HTBL_ENTRY*           hte;
    PIXELFORMATDESCRIPTOR pfd;
    BOOL                  DBuffer = TRUE;
    int                   iPixelFormat;
    char                  string[ CALL_DEF_STRING_LENGTH ];

#ifdef BUC60691
    OSVERSIONINFO os;
    os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
    GetVersionEx(&os);
    if( os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) win95 = TRUE; 
#endif

    if ( txgltbl ) 
    {
	rec = cmn_find_in_htbl (  txgltbl, ( Tint )par, ( void** )&hte  );
	
	if ( rec ) 
	{
	    ++hte -> nUsed;
	    printf("*TxglCreateWindow.window %d is alreday created\n",par);
	    return par;
	}  
    }  

    hte = ( HTBL_ENTRY* )cmn_getmem (  1, sizeof ( HTBL_ENTRY ), 1  );
    
    if ( !hte ) return 0;

    if (  call_util_osd_getenv ("CALL_OPENGL_NO_DBF", string, CALL_DEF_STRING_LENGTH)) 
	DBuffer = FALSE;

    pfd.nSize           = sizeof ( PIXELFORMATDESCRIPTOR );
    pfd.nVersion        = 1;
    pfd.dwFlags         = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    pfd.dwFlags        |= ( DBuffer ) ? PFD_DOUBLEBUFFER : PFD_SUPPORT_GDI;
    pfd.iPixelType      = PFD_TYPE_RGBA;
    pfd.cColorBits      = 24;
    pfd.cRedBits        = 0;
    pfd.cRedShift       = 0;
    pfd.cGreenBits      = 0;
    pfd.cGreenShift     = 0;
    pfd.cBlueBits       = 0;
    pfd.cBlueShift      = 0;
    pfd.cAlphaBits      = 0;
    pfd.cAlphaShift     = 0;
    pfd.cAccumBits      = 0;
    pfd.cAccumRedBits   = 0;
    pfd.cAccumGreenBits = 0;
    pfd.cAccumBlueBits  = 0;
    pfd.cAccumAlphaBits = 0;
    pfd.cDepthBits      = 32;
    pfd.cStencilBits    = 0;
    pfd.cAuxBuffers     = 0;
    pfd.iLayerType      = PFD_MAIN_PLANE;
    pfd.bReserved       = 0;
    pfd.dwLayerMask     = 0;
    pfd.dwVisibleMask   = 0;
    pfd.dwDamageMask    = 0;

    hte -> nUsed = 1;
    
    hte -> hDC   = GetDC ( par );
    iPixelFormat = ChoosePixelFormat ( hte -> hDC, &pfd );

    if ( !iPixelFormat ) 
    {
	printf ("*OpenGL interface: ChoosePixelFormat failed. Error code: %d\n",GetLastError ());
	
	ReleaseDC ( par, hte -> hDC );
	cmn_freemem (  ( void* )hte  );
	
	return 0;
    }  

    DescribePixelFormat (hte -> hDC, iPixelFormat, sizeof ( PIXELFORMATDESCRIPTOR ), &pfd);

    if ( pfd.dwFlags & PFD_NEED_PALETTE ) 
    {
#ifndef _WIN64
	WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLong ( par, GWL_USERDATA );
#else
	WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLong ( par, GWLP_USERDATA );
#endif
	
	InterfaceGraphic_RealizePalette (hte -> hDC, wd -> hPal, FALSE,
	    s_sysPalInUse = pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE); 
    }  

    if ( pfd.cColorBits <= 8 ) 
    { 
	DitherProp     = TRUE;
	BackDitherProp = TRUE;    
    }  

    if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
	DitherProp = FALSE;
    
    if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
	BackDitherProp = FALSE;

    if (  !SetPixelFormat ( hte -> hDC, iPixelFormat, &pfd )  ) 
    {
	printf ("*OpenGL interface: SetPixelFormat failed. Error code %d\n",GetLastError ()); 
	ReleaseDC ( par, hte -> hDC );
	cmn_freemem (  ( void* )hte  );   
	return 0; 
    }  

    hte -> hGLRC = wglCreateContext ( hte -> hDC );
    
    if ( !hte -> hGLRC ) 
    { 
	printf ("*OpenGL interface: wglCreateContext failed. Error code: %d\n",GetLastError ());    
	return 0;  	  
    }  
    
    if (previous_ctx == 0 )    
    {
        previous_ctx = hte -> hGLRC;
    } else
	wglShareLists(previous_ctx, hte -> hGLRC);

    if ( !txgltbl ) 
    {
#ifdef BUC60691
	txgltbl = cmn_create_htbl( WIN_HTBL_SIZE );
#else
	txgltbl = cmn_create_htbl (  sizeof ( HTBL_ENTRY* )  );
#endif
	
	if ( !txgltbl ) 
	{
	    ReleaseDC ( par, hte -> hDC );
	    cmn_freemem (  ( void* )hte );
	    printf( "*OpenGL interface: cmn_create_htbl failed\n" );
	}  
    }  
    
    cmn_add_in_htbl (  txgltbl, ( Tint )par, hte  );
    
    return par;

#endif  /* WNT */

}

#ifdef RIC120302
Window
TxglSetWindow( Display  *disp, Window par, GLXContext ctx)
{
#ifndef WNT
    XVisualInfo* vis;
    char string[CALL_DEF_STRING_LENGTH];
    XWindowAttributes wattr;

    XGetWindowAttributes( disp , par , &wattr );
    {
      unsigned long vmask = VisualIDMask |  VisualScreenMask;
      XVisualInfo vinfo;
      int ninfo;
      vinfo.visualid = wattr.visual->visualid;
      vinfo.screen = DefaultScreen( disp );
      vis = XGetVisualInfo( disp, vmask, &vinfo, &ninfo);
    }

    if( !vis) return TFailure;

#ifdef TRACE
    printf ("TxglSetWindow \n");
    printf ("Informations sur le visual\n");
    printf ("par visualid %x%x %d\n", wattr.visual->visualid, wattr.visual->visualid);
    printf ("vis visualid 0x%x %d\n", vis->visualid, vis->visualid);
    printf ("vis depth %d\n", vis->depth);
    printf ("vis class %d\n", vis->class);
    printf ("vis red_mask %ld\n", vis->red_mask);
    printf ("vis green_mask %ld\n", vis->green_mask);
    printf ("vis blue_mask %ld\n", vis->blue_mask);
    printf ("vis colormap_size %d\n", vis->colormap_size);
    printf ("vis bits_per_rgb %d\n", vis->bits_per_rgb);
    printVisualInfo( disp, vis );
#endif

    /*
     * Le BackDitherProp est utilise pour le clear du background
     * Pour eviter une difference de couleurs avec la couleur choisie
     * par l'application (XWindow) il faut desactiver le dithering
     * au dessus de 8 plans.
     * 
     * Pour le DitherProp:
     * On cherchera a activer le Dithering que si le Visual a au moins
     * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
     * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
     * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
     */

    {
      int value;
      glXGetConfig( disp, vis, GLX_RED_SIZE, &value );

      if ( value < 8 ) {
        DitherProp = True;
      } else {
        DitherProp = False;
      }

      if ( vis->depth <= 8 ) {
        BackDitherProp = True;
      } else {
        BackDitherProp = False;
      }
    }

#ifdef TRACE
    printf("Dithering %d BackDithering %d \n",DitherProp,BackDitherProp);
#endif

    if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
        DitherProp = False;

    if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
        BackDitherProp = False;

    previous_ctx = ctx;

    XFree((char*)vis);  

    if( !txgltbl ) {
	/*
	 * PRO 16311 et PRO 11821
	 * txgltbl = cmn_create_htbl(  sizeof( GLXContext)+1 );
	 */
	txgltbl = cmn_create_htbl( WIN_HTBL_SIZE );
	if( !txgltbl ) return 0;
    }
    cmn_add_in_htbl( txgltbl, par, ctx );

#else /* WNT */

    cmn_htbl_elem         rec;
    HTBL_ENTRY*           hte;
    PIXELFORMATDESCRIPTOR pfd;
    BOOL                  DBuffer = TRUE;
    int                   iPixelFormat;
    char                  string[ CALL_DEF_STRING_LENGTH ];

#ifdef BUC60691
    OSVERSIONINFO os;
    os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
    GetVersionEx(&os);
    if( os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) win95 = TRUE; 
#endif

    if ( txgltbl ) 
    {
	rec = cmn_find_in_htbl (  txgltbl, ( Tint )par, ( void** )&hte  );
	
	if ( rec ) 
	{
	    ++hte -> nUsed;
	    printf("*TxglSetWindow.window %d is alreday created\n",par);
	    return par;
	}  
    }  

    hte = ( HTBL_ENTRY* )cmn_getmem (  1, sizeof ( HTBL_ENTRY ), 1  );
    
    if ( !hte ) return 0;

    if (  call_util_osd_getenv ("CALL_OPENGL_NO_DBF", string, CALL_DEF_STRING_LENGTH)) 
	DBuffer = FALSE;

    pfd.nSize           = sizeof ( PIXELFORMATDESCRIPTOR );
    pfd.nVersion        = 1;
    pfd.dwFlags         = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    pfd.dwFlags        |= ( DBuffer ) ? PFD_DOUBLEBUFFER : PFD_SUPPORT_GDI;
    pfd.iPixelType      = PFD_TYPE_RGBA;
    pfd.cColorBits      = 24;
    pfd.cRedBits        = 0;
    pfd.cRedShift       = 0;
    pfd.cGreenBits      = 0;
    pfd.cGreenShift     = 0;
    pfd.cBlueBits       = 0;
    pfd.cBlueShift      = 0;
    pfd.cAlphaBits      = 0;
    pfd.cAlphaShift     = 0;
    pfd.cAccumBits      = 0;
    pfd.cAccumRedBits   = 0;
    pfd.cAccumGreenBits = 0;
    pfd.cAccumBlueBits  = 0;
    pfd.cAccumAlphaBits = 0;
    pfd.cDepthBits      = 32;
    pfd.cStencilBits    = 0;
    pfd.cAuxBuffers     = 0;
    pfd.iLayerType      = PFD_MAIN_PLANE;
    pfd.bReserved       = 0;
    pfd.dwLayerMask     = 0;
    pfd.dwVisibleMask   = 0;
    pfd.dwDamageMask    = 0;

    hte -> nUsed = 1;
    
    hte -> hDC   = GetDC ( par );
    iPixelFormat = ChoosePixelFormat ( hte -> hDC, &pfd );

    if ( !iPixelFormat ) 
    {
	printf ("*OpenGL interface: ChoosePixelFormat failed. Error code: %d\n",GetLastError ());
	
	ReleaseDC ( par, hte -> hDC );
	cmn_freemem (  ( void* )hte  );
	
	return 0;
    }  

    DescribePixelFormat (hte -> hDC, iPixelFormat, sizeof ( PIXELFORMATDESCRIPTOR ), &pfd);

    if ( pfd.dwFlags & PFD_NEED_PALETTE ) 
    {
#ifndef _WIN64
	WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLong ( par, GWL_USERDATA );
#else
	WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLong ( par, GWLP_USERDATA );
#endif
	
	InterfaceGraphic_RealizePalette (hte -> hDC, wd -> hPal, FALSE,
	    s_sysPalInUse = pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE); 
    }  

    if ( pfd.cColorBits <= 8 ) 
    { 
	DitherProp     = TRUE;
	BackDitherProp = TRUE;    
    }  

    if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
	DitherProp = FALSE;
    
    if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
	BackDitherProp = FALSE;

    if (  !SetPixelFormat ( hte -> hDC, iPixelFormat, &pfd )  ) 
    {
	printf ("*OpenGL interface: SetPixelFormat failed. Error code %d\n",GetLastError ()); 
	ReleaseDC ( par, hte -> hDC );
	cmn_freemem (  ( void* )hte  );   
	return 0; 
    }  

    hte -> hGLRC = previous_ctx = ctx;
    
    if ( !txgltbl ) 
    {
#ifdef BUC60691
	txgltbl = cmn_create_htbl( WIN_HTBL_SIZE );
#else
	txgltbl = cmn_create_htbl (  sizeof ( HTBL_ENTRY* )  );
#endif
	
	if ( !txgltbl ) 
	{
	    ReleaseDC ( par, hte -> hDC );
	    cmn_freemem (  ( void* )hte );
	    printf( "*OpenGL interface: cmn_create_htbl failed\n" );
	}  
    }  
    
    cmn_add_in_htbl (  txgltbl, ( Tint )par, hte  );

#endif  /* WNT */

    return par;

}
#endif /*RIC120302*/

/*----------------------------------------------------------------------*/

TStatus
TxglWinset( Display *disp, Window win )
{

#ifndef WNT

    Bool  i;
    GLXContext ctx;
    cmn_htbl_elem  rec;
    GLenum errorcode;
    const GLubyte *errorstring;

    if( !txgltbl ) return TFailure;

    rec = cmn_find_in_htbl( txgltbl, win, (void**)&ctx );
    if( !rec ) return TFailure;

#ifdef TRACE
    printf ("TxglWinset::glXMakeCurrent %x \n", win);
#endif
    if (TelTestPixmapDB())
      {
        i = glXMakeCurrent(disp, TelGetGLXPixmap(), ctx);
      }
    else
      {
        i = glXMakeCurrent(disp, win, ctx);  /* TRUE/FALSE */
      }
    if (!i)
      {
	errorcode = glGetError();
	errorstring = gluErrorString(errorcode);
	printf("glXMakeCurrent failed: %d %s\n", errorcode, errorstring);
      }

    return  i == True ? TSuccess : TFailure;

#else /* WNT */

    HTBL_ENTRY*   hte;
    cmn_htbl_elem rec;
    HDC    hdc    = NULL;
    HGLRC  hglrc  = NULL;
    TStatus       retVal = TFailure;

    __try {
    
	if ( !txgltbl ) __leave;
		
	if (    !(   rec = cmn_find_in_htbl (  txgltbl, ( Tint )win, ( void** )&hte  )   )    ) {
	  printf("OpenGL interface:  TxglWinset failed.UNKNOWN win %x\n",win);
	  __leave;
	}

#ifdef BUC60691
      if( win95 ) {
	  retVal = ReleaseDC ( win, hte -> hDC );
	  hte -> hDC   = GetDC ( win );
      }		
#endif
	if (  !wglMakeCurrent ( hte -> hDC, hte -> hGLRC )  ) 
	{
#ifdef BUC60691
    	   GLenum errorcode;
    	   const GLubyte *errorstring;

	   errorcode = glGetError();
	   errorstring = gluErrorString(errorcode);
	   printf("wglMakeCurrent failed: %d %s\n", errorcode, errorstring);
#else
	    printf ("OpenGL interface: wglMakeCurrent failed. Error code: %d\n",GetLastError ());
#endif
	    retVal = TFailure;	
	} else retVal = TSuccess;
    
    }  /* end __try */


    __finally 
    {    
    }  

    return retVal;

#endif  /* WNT */

}

/*----------------------------------------------------------------------*/

Window
TxglGetSubWindow( Display *disp, Window win )
                               /* This function assumes that there is only
                                  one child for the parent */
{

#ifndef WNT

   Window root, parent, *child, w;
   unsigned int num;

   if( XQueryTree( disp, win, &root, &parent, &child, &num ) )
   {
      if (! num) return win;
      w = child[0];
      XFree( (char *)child );
      return w;
   }
   else
      return 0;

#else /* WNT */

   return win;

#endif  /* WNT */

}

/*----------------------------------------------------------------------*/

void
TxglDestroyWindow( Display *disp, Window win )
{

#ifndef WNT

    GLXContext ctx;
    cmn_htbl_elem rec;
    Tint dummy;
    
    if( !txgltbl ) return ;
    
    rec = cmn_find_in_htbl( txgltbl, win, (void**)&ctx );
    if( !rec ) return ;

    /* FSXXX sync necessary if non-direct rendering */
    glXWaitGL();

    glXDestroyContext(disp, ctx);
    cmn_delete_from_htbl( txgltbl, win, (void**)&ctx );

    if (previous_ctx == ctx) {
       /* san -- OCC12977: it's important to put some valid GLXContext or null into
	  previous_ctx here, otherwise next glxCreateContext() will crash on some ATI Radeon cards
        */
       cmn_get_from_htbl( txgltbl, &dummy, (void**)&previous_ctx, 0 );
    }

#else /* WNT */

    HTBL_ENTRY*   hte;
    cmn_htbl_elem rec;
#ifdef _DEBUG 
    WINDOW_DATA*  wd;
#endif  /* _DEBUG */
    
    if ( !txgltbl ) return;

    rec = cmn_find_in_htbl (  txgltbl, ( Tint )win, ( void** )&hte  );
    if ( !rec ) return;
    
#ifdef _DEBUG 
    /* In release version of application we need to process    */
    /*  palette messages in the main application message loop. */
    /*  In debug version we don't have message loop for most   */
    /*  cases. So, let's restore system colors here now.       */
#ifndef _WIN64
    wd = ( WINDOW_DATA* )GetWindowLong ( win, GWL_USERDATA );
#else
    wd = ( WINDOW_DATA* )GetWindowLong ( win, GWLP_USERDATA );
#endif

    if ( wd != NULL ) InterfaceGraphic_RealizePalette (
		     hte -> hDC, wd -> hPal, TRUE, s_sysPalInUse);
#endif  /* _DEBUG */

    if ( --hte -> nUsed == 0 ) 
    { 
#ifdef OCC954    
      if ( wglGetCurrentContext() != NULL )
#endif
	wglDeleteContext ( hte -> hGLRC );
	ReleaseDC ( win, hte -> hDC );
	cmn_freemem (  ( void* )hte  );
	cmn_delete_from_htbl (  txgltbl, (Tint ) win, ( void** )&hte  );
    }  

#endif  /* WNT */

}

/*----------------------------------------------------------------------*/

int
TxglGetDither(void)
{
    return DitherProp;
}

/*----------------------------------------------------------------------*/

int
TxglGetBackDither(void)
{
    return BackDitherProp;
}


/*----------------------------------------------------------------------*/
/*RIC120302*/
GLXContext 
TxglGetContext( Window win )
{
    cmn_htbl_elem  rec;
    GLXContext ctx;

    rec = cmn_find_in_htbl (  txgltbl, ( Tint )win, ( void** )&ctx  );
    if( !rec ) return NULL;
    return ctx;
}
/*RIC120302*/

/*----------------------------------------------------------------------*/
enum { ZERO = 0, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN };

/* Unused :*/
#ifdef TRACE
static const char*
className( int class )
{
    static char      *classes[] = {
	    "StaticGray",
	    "GrayScale",
	    "StaticColor",
	    "PseudoColor",
	    "TrueColor",
	    "DirectColor",
    };
    
    if ( class < ZERO || class > FIVE )
	    return "unknown";
    else
	    return classes[class];
}
#endif
/*----------------------------------------------------------------------*/
#ifndef WNT

#ifdef TRACE
static GLvoid printVisualInfo( Display  *display, XVisualInfo *glxVisual )
{

#define TrueFalse(x)  ( x ? "True" : "False" )

    int        tmp;

    printf("\n" );
    printf("   X Visual Information ...\n\n" );
    printf("\tvisualid : 0x%x\n", glxVisual->visualid );
    printf("\tclass    : %s\n\n", className( glxVisual->class ) );

    glXGetConfig(display, glxVisual, GLX_USE_GL, &tmp);
    printf( "\tSupport GL ( GLX_USE_GL ) : %s\n", TrueFalse(tmp) );

    glXGetConfig(display, glxVisual, GLX_LEVEL, &tmp);
    printf( "\tFramebuffer ( GLX_LEVEL ) : %s\n\n",
	    (tmp < ZERO) ? "Underlay" : (tmp == ZERO ? "Normal"  : tmp > ONE ? "Overlay"  : "Popup") );

    glXGetConfig(display, glxVisual, GLX_BUFFER_SIZE, &tmp);
    printf( "\tFramebuffer depth ( GLX_BUFFER_SIZE )     : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_DOUBLEBUFFER, &tmp);
    printf( "\tDoublebuffer ( GLX_DOUBLEBUFFER )         : %s\n",
	    TrueFalse(tmp) );

    glXGetConfig(display, glxVisual, GLX_DEPTH_SIZE, &tmp);
    printf( "\tDepth buffer depth ( GLX_DEPTH_SIZE )     : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_STENCIL_SIZE, &tmp);
    printf( "\tStencil buffer depth ( GLX_STENCIL_SIZE ) : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_STEREO, &tmp);
    printf( "\tStereo Buffer ( GLX_STEREO )              : %s\n",
	    TrueFalse(tmp) );

    glXGetConfig(display, glxVisual, GLX_AUX_BUFFERS, &tmp);
    printf( "\tAuxillary Buffers ( GLX_AUX_BUFFERS)      : %d\n\n", tmp );

    glXGetConfig(display, glxVisual, GLX_RGBA, &tmp);
    printf( "\tColor mode ( GLX_RGBA )       : %s\n", tmp ? "RGBA" :
	    "Color Index" );

    glXGetConfig(display, glxVisual, GLX_RED_SIZE, &tmp);
    printf( "\tRed Bits ( GLX_RED_SIZE )     : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_GREEN_SIZE, &tmp);
    printf( "\tGreen Bits ( GLX_GREEN_SIZE ) : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_BLUE_SIZE, &tmp);
    printf( "\tBlue Bits ( GLX_BLUE_SIZE )   : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_ALPHA_SIZE, &tmp);
    printf( "\tAlpha Bits ( GLX_ALPHA_SIZE ) : %d\n\n", tmp );

    glXGetConfig(display, glxVisual, GLX_ACCUM_RED_SIZE, &tmp);
    printf( "\tRed Accumulation Bits ( GLX_ACCUM_RED_SIZE )     : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_ACCUM_GREEN_SIZE, &tmp);
    printf( "\tGreen Accumulation Bits ( GLX_ACCUM_GREEN_SIZE ) : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_ACCUM_BLUE_SIZE, &tmp);
    printf( "\tBlue Accumulation Bits ( GLX_ACCUM_BLUE_SIZE )   : %d\n", tmp );

    glXGetConfig(display, glxVisual, GLX_ACCUM_ALPHA_SIZE, &tmp);
    printf( "\tAlpha Accumulation Bits ( GLX_ACCUM_ALPHA_SIZE ) : %d\n\n", tmp );
}
#endif
#endif  /* WNT */
/*----------------------------------------------------------------------*/
