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)
40 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
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
93 #define WGL_NO_ACCELERATION_ARB 0x2025
94 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
95 #define WGL_FULL_ACCELERATION_ARB 0x2027
97 #define WGL_SWAP_EXCHANGE_ARB 0x2028
98 #define WGL_SWAP_COPY_ARB 0x2029
99 #define WGL_SWAP_UNDEFINED_ARB 0x202A
101 #define WGL_TYPE_RGBA_ARB 0x202B
102 #define WGL_TYPE_COLORINDEX_ARB 0x202C
103 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
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
113 // WGL_CONTEXT_FLAGS bits
114 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
115 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
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
122 static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
124 return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
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
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
142 //! Dummy XError handler which just skips errors
143 static int xErrorDummyHandler (Display* /*theDisplay*/,
144 XErrorEvent* /*theErrorEvent*/)
149 //! Auxiliary method to format list.
150 static void addMsgToList (TCollection_ExtendedString& theList,
151 const TCollection_ExtendedString& theMsg)
153 if (!theList.IsEmpty())
163 // =======================================================================
164 // function : OpenGl_Window
166 // =======================================================================
167 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
168 const Handle(Aspect_Window)& thePlatformWindow,
169 Aspect_RenderingContext theGContext,
170 const Handle(OpenGl_Caps)& theCaps,
171 const Handle(OpenGl_Context)& theShareCtx)
172 : myGlContext (new OpenGl_Context (theCaps)),
173 myOwnGContext (theGContext == 0),
174 myPlatformWindow (thePlatformWindow),
175 mySwapInterval (theCaps->swapInterval)
177 myPlatformWindow->Size (myWidth, myHeight);
179 Standard_Boolean isCoreProfile = Standard_False;
181 #if defined(HAVE_EGL)
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
187 || (anEglConfig == NULL
188 && (EGLContext )theGContext == EGL_NO_CONTEXT))
190 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
194 EGLSurface anEglSurf = EGL_NO_SURFACE;
195 if ((EGLContext )theGContext == EGL_NO_CONTEXT)
197 // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
198 //const int aSurfAttribs[] =
200 // EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
204 // create new surface
205 anEglSurf = eglCreateWindowSurface (anEglDisplay,
207 (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
209 if (anEglSurf == EGL_NO_SURFACE)
211 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
215 else if (theGContext != anEglContext)
217 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
222 anEglSurf = eglGetCurrentSurface(EGL_DRAW);
223 if (anEglSurf == EGL_NO_SURFACE)
225 // window-less EGL context (off-screen)
226 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
227 if (anEglConfig != NULL)
229 #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
230 const int aSurfAttribs[] =
233 EGL_HEIGHT, myHeight,
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,
238 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
239 if (anEglSurf == EGL_NO_SURFACE)
241 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
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!");
250 myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
251 #elif defined(_WIN32)
253 HWND aWindow = (HWND )myPlatformWindow->NativeHandle();
254 HDC aWindowDC = GetDC (aWindow);
255 HGLRC aGContext = (HGLRC )theGContext;
257 PIXELFORMATDESCRIPTOR aPixelFrmt;
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)
269 aPixelFrmt.dwFlags |= PFD_STEREO;
272 int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
274 // in case of failure try without stereo if any
275 const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
276 if (aPixelFrmtId == 0 && theCaps->contextStereo)
278 TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
279 "ChoosePixelFormat is unable to find stereo supported pixel format. "
280 "Choosing similar non stereo format.");
281 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
283 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
285 aPixelFrmt.dwFlags &= ~PFD_STEREO;
286 aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
289 if (aPixelFrmtId == 0)
291 ReleaseDC (aWindow, aWindowDC);
293 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
294 aMsg += (int )GetLastError();
295 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
299 DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
301 HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
302 if (aGContext == NULL)
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";
312 HDC aDevCtxTmp = NULL;
313 HGLRC aRendCtxTmp = NULL;
314 if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
315 || RegisterClassW (&aClass) == 0)
317 aClass.lpszClassName = NULL;
319 if (aClass.lpszClassName != NULL)
321 DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
322 #if (_WIN32_WINNT >= 0x0500)
323 anExStyle |= WS_EX_NOACTIVATE;
325 aWinTmp = CreateWindowExW(anExStyle,
326 aClass.lpszClassName, L"OpenGl_WindowTmp",
327 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
329 NULL, NULL, aModule, NULL);
333 aDevCtxTmp = GetDC (aWinTmp);
334 SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
335 aRendCtxTmp = wglCreateContext (aDevCtxTmp);
338 typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx,
339 const int* theIntAttribs,
340 const float* theFloatAttribs,
341 unsigned int theMaxFormats,
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;
349 if (aRendCtxTmp != NULL)
351 wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
353 typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
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"))
358 aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
360 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
362 aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
366 // choose extended pixel format
367 if (aChoosePixProc != NULL)
369 const int aPixAttribs[] =
371 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
372 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
373 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
374 WGL_STEREO_ARB, hasStereo ? GL_TRUE : GL_FALSE,
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,
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,
385 WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
388 unsigned int aFrmtsNb = 0;
389 aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
392 // setup pixel format - may be set only once per window
393 if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
395 ReleaseDC (aWindow, aWindowDC);
397 TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
398 aMsg += (int )GetLastError();
399 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
403 // create GL context with extra options
404 if (aCreateCtxProc != NULL)
406 if (!theCaps->contextCompatible)
408 int aCoreCtxAttribs[] =
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,
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)
422 aCoreCtxAttribs[1] = 4;
423 aCoreCtxAttribs[3] = aLowVer4;
424 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
426 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
428 aCoreCtxAttribs[1] = 3;
429 aCoreCtxAttribs[3] = aLowVer3;
430 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
432 isCoreProfile = aGContext != NULL;
435 if (aGContext == NULL)
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,
445 isCoreProfile = Standard_False;
446 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
448 if (aGContext != NULL
449 && !theCaps->contextCompatible)
451 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
452 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
456 if (aGContext != NULL)
462 if (aRendCtxTmp != NULL)
464 wglDeleteContext (aRendCtxTmp);
466 if (aDevCtxTmp != NULL)
468 ReleaseDC (aWinTmp, aDevCtxTmp);
472 DestroyWindow (aWinTmp);
474 if (aClass.lpszClassName != NULL)
476 UnregisterClassW (aClass.lpszClassName, aModule);
479 if (aGContext == NULL)
481 // create context using obsolete functionality
482 aGContext = wglCreateContext (aWindowDC);
484 if (aGContext == NULL)
486 ReleaseDC (aWindow, aWindowDC);
488 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
489 aMsg += (int )GetLastError();
490 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
495 // all GL context within one OpenGl_GraphicDriver should be shared!
496 if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
498 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
499 aMsg += (int )GetLastError();
500 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
504 myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
506 Window aWindow = (Window )myPlatformWindow->NativeHandle();
507 Display* aDisp = theDriver->GetDisplayConnection()->GetDisplay();
508 GLXContext aGContext = (GLXContext )theGContext;
509 GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
511 XWindowAttributes aWinAttribs;
512 XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
513 XVisualInfo aVisInfo;
514 aVisInfo.visualid = aWinAttribs.visual->visualid;
515 aVisInfo.screen = DefaultScreen (aDisp);
517 std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
519 if (aVis.get() == NULL)
521 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
524 else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
526 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
530 // create new context
531 GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
532 const char* aGlxExts = glXQueryExtensionsString (aDisp, aVisInfo.screen);
534 && anFBConfig != NULL
535 && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
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);
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)
548 int aCoreCtxAttribs[] =
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,
557 // try to create the core profile of highest OpenGL version supported by OCCT
558 for (int aLowVer4 = 5; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
560 aCoreCtxAttribs[1] = 4;
561 aCoreCtxAttribs[3] = aLowVer4;
562 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
564 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
566 aCoreCtxAttribs[1] = 3;
567 aCoreCtxAttribs[3] = aLowVer3;
568 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
570 isCoreProfile = aGContext != NULL;
573 if (aGContext == NULL)
577 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
580 isCoreProfile = Standard_False;
581 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
583 if (aGContext != NULL
584 && !theCaps->contextCompatible)
586 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
587 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
590 XSetErrorHandler(anOldHandler);
594 && aGContext == NULL)
596 aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
597 if (aGContext == NULL)
599 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
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;
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);
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)
619 addMsgToList (aList, "no Quad Buffer");
621 else if (!theCaps->contextStereo && isStereo == 1)
623 addMsgToList (aList, "extra Quad Buffer");
625 if (!aList.IsEmpty())
627 TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
628 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
630 0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
633 myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
635 myGlContext->Share (theShareCtx);
636 myGlContext->SetSwapInterval (mySwapInterval);
640 // =======================================================================
641 // function : ~OpenGl_Window
643 // =======================================================================
644 OpenGl_Window::~OpenGl_Window()
647 || myGlContext.IsNull())
649 myGlContext.Nullify();
653 // release "GL" context if it is owned by window
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.
656 #if defined(HAVE_EGL)
657 if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
659 eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
660 (EGLSurface )myGlContext->myWindow);
662 #elif defined(_WIN32)
663 HWND aWindow = (HWND )myGlContext->myWindow;
664 HDC aWindowDC = (HDC )myGlContext->myWindowDC;
665 HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext;
666 HGLRC aThreadGContext = wglGetCurrentContext();
667 myGlContext.Nullify();
669 if (aThreadGContext != NULL)
671 if (aThreadGContext == aWindowGContext)
673 wglMakeCurrent (NULL, NULL);
676 wglDeleteContext (aWindowGContext);
678 ReleaseDC (aWindow, aWindowDC);
680 Display* aDisplay = (Display* )myGlContext->myDisplay;
681 GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext;
682 GLXContext aThreadGContext = glXGetCurrentContext();
683 myGlContext.Nullify();
685 if (aDisplay != NULL)
687 if (aThreadGContext == aWindowGContext)
689 glXMakeCurrent (aDisplay, None, NULL);
692 // FSXXX sync necessary if non-direct rendering
694 glXDestroyContext (aDisplay, aWindowGContext);
701 // =======================================================================
702 // function : Activate
704 // =======================================================================
705 Standard_Boolean OpenGl_Window::Activate()
707 return myGlContext->MakeCurrent();
710 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
712 // =======================================================================
714 // purpose : call_subr_resize
715 // =======================================================================
716 void OpenGl_Window::Resize()
718 Standard_Integer aWidth = 0, aHeight = 0;
719 myPlatformWindow->Size (aWidth, aHeight);
720 if (myWidth == aWidth
721 && myHeight == aHeight)
723 // if the size is not changed - do nothing
733 // =======================================================================
736 // =======================================================================
737 void OpenGl_Window::Init()
742 #if defined(HAVE_EGL)
743 if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
745 // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
746 // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
747 // for offscreen rendering on bugged OpenGL ES drivers
748 Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
749 if (!aDefFbo.IsNull())
751 aDefFbo->Release (myGlContext.operator->());
755 aDefFbo = new OpenGl_FrameBuffer();
758 if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
760 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
761 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
763 myGlContext->SetDefaultFrameBuffer (aDefFbo);
764 aDefFbo->BindBuffer (myGlContext);
766 else if (!myPlatformWindow->IsVirtual())
768 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
769 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
775 glDisable (GL_DITHER);
776 glDisable (GL_SCISSOR_TEST);
777 const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
778 myGlContext->ResizeViewport (aViewport);
779 #if !defined(GL_ES_VERSION_2_0)
780 myGlContext->SetDrawBuffer (GL_BACK);
781 if (myGlContext->core11 != NULL)
783 glMatrixMode (GL_MODELVIEW);
788 // =======================================================================
789 // function : SetSwapInterval
791 // =======================================================================
792 void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
794 const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
795 if (mySwapInterval != aSwapInterval)
797 mySwapInterval = aSwapInterval;
798 myGlContext->SetSwapInterval (mySwapInterval);