1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkWin32OpenGLRenderWindow.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkWin32OpenGLRenderWindow.h"
16
17 #include "vtkIdList.h"
18 #include "vtkCommand.h"
19 #include "vtkNew.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkOpenGLRenderer.h"
22 #include "vtkOpenGLRenderWindow.h"
23 #include "vtkOpenGLError.h"
24 #include "vtkOpenGLShaderCache.h"
25 #include "vtkOpenGLVertexBufferObjectCache.h"
26 #include "vtkRendererCollection.h"
27 #include "vtkStringOutputWindow.h"
28 #include "vtkWin32RenderWindowInteractor.h"
29
30 #include <cmath>
31 #include <sstream>
32
33 #include "vtkOpenGLError.h"
34
35 // Mouse wheel support
36 // In an ideal world we would just have to include <zmouse.h>, but it is not
37 // always available with all compilers/headers
38 #ifndef WM_MOUSEWHEEL
39 # define WM_MOUSEWHEEL 0x020A
40 #endif //WM_MOUSEWHEEL
41
42 vtkStandardNewMacro(vtkWin32OpenGLRenderWindow);
43
vtkWin32OpenGLRenderWindow()44 vtkWin32OpenGLRenderWindow::vtkWin32OpenGLRenderWindow()
45 {
46 this->ApplicationInstance = nullptr;
47 this->Palette = nullptr;
48 this->ContextId = 0;
49 this->WindowId = 0;
50 this->ParentId = 0;
51 this->NextWindowId = 0;
52 this->DeviceContext = (HDC)0; // hsr
53 this->MFChandledWindow = FALSE; // hsr
54 this->StereoType = VTK_STEREO_CRYSTAL_EYES;
55 this->CursorHidden = 0;
56
57 this->CreatingOffScreenWindow = 0;
58 this->WindowIdReferenceCount = 0;
59 }
60
~vtkWin32OpenGLRenderWindow()61 vtkWin32OpenGLRenderWindow::~vtkWin32OpenGLRenderWindow()
62 {
63 this->Finalize();
64
65 vtkRenderer *ren;
66 vtkCollectionSimpleIterator rit;
67 this->Renderers->InitTraversal(rit);
68 while ( (ren = this->Renderers->GetNextRenderer(rit)) )
69 {
70 ren->SetRenderWindow(nullptr);
71 }
72 }
73
Clean()74 void vtkWin32OpenGLRenderWindow::Clean()
75 {
76 /* finish OpenGL rendering */
77 if (this->OwnContext && this->ContextId)
78 {
79 this->MakeCurrent();
80 this->CleanUpRenderers();
81
82 // Note: wglMakeCurrent(nullptr,nullptr) is valid according to the documentation
83 // and works with nVidia and ATI but not with Intel. Passing an existing
84 // device context works in any case.
85 // see VTK Bug 7119.
86 if(wglMakeCurrent(this->DeviceContext,nullptr)!=TRUE)
87 {
88 vtkErrorMacro("wglMakeCurrent failed in Clean(), error: " << GetLastError());
89 }
90 if (wglDeleteContext(this->ContextId) != TRUE)
91 {
92 vtkErrorMacro("wglDeleteContext failed in Clean(), error: " << GetLastError());
93 }
94 }
95 this->ContextId = nullptr;
96
97 if (this->Palette)
98 {
99 SelectPalette(this->DeviceContext, this->OldPalette, FALSE); // SVA delete the old palette
100 DeleteObject(this->Palette);
101 this->Palette = nullptr;
102 }
103 }
104
CleanUpRenderers()105 void vtkWin32OpenGLRenderWindow::CleanUpRenderers()
106 {
107 // tell each of the renderers that this render window/graphics context
108 // is being removed (the RendererCollection is removed by vtkRenderWindow's
109 // destructor)
110 this->ReleaseGraphicsResources(this);
111 }
112
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)113 LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message,
114 WPARAM wParam,
115 LPARAM lParam)
116 {
117 LRESULT res;
118
119 vtkWin32OpenGLRenderWindow *me =
120 (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,sizeof(vtkLONG));
121
122 if (me && me->GetReferenceCount()>0)
123 {
124 me->Register(me);
125 res = me->MessageProc(hWnd, message, wParam, lParam);
126 me->UnRegister(me);
127 }
128 else
129 {
130 res = DefWindowProc(hWnd, message, wParam, lParam);
131 }
132
133 return res;
134 }
135
SetWindowName(const char * _arg)136 void vtkWin32OpenGLRenderWindow::SetWindowName( const char * _arg )
137 {
138 vtkWindow::SetWindowName(_arg);
139 if (this->WindowId)
140 {
141 #ifdef UNICODE
142 wchar_t *wname = new wchar_t [mbstowcs(nullptr, this->WindowName, 32000)+1];
143 mbstowcs(wname, this->WindowName, 32000);
144 SetWindowText(this->WindowId, wname);
145 delete [] wname;
146 #else
147 SetWindowText(this->WindowId, this->WindowName);
148 #endif
149 }
150 }
151
GetEventPending()152 int vtkWin32OpenGLRenderWindow::GetEventPending()
153 {
154 MSG msg;
155 if (PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_NOREMOVE))
156 {
157 if (msg.message == WM_MOUSEMOVE)
158 {
159 PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE);
160 }
161 if ((msg.message == WM_LBUTTONDOWN) ||
162 (msg.message == WM_RBUTTONDOWN) ||
163 (msg.message == WM_MBUTTONDOWN) ||
164 (msg.message == WM_MOUSEWHEEL))
165 {
166 return 1;
167 }
168 }
169
170 return 0;
171 }
172
173 // ----------------------------------------------------------------------------
InitializeFromCurrentContext()174 bool vtkWin32OpenGLRenderWindow::InitializeFromCurrentContext()
175 {
176 HGLRC currentContext = wglGetCurrentContext();
177 if (currentContext != nullptr)
178 {
179 this->SetWindowId(WindowFromDC(wglGetCurrentDC()));
180 this->SetDeviceContext(wglGetCurrentDC());
181 this->SetContextId(currentContext);
182 return this->Superclass::InitializeFromCurrentContext();
183 }
184 return false;
185 }
186
187 // ----------------------------------------------------------------------------
MakeCurrent()188 void vtkWin32OpenGLRenderWindow::MakeCurrent()
189 {
190 // Try to avoid doing anything (for performance).
191 HGLRC current = wglGetCurrentContext();
192 if (this->ContextId != current)
193 {
194 if(this->IsPicking && current)
195 {
196 vtkErrorMacro("Attempting to call MakeCurrent for a different window"
197 " than the one doing the picking, this can causes crashes"
198 " and/or bad pick results");
199 }
200 else
201 {
202 if (wglMakeCurrent(this->DeviceContext, this->ContextId) != TRUE)
203 {
204 LPVOID lpMsgBuf;
205 ::FormatMessage(
206 FORMAT_MESSAGE_ALLOCATE_BUFFER |
207 FORMAT_MESSAGE_FROM_SYSTEM |
208 FORMAT_MESSAGE_IGNORE_INSERTS,
209 nullptr,
210 GetLastError(),
211 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
212 (LPTSTR) &lpMsgBuf,
213 0,
214 nullptr
215 );
216 if(lpMsgBuf)
217 {
218 #ifdef UNICODE
219 wchar_t *wmsg = new wchar_t [mbstowcs(nullptr, (const char*)lpMsgBuf, 32000)+1];
220 wchar_t *wtemp = new wchar_t [mbstowcs(nullptr, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000)+1];
221 mbstowcs(wmsg, (const char*)lpMsgBuf, 32000);
222 mbstowcs(wtemp, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000);
223 vtkErrorMacro(<< wcscat(wtemp, wmsg));
224 delete [] wmsg;
225 delete [] wtemp;
226 #else
227 vtkErrorMacro("wglMakeCurrent failed in MakeCurrent(), error: "
228 << (LPCTSTR)lpMsgBuf);
229 #endif
230 ::LocalFree( lpMsgBuf );
231 }
232 }
233 }
234 }
235 }
236
PushContext()237 void vtkWin32OpenGLRenderWindow::PushContext()
238 {
239 HGLRC current = wglGetCurrentContext();
240 this->ContextStack.push(current);
241 this->DCStack.push(wglGetCurrentDC());
242 if (current != this->ContextId)
243 {
244 this->MakeCurrent();
245 }
246 }
247
PopContext()248 void vtkWin32OpenGLRenderWindow::PopContext()
249 {
250 HGLRC current = wglGetCurrentContext();
251 HGLRC target = this->ContextStack.top();
252 HDC dc = this->DCStack.top();
253 this->ContextStack.pop();
254 this->DCStack.pop();
255 if (target != current)
256 {
257 wglMakeCurrent(dc, target);
258 }
259 }
260
261 // ----------------------------------------------------------------------------
262 // Description:
263 // Tells if this window is the current OpenGL context for the calling thread.
IsCurrent()264 bool vtkWin32OpenGLRenderWindow::IsCurrent()
265 {
266 return this->ContextId!=0 && this->ContextId==wglGetCurrentContext();
267 }
268
SetSwapControl(int i)269 bool vtkWin32OpenGLRenderWindow::SetSwapControl(int i)
270 {
271 if (!wglewIsSupported("WGL_EXT_swap_control"))
272 {
273 return false;
274 }
275
276 if (i < 0)
277 {
278 if (wglewIsSupported("WGL_EXT_swap_control_tear"))
279 {
280 wglSwapIntervalEXT(i);
281 return true;
282 }
283 return false;
284 }
285
286 wglSwapIntervalEXT(i);
287 return true;
288 }
289
290 // ----------------------------------------------------------------------------
AdjustWindowRectForBorders(HWND hwnd,DWORD style,const int x,const int y,const int width,const int height,RECT & r)291 void AdjustWindowRectForBorders(HWND hwnd, DWORD style, const int x, const int y,
292 const int width, const int height, RECT &r)
293 {
294 if (!style && hwnd)
295 {
296 style = GetWindowLong(hwnd, GWL_STYLE);
297 }
298 r.left = x;
299 r.top = y;
300 r.right = r.left + width;
301 r.bottom = r.top + height;
302 BOOL result = AdjustWindowRect(&r, style, FALSE);
303 if (!result)
304 {
305 vtkGenericWarningMacro("AdjustWindowRect failed, error: "
306 << GetLastError());
307 }
308 }
309
310 // ----------------------------------------------------------------------------
SetSize(int x,int y)311 void vtkWin32OpenGLRenderWindow::SetSize(int x, int y)
312 {
313 static bool resizing = false;
314 if ((this->Size[0] != x) || (this->Size[1] != y))
315 {
316 this->Superclass::SetSize(x, y);
317
318 if (this->Interactor)
319 {
320 this->Interactor->SetSize(x, y);
321 }
322
323 if (this->OffScreenRendering)
324 {
325 if(!this->CreatingOffScreenWindow)
326 {
327 if (!resizing)
328 {
329 resizing = true;
330 this->CleanUpOffScreenRendering();
331 this->CreateOffScreenWindow(x,y);
332 resizing = false;
333 }
334 }
335 }
336
337 else if (this->Mapped)
338 {
339 if (!resizing)
340 {
341 resizing = true;
342
343 if (this->ParentId)
344 {
345 SetWindowExtEx(this->DeviceContext, x, y, nullptr);
346 SetViewportExtEx(this->DeviceContext, x, y, nullptr);
347 SetWindowPos(this->WindowId, HWND_TOP, 0, 0,
348 x, y, SWP_NOMOVE | SWP_NOZORDER);
349 }
350 else
351 {
352 RECT r;
353 AdjustWindowRectForBorders(this->WindowId, 0, 0, 0, x, y, r);
354 SetWindowPos(this->WindowId, HWND_TOP, 0, 0,
355 r.right - r.left,
356 r.bottom - r.top,
357 SWP_NOMOVE | SWP_NOZORDER);
358 }
359 resizing = false;
360 }
361 }
362 }
363 }
364
SetPosition(int x,int y)365 void vtkWin32OpenGLRenderWindow::SetPosition(int x, int y)
366 {
367 static bool resizing = false;
368
369 if ((this->Position[0] != x) || (this->Position[1] != y))
370 {
371 this->Modified();
372 this->Position[0] = x;
373 this->Position[1] = y;
374 if (this->Mapped)
375 {
376 if (!resizing)
377 {
378 resizing = true;
379
380 SetWindowPos(this->WindowId,HWND_TOP,x,y,
381 0, 0, SWP_NOSIZE | SWP_NOZORDER);
382 resizing = false;
383 }
384 }
385 }
386 }
387
388
389 // End the rendering process and display the image.
Frame(void)390 void vtkWin32OpenGLRenderWindow::Frame(void)
391 {
392 this->MakeCurrent();
393 if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
394 {
395 // If this check is not enforced, we crash in offscreen rendering
396 if (this->DeviceContext)
397 {
398 // use global scope to get Win32 API SwapBuffers and not be
399 // confused with this->SwapBuffers
400 ::SwapBuffers(this->DeviceContext);
401 vtkDebugMacro(<< " SwapBuffers\n");
402 }
403 }
404 }
405
VTKRegisterClass()406 void vtkWin32OpenGLRenderWindow::VTKRegisterClass()
407 {
408 // has the class been registered ?
409 WNDCLASS wndClass;
410 #ifdef UNICODE
411 if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass))
412 #else
413 if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass))
414 #endif
415 {
416 wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
417 wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc;
418 wndClass.cbClsExtra = 0;
419 wndClass.hInstance = this->ApplicationInstance;
420 wndClass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
421 wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
422 wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
423 wndClass.lpszMenuName = nullptr;
424 #ifdef UNICODE
425 wndClass.lpszClassName = L"vtkOpenGL";
426 #else
427 wndClass.lpszClassName = "vtkOpenGL";
428 #endif
429 // vtk doesn't use the first extra vtkLONG's worth of bytes,
430 // but app writers may want them, so we provide them. VTK
431 // does use the second vtkLONG's worth of bytes of extra space.
432 wndClass.cbWndExtra = 2 * sizeof(vtkLONG);
433 RegisterClass(&wndClass);
434 }
435 }
436
IsDirect()437 int vtkWin32OpenGLRenderWindow::IsDirect()
438 {
439 this->MakeCurrent();
440 if (!this->DeviceContext)
441 {
442 return 0;
443 }
444
445 int pixelFormat = GetPixelFormat(this->DeviceContext);
446 PIXELFORMATDESCRIPTOR pfd;
447
448 DescribePixelFormat(this->DeviceContext, pixelFormat,
449 sizeof(PIXELFORMATDESCRIPTOR), &pfd);
450
451 return (pfd.dwFlags & PFD_GENERIC_FORMAT) ? 0:1;
452
453 }
454
455
ReportCapabilities()456 const char* vtkWin32OpenGLRenderWindow::ReportCapabilities()
457 {
458 this->MakeCurrent();
459
460 if (!this->DeviceContext)
461 {
462 return "no device context";
463 }
464
465 int pixelFormat = GetPixelFormat(this->DeviceContext);
466 PIXELFORMATDESCRIPTOR pfd;
467
468 DescribePixelFormat(this->DeviceContext, pixelFormat,
469 sizeof(PIXELFORMATDESCRIPTOR), &pfd);
470
471 const char *glVendor = (const char *) glGetString(GL_VENDOR);
472 const char *glRenderer = (const char *) glGetString(GL_RENDERER);
473 const char *glVersion = (const char *) glGetString(GL_VERSION);
474
475 std::ostringstream strm;
476 if(glVendor)
477 strm << "OpenGL vendor string: " << glVendor << endl;
478 if(glRenderer)
479 strm << "OpenGL renderer string: " << glRenderer << endl;
480 if(glVersion)
481 strm << "OpenGL version string: " << glVersion << endl;
482
483 strm << "OpenGL extensions: " << endl;
484 GLint n, i;
485 glGetIntegerv(GL_NUM_EXTENSIONS, &n);
486 for (i = 0; i < n; i++)
487 {
488 const char *ext = (const char *)glGetStringi(GL_EXTENSIONS, i);
489 strm << " " << ext << endl;
490 }
491 strm << "PixelFormat Descriptor:" << endl;
492 strm << "depth: " << static_cast<int>(pfd.cDepthBits) << endl;
493 if (pfd.cColorBits <= 8)
494 {
495 strm << "class: PseudoColor" << endl;
496 }
497 else
498 {
499 strm << "class: TrueColor" << endl;
500 }
501 strm << "buffer size: " << static_cast<int>(pfd.cColorBits) << endl;
502 strm << "level: " << static_cast<int>(pfd.bReserved) << endl;
503 if (pfd.iPixelType == PFD_TYPE_RGBA)
504 {
505 strm << "renderType: rgba" << endl;
506 }
507 else
508 {
509 strm <<"renderType: ci" << endl;
510 }
511 if (pfd.dwFlags & PFD_DOUBLEBUFFER) {
512 strm << "double buffer: True" << endl;
513 } else {
514 strm << "double buffer: False" << endl;
515 }
516 if (pfd.dwFlags & PFD_STEREO) {
517 strm << "stereo: True" << endl;
518 } else {
519 strm << "stereo: False" << endl;
520 }
521 if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
522 strm << "hardware acceleration: False" << endl;
523 } else {
524 strm << "hardware acceleration: True" << endl;
525 }
526 strm << "rgba: redSize=" << static_cast<int>(pfd.cRedBits) << " greenSize=" << static_cast<int>(pfd.cGreenBits) << "blueSize=" << static_cast<int>(pfd.cBlueBits) << "alphaSize=" << static_cast<int>(pfd.cAlphaBits) << endl;
527 strm << "aux buffers: " << static_cast<int>(pfd.cAuxBuffers)<< endl;
528 strm << "depth size: " << static_cast<int>(pfd.cDepthBits) << endl;
529 strm << "stencil size: " << static_cast<int>(pfd.cStencilBits) << endl;
530 strm << "accum: redSize=" << static_cast<int>(pfd.cAccumRedBits) << " greenSize=" << static_cast<int>(pfd.cAccumGreenBits) << "blueSize=" << static_cast<int>(pfd.cAccumBlueBits) << "alphaSize=" << static_cast<int>(pfd.cAccumAlphaBits) << endl;
531
532 delete[] this->Capabilities;
533
534 size_t len = strm.str().length() + 1;
535 this->Capabilities = new char[len];
536 strncpy(this->Capabilities, strm.str().c_str(), len);
537
538 return this->Capabilities;
539 }
540
541 typedef bool (APIENTRY *wglChoosePixelFormatARBType)(HDC, const int*, const float*, unsigned int, int*, unsigned int*);
542
SetupPixelFormatPaletteAndContext(HDC hDC,DWORD dwFlags,int debug,int bpp,int zbpp)543 void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
544 HDC hDC, DWORD dwFlags,
545 int debug, int bpp,
546 int zbpp)
547 {
548 // Create a dummy window, needed for calling wglGetProcAddress.
549 #ifdef UNICODE
550 HWND tempId = CreateWindow(L"vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0);
551 #else
552 HWND tempId = CreateWindow("vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0);
553 #endif
554 HDC tempDC = GetDC(tempId);
555 PIXELFORMATDESCRIPTOR tempPfd;
556 memset(&tempPfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
557 tempPfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
558 tempPfd.nVersion = 1;
559 tempPfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
560 tempPfd.iPixelType = PFD_TYPE_RGBA;
561 int tempPixelFormat = ChoosePixelFormat(tempDC, &tempPfd);
562 SetPixelFormat(tempDC, tempPixelFormat, &tempPfd);
563 HGLRC tempContext = wglCreateContext(tempDC);
564 if (!wglMakeCurrent(tempDC, tempContext))
565 {
566 vtkErrorMacro("failed to create temporary windows OpenGL context with error: " << GetLastError());
567 }
568
569 // make sure glew is initialized with fake window
570 GLenum result = glewInit();
571 bool m_valid = (result == GLEW_OK);
572 if (!m_valid)
573 {
574 vtkErrorMacro("GLEW could not be initialized.");
575 return;
576 }
577
578 // First we try to use the newer wglChoosePixelFormatARB which enables
579 // features like multisamples.
580 PIXELFORMATDESCRIPTOR pfd;
581 int pixelFormat = 0;
582 if (wglChoosePixelFormatARB)
583 {
584 int attrib[] = {
585 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
586 WGL_SUPPORT_OPENGL_ARB, TRUE,
587 WGL_DRAW_TO_WINDOW_ARB, TRUE,
588 WGL_DOUBLE_BUFFER_ARB, TRUE,
589 WGL_COLOR_BITS_ARB, bpp/4*3,
590 WGL_ALPHA_BITS_ARB, bpp/4,
591 WGL_DEPTH_BITS_ARB, zbpp/4*3,
592 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
594 unsigned int n = 16;
595 if (this->StencilCapable)
596 {
597 attrib[n] = WGL_STENCIL_BITS_ARB;
598 attrib[n+1] = 8;
599 n += 2;
600 }
601 unsigned int stereoAttributeIndex = 0;
602 if (dwFlags & PFD_STEREO)
603 {
604 attrib[n] = WGL_STEREO_ARB;
605 attrib[n+1] = TRUE;
606 stereoAttributeIndex = n+1;
607 n += 2;
608 }
609 unsigned int multiSampleAttributeIndex = 0;
610 unsigned int multiSampleBuffersIndex = 0;
611 if (this->MultiSamples > 1 &&
612 wglewIsSupported("WGL_ARB_multisample"))
613 {
614 attrib[n] = WGL_SAMPLE_BUFFERS_ARB;
615 attrib[n+1] = 1;
616 attrib[n+2] = WGL_SAMPLES_ARB;
617 attrib[n+3] = this->MultiSamples;
618 multiSampleBuffersIndex = n+1;
619 multiSampleAttributeIndex = n+3;
620 n += 4;
621 }
622 if (this->UseSRGBColorSpace && WGLEW_EXT_framebuffer_sRGB)
623 {
624 attrib[n++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT;
625 attrib[n++] = TRUE;
626 }
627 else if (this->UseSRGBColorSpace && WGLEW_ARB_framebuffer_sRGB)
628 {
629 attrib[n++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
630 attrib[n++] = TRUE;
631 }
632
633 unsigned int numFormats;
634 if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)
635 || numFormats == 0)
636 {
637 // if we are trying for stereo and multisamples
638 // then drop stereo first if we cannot get a context
639 if (stereoAttributeIndex && multiSampleAttributeIndex)
640 {
641 attrib[stereoAttributeIndex] = FALSE;
642 wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats);
643 }
644 // Next try dropping multisamples if requested
645 if (multiSampleAttributeIndex && numFormats == 0)
646 {
647 while (numFormats == 0 && attrib[multiSampleAttributeIndex] > 0)
648 {
649 attrib[multiSampleAttributeIndex] /= 2;
650 if (attrib[multiSampleAttributeIndex] < 2)
651 {
652 // try disabling multisampling altogether
653 attrib[multiSampleAttributeIndex] = 0;
654 if (multiSampleBuffersIndex)
655 {
656 attrib[multiSampleBuffersIndex] = 0;
657 }
658 }
659 wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats);
660 }
661 }
662 // finally try dropping stereo when requested without multisamples
663 if (stereoAttributeIndex && numFormats == 0)
664 {
665 attrib[stereoAttributeIndex] = FALSE;
666 wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats);
667 }
668 }
669
670 DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd);
671 if (!SetPixelFormat(hDC, pixelFormat, &pfd))
672 {
673 pixelFormat = 0;
674 }
675 else
676 {
677 if (debug && (dwFlags & PFD_STEREO) && !(pfd.dwFlags & PFD_STEREO))
678 {
679 vtkGenericWarningMacro("No Stereo Available!");
680 this->StereoCapableWindow = 0;
681 }
682 }
683 }
684 else
685 {
686 vtkErrorMacro("failed to get wglChoosePixelFormatARB");
687 }
688
689 // see if we can get a 3.2 context
690 if (pixelFormat)
691 {
692 this->SetupPalette(hDC);
693
694 // create a context
695 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
696 reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));
697 this->ContextId = 0;
698 if (wglCreateContextAttribsARB)
699 {
700 // we believe that these later versions are all compatible with
701 // OpenGL 3.2 so get a more recent context if we can.
702 int attemptedVersions[] = {4,5, 4,4, 4,3, 4,2, 4,1, 4,0, 3,3, 3,2, 3,1};
703 int iContextAttribs[] =
704 {
705 WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
706 WGL_CONTEXT_MINOR_VERSION_ARB, 2,
707 WGL_CONTEXT_FLAGS_ARB, 0,
708 // WGL_CONTEXT_PROFILE_MASK_ARB,
709 // WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
710 // WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
711 0 // End of attributes list
712 };
713 for (int i = 0; i < 9 && !this->ContextId; i++)
714 {
715 iContextAttribs[1] = attemptedVersions[i*2];
716 iContextAttribs[3] = attemptedVersions[i*2+1];
717 this->ContextId = wglCreateContextAttribsARB(hDC, 0, iContextAttribs);
718 }
719 if (this->ContextId)
720 {
721 // if it is a 3.1 context check for systems that we allow
722 if (iContextAttribs[1] == 3 && iContextAttribs[3] == 1)
723 {
724 std::string vendor = (const char *)glGetString(GL_VENDOR);
725 std::string renderer = (const char *)glGetString(GL_RENDERER);
726 std::string version = (const char *)glGetString(GL_VERSION);
727 if (vendor.find("Intel") != std::string::npos &&
728 (renderer.find("HD Graphics 3000") != std::string::npos ||
729 renderer.find("HD Graphics 2000") != std::string::npos))
730 {
731 vtkErrorMacro("We have determined that your graphics system is"
732 " an Intel SandyBridge based system. These systems only partially "
733 " support VTK. If you encounter any issues please make sure"
734 " your graphics drivers from Intel are up to date.");
735 }
736 else
737 {
738 wglDeleteContext(this->ContextId);
739 this->ContextId = nullptr;
740 }
741 }
742 }
743 }
744 // fallback on old approach
745 if (!this->ContextId)
746 {
747 this->ContextId = wglCreateContext(hDC);
748 }
749 if (this->ContextId == nullptr)
750 {
751 vtkErrorMacro("wglCreateContext failed in CreateAWindow(), error: " << GetLastError());
752 }
753 }
754
755 // Delete the dummy window
756 wglMakeCurrent(tempDC, 0);
757 wglDeleteContext(tempContext);
758 ReleaseDC(tempId, tempDC);
759 ::DestroyWindow(tempId); // windows api
760
761 // If we got a valid pixel format in the process, we are done.
762 // Otherwise fail as the OpenGL does not support even 2.1
763 if (!pixelFormat)
764 {
765 vtkErrorMacro("failed to get valid pixel format.");
766 }
767
768 return;
769 }
770
SetupPalette(HDC hDC)771 void vtkWin32OpenGLRenderWindow::SetupPalette(HDC hDC)
772 {
773 int pixelFormat = GetPixelFormat(hDC);
774 PIXELFORMATDESCRIPTOR pfd;
775 LOGPALETTE* pPal;
776 int paletteSize;
777
778 DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
779
780 if (pfd.dwFlags & PFD_NEED_PALETTE)
781 {
782 paletteSize = 1 << pfd.cColorBits;
783 }
784 else
785 {
786 return;
787 }
788
789 pPal = (LOGPALETTE*)
790 malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
791 pPal->palVersion = 0x300;
792 pPal->palNumEntries = paletteSize;
793
794 /* build a simple RGB color palette */
795 {
796 int redMask = (1 << pfd.cRedBits) - 1;
797 int greenMask = (1 << pfd.cGreenBits) - 1;
798 int blueMask = (1 << pfd.cBlueBits) - 1;
799 int i;
800
801 for (i=0; i<paletteSize; ++i)
802 {
803 pPal->palPalEntry[i].peRed =
804 (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
805 pPal->palPalEntry[i].peGreen =
806 (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
807 pPal->palPalEntry[i].peBlue =
808 (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
809 pPal->palPalEntry[i].peFlags = 0;
810 }
811 }
812
813 this->Palette = CreatePalette(pPal);
814 free(pPal);
815
816 if (this->Palette)
817 {
818 this->OldPalette = SelectPalette(hDC, this->Palette, FALSE);
819 RealizePalette(hDC);
820 }
821 }
822
823
MessageProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)824 LRESULT vtkWin32OpenGLRenderWindow::MessageProc(HWND hWnd, UINT message,
825 WPARAM wParam, LPARAM lParam)
826 {
827 switch (message)
828 {
829 case WM_CREATE:
830 {
831 // nothing to be done here, opengl is initialized after the call to
832 // create now
833 return 0;
834 }
835 case WM_DESTROY:
836 this->Clean();
837 if (this->DeviceContext)
838 {
839 ReleaseDC(this->WindowId, this->DeviceContext);
840 this->DeviceContext = nullptr;
841 this->WindowId = nullptr;
842 }
843 return 0;
844 case WM_SIZE:
845 /* track window size changes */
846 if (this->ContextId)
847 {
848 this->SetSize((int) LOWORD(lParam),(int) HIWORD(lParam));
849 return 0;
850 }
851 case WM_PALETTECHANGED:
852 /* realize palette if this is *not* the current window */
853 if (this->ContextId && this->Palette && (HWND) wParam != hWnd)
854 {
855 SelectPalette(this->DeviceContext, this->OldPalette, FALSE);
856 UnrealizeObject(this->Palette);
857 this->OldPalette = SelectPalette(this->DeviceContext,
858 this->Palette, FALSE);
859 RealizePalette(this->DeviceContext);
860 this->Render();
861 }
862 break;
863 case WM_QUERYNEWPALETTE:
864 /* realize palette if this is the current window */
865 if (this->ContextId && this->Palette)
866 {
867 SelectPalette(this->DeviceContext, this->OldPalette, FALSE);
868 UnrealizeObject(this->Palette);
869 this->OldPalette = SelectPalette(this->DeviceContext,
870 this->Palette, FALSE);
871 RealizePalette(this->DeviceContext);
872 this->Render();
873 return TRUE;
874 }
875 break;
876 case WM_PAINT:
877 {
878 PAINTSTRUCT ps;
879 BeginPaint(hWnd, &ps);
880 if (this->ContextId)
881 {
882 this->Render();
883 }
884 EndPaint(hWnd, &ps);
885 return 0;
886 }
887 break;
888 case WM_ERASEBKGND:
889 return TRUE;
890 case WM_SETCURSOR:
891 if (HTCLIENT == LOWORD(lParam))
892 {
893 this->SetCurrentCursor(this->GetCurrentCursor());
894 return TRUE;
895 }
896 break;
897 default:
898 this->InvokeEvent(vtkCommand::RenderWindowMessageEvent, &message);
899 break;
900 }
901 return DefWindowProc(hWnd, message, wParam, lParam);
902 }
903
904
InitializeApplication()905 void vtkWin32OpenGLRenderWindow::InitializeApplication()
906 {
907 // get the application instance if we don't have one already
908 if (!this->ApplicationInstance)
909 {
910 // if we have a parent window get the app instance from it
911 if (this->ParentId)
912 {
913 this->ApplicationInstance = (HINSTANCE)vtkGetWindowLong(this->ParentId,vtkGWL_HINSTANCE);
914 }
915 else
916 {
917 this->ApplicationInstance = GetModuleHandle(nullptr); /*AfxGetInstanceHandle();*/
918 }
919 }
920 }
921
CreateAWindow()922 void vtkWin32OpenGLRenderWindow::CreateAWindow()
923 {
924 this->VTKRegisterClass();
925
926 if(this->WindowIdReferenceCount == 0)
927 {
928 static int count = 1;
929 char *windowName;
930
931 if (!this->WindowId)
932 {
933 this->DeviceContext = 0;
934
935 int len = static_cast<int>(strlen("Visualization Toolkit - Win32OpenGL #"))
936 + (int)ceil( (double) log10( (double)(count+1) ) )
937 + 1;
938 windowName = new char [ len ];
939 snprintf(windowName,len,"Visualization Toolkit - Win32OpenGL #%i",count++);
940 this->SetWindowName(windowName);
941 delete [] windowName;
942
943 #ifdef UNICODE
944 wchar_t *wname = new wchar_t [mbstowcs(nullptr, this->WindowName, 32000)+1];
945 mbstowcs(wname, this->WindowName, 32000);
946 #endif
947 int x = ((this->Position[0] >= 0) ? this->Position[0] : 5);
948 int y = ((this->Position[1] >= 0) ? this->Position[1] : 5);
949 int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
950 int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
951
952 /* create window */
953 if (this->ParentId)
954 {
955 #ifdef UNICODE
956 this->WindowId = CreateWindow(
957 L"vtkOpenGL", wname,
958 WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/,
959 x, y, width, height,
960 this->ParentId, nullptr, this->ApplicationInstance, nullptr);
961 #else
962 this->WindowId = CreateWindow(
963 "vtkOpenGL", this->WindowName,
964 WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/,
965 x, y, width, height,
966 this->ParentId, nullptr, this->ApplicationInstance, nullptr);
967 #endif
968 }
969 else
970 {
971 DWORD style;
972 if (this->Borders)
973 {
974 style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/;
975 }
976 else
977 {
978 style = WS_POPUP | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/;
979 }
980 RECT r;
981 AdjustWindowRectForBorders(0, style, x, y, width, height, r);
982 #ifdef UNICODE
983 this->WindowId = CreateWindow(
984 L"vtkOpenGL", wname, style,
985 x, y, r.right-r.left, r.bottom-r.top,
986 nullptr, nullptr, this->ApplicationInstance, nullptr);
987 #else
988 this->WindowId = CreateWindow(
989 "vtkOpenGL", this->WindowName, style,
990 x, y, r.right-r.left, r.bottom-r.top,
991 nullptr, nullptr, this->ApplicationInstance, nullptr);
992 #endif
993 }
994 #ifdef UNICODE
995 delete [] wname;
996 #endif
997
998 if (!this->WindowId)
999 {
1000 vtkErrorMacro("Could not create window, error: " << GetLastError());
1001 return;
1002 }
1003 // extract the create info
1004
1005 /* display window */
1006 if(!this->OffScreenRendering)
1007 {
1008 ShowWindow(this->WindowId, SW_SHOW);
1009 }
1010 //UpdateWindow(this->WindowId);
1011 this->OwnWindow = 1;
1012 vtkSetWindowLong(this->WindowId,sizeof(vtkLONG),(intptr_t)this);
1013 }
1014 if (!this->DeviceContext)
1015 {
1016 this->DeviceContext = GetDC(this->WindowId);
1017 }
1018 if (this->StereoCapableWindow)
1019 {
1020 this->SetupPixelFormatPaletteAndContext(this->DeviceContext, PFD_SUPPORT_OPENGL |
1021 PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER |
1022 PFD_STEREO, this->GetDebug(), 32, 32);
1023 }
1024 else
1025 {
1026 this->SetupPixelFormatPaletteAndContext(this->DeviceContext, PFD_SUPPORT_OPENGL |
1027 PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,
1028 this->GetDebug(), 32, 32);
1029 }
1030 this->MakeCurrent();
1031
1032 // wipe out any existing display lists
1033 this->ReleaseGraphicsResources(this);
1034 this->OpenGLInit();
1035 this->Mapped = 1;
1036 this->WindowIdReferenceCount = 1;
1037 }
1038 else
1039 {
1040 ++this->WindowIdReferenceCount;
1041 }
1042 }
1043
1044 // Initialize the window for rendering.
WindowInitialize()1045 void vtkWin32OpenGLRenderWindow::WindowInitialize()
1046 {
1047 // create our own window if not already set
1048 this->OwnWindow = 0;
1049 if (!this->MFChandledWindow)
1050 {
1051 this->InitializeApplication();
1052 this->CreateAWindow();
1053 }
1054 else
1055 {
1056 this->MakeCurrent(); // hsr
1057 this->OpenGLInit();
1058 }
1059 }
1060
1061 // Initialize the rendering window.
Initialize(void)1062 void vtkWin32OpenGLRenderWindow::Initialize (void)
1063 {
1064 // make sure we haven't already been initialized
1065 if (!this->OffScreenRendering && !this->ContextId)
1066 {
1067 this->WindowInitialize();
1068 }
1069 else
1070 {
1071 if(this->OffScreenRendering && !(this->ContextId ||
1072 this->OffScreenUseFrameBuffer))
1073 {
1074 this->InitializeApplication();
1075 int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
1076 int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
1077 this->CreateOffScreenWindow(width,height);
1078 }
1079 }
1080
1081 if (this->SharedRenderWindow)
1082 {
1083 vtkWin32OpenGLRenderWindow *renWin =
1084 vtkWin32OpenGLRenderWindow::SafeDownCast(this->SharedRenderWindow);
1085 if (renWin && renWin->Initialized)
1086 {
1087 bool result = wglShareLists( renWin->ContextId, this->ContextId) == TRUE;
1088 if (result)
1089 {
1090 this->VBOCache->Delete();
1091 this->VBOCache = renWin->VBOCache;
1092 this->VBOCache->Register(this);
1093 }
1094 }
1095 }
1096 }
1097
Finalize(void)1098 void vtkWin32OpenGLRenderWindow::Finalize (void)
1099 {
1100 if (this->CursorHidden)
1101 {
1102 this->ShowCursor();
1103 }
1104
1105 if (this->OffScreenRendering)
1106 {
1107 this->CleanUpOffScreenRendering();
1108 }
1109 this->DestroyWindow();
1110 }
1111
DestroyWindow()1112 void vtkWin32OpenGLRenderWindow::DestroyWindow()
1113 {
1114 if(this->WindowIdReferenceCount > 0)
1115 {
1116 --this->WindowIdReferenceCount;
1117 if(this->WindowIdReferenceCount == 0)
1118 {
1119 this->Clean();
1120 if (this->WindowId)
1121 {
1122 ReleaseDC(this->WindowId, this->DeviceContext);
1123 // can't set WindowId=nullptr, needed for DestroyWindow
1124 this->DeviceContext = nullptr;
1125
1126 // clear the extra data before calling destroy
1127 vtkSetWindowLong(this->WindowId,sizeof(vtkLONG),(vtkLONG)0);
1128 if(this->OwnWindow)
1129 {
1130 ::DestroyWindow(this->WindowId); // windows api
1131 this->WindowId=0;
1132 }
1133 }
1134 }
1135 }
1136 }
1137
1138 // Get the current size of the window.
GetSize(void)1139 int *vtkWin32OpenGLRenderWindow::GetSize(void)
1140 {
1141 // if we aren't mapped then just return the ivar
1142 if (this->Mapped)
1143 {
1144 RECT rect;
1145
1146 // Find the current window size
1147 if (GetClientRect(this->WindowId, &rect))
1148 {
1149 this->Size[0] = rect.right;
1150 this->Size[1] = rect.bottom;
1151 }
1152 else
1153 {
1154 this->Size[0] = 0;
1155 this->Size[1] = 0;
1156 }
1157
1158 }
1159
1160 return this->vtkOpenGLRenderWindow::GetSize();
1161 }
1162
1163 // Get the size of the whole screen.
GetScreenSize(void)1164 int *vtkWin32OpenGLRenderWindow::GetScreenSize(void)
1165 {
1166 HDC hDC = ::GetDC(nullptr);
1167 if (hDC)
1168 {
1169 // This technique yields the screen size of the primary monitor
1170 // only in a multi-monitor configuration...
1171 this->Size[0] = ::GetDeviceCaps(hDC, HORZRES);
1172 this->Size[1] = ::GetDeviceCaps(hDC, VERTRES);
1173 ::ReleaseDC(nullptr, hDC);
1174 }
1175 else
1176 {
1177 // This technique gets the "work area" (the whole screen except
1178 // for the bit covered by the Windows task bar) -- use it as a
1179 // fallback if there's an error calling GetDC.
1180 RECT rect;
1181 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
1182
1183 this->Size[0] = rect.right - rect.left;
1184 this->Size[1] = rect.bottom - rect.top;
1185 }
1186
1187 return this->Size;
1188 }
1189
1190 // Get the position in screen coordinates of the window.
GetPosition(void)1191 int *vtkWin32OpenGLRenderWindow::GetPosition(void)
1192 {
1193 // if we aren't mapped then just return the ivar
1194 if (!this->Mapped)
1195 {
1196 return this->Position;
1197 }
1198
1199 // Find the current window position
1200 // x,y,&this->Position[0],&this->Position[1],&child);
1201
1202 return this->Position;
1203 }
1204
1205 // Change the window to fill the entire screen.
SetFullScreen(vtkTypeBool arg)1206 void vtkWin32OpenGLRenderWindow::SetFullScreen(vtkTypeBool arg)
1207 {
1208 int *temp;
1209
1210 if (this->FullScreen == arg)
1211 {
1212 return;
1213 }
1214
1215 if (!this->Mapped)
1216 {
1217 this->PrefFullScreen();
1218 return;
1219 }
1220
1221 // set the mode
1222 this->FullScreen = arg;
1223 if (this->FullScreen <= 0)
1224 {
1225 this->Position[0] = this->OldScreen[0];
1226 this->Position[1] = this->OldScreen[1];
1227 this->Size[0] = this->OldScreen[2];
1228 this->Size[1] = this->OldScreen[3];
1229 this->Borders = this->OldScreen[4];
1230 }
1231 else
1232 {
1233 // if window already up get its values
1234 if (this->WindowId)
1235 {
1236 temp = this->GetPosition();
1237 this->OldScreen[0] = temp[0];
1238 this->OldScreen[1] = temp[1];
1239
1240 this->OldScreen[4] = this->Borders;
1241 this->PrefFullScreen();
1242 }
1243 }
1244
1245 // remap the window
1246 this->WindowRemap();
1247
1248 this->Modified();
1249 }
1250
1251 //
1252 // Set the variable that indicates that we want a stereo capable window
1253 // be created. This method can only be called before a window is realized.
1254 //
SetStereoCapableWindow(vtkTypeBool capable)1255 void vtkWin32OpenGLRenderWindow::SetStereoCapableWindow(vtkTypeBool capable)
1256 {
1257 if (this->ContextId == 0)
1258 {
1259 vtkRenderWindow::SetStereoCapableWindow(capable);
1260 }
1261 else
1262 {
1263 vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
1264 << "before the window is realized, i.e. before a render.");
1265 }
1266 }
1267
1268
1269 // Set the preferred window size to full screen.
PrefFullScreen()1270 void vtkWin32OpenGLRenderWindow::PrefFullScreen()
1271 {
1272 int *size = this->GetScreenSize();
1273
1274 // don't show borders
1275 this->Borders = 0;
1276
1277 RECT r;
1278 AdjustWindowRectForBorders(this->WindowId, 0, 0, 0, size[0], size[1], r);
1279
1280 // use full screen
1281 this->Position[0] = 0;
1282 this->Position[1] = 0;
1283 this->Size[0] = r.right - r.left;
1284 this->Size[1] = r.bottom - r.top;
1285 }
1286
1287 // Remap the window.
WindowRemap()1288 void vtkWin32OpenGLRenderWindow::WindowRemap()
1289 {
1290 // close everything down
1291 this->Finalize();
1292
1293 // set the default windowid
1294 this->WindowId = this->NextWindowId;
1295 this->NextWindowId = 0;
1296
1297 // and set it up!
1298 this->Initialize();
1299 }
1300
PrintSelf(ostream & os,vtkIndent indent)1301 void vtkWin32OpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
1302 {
1303 this->Superclass::PrintSelf(os,indent);
1304
1305 os << indent << "ContextId: " << this->ContextId << "\n";
1306 os << indent << "Next Window Id: " << this->NextWindowId << "\n";
1307 os << indent << "Window Id: " << this->WindowId << "\n";
1308 }
1309
1310 // Get the window id.
GetWindowId()1311 HWND vtkWin32OpenGLRenderWindow::GetWindowId()
1312 {
1313 vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n");
1314
1315 return this->WindowId;
1316 }
1317
1318 // Set the window id to a pre-existing window.
SetWindowId(HWND arg)1319 void vtkWin32OpenGLRenderWindow::SetWindowId(HWND arg)
1320 {
1321 vtkDebugMacro(<< "Setting WindowId to " << arg << "\n");
1322
1323 if (arg != this->WindowId)
1324 {
1325 this->WindowId = arg;
1326 if (this->ContextId)
1327 {
1328 wglDeleteContext(this->ContextId);
1329 }
1330 this->ContextId = 0;
1331 this->DeviceContext = 0;
1332 }
1333 }
1334
1335 // Set this RenderWindow's X window id to a pre-existing window.
SetWindowInfo(const char * info)1336 void vtkWin32OpenGLRenderWindow::SetWindowInfo(const char *info)
1337 {
1338 int tmp;
1339
1340 sscanf(info,"%i",&tmp);
1341
1342 this->WindowId = (HWND)tmp;
1343 vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n");
1344 }
1345
SetNextWindowInfo(const char * info)1346 void vtkWin32OpenGLRenderWindow::SetNextWindowInfo(const char *info)
1347 {
1348 int tmp;
1349
1350 sscanf(info,"%i",&tmp);
1351
1352 this->SetNextWindowId((HWND)tmp);
1353 }
1354
SetDisplayId(void * arg)1355 void vtkWin32OpenGLRenderWindow::SetDisplayId(void * arg)
1356 {
1357 this->DeviceContext = (HDC) arg;
1358 }
1359
SetContextId(HGLRC arg)1360 void vtkWin32OpenGLRenderWindow::SetContextId(HGLRC arg)
1361 {
1362 this->ContextId = arg;
1363 }
1364
SetDeviceContext(HDC arg)1365 void vtkWin32OpenGLRenderWindow::SetDeviceContext(HDC arg)
1366 {
1367 this->DeviceContext = arg;
1368 this->MFChandledWindow = TRUE;
1369 }
1370
1371 // Sets the HWND id of the window that WILL BE created.
SetParentInfo(const char * info)1372 void vtkWin32OpenGLRenderWindow::SetParentInfo(const char *info)
1373 {
1374 int tmp;
1375
1376 sscanf(info,"%i",&tmp);
1377
1378 this->ParentId = (HWND)tmp;
1379 vtkDebugMacro(<< "Setting ParentId to " << this->ParentId << "\n");
1380 }
1381
1382 // Set the window id to a pre-existing window.
SetParentId(HWND arg)1383 void vtkWin32OpenGLRenderWindow::SetParentId(HWND arg)
1384 {
1385 vtkDebugMacro(<< "Setting ParentId to " << arg << "\n");
1386
1387 this->ParentId = arg;
1388 }
1389
1390 // Set the window id of the new window once a WindowRemap is done.
SetNextWindowId(HWND arg)1391 void vtkWin32OpenGLRenderWindow::SetNextWindowId(HWND arg)
1392 {
1393 vtkDebugMacro(<< "Setting NextWindowId to " << arg << "\n");
1394
1395 this->NextWindowId = arg;
1396 }
1397
SetNextWindowId(void * arg)1398 void vtkWin32OpenGLRenderWindow::SetNextWindowId(void *arg)
1399 {
1400 this->SetNextWindowId((HWND)arg);
1401 }
1402
1403 // Begin the rendering process.
Start(void)1404 void vtkWin32OpenGLRenderWindow::Start(void)
1405 {
1406 // if the renderer has not been initialized, do so now
1407 if (!this->ContextId)
1408 {
1409 this->Initialize();
1410 }
1411
1412 // set the current window
1413 this->MakeCurrent();
1414 }
1415
1416
SetOffScreenRendering(vtkTypeBool offscreen)1417 void vtkWin32OpenGLRenderWindow::SetOffScreenRendering(vtkTypeBool offscreen)
1418 {
1419 if (offscreen == this->OffScreenRendering)
1420 {
1421 return;
1422 }
1423
1424 this->vtkRenderWindow::SetOffScreenRendering(offscreen);
1425
1426 if (offscreen)
1427 {
1428 int size[2];
1429 size[0] = (this->Size[0] > 0) ? this->Size[0] : 300;
1430 size[1] = (this->Size[1] > 0) ? this->Size[1] : 300;
1431 this->CreateOffScreenWindow(size[0],size[1]);
1432 }
1433 else
1434 {
1435 this->CleanUpOffScreenRendering();
1436 }
1437 }
1438
CreateOffScreenWindow(int width,int height)1439 void vtkWin32OpenGLRenderWindow::CreateOffScreenWindow(int width,
1440 int height)
1441 {
1442 int status = this->CreatingOffScreenWindow;
1443 this->CreatingOffScreenWindow = 1;
1444 this->CreateHardwareOffScreenWindow(width,height);
1445 this->CreatingOffScreenWindow = status;
1446 }
1447
CleanUpOffScreenRendering(void)1448 void vtkWin32OpenGLRenderWindow::CleanUpOffScreenRendering(void)
1449 {
1450 if(this->OffScreenUseFrameBuffer)
1451 {
1452 this->DestroyHardwareOffScreenWindow();
1453 }
1454 }
1455
1456 //----------------------------------------------------------------------------
HideCursor()1457 void vtkWin32OpenGLRenderWindow::HideCursor()
1458 {
1459 if (this->CursorHidden)
1460 {
1461 return;
1462 }
1463 this->CursorHidden = 1;
1464
1465 ::ShowCursor(!this->CursorHidden);
1466 }
1467
1468 //----------------------------------------------------------------------------
ShowCursor()1469 void vtkWin32OpenGLRenderWindow::ShowCursor()
1470 {
1471 if (!this->CursorHidden)
1472 {
1473 return;
1474 }
1475 this->CursorHidden = 0;
1476
1477 ::ShowCursor(!this->CursorHidden);
1478 }
1479
1480 //----------------------------------------------------------------------------
SetCursorPosition(int x,int y)1481 void vtkWin32OpenGLRenderWindow::SetCursorPosition(int x, int y)
1482 {
1483 int *size = this->GetSize();
1484
1485 POINT point;
1486 point.x = x;
1487 point.y = size[1] - y - 1;
1488
1489 if (ClientToScreen(this->WindowId, &point))
1490 {
1491 SetCursorPos(point.x, point.y);
1492 }
1493 }
1494
1495 //----------------------------------------------------------------------------
SetCurrentCursor(int shape)1496 void vtkWin32OpenGLRenderWindow::SetCurrentCursor(int shape)
1497 {
1498 if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) )
1499 {
1500 return;
1501 }
1502 this->Superclass::SetCurrentCursor(shape);
1503 LPCTSTR cursorName = 0;
1504 switch (shape)
1505 {
1506 case VTK_CURSOR_DEFAULT:
1507 case VTK_CURSOR_ARROW:
1508 cursorName = IDC_ARROW;
1509 break;
1510 case VTK_CURSOR_SIZENE:
1511 case VTK_CURSOR_SIZESW:
1512 cursorName = IDC_SIZENESW;
1513 break;
1514 case VTK_CURSOR_SIZENW:
1515 case VTK_CURSOR_SIZESE:
1516 cursorName = IDC_SIZENWSE;
1517 break;
1518 case VTK_CURSOR_SIZENS:
1519 cursorName = IDC_SIZENS;
1520 break;
1521 case VTK_CURSOR_SIZEWE:
1522 cursorName = IDC_SIZEWE;
1523 break;
1524 case VTK_CURSOR_SIZEALL:
1525 cursorName = IDC_SIZEALL;
1526 break;
1527 case VTK_CURSOR_HAND:
1528 #if(WINVER >= 0x0500)
1529 cursorName = IDC_HAND;
1530 #else
1531 cursorName = IDC_ARROW;
1532 #endif
1533 break;
1534 case VTK_CURSOR_CROSSHAIR:
1535 cursorName = IDC_CROSS;
1536 break;
1537 }
1538
1539 if (cursorName)
1540 {
1541 HANDLE cursor =
1542 LoadImage(0,cursorName,IMAGE_CURSOR,0,0,LR_SHARED | LR_DEFAULTSIZE);
1543 SetCursor((HCURSOR)cursor);
1544 }
1545 }
1546
1547 //----------------------------------------------------------------------------
DetectDPI()1548 bool vtkWin32OpenGLRenderWindow::DetectDPI()
1549 {
1550 this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY));
1551 return true;
1552 }
1553