| 1 | // Created on: 2011-09-20 |
| 2 | // Created by: Sergey ZERCHANINOV |
| 3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
| 4 | // |
| 5 | // This file is part of Open CASCADE Technology software library. |
| 6 | // |
| 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. |
| 12 | // |
| 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
| 14 | // commercial license or contractual agreement. |
| 15 | |
| 16 | #include <OpenGl_GlCore12.hxx> |
| 17 | |
| 18 | #include <InterfaceGraphic.hxx> |
| 19 | |
| 20 | #include <OpenGl_Window.hxx> |
| 21 | |
| 22 | #include <OpenGl_Context.hxx> |
| 23 | |
| 24 | #include <Aspect_GraphicDeviceDefinitionError.hxx> |
| 25 | #include <TCollection_AsciiString.hxx> |
| 26 | #include <TCollection_ExtendedString.hxx> |
| 27 | |
| 28 | IMPLEMENT_STANDARD_HANDLE(OpenGl_Window,MMgt_TShared) |
| 29 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Window,MMgt_TShared) |
| 30 | |
| 31 | #if !defined(__APPLE__) || defined(MACOSX_USE_GLX) |
| 32 | |
| 33 | namespace |
| 34 | { |
| 35 | static const TEL_COLOUR THE_DEFAULT_BG_COLOR = { { 0.F, 0.F, 0.F, 1.F } }; |
| 36 | |
| 37 | #if defined(_WIN32) |
| 38 | |
| 39 | // WGL_ARB_pixel_format |
| 40 | #ifndef WGL_NUMBER_PIXEL_FORMATS_ARB |
| 41 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 |
| 42 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 |
| 43 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 |
| 44 | #define WGL_ACCELERATION_ARB 0x2003 |
| 45 | #define WGL_NEED_PALETTE_ARB 0x2004 |
| 46 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 |
| 47 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 |
| 48 | #define WGL_SWAP_METHOD_ARB 0x2007 |
| 49 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 |
| 50 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 |
| 51 | #define WGL_TRANSPARENT_ARB 0x200A |
| 52 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 |
| 53 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 |
| 54 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 |
| 55 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A |
| 56 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B |
| 57 | #define WGL_SHARE_DEPTH_ARB 0x200C |
| 58 | #define WGL_SHARE_STENCIL_ARB 0x200D |
| 59 | #define WGL_SHARE_ACCUM_ARB 0x200E |
| 60 | #define WGL_SUPPORT_GDI_ARB 0x200F |
| 61 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 |
| 62 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 |
| 63 | #define WGL_STEREO_ARB 0x2012 |
| 64 | #define WGL_PIXEL_TYPE_ARB 0x2013 |
| 65 | #define WGL_COLOR_BITS_ARB 0x2014 |
| 66 | #define WGL_RED_BITS_ARB 0x2015 |
| 67 | #define WGL_RED_SHIFT_ARB 0x2016 |
| 68 | #define WGL_GREEN_BITS_ARB 0x2017 |
| 69 | #define WGL_GREEN_SHIFT_ARB 0x2018 |
| 70 | #define WGL_BLUE_BITS_ARB 0x2019 |
| 71 | #define WGL_BLUE_SHIFT_ARB 0x201A |
| 72 | #define WGL_ALPHA_BITS_ARB 0x201B |
| 73 | #define WGL_ALPHA_SHIFT_ARB 0x201C |
| 74 | #define WGL_ACCUM_BITS_ARB 0x201D |
| 75 | #define WGL_ACCUM_RED_BITS_ARB 0x201E |
| 76 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F |
| 77 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 |
| 78 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 |
| 79 | #define WGL_DEPTH_BITS_ARB 0x2022 |
| 80 | #define WGL_STENCIL_BITS_ARB 0x2023 |
| 81 | #define WGL_AUX_BUFFERS_ARB 0x2024 |
| 82 | |
| 83 | #define WGL_NO_ACCELERATION_ARB 0x2025 |
| 84 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 |
| 85 | #define WGL_FULL_ACCELERATION_ARB 0x2027 |
| 86 | |
| 87 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 |
| 88 | #define WGL_SWAP_COPY_ARB 0x2029 |
| 89 | #define WGL_SWAP_UNDEFINED_ARB 0x202A |
| 90 | |
| 91 | #define WGL_TYPE_RGBA_ARB 0x202B |
| 92 | #define WGL_TYPE_COLORINDEX_ARB 0x202C |
| 93 | #endif // WGL_NUMBER_PIXEL_FORMATS_ARB |
| 94 | |
| 95 | // WGL_ARB_create_context_profile |
| 96 | #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB |
| 97 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 |
| 98 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 |
| 99 | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 |
| 100 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 |
| 101 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 |
| 102 | |
| 103 | // WGL_CONTEXT_FLAGS bits |
| 104 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 |
| 105 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 |
| 106 | |
| 107 | // WGL_CONTEXT_PROFILE_MASK_ARB bits |
| 108 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 |
| 109 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 |
| 110 | #endif // WGL_CONTEXT_MAJOR_VERSION_ARB |
| 111 | |
| 112 | static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL) |
| 113 | { |
| 114 | return DefWindowProcW (theWin, theMsg, theParamW, theParamL); |
| 115 | } |
| 116 | #else |
| 117 | static Bool WaitForNotify (Display* theDisp, XEvent* theEv, char* theArg) |
| 118 | { |
| 119 | return (theEv->type == MapNotify) && (theEv->xmap.window == (Window )theArg); |
| 120 | } |
| 121 | #endif |
| 122 | |
| 123 | } |
| 124 | |
| 125 | // ======================================================================= |
| 126 | // function : OpenGl_Window |
| 127 | // purpose : |
| 128 | // ======================================================================= |
| 129 | OpenGl_Window::OpenGl_Window (const Handle(Aspect_DisplayConnection)& theDisplayConnection, |
| 130 | const CALL_DEF_WINDOW& theCWindow, |
| 131 | Aspect_RenderingContext theGContext, |
| 132 | const Handle(OpenGl_Caps)& theCaps, |
| 133 | const Handle(OpenGl_Context)& theShareCtx) |
| 134 | : myGlContext (new OpenGl_Context (theCaps)), |
| 135 | myOwnGContext (theGContext == 0), |
| 136 | myWidth ((Standard_Integer )theCWindow.dx), |
| 137 | myHeight ((Standard_Integer )theCWindow.dy), |
| 138 | myBgColor (THE_DEFAULT_BG_COLOR) |
| 139 | { |
| 140 | myBgColor.rgb[0] = theCWindow.Background.r; |
| 141 | myBgColor.rgb[1] = theCWindow.Background.g; |
| 142 | myBgColor.rgb[2] = theCWindow.Background.b; |
| 143 | |
| 144 | #if defined(_WIN32) |
| 145 | (void )theDisplayConnection; |
| 146 | HWND aWindow = (HWND )theCWindow.XWindow; |
| 147 | HDC aWindowDC = GetDC (aWindow); |
| 148 | HGLRC aGContext = (HGLRC )theGContext; |
| 149 | |
| 150 | PIXELFORMATDESCRIPTOR aPixelFrmt; |
| 151 | memset (&aPixelFrmt, 0, sizeof(aPixelFrmt)); |
| 152 | aPixelFrmt.nSize = sizeof(PIXELFORMATDESCRIPTOR); |
| 153 | aPixelFrmt.nVersion = 1; |
| 154 | aPixelFrmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; |
| 155 | aPixelFrmt.iPixelType = PFD_TYPE_RGBA; |
| 156 | aPixelFrmt.cColorBits = 24; |
| 157 | aPixelFrmt.cDepthBits = 24; |
| 158 | aPixelFrmt.cStencilBits = 8; |
| 159 | aPixelFrmt.iLayerType = PFD_MAIN_PLANE; |
| 160 | if (theCaps->contextStereo) |
| 161 | { |
| 162 | aPixelFrmt.dwFlags |= PFD_STEREO; |
| 163 | } |
| 164 | |
| 165 | int aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt); |
| 166 | |
| 167 | // in case of failure try without stereo if any |
| 168 | if (aPixelFrmtId == 0 && theCaps->contextStereo) |
| 169 | { |
| 170 | TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: " |
| 171 | "ChoosePixelFormat is unable to find stereo supported pixel format. " |
| 172 | "Choosing similar non stereo format."); |
| 173 | myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, |
| 174 | GL_DEBUG_TYPE_OTHER_ARB, |
| 175 | 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg); |
| 176 | |
| 177 | aPixelFrmt.dwFlags &= ~PFD_STEREO; |
| 178 | aPixelFrmtId = ChoosePixelFormat (aWindowDC, &aPixelFrmt); |
| 179 | } |
| 180 | |
| 181 | if (aPixelFrmtId == 0) |
| 182 | { |
| 183 | ReleaseDC (aWindow, aWindowDC); |
| 184 | |
| 185 | TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: "); |
| 186 | aMsg += (int )GetLastError(); |
| 187 | Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString()); |
| 188 | return; |
| 189 | } |
| 190 | |
| 191 | DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt); |
| 192 | |
| 193 | HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL; |
| 194 | if (aGContext == NULL) |
| 195 | { |
| 196 | // create temporary context to retrieve advanced context creation procedures |
| 197 | HMODULE aModule = GetModuleHandleW(NULL); |
| 198 | WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass)); |
| 199 | aClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; |
| 200 | aClass.lpfnWndProc = wndProcDummy; |
| 201 | aClass.hInstance = aModule; |
| 202 | aClass.lpszClassName = L"OpenGl_WindowTmp"; |
| 203 | HWND aWinTmp = NULL; |
| 204 | HDC aDevCtxTmp = NULL; |
| 205 | HGLRC aRendCtxTmp = NULL; |
| 206 | if ((!theCaps->contextDebug && !theCaps->contextNoAccel) |
| 207 | || RegisterClassW (&aClass) == 0) |
| 208 | { |
| 209 | aClass.lpszClassName = NULL; |
| 210 | } |
| 211 | if (aClass.lpszClassName != NULL) |
| 212 | { |
| 213 | DWORD anExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE; |
| 214 | #if (_WIN32_WINNT >= 0x0500) |
| 215 | anExStyle |= WS_EX_NOACTIVATE; |
| 216 | #endif |
| 217 | aWinTmp = CreateWindowExW(anExStyle, |
| 218 | aClass.lpszClassName, L"OpenGl_WindowTmp", |
| 219 | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED, |
| 220 | 2, 2, 4, 4, |
| 221 | NULL, NULL, aModule, NULL); |
| 222 | } |
| 223 | if (aWinTmp != NULL) |
| 224 | { |
| 225 | aDevCtxTmp = GetDC (aWinTmp); |
| 226 | SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt); |
| 227 | aRendCtxTmp = wglCreateContext (aDevCtxTmp); |
| 228 | } |
| 229 | |
| 230 | typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx, |
| 231 | const int* theIntAttribs, |
| 232 | const float* theFloatAttribs, |
| 233 | unsigned int theMaxFormats, |
| 234 | int* theFormatsOut, |
| 235 | unsigned int* theNumFormatsOut); |
| 236 | typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx, |
| 237 | HGLRC theShareContext, |
| 238 | const int* theAttribs); |
| 239 | wglChoosePixelFormatARB_t aChoosePixProc = NULL; |
| 240 | wglCreateContextAttribsARB_t aCreateCtxProc = NULL; |
| 241 | if (aRendCtxTmp != NULL) |
| 242 | { |
| 243 | wglMakeCurrent (aDevCtxTmp, aRendCtxTmp); |
| 244 | |
| 245 | typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext); |
| 246 | wglGetExtensionsStringARB_t aGetExtensions = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB"); |
| 247 | const char* aWglExts = (aGetExtensions != NULL) ? aGetExtensions (wglGetCurrentDC()) : NULL; |
| 248 | if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_pixel_format")) |
| 249 | { |
| 250 | aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB"); |
| 251 | } |
| 252 | if (OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile")) |
| 253 | { |
| 254 | aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB"); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | // choose extended pixel format |
| 259 | if (aChoosePixProc != NULL) |
| 260 | { |
| 261 | const int aPixAttribs[] = |
| 262 | { |
| 263 | WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, |
| 264 | WGL_SUPPORT_OPENGL_ARB, GL_TRUE, |
| 265 | WGL_DOUBLE_BUFFER_ARB, GL_TRUE, |
| 266 | WGL_STEREO_ARB, theCaps->contextStereo ? GL_TRUE : GL_FALSE, |
| 267 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, |
| 268 | //WGL_SAMPLE_BUFFERS_ARB, 1, |
| 269 | //WGL_SAMPLES_ARB, 8, |
| 270 | WGL_COLOR_BITS_ARB, 24, |
| 271 | WGL_DEPTH_BITS_ARB, 24, |
| 272 | WGL_STENCIL_BITS_ARB, 8, |
| 273 | WGL_ACCELERATION_ARB, theCaps->contextNoAccel ? WGL_NO_ACCELERATION_ARB : WGL_FULL_ACCELERATION_ARB, |
| 274 | 0, 0, |
| 275 | }; |
| 276 | unsigned int aFrmtsNb = 0; |
| 277 | aChoosePixProc (aWindowDC, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb); |
| 278 | } |
| 279 | |
| 280 | // setup pixel format - may be set only once per window |
| 281 | if (!SetPixelFormat (aWindowDC, aPixelFrmtId, &aPixelFrmt)) |
| 282 | { |
| 283 | ReleaseDC (aWindow, aWindowDC); |
| 284 | |
| 285 | TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: "); |
| 286 | aMsg += (int )GetLastError(); |
| 287 | Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString()); |
| 288 | return; |
| 289 | } |
| 290 | |
| 291 | // create GL context with extra options |
| 292 | if (aCreateCtxProc != NULL) |
| 293 | { |
| 294 | // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified |
| 295 | // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB. |
| 296 | int aCtxAttribs[] = |
| 297 | { |
| 298 | //WGL_CONTEXT_MAJOR_VERSION_ARB, 3, |
| 299 | //WGL_CONTEXT_MINOR_VERSION_ARB, 2, |
| 300 | //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB, |
| 301 | WGL_CONTEXT_FLAGS_ARB, theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, |
| 302 | 0, 0 |
| 303 | }; |
| 304 | |
| 305 | aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs); |
| 306 | if (aGContext != NULL) |
| 307 | { |
| 308 | aSlaveCtx = NULL; |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | if (aRendCtxTmp != NULL) |
| 313 | { |
| 314 | wglDeleteContext (aRendCtxTmp); |
| 315 | } |
| 316 | if (aDevCtxTmp != NULL) |
| 317 | { |
| 318 | ReleaseDC (aWinTmp, aDevCtxTmp); |
| 319 | } |
| 320 | if (aWinTmp != NULL) |
| 321 | { |
| 322 | DestroyWindow (aWinTmp); |
| 323 | } |
| 324 | if (aClass.lpszClassName != NULL) |
| 325 | { |
| 326 | UnregisterClassW (aClass.lpszClassName, aModule); |
| 327 | } |
| 328 | |
| 329 | if (aGContext == NULL) |
| 330 | { |
| 331 | // create context using obsolete functionality |
| 332 | aGContext = wglCreateContext (aWindowDC); |
| 333 | } |
| 334 | if (aGContext == NULL) |
| 335 | { |
| 336 | ReleaseDC (aWindow, aWindowDC); |
| 337 | |
| 338 | TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: "); |
| 339 | aMsg += (int )GetLastError(); |
| 340 | Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString()); |
| 341 | return; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | // all GL context within one OpenGl_GraphicDriver should be shared! |
| 346 | if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE) |
| 347 | { |
| 348 | TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: "); |
| 349 | aMsg += (int )GetLastError(); |
| 350 | Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString()); |
| 351 | return; |
| 352 | } |
| 353 | |
| 354 | myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext); |
| 355 | #else |
| 356 | Window aParent = (Window )theCWindow.XWindow; |
| 357 | Window aWindow = 0; |
| 358 | |
| 359 | Display* aDisp = theDisplayConnection->GetDisplay(); |
| 360 | GLXContext aGContext = (GLXContext )theGContext; |
| 361 | |
| 362 | XWindowAttributes wattr; |
| 363 | XGetWindowAttributes (aDisp, aParent, &wattr); |
| 364 | const int scr = DefaultScreen (aDisp); |
| 365 | |
| 366 | XVisualInfo* aVis = NULL; |
| 367 | { |
| 368 | unsigned long aVisInfoMask = VisualIDMask | VisualScreenMask; |
| 369 | XVisualInfo aVisInfo; |
| 370 | aVisInfo.visualid = wattr.visual->visualid; |
| 371 | aVisInfo.screen = scr; |
| 372 | int aNbItems; |
| 373 | aVis = XGetVisualInfo (aDisp, aVisInfoMask, &aVisInfo, &aNbItems); |
| 374 | } |
| 375 | |
| 376 | if (!myOwnGContext) |
| 377 | { |
| 378 | if (aVis != NULL) |
| 379 | { |
| 380 | Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: XGetVisualInfo failed."); |
| 381 | return; |
| 382 | } |
| 383 | |
| 384 | aWindow = aParent; |
| 385 | } |
| 386 | else |
| 387 | { |
| 388 | #if defined(__linux) || defined(Linux) || defined(__APPLE__) |
| 389 | if (aVis != NULL) |
| 390 | { |
| 391 | // check Visual for OpenGl context's parameters compability |
| 392 | int isGl = 0, isDoubleBuffer = 0, isRGBA = 0, isStereo = 0; |
| 393 | int aDepthSize = 0, aStencilSize = 0; |
| 394 | |
| 395 | if (glXGetConfig (aDisp, aVis, GLX_USE_GL, &isGl) != 0) |
| 396 | isGl = 0; |
| 397 | |
| 398 | if (glXGetConfig (aDisp, aVis, GLX_RGBA, &isRGBA) != 0) |
| 399 | isRGBA = 0; |
| 400 | |
| 401 | if (glXGetConfig (aDisp, aVis, GLX_DOUBLEBUFFER, &isDoubleBuffer) != 0) |
| 402 | isDoubleBuffer = 0; |
| 403 | |
| 404 | if (glXGetConfig (aDisp, aVis, GLX_STEREO, &isStereo) != 0) |
| 405 | isStereo = 0; |
| 406 | |
| 407 | if (glXGetConfig (aDisp, aVis, GLX_DEPTH_SIZE, &aDepthSize) != 0) |
| 408 | aDepthSize = 0; |
| 409 | |
| 410 | if (glXGetConfig (aDisp, aVis, GLX_STENCIL_SIZE, &aStencilSize) != 0) |
| 411 | aStencilSize = 0; |
| 412 | |
| 413 | if (!isGl || !aDepthSize || !isRGBA || !aStencilSize || |
| 414 | (isDoubleBuffer ? 1 : 0) != 1 || |
| 415 | (isStereo ? 1 : 0) != (theCaps->contextStereo ? 1 : 0)) |
| 416 | { |
| 417 | XFree (aVis); |
| 418 | aVis = NULL; |
| 419 | } |
| 420 | } |
| 421 | #endif |
| 422 | |
| 423 | if (aVis == NULL) |
| 424 | { |
| 425 | int anIter = 0; |
| 426 | int anAttribs[13]; |
| 427 | anAttribs[anIter++] = GLX_RGBA; |
| 428 | |
| 429 | anAttribs[anIter++] = GLX_DEPTH_SIZE; |
| 430 | anAttribs[anIter++] = 1; |
| 431 | |
| 432 | anAttribs[anIter++] = GLX_STENCIL_SIZE; |
| 433 | anAttribs[anIter++] = 1; |
| 434 | |
| 435 | anAttribs[anIter++] = GLX_RED_SIZE; |
| 436 | anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1; |
| 437 | |
| 438 | anAttribs[anIter++] = GLX_GREEN_SIZE; |
| 439 | anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1; |
| 440 | |
| 441 | anAttribs[anIter++] = GLX_BLUE_SIZE; |
| 442 | anAttribs[anIter++] = (wattr.depth <= 8) ? 0 : 1; |
| 443 | |
| 444 | anAttribs[anIter++] = GLX_DOUBLEBUFFER; |
| 445 | |
| 446 | // warning: this flag may be set to None, so it need to be last in anAttribs |
| 447 | Standard_Integer aStereoFlagPos = anIter; |
| 448 | if (theCaps->contextStereo) |
| 449 | anAttribs[anIter++] = GLX_STEREO; |
| 450 | |
| 451 | anAttribs[anIter++] = None; |
| 452 | |
| 453 | aVis = glXChooseVisual (aDisp, scr, anAttribs); |
| 454 | |
| 455 | // in case of failure try without stereo if any |
| 456 | if (aVis == NULL && theCaps->contextStereo) |
| 457 | { |
| 458 | TCollection_ExtendedString aMsg ("OpenGl_Window::CreateWindow: " |
| 459 | "glXChooseVisual is unable to find stereo supported pixel format. " |
| 460 | "Choosing similar non stereo format."); |
| 461 | myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, |
| 462 | GL_DEBUG_TYPE_OTHER_ARB, |
| 463 | 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg); |
| 464 | |
| 465 | anAttribs[aStereoFlagPos] = None; |
| 466 | aVis = glXChooseVisual (aDisp, scr, anAttribs); |
| 467 | } |
| 468 | |
| 469 | if (aVis == NULL) |
| 470 | { |
| 471 | Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXChooseVisual failed."); |
| 472 | return; |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | if (!theShareCtx.IsNull()) |
| 477 | { |
| 478 | // ctx est une copie du previous |
| 479 | aGContext = glXCreateContext (aDisp, aVis, (GLXContext )theShareCtx->myGContext, GL_TRUE); |
| 480 | } |
| 481 | else |
| 482 | { |
| 483 | aGContext = glXCreateContext (aDisp, aVis, NULL, GL_TRUE); |
| 484 | } |
| 485 | |
| 486 | if (!aGContext) |
| 487 | { |
| 488 | Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_Window::CreateWindow: glXCreateContext failed."); |
| 489 | return; |
| 490 | } |
| 491 | |
| 492 | Colormap cmap = XCreateColormap (aDisp, aParent, aVis->visual, AllocNone); |
| 493 | |
| 494 | XColor color; |
| 495 | color.red = (unsigned short) (myBgColor.rgb[0] * 0xFFFF); |
| 496 | color.green = (unsigned short) (myBgColor.rgb[1] * 0xFFFF); |
| 497 | color.blue = (unsigned short) (myBgColor.rgb[2] * 0xFFFF); |
| 498 | color.flags = DoRed | DoGreen | DoBlue; |
| 499 | XAllocColor (aDisp, cmap, &color); |
| 500 | |
| 501 | XSetWindowAttributes cwa; |
| 502 | cwa.colormap = cmap; |
| 503 | cwa.event_mask = StructureNotifyMask; |
| 504 | cwa.border_pixel = color.pixel; |
| 505 | cwa.background_pixel = color.pixel; |
| 506 | |
| 507 | if (aVis->visualid == wattr.visual->visualid) |
| 508 | { |
| 509 | aWindow = aParent; |
| 510 | } |
| 511 | else |
| 512 | { |
| 513 | unsigned long mask = CWBackPixel | CWColormap | CWBorderPixel | CWEventMask; |
| 514 | aWindow = XCreateWindow (aDisp, aParent, 0, 0, myWidth, myHeight, 0/*bw*/, aVis->depth, InputOutput, aVis->visual, mask, &cwa); |
| 515 | } |
| 516 | |
| 517 | XSetWindowBackground (aDisp, aWindow, cwa.background_pixel); |
| 518 | XClearWindow (aDisp, aWindow); |
| 519 | |
| 520 | if (aWindow != aParent) |
| 521 | { |
| 522 | XEvent anEvent; |
| 523 | XMapWindow (aDisp, aWindow); |
| 524 | XIfEvent (aDisp, &anEvent, WaitForNotify, (char* )aWindow); |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | myGlContext->Init ((Aspect_Drawable )aWindow, (Aspect_Display )aDisp, (Aspect_RenderingContext )aGContext); |
| 529 | #endif |
| 530 | myGlContext->Share (theShareCtx); |
| 531 | |
| 532 | Init(); |
| 533 | } |
| 534 | |
| 535 | // ======================================================================= |
| 536 | // function : ~OpenGl_Window |
| 537 | // purpose : |
| 538 | // ======================================================================= |
| 539 | OpenGl_Window::~OpenGl_Window() |
| 540 | { |
| 541 | if (!myOwnGContext) |
| 542 | { |
| 543 | myGlContext.Nullify(); |
| 544 | return; |
| 545 | } |
| 546 | |
| 547 | // release "GL" context if it is owned by window |
| 548 | // Mesa implementation can fail to destroy GL context if it set for current thread. |
| 549 | // It should be safer to unset thread GL context before its destruction. |
| 550 | #if defined(_WIN32) |
| 551 | HWND aWindow = (HWND )myGlContext->myWindow; |
| 552 | HDC aWindowDC = (HDC )myGlContext->myWindowDC; |
| 553 | HGLRC aWindowGContext = (HGLRC )myGlContext->myGContext; |
| 554 | HGLRC aThreadGContext = wglGetCurrentContext(); |
| 555 | myGlContext.Nullify(); |
| 556 | |
| 557 | if (aThreadGContext != NULL) |
| 558 | { |
| 559 | if (aThreadGContext == aWindowGContext) |
| 560 | { |
| 561 | wglMakeCurrent (NULL, NULL); |
| 562 | } |
| 563 | |
| 564 | wglDeleteContext (aWindowGContext); |
| 565 | } |
| 566 | ReleaseDC (aWindow, aWindowDC); |
| 567 | #else |
| 568 | Display* aDisplay = (Display* )myGlContext->myDisplay; |
| 569 | GLXContext aWindowGContext = (GLXContext )myGlContext->myGContext; |
| 570 | GLXContext aThreadGContext = glXGetCurrentContext(); |
| 571 | myGlContext.Nullify(); |
| 572 | |
| 573 | if (aDisplay != NULL) |
| 574 | { |
| 575 | if (aThreadGContext == aWindowGContext) |
| 576 | { |
| 577 | glXMakeCurrent (aDisplay, None, NULL); |
| 578 | } |
| 579 | |
| 580 | // FSXXX sync necessary if non-direct rendering |
| 581 | glXWaitGL(); |
| 582 | glXDestroyContext (aDisplay, aWindowGContext); |
| 583 | } |
| 584 | #endif |
| 585 | } |
| 586 | |
| 587 | #endif // !__APPLE__ |
| 588 | |
| 589 | // ======================================================================= |
| 590 | // function : Activate |
| 591 | // purpose : |
| 592 | // ======================================================================= |
| 593 | Standard_Boolean OpenGl_Window::Activate() |
| 594 | { |
| 595 | return myGlContext->MakeCurrent(); |
| 596 | } |
| 597 | |
| 598 | #if !defined(__APPLE__) || defined(MACOSX_USE_GLX) |
| 599 | |
| 600 | // ======================================================================= |
| 601 | // function : Resize |
| 602 | // purpose : call_subr_resize |
| 603 | // ======================================================================= |
| 604 | void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow) |
| 605 | { |
| 606 | #if !defined(_WIN32) |
| 607 | Display* aDisp = (Display* )myGlContext->myDisplay; |
| 608 | if (aDisp == NULL) |
| 609 | return; |
| 610 | #endif |
| 611 | |
| 612 | // If the size is not changed - do nothing |
| 613 | if ((myWidth == theCWindow.dx) && (myHeight == theCWindow.dy)) |
| 614 | return; |
| 615 | |
| 616 | myWidth = (Standard_Integer )theCWindow.dx; |
| 617 | myHeight = (Standard_Integer )theCWindow.dy; |
| 618 | |
| 619 | #if !defined(_WIN32) |
| 620 | XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight); |
| 621 | XSync (aDisp, False); |
| 622 | #endif |
| 623 | |
| 624 | Init(); |
| 625 | } |
| 626 | |
| 627 | #endif // !__APPLE__ |
| 628 | |
| 629 | // ======================================================================= |
| 630 | // function : ReadDepths |
| 631 | // purpose : TelReadDepths |
| 632 | // ======================================================================= |
| 633 | void OpenGl_Window::ReadDepths (const Standard_Integer theX, const Standard_Integer theY, |
| 634 | const Standard_Integer theWidth, const Standard_Integer theHeight, |
| 635 | float* theDepths) |
| 636 | { |
| 637 | if (theDepths == NULL || !Activate()) |
| 638 | return; |
| 639 | |
| 640 | glMatrixMode (GL_PROJECTION); |
| 641 | glLoadIdentity(); |
| 642 | gluOrtho2D (0.0, (GLdouble )myWidth, 0.0, (GLdouble )myHeight); |
| 643 | glMatrixMode (GL_MODELVIEW); |
| 644 | glLoadIdentity(); |
| 645 | |
| 646 | glRasterPos2i (theX, theY); |
| 647 | DisableFeatures(); |
| 648 | glReadPixels (theX, theY, theWidth, theHeight, GL_DEPTH_COMPONENT, GL_FLOAT, theDepths); |
| 649 | EnableFeatures(); |
| 650 | } |
| 651 | |
| 652 | // ======================================================================= |
| 653 | // function : SetBackgroundColor |
| 654 | // purpose : call_subr_set_background |
| 655 | // ======================================================================= |
| 656 | void OpenGl_Window::SetBackgroundColor (const Standard_ShortReal theR, |
| 657 | const Standard_ShortReal theG, |
| 658 | const Standard_ShortReal theB) |
| 659 | { |
| 660 | myBgColor.rgb[0] = theR; |
| 661 | myBgColor.rgb[1] = theG; |
| 662 | myBgColor.rgb[2] = theB; |
| 663 | } |
| 664 | |
| 665 | #if !defined(__APPLE__) || defined(MACOSX_USE_GLX) |
| 666 | |
| 667 | // ======================================================================= |
| 668 | // function : Init |
| 669 | // purpose : |
| 670 | // ======================================================================= |
| 671 | void OpenGl_Window::Init() |
| 672 | { |
| 673 | if (!Activate()) |
| 674 | return; |
| 675 | |
| 676 | #if defined(_WIN32) |
| 677 | RECT cr; |
| 678 | GetClientRect ((HWND )myGlContext->myWindow, &cr); |
| 679 | myWidth = cr.right - cr.left; |
| 680 | myHeight = cr.bottom - cr.top; |
| 681 | #else |
| 682 | Window aRootWin; |
| 683 | int aDummy; |
| 684 | unsigned int aDummyU; |
| 685 | unsigned int aNewWidth = 0; |
| 686 | unsigned int aNewHeight = 0; |
| 687 | Display* aDisp = (Display* )myGlContext->myDisplay; |
| 688 | XGetGeometry (aDisp, myGlContext->myWindow, &aRootWin, &aDummy, &aDummy, &aNewWidth, &aNewHeight, &aDummyU, &aDummyU); |
| 689 | myWidth = aNewWidth; |
| 690 | myHeight = aNewHeight; |
| 691 | #endif |
| 692 | |
| 693 | glMatrixMode (GL_MODELVIEW); |
| 694 | glViewport (0, 0, myWidth, myHeight); |
| 695 | |
| 696 | glDisable (GL_SCISSOR_TEST); |
| 697 | glDrawBuffer (GL_BACK); |
| 698 | } |
| 699 | |
| 700 | #endif // !__APPLE__ |
| 701 | |
| 702 | // ======================================================================= |
| 703 | // function : EnableFeatures |
| 704 | // purpose : |
| 705 | // ======================================================================= |
| 706 | void OpenGl_Window::EnableFeatures() const |
| 707 | { |
| 708 | // |
| 709 | } |
| 710 | |
| 711 | // ======================================================================= |
| 712 | // function : DisableFeatures |
| 713 | // purpose : |
| 714 | // ======================================================================= |
| 715 | void OpenGl_Window::DisableFeatures() const |
| 716 | { |
| 717 | glPixelTransferi (GL_MAP_COLOR, GL_FALSE); |
| 718 | |
| 719 | /* |
| 720 | * Disable stuff that's likely to slow down glDrawPixels. |
| 721 | * (Omit as much of this as possible, when you know in advance |
| 722 | * that the OpenGL state will already be set correctly.) |
| 723 | */ |
| 724 | glDisable(GL_ALPHA_TEST); |
| 725 | glDisable(GL_BLEND); |
| 726 | glDisable(GL_DEPTH_TEST); |
| 727 | glDisable(GL_FOG); |
| 728 | glDisable(GL_LIGHTING); |
| 729 | |
| 730 | glDisable(GL_LOGIC_OP); |
| 731 | glDisable(GL_STENCIL_TEST); |
| 732 | glDisable(GL_TEXTURE_1D); |
| 733 | glDisable(GL_TEXTURE_2D); |
| 734 | glPixelTransferi(GL_MAP_COLOR, GL_FALSE); |
| 735 | glPixelTransferi(GL_RED_SCALE, 1); |
| 736 | glPixelTransferi(GL_RED_BIAS, 0); |
| 737 | glPixelTransferi(GL_GREEN_SCALE, 1); |
| 738 | glPixelTransferi(GL_GREEN_BIAS, 0); |
| 739 | glPixelTransferi(GL_BLUE_SCALE, 1); |
| 740 | glPixelTransferi(GL_BLUE_BIAS, 0); |
| 741 | glPixelTransferi(GL_ALPHA_SCALE, 1); |
| 742 | glPixelTransferi(GL_ALPHA_BIAS, 0); |
| 743 | |
| 744 | /* |
| 745 | * Disable extensions that could slow down glDrawPixels. |
| 746 | * (Actually, you should check for the presence of the proper |
| 747 | * extension before making these calls. I've omitted that |
| 748 | * code for simplicity.) |
| 749 | */ |
| 750 | |
| 751 | if ((myGlContext->myGlVerMajor >= 1) && (myGlContext->myGlVerMinor >= 2)) |
| 752 | { |
| 753 | #ifdef GL_EXT_convolution |
| 754 | if (myGlContext->CheckExtension ("GL_CONVOLUTION_1D_EXT")) |
| 755 | glDisable(GL_CONVOLUTION_1D_EXT); |
| 756 | |
| 757 | if (myGlContext->CheckExtension ("GL_CONVOLUTION_2D_EXT")) |
| 758 | glDisable(GL_CONVOLUTION_2D_EXT); |
| 759 | |
| 760 | if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT")) |
| 761 | glDisable(GL_SEPARABLE_2D_EXT); |
| 762 | #endif |
| 763 | |
| 764 | #ifdef GL_EXT_histogram |
| 765 | if (myGlContext->CheckExtension ("GL_SEPARABLE_2D_EXT")) |
| 766 | glDisable(GL_HISTOGRAM_EXT); |
| 767 | |
| 768 | if (myGlContext->CheckExtension ("GL_MINMAX_EXT")) |
| 769 | glDisable(GL_MINMAX_EXT); |
| 770 | #endif |
| 771 | |
| 772 | #ifdef GL_EXT_texture3D |
| 773 | if (myGlContext->CheckExtension ("GL_TEXTURE_3D_EXT")) |
| 774 | glDisable(GL_TEXTURE_3D_EXT); |
| 775 | #endif |
| 776 | } |
| 777 | } |
| 778 | |
| 779 | // ======================================================================= |
| 780 | // function : MakeFrontBufCurrent |
| 781 | // purpose : TelMakeFrontBufCurrent |
| 782 | // ======================================================================= |
| 783 | void OpenGl_Window::MakeFrontBufCurrent() const |
| 784 | { |
| 785 | glDrawBuffer (GL_FRONT); |
| 786 | } |
| 787 | |
| 788 | // ======================================================================= |
| 789 | // function : MakeBackBufCurrent |
| 790 | // purpose : TelMakeBackBufCurrent |
| 791 | // ======================================================================= |
| 792 | void OpenGl_Window::MakeBackBufCurrent() const |
| 793 | { |
| 794 | glDrawBuffer (GL_BACK); |
| 795 | } |