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.
20 #include <OpenGl_GlCore12.hxx>
22 #include <OpenGl_Context.hxx>
23 #include <OpenGl_GraphicDriver.hxx>
24 #include <OpenGl_Window.hxx>
25 #include <OpenGl_FrameBuffer.hxx>
27 #include <Aspect_GraphicDeviceDefinitionError.hxx>
28 #include <Graphic3d_TransformUtils.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <Graphic3d_GraphicDriver.hxx>
35 #include <Standard_WarningDisableFunctionCast.hxx>
37 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient)
41 #elif defined(HAVE_XLIB)
45 #if !defined(__APPLE__) || defined(HAVE_XLIB)
54 // WGL_ARB_pixel_format
55 #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
56 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
57 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
58 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
59 #define WGL_ACCELERATION_ARB 0x2003
60 #define WGL_NEED_PALETTE_ARB 0x2004
61 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
62 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
63 #define WGL_SWAP_METHOD_ARB 0x2007
64 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
65 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
66 #define WGL_TRANSPARENT_ARB 0x200A
67 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
68 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
69 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
70 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
71 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
72 #define WGL_SHARE_DEPTH_ARB 0x200C
73 #define WGL_SHARE_STENCIL_ARB 0x200D
74 #define WGL_SHARE_ACCUM_ARB 0x200E
75 #define WGL_SUPPORT_GDI_ARB 0x200F
76 #define WGL_SUPPORT_OPENGL_ARB 0x2010
77 #define WGL_DOUBLE_BUFFER_ARB 0x2011
78 #define WGL_STEREO_ARB 0x2012
79 #define WGL_PIXEL_TYPE_ARB 0x2013
80 #define WGL_COLOR_BITS_ARB 0x2014
81 #define WGL_RED_BITS_ARB 0x2015
82 #define WGL_RED_SHIFT_ARB 0x2016
83 #define WGL_GREEN_BITS_ARB 0x2017
84 #define WGL_GREEN_SHIFT_ARB 0x2018
85 #define WGL_BLUE_BITS_ARB 0x2019
86 #define WGL_BLUE_SHIFT_ARB 0x201A
87 #define WGL_ALPHA_BITS_ARB 0x201B
88 #define WGL_ALPHA_SHIFT_ARB 0x201C
89 #define WGL_ACCUM_BITS_ARB 0x201D
90 #define WGL_ACCUM_RED_BITS_ARB 0x201E
91 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
92 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
93 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
94 #define WGL_DEPTH_BITS_ARB 0x2022
95 #define WGL_STENCIL_BITS_ARB 0x2023
96 #define WGL_AUX_BUFFERS_ARB 0x2024
98 #define WGL_NO_ACCELERATION_ARB 0x2025
99 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
100 #define WGL_FULL_ACCELERATION_ARB 0x2027
102 #define WGL_SWAP_EXCHANGE_ARB 0x2028
103 #define WGL_SWAP_COPY_ARB 0x2029
104 #define WGL_SWAP_UNDEFINED_ARB 0x202A
106 #define WGL_TYPE_RGBA_ARB 0x202B
107 #define WGL_TYPE_COLORINDEX_ARB 0x202C
108 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
110 // WGL_ARB_create_context_profile
111 #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
112 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
113 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
114 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
115 #define WGL_CONTEXT_FLAGS_ARB 0x2094
116 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
118 // WGL_CONTEXT_FLAGS bits
119 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
120 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
122 // WGL_CONTEXT_PROFILE_MASK_ARB bits
123 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
124 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
125 #endif // WGL_CONTEXT_MAJOR_VERSION_ARB
127 static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
129 return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
131 #elif defined(HAVE_XLIB)
133 // GLX_ARB_create_context
134 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
135 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
136 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
137 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
138 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
139 #define GLX_CONTEXT_FLAGS_ARB 0x2094
141 // GLX_ARB_create_context_profile
142 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
143 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
144 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
147 //! Dummy XError handler which just skips errors
148 static int xErrorDummyHandler (Display* /*theDisplay*/,
149 XErrorEvent* /*theErrorEvent*/)
154 //! Auxiliary method to format list.
155 static void addMsgToList (TCollection_ExtendedString& theList,
156 const TCollection_ExtendedString& theMsg)
158 if (!theList.IsEmpty())
168 // =======================================================================
169 // function : OpenGl_Window
171 // =======================================================================
172 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
173 const Handle(Aspect_Window)& thePlatformWindow,
174 Aspect_RenderingContext theGContext,
175 const Handle(OpenGl_Caps)& theCaps,
176 const Handle(OpenGl_Context)& theShareCtx)
177 : myGlContext (new OpenGl_Context (theCaps)),
178 myOwnGContext (theGContext == 0),
179 myPlatformWindow (thePlatformWindow),
180 mySwapInterval (theCaps->swapInterval)
182 myPlatformWindow->Size (myWidth, myHeight);
184 Standard_Boolean isCoreProfile = Standard_False;
186 #if defined(HAVE_EGL)
187 EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
188 EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
189 EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
190 if (anEglDisplay == EGL_NO_DISPLAY
191 || anEglContext == EGL_NO_CONTEXT
192 || (anEglConfig == NULL
193 && (EGLContext )theGContext == EGL_NO_CONTEXT))
195 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
199 EGLSurface anEglSurf = EGL_NO_SURFACE;
200 if ((EGLContext )theGContext == EGL_NO_CONTEXT)
202 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
203 //const int aSurfAttribs[] =
205 // EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
209 // create new surface
210 anEglSurf = eglCreateWindowSurface (anEglDisplay,
212 (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
214 if (anEglSurf == EGL_NO_SURFACE
215 && myPlatformWindow->NativeHandle() != 0)
217 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
219 else if (anEglSurf == EGL_NO_SURFACE)
221 // window-less EGL context (off-screen)
222 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
223 if (anEglConfig != NULL)
225 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
226 const int aSurfAttribs[] =
229 EGL_HEIGHT, myHeight,
230 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
231 //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
234 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
235 if (anEglSurf == EGL_NO_SURFACE)
237 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
241 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
242 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
245 else if (theGContext != anEglContext)
247 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
251 anEglSurf = eglGetCurrentSurface(EGL_DRAW);
252 if (anEglSurf == EGL_NO_SURFACE)
254 // window-less EGL context (off-screen)
255 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
256 if (anEglConfig != NULL)
258 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
259 const int aSurfAttribs[] =
262 EGL_HEIGHT, myHeight,
263 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
264 //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
267 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
268 if (anEglSurf == EGL_NO_SURFACE)
270 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
274 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
275 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
279 myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
280 #elif defined(_WIN32)
282 HWND aWindow = (HWND )myPlatformWindow->NativeHandle();
283 HDC aWindowDC = GetDC (aWindow);
284 HGLRC aGContext = (HGLRC )theGContext;
286 PIXELFORMATDESCRIPTOR aPixelFrmt;
287 memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
288 aPixelFrmt.nSize = sizeof(PIXELFORMATDESCRIPTOR);
289 aPixelFrmt.nVersion = 1;
290 aPixelFrmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
291 aPixelFrmt.iPixelType = PFD_TYPE_RGBA;
292 aPixelFrmt.cColorBits = 24;
293 aPixelFrmt.cDepthBits = 24;
294 aPixelFrmt.cStencilBits = 8;
295 aPixelFrmt.iLayerType = PFD_MAIN_PLANE;
296 if (theCaps->contextStereo)
298 aPixelFrmt.dwFlags |= PFD_STEREO;
301 int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
303 // in case of failure try without stereo if any
304 const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
305 if (aPixelFrmtId == 0 && theCaps->contextStereo)
307 TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
308 "ChoosePixelFormat is unable to find stereo supported pixel format. "
309 "Choosing similar non stereo format.");
310 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
312 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
314 aPixelFrmt.dwFlags &= ~PFD_STEREO;
315 aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
318 if (aPixelFrmtId == 0)
320 ReleaseDC (aWindow, aWindowDC);
322 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
323 aMsg += (int )GetLastError();
324 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
328 DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
330 HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
331 if (aGContext == NULL)
333 // create temporary context to retrieve advanced context creation procedures
334 HMODULE aModule = GetModuleHandleW(NULL);
335 WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
336 aClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
337 aClass.lpfnWndProc = wndProcDummy;
338 aClass.hInstance = aModule;
339 aClass.lpszClassName = L"OpenGl_WindowTmp";
341 HDC aDevCtxTmp = NULL;
342 HGLRC aRendCtxTmp = NULL;
343 if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
344 || RegisterClassW (&aClass) == 0)
346 aClass.lpszClassName = NULL;
348 if (aClass.lpszClassName != NULL)
350 DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
351 #if (_WIN32_WINNT >= 0x0500)
352 anExStyle |= WS_EX_NOACTIVATE;
354 aWinTmp = CreateWindowExW(anExStyle,
355 aClass.lpszClassName, L"OpenGl_WindowTmp",
356 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
358 NULL, NULL, aModule, NULL);
362 aDevCtxTmp = GetDC (aWinTmp);
363 SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
364 aRendCtxTmp = wglCreateContext (aDevCtxTmp);
367 typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx,
368 const int* theIntAttribs,
369 const float* theFloatAttribs,
370 unsigned int theMaxFormats,
372 unsigned int* theNumFormatsOut);
373 typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx,
374 HGLRC theShareContext,
375 const int* theAttribs);
376 wglChoosePixelFormatARB_t aChoosePixProc = NULL;
377 wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
378 if (aRendCtxTmp != NULL)
380 wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
382 typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
383 wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB");
384 const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
385 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
387 aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
389 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
391 aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
395 // choose extended pixel format
396 if (aChoosePixProc != NULL)
398 const int aPixAttribs[] =
400 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
401 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
402 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
403 WGL_STEREO_ARB, hasStereo ? GL_TRUE : GL_FALSE,
404 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
405 //WGL_SAMPLE_BUFFERS_ARB, 1,
406 //WGL_SAMPLES_ARB, 8,
407 WGL_COLOR_BITS_ARB, 24,
408 WGL_DEPTH_BITS_ARB, 24,
409 WGL_STENCIL_BITS_ARB, 8,
410 // WGL_EXT_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
411 //WGL_COLORSPACE_EXT, !theCaps->sRGBDisable ? WGL_COLORSPACE_SRGB_EXT : WGL_COLORSPACE_LINEAR_EXT,
412 // requires WGL_ARB_framebuffer_sRGB or WGL_EXT_framebuffer_sRGB extensions
413 //WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, !theCaps->sRGBDisable ? GL_TRUE : GL_FALSE,
414 WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
417 unsigned int aFrmtsNb = 0;
418 aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
421 // setup pixel format - may be set only once per window
422 if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
424 ReleaseDC (aWindow, aWindowDC);
426 TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
427 aMsg += (int )GetLastError();
428 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
432 // create GL context with extra options
433 if (aCreateCtxProc != NULL)
435 if (!theCaps->contextCompatible)
437 int aCoreCtxAttribs[] =
439 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
440 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
441 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
442 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
446 // Try to create the core profile of highest OpenGL version supported by OCCT
447 // (this will be done automatically by some drivers when requesting 3.2,
448 // but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations).
449 for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
451 aCoreCtxAttribs[1] = 4;
452 aCoreCtxAttribs[3] = aLowVer4;
453 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
455 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
457 aCoreCtxAttribs[1] = 3;
458 aCoreCtxAttribs[3] = aLowVer3;
459 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
461 isCoreProfile = aGContext != NULL;
464 if (aGContext == NULL)
468 // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
469 // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
470 //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
471 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
474 isCoreProfile = Standard_False;
475 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
477 if (aGContext != NULL
478 && !theCaps->contextCompatible)
480 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
481 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
485 if (aGContext != NULL)
491 if (aRendCtxTmp != NULL)
493 wglDeleteContext (aRendCtxTmp);
495 if (aDevCtxTmp != NULL)
497 ReleaseDC (aWinTmp, aDevCtxTmp);
501 DestroyWindow (aWinTmp);
503 if (aClass.lpszClassName != NULL)
505 UnregisterClassW (aClass.lpszClassName, aModule);
508 if (aGContext == NULL)
510 // create context using obsolete functionality
511 aGContext = wglCreateContext (aWindowDC);
513 if (aGContext == NULL)
515 ReleaseDC (aWindow, aWindowDC);
517 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
518 aMsg += (int )GetLastError();
519 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
524 // all GL context within one OpenGl_GraphicDriver should be shared!
525 if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
527 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
528 aMsg += (int )GetLastError();
529 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
533 myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
534 #elif defined(HAVE_XLIB)
535 Window aWindow = (Window )myPlatformWindow->NativeHandle();
536 Display* aDisp = (Display* )theDriver->GetDisplayConnection()->GetDisplayAspect();
537 GLXContext aGContext = (GLXContext )theGContext;
538 GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
540 XWindowAttributes aWinAttribs;
541 XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
542 XVisualInfo aVisInfo;
543 aVisInfo.visualid = aWinAttribs.visual->visualid;
544 aVisInfo.screen = DefaultScreen (aDisp);
546 std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
548 if (aVis.get() == NULL)
550 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
553 else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
555 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
559 // create new context
560 GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
561 const char* aGlxExts = glXQueryExtensionsString (aDisp, aVisInfo.screen);
563 && anFBConfig != NULL
564 && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
566 // Replace default XError handler to ignore errors.
567 // Warning - this is global for all threads!
568 typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
569 xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);
571 typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
572 GLXContext share_context, Bool direct,
573 const int* attrib_list);
574 glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
575 if (!theCaps->contextCompatible)
577 int aCoreCtxAttribs[] =
579 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
580 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
581 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
582 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
586 // try to create the core profile of highest OpenGL version supported by OCCT
587 for (int aLowVer4 = 6; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
589 aCoreCtxAttribs[1] = 4;
590 aCoreCtxAttribs[3] = aLowVer4;
591 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
593 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
595 aCoreCtxAttribs[1] = 3;
596 aCoreCtxAttribs[3] = aLowVer3;
597 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
599 isCoreProfile = aGContext != NULL;
602 if (aGContext == NULL)
606 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
609 isCoreProfile = Standard_False;
610 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
612 if (aGContext != NULL
613 && !theCaps->contextCompatible)
615 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
616 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
619 XSetErrorHandler(anOldHandler);
623 && aGContext == NULL)
625 aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
626 if (aGContext == NULL)
628 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
633 // check Visual for OpenGl context's parameters compatibility
634 TCollection_ExtendedString aList;
635 int isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
636 int aDepthSize = 0, aStencilSize = 0;
637 glXGetConfig (aDisp, aVis.get(), GLX_RGBA, &isRGBA);
638 glXGetConfig (aDisp, aVis.get(), GLX_DOUBLEBUFFER, &isDoubleBuffer);
639 glXGetConfig (aDisp, aVis.get(), GLX_STEREO, &isStereo);
640 glXGetConfig (aDisp, aVis.get(), GLX_DEPTH_SIZE, &aDepthSize);
641 glXGetConfig (aDisp, aVis.get(), GLX_STENCIL_SIZE, &aStencilSize);
642 if (aDepthSize < 1) addMsgToList (aList, "no depth buffer");
643 if (aStencilSize < 1) addMsgToList (aList, "no stencil buffer");
644 if (isRGBA == 0) addMsgToList (aList, "no RGBA color buffer");
645 if (isDoubleBuffer == 0) addMsgToList (aList, "no Double Buffer");
646 if (theCaps->contextStereo && isStereo == 0)
648 addMsgToList (aList, "no Quad Buffer");
650 else if (!theCaps->contextStereo && isStereo == 1)
652 addMsgToList (aList, "extra Quad Buffer");
654 if (!aList.IsEmpty())
656 TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
657 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
659 0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
662 myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
665 (void )isCoreProfile;
667 myGlContext->Share (theShareCtx);
668 myGlContext->SetSwapInterval (mySwapInterval);
672 // =======================================================================
673 // function : ~OpenGl_Window
675 // =======================================================================
676 OpenGl_Window::~OpenGl_Window()
679 || myGlContext.IsNull())
681 myGlContext.Nullify();
685 // release "GL" context if it is owned by window
686 // Mesa implementation can fail to destroy GL context if it set for current thread.
687 // It should be safer to unset thread GL context before its destruction.
688 #if defined(HAVE_EGL)
689 if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
691 eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
692 (EGLSurface )myGlContext->myWindow);
694 #elif defined(_WIN32)
695 HWND aWindow = (HWND )myGlContext->myWindow;
696 HDC aWindowDC = (HDC )myGlContext->myDisplay;
697 HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext;
698 HGLRC aThreadGContext = wglGetCurrentContext();
699 myGlContext.Nullify();
701 if (aThreadGContext != NULL)
703 if (aThreadGContext == aWindowGContext)
705 wglMakeCurrent (NULL, NULL);
708 wglDeleteContext (aWindowGContext);
710 ReleaseDC (aWindow, aWindowDC);
711 #elif defined(HAVE_XLIB)
712 Display* aDisplay = (Display* )myGlContext->myDisplay;
713 GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext;
714 GLXContext aThreadGContext = glXGetCurrentContext();
715 myGlContext.Nullify();
717 if (aDisplay != NULL)
719 if (aThreadGContext == aWindowGContext)
721 glXMakeCurrent (aDisplay, None, NULL);
724 // FSXXX sync necessary if non-direct rendering
726 glXDestroyContext (aDisplay, aWindowGContext);
735 // =======================================================================
736 // function : Activate
738 // =======================================================================
739 Standard_Boolean OpenGl_Window::Activate()
741 return myGlContext->MakeCurrent();
744 #if !defined(__APPLE__) || defined(HAVE_XLIB)
746 // =======================================================================
748 // purpose : call_subr_resize
749 // =======================================================================
750 void OpenGl_Window::Resize()
752 Standard_Integer aWidth = 0, aHeight = 0;
753 myPlatformWindow->Size (aWidth, aHeight);
754 if (myWidth == aWidth
755 && myHeight == aHeight)
757 // if the size is not changed - do nothing
767 // =======================================================================
770 // =======================================================================
771 void OpenGl_Window::Init()
776 #if defined(HAVE_EGL)
777 if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
779 // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
780 // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
781 // for offscreen rendering on bugged OpenGL ES drivers
782 Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
783 if (!aDefFbo.IsNull())
785 aDefFbo->Release (myGlContext.operator->());
789 aDefFbo = new OpenGl_FrameBuffer();
792 OpenGl_ColorFormats aColorFormats;
793 aColorFormats.Append (GL_RGBA8);
794 if (!aDefFbo->InitRenderBuffer (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), aColorFormats, GL_DEPTH24_STENCIL8))
796 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
797 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
799 myGlContext->SetDefaultFrameBuffer (aDefFbo);
800 aDefFbo->BindBuffer (myGlContext);
802 else if (!myPlatformWindow->IsVirtual())
804 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
805 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
811 myGlContext->core11fwd->glDisable (GL_DITHER);
812 myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST);
813 const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
814 myGlContext->ResizeViewport (aViewport);
815 myGlContext->SetDrawBuffer (GL_BACK);
816 if (myGlContext->core11ffp != NULL)
818 myGlContext->core11ffp->glMatrixMode (GL_MODELVIEW);
822 // =======================================================================
823 // function : SetSwapInterval
825 // =======================================================================
826 void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
828 const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
829 if (mySwapInterval != aSwapInterval)
831 mySwapInterval = aSwapInterval;
832 myGlContext->SetSwapInterval (mySwapInterval);