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