0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[occt.git] / src / OpenGl / OpenGl_Window.cxx
1 // File:      OpenGl_Window.cxx
2 // Created:   20 September 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <InterfaceGraphic.hxx>
7
8 #include <OpenGl_Window.hxx>
9
10 #include <OpenGl_Context.hxx>
11 #include <OpenGl_Display.hxx>
12 #include <OpenGl_ResourceCleaner.hxx>
13 #include <OpenGl_ResourceTexture.hxx>
14
15 #include <Aspect_GraphicDeviceDefinitionError.hxx>
16 #include <TCollection_AsciiString.hxx>
17
18 #include <GL/glu.h> // gluOrtho2D()
19
20 IMPLEMENT_STANDARD_HANDLE(OpenGl_Window,MMgt_TShared)
21 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,MMgt_TShared)
22
23 namespace
24 {
25   static const TEL_COLOUR THE_DEFAULT_BG_COLOR = { { 0.F, 0.F, 0.F, 1.F } };
26
27   static GLCONTEXT ThePreviousCtx = 0; // to share GL resources
28 #if (!defined(_WIN32) && !defined(__WIN32__))
29   static GLXContext TheDeadGlxCtx; // Context to be destroyed
30   static Display*   TheDeadGlxDpy; // Display associated with TheDeadGlxCtx
31 #endif
32   
33 #if (defined(_WIN32) || defined(__WIN32__))
34   static int find_pixel_format (HDC hDC, PIXELFORMATDESCRIPTOR* pfd, const Standard_Boolean dbuff)
35   {
36     PIXELFORMATDESCRIPTOR pfd0;
37     memset (&pfd0, 0, sizeof (PIXELFORMATDESCRIPTOR));
38     pfd0.nSize           = sizeof (PIXELFORMATDESCRIPTOR);
39     pfd0.nVersion        = 1;
40     pfd0.dwFlags         = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | (dbuff ? PFD_DOUBLEBUFFER : PFD_SUPPORT_GDI);
41     pfd0.iPixelType      = PFD_TYPE_RGBA;
42     pfd0.iLayerType      = PFD_MAIN_PLANE;
43
44     int       iPixelFormat = 0;
45     int       iGood = 0;
46     const int cBits[] = { 32, 24 };
47     const int dBits[] = { 32, 24, 16 };
48
49     int i, j;
50     for (i = 0; i < sizeof(dBits) / sizeof(int); i++)
51     {
52       pfd0.cDepthBits = dBits[i];
53       iGood = 0;
54       for (j = 0; j < sizeof(cBits) / sizeof(int); j++)
55       {
56         pfd0.cColorBits = cBits[j];
57         iPixelFormat = ChoosePixelFormat (hDC, &pfd0);
58         if (iPixelFormat)
59         {
60           pfd->cDepthBits = 0;
61           pfd->cColorBits = 0;
62           DescribePixelFormat (hDC, iPixelFormat, sizeof (PIXELFORMATDESCRIPTOR), pfd);
63           if (pfd->cColorBits >= cBits[j] && pfd->cDepthBits >= dBits[i])
64             break;
65           if (iGood == 0)
66             iGood = iPixelFormat;
67         }
68       }
69       if (j < sizeof(cBits) / sizeof(int))
70         break;
71     }
72
73     if (iPixelFormat == 0)
74       iPixelFormat = iGood;
75
76     return iPixelFormat;
77   }
78 #else
79   static Bool WaitForNotify (Display* theDisp, XEvent* theEv, char* theArg)
80   {
81     return (theEv->type == MapNotify) && (theEv->xmap.window == (Window )theArg);
82   }
83 #endif
84
85 };
86
87 // =======================================================================
88 // function : OpenGl_Window
89 // purpose  :
90 // =======================================================================
91 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
92                               const CALL_DEF_WINDOW&        theCWindow,
93                               Aspect_RenderingContext       theGContext)
94 : myDisplay (theDisplay),
95   myWindow (0),
96   myGContext ((GLCONTEXT )theGContext),
97   myGlContext (new OpenGl_Context()),
98   myOwnGContext (theGContext == 0),
99 #if (defined(_WIN32) || defined(__WIN32__))
100   myWindowDC (0),
101   mySysPalInUse (FALSE),
102 #endif
103   myWidth ((Standard_Integer )theCWindow.dx),
104   myHeight ((Standard_Integer )theCWindow.dy),
105   myBgColor (THE_DEFAULT_BG_COLOR),
106   myDither (theDisplay->Dither()),
107   myBackDither (theDisplay->BackDither())
108 {
109   myBgColor.rgb[0] = theCWindow.Background.r;
110   myBgColor.rgb[1] = theCWindow.Background.g;
111   myBgColor.rgb[2] = theCWindow.Background.b;
112
113   WINDOW aParent = (WINDOW )theCWindow.XWindow;
114   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
115
116 #if (!defined(_WIN32) && !defined(__WIN32__))
117   XWindowAttributes wattr;
118   XGetWindowAttributes (aDisp, aParent, &wattr);
119   const int scr = DefaultScreen (aDisp);
120
121   XVisualInfo* aVis = NULL;
122   {
123     unsigned long aVisInfoMask = VisualIDMask | VisualScreenMask;
124     XVisualInfo aVisInfo;
125     aVisInfo.visualid = wattr.visual->visualid;
126     aVisInfo.screen   = scr;
127     int aNbItems;
128     aVis = XGetVisualInfo (aDisp, aVisInfoMask, &aVisInfo, &aNbItems);
129   }
130
131   WINDOW win;
132
133   if (!myOwnGContext)
134   {
135     if (aVis != NULL)
136     {
137       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: XGetVisualInfo failed.");
138       return;
139     }
140
141     win = aParent;
142   }
143   else
144   {
145     GLCONTEXT ctx;
146
147   #if defined(__linux) || defined(Linux)
148     if (aVis != NULL)
149     {
150       // check Visual for OpenGl context's parameters compability
151       int isGl = 0, isDoubleBuffer = 0, isRGBA = 0, aDepthSize = 0;
152
153       if (glXGetConfig (aDisp, aVis, GLX_USE_GL, &isGl) != 0)
154         isGl = 0;
155
156       if (glXGetConfig (aDisp, aVis, GLX_RGBA, &isRGBA) != 0)
157         isRGBA = 0;
158
159       if (glXGetConfig (aDisp, aVis, GLX_DOUBLEBUFFER, &isDoubleBuffer) != 0)
160         isDoubleBuffer = 0;
161
162       if (glXGetConfig (aDisp, aVis, GLX_DEPTH_SIZE, &aDepthSize) != 0)
163         aDepthSize = 0;
164
165       if (!isGl || !aDepthSize || !isRGBA  || (isDoubleBuffer ? 1 : 0) != (myDisplay->DBuffer()? 1 : 0))
166       {
167         XFree (aVis);
168         aVis = NULL;
169       }
170     }
171   #endif
172
173     if (aVis == NULL)
174     {
175       int anIter = 0;
176       int anAttribs[11];
177       anAttribs[anIter++] = GLX_RGBA;
178
179       anAttribs[anIter++] = GLX_DEPTH_SIZE;
180       anAttribs[anIter++] = 1;
181
182       anAttribs[anIter++] = GLX_RED_SIZE;
183       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
184
185       anAttribs[anIter++] = GLX_GREEN_SIZE;
186       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
187
188       anAttribs[anIter++] = GLX_BLUE_SIZE;
189       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
190
191       if (myDisplay->DBuffer())
192         anAttribs[anIter++] = GLX_DOUBLEBUFFER;
193
194       anAttribs[anIter++] = None;
195
196       aVis = glXChooseVisual (aDisp, scr, anAttribs);
197       if (aVis == NULL)
198       {
199         Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXChooseVisual failed.");
200         return;
201       }
202     }
203
204     if (TheDeadGlxCtx)
205     {
206       // recover display lists from TheDeadGlxCtx, then destroy it
207       ctx = glXCreateContext (aDisp, aVis, TheDeadGlxCtx, GL_TRUE);
208
209       OpenGl_ResourceCleaner::GetInstance()->RemoveContext (TheDeadGlxCtx);
210       glXDestroyContext (TheDeadGlxDpy, TheDeadGlxCtx);
211
212       TheDeadGlxCtx = 0;
213     }
214     else if (ThePreviousCtx == 0)
215     {
216       ctx = glXCreateContext (aDisp, aVis, NULL, GL_TRUE);
217     }
218     else
219     {
220       // ctx est une copie du previous
221       ctx = glXCreateContext (aDisp, aVis, ThePreviousCtx, GL_TRUE);
222     }
223
224     if (!ctx)
225     {
226       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXCreateContext failed.");
227       return;
228     }
229
230     OpenGl_ResourceCleaner::GetInstance()->AppendContext (ctx, true);
231
232     ThePreviousCtx = ctx;
233
234     Colormap cmap = XCreateColormap (aDisp, aParent, aVis->visual, AllocNone);
235
236     XColor color;
237     color.red   = (unsigned short) (myBgColor.rgb[0] * 0xFFFF);
238     color.green = (unsigned short) (myBgColor.rgb[1] * 0xFFFF);
239     color.blue  = (unsigned short) (myBgColor.rgb[2] * 0xFFFF);
240     color.flags = DoRed | DoGreen | DoBlue;
241     XAllocColor (aDisp, cmap, &color);
242
243     XSetWindowAttributes cwa;
244     cwa.colormap         = cmap;
245     cwa.event_mask       = StructureNotifyMask;
246     cwa.border_pixel     = color.pixel;
247     cwa.background_pixel = color.pixel;
248
249     if (aVis->visualid == wattr.visual->visualid)
250     {
251       win = aParent;
252     }
253     else
254     {
255       unsigned long mask = CWBackPixel | CWColormap | CWBorderPixel | CWEventMask;
256       win = XCreateWindow (aDisp, aParent, 0, 0, myWidth, myHeight, 0/*bw*/, aVis->depth, InputOutput, aVis->visual, mask, &cwa);
257     }
258
259     XSetWindowBackground (aDisp, win, cwa.background_pixel);
260     XClearWindow (aDisp, win);
261
262     if (win != aParent)
263     {
264       XEvent anEvent;
265       XMapWindow (aDisp, win);
266       XIfEvent (aDisp, &anEvent, WaitForNotify, (char* )win);
267     }
268
269     myGContext = ctx;
270   }
271
272   /*
273   * Le BackDitherProp est utilise pour le clear du background
274   * Pour eviter une difference de couleurs avec la couleur choisie
275   * par l'application (XWindow) il faut desactiver le dithering
276   * au dessus de 8 plans.
277   *
278   * Pour le DitherProp:
279   * On cherchera a activer le Dithering que si le Visual a au moins
280   * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
281   * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
282   * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
283   */
284
285   int value;
286   glXGetConfig (aDisp, aVis, GLX_RED_SIZE, &value);
287
288   if (myDither)
289     myDither = (value < 8);
290
291   if (myBackDither)
292     myBackDither = (aVis->depth <= 8);
293
294   XFree ((char* )aVis);
295
296   myWindow = win;
297
298 #else
299
300   myWindowDC = GetDC (aParent);
301
302   PIXELFORMATDESCRIPTOR pfd;
303   int iPixelFormat = find_pixel_format (myWindowDC, &pfd, myDisplay->DBuffer());
304   if (iPixelFormat == 0)
305   {
306     ReleaseDC (aParent, myWindowDC);
307     myWindowDC = 0;
308
309     TCollection_AsciiString msg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
310     msg += (int )GetLastError();
311     Aspect_GraphicDeviceDefinitionError::Raise (msg.ToCString());
312     return;
313   }
314
315   if (pfd.dwFlags & PFD_NEED_PALETTE)
316   {
317     WINDOW_DATA* wd = (WINDOW_DATA* )GetWindowLongPtr (aParent, GWLP_USERDATA);
318
319     mySysPalInUse = (pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE) ? TRUE : FALSE;
320     InterfaceGraphic_RealizePalette (myWindowDC, wd->hPal, FALSE, mySysPalInUse);
321   }
322
323   if (myDither)
324     myDither = (pfd.cColorBits <= 8);
325
326   if (myBackDither)
327     myBackDither = (pfd.cColorBits <= 8);
328
329   if (!SetPixelFormat (myWindowDC, iPixelFormat, &pfd))
330   {
331     ReleaseDC (aParent, myWindowDC);
332     myWindowDC = NULL;
333
334     TCollection_AsciiString msg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
335     msg += (int)GetLastError();
336     Aspect_GraphicDeviceDefinitionError::Raise (msg.ToCString());
337     return;
338   }
339
340   if (!myOwnGContext)
341   {
342     ThePreviousCtx = myGContext;
343   }
344   else
345   {
346     myGContext = wglCreateContext (myWindowDC);
347     if (myGContext == NULL)
348     {
349       ReleaseDC (aParent, myWindowDC);
350       myWindowDC = NULL;
351
352       TCollection_AsciiString msg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
353       msg += (int )GetLastError();
354       Aspect_GraphicDeviceDefinitionError::Raise (msg.ToCString());
355       return;
356     }
357
358     Standard_Boolean isShared = Standard_True;
359     if (ThePreviousCtx == NULL)
360     {
361       ThePreviousCtx = myGContext;
362     }
363     else
364     {
365       // if we already have some shared context
366       GLCONTEXT shareCtx = OpenGl_ResourceCleaner::GetInstance()->GetSharedContext();
367       if (shareCtx != NULL)
368       {
369         // try to share context with one from resource cleaner list
370         isShared = (Standard_Boolean )wglShareLists (shareCtx, myGContext);
371       }
372       else
373       {
374         isShared = (Standard_Boolean )wglShareLists (ThePreviousCtx, myGContext);
375         // add shared ThePreviousCtx to a control list if it's not there
376         if (isShared)
377           OpenGl_ResourceCleaner::GetInstance()->AppendContext (ThePreviousCtx, isShared);
378       }
379     }
380
381     // add the context to OpenGl_ResourceCleaner control list
382     OpenGl_ResourceCleaner::GetInstance()->AppendContext (myGContext, isShared);
383   }
384
385   myWindow = aParent;
386 #endif
387
388   Init();
389   myGlContext->Init();
390 }
391
392 // =======================================================================
393 // function : ~OpenGl_Window
394 // purpose  :
395 // =======================================================================
396 OpenGl_Window::~OpenGl_Window()
397 {
398   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
399   if (aDisp == NULL || !myOwnGContext)
400     return;
401
402 #if (defined(_WIN32) || defined(__WIN32__))
403   OpenGl_ResourceCleaner::GetInstance()->RemoveContext (myGContext);
404
405   if (wglGetCurrentContext() != NULL)
406     wglDeleteContext (myGContext);
407   ReleaseDC (myWindow, myWindowDC);
408
409   if (myDisplay->myMapOfWindows.Size() == 0)
410     ThePreviousCtx = 0;
411 #else
412   // FSXXX sync necessary if non-direct rendering
413   glXWaitGL();
414
415   if (ThePreviousCtx == myGContext)
416   {
417     ThePreviousCtx = NULL;
418     if (myDisplay->myMapOfWindows.Size() > 0)
419     {
420       NCollection_DataMap<Standard_Integer, Handle(OpenGl_Window)>::Iterator it (myDisplay->myMapOfWindows);
421       ThePreviousCtx = it.Value()->myGContext;
422     }
423
424     // if this is the last remaining context, do not destroy it yet, to avoid
425     // losing any shared display lists (fonts...)
426     if (ThePreviousCtx)
427     {
428       OpenGl_ResourceCleaner::GetInstance()->RemoveContext(myGContext);
429       glXDestroyContext(aDisp, myGContext);
430     }
431     else
432     {
433       TheDeadGlxCtx = myGContext;
434       TheDeadGlxDpy = aDisp;
435     }
436   }
437   else
438   {
439     OpenGl_ResourceCleaner::GetInstance()->RemoveContext (myGContext);
440     glXDestroyContext (aDisp, myGContext);
441   }
442 #endif
443 }
444
445 // =======================================================================
446 // function : Activate
447 // purpose  :
448 // =======================================================================
449 Standard_Boolean OpenGl_Window::Activate()
450 {
451   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
452   if (aDisp == NULL)
453     return Standard_False;
454
455 #if (defined(_WIN32) || defined(__WIN32__))
456   if (!wglMakeCurrent (myWindowDC, myGContext))
457   {
458     //GLenum errorcode = glGetError();
459     //const GLubyte *errorstring = gluErrorString(errorcode);
460     //printf("wglMakeCurrent failed: %d %s\n", errorcode, errorstring);
461     return Standard_False;
462   }
463 #else
464   if (!glXMakeCurrent (aDisp, myWindow, myGContext))
465   {
466     // if there is no current context it might be impossible to use glGetError correctly
467     //printf("glXMakeCurrent failed!\n");
468     return Standard_False;
469   }
470 #endif
471
472   return Standard_True;
473 }
474
475 // =======================================================================
476 // function : Resize
477 // purpose  : call_subr_resize
478 // =======================================================================
479 void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow)
480 {
481   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
482   if (aDisp == NULL)
483     return;
484
485   // If the size is not changed - do nothing
486   if ((myWidth == theCWindow.dx) && (myHeight == theCWindow.dy))
487     return;
488
489   myWidth  = (Standard_Integer )theCWindow.dx;
490   myHeight = (Standard_Integer )theCWindow.dy;
491
492 #if (!defined(_WIN32) && !defined(__WIN32__))
493   XResizeWindow (aDisp, myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
494   XSync (aDisp, False);
495 #endif
496
497   Init();
498 }
499
500 // =======================================================================
501 // function : ReadDepths
502 // purpose  : TelReadDepths
503 // =======================================================================
504 void OpenGl_Window::ReadDepths (const Standard_Integer theX,     const Standard_Integer theY,
505                                 const Standard_Integer theWidth, const Standard_Integer theHeight,
506                                 float* theDepths)
507 {
508   if (theDepths == NULL || !Activate())
509     return;
510
511   glMatrixMode (GL_PROJECTION);
512   glLoadIdentity();
513   gluOrtho2D (0.0, (GLdouble )myWidth, 0.0, (GLdouble )myHeight);
514   glMatrixMode (GL_MODELVIEW);
515   glLoadIdentity();
516
517   glRasterPos2i (theX, theY);
518   DisableFeatures();
519   glReadPixels (theX, theY, theWidth, theHeight, GL_DEPTH_COMPONENT, GL_FLOAT, theDepths);
520   EnableFeatures();
521 }
522
523 // =======================================================================
524 // function : SetBackgroundColor
525 // purpose  : call_subr_set_background
526 // =======================================================================
527 void OpenGl_Window::SetBackgroundColor (const Standard_ShortReal theR,
528                                         const Standard_ShortReal theG,
529                                         const Standard_ShortReal theB)
530 {
531   myBgColor.rgb[0] = theR;
532   myBgColor.rgb[1] = theG;
533   myBgColor.rgb[2] = theB;
534 }
535
536 // =======================================================================
537 // function : Init
538 // purpose  :
539 // =======================================================================
540 void OpenGl_Window::Init()
541 {
542   if (!Activate())
543     return;
544
545 #if (defined(_WIN32) || defined(__WIN32__))
546   RECT cr;
547   GetClientRect (myWindow, &cr);
548   myWidth  = cr.right - cr.left;
549   myHeight = cr.bottom - cr.top;
550 #else
551   Window aRootWin;
552   int aDummy;
553   unsigned int aDummyU;
554   unsigned int aNewWidth  = 0;
555   unsigned int aNewHeight = 0;
556   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
557   XGetGeometry (aDisp, myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU);
558   myWidth  = aNewWidth;
559   myHeight = aNewHeight;
560 #endif
561
562   glMatrixMode (GL_MODELVIEW);
563   glViewport (0, 0, myWidth, myHeight);
564
565   glDisable (GL_SCISSOR_TEST);
566   glDrawBuffer (GL_BACK);
567 }
568
569 // =======================================================================
570 // function : EnablePolygonOffset
571 // purpose  : call_subr_enable_polygon_offset
572 // =======================================================================
573 void OpenGl_Window::EnablePolygonOffset() const
574 {
575   Standard_ShortReal aFactor, aUnits;
576   myDisplay->PolygonOffset (aFactor, aUnits);
577   glPolygonOffset (aFactor, aUnits);
578   glEnable (GL_POLYGON_OFFSET_FILL);
579 }
580
581 // =======================================================================
582 // function : DisablePolygonOffset
583 // purpose  : call_subr_disable_polygon_offset
584 // =======================================================================
585 void OpenGl_Window::DisablePolygonOffset() const
586 {
587   glDisable (GL_POLYGON_OFFSET_FILL);
588 }
589
590 // =======================================================================
591 // function : EnableFeatures
592 // purpose  :
593 // =======================================================================
594 void OpenGl_Window::EnableFeatures() const
595 {
596   /*glPixelTransferi (GL_MAP_COLOR, GL_TRUE);*/
597
598   if (myDither)
599     glEnable (GL_DITHER);
600   else
601     glDisable (GL_DITHER);
602 }
603
604 // =======================================================================
605 // function : DisableFeatures
606 // purpose  :
607 // =======================================================================
608 void OpenGl_Window::DisableFeatures() const
609 {
610   glDisable (GL_DITHER);
611   glPixelTransferi (GL_MAP_COLOR, GL_FALSE);
612
613   /*
614   * Disable stuff that's likely to slow down glDrawPixels.
615   * (Omit as much of this as possible, when you know in advance
616   * that the OpenGL state will already be set correctly.)
617   */
618   glDisable(GL_ALPHA_TEST);
619   glDisable(GL_BLEND);
620   glDisable(GL_DEPTH_TEST);
621   glDisable(GL_FOG);
622   glDisable(GL_LIGHTING);
623
624   glDisable(GL_LOGIC_OP);
625   glDisable(GL_STENCIL_TEST);
626   glDisable(GL_TEXTURE_1D);
627   glDisable(GL_TEXTURE_2D);
628   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
629   glPixelTransferi(GL_RED_SCALE, 1);
630   glPixelTransferi(GL_RED_BIAS, 0);
631   glPixelTransferi(GL_GREEN_SCALE, 1);
632   glPixelTransferi(GL_GREEN_BIAS, 0);
633   glPixelTransferi(GL_BLUE_SCALE, 1);
634   glPixelTransferi(GL_BLUE_BIAS, 0);
635   glPixelTransferi(GL_ALPHA_SCALE, 1);
636   glPixelTransferi(GL_ALPHA_BIAS, 0);
637
638   /*
639   * Disable extensions that could slow down glDrawPixels.
640   * (Actually, you should check for the presence of the proper
641   * extension before making these calls.  I've omitted that
642   * code for simplicity.)
643   */
644
645 #ifdef GL_EXT_convolution
646   glDisable(GL_CONVOLUTION_1D_EXT);
647   glDisable(GL_CONVOLUTION_2D_EXT);
648   glDisable(GL_SEPARABLE_2D_EXT);
649 #endif
650
651 #ifdef GL_EXT_histogram
652   glDisable(GL_HISTOGRAM_EXT);
653   glDisable(GL_MINMAX_EXT);
654 #endif
655
656 #ifdef GL_EXT_texture3D
657   glDisable(GL_TEXTURE_3D_EXT);
658 #endif
659 }
660
661 // =======================================================================
662 // function : MakeFrontBufCurrent
663 // purpose  : TelMakeFrontBufCurrent
664 // =======================================================================
665 void OpenGl_Window::MakeFrontBufCurrent() const
666 {
667   glDrawBuffer (GL_FRONT);
668 }
669
670 // =======================================================================
671 // function : MakeBackBufCurrent
672 // purpose  : TelMakeBackBufCurrent
673 // =======================================================================
674 void OpenGl_Window::MakeBackBufCurrent() const
675 {
676   glDrawBuffer (GL_BACK);
677 }
678
679 // =======================================================================
680 // function : MakeFrontAndBackBufCurrent
681 // purpose  : TelMakeFrontAndBackBufCurrent
682 // =======================================================================
683 void OpenGl_Window::MakeFrontAndBackBufCurrent() const
684 {
685   glDrawBuffer (GL_FRONT_AND_BACK);
686 }