0024747: TKOpenGl - Mesa fails to destroy context if it set to current thread
[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 under
8 // the terms of the GNU Lesser General Public License 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   // Mesa implementation can fail to destroy GL context if it set for current thread.
596   // It should be safer to unset thread GL context before its destruction.
597 #if defined(_WIN32)
598   HWND  aWindow          = (HWND  )myGlContext->myWindow;
599   HDC   aWindowDC        = (HDC   )myGlContext->myWindowDC;
600   HGLRC aWindowGContext  = (HGLRC )myGlContext->myGContext;
601   HGLRC aThreadGContext  = wglGetCurrentContext();
602   myGlContext.Nullify();
603
604   if (aThreadGContext != NULL)
605   {
606     if (aThreadGContext == aWindowGContext)
607     {
608       wglMakeCurrent (NULL, NULL);
609     }
610
611     wglDeleteContext (aWindowGContext);
612   }
613   ReleaseDC (aWindow, aWindowDC);
614 #else
615   Display*    aDisplay        = (Display*    )myGlContext->myDisplay;
616   GLXContext  aWindowGContext = (GLXContext  )myGlContext->myGContext;
617   GLXContext  aThreadGContext = glXGetCurrentContext();
618   myGlContext.Nullify();
619
620   if (aDisplay != NULL)
621   {
622     if (aThreadGContext == aWindowGContext)
623     {
624       glXMakeCurrent (aDisplay, None, NULL);
625     }
626
627     // FSXXX sync necessary if non-direct rendering
628     glXWaitGL();
629     glXDestroyContext (aDisplay, aWindowGContext);
630   }
631 #endif
632 }
633
634 #endif // !__APPLE__
635
636 // =======================================================================
637 // function : Activate
638 // purpose  :
639 // =======================================================================
640 Standard_Boolean OpenGl_Window::Activate()
641 {
642   return myGlContext->MakeCurrent();
643 }
644
645 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
646
647 // =======================================================================
648 // function : Resize
649 // purpose  : call_subr_resize
650 // =======================================================================
651 void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow)
652 {
653   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
654   if (aDisp == NULL)
655     return;
656
657   // If the size is not changed - do nothing
658   if ((myWidth == theCWindow.dx) && (myHeight == theCWindow.dy))
659     return;
660
661   myWidth  = (Standard_Integer )theCWindow.dx;
662   myHeight = (Standard_Integer )theCWindow.dy;
663
664 #if !defined(_WIN32)
665   XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
666   XSync (aDisp, False);
667 #endif
668
669   Init();
670 }
671
672 #endif // !__APPLE__
673
674 // =======================================================================
675 // function : ReadDepths
676 // purpose  : TelReadDepths
677 // =======================================================================
678 void OpenGl_Window::ReadDepths (const Standard_Integer theX,     const Standard_Integer theY,
679                                 const Standard_Integer theWidth, const Standard_Integer theHeight,
680                                 float* theDepths)
681 {
682   if (theDepths == NULL || !Activate())
683     return;
684
685   glMatrixMode (GL_PROJECTION);
686   glLoadIdentity();
687   gluOrtho2D (0.0, (GLdouble )myWidth, 0.0, (GLdouble )myHeight);
688   glMatrixMode (GL_MODELVIEW);
689   glLoadIdentity();
690
691   glRasterPos2i (theX, theY);
692   DisableFeatures();
693   glReadPixels (theX, theY, theWidth, theHeight, GL_DEPTH_COMPONENT, GL_FLOAT, theDepths);
694   EnableFeatures();
695 }
696
697 // =======================================================================
698 // function : SetBackgroundColor
699 // purpose  : call_subr_set_background
700 // =======================================================================
701 void OpenGl_Window::SetBackgroundColor (const Standard_ShortReal theR,
702                                         const Standard_ShortReal theG,
703                                         const Standard_ShortReal theB)
704 {
705   myBgColor.rgb[0] = theR;
706   myBgColor.rgb[1] = theG;
707   myBgColor.rgb[2] = theB;
708 }
709
710 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
711
712 // =======================================================================
713 // function : Init
714 // purpose  :
715 // =======================================================================
716 void OpenGl_Window::Init()
717 {
718   if (!Activate())
719     return;
720
721 #if defined(_WIN32)
722   RECT cr;
723   GetClientRect ((HWND )myGlContext->myWindow, &cr);
724   myWidth  = cr.right - cr.left;
725   myHeight = cr.bottom - cr.top;
726 #else
727   Window aRootWin;
728   int aDummy;
729   unsigned int aDummyU;
730   unsigned int aNewWidth  = 0;
731   unsigned int aNewHeight = 0;
732   DISPLAY* aDisp = (DISPLAY* )myDisplay->GetDisplay();
733   XGetGeometry (aDisp, myGlContext->myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU);
734   myWidth  = aNewWidth;
735   myHeight = aNewHeight;
736 #endif
737
738   glMatrixMode (GL_MODELVIEW);
739   glViewport (0, 0, myWidth, myHeight);
740
741   glDisable (GL_SCISSOR_TEST);
742   glDrawBuffer (GL_BACK);
743 }
744
745 #endif // !__APPLE__
746
747 // =======================================================================
748 // function : EnablePolygonOffset
749 // purpose  : call_subr_enable_polygon_offset
750 // =======================================================================
751 void OpenGl_Window::EnablePolygonOffset() const
752 {
753   Standard_ShortReal aFactor, aUnits;
754   myDisplay->PolygonOffset (aFactor, aUnits);
755   glPolygonOffset (aFactor, aUnits);
756   glEnable (GL_POLYGON_OFFSET_FILL);
757 }
758
759 // =======================================================================
760 // function : DisablePolygonOffset
761 // purpose  : call_subr_disable_polygon_offset
762 // =======================================================================
763 void OpenGl_Window::DisablePolygonOffset() const
764 {
765   glDisable (GL_POLYGON_OFFSET_FILL);
766 }
767
768 // =======================================================================
769 // function : EnableFeatures
770 // purpose  :
771 // =======================================================================
772 void OpenGl_Window::EnableFeatures() const
773 {
774   /*glPixelTransferi (GL_MAP_COLOR, GL_TRUE);*/
775
776   if (myDither)
777     glEnable (GL_DITHER);
778   else
779     glDisable (GL_DITHER);
780 }
781
782 // =======================================================================
783 // function : DisableFeatures
784 // purpose  :
785 // =======================================================================
786 void OpenGl_Window::DisableFeatures() const
787 {
788   glDisable (GL_DITHER);
789   glPixelTransferi (GL_MAP_COLOR, GL_FALSE);
790
791   /*
792   * Disable stuff that's likely to slow down glDrawPixels.
793   * (Omit as much of this as possible, when you know in advance
794   * that the OpenGL state will already be set correctly.)
795   */
796   glDisable(GL_ALPHA_TEST);
797   glDisable(GL_BLEND);
798   glDisable(GL_DEPTH_TEST);
799   glDisable(GL_FOG);
800   glDisable(GL_LIGHTING);
801
802   glDisable(GL_LOGIC_OP);
803   glDisable(GL_STENCIL_TEST);
804   glDisable(GL_TEXTURE_1D);
805   glDisable(GL_TEXTURE_2D);
806   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
807   glPixelTransferi(GL_RED_SCALE, 1);
808   glPixelTransferi(GL_RED_BIAS, 0);
809   glPixelTransferi(GL_GREEN_SCALE, 1);
810   glPixelTransferi(GL_GREEN_BIAS, 0);
811   glPixelTransferi(GL_BLUE_SCALE, 1);
812   glPixelTransferi(GL_BLUE_BIAS, 0);
813   glPixelTransferi(GL_ALPHA_SCALE, 1);
814   glPixelTransferi(GL_ALPHA_BIAS, 0);
815
816   /*
817   * Disable extensions that could slow down glDrawPixels.
818   * (Actually, you should check for the presence of the proper
819   * extension before making these calls.  I've omitted that
820   * code for simplicity.)
821   */
822
823   if ((myGlContext->myGlVerMajor >= 1) && (myGlContext->myGlVerMinor >= 2))
824   {
825 #ifdef GL_EXT_convolution
826     if (myGlContext->CheckExtension ("GL_CONVOLUTION_1D_EXT"))
827       glDisable(GL_CONVOLUTION_1D_EXT);
828
829     if (myGlContext->CheckExtension ("GL_CONVOLUTION_2D_EXT"))
830       glDisable(GL_CONVOLUTION_2D_EXT);
831
832     if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT"))
833       glDisable(GL_SEPARABLE_2D_EXT);
834 #endif
835
836 #ifdef GL_EXT_histogram
837     if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT"))
838       glDisable(GL_HISTOGRAM_EXT);
839
840     if (myGlContext->CheckExtension ("GL_MINMAX_EXT"))
841       glDisable(GL_MINMAX_EXT);
842 #endif
843
844 #ifdef GL_EXT_texture3D
845     if (myGlContext->CheckExtension ("GL_TEXTURE_3D_EXT"))
846       glDisable(GL_TEXTURE_3D_EXT);
847 #endif
848   }
849 }
850
851 // =======================================================================
852 // function : MakeFrontBufCurrent
853 // purpose  : TelMakeFrontBufCurrent
854 // =======================================================================
855 void OpenGl_Window::MakeFrontBufCurrent() const
856 {
857   glDrawBuffer (GL_FRONT);
858 }
859
860 // =======================================================================
861 // function : MakeBackBufCurrent
862 // purpose  : TelMakeBackBufCurrent
863 // =======================================================================
864 void OpenGl_Window::MakeBackBufCurrent() const
865 {
866   glDrawBuffer (GL_BACK);
867 }
868
869 // =======================================================================
870 // function : GetGContext
871 // purpose  :
872 // =======================================================================
873 GLCONTEXT OpenGl_Window::GetGContext() const
874 {
875   return (GLCONTEXT )myGlContext->myGContext;
876 }