0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_txgl.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_txgl :
6
7
8 REMARQUES:
9 ---------- 
10
11
12 HISTORIQUE DES MODIFICATIONS   :
13 --------------------------------
14 xx-xx-xx : xxx ; Creation.
15 07-02-96 : FMN ; Suppression code inutile:
16 - TxglLink() et TxglUnlink()
17 08-03-96 : FMN ; Suppression variables globales
18 Ajout cmn_delete_from_htbl() dans TxglDestroyWindow()
19 21-03-96 : CAL ; test sur previous_ctx dans TxglDestroyWindow()
20 et dans TxglSetDbuff()
21 01-04-96 : CAL ; Integration MINSK portage WNT
22 15-04-96 : CAL ; Integration travail PIXMAP de Jim ROTH
23 26-04-96 : FMN ; Correction warning de compilation
24 20-06-96 : CAL ; Retrait du XDestroyWindow dans TxglDestroyWindow
25 18-07-96 : FMN ; Suppression code inutile: TxglSetWindow().
26 27-09-96 : CAL ; Portage WNT
27 16-10-96 : GG  ; Coder le parametre de GLX_DEPTH_SIZE a 1 plutot
28 que 0 si l'on souhaite accroitre les performances
29 de 50% en utilisant le ZBuffer hardware !!!
30 Si la fenetre fournie a deja le bon visual pas
31 la peine de creer une sous-fenetre.
32 16-10-96 : GG  ; Le dithering doit etre active aussi avec 12 plans
33 de maniere a ameliorer la qualite
34 17-10-96 : FMN ; Ajout fonction printVisualInfo()
35 06-11-96 : CAL ; Remise a True du BackDitherProp pour < 12 plans
36 12-11-96 : CAL ; BackDitherProp = True pour <= 8 plans
37 BackDitherProp = False pour > 8 plans
38 29-01-97 : FMN ; Amelioration du tests pour le dithering
39 DitherProp = True pour <= 8 plans red
40 DitherProp = False pour > 8 plans red
41 Suppression de TxglSetDbuff()
42 06-06-97 : FMN ; Meilleure gestion glXMakeCurrent (pb avec LightWoks)
43 Suppression de previous_win
44 02-07-97 : FMN ; Suppression variable ESSAI
45 07-10-97 : FMN ; Simplification WNT 
46 13-10-97 : FMN ; Ajout wglShareLists
47 06-02-98 : FMN ; PRO11674: Suppression XSetErrorHandler(0) inutile
48 23-11-98 : CAL ; PRO16603: previous_ctx jamais remis a 0 pour eviter
49 la perte des lists.
50 07-12-98 : CAL ; PRO 16311 et PRO 11821
51 02.14.100 : JR : Warnings on WNT
52 14.07.06 : SAN : OCC12977: update previous_ctx properly in TxglDestroyWindow.
53 Old code resulted in crashes on some ATI Radeon cards under Linux.
54
55 ************************************************************************/
56
57 #define BUC60691  /*GG 06/06/00 Due to a severe bug in secondary 
58 //      table hash-code computation not yet solve,
59 //      It's necessary to compute the primary hash-key key
60 //      correctly under WNT/W98. The actual method is wrong
61 //      because a size 4 is used for this table instead
62 //      a conventional prime number as under UNIX system (23).
63 //       Under W98 sometimes the function wglMakeContext() does
64 //      not work for an UNKNOWN reason, the number of DC
65 //      seems limited to 5 but nothing tell that the limit is
66 //      reached !
67 //      We try right now to recover this error by creating a new DC.
68 */
69
70 #define RIC120303 /*GG Add new function TxglSetWindow using
71 //      the GLXContext defined by the user
72 //      Add new function TxglGetContext.
73 */
74
75 #define OCC954  /*SAV: 13/11/02 - check GLRC before deleting it*/
76
77 /*----------------------------------------------------------------------*/
78 /*
79 * Includes
80 */
81 #include <OpenGl_tgl_all.hxx>
82 #include <OpenGl_telem_util.hxx>
83 #include <stdio.h>
84
85 #include <OpenGl_Memory.hxx>
86 #include <OpenGl_ResourceCleaner.hxx>
87
88
89 #ifdef WNT
90 struct HTBL_ENTRY {
91   HDC   hDC;
92   HGLRC hGLRC;
93   int   nUsed;
94   IMPLEMENT_MEMORY_OPERATORS
95 };
96
97
98 int call_util_osd_getenv ( char*, char*, int );
99 #endif  /* WNT */
100
101 #include <OpenGl_txgl.hxx>
102 int call_util_osd_getenv( char * , char * , int ) ;
103
104 /*----------------------------------------------------------------------*/
105 /*
106 * Variables statiques
107 */
108
109 #ifndef WNT
110 typedef NCollection_DataMap<Tint, GLCONTEXT> GLContextMap;
111 #else
112 typedef NCollection_DataMap<Tint, HTBL_ENTRY*> GLContextMap;
113 #endif
114
115 static GLContextMap _Txgl_Map;
116
117
118 #ifndef WNT
119 static  int BackDitherProp = False; /* Dithering pour le background */
120 static  int DitherProp = True;    /* Dithering pour le trace  */
121 static  GLXContext previous_ctx = 0;  /* Use for share display list */
122 static  GLXContext dead_ctx;            /* Context to be destroyed */
123 static  Display *dead_dpy;              /* Display associated with dead_ctx */
124 #else
125 static  int BackDitherProp = FALSE; /* Dithering pour le background */
126 static  int DitherProp = TRUE;    /* Dithering pour le trace  */
127 static  BOOL s_sysPalInUse;             /* Flag to check system colors usage */ 
128 static  HGLRC previous_ctx = 0;   /* Use for share display list */
129 #endif /* WNT */
130
131 /*----------------------------------------------------------------------*/
132 /*
133 * Constantes
134 */
135
136 #define NO_TRACE
137
138 #define CALL_DEF_STRING_LENGTH 132
139
140 #define WIN_HTBL_SIZE 23
141
142 /*----------------------------------------------------------------------*/
143 /*
144 * Fonctions statiques
145 */
146
147 #ifndef WNT
148 #ifdef TRACE
149 static GLvoid printVisualInfo( Display *, XVisualInfo *glxVisual );
150 #endif
151 #else
152 #ifdef BUC60691
153 static BOOL win95 = FALSE;
154 #endif
155
156 static int find_pixel_format(HTBL_ENTRY * hte, PIXELFORMATDESCRIPTOR * pfd);
157
158 __declspec( dllexport ) int __fastcall __OpenGl_INIT__ ( 
159   unsigned hInstance, unsigned long reason_for_call
160   ) {
161     if ( reason_for_call == DLL_PROCESS_ATTACH ) {
162
163     }
164     return 1;
165
166   }  /* end __OpenGl_INIT__ */
167 #endif  /* WNT */
168
169   /*----------------------------------------------------------------------*/
170
171   WINDOW
172     TxglCreateWindow( DISPLAY  *disp, WINDOW par,
173     Tint x, Tint y, Tint w, Tint h, Tint bw,
174     Tfloat bgcolr, Tfloat bgcolg, Tfloat bgcolb )
175   {
176
177 #ifndef WNT
178
179     GLCONTEXT ctx;
180     Colormap cmap;
181     XVisualInfo* vis=NULL;
182     /*    XVisualInfo tmplt;*/
183     XSetWindowAttributes cwa;
184     XColor color;
185     int value;
186     char string[CALL_DEF_STRING_LENGTH];
187     WINDOW win;
188
189     int DBuffer = (call_util_osd_getenv ("CALL_OPENGL_NO_DBF", string, CALL_DEF_STRING_LENGTH)) ? False : True;
190
191     if (call_util_osd_getenv("JWR_PIXMAP_DB", string, CALL_DEF_STRING_LENGTH))
192       TelSetPixmapDB(1);
193
194     XWindowAttributes wattr;
195     XGetWindowAttributes (disp, par, &wattr);
196     Tint scr = DefaultScreen (disp);
197
198 #if defined(__linux) || defined(Linux)
199     {
200       XVisualInfo aVisInfo;
201       int aNbItems;
202       int isGl, isDoubleBuffer, isRGBA, aDepthSize, aStencilSize;
203       unsigned long aVisInfoMask = VisualIDMask | VisualScreenMask;
204       aVisInfo.visualid = wattr.visual->visualid;
205       aVisInfo.screen   = DefaultScreen (disp);
206       vis = XGetVisualInfo (disp, aVisInfoMask, &aVisInfo, &aNbItems);
207       if (vis != NULL)
208       {
209         // check Visual for OpenGl context's parameters compability
210         if (glXGetConfig (disp, vis, GLX_USE_GL, &isGl) != 0)
211           isGl = 0;
212
213         if (glXGetConfig (disp, vis, GLX_RGBA, &isRGBA) != 0)
214           isRGBA = 0;
215
216         if (glXGetConfig (disp, vis, GLX_DOUBLEBUFFER, &isDoubleBuffer) != 0)
217           isDoubleBuffer = 0;
218
219         if (glXGetConfig (disp, vis, GLX_DEPTH_SIZE, &aDepthSize) != 0)
220           aDepthSize = 0;
221
222         if (glXGetConfig (disp, vis, GLX_STENCIL_SIZE, &aStencilSize) != 0)
223           aStencilSize = 0;
224
225         if (!isGl || !aDepthSize || !aStencilSize ||
226             !isRGBA  || isDoubleBuffer != DBuffer)
227         {
228           XFree (vis);
229           vis = NULL;
230         }
231       }
232     }
233 #endif
234
235     if (vis == NULL)
236     {
237       int anIter = 0;
238       int anAttribs[13];
239       anAttribs[anIter++] = GLX_RGBA;
240
241       anAttribs[anIter++] = GLX_DEPTH_SIZE;
242       anAttribs[anIter++] = 1;
243
244       anAttribs[anIter++] = GLX_STENCIL_SIZE;
245       anAttribs[anIter++] = 1;
246
247       anAttribs[anIter++] = GLX_RED_SIZE;
248       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
249
250       anAttribs[anIter++] = GLX_GREEN_SIZE;
251       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
252
253       anAttribs[anIter++] = GLX_BLUE_SIZE;
254       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
255
256       if (DBuffer)
257         anAttribs[anIter++] = GLX_DOUBLEBUFFER;
258
259       anAttribs[anIter++] = None;
260
261       vis = glXChooseVisual (disp, scr, anAttribs);
262       if (vis == NULL) return TFailure;
263     }
264
265 #ifdef TRACE
266     printf ("TxglCreateWindow \n");
267     printf ("Informations sur le visual\n");
268     printf ("par visualid %x%x %d\n", wattr.visual->visualid, wattr.visual->visualid);
269     printf ("vis visualid 0x%x %d\n", vis->visualid, vis->visualid);
270     printf ("vis depth %d\n", vis->depth);
271     printf ("vis class %d\n", vis->class);
272     printf ("vis red_mask %ld\n", vis->red_mask);
273     printf ("vis green_mask %ld\n", vis->green_mask);
274     printf ("vis blue_mask %ld\n", vis->blue_mask);
275     printf ("vis colormap_size %d\n", vis->colormap_size);
276     printf ("vis bits_per_rgb %d\n", vis->bits_per_rgb);
277     printVisualInfo( disp, vis );
278 #endif
279
280     /*
281     * Le BackDitherProp est utilise pour le clear du background
282     * Pour eviter une difference de couleurs avec la couleur choisie
283     * par l'application (XWindow) il faut desactiver le dithering
284     * au dessus de 8 plans.
285     * 
286     * Pour le DitherProp:
287     * On cherchera a activer le Dithering que si le Visual a au moins
288     * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
289     * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
290     * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
291     */
292
293     glXGetConfig( disp, vis, GLX_RED_SIZE, &value );
294     DitherProp = (value < 8) ? True : False;
295     BackDitherProp = (vis->depth <= 8) ? True : False;
296
297 #ifdef TRACE
298     printf("Dithering %d BackDithering %d \n",DitherProp,BackDitherProp);
299 #endif
300
301     if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
302       DitherProp = False;
303
304     if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
305       BackDitherProp = False;
306
307     if (dead_ctx) {
308       /* recover display lists from dead_ctx, then destroy it */
309       ctx = glXCreateContext( disp, vis, dead_ctx, GL_TRUE );
310       glXDestroyContext(dead_dpy, dead_ctx);
311     } else if (previous_ctx == 0) {
312       ctx = glXCreateContext( disp, vis, NULL, GL_TRUE );
313     } else {
314       /* ctx est une copie du previous */
315       ctx = glXCreateContext( disp, vis, previous_ctx, GL_TRUE );
316     }
317     previous_ctx = ctx;
318
319     if( ctx )
320       OpenGl_ResourceCleaner::GetInstance()->AppendContext( ctx, true );
321
322     // remove the dead_ctx for ResourceCleaner after appending shared ctx
323     if (dead_ctx) {
324       OpenGl_ResourceCleaner::GetInstance()->RemoveContext(dead_ctx);
325       dead_ctx = 0;
326     }
327
328     if( !ctx) return TFailure;
329
330     cmap = XCreateColormap( disp,  par, vis->visual, AllocNone );
331
332     color.red = (unsigned short) (bgcolr * 0xFFFF);
333     color.green = (unsigned short) (bgcolg * 0xFFFF);
334     color.blue  = (unsigned short) (bgcolb * 0xFFFF);
335     color.flags = DoRed | DoGreen | DoBlue;
336     XAllocColor( disp, cmap, &color );
337
338     cwa.colormap  = cmap;
339     cwa.event_mask  = StructureNotifyMask;
340     cwa.border_pixel  = color.pixel;
341     cwa.background_pixel = color.pixel;
342
343     unsigned long mask = CWBackPixel | CWColormap | CWBorderPixel | CWEventMask;
344
345     if( vis->visualid == wattr.visual->visualid ) {
346       win = par;
347     } 
348     else 
349     {
350       win = XCreateWindow( disp, par, x, y, w, h, bw,
351         vis->depth, InputOutput, vis->visual,
352         mask, &cwa );
353     }
354
355 #ifdef TRACE
356     printf ("TxglCreateWindow win %x par %x \n", win, par);
357 #endif
358
359     XSetWindowBackground( disp, win, cwa.background_pixel );
360     XClearWindow( disp, win );
361
362     /* if in Pixmap double buffering mode, set up pixmap */
363
364     if (TelTestPixmapDB())
365     {
366       GC gc;
367       Pixmap pixmap;
368       GLXPixmap glxpixmap;
369
370       printf("setting up pixmap double buffering\n");
371
372       gc = XCreateGC(disp, win, 0, NULL);
373
374       pixmap = XCreatePixmap(disp, win, w, h, vis->depth);
375
376       glxpixmap = glXCreateGLXPixmap(disp, vis, pixmap);
377
378       glXMakeCurrent(disp, glxpixmap, ctx);
379
380       glDrawBuffer(GL_FRONT);
381
382       TelSetPixmapDBParams(disp, win, w, h, vis->depth, gc, pixmap, glxpixmap, ctx);
383     }
384
385     XFree((char*)vis);  
386
387     _Txgl_Map.Bind( (Tint)win, ctx );
388
389     return win;
390
391 #else /* WNT */
392
393     HTBL_ENTRY*           hte;
394     PIXELFORMATDESCRIPTOR pfd;
395     BOOL                  DBuffer = TRUE;
396     int                   iPixelFormat;
397     char                  string[ CALL_DEF_STRING_LENGTH ];
398
399 #ifdef BUC60691
400     OSVERSIONINFO os;
401     os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
402     GetVersionEx(&os);
403     if( os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) win95 = TRUE; 
404 #endif
405
406     if ( _Txgl_Map.IsBound( (Tint)par ) ) {
407       hte = _Txgl_Map.ChangeFind( (Tint)par );
408       if ( hte ) 
409       {
410         ++hte -> nUsed;
411         printf("*TxglCreateWindow.window %d is alreday created\n",par);
412         return par;
413       }
414     }
415
416     hte = new HTBL_ENTRY();
417
418     if ( !hte ) return 0;
419     hte -> hDC   = GetDC ( par );
420
421     iPixelFormat = find_pixel_format(hte, &pfd);
422
423     if ( !iPixelFormat ) 
424     {
425       printf ("*OpenGL interface: ChoosePixelFormat failed. Error code: %d\n",GetLastError ());
426
427       ReleaseDC ( par, hte -> hDC );
428       delete hte;
429
430       return 0;
431     }  
432
433     if ( pfd.dwFlags & PFD_NEED_PALETTE ) 
434     {
435       WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLongPtr ( par, GWLP_USERDATA );
436
437       InterfaceGraphic_RealizePalette (hte -> hDC, wd -> hPal, FALSE,
438         s_sysPalInUse = pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE); 
439     }  
440
441     if ( pfd.cColorBits <= 8 ) 
442     { 
443       DitherProp     = TRUE;
444       BackDitherProp = TRUE;    
445     }  
446
447     if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
448       DitherProp = FALSE;
449
450     if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
451       BackDitherProp = FALSE;
452
453     if (  !SetPixelFormat ( hte -> hDC, iPixelFormat, &pfd )  ) 
454     {
455       printf ("*OpenGL interface: SetPixelFormat failed. Error code %d\n",GetLastError ()); 
456       ReleaseDC ( par, hte -> hDC );
457       delete hte;
458       return 0; 
459     }  
460
461     hte -> hGLRC = wglCreateContext ( hte -> hDC );
462
463     if ( !hte -> hGLRC ) 
464     { 
465       printf ("*OpenGL interface: wglCreateContext failed. Error code: %d\n",GetLastError ());    
466       return 0;     
467     }  
468
469     Standard_Boolean isShared = Standard_True;
470
471     if (previous_ctx == 0 )
472       previous_ctx = hte -> hGLRC;
473     // if we already have some shared context
474     else
475     {
476       // try to share context with one from resource cleaner list
477       GLCONTEXT shareCtx = OpenGl_ResourceCleaner::GetInstance()->GetSharedContext();
478       
479       if (shareCtx != 0)
480         isShared = (Standard_Boolean)wglShareLists(shareCtx, hte -> hGLRC);
481       else
482       {
483         isShared = (Standard_Boolean)wglShareLists(previous_ctx, hte -> hGLRC);
484               // add shared previous_ctx to a control list if it's not there
485         if (isShared)
486           OpenGl_ResourceCleaner::GetInstance()->AppendContext(previous_ctx, isShared);
487       }
488     }
489
490     // add the context to OpenGl_ResourceCleaner control list
491     OpenGl_ResourceCleaner::GetInstance()->AppendContext( hte -> hGLRC, isShared);
492     _Txgl_Map.Bind( (Tint)par, hte );
493
494     return par;
495
496 #endif  /* WNT */
497
498   }
499
500 #ifdef RIC120302
501   WINDOW
502     TxglSetWindow( DISPLAY  *disp, WINDOW par, GLCONTEXT ctx)
503   {
504 #ifndef WNT
505     XVisualInfo* vis;
506     char string[CALL_DEF_STRING_LENGTH];
507     XWindowAttributes wattr;
508
509     XGetWindowAttributes( disp , par , &wattr );
510     {
511       unsigned long vmask = VisualIDMask |  VisualScreenMask;
512       XVisualInfo vinfo;
513       int ninfo;
514       vinfo.visualid = wattr.visual->visualid;
515       vinfo.screen = DefaultScreen( disp );
516       vis = XGetVisualInfo( disp, vmask, &vinfo, &ninfo);
517     }
518
519     if( !vis) return TFailure;
520
521 #ifdef TRACE
522     printf ("TxglSetWindow \n");
523     printf ("Informations sur le visual\n");
524     printf ("par visualid %x%x %d\n", wattr.visual->visualid, wattr.visual->visualid);
525     printf ("vis visualid 0x%x %d\n", vis->visualid, vis->visualid);
526     printf ("vis depth %d\n", vis->depth);
527     printf ("vis class %d\n", vis->class);
528     printf ("vis red_mask %ld\n", vis->red_mask);
529     printf ("vis green_mask %ld\n", vis->green_mask);
530     printf ("vis blue_mask %ld\n", vis->blue_mask);
531     printf ("vis colormap_size %d\n", vis->colormap_size);
532     printf ("vis bits_per_rgb %d\n", vis->bits_per_rgb);
533     printVisualInfo( disp, vis );
534 #endif
535
536     /*
537     * Le BackDitherProp est utilise pour le clear du background
538     * Pour eviter une difference de couleurs avec la couleur choisie
539     * par l'application (XWindow) il faut desactiver le dithering
540     * au dessus de 8 plans.
541     * 
542     * Pour le DitherProp:
543     * On cherchera a activer le Dithering que si le Visual a au moins
544     * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
545     * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
546     * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
547     */
548
549     {
550       int value;
551       glXGetConfig( disp, vis, GLX_RED_SIZE, &value );
552
553       if ( value < 8 ) {
554         DitherProp = True;
555       } else {
556         DitherProp = False;
557       }
558
559       if ( vis->depth <= 8 ) {
560         BackDitherProp = True;
561       } else {
562         BackDitherProp = False;
563       }
564     }
565
566 #ifdef TRACE
567     printf("Dithering %d BackDithering %d \n",DitherProp,BackDitherProp);
568 #endif
569
570     if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
571       DitherProp = False;
572
573     if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
574       BackDitherProp = False;
575
576     previous_ctx = ctx;
577
578     XFree((char*)vis);  
579
580     _Txgl_Map.Bind( ( Tint )par, ctx );
581 #else /* WNT */
582
583     /* abd
584     cmn_htbl_elem         rec;*/
585     HTBL_ENTRY*           hte;
586     PIXELFORMATDESCRIPTOR pfd;
587     BOOL                  DBuffer = TRUE;
588     int                   iPixelFormat;
589     char                  string[ CALL_DEF_STRING_LENGTH ];
590
591 #ifdef BUC60691
592     OSVERSIONINFO os;
593     os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
594     GetVersionEx(&os);
595     if( os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) win95 = TRUE; 
596 #endif
597
598     if ( _Txgl_Map.IsBound( ( Tint )par ) )
599     {
600       hte = _Txgl_Map.ChangeFind( ( Tint )par );
601       ++hte -> nUsed;
602       printf("*TxglSetWindow.window %d is alreday created\n",par);
603       return par;
604     }
605
606     hte = new HTBL_ENTRY();
607
608     if ( !hte ) return 0;
609
610     hte -> hDC   = GetDC ( par );
611     iPixelFormat = find_pixel_format(hte, &pfd);
612
613     if ( !iPixelFormat ) 
614     {
615       printf ("*OpenGL interface: ChoosePixelFormat failed. Error code: %d\n",GetLastError ());
616
617       ReleaseDC ( par, hte -> hDC );
618       delete hte;
619
620       return 0;
621     }  
622
623     if ( pfd.dwFlags & PFD_NEED_PALETTE ) 
624     {
625       WINDOW_DATA* wd = ( WINDOW_DATA* )GetWindowLongPtr ( par, GWLP_USERDATA );
626
627       InterfaceGraphic_RealizePalette (hte -> hDC, wd -> hPal, FALSE,
628         s_sysPalInUse = pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE); 
629     }  
630
631     if ( pfd.cColorBits <= 8 ) 
632     { 
633       DitherProp     = TRUE;
634       BackDitherProp = TRUE;    
635     }  
636
637     if (call_util_osd_getenv ("CALL_OPENGL_NO_DITHER", string, CALL_DEF_STRING_LENGTH))
638       DitherProp = FALSE;
639
640     if (call_util_osd_getenv ("CALL_OPENGL_NO_BACKDITHER", string, CALL_DEF_STRING_LENGTH))
641       BackDitherProp = FALSE;
642
643     if (  !SetPixelFormat ( hte -> hDC, iPixelFormat, &pfd )  ) 
644     {
645       printf ("*OpenGL interface: SetPixelFormat failed. Error code %d\n",GetLastError ()); 
646       ReleaseDC ( par, hte -> hDC );
647       delete hte;
648       return 0; 
649     }  
650
651     hte -> hGLRC = previous_ctx = ctx;
652
653     _Txgl_Map.Bind( ( Tint )par, hte );
654 #endif  /* WNT */
655
656     return par;
657
658   }
659 #endif /*RIC120302*/
660
661   /*----------------------------------------------------------------------*/
662
663   TStatus
664     TxglWinset( DISPLAY *disp, WINDOW win )
665   {
666
667 #ifndef WNT
668
669     Bool  i;
670     GLXContext ctx;
671     GLenum errorcode;
672     const GLubyte *errorstring;
673
674     if ( !_Txgl_Map.IsBound( win ) )
675       return TFailure;
676
677     ctx = _Txgl_Map.ChangeFind( win );
678
679
680 #ifdef TRACE
681     printf ("TxglWinset::glXMakeCurrent %x \n", win);
682 #endif
683     if (TelTestPixmapDB())
684     {
685       i = glXMakeCurrent(disp, TelGetGLXPixmap(), ctx);
686     }
687     else
688     {
689       i = glXMakeCurrent(disp, win, ctx);  /* TRUE/FALSE */
690     }
691     if (!i)
692     {
693       // if there is no current context it might be impossible to use
694       // glGetError correctly
695       printf("glXMakeCurrent failed!\n");
696     }
697
698     return  i == True ? TSuccess : TFailure;
699
700 #else /* WNT */
701
702     HTBL_ENTRY*   hte;
703     HDC    hdc    = NULL;
704     HGLRC  hglrc  = NULL;
705     TStatus       retVal = TFailure;
706
707     __try {
708
709       if ( !_Txgl_Map.IsBound( ( Tint )win ) ) {
710         printf("OpenGL interface:  TxglWinset failed.UNKNOWN win %x\n",win);
711         __leave;
712       }
713       hte = _Txgl_Map.ChangeFind( ( Tint )win );
714
715 #ifdef BUC60691
716       if( win95 ) {
717         retVal = (TStatus)ReleaseDC ( win, hte -> hDC );
718         hte -> hDC   = GetDC ( win );
719       }   
720 #endif
721       if (  !wglMakeCurrent ( hte -> hDC, hte -> hGLRC )  ) 
722       {
723 #ifdef BUC60691
724         GLenum errorcode;
725         const GLubyte *errorstring;
726
727         errorcode = glGetError();
728         errorstring = gluErrorString(errorcode);
729         printf("wglMakeCurrent failed: %d %s\n", errorcode, errorstring);
730 #else
731         printf ("OpenGL interface: wglMakeCurrent failed. Error code: %d\n",GetLastError ());
732 #endif
733         retVal = TFailure;  
734       } else retVal = TSuccess;
735
736     }  /* end __try */
737
738
739     __finally 
740     {    
741     }  
742
743     return retVal;
744
745 #endif  /* WNT */
746
747   }
748
749   /*----------------------------------------------------------------------*/
750
751   WINDOW
752     TxglGetSubWindow( DISPLAY *disp, WINDOW win )
753     /* This function assumes that there is only
754     one child for the parent */
755   {
756
757 #ifndef WNT
758
759     Window root, parent, *child, w;
760     unsigned int num;
761
762     if( XQueryTree( disp, win, &root, &parent, &child, &num ) )
763     {
764       if (! num) return win;
765       w = child[0];
766       XFree( (char *)child );
767       return w;
768     }
769     else
770       return 0;
771
772 #else /* WNT */
773
774     return win;
775
776 #endif  /* WNT */
777
778   }
779
780   /*----------------------------------------------------------------------*/
781
782   void
783     TxglDestroyWindow( DISPLAY *disp, WINDOW win )
784   {
785
786 #ifndef WNT
787
788     GLXContext ctx;
789     Tint dummy;
790
791     if ( !_Txgl_Map.IsBound(win) )
792       return;
793     ctx = _Txgl_Map.ChangeFind(win);
794
795     /* FSXXX sync necessary if non-direct rendering */
796     glXWaitGL();
797
798     _Txgl_Map.UnBind( win );
799
800     if (previous_ctx == ctx) {
801       /* san -- OCC12977: it's important to put some valid GLXContext or null into
802       previous_ctx here, otherwise next glxCreateContext() will crash on some ATI Radeon cards
803       */
804       previous_ctx = NULL;
805       if ( _Txgl_Map.Size() > 0 ) {
806         GLContextMap::Iterator it(_Txgl_Map);
807         previous_ctx = it.Value();
808       }
809       /*
810       * if this is the last remaining context, do not destroy it yet, to avoid
811       * losing any shared display lists (fonts...)
812       */
813       if (previous_ctx) {
814         OpenGl_ResourceCleaner::GetInstance()->RemoveContext(ctx);
815         glXDestroyContext(disp, ctx);
816       } else {
817         dead_ctx = ctx;
818         dead_dpy = disp;
819       }
820     } else {
821       OpenGl_ResourceCleaner::GetInstance()->RemoveContext(ctx);
822       glXDestroyContext(disp, ctx);
823     }
824
825 #else /* WNT */
826
827     HTBL_ENTRY*   hte;
828 #ifdef _DEBUG 
829     WINDOW_DATA*  wd;
830 #endif  /* _DEBUG */
831     if ( !_Txgl_Map.IsBound(( Tint )win) )
832       return;
833     hte = _Txgl_Map.ChangeFind(( Tint )win);
834
835 #ifdef _DEBUG 
836     /* In release version of application we need to process    */
837     /*  palette messages in the main application message loop. */
838     /*  In debug version we don't have message loop for most   */
839     /*  cases. So, let's restore system colors here now.       */
840     wd = ( WINDOW_DATA* )GetWindowLongPtr ( win, GWLP_USERDATA );
841
842     if ( wd != NULL ) InterfaceGraphic_RealizePalette (
843       hte -> hDC, wd -> hPal, TRUE, s_sysPalInUse);
844 #endif  /* _DEBUG */
845
846     if ( --hte -> nUsed == 0 ) 
847     { 
848       OpenGl_ResourceCleaner::GetInstance()->RemoveContext( hte -> hGLRC );
849 #ifdef OCC954    
850       if ( wglGetCurrentContext() != NULL )
851 #endif
852         wglDeleteContext ( hte -> hGLRC );
853       ReleaseDC ( win, hte -> hDC );
854       _Txgl_Map.UnBind( (Tint ) win );
855       if( _Txgl_Map.Size() == 0 ) {
856         previous_ctx = 0;
857       }
858       delete hte;
859     }  
860
861 #endif  /* WNT */
862
863   }
864
865   /*----------------------------------------------------------------------*/
866
867   int
868     TxglGetDither(void)
869   {
870     return DitherProp;
871   }
872
873   /*----------------------------------------------------------------------*/
874
875   int
876     TxglGetBackDither(void)
877   {
878     return BackDitherProp;
879   }
880
881
882   /*----------------------------------------------------------------------*/
883   /*RIC120302*/
884   GLCONTEXT 
885     TxglGetContext( WINDOW win )
886   {
887     GLCONTEXT ctx = NULL;
888     if ( _Txgl_Map.IsBound( (Tint) win ) )
889       ctx = 
890 #ifdef WNT    
891       _Txgl_Map.Find( (Tint) win )->hGLRC;
892 #else
893       _Txgl_Map.Find( win );
894 #endif
895
896     return ctx;  
897   }
898   /*RIC120302*/
899
900   /*----------------------------------------------------------------------*/
901   enum { ZERO = 0, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN };
902
903   /* Unused :*/
904 #ifdef TRACE
905   static const char*
906     className( int class )
907   {
908     static char      *classes[] = {
909       "StaticGray",
910         "GrayScale",
911         "StaticColor",
912         "PseudoColor",
913         "TrueColor",
914         "DirectColor",
915     };
916
917     if ( class < ZERO || class > FIVE )
918       return "unknown";
919     else
920       return classes[class];
921   }
922 #endif
923   /*----------------------------------------------------------------------*/
924 #ifndef WNT
925
926 #ifdef TRACE
927   static GLvoid printVisualInfo( DISPLAY  *display, XVisualInfo *glxVisual )
928   {
929
930 #define TrueFalse(x)  ( x ? "True" : "False" )
931
932     int        tmp;
933
934     printf("\n" );
935     printf("   X Visual Information ...\n\n" );
936     printf("\tvisualid : 0x%x\n", glxVisual->visualid );
937     printf("\tclass    : %s\n\n", className( glxVisual->class ) );
938
939     glXGetConfig(display, glxVisual, GLX_USE_GL, &tmp);
940     printf( "\tSupport GL ( GLX_USE_GL ) : %s\n", TrueFalse(tmp) );
941
942     glXGetConfig(display, glxVisual, GLX_LEVEL, &tmp);
943     printf( "\tFramebuffer ( GLX_LEVEL ) : %s\n\n",
944       (tmp < ZERO) ? "Underlay" : (tmp == ZERO ? "Normal"  : tmp > ONE ? "Overlay"  : "Popup") );
945
946     glXGetConfig(display, glxVisual, GLX_BUFFER_SIZE, &tmp);
947     printf( "\tFramebuffer depth ( GLX_BUFFER_SIZE )     : %d\n", tmp );
948
949     glXGetConfig(display, glxVisual, GLX_DOUBLEBUFFER, &tmp);
950     printf( "\tDoublebuffer ( GLX_DOUBLEBUFFER )         : %s\n",
951       TrueFalse(tmp) );
952
953     glXGetConfig(display, glxVisual, GLX_DEPTH_SIZE, &tmp);
954     printf( "\tDepth buffer depth ( GLX_DEPTH_SIZE )     : %d\n", tmp );
955
956     glXGetConfig(display, glxVisual, GLX_STENCIL_SIZE, &tmp);
957     printf( "\tStencil buffer depth ( GLX_STENCIL_SIZE ) : %d\n", tmp );
958
959     glXGetConfig(display, glxVisual, GLX_STEREO, &tmp);
960     printf( "\tStereo Buffer ( GLX_STEREO )              : %s\n",
961       TrueFalse(tmp) );
962
963     glXGetConfig(display, glxVisual, GLX_AUX_BUFFERS, &tmp);
964     printf( "\tAuxillary Buffers ( GLX_AUX_BUFFERS)      : %d\n\n", tmp );
965
966     glXGetConfig(display, glxVisual, GLX_RGBA, &tmp);
967     printf( "\tColor mode ( GLX_RGBA )       : %s\n", tmp ? "RGBA" :
968     "Color Index" );
969
970     glXGetConfig(display, glxVisual, GLX_RED_SIZE, &tmp);
971     printf( "\tRed Bits ( GLX_RED_SIZE )     : %d\n", tmp );
972
973     glXGetConfig(display, glxVisual, GLX_GREEN_SIZE, &tmp);
974     printf( "\tGreen Bits ( GLX_GREEN_SIZE ) : %d\n", tmp );
975
976     glXGetConfig(display, glxVisual, GLX_BLUE_SIZE, &tmp);
977     printf( "\tBlue Bits ( GLX_BLUE_SIZE )   : %d\n", tmp );
978
979     glXGetConfig(display, glxVisual, GLX_ALPHA_SIZE, &tmp);
980     printf( "\tAlpha Bits ( GLX_ALPHA_SIZE ) : %d\n\n", tmp );
981
982     glXGetConfig(display, glxVisual, GLX_ACCUM_RED_SIZE, &tmp);
983     printf( "\tRed Accumulation Bits ( GLX_ACCUM_RED_SIZE )     : %d\n", tmp );
984
985     glXGetConfig(display, glxVisual, GLX_ACCUM_GREEN_SIZE, &tmp);
986     printf( "\tGreen Accumulation Bits ( GLX_ACCUM_GREEN_SIZE ) : %d\n", tmp );
987
988     glXGetConfig(display, glxVisual, GLX_ACCUM_BLUE_SIZE, &tmp);
989     printf( "\tBlue Accumulation Bits ( GLX_ACCUM_BLUE_SIZE )   : %d\n", tmp );
990
991     glXGetConfig(display, glxVisual, GLX_ACCUM_ALPHA_SIZE, &tmp);
992     printf( "\tAlpha Accumulation Bits ( GLX_ACCUM_ALPHA_SIZE ) : %d\n\n", tmp );
993   }
994 #endif //TRACE
995 #else //WNT
996   int find_pixel_format(HTBL_ENTRY * hte, PIXELFORMATDESCRIPTOR * pfd)
997   {
998     int                   iPixelFormat = 0;
999     int                   iGood = 0;
1000     int                   i, j, k;
1001     PIXELFORMATDESCRIPTOR pfd0;
1002     char                  string[ CALL_DEF_STRING_LENGTH ];
1003     BOOL                  DBuffer = TRUE;
1004     const int             sBits[] = { 8, 1 };
1005     const int             cBits[] = { 32, 24 };
1006     const int             dBits[] = { 32, 24, 16 };
1007     int                   goodBits[3] = { 0, 0, 0 };
1008
1009     if (call_util_osd_getenv ("CALL_OPENGL_NO_DBF",
1010       string, CALL_DEF_STRING_LENGTH)) 
1011       DBuffer = FALSE;
1012
1013     pfd0.nSize           = sizeof ( PIXELFORMATDESCRIPTOR );
1014     pfd0.nVersion        = 1;
1015     pfd0.dwFlags         = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
1016     pfd0.dwFlags        |= ( DBuffer ) ? PFD_DOUBLEBUFFER : PFD_SUPPORT_GDI;
1017     pfd0.iPixelType      = PFD_TYPE_RGBA;
1018     pfd0.cRedBits        = 0;
1019     pfd0.cRedShift       = 0;
1020     pfd0.cGreenBits      = 0;
1021     pfd0.cGreenShift     = 0;
1022     pfd0.cBlueBits       = 0;
1023     pfd0.cBlueShift      = 0;
1024     pfd0.cAlphaBits      = 0;
1025     pfd0.cAlphaShift     = 0;
1026     pfd0.cAccumBits      = 0;
1027     pfd0.cAccumRedBits   = 0;
1028     pfd0.cAccumGreenBits = 0;
1029     pfd0.cAccumBlueBits  = 0;
1030     pfd0.cAccumAlphaBits = 0;
1031     pfd0.cStencilBits    = 0;
1032     pfd0.cAuxBuffers     = 0;
1033     pfd0.iLayerType      = PFD_MAIN_PLANE;
1034     pfd0.bReserved       = 0;
1035     pfd0.dwLayerMask     = 0;
1036     pfd0.dwVisibleMask   = 0;
1037     pfd0.dwDamageMask    = 0;
1038
1039     hte -> nUsed = 1;    
1040     /*
1041       This loop tries to find the pixel format with parameters not worse
1042       than given in sBits, cBits, dBits, giving the priority to color bits
1043       then depth bits, with stencil bits having the lowest priority.
1044       If the needed combination is not found then the iGood value is used, it
1045       is rememebered during the loop as the best ever found combination. 
1046      */
1047
1048     for (k = 0; k < sizeof(sBits) / sizeof(int); k++) {
1049
1050       pfd0.cStencilBits = sBits[k];
1051       for (i = 0; i < sizeof(dBits) / sizeof(int); i++) {
1052
1053         pfd0.cDepthBits = dBits[i];
1054         iGood = 0;
1055         for (j = 0; j < sizeof(cBits) / sizeof(int); j++) {
1056
1057           pfd0.cColorBits = cBits[j];
1058           iPixelFormat = ChoosePixelFormat ( hte -> hDC, &pfd0 );
1059
1060           if (iPixelFormat) {
1061             pfd->cDepthBits = 0;
1062             pfd->cColorBits = 0;
1063             pfd->cStencilBits = 0;
1064             DescribePixelFormat (hte -> hDC, iPixelFormat,
1065                                  sizeof ( PIXELFORMATDESCRIPTOR ), pfd);
1066             if (pfd->cColorBits >= cBits[j] &&
1067                 pfd->cDepthBits >= dBits[i] &&
1068                 pfd->cStencilBits >= sBits[k])
1069               break; /* found - stop the lookup immediately */
1070             if (pfd->cColorBits > goodBits[0]) {
1071               goodBits[0] = pfd->cColorBits;
1072               goodBits[1] = pfd->cDepthBits;
1073               goodBits[2] = pfd->cStencilBits;
1074               iGood = iPixelFormat;
1075             } else if (pfd->cColorBits == goodBits[0]) {
1076               if (pfd->cDepthBits > goodBits[1]) {
1077                 goodBits[1] = pfd->cDepthBits;
1078                 goodBits[2] = pfd->cStencilBits;
1079                 iGood = iPixelFormat;
1080               } else if (pfd->cDepthBits == goodBits[1]) {
1081                 if (pfd->cStencilBits > goodBits[2]) {
1082                   goodBits[2] = pfd->cStencilBits;
1083                   iGood = iPixelFormat;
1084                 }
1085               }
1086             }
1087           }
1088         }
1089         if (j < sizeof(cBits) / sizeof(int))
1090           break;
1091       }
1092       if (i < sizeof(dBits) / sizeof(int))
1093         break;
1094     }
1095
1096     if ( !iPixelFormat )
1097       iPixelFormat = iGood;
1098
1099     return iPixelFormat;
1100   }
1101
1102 #endif  /* WNT */
1103   /*----------------------------------------------------------------------*/