0024001: Stereographic rendering support
[occt.git] / src / OpenGl / OpenGl_Window.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_GlCore12.hxx>
17
18 #include <InterfaceGraphic.hxx>
19
20 #include <OpenGl_Window.hxx>
21
22 #include <OpenGl_Context.hxx>
23 #include <OpenGl_Display.hxx>
24
25 #include <Aspect_GraphicDeviceDefinitionError.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <TCollection_ExtendedString.hxx>
28
29 IMPLEMENT_STANDARD_HANDLE(OpenGl_Window,MMgt_TShared)
30 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,MMgt_TShared)
31
32 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
33
34 namespace
35 {
36   static const TEL_COLOUR THE_DEFAULT_BG_COLOR = { { 0.F, 0.F, 0.F, 1.F } };
37
38 #if defined(_WIN32)
39
40   // WGL_ARB_pixel_format
41 #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
42   #define WGL_NUMBER_PIXEL_FORMATS_ARB            0x2000
43   #define WGL_DRAW_TO_WINDOW_ARB                  0x2001
44   #define WGL_DRAW_TO_BITMAP_ARB                  0x2002
45   #define WGL_ACCELERATION_ARB                    0x2003
46   #define WGL_NEED_PALETTE_ARB                    0x2004
47   #define WGL_NEED_SYSTEM_PALETTE_ARB             0x2005
48   #define WGL_SWAP_LAYER_BUFFERS_ARB              0x2006
49   #define WGL_SWAP_METHOD_ARB                     0x2007
50   #define WGL_NUMBER_OVERLAYS_ARB                 0x2008
51   #define WGL_NUMBER_UNDERLAYS_ARB                0x2009
52   #define WGL_TRANSPARENT_ARB                     0x200A
53   #define WGL_TRANSPARENT_RED_VALUE_ARB           0x2037
54   #define WGL_TRANSPARENT_GREEN_VALUE_ARB         0x2038
55   #define WGL_TRANSPARENT_BLUE_VALUE_ARB          0x2039
56   #define WGL_TRANSPARENT_ALPHA_VALUE_ARB         0x203A
57   #define WGL_TRANSPARENT_INDEX_VALUE_ARB         0x203B
58   #define WGL_SHARE_DEPTH_ARB                     0x200C
59   #define WGL_SHARE_STENCIL_ARB                   0x200D
60   #define WGL_SHARE_ACCUM_ARB                     0x200E
61   #define WGL_SUPPORT_GDI_ARB                     0x200F
62   #define WGL_SUPPORT_OPENGL_ARB                  0x2010
63   #define WGL_DOUBLE_BUFFER_ARB                   0x2011
64   #define WGL_STEREO_ARB                          0x2012
65   #define WGL_PIXEL_TYPE_ARB                      0x2013
66   #define WGL_COLOR_BITS_ARB                      0x2014
67   #define WGL_RED_BITS_ARB                        0x2015
68   #define WGL_RED_SHIFT_ARB                       0x2016
69   #define WGL_GREEN_BITS_ARB                      0x2017
70   #define WGL_GREEN_SHIFT_ARB                     0x2018
71   #define WGL_BLUE_BITS_ARB                       0x2019
72   #define WGL_BLUE_SHIFT_ARB                      0x201A
73   #define WGL_ALPHA_BITS_ARB                      0x201B
74   #define WGL_ALPHA_SHIFT_ARB                     0x201C
75   #define WGL_ACCUM_BITS_ARB                      0x201D
76   #define WGL_ACCUM_RED_BITS_ARB                  0x201E
77   #define WGL_ACCUM_GREEN_BITS_ARB                0x201F
78   #define WGL_ACCUM_BLUE_BITS_ARB                 0x2020
79   #define WGL_ACCUM_ALPHA_BITS_ARB                0x2021
80   #define WGL_DEPTH_BITS_ARB                      0x2022
81   #define WGL_STENCIL_BITS_ARB                    0x2023
82   #define WGL_AUX_BUFFERS_ARB                     0x2024
83
84   #define WGL_NO_ACCELERATION_ARB                 0x2025
85   #define WGL_GENERIC_ACCELERATION_ARB            0x2026
86   #define WGL_FULL_ACCELERATION_ARB               0x2027
87
88   #define WGL_SWAP_EXCHANGE_ARB                   0x2028
89   #define WGL_SWAP_COPY_ARB                       0x2029
90   #define WGL_SWAP_UNDEFINED_ARB                  0x202A
91
92   #define WGL_TYPE_RGBA_ARB                       0x202B
93   #define WGL_TYPE_COLORINDEX_ARB                 0x202C
94 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
95
96   // WGL_ARB_create_context_profile
97 #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
98   #define WGL_CONTEXT_MAJOR_VERSION_ARB           0x2091
99   #define WGL_CONTEXT_MINOR_VERSION_ARB           0x2092
100   #define WGL_CONTEXT_LAYER_PLANE_ARB             0x2093
101   #define WGL_CONTEXT_FLAGS_ARB                   0x2094
102   #define WGL_CONTEXT_PROFILE_MASK_ARB            0x9126
103
104   // WGL_CONTEXT_FLAGS bits
105   #define WGL_CONTEXT_DEBUG_BIT_ARB               0x0001
106   #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
107
108   // WGL_CONTEXT_PROFILE_MASK_ARB bits
109   #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
110   #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
111 #endif // WGL_CONTEXT_MAJOR_VERSION_ARB
112
113   static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
114   {
115     return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
116   }
117 #else
118   static Bool WaitForNotify (Display* theDisp, XEvent* theEv, char* theArg)
119   {
120     return (theEv->type == MapNotify) && (theEv->xmap.window == (Window )theArg);
121   }
122 #endif
123
124 }
125
126 // =======================================================================
127 // function : OpenGl_Window
128 // purpose  :
129 // =======================================================================
130 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
131                               const CALL_DEF_WINDOW&        theCWindow,
132                               Aspect_RenderingContext       theGContext,
133                               const Handle(OpenGl_Caps)&    theCaps,
134                               const Handle(OpenGl_Context)& theShareCtx)
135 : myDisplay (theDisplay),
136   myGlContext (new OpenGl_Context (theCaps)),
137   myOwnGContext (theGContext == 0),
138 #if defined(_WIN32)
139   mySysPalInUse (FALSE),
140 #endif
141   myWidth ((Standard_Integer )theCWindow.dx),
142   myHeight ((Standard_Integer )theCWindow.dy),
143   myBgColor (THE_DEFAULT_BG_COLOR),
144   myDither (theDisplay->Dither()),
145   myBackDither (theDisplay->BackDither())
146 {
147   myBgColor.rgb[0] = theCWindow.Background.r;
148   myBgColor.rgb[1] = theCWindow.Background.g;
149   myBgColor.rgb[2] = theCWindow.Background.b;
150
151 #if defined(_WIN32)
152   HWND  aWindow   = (HWND )theCWindow.XWindow;
153   HDC   aWindowDC = GetDC (aWindow);
154   HGLRC aGContext = (HGLRC )theGContext;
155
156   PIXELFORMATDESCRIPTOR aPixelFrmt;
157   memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
158   aPixelFrmt.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
159   aPixelFrmt.nVersion     = 1;
160   aPixelFrmt.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
161   aPixelFrmt.iPixelType   = PFD_TYPE_RGBA;
162   aPixelFrmt.cColorBits   = 24;
163   aPixelFrmt.cDepthBits   = 24;
164   aPixelFrmt.cStencilBits = 8;
165   aPixelFrmt.iLayerType   = PFD_MAIN_PLANE;
166   if (theCaps->contextStereo)
167   {
168     aPixelFrmt.dwFlags |= PFD_STEREO;
169   }
170
171   int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
172
173   // in case of failure try without stereo if any
174   if (aPixelFrmtId == 0 && theCaps->contextStereo)
175   {
176     TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
177                                      "ChoosePixelFormat is unable to find stereo supported pixel format. "
178                                      "Choosing similar non stereo format.");
179     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
180                               GL_DEBUG_TYPE_OTHER_ARB,
181                               0, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
182
183     aPixelFrmt.dwFlags &= ~PFD_STEREO;
184     aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
185   }
186
187   if (aPixelFrmtId == 0)
188   {
189     ReleaseDC (aWindow, aWindowDC);
190
191     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
192     aMsg += (int )GetLastError();
193     Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString());
194     return;
195   }
196
197   DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
198   if (aPixelFrmt.dwFlags & PFD_NEED_PALETTE)
199   {
200     WINDOW_DATA* aWndData = (WINDOW_DATA* )GetWindowLongPtr (aWindow, GWLP_USERDATA);
201
202     mySysPalInUse = (aPixelFrmt.dwFlags & PFD_NEED_SYSTEM_PALETTE) ? TRUE : FALSE;
203     InterfaceGraphic_RealizePalette (aWindowDC, aWndData->hPal, FALSE, mySysPalInUse);
204   }
205
206   if (myDither)
207   {
208     myDither = (aPixelFrmt.cColorBits <= 8);
209   }
210
211   if (myBackDither)
212   {
213     myBackDither = (aPixelFrmt.cColorBits <= 8);
214   }
215
216   HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
217   if (aGContext == NULL)
218   {
219     // create temporary context to retrieve advanced context creation procedures
220     HMODULE aModule = GetModuleHandleW(NULL);
221     WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
222     aClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
223     aClass.lpfnWndProc   = wndProcDummy;
224     aClass.hInstance     = aModule;
225     aClass.lpszClassName = L"OpenGl_WindowTmp";
226     HWND  aWinTmp     = NULL;
227     HDC   aDevCtxTmp  = NULL;
228     HGLRC aRendCtxTmp = NULL;
229     if ((!theCaps->contextDebug && !theCaps->contextNoAccel)
230      || RegisterClassW (&aClass) == 0)
231     {
232       aClass.lpszClassName = NULL;
233     }
234     if (aClass.lpszClassName != NULL)
235     {
236       DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
237     #if (_WIN32_WINNT >= 0x0500)
238       anExStyle |= WS_EX_NOACTIVATE;
239     #endif
240       aWinTmp = CreateWindowExW(anExStyle,
241                                 aClass.lpszClassName, L"OpenGl_WindowTmp",
242                                 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
243                                 2, 2, 4, 4,
244                                 NULL, NULL, aModule, NULL);
245     }
246     if (aWinTmp != NULL)
247     {
248       aDevCtxTmp = GetDC (aWinTmp);
249       SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
250       aRendCtxTmp = wglCreateContext (aDevCtxTmp);
251     }
252
253     typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC           theDevCtx,
254                                                      const int*    theIntAttribs,
255                                                      const float*  theFloatAttribs,
256                                                      unsigned int  theMaxFormats,
257                                                      int*          theFormatsOut,
258                                                      unsigned int* theNumFormatsOut);
259     typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC        theDevCtx,
260                                                          HGLRC      theShareContext,
261                                                          const int* theAttribs);
262     wglChoosePixelFormatARB_t    aChoosePixProc = NULL;
263     wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
264     if (aRendCtxTmp != NULL)
265     {
266       wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
267
268       typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
269       wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t  )wglGetProcAddress ("wglGetExtensionsStringARB");
270       const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
271       if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
272       {
273         aChoosePixProc = (wglChoosePixelFormatARB_t    )wglGetProcAddress ("wglChoosePixelFormatARB");
274       }
275       if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
276       {
277         aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
278       }
279     }
280
281     // choose extended pixel format
282     if (aChoosePixProc != NULL)
283     {
284       const int aPixAttribs[] =
285       {
286         WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
287         WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
288         WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
289         WGL_STEREO_ARB,         theCaps->contextStereo ? GL_TRUE : GL_FALSE,
290         WGL_PIXEL_TYPE_ARB,     WGL_TYPE_RGBA_ARB,
291         //WGL_SAMPLE_BUFFERS_ARB, 1,
292         //WGL_SAMPLES_ARB,        8,
293         WGL_COLOR_BITS_ARB,     24,
294         WGL_DEPTH_BITS_ARB,     24,
295         WGL_STENCIL_BITS_ARB,   8,
296         WGL_ACCELERATION_ARB,   theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
297         0, 0,
298       };
299       unsigned int aFrmtsNb = 0;
300       aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
301     }
302
303     // setup pixel format - may be set only once per window
304     if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
305     {
306       ReleaseDC (aWindow, aWindowDC);
307
308       TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
309       aMsg += (int )GetLastError();
310       Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString());
311       return;
312     }
313
314     // create GL context with extra options
315     if (aCreateCtxProc != NULL)
316     {
317       // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
318       // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
319       int aCtxAttribs[] =
320       {
321         //WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
322         //WGL_CONTEXT_MINOR_VERSION_ARB, 2,
323         //WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
324         WGL_CONTEXT_FLAGS_ARB,         theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
325         0, 0
326       };
327
328       aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
329       if (aGContext != NULL)
330       {
331         aSlaveCtx = NULL;
332       }
333     }
334
335     if (aRendCtxTmp != NULL)
336     {
337       wglDeleteContext (aRendCtxTmp);
338     }
339     if (aDevCtxTmp != NULL)
340     {
341       ReleaseDC (aWinTmp, aDevCtxTmp);
342     }
343     if (aWinTmp != NULL)
344     {
345       DestroyWindow (aWinTmp);
346     }
347     if (aClass.lpszClassName != NULL)
348     {
349       UnregisterClassW (aClass.lpszClassName, aModule);
350     }
351
352     if (aGContext == NULL)
353     {
354       // create context using obsolete functionality
355       aGContext = wglCreateContext (aWindowDC);
356     }
357     if (aGContext == NULL)
358     {
359       ReleaseDC (aWindow, aWindowDC);
360
361       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
362       aMsg += (int )GetLastError();
363       Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString());
364       return;
365     }
366   }
367
368   // all GL context within one OpenGl_GraphicDriver should be shared!
369   if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
370   {
371     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
372     aMsg += (int )GetLastError();
373     Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString());
374     return;
375   }
376
377   myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext);
378 #else
379   WINDOW aParent = (WINDOW )theCWindow.XWindow;
380   WINDOW aWindow = 0;
381   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
382   GLXContext aGContext = (GLXContext )theGContext;
383
384   XWindowAttributes wattr;
385   XGetWindowAttributes (aDisp, aParent, &wattr);
386   const int scr = DefaultScreen (aDisp);
387
388   XVisualInfo* aVis = NULL;
389   {
390     unsigned long aVisInfoMask = VisualIDMask | VisualScreenMask;
391     XVisualInfo aVisInfo;
392     aVisInfo.visualid = wattr.visual->visualid;
393     aVisInfo.screen   = scr;
394     int aNbItems;
395     aVis = XGetVisualInfo (aDisp, aVisInfoMask, &aVisInfo, &aNbItems);
396   }
397
398   if (!myOwnGContext)
399   {
400     if (aVis != NULL)
401     {
402       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: XGetVisualInfo failed.");
403       return;
404     }
405
406     aWindow = aParent;
407   }
408   else
409   {
410   #if defined(__linux) || defined(Linux) || defined(__APPLE__)
411     if (aVis != NULL)
412     {
413       // check Visual for OpenGl context's parameters compability
414       int isGl = 0, isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
415       int aDepthSize = 0, aStencilSize = 0;
416
417       if (glXGetConfig (aDisp, aVis, GLX_USE_GL, &isGl) != 0)
418         isGl = 0;
419
420       if (glXGetConfig (aDisp, aVis, GLX_RGBA, &isRGBA) != 0)
421         isRGBA = 0;
422
423       if (glXGetConfig (aDisp, aVis, GLX_DOUBLEBUFFER, &isDoubleBuffer) != 0)
424         isDoubleBuffer = 0;
425
426       if (glXGetConfig (aDisp, aVis, GLX_STEREO, &isStereo) != 0)
427         isStereo = 0;
428
429       if (glXGetConfig (aDisp, aVis, GLX_DEPTH_SIZE, &aDepthSize) != 0)
430         aDepthSize = 0;
431
432       if (glXGetConfig (aDisp, aVis, GLX_STENCIL_SIZE, &aStencilSize) != 0)
433         aStencilSize = 0;
434
435       if (!isGl || !aDepthSize || !isRGBA  || !aStencilSize ||
436           (isDoubleBuffer ? 1 : 0) != (myDisplay->DBuffer()   ? 1 : 0) ||
437           (isStereo       ? 1 : 0) != (theCaps->contextStereo ? 1 : 0))
438       {
439         XFree (aVis);
440         aVis = NULL;
441       }
442     }
443   #endif
444
445     if (aVis == NULL)
446     {
447       int anIter = 0;
448       int anAttribs[13];
449       anAttribs[anIter++] = GLX_RGBA;
450
451       anAttribs[anIter++] = GLX_DEPTH_SIZE;
452       anAttribs[anIter++] = 1;
453
454       anAttribs[anIter++] = GLX_STENCIL_SIZE;
455       anAttribs[anIter++] = 1;
456
457       anAttribs[anIter++] = GLX_RED_SIZE;
458       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
459
460       anAttribs[anIter++] = GLX_GREEN_SIZE;
461       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
462
463       anAttribs[anIter++] = GLX_BLUE_SIZE;
464       anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1;
465
466       if (myDisplay->DBuffer())
467         anAttribs[anIter++] = GLX_DOUBLEBUFFER;
468
469       // warning: this flag may be set to None, so it need to be last in anAttribs
470       Standard_Integer aStereoFlagPos = anIter;
471       if (theCaps->contextStereo)
472         anAttribs[anIter++] = GLX_STEREO;
473
474       anAttribs[anIter++] = None;
475
476       aVis = glXChooseVisual (aDisp, scr, anAttribs);
477
478       // in case of failure try without stereo if any
479       if (aVis == NULL && theCaps->contextStereo)
480       {
481         TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
482                                          "glXChooseVisual is unable to find stereo supported pixel format. "
483                                          "Choosing similar non stereo format.");
484         myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
485                                   GL_DEBUG_TYPE_OTHER_ARB,
486                                   0, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
487
488         anAttribs[aStereoFlagPos] = None;
489         aVis = glXChooseVisual (aDisp, scr, anAttribs);
490       }
491
492       if (aVis == NULL)
493       {
494         Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXChooseVisual failed.");
495         return;
496       }
497     }
498
499     if (!theShareCtx.IsNull())
500     {
501       // ctx est une copie du previous
502       aGContext = glXCreateContext (aDisp, aVis, (GLXContext )theShareCtx->myGContext, GL_TRUE);
503     }
504     else
505     {
506       aGContext = glXCreateContext (aDisp, aVis, NULL, GL_TRUE);
507     }
508
509     if (!aGContext)
510     {
511       Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXCreateContext failed.");
512       return;
513     }
514
515     Colormap cmap = XCreateColormap (aDisp, aParent, aVis->visual, AllocNone);
516
517     XColor color;
518     color.red   = (unsigned short) (myBgColor.rgb[0] * 0xFFFF);
519     color.green = (unsigned short) (myBgColor.rgb[1] * 0xFFFF);
520     color.blue  = (unsigned short) (myBgColor.rgb[2] * 0xFFFF);
521     color.flags = DoRed | DoGreen | DoBlue;
522     XAllocColor (aDisp, cmap, &color);
523
524     XSetWindowAttributes cwa;
525     cwa.colormap         = cmap;
526     cwa.event_mask       = StructureNotifyMask;
527     cwa.border_pixel     = color.pixel;
528     cwa.background_pixel = color.pixel;
529
530     if (aVis->visualid == wattr.visual->visualid)
531     {
532       aWindow = aParent;
533     }
534     else
535     {
536       unsigned long mask = CWBackPixel | CWColormap | CWBorderPixel | CWEventMask;
537       aWindow = XCreateWindow (aDisp, aParent, 0, 0, myWidth, myHeight, 0/*bw*/, aVis->depth, InputOutput, aVis->visual, mask, &cwa);
538     }
539
540     XSetWindowBackground (aDisp, aWindow, cwa.background_pixel);
541     XClearWindow (aDisp, aWindow);
542
543     if (aWindow != aParent)
544     {
545       XEvent anEvent;
546       XMapWindow (aDisp, aWindow);
547       XIfEvent (aDisp, &anEvent, WaitForNotify, (char* )aWindow);
548     }
549   }
550
551   /*
552   * Le BackDitherProp est utilise pour le clear du background
553   * Pour eviter une difference de couleurs avec la couleur choisie
554   * par l'application (XWindow) il faut desactiver le dithering
555   * au dessus de 8 plans.
556   *
557   * Pour le DitherProp:
558   * On cherchera a activer le Dithering que si le Visual a au moins
559   * 8 plans pour le GLX_RED_SIZE. Le test est plus sur car on peut
560   * avoir une profondeur superieure a 12 mais avoir besoin du dithering.
561   * (Carte Impact avec GLX_RED_SIZE a 5 par exemple)
562   */
563
564   int aValue;
565   glXGetConfig (aDisp, aVis, GLX_RED_SIZE, &aValue);
566
567   if (myDither)
568     myDither = (aValue < 8);
569
570   if (myBackDither)
571     myBackDither = (aVis->depth <= 8);
572
573   XFree ((char* )aVis);
574
575   myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )myDisplay->GetDisplay(), (Aspect_RenderingContext )aGContext);
576 #endif
577   myGlContext->Share (theShareCtx);
578
579   Init();
580 }
581
582 // =======================================================================
583 // function : ~OpenGl_Window
584 // purpose  :
585 // =======================================================================
586 OpenGl_Window::~OpenGl_Window()
587 {
588   if (!myOwnGContext)
589   {
590     myGlContext.Nullify();
591     return;
592   }
593
594   // release "GL" context if it is owned by window
595 #if defined(_WIN32)
596   HWND  aWindow          = (HWND  )myGlContext->myWindow;
597   HDC   aWindowDC        = (HDC   )myGlContext->myWindowDC;
598   HGLRC aWindowGContext  = (HGLRC )myGlContext->myGContext;
599   HGLRC aThreadGlContext = wglGetCurrentContext();
600   myGlContext.Nullify();
601
602   if (aThreadGlContext != NULL)
603   {
604     // Mesa implementation can fail to reset this thread's context if wglDeleteContext()
605     // called without this step. This might lead to crash when using newly created
606     // context if wglMakeCurrent() is not forced right after the wglCreateContext().
607     if (aThreadGlContext == aWindowGContext)
608     {
609       wglMakeCurrent (NULL, NULL);
610     }
611
612     wglDeleteContext (aWindowGContext);
613   }
614   ReleaseDC (aWindow, aWindowDC);
615 #else
616   Display*    aDisplay  = (Display*    )myGlContext->myDisplay;
617   GLXContext  aGContext = (GLXContext  )myGlContext->myGContext;
618   myGlContext.Nullify();
619
620   if (aDisplay != NULL)
621   {
622     // FSXXX sync necessary if non-direct rendering
623     glXWaitGL();
624     glXDestroyContext (aDisplay, aGContext);
625   }
626 #endif
627 }
628
629 #endif // !__APPLE__
630
631 // =======================================================================
632 // function : Activate
633 // purpose  :
634 // =======================================================================
635 Standard_Boolean OpenGl_Window::Activate()
636 {
637   return myGlContext->MakeCurrent();
638 }
639
640 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
641
642 // =======================================================================
643 // function : Resize
644 // purpose  : call_subr_resize
645 // =======================================================================
646 void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow)
647 {
648   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
649   if (aDisp == NULL)
650     return;
651
652   // If the size is not changed - do nothing
653   if ((myWidth == theCWindow.dx) && (myHeight == theCWindow.dy))
654     return;
655
656   myWidth  = (Standard_Integer )theCWindow.dx;
657   myHeight = (Standard_Integer )theCWindow.dy;
658
659 #if !defined(_WIN32)
660   XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
661   XSync (aDisp, False);
662 #endif
663
664   Init();
665 }
666
667 #endif // !__APPLE__
668
669 // =======================================================================
670 // function : ReadDepths
671 // purpose  : TelReadDepths
672 // =======================================================================
673 void OpenGl_Window::ReadDepths (const Standard_Integer theX,     const Standard_Integer theY,
674                                 const Standard_Integer theWidth, const Standard_Integer theHeight,
675                                 float* theDepths)
676 {
677   if (theDepths == NULL || !Activate())
678     return;
679
680   glMatrixMode (GL_PROJECTION);
681   glLoadIdentity();
682   gluOrtho2D (0.0, (GLdouble )myWidth, 0.0, (GLdouble )myHeight);
683   glMatrixMode (GL_MODELVIEW);
684   glLoadIdentity();
685
686   glRasterPos2i (theX, theY);
687   DisableFeatures();
688   glReadPixels (theX, theY, theWidth, theHeight, GL_DEPTH_COMPONENT, GL_FLOAT, theDepths);
689   EnableFeatures();
690 }
691
692 // =======================================================================
693 // function : SetBackgroundColor
694 // purpose  : call_subr_set_background
695 // =======================================================================
696 void OpenGl_Window::SetBackgroundColor (const Standard_ShortReal theR,
697                                         const Standard_ShortReal theG,
698                                         const Standard_ShortReal theB)
699 {
700   myBgColor.rgb[0] = theR;
701   myBgColor.rgb[1] = theG;
702   myBgColor.rgb[2] = theB;
703 }
704
705 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
706
707 // =======================================================================
708 // function : Init
709 // purpose  :
710 // =======================================================================
711 void OpenGl_Window::Init()
712 {
713   if (!Activate())
714     return;
715
716 #if defined(_WIN32)
717   RECT cr;
718   GetClientRect ((HWND )myGlContext->myWindow, &cr);
719   myWidth  = cr.right - cr.left;
720   myHeight = cr.bottom - cr.top;
721 #else
722   Window aRootWin;
723   int aDummy;
724   unsigned int aDummyU;
725   unsigned int aNewWidth  = 0;
726   unsigned int aNewHeight = 0;
727   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
728   XGetGeometry (aDisp, myGlContext->myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU);
729   myWidth  = aNewWidth;
730   myHeight = aNewHeight;
731 #endif
732
733   glMatrixMode (GL_MODELVIEW);
734   glViewport (0, 0, myWidth, myHeight);
735
736   glDisable (GL_SCISSOR_TEST);
737   glDrawBuffer (GL_BACK);
738 }
739
740 #endif // !__APPLE__
741
742 // =======================================================================
743 // function : EnablePolygonOffset
744 // purpose  : call_subr_enable_polygon_offset
745 // =======================================================================
746 void OpenGl_Window::EnablePolygonOffset() const
747 {
748   Standard_ShortReal aFactor, aUnits;
749   myDisplay->PolygonOffset (aFactor, aUnits);
750   glPolygonOffset (aFactor, aUnits);
751   glEnable (GL_POLYGON_OFFSET_FILL);
752 }
753
754 // =======================================================================
755 // function : DisablePolygonOffset
756 // purpose  : call_subr_disable_polygon_offset
757 // =======================================================================
758 void OpenGl_Window::DisablePolygonOffset() const
759 {
760   glDisable (GL_POLYGON_OFFSET_FILL);
761 }
762
763 // =======================================================================
764 // function : EnableFeatures
765 // purpose  :
766 // =======================================================================
767 void OpenGl_Window::EnableFeatures() const
768 {
769   /*glPixelTransferi (GL_MAP_COLOR, GL_TRUE);*/
770
771   if (myDither)
772     glEnable (GL_DITHER);
773   else
774     glDisable (GL_DITHER);
775 }
776
777 // =======================================================================
778 // function : DisableFeatures
779 // purpose  :
780 // =======================================================================
781 void OpenGl_Window::DisableFeatures() const
782 {
783   glDisable (GL_DITHER);
784   glPixelTransferi (GL_MAP_COLOR, GL_FALSE);
785
786   /*
787   * Disable stuff that's likely to slow down glDrawPixels.
788   * (Omit as much of this as possible, when you know in advance
789   * that the OpenGL state will already be set correctly.)
790   */
791   glDisable(GL_ALPHA_TEST);
792   glDisable(GL_BLEND);
793   glDisable(GL_DEPTH_TEST);
794   glDisable(GL_FOG);
795   glDisable(GL_LIGHTING);
796
797   glDisable(GL_LOGIC_OP);
798   glDisable(GL_STENCIL_TEST);
799   glDisable(GL_TEXTURE_1D);
800   glDisable(GL_TEXTURE_2D);
801   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
802   glPixelTransferi(GL_RED_SCALE, 1);
803   glPixelTransferi(GL_RED_BIAS, 0);
804   glPixelTransferi(GL_GREEN_SCALE, 1);
805   glPixelTransferi(GL_GREEN_BIAS, 0);
806   glPixelTransferi(GL_BLUE_SCALE, 1);
807   glPixelTransferi(GL_BLUE_BIAS, 0);
808   glPixelTransferi(GL_ALPHA_SCALE, 1);
809   glPixelTransferi(GL_ALPHA_BIAS, 0);
810
811   /*
812   * Disable extensions that could slow down glDrawPixels.
813   * (Actually, you should check for the presence of the proper
814   * extension before making these calls.  I've omitted that
815   * code for simplicity.)
816   */
817
818   if ((myGlContext->myGlVerMajor >= 1) && (myGlContext->myGlVerMinor >= 2))
819   {
820 #ifdef GL_EXT_convolution
821     if (myGlContext->CheckExtension ("GL_CONVOLUTION_1D_EXT"))
822       glDisable(GL_CONVOLUTION_1D_EXT);
823
824     if (myGlContext->CheckExtension ("GL_CONVOLUTION_2D_EXT"))
825       glDisable(GL_CONVOLUTION_2D_EXT);
826
827     if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT"))
828       glDisable(GL_SEPARABLE_2D_EXT);
829 #endif
830
831 #ifdef GL_EXT_histogram
832     if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT"))
833       glDisable(GL_HISTOGRAM_EXT);
834
835     if (myGlContext->CheckExtension ("GL_MINMAX_EXT"))
836       glDisable(GL_MINMAX_EXT);
837 #endif
838
839 #ifdef GL_EXT_texture3D
840     if (myGlContext->CheckExtension ("GL_TEXTURE_3D_EXT"))
841       glDisable(GL_TEXTURE_3D_EXT);
842 #endif
843   }
844 }
845
846 // =======================================================================
847 // function : MakeFrontBufCurrent
848 // purpose  : TelMakeFrontBufCurrent
849 // =======================================================================
850 void OpenGl_Window::MakeFrontBufCurrent() const
851 {
852   glDrawBuffer (GL_FRONT);
853 }
854
855 // =======================================================================
856 // function : MakeBackBufCurrent
857 // purpose  : TelMakeBackBufCurrent
858 // =======================================================================
859 void OpenGl_Window::MakeBackBufCurrent() const
860 {
861   glDrawBuffer (GL_BACK);
862 }
863
864 // =======================================================================
865 // function : MakeFrontAndBackBufCurrent
866 // purpose  : TelMakeFrontAndBackBufCurrent
867 // =======================================================================
868 void OpenGl_Window::MakeFrontAndBackBufCurrent() const
869 {
870   glDrawBuffer (GL_FRONT_AND_BACK);
871 }
872
873 // =======================================================================
874 // function : GetGContext
875 // purpose  :
876 // =======================================================================
877 GLCONTEXT OpenGl_Window::GetGContext() const
878 {
879   return (GLCONTEXT )myGlContext->myGContext;
880 }