0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / OpenGl / OpenGl_Window.cxx
CommitLineData
b311480e 1// Created on: 2011-09-20
2// Created by: Sergey ZERCHANINOV
973c2be1 3// Copyright (c) 2011-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
b5ac8292 16#include <OpenGl_GlCore12.hxx>
2166f0fa 17
2166f0fa 18#include <OpenGl_Context.hxx>
25b97fac 19#include <OpenGl_GraphicDriver.hxx>
c827ea3a 20#include <OpenGl_Window.hxx>
39235bed 21#include <OpenGl_FrameBuffer.hxx>
2166f0fa
SK
22
23#include <Aspect_GraphicDeviceDefinitionError.hxx>
825aa485 24#include <Graphic3d_TransformUtils.hxx>
2166f0fa 25#include <TCollection_AsciiString.hxx>
b5ac8292 26#include <TCollection_ExtendedString.hxx>
c04c30b3 27#include <Graphic3d_GraphicDriver.hxx>
2166f0fa 28
2f690078 29#include <memory>
30
f4a7308f 31#include <Standard_WarningDisableFunctionCast.hxx>
32
25e59720 33IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient)
92efcf78 34
1ce0716b 35#if defined(HAVE_EGL)
25b97fac 36 #include <EGL/egl.h>
37#endif
38
2166f0fa 39
4fe56619 40#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
41
2166f0fa
SK
42namespace
43{
2166f0fa 44
1ce0716b 45#if defined(HAVE_EGL)
25b97fac 46 //
47#elif defined(_WIN32)
58655684 48
abe46077 49 // WGL_ARB_pixel_format
50#ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
51 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
52 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
53 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
54 #define WGL_ACCELERATION_ARB 0x2003
55 #define WGL_NEED_PALETTE_ARB 0x2004
56 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
57 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
58 #define WGL_SWAP_METHOD_ARB 0x2007
59 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
60 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
61 #define WGL_TRANSPARENT_ARB 0x200A
62 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
63 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
64 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
65 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
66 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
67 #define WGL_SHARE_DEPTH_ARB 0x200C
68 #define WGL_SHARE_STENCIL_ARB 0x200D
69 #define WGL_SHARE_ACCUM_ARB 0x200E
70 #define WGL_SUPPORT_GDI_ARB 0x200F
71 #define WGL_SUPPORT_OPENGL_ARB 0x2010
72 #define WGL_DOUBLE_BUFFER_ARB 0x2011
73 #define WGL_STEREO_ARB 0x2012
74 #define WGL_PIXEL_TYPE_ARB 0x2013
75 #define WGL_COLOR_BITS_ARB 0x2014
76 #define WGL_RED_BITS_ARB 0x2015
77 #define WGL_RED_SHIFT_ARB 0x2016
78 #define WGL_GREEN_BITS_ARB 0x2017
79 #define WGL_GREEN_SHIFT_ARB 0x2018
80 #define WGL_BLUE_BITS_ARB 0x2019
81 #define WGL_BLUE_SHIFT_ARB 0x201A
82 #define WGL_ALPHA_BITS_ARB 0x201B
83 #define WGL_ALPHA_SHIFT_ARB 0x201C
84 #define WGL_ACCUM_BITS_ARB 0x201D
85 #define WGL_ACCUM_RED_BITS_ARB 0x201E
86 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
87 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
88 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
89 #define WGL_DEPTH_BITS_ARB 0x2022
90 #define WGL_STENCIL_BITS_ARB 0x2023
91 #define WGL_AUX_BUFFERS_ARB 0x2024
92
93 #define WGL_NO_ACCELERATION_ARB 0x2025
94 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
95 #define WGL_FULL_ACCELERATION_ARB 0x2027
96
97 #define WGL_SWAP_EXCHANGE_ARB 0x2028
98 #define WGL_SWAP_COPY_ARB 0x2029
99 #define WGL_SWAP_UNDEFINED_ARB 0x202A
100
101 #define WGL_TYPE_RGBA_ARB 0x202B
102 #define WGL_TYPE_COLORINDEX_ARB 0x202C
103#endif // WGL_NUMBER_PIXEL_FORMATS_ARB
104
58655684 105 // WGL_ARB_create_context_profile
106#ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
107 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
108 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
109 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
110 #define WGL_CONTEXT_FLAGS_ARB 0x2094
111 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
112
113 // WGL_CONTEXT_FLAGS bits
114 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
115 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
116
117 // WGL_CONTEXT_PROFILE_MASK_ARB bits
118 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
119 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
120#endif // WGL_CONTEXT_MAJOR_VERSION_ARB
121
122 static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
123 {
124 return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
125 }
2166f0fa 126#else
b6bf4ec1 127
128 // GLX_ARB_create_context
129#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
130 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
131 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
132 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
133 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
134 #define GLX_CONTEXT_FLAGS_ARB 0x2094
135
136 // GLX_ARB_create_context_profile
137 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
138 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
139 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
140#endif
141
142 //! Dummy XError handler which just skips errors
143 static int xErrorDummyHandler (Display* /*theDisplay*/,
144 XErrorEvent* /*theErrorEvent*/)
145 {
146 return 0;
147 }
148
149 //! Auxiliary method to format list.
150 static void addMsgToList (TCollection_ExtendedString& theList,
151 const TCollection_ExtendedString& theMsg)
2166f0fa 152 {
b6bf4ec1 153 if (!theList.IsEmpty())
154 {
155 theList += ", ";
156 }
157 theList += theMsg;
2166f0fa
SK
158 }
159#endif
160
5640d653 161}
2166f0fa
SK
162
163// =======================================================================
164// function : OpenGl_Window
165// purpose :
166// =======================================================================
25b97fac 167OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
c357e426 168 const Handle(Aspect_Window)& thePlatformWindow,
5e27df78 169 Aspect_RenderingContext theGContext,
58655684 170 const Handle(OpenGl_Caps)& theCaps,
5e27df78 171 const Handle(OpenGl_Context)& theShareCtx)
73192b37 172: myGlContext (new OpenGl_Context (theCaps)),
2166f0fa 173 myOwnGContext (theGContext == 0),
c357e426 174 myPlatformWindow (thePlatformWindow),
f978241f 175 mySwapInterval (theCaps->swapInterval)
2166f0fa 176{
c357e426 177 myPlatformWindow->Size (myWidth, myHeight);
2166f0fa 178
4e1523ef 179 Standard_Boolean isCoreProfile = Standard_False;
180
1ce0716b 181#if defined(HAVE_EGL)
25b97fac 182 EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
183 EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
184 EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
185 if (anEglDisplay == EGL_NO_DISPLAY
186 || anEglContext == EGL_NO_CONTEXT
39235bed 187 || (anEglConfig == NULL
188 && (EGLContext )theGContext == EGL_NO_CONTEXT))
25b97fac 189 {
9775fa61 190 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
25b97fac 191 return;
192 }
193
194 EGLSurface anEglSurf = EGL_NO_SURFACE;
39235bed 195 if ((EGLContext )theGContext == EGL_NO_CONTEXT)
25b97fac 196 {
ba00aab7 197 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
198 //const int aSurfAttribs[] =
199 //{
200 // EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
201 // EGL_NONE,
202 //};
203
25b97fac 204 // create new surface
c357e426 205 anEglSurf = eglCreateWindowSurface (anEglDisplay,
206 anEglConfig,
207 (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
208 NULL);
25b97fac 209 if (anEglSurf == EGL_NO_SURFACE)
210 {
9775fa61 211 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
25b97fac 212 return;
213 }
214 }
215 else if (theGContext != anEglContext)
216 {
9775fa61 217 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
25b97fac 218 return;
219 }
220 else
221 {
222 anEglSurf = eglGetCurrentSurface(EGL_DRAW);
223 if (anEglSurf == EGL_NO_SURFACE)
224 {
39235bed 225 // window-less EGL context (off-screen)
226 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
227 if (anEglConfig != NULL)
228 {
565baee6 229 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
39235bed 230 const int aSurfAttribs[] =
231 {
232 EGL_WIDTH, myWidth,
233 EGL_HEIGHT, myHeight,
ba00aab7 234 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
235 //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
39235bed 236 EGL_NONE
237 };
238 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
239 if (anEglSurf == EGL_NO_SURFACE)
240 {
241 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
242 }
565baee6 243 #endif
39235bed 244 }
245 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
246 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
25b97fac 247 }
248 }
249
4e1523ef 250 myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
25b97fac 251#elif defined(_WIN32)
252 (void )theDriver;
c357e426 253 HWND aWindow = (HWND )myPlatformWindow->NativeHandle();
5e27df78 254 HDC aWindowDC = GetDC (aWindow);
255 HGLRC aGContext = (HGLRC )theGContext;
256
3d8969b1 257 PIXELFORMATDESCRIPTOR aPixelFrmt;
abe46077 258 memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
259 aPixelFrmt.nSize = sizeof(PIXELFORMATDESCRIPTOR);
260 aPixelFrmt.nVersion = 1;
261 aPixelFrmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
262 aPixelFrmt.iPixelType = PFD_TYPE_RGBA;
263 aPixelFrmt.cColorBits = 24;
264 aPixelFrmt.cDepthBits = 24;
265 aPixelFrmt.cStencilBits = 8;
266 aPixelFrmt.iLayerType = PFD_MAIN_PLANE;
267 if (theCaps->contextStereo)
268 {
269 aPixelFrmt.dwFlags |= PFD_STEREO;
270 }
271
272 int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
b5ac8292 273
274 // in case of failure try without stereo if any
4e1523ef 275 const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
b5ac8292 276 if (aPixelFrmtId == 0 && theCaps->contextStereo)
277 {
278 TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
279 "ChoosePixelFormat is unable to find stereo supported pixel format. "
280 "Choosing similar non stereo format.");
3b523c4c 281 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
282 GL_DEBUG_TYPE_OTHER,
283 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
b5ac8292 284
285 aPixelFrmt.dwFlags &= ~PFD_STEREO;
286 aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
287 }
288
3d8969b1 289 if (aPixelFrmtId == 0)
5e27df78 290 {
291 ReleaseDC (aWindow, aWindowDC);
292
293 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
294 aMsg += (int )GetLastError();
9775fa61 295 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
5e27df78 296 return;
297 }
298
abe46077 299 DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
5e27df78 300
58655684 301 HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
5e27df78 302 if (aGContext == NULL)
303 {
58655684 304 // create temporary context to retrieve advanced context creation procedures
305 HMODULE aModule = GetModuleHandleW(NULL);
306 WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
307 aClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
308 aClass.lpfnWndProc = wndProcDummy;
309 aClass.hInstance = aModule;
310 aClass.lpszClassName = L"OpenGl_WindowTmp";
311 HWND aWinTmp = NULL;
312 HDC aDevCtxTmp = NULL;
313 HGLRC aRendCtxTmp = NULL;
4e1523ef 314 if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
58655684 315 || RegisterClassW (&aClass) == 0)
316 {
317 aClass.lpszClassName = NULL;
318 }
319 if (aClass.lpszClassName != NULL)
320 {
229c0b6a 321 DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
322 #if (_WIN32_WINNT >= 0x0500)
323 anExStyle |= WS_EX_NOACTIVATE;
324 #endif
325 aWinTmp = CreateWindowExW(anExStyle,
58655684 326 aClass.lpszClassName, L"OpenGl_WindowTmp",
327 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
328 2, 2, 4, 4,
329 NULL, NULL, aModule, NULL);
330 }
331 if (aWinTmp != NULL)
332 {
333 aDevCtxTmp = GetDC (aWinTmp);
334 SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
335 aRendCtxTmp = wglCreateContext (aDevCtxTmp);
336 }
abe46077 337
338 typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx,
339 const int* theIntAttribs,
340 const float* theFloatAttribs,
341 unsigned int theMaxFormats,
342 int* theFormatsOut,
343 unsigned int* theNumFormatsOut);
344 typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx,
345 HGLRC theShareContext,
346 const int* theAttribs);
347 wglChoosePixelFormatARB_t aChoosePixProc = NULL;
348 wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
58655684 349 if (aRendCtxTmp != NULL)
350 {
351 wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
352
353 typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
abe46077 354 wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB");
355 const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
356 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
357 {
358 aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
359 }
360 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
361 {
362 aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
363 }
364 }
365
366 // choose extended pixel format
367 if (aChoosePixProc != NULL)
368 {
369 const int aPixAttribs[] =
370 {
371 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
372 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
373 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
4e1523ef 374 WGL_STEREO_ARB, hasStereo ? GL_TRUE : GL_FALSE,
abe46077 375 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
376 //WGL_SAMPLE_BUFFERS_ARB, 1,
377 //WGL_SAMPLES_ARB, 8,
378 WGL_COLOR_BITS_ARB, 24,
379 WGL_DEPTH_BITS_ARB, 24,
380 WGL_STENCIL_BITS_ARB, 8,
ba00aab7 381 // WGL_EXT_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
382 //WGL_COLORSPACE_EXT, !theCaps->sRGBDisable ? WGL_COLORSPACE_SRGB_EXT : WGL_COLORSPACE_LINEAR_EXT,
383 // requires WGL_ARB_framebuffer_sRGB or WGL_EXT_framebuffer_sRGB extensions
384 //WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, !theCaps->sRGBDisable ? GL_TRUE : GL_FALSE,
abe46077 385 WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
386 0, 0,
387 };
388 unsigned int aFrmtsNb = 0;
389 aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
390 }
391
392 // setup pixel format - may be set only once per window
393 if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
394 {
395 ReleaseDC (aWindow, aWindowDC);
396
397 TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
398 aMsg += (int )GetLastError();
9775fa61 399 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
abe46077 400 return;
401 }
402
403 // create GL context with extra options
404 if (aCreateCtxProc != NULL)
405 {
4e1523ef 406 if (!theCaps->contextCompatible)
abe46077 407 {
4e1523ef 408 int aCoreCtxAttribs[] =
409 {
410 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
411 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
412 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
413 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
414 0, 0
415 };
416
417 // Try to create the core profile of highest OpenGL version supported by OCCT
418 // (this will be done automatically by some drivers when requesting 3.2,
419 // but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations).
420 for (int aLowVer4 = 5; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
421 {
422 aCoreCtxAttribs[1] = 4;
423 aCoreCtxAttribs[3] = aLowVer4;
424 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
425 }
426 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
427 {
428 aCoreCtxAttribs[1] = 3;
429 aCoreCtxAttribs[3] = aLowVer3;
430 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
431 }
432 isCoreProfile = aGContext != NULL;
433 }
434
435 if (aGContext == NULL)
436 {
437 int aCtxAttribs[] =
438 {
439 // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
440 // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
441 //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
442 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
443 0, 0
444 };
445 isCoreProfile = Standard_False;
446 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
447
448 if (aGContext != NULL
449 && !theCaps->contextCompatible)
450 {
451 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
3b523c4c 452 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
4e1523ef 453 }
454 }
abe46077 455
abe46077 456 if (aGContext != NULL)
58655684 457 {
abe46077 458 aSlaveCtx = NULL;
58655684 459 }
460 }
461
462 if (aRendCtxTmp != NULL)
463 {
464 wglDeleteContext (aRendCtxTmp);
465 }
466 if (aDevCtxTmp != NULL)
467 {
468 ReleaseDC (aWinTmp, aDevCtxTmp);
469 }
470 if (aWinTmp != NULL)
471 {
472 DestroyWindow (aWinTmp);
473 }
474 if (aClass.lpszClassName != NULL)
475 {
476 UnregisterClassW (aClass.lpszClassName, aModule);
477 }
478
479 if (aGContext == NULL)
480 {
abe46077 481 // create context using obsolete functionality
58655684 482 aGContext = wglCreateContext (aWindowDC);
483 }
5e27df78 484 if (aGContext == NULL)
485 {
486 ReleaseDC (aWindow, aWindowDC);
487
488 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
489 aMsg += (int )GetLastError();
9775fa61 490 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
5e27df78 491 return;
492 }
493 }
494
495 // all GL context within one OpenGl_GraphicDriver should be shared!
58655684 496 if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
5e27df78 497 {
498 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
499 aMsg += (int )GetLastError();
9775fa61 500 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
5e27df78 501 return;
502 }
503
4e1523ef 504 myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
5e27df78 505#else
b6bf4ec1 506 Window aWindow = (Window )myPlatformWindow->NativeHandle();
25b97fac 507 Display* aDisp = theDriver->GetDisplayConnection()->GetDisplay();
5e27df78 508 GLXContext aGContext = (GLXContext )theGContext;
b6bf4ec1 509 GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
510
511 XWindowAttributes aWinAttribs;
512 XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
513 XVisualInfo aVisInfo;
514 aVisInfo.visualid = aWinAttribs.visual->visualid;
515 aVisInfo.screen = DefaultScreen (aDisp);
516 int aNbItems;
2f690078 517 std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
b6bf4ec1 518 int isGl = 0;
2f690078 519 if (aVis.get() == NULL)
2166f0fa 520 {
9775fa61 521 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
b6bf4ec1 522 return;
2166f0fa 523 }
2f690078 524 else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
2166f0fa 525 {
9775fa61 526 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
b6bf4ec1 527 return;
528 }
3d8969b1 529
b6bf4ec1 530 // create new context
531 GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
532 const char* aGlxExts = glXQueryExtensionsString (aDisp, aVisInfo.screen);
533 if (myOwnGContext
534 && anFBConfig != NULL
535 && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
536 {
537 // Replace default XError handler to ignore errors.
538 // Warning - this is global for all threads!
539 typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
540 xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);
541
542 typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
543 GLXContext share_context, Bool direct,
544 const int* attrib_list);
545 glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
546 if (!theCaps->contextCompatible)
95db72f1 547 {
b6bf4ec1 548 int aCoreCtxAttribs[] =
95db72f1 549 {
b6bf4ec1 550 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
551 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
552 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
553 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
554 0, 0
555 };
556
557 // try to create the core profile of highest OpenGL version supported by OCCT
558 for (int aLowVer4 = 5; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
2166f0fa 559 {
b6bf4ec1 560 aCoreCtxAttribs[1] = 4;
561 aCoreCtxAttribs[3] = aLowVer4;
562 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
2166f0fa 563 }
b6bf4ec1 564 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
95db72f1 565 {
b6bf4ec1 566 aCoreCtxAttribs[1] = 3;
567 aCoreCtxAttribs[3] = aLowVer3;
568 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
95db72f1 569 }
b6bf4ec1 570 isCoreProfile = aGContext != NULL;
2166f0fa 571 }
2166f0fa 572
b6bf4ec1 573 if (aGContext == NULL)
2166f0fa 574 {
b6bf4ec1 575 int aCtxAttribs[] =
b5ac8292 576 {
b6bf4ec1 577 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
578 0, 0
579 };
580 isCoreProfile = Standard_False;
581 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
b5ac8292 582
b6bf4ec1 583 if (aGContext != NULL
584 && !theCaps->contextCompatible)
95db72f1 585 {
b6bf4ec1 586 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
3b523c4c 587 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
95db72f1 588 }
2166f0fa 589 }
b6bf4ec1 590 XSetErrorHandler(anOldHandler);
591 }
2166f0fa 592
b6bf4ec1 593 if (myOwnGContext
594 && aGContext == NULL)
595 {
2f690078 596 aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
b6bf4ec1 597 if (aGContext == NULL)
2166f0fa 598 {
9775fa61 599 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
2166f0fa
SK
600 return;
601 }
b6bf4ec1 602 }
2166f0fa 603
b6bf4ec1 604 // check Visual for OpenGl context's parameters compatibility
605 TCollection_ExtendedString aList;
606 int isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
607 int aDepthSize = 0, aStencilSize = 0;
2f690078 608 glXGetConfig (aDisp, aVis.get(), GLX_RGBA, &isRGBA);
609 glXGetConfig (aDisp, aVis.get(), GLX_DOUBLEBUFFER, &isDoubleBuffer);
610 glXGetConfig (aDisp, aVis.get(), GLX_STEREO, &isStereo);
611 glXGetConfig (aDisp, aVis.get(), GLX_DEPTH_SIZE, &aDepthSize);
612 glXGetConfig (aDisp, aVis.get(), GLX_STENCIL_SIZE, &aStencilSize);
b6bf4ec1 613 if (aDepthSize < 1) addMsgToList (aList, "no depth buffer");
614 if (aStencilSize < 1) addMsgToList (aList, "no stencil buffer");
615 if (isRGBA == 0) addMsgToList (aList, "no RGBA color buffer");
616 if (isDoubleBuffer == 0) addMsgToList (aList, "no Double Buffer");
617 if (theCaps->contextStereo && isStereo == 0)
618 {
619 addMsgToList (aList, "no Quad Buffer");
620 }
621 else if (!theCaps->contextStereo && isStereo == 1)
622 {
623 addMsgToList (aList, "extra Quad Buffer");
624 }
625 if (!aList.IsEmpty())
626 {
627 TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
3b523c4c 628 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
629 GL_DEBUG_TYPE_OTHER,
630 0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
2166f0fa
SK
631 }
632
4e1523ef 633 myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
2166f0fa 634#endif
5e27df78 635 myGlContext->Share (theShareCtx);
f978241f 636 myGlContext->SetSwapInterval (mySwapInterval);
2166f0fa 637 Init();
2166f0fa
SK
638}
639
640// =======================================================================
641// function : ~OpenGl_Window
642// purpose :
643// =======================================================================
644OpenGl_Window::~OpenGl_Window()
645{
25b97fac 646 if (!myOwnGContext
647 || myGlContext.IsNull())
fd4a6963 648 {
649 myGlContext.Nullify();
650 return;
651 }
652
653 // release "GL" context if it is owned by window
544da5a4 654 // Mesa implementation can fail to destroy GL context if it set for current thread.
655 // It should be safer to unset thread GL context before its destruction.
1ce0716b 656#if defined(HAVE_EGL)
25b97fac 657 if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
658 {
659 eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
660 (EGLSurface )myGlContext->myWindow);
661 }
662#elif defined(_WIN32)
fd4a6963 663 HWND aWindow = (HWND )myGlContext->myWindow;
664 HDC aWindowDC = (HDC )myGlContext->myWindowDC;
665 HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext;
544da5a4 666 HGLRC aThreadGContext = wglGetCurrentContext();
5e27df78 667 myGlContext.Nullify();
2166f0fa 668
544da5a4 669 if (aThreadGContext != NULL)
2166f0fa 670 {
544da5a4 671 if (aThreadGContext == aWindowGContext)
2166f0fa 672 {
fd4a6963 673 wglMakeCurrent (NULL, NULL);
2166f0fa 674 }
fd4a6963 675
676 wglDeleteContext (aWindowGContext);
2166f0fa 677 }
fd4a6963 678 ReleaseDC (aWindow, aWindowDC);
5e27df78 679#else
544da5a4 680 Display* aDisplay = (Display* )myGlContext->myDisplay;
681 GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext;
682 GLXContext aThreadGContext = glXGetCurrentContext();
5e27df78 683 myGlContext.Nullify();
684
fd4a6963 685 if (aDisplay != NULL)
2166f0fa 686 {
544da5a4 687 if (aThreadGContext == aWindowGContext)
688 {
689 glXMakeCurrent (aDisplay, None, NULL);
690 }
691
5e27df78 692 // FSXXX sync necessary if non-direct rendering
693 glXWaitGL();
544da5a4 694 glXDestroyContext (aDisplay, aWindowGContext);
2166f0fa
SK
695 }
696#endif
697}
698
4fe56619 699#endif // !__APPLE__
700
2166f0fa
SK
701// =======================================================================
702// function : Activate
703// purpose :
704// =======================================================================
705Standard_Boolean OpenGl_Window::Activate()
706{
86fa64d9 707 return myGlContext->MakeCurrent();
2166f0fa
SK
708}
709
4fe56619 710#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
711
2166f0fa
SK
712// =======================================================================
713// function : Resize
714// purpose : call_subr_resize
715// =======================================================================
c357e426 716void OpenGl_Window::Resize()
2166f0fa 717{
1ce0716b 718#if !defined(_WIN32) && !defined(HAVE_EGL)
73192b37 719 Display* aDisp = (Display* )myGlContext->myDisplay;
2166f0fa
SK
720 if (aDisp == NULL)
721 return;
73192b37 722#endif
2166f0fa 723
c357e426 724 Standard_Integer aWidth = 0;
725 Standard_Integer aHeight = 0;
726 myPlatformWindow->Size (aWidth, aHeight);
727
2166f0fa 728 // If the size is not changed - do nothing
c357e426 729 if ((myWidth == aWidth) && (myHeight == aHeight))
2166f0fa
SK
730 return;
731
c357e426 732 myWidth = aWidth;
733 myHeight = aHeight;
2166f0fa 734
1ce0716b 735#if !defined(_WIN32) && !defined(HAVE_EGL)
5e27df78 736 XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
2166f0fa
SK
737 XSync (aDisp, False);
738#endif
739
740 Init();
741}
742
2166f0fa
SK
743// =======================================================================
744// function : Init
745// purpose :
746// =======================================================================
747void OpenGl_Window::Init()
748{
749 if (!Activate())
750 return;
751
1ce0716b 752#if defined(HAVE_EGL)
39235bed 753 if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
754 {
755 // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
756 // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
757 // for offscreen rendering on bugged OpenGL ES drivers
758 Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
759 if (!aDefFbo.IsNull())
760 {
761 aDefFbo->Release (myGlContext.operator->());
762 }
763 else
764 {
765 aDefFbo = new OpenGl_FrameBuffer();
766 }
767
768 if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
769 {
770 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
771 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
772 }
773 myGlContext->SetDefaultFrameBuffer (aDefFbo);
774 aDefFbo->BindBuffer (myGlContext);
775 }
776 else if (!myPlatformWindow->IsVirtual())
6cde53c4 777 {
778 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
779 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
780 }
25b97fac 781#elif defined(_WIN32)
62e1beed 782 //
2166f0fa
SK
783#else
784 Window aRootWin;
785 int aDummy;
786 unsigned int aDummyU;
787 unsigned int aNewWidth = 0;
788 unsigned int aNewHeight = 0;
73192b37 789 Display* aDisp = (Display* )myGlContext->myDisplay;
5e27df78 790 XGetGeometry (aDisp, myGlContext->myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU);
2166f0fa
SK
791 myWidth = aNewWidth;
792 myHeight = aNewHeight;
793#endif
794
5bd9ed93 795 glDisable (GL_DITHER);
ca3c13d1 796 glDisable (GL_SCISSOR_TEST);
3bffef55 797 const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
798 myGlContext->ResizeViewport (aViewport);
ca3c13d1 799#if !defined(GL_ES_VERSION_2_0)
3bffef55 800 myGlContext->SetDrawBuffer (GL_BACK);
4e1523ef 801 if (myGlContext->core11 != NULL)
802 {
803 glMatrixMode (GL_MODELVIEW);
804 }
ca3c13d1 805#endif
2166f0fa
SK
806}
807
2166f0fa 808// =======================================================================
c357e426 809// function : SetSwapInterval
2166f0fa
SK
810// purpose :
811// =======================================================================
b40cdc2b 812void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
2166f0fa 813{
b40cdc2b 814 const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
815 if (mySwapInterval != aSwapInterval)
b5ac8292 816 {
b40cdc2b 817 mySwapInterval = aSwapInterval;
c357e426 818 myGlContext->SetSwapInterval (mySwapInterval);
b5ac8292 819 }
2166f0fa 820}
c357e426 821
822#endif // !__APPLE__