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