1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_GlCore12.hxx>
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_GraphicDriver.hxx>
20 #include <OpenGl_Window.hxx>
21 #include <OpenGl_FrameBuffer.hxx>
23 #include <Aspect_GraphicDeviceDefinitionError.hxx>
24 #include <Graphic3d_TransformUtils.hxx>
25 #include <TCollection_AsciiString.hxx>
26 #include <TCollection_ExtendedString.hxx>
27 #include <Graphic3d_GraphicDriver.hxx>
31 #include <Standard_WarningDisableFunctionCast.hxx>
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient)
37 #elif defined(HAVE_XLIB)
41 #if !defined(__APPLE__) || defined(HAVE_XLIB)
50 // WGL_ARB_pixel_format
51 #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
52 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
53 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
54 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
55 #define WGL_ACCELERATION_ARB 0x2003
56 #define WGL_NEED_PALETTE_ARB 0x2004
57 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
58 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
59 #define WGL_SWAP_METHOD_ARB 0x2007
60 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
61 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
62 #define WGL_TRANSPARENT_ARB 0x200A
63 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
64 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
65 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
66 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
67 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
68 #define WGL_SHARE_DEPTH_ARB 0x200C
69 #define WGL_SHARE_STENCIL_ARB 0x200D
70 #define WGL_SHARE_ACCUM_ARB 0x200E
71 #define WGL_SUPPORT_GDI_ARB 0x200F
72 #define WGL_SUPPORT_OPENGL_ARB 0x2010
73 #define WGL_DOUBLE_BUFFER_ARB 0x2011
74 #define WGL_STEREO_ARB 0x2012
75 #define WGL_PIXEL_TYPE_ARB 0x2013
76 #define WGL_COLOR_BITS_ARB 0x2014
77 #define WGL_RED_BITS_ARB 0x2015
78 #define WGL_RED_SHIFT_ARB 0x2016
79 #define WGL_GREEN_BITS_ARB 0x2017
80 #define WGL_GREEN_SHIFT_ARB 0x2018
81 #define WGL_BLUE_BITS_ARB 0x2019
82 #define WGL_BLUE_SHIFT_ARB 0x201A
83 #define WGL_ALPHA_BITS_ARB 0x201B
84 #define WGL_ALPHA_SHIFT_ARB 0x201C
85 #define WGL_ACCUM_BITS_ARB 0x201D
86 #define WGL_ACCUM_RED_BITS_ARB 0x201E
87 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
88 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
89 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
90 #define WGL_DEPTH_BITS_ARB 0x2022
91 #define WGL_STENCIL_BITS_ARB 0x2023
92 #define WGL_AUX_BUFFERS_ARB 0x2024
94 #define WGL_NO_ACCELERATION_ARB 0x2025
95 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
96 #define WGL_FULL_ACCELERATION_ARB 0x2027
98 #define WGL_SWAP_EXCHANGE_ARB 0x2028
99 #define WGL_SWAP_COPY_ARB 0x2029
100 #define WGL_SWAP_UNDEFINED_ARB 0x202A
102 #define WGL_TYPE_RGBA_ARB 0x202B
103 #define WGL_TYPE_COLORINDEX_ARB 0x202C
104 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
106 // WGL_ARB_create_context_profile
107 #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
108 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
109 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
110 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
111 #define WGL_CONTEXT_FLAGS_ARB 0x2094
112 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
114 // WGL_CONTEXT_FLAGS bits
115 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
116 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
118 // WGL_CONTEXT_PROFILE_MASK_ARB bits
119 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
120 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
121 #endif // WGL_CONTEXT_MAJOR_VERSION_ARB
123 static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
125 return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
127 #elif defined(HAVE_XLIB)
129 // GLX_ARB_create_context
130 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
131 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
132 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
133 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
134 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
135 #define GLX_CONTEXT_FLAGS_ARB 0x2094
137 // GLX_ARB_create_context_profile
138 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
139 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
140 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
143 //! Dummy XError handler which just skips errors
144 static int xErrorDummyHandler (Display* /*theDisplay*/,
145 XErrorEvent* /*theErrorEvent*/)
150 //! Auxiliary method to format list.
151 static void addMsgToList (TCollection_ExtendedString& theList,
152 const TCollection_ExtendedString& theMsg)
154 if (!theList.IsEmpty())
164 // =======================================================================
165 // function : OpenGl_Window
167 // =======================================================================
168 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
169 const Handle(Aspect_Window)& thePlatformWindow,
170 Aspect_RenderingContext theGContext,
171 const Handle(OpenGl_Caps)& theCaps,
172 const Handle(OpenGl_Context)& theShareCtx)
173 : myGlContext (new OpenGl_Context (theCaps)),
174 myOwnGContext (theGContext == 0),
175 myPlatformWindow (thePlatformWindow),
176 mySwapInterval (theCaps->swapInterval)
178 myPlatformWindow->Size (myWidth, myHeight);
180 Standard_Boolean isCoreProfile = Standard_False;
182 #if defined(HAVE_EGL)
183 EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
184 EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
185 EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
186 if (anEglDisplay == EGL_NO_DISPLAY
187 || anEglContext == EGL_NO_CONTEXT
188 || (anEglConfig == NULL
189 && (EGLContext )theGContext == EGL_NO_CONTEXT))
191 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
195 EGLSurface anEglSurf = EGL_NO_SURFACE;
196 if ((EGLContext )theGContext == EGL_NO_CONTEXT)
198 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
199 //const int aSurfAttribs[] =
201 // EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
205 // create new surface
206 anEglSurf = eglCreateWindowSurface (anEglDisplay,
208 (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
210 if (anEglSurf == EGL_NO_SURFACE
211 && myPlatformWindow->NativeHandle() != 0)
213 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
215 else if (anEglSurf == EGL_NO_SURFACE)
217 // window-less EGL context (off-screen)
218 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
219 if (anEglConfig != NULL)
221 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
222 const int aSurfAttribs[] =
225 EGL_HEIGHT, myHeight,
226 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
227 //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
230 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
231 if (anEglSurf == EGL_NO_SURFACE)
233 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
237 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
238 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
241 else if (theGContext != anEglContext)
243 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
247 anEglSurf = eglGetCurrentSurface(EGL_DRAW);
248 if (anEglSurf == EGL_NO_SURFACE)
250 // window-less EGL context (off-screen)
251 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
252 if (anEglConfig != NULL)
254 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
255 const int aSurfAttribs[] =
258 EGL_HEIGHT, myHeight,
259 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
260 //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
263 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
264 if (anEglSurf == EGL_NO_SURFACE)
266 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
270 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
271 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
275 myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
276 #elif defined(_WIN32)
278 HWND aWindow = (HWND )myPlatformWindow->NativeHandle();
279 HDC aWindowDC = GetDC (aWindow);
280 HGLRC aGContext = (HGLRC )theGContext;
282 PIXELFORMATDESCRIPTOR aPixelFrmt;
283 memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
284 aPixelFrmt.nSize = sizeof(PIXELFORMATDESCRIPTOR);
285 aPixelFrmt.nVersion = 1;
286 aPixelFrmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
287 aPixelFrmt.iPixelType = PFD_TYPE_RGBA;
288 aPixelFrmt.cColorBits = 24;
289 aPixelFrmt.cDepthBits = 24;
290 aPixelFrmt.cStencilBits = 8;
291 aPixelFrmt.iLayerType = PFD_MAIN_PLANE;
292 if (theCaps->contextStereo)
294 aPixelFrmt.dwFlags |= PFD_STEREO;
297 int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
299 // in case of failure try without stereo if any
300 const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
301 if (aPixelFrmtId == 0 && theCaps->contextStereo)
303 TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
304 "ChoosePixelFormat is unable to find stereo supported pixel format. "
305 "Choosing similar non stereo format.");
306 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
308 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
310 aPixelFrmt.dwFlags &= ~PFD_STEREO;
311 aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
314 if (aPixelFrmtId == 0)
316 ReleaseDC (aWindow, aWindowDC);
318 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
319 aMsg += (int )GetLastError();
320 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
324 DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
326 HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
327 if (aGContext == NULL)
329 // create temporary context to retrieve advanced context creation procedures
330 HMODULE aModule = GetModuleHandleW(NULL);
331 WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
332 aClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
333 aClass.lpfnWndProc = wndProcDummy;
334 aClass.hInstance = aModule;
335 aClass.lpszClassName = L"OpenGl_WindowTmp";
337 HDC aDevCtxTmp = NULL;
338 HGLRC aRendCtxTmp = NULL;
339 if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
340 || RegisterClassW (&aClass) == 0)
342 aClass.lpszClassName = NULL;
344 if (aClass.lpszClassName != NULL)
346 DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
347 #if (_WIN32_WINNT >= 0x0500)
348 anExStyle |= WS_EX_NOACTIVATE;
350 aWinTmp = CreateWindowExW(anExStyle,
351 aClass.lpszClassName, L"OpenGl_WindowTmp",
352 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
354 NULL, NULL, aModule, NULL);
358 aDevCtxTmp = GetDC (aWinTmp);
359 SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
360 aRendCtxTmp = wglCreateContext (aDevCtxTmp);
363 typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx,
364 const int* theIntAttribs,
365 const float* theFloatAttribs,
366 unsigned int theMaxFormats,
368 unsigned int* theNumFormatsOut);
369 typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx,
370 HGLRC theShareContext,
371 const int* theAttribs);
372 wglChoosePixelFormatARB_t aChoosePixProc = NULL;
373 wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
374 if (aRendCtxTmp != NULL)
376 wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
378 typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
379 wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB");
380 const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
381 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
383 aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
385 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
387 aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
391 // choose extended pixel format
392 if (aChoosePixProc != NULL)
394 const int aPixAttribs[] =
396 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
397 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
398 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
399 WGL_STEREO_ARB, hasStereo ? GL_TRUE : GL_FALSE,
400 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
401 //WGL_SAMPLE_BUFFERS_ARB, 1,
402 //WGL_SAMPLES_ARB, 8,
403 WGL_COLOR_BITS_ARB, 24,
404 WGL_DEPTH_BITS_ARB, 24,
405 WGL_STENCIL_BITS_ARB, 8,
406 // WGL_EXT_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
407 //WGL_COLORSPACE_EXT, !theCaps->sRGBDisable ? WGL_COLORSPACE_SRGB_EXT : WGL_COLORSPACE_LINEAR_EXT,
408 // requires WGL_ARB_framebuffer_sRGB or WGL_EXT_framebuffer_sRGB extensions
409 //WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, !theCaps->sRGBDisable ? GL_TRUE : GL_FALSE,
410 WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
413 unsigned int aFrmtsNb = 0;
414 aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
417 // setup pixel format - may be set only once per window
418 if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
420 ReleaseDC (aWindow, aWindowDC);
422 TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
423 aMsg += (int )GetLastError();
424 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
428 // create GL context with extra options
429 if (aCreateCtxProc != NULL)
431 if (!theCaps->contextCompatible)
433 int aCoreCtxAttribs[] =
435 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
436 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
437 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
438 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
442 // Try to create the core profile of highest OpenGL version supported by OCCT
443 // (this will be done automatically by some drivers when requesting 3.2,
444 // but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations).
445 for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
447 aCoreCtxAttribs[1] = 4;
448 aCoreCtxAttribs[3] = aLowVer4;
449 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
451 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
453 aCoreCtxAttribs[1] = 3;
454 aCoreCtxAttribs[3] = aLowVer3;
455 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
457 isCoreProfile = aGContext != NULL;
460 if (aGContext == NULL)
464 // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
465 // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
466 //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
467 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
470 isCoreProfile = Standard_False;
471 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
473 if (aGContext != NULL
474 && !theCaps->contextCompatible)
476 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
477 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
481 if (aGContext != NULL)
487 if (aRendCtxTmp != NULL)
489 wglDeleteContext (aRendCtxTmp);
491 if (aDevCtxTmp != NULL)
493 ReleaseDC (aWinTmp, aDevCtxTmp);
497 DestroyWindow (aWinTmp);
499 if (aClass.lpszClassName != NULL)
501 UnregisterClassW (aClass.lpszClassName, aModule);
504 if (aGContext == NULL)
506 // create context using obsolete functionality
507 aGContext = wglCreateContext (aWindowDC);
509 if (aGContext == NULL)
511 ReleaseDC (aWindow, aWindowDC);
513 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
514 aMsg += (int )GetLastError();
515 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
520 // all GL context within one OpenGl_GraphicDriver should be shared!
521 if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
523 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
524 aMsg += (int )GetLastError();
525 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
529 myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
530 #elif defined(HAVE_XLIB)
531 Window aWindow = (Window )myPlatformWindow->NativeHandle();
532 Display* aDisp = (Display* )theDriver->GetDisplayConnection()->GetDisplayAspect();
533 GLXContext aGContext = (GLXContext )theGContext;
534 GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
536 XWindowAttributes aWinAttribs;
537 XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
538 XVisualInfo aVisInfo;
539 aVisInfo.visualid = aWinAttribs.visual->visualid;
540 aVisInfo.screen = DefaultScreen (aDisp);
542 std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
544 if (aVis.get() == NULL)
546 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
549 else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
551 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
555 // create new context
556 GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
557 const char* aGlxExts = glXQueryExtensionsString (aDisp, aVisInfo.screen);
559 && anFBConfig != NULL
560 && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
562 // Replace default XError handler to ignore errors.
563 // Warning - this is global for all threads!
564 typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
565 xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);
567 typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
568 GLXContext share_context, Bool direct,
569 const int* attrib_list);
570 glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
571 if (!theCaps->contextCompatible)
573 int aCoreCtxAttribs[] =
575 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
576 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
577 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
578 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
582 // try to create the core profile of highest OpenGL version supported by OCCT
583 for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
585 aCoreCtxAttribs[1] = 4;
586 aCoreCtxAttribs[3] = aLowVer4;
587 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
589 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
591 aCoreCtxAttribs[1] = 3;
592 aCoreCtxAttribs[3] = aLowVer3;
593 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
595 isCoreProfile = aGContext != NULL;
598 if (aGContext == NULL)
602 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
605 isCoreProfile = Standard_False;
606 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
608 if (aGContext != NULL
609 && !theCaps->contextCompatible)
611 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
612 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
615 XSetErrorHandler(anOldHandler);
619 && aGContext == NULL)
621 aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
622 if (aGContext == NULL)
624 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
629 // check Visual for OpenGl context's parameters compatibility
630 TCollection_ExtendedString aList;
631 int isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
632 int aDepthSize = 0, aStencilSize = 0;
633 glXGetConfig (aDisp, aVis.get(), GLX_RGBA, &isRGBA);
634 glXGetConfig (aDisp, aVis.get(), GLX_DOUBLEBUFFER, &isDoubleBuffer);
635 glXGetConfig (aDisp, aVis.get(), GLX_STEREO, &isStereo);
636 glXGetConfig (aDisp, aVis.get(), GLX_DEPTH_SIZE, &aDepthSize);
637 glXGetConfig (aDisp, aVis.get(), GLX_STENCIL_SIZE, &aStencilSize);
638 if (aDepthSize < 1) addMsgToList (aList, "no depth buffer");
639 if (aStencilSize < 1) addMsgToList (aList, "no stencil buffer");
640 if (isRGBA == 0) addMsgToList (aList, "no RGBA color buffer");
641 if (isDoubleBuffer == 0) addMsgToList (aList, "no Double Buffer");
642 if (theCaps->contextStereo && isStereo == 0)
644 addMsgToList (aList, "no Quad Buffer");
646 else if (!theCaps->contextStereo && isStereo == 1)
648 addMsgToList (aList, "extra Quad Buffer");
650 if (!aList.IsEmpty())
652 TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
653 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
655 0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
658 myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
661 (void )isCoreProfile;
663 myGlContext->Share (theShareCtx);
664 myGlContext->SetSwapInterval (mySwapInterval);
668 // =======================================================================
669 // function : ~OpenGl_Window
671 // =======================================================================
672 OpenGl_Window::~OpenGl_Window()
675 || myGlContext.IsNull())
677 myGlContext.Nullify();
681 // release "GL" context if it is owned by window
682 // Mesa implementation can fail to destroy GL context if it set for current thread.
683 // It should be safer to unset thread GL context before its destruction.
684 #if defined(HAVE_EGL)
685 if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
687 eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
688 (EGLSurface )myGlContext->myWindow);
690 #elif defined(_WIN32)
691 HWND aWindow = (HWND )myGlContext->myWindow;
692 HDC aWindowDC = (HDC )myGlContext->myDisplay;
693 HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext;
694 HGLRC aThreadGContext = wglGetCurrentContext();
695 myGlContext.Nullify();
697 if (aThreadGContext != NULL)
699 if (aThreadGContext == aWindowGContext)
701 wglMakeCurrent (NULL, NULL);
704 wglDeleteContext (aWindowGContext);
706 ReleaseDC (aWindow, aWindowDC);
707 #elif defined(HAVE_XLIB)
708 Display* aDisplay = (Display* )myGlContext->myDisplay;
709 GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext;
710 GLXContext aThreadGContext = glXGetCurrentContext();
711 myGlContext.Nullify();
713 if (aDisplay != NULL)
715 if (aThreadGContext == aWindowGContext)
717 glXMakeCurrent (aDisplay, None, NULL);
720 // FSXXX sync necessary if non-direct rendering
722 glXDestroyContext (aDisplay, aWindowGContext);
731 // =======================================================================
732 // function : Activate
734 // =======================================================================
735 Standard_Boolean OpenGl_Window::Activate()
737 return myGlContext->MakeCurrent();
740 #if !defined(__APPLE__) || defined(HAVE_XLIB)
742 // =======================================================================
744 // purpose : call_subr_resize
745 // =======================================================================
746 void OpenGl_Window::Resize()
748 Standard_Integer aWidth = 0, aHeight = 0;
749 myPlatformWindow->Size (aWidth, aHeight);
750 if (myWidth == aWidth
751 && myHeight == aHeight)
753 // if the size is not changed - do nothing
763 // =======================================================================
766 // =======================================================================
767 void OpenGl_Window::Init()
772 #if defined(HAVE_EGL)
773 if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
775 // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
776 // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
777 // for offscreen rendering on bugged OpenGL ES drivers
778 Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
779 if (!aDefFbo.IsNull())
781 aDefFbo->Release (myGlContext.operator->());
785 aDefFbo = new OpenGl_FrameBuffer();
788 if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
790 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
791 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
793 myGlContext->SetDefaultFrameBuffer (aDefFbo);
794 aDefFbo->BindBuffer (myGlContext);
796 else if (!myPlatformWindow->IsVirtual())
798 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
799 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
805 glDisable (GL_DITHER);
806 glDisable (GL_SCISSOR_TEST);
807 const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
808 myGlContext->ResizeViewport (aViewport);
809 #if !defined(GL_ES_VERSION_2_0)
810 myGlContext->SetDrawBuffer (GL_BACK);
811 if (myGlContext->core11ffp != NULL)
813 glMatrixMode (GL_MODELVIEW);
818 // =======================================================================
819 // function : SetSwapInterval
821 // =======================================================================
822 void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
824 const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
825 if (mySwapInterval != aSwapInterval)
827 mySwapInterval = aSwapInterval;
828 myGlContext->SetSwapInterval (mySwapInterval);