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