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 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient)
38 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
47 // WGL_ARB_pixel_format
48 #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB
49 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
50 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
51 #define WGL_DRAW_TO_BITMAP_ARB 0x2002
52 #define WGL_ACCELERATION_ARB 0x2003
53 #define WGL_NEED_PALETTE_ARB 0x2004
54 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
55 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
56 #define WGL_SWAP_METHOD_ARB 0x2007
57 #define WGL_NUMBER_OVERLAYS_ARB 0x2008
58 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
59 #define WGL_TRANSPARENT_ARB 0x200A
60 #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
61 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
62 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
63 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
64 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
65 #define WGL_SHARE_DEPTH_ARB 0x200C
66 #define WGL_SHARE_STENCIL_ARB 0x200D
67 #define WGL_SHARE_ACCUM_ARB 0x200E
68 #define WGL_SUPPORT_GDI_ARB 0x200F
69 #define WGL_SUPPORT_OPENGL_ARB 0x2010
70 #define WGL_DOUBLE_BUFFER_ARB 0x2011
71 #define WGL_STEREO_ARB 0x2012
72 #define WGL_PIXEL_TYPE_ARB 0x2013
73 #define WGL_COLOR_BITS_ARB 0x2014
74 #define WGL_RED_BITS_ARB 0x2015
75 #define WGL_RED_SHIFT_ARB 0x2016
76 #define WGL_GREEN_BITS_ARB 0x2017
77 #define WGL_GREEN_SHIFT_ARB 0x2018
78 #define WGL_BLUE_BITS_ARB 0x2019
79 #define WGL_BLUE_SHIFT_ARB 0x201A
80 #define WGL_ALPHA_BITS_ARB 0x201B
81 #define WGL_ALPHA_SHIFT_ARB 0x201C
82 #define WGL_ACCUM_BITS_ARB 0x201D
83 #define WGL_ACCUM_RED_BITS_ARB 0x201E
84 #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
85 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
86 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
87 #define WGL_DEPTH_BITS_ARB 0x2022
88 #define WGL_STENCIL_BITS_ARB 0x2023
89 #define WGL_AUX_BUFFERS_ARB 0x2024
91 #define WGL_NO_ACCELERATION_ARB 0x2025
92 #define WGL_GENERIC_ACCELERATION_ARB 0x2026
93 #define WGL_FULL_ACCELERATION_ARB 0x2027
95 #define WGL_SWAP_EXCHANGE_ARB 0x2028
96 #define WGL_SWAP_COPY_ARB 0x2029
97 #define WGL_SWAP_UNDEFINED_ARB 0x202A
99 #define WGL_TYPE_RGBA_ARB 0x202B
100 #define WGL_TYPE_COLORINDEX_ARB 0x202C
101 #endif // WGL_NUMBER_PIXEL_FORMATS_ARB
103 // WGL_ARB_create_context_profile
104 #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
105 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
106 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
107 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
108 #define WGL_CONTEXT_FLAGS_ARB 0x2094
109 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
111 // WGL_CONTEXT_FLAGS bits
112 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
113 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
115 // WGL_CONTEXT_PROFILE_MASK_ARB bits
116 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
117 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
118 #endif // WGL_CONTEXT_MAJOR_VERSION_ARB
120 static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
122 return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
126 // GLX_ARB_create_context
127 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
128 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
129 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
130 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
131 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
132 #define GLX_CONTEXT_FLAGS_ARB 0x2094
134 // GLX_ARB_create_context_profile
135 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
136 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
137 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
140 //! Dummy XError handler which just skips errors
141 static int xErrorDummyHandler (Display* /*theDisplay*/,
142 XErrorEvent* /*theErrorEvent*/)
147 //! Auxiliary method to format list.
148 static void addMsgToList (TCollection_ExtendedString& theList,
149 const TCollection_ExtendedString& theMsg)
151 if (!theList.IsEmpty())
161 // =======================================================================
162 // function : OpenGl_Window
164 // =======================================================================
165 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
166 const Handle(Aspect_Window)& thePlatformWindow,
167 Aspect_RenderingContext theGContext,
168 const Handle(OpenGl_Caps)& theCaps,
169 const Handle(OpenGl_Context)& theShareCtx)
170 : myGlContext (new OpenGl_Context (theCaps)),
171 myOwnGContext (theGContext == 0),
172 myPlatformWindow (thePlatformWindow),
173 mySwapInterval (theCaps->swapInterval)
175 myPlatformWindow->Size (myWidth, myHeight);
177 Standard_Boolean isCoreProfile = Standard_False;
179 #if defined(HAVE_EGL)
180 EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
181 EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
182 EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
183 if (anEglDisplay == EGL_NO_DISPLAY
184 || anEglContext == EGL_NO_CONTEXT
185 || (anEglConfig == NULL
186 && (EGLContext )theGContext == EGL_NO_CONTEXT))
188 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
192 EGLSurface anEglSurf = EGL_NO_SURFACE;
193 if ((EGLContext )theGContext == EGL_NO_CONTEXT)
195 // create new surface
196 anEglSurf = eglCreateWindowSurface (anEglDisplay,
198 (EGLNativeWindowType )myPlatformWindow->NativeHandle(),
200 if (anEglSurf == EGL_NO_SURFACE)
202 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create surface for window!");
206 else if (theGContext != anEglContext)
208 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is used in unsupported combination!");
213 anEglSurf = eglGetCurrentSurface(EGL_DRAW);
214 if (anEglSurf == EGL_NO_SURFACE)
216 // window-less EGL context (off-screen)
217 //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
218 if (anEglConfig != NULL)
220 const int aSurfAttribs[] =
223 EGL_HEIGHT, myHeight,
226 anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
227 if (anEglSurf == EGL_NO_SURFACE)
229 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
232 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
233 "OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
237 myGlContext->Init ((Aspect_Drawable )anEglSurf, (Aspect_Display )anEglDisplay, (Aspect_RenderingContext )anEglContext, isCoreProfile);
238 #elif defined(_WIN32)
240 HWND aWindow = (HWND )myPlatformWindow->NativeHandle();
241 HDC aWindowDC = GetDC (aWindow);
242 HGLRC aGContext = (HGLRC )theGContext;
244 PIXELFORMATDESCRIPTOR aPixelFrmt;
245 memset (&aPixelFrmt, 0, sizeof(aPixelFrmt));
246 aPixelFrmt.nSize = sizeof(PIXELFORMATDESCRIPTOR);
247 aPixelFrmt.nVersion = 1;
248 aPixelFrmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
249 aPixelFrmt.iPixelType = PFD_TYPE_RGBA;
250 aPixelFrmt.cColorBits = 24;
251 aPixelFrmt.cDepthBits = 24;
252 aPixelFrmt.cStencilBits = 8;
253 aPixelFrmt.iLayerType = PFD_MAIN_PLANE;
254 if (theCaps->contextStereo)
256 aPixelFrmt.dwFlags |= PFD_STEREO;
259 int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
261 // in case of failure try without stereo if any
262 const Standard_Boolean hasStereo = aPixelFrmtId != 0 && theCaps->contextStereo;
263 if (aPixelFrmtId == 0 && theCaps->contextStereo)
265 TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: "
266 "ChoosePixelFormat is unable to find stereo supported pixel format. "
267 "Choosing similar non stereo format.");
268 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
270 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
272 aPixelFrmt.dwFlags &= ~PFD_STEREO;
273 aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt);
276 if (aPixelFrmtId == 0)
278 ReleaseDC (aWindow, aWindowDC);
280 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
281 aMsg += (int )GetLastError();
282 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
286 DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
288 HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
289 if (aGContext == NULL)
291 // create temporary context to retrieve advanced context creation procedures
292 HMODULE aModule = GetModuleHandleW(NULL);
293 WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
294 aClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
295 aClass.lpfnWndProc = wndProcDummy;
296 aClass.hInstance = aModule;
297 aClass.lpszClassName = L"OpenGl_WindowTmp";
299 HDC aDevCtxTmp = NULL;
300 HGLRC aRendCtxTmp = NULL;
301 if ((!theCaps->contextDebug && !theCaps->contextNoAccel && theCaps->contextCompatible)
302 || RegisterClassW (&aClass) == 0)
304 aClass.lpszClassName = NULL;
306 if (aClass.lpszClassName != NULL)
308 DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
309 #if (_WIN32_WINNT >= 0x0500)
310 anExStyle |= WS_EX_NOACTIVATE;
312 aWinTmp = CreateWindowExW(anExStyle,
313 aClass.lpszClassName, L"OpenGl_WindowTmp",
314 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
316 NULL, NULL, aModule, NULL);
320 aDevCtxTmp = GetDC (aWinTmp);
321 SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
322 aRendCtxTmp = wglCreateContext (aDevCtxTmp);
325 typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx,
326 const int* theIntAttribs,
327 const float* theFloatAttribs,
328 unsigned int theMaxFormats,
330 unsigned int* theNumFormatsOut);
331 typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx,
332 HGLRC theShareContext,
333 const int* theAttribs);
334 wglChoosePixelFormatARB_t aChoosePixProc = NULL;
335 wglCreateContextAttribsARB_t aCreateCtxProc = NULL;
336 if (aRendCtxTmp != NULL)
338 wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
340 typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
341 wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB");
342 const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL;
343 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
345 aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
347 if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
349 aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
353 // choose extended pixel format
354 if (aChoosePixProc != NULL)
356 const int aPixAttribs[] =
358 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
359 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
360 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
361 WGL_STEREO_ARB, hasStereo ? GL_TRUE : GL_FALSE,
362 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
363 //WGL_SAMPLE_BUFFERS_ARB, 1,
364 //WGL_SAMPLES_ARB, 8,
365 WGL_COLOR_BITS_ARB, 24,
366 WGL_DEPTH_BITS_ARB, 24,
367 WGL_STENCIL_BITS_ARB, 8,
368 WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB,
371 unsigned int aFrmtsNb = 0;
372 aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb);
375 // setup pixel format - may be set only once per window
376 if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt))
378 ReleaseDC (aWindow, aWindowDC);
380 TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
381 aMsg += (int )GetLastError();
382 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
386 // create GL context with extra options
387 if (aCreateCtxProc != NULL)
389 if (!theCaps->contextCompatible)
391 int aCoreCtxAttribs[] =
393 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
394 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
395 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
396 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
400 // Try to create the core profile of highest OpenGL version supported by OCCT
401 // (this will be done automatically by some drivers when requesting 3.2,
402 // but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations).
403 for (int aLowVer4 = 5; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
405 aCoreCtxAttribs[1] = 4;
406 aCoreCtxAttribs[3] = aLowVer4;
407 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
409 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
411 aCoreCtxAttribs[1] = 3;
412 aCoreCtxAttribs[3] = aLowVer3;
413 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCoreCtxAttribs);
415 isCoreProfile = aGContext != NULL;
418 if (aGContext == NULL)
422 // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
423 // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
424 //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
425 WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
428 isCoreProfile = Standard_False;
429 aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
431 if (aGContext != NULL
432 && !theCaps->contextCompatible)
434 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
435 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
439 if (aGContext != NULL)
445 if (aRendCtxTmp != NULL)
447 wglDeleteContext (aRendCtxTmp);
449 if (aDevCtxTmp != NULL)
451 ReleaseDC (aWinTmp, aDevCtxTmp);
455 DestroyWindow (aWinTmp);
457 if (aClass.lpszClassName != NULL)
459 UnregisterClassW (aClass.lpszClassName, aModule);
462 if (aGContext == NULL)
464 // create context using obsolete functionality
465 aGContext = wglCreateContext (aWindowDC);
467 if (aGContext == NULL)
469 ReleaseDC (aWindow, aWindowDC);
471 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
472 aMsg += (int )GetLastError();
473 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
478 // all GL context within one OpenGl_GraphicDriver should be shared!
479 if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
481 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
482 aMsg += (int )GetLastError();
483 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
487 myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
489 Window aWindow = (Window )myPlatformWindow->NativeHandle();
490 Display* aDisp = theDriver->GetDisplayConnection()->GetDisplay();
491 GLXContext aGContext = (GLXContext )theGContext;
492 GLXContext aSlaveCtx = !theShareCtx.IsNull() ? (GLXContext )theShareCtx->myGContext : NULL;
494 XWindowAttributes aWinAttribs;
495 XGetWindowAttributes (aDisp, aWindow, &aWinAttribs);
496 XVisualInfo aVisInfo;
497 aVisInfo.visualid = aWinAttribs.visual->visualid;
498 aVisInfo.screen = DefaultScreen (aDisp);
500 std::unique_ptr<XVisualInfo, int(*)(void*)> aVis (XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfo, &aNbItems), &XFree);
502 if (aVis.get() == NULL)
504 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
507 else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
509 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
513 // create new context
514 GLXFBConfig anFBConfig = myPlatformWindow->NativeFBConfig();
515 const char* aGlxExts = glXQueryExtensionsString (aDisp, aVisInfo.screen);
517 && anFBConfig != NULL
518 && OpenGl_Context::CheckExtension (aGlxExts, "GLX_ARB_create_context_profile"))
520 // Replace default XError handler to ignore errors.
521 // Warning - this is global for all threads!
522 typedef int (*xerrorhandler_t)(Display* , XErrorEvent* );
523 xerrorhandler_t anOldHandler = XSetErrorHandler(xErrorDummyHandler);
525 typedef GLXContext (*glXCreateContextAttribsARB_t)(Display* dpy, GLXFBConfig config,
526 GLXContext share_context, Bool direct,
527 const int* attrib_list);
528 glXCreateContextAttribsARB_t aCreateCtxProc = (glXCreateContextAttribsARB_t )glXGetProcAddress((const GLubyte* )"glXCreateContextAttribsARB");
529 if (!theCaps->contextCompatible)
531 int aCoreCtxAttribs[] =
533 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
534 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
535 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
536 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
540 // try to create the core profile of highest OpenGL version supported by OCCT
541 for (int aLowVer4 = 5; aLowVer4 >= 0 && aGContext == NULL; --aLowVer4)
543 aCoreCtxAttribs[1] = 4;
544 aCoreCtxAttribs[3] = aLowVer4;
545 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
547 for (int aLowVer3 = 3; aLowVer3 >= 2 && aGContext == NULL; --aLowVer3)
549 aCoreCtxAttribs[1] = 3;
550 aCoreCtxAttribs[3] = aLowVer3;
551 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCoreCtxAttribs);
553 isCoreProfile = aGContext != NULL;
556 if (aGContext == NULL)
560 GLX_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0,
563 isCoreProfile = Standard_False;
564 aGContext = aCreateCtxProc (aDisp, anFBConfig, aSlaveCtx, True, aCtxAttribs);
566 if (aGContext != NULL
567 && !theCaps->contextCompatible)
569 TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
570 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
573 XSetErrorHandler(anOldHandler);
577 && aGContext == NULL)
579 aGContext = glXCreateContext (aDisp, aVis.get(), aSlaveCtx, GL_TRUE);
580 if (aGContext == NULL)
582 throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
587 // check Visual for OpenGl context's parameters compatibility
588 TCollection_ExtendedString aList;
589 int isDoubleBuffer = 0, isRGBA = 0, isStereo = 0;
590 int aDepthSize = 0, aStencilSize = 0;
591 glXGetConfig (aDisp, aVis.get(), GLX_RGBA, &isRGBA);
592 glXGetConfig (aDisp, aVis.get(), GLX_DOUBLEBUFFER, &isDoubleBuffer);
593 glXGetConfig (aDisp, aVis.get(), GLX_STEREO, &isStereo);
594 glXGetConfig (aDisp, aVis.get(), GLX_DEPTH_SIZE, &aDepthSize);
595 glXGetConfig (aDisp, aVis.get(), GLX_STENCIL_SIZE, &aStencilSize);
596 if (aDepthSize < 1) addMsgToList (aList, "no depth buffer");
597 if (aStencilSize < 1) addMsgToList (aList, "no stencil buffer");
598 if (isRGBA == 0) addMsgToList (aList, "no RGBA color buffer");
599 if (isDoubleBuffer == 0) addMsgToList (aList, "no Double Buffer");
600 if (theCaps->contextStereo && isStereo == 0)
602 addMsgToList (aList, "no Quad Buffer");
604 else if (!theCaps->contextStereo && isStereo == 1)
606 addMsgToList (aList, "extra Quad Buffer");
608 if (!aList.IsEmpty())
610 TCollection_ExtendedString aMsg = TCollection_ExtendedString ("OpenGl_Window::CreateWindow: window Visual is incomplete: ") + aList;
611 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
613 0, GL_DEBUG_SEVERITY_MEDIUM, aMsg);
616 myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext, isCoreProfile);
618 myGlContext->Share (theShareCtx);
619 myGlContext->SetSwapInterval (mySwapInterval);
623 // =======================================================================
624 // function : ~OpenGl_Window
626 // =======================================================================
627 OpenGl_Window::~OpenGl_Window()
630 || myGlContext.IsNull())
632 myGlContext.Nullify();
636 // release "GL" context if it is owned by window
637 // Mesa implementation can fail to destroy GL context if it set for current thread.
638 // It should be safer to unset thread GL context before its destruction.
639 #if defined(HAVE_EGL)
640 if ((EGLSurface )myGlContext->myWindow != EGL_NO_SURFACE)
642 eglDestroySurface ((EGLDisplay )myGlContext->myDisplay,
643 (EGLSurface )myGlContext->myWindow);
645 #elif defined(_WIN32)
646 HWND aWindow = (HWND )myGlContext->myWindow;
647 HDC aWindowDC = (HDC )myGlContext->myWindowDC;
648 HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext;
649 HGLRC aThreadGContext = wglGetCurrentContext();
650 myGlContext.Nullify();
652 if (aThreadGContext != NULL)
654 if (aThreadGContext == aWindowGContext)
656 wglMakeCurrent (NULL, NULL);
659 wglDeleteContext (aWindowGContext);
661 ReleaseDC (aWindow, aWindowDC);
663 Display* aDisplay = (Display* )myGlContext->myDisplay;
664 GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext;
665 GLXContext aThreadGContext = glXGetCurrentContext();
666 myGlContext.Nullify();
668 if (aDisplay != NULL)
670 if (aThreadGContext == aWindowGContext)
672 glXMakeCurrent (aDisplay, None, NULL);
675 // FSXXX sync necessary if non-direct rendering
677 glXDestroyContext (aDisplay, aWindowGContext);
684 // =======================================================================
685 // function : Activate
687 // =======================================================================
688 Standard_Boolean OpenGl_Window::Activate()
690 return myGlContext->MakeCurrent();
693 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
695 // =======================================================================
697 // purpose : call_subr_resize
698 // =======================================================================
699 void OpenGl_Window::Resize()
701 #if !defined(_WIN32) && !defined(HAVE_EGL)
702 Display* aDisp = (Display* )myGlContext->myDisplay;
707 Standard_Integer aWidth = 0;
708 Standard_Integer aHeight = 0;
709 myPlatformWindow->Size (aWidth, aHeight);
711 // If the size is not changed - do nothing
712 if ((myWidth == aWidth) && (myHeight == aHeight))
718 #if !defined(_WIN32) && !defined(HAVE_EGL)
719 XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
720 XSync (aDisp, False);
726 // =======================================================================
729 // =======================================================================
730 void OpenGl_Window::Init()
735 #if defined(HAVE_EGL)
736 if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
738 // define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
739 // note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
740 // for offscreen rendering on bugged OpenGL ES drivers
741 Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
742 if (!aDefFbo.IsNull())
744 aDefFbo->Release (myGlContext.operator->());
748 aDefFbo = new OpenGl_FrameBuffer();
751 if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
753 TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
754 throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
756 myGlContext->SetDefaultFrameBuffer (aDefFbo);
757 aDefFbo->BindBuffer (myGlContext);
759 else if (!myPlatformWindow->IsVirtual())
761 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
762 eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
764 #elif defined(_WIN32)
769 unsigned int aDummyU;
770 unsigned int aNewWidth = 0;
771 unsigned int aNewHeight = 0;
772 Display* aDisp = (Display* )myGlContext->myDisplay;
773 XGetGeometry (aDisp, myGlContext->myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU);
775 myHeight = aNewHeight;
778 glDisable (GL_DITHER);
779 glDisable (GL_SCISSOR_TEST);
780 const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
781 myGlContext->ResizeViewport (aViewport);
782 #if !defined(GL_ES_VERSION_2_0)
783 myGlContext->SetDrawBuffer (GL_BACK);
784 if (myGlContext->core11 != NULL)
786 glMatrixMode (GL_MODELVIEW);
791 // =======================================================================
792 // function : SetSwapInterval
794 // =======================================================================
795 void OpenGl_Window::SetSwapInterval()
797 if (mySwapInterval != myGlContext->caps->swapInterval)
799 mySwapInterval = myGlContext->caps->swapInterval;
800 myGlContext->SetSwapInterval (mySwapInterval);