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