diff --git a/CMakeExternals/PatchVTK-5.10-Mac.cmake b/CMakeExternals/PatchVTK-5.10-Mac.cmake deleted file mode 100644 index 3f46c3563e..0000000000 --- a/CMakeExternals/PatchVTK-5.10-Mac.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# Called by VTK.cmake (ExternalProject_Add) as a patch for VTK 5.10 to work on Mac OS X - -# Updates vtkQtBarChart.cxx which fails to build on Mac OS X. The Mac OS X compiler can not resolve a isnan call of vtk. -# Calling std::isnan solves this problem. But std::isnan is part of c++ 11 which most likely will not be recognized -# by windows and linux compilers so this patch is needed only for Mac OS X systems -# read whole file vtkQtBarChart.cxx -file(STRINGS GUISupport/Qt/Chart/vtkQtBarChart.cxx sourceCode NEWLINE_CONSUME) - -# substitute dependency to gdcmMSFF by dependencies for more libraries -string(REGEX REPLACE "[(]isnan" "(std::isnan" sourceCode ${sourceCode}) - -# set variable CONTENTS, which is substituted in TEMPLATE_FILE -set(CONTENTS ${sourceCode}) -configure_file(${TEMPLATE_FILE} GUISupport/Qt/Chart/vtkQtBarChart.cxx @ONLY) \ No newline at end of file diff --git a/CMakeExternals/PatchVTK-5.10.cmake b/CMakeExternals/PatchVTK-5.10.cmake new file mode 100644 index 0000000000..9bea769311 --- /dev/null +++ b/CMakeExternals/PatchVTK-5.10.cmake @@ -0,0 +1,29 @@ +# Called by VTK.cmake (ExternalProject_Add) as a patch for VTK 5.10 +if(APPLE) + # patch for VTK 5.10 to work on Mac OS X + + # Updates vtkQtBarChart.cxx which fails to build on Mac OS X. The Mac OS X compiler can not resolve a isnan call of vtk. + # Calling std::isnan solves this problem. But std::isnan is part of c++ 11 which most likely will not be recognized + # by windows and linux compilers so this patch is needed only for Mac OS X systems + # read whole file vtkQtBarChart.cxx + file(STRINGS GUISupport/Qt/Chart/vtkQtBarChart.cxx sourceCode NEWLINE_CONSUME) + + # substitute dependency to gdcmMSFF by dependencies for more libraries + string(REGEX REPLACE "[(]isnan" "(std::isnan" sourceCode ${sourceCode}) + + # set variable CONTENTS, which is substituted in TEMPLATE_FILE + set(CONTENTS ${sourceCode}) + configure_file(${TEMPLATE_FILE} GUISupport/Qt/Chart/vtkQtBarChart.cxx @ONLY) + +endif() + +if (WIN32) + # patch for VTK 5.10, bug http://paraview.org/Bug/view.php?id=14122 + # fix is included in VTK 6, so we can remove this part as soon as VTK 6 is our default + + # complete patched file is in ${WIN32_OPENGL_RW_FILE} + + file(STRINGS ${WIN32_OPENGL_RW_FILE} sourceCode NEWLINE_CONSUME) + set(CONTENTS ${sourceCode}) + configure_file(${TEMPLATE_FILE} Rendering/vtkWin32OpenGLRenderWindow.cxx @ONLY) +endif() diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index 8da05df029..5937a4e2f8 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,99 +1,97 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else(WIN32) option(VTK_USE_SYSTEM_FREETYPE ON) endif(WIN32) # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF -DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW ) endif() if(MITK_USE_Python) list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=ON -DVTK_USE_TK:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} #-DPYTHON_LIBRARIES=${PYTHON_LIBRARY} #-DPYTHON_DEBUG_LIBRARIES=${PYTHON_DEBUG_LIBRARIES} ) else() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) endif() if(MITK_USE_QT) list(APPEND additional_cmake_args -DDESIRED_QT_VERSION:STRING=4 -DVTK_USE_GUISUPPORT:BOOL=ON -DVTK_USE_QVTK_QTOPENGL:BOOL=OFF -DVTK_USE_QT:BOOL=ON -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) endif() set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/vtk-5.10.0.tar.gz) set(VTK_URL_MD5 a0363f78910f466ba8f1bd5ab5437cb9) - if(APPLE) - set(VTK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchVTK-5.10-Mac.cmake) - endif() + set(VTK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -DWIN32_OPENGL_RW_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/vtkWin32OpenGLRenderWindow.cxx.vtk-5.10.patched -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchVTK-5.10.cmake) ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src BINARY_DIR ${proj}-build PREFIX ${proj}-cmake URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} INSTALL_COMMAND "" PATCH_COMMAND ${VTK_PATCH_COMMAND} CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON -DVTK_USE_PARALLEL:BOOL=ON -DVTK_USE_CHARTS:BOOL=OFF -DVTK_USE_QTCHARTS:BOOL=ON -DVTK_USE_GEOVIS:BOOL=OFF -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_USE_QVTK_QTOPENGL:BOOL=OFF -DVTK_LEGACY_REMOVE:BOOL=ON ${additional_cmake_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/vtkWin32OpenGLRenderWindow.cxx.vtk-5.10.patched b/CMakeExternals/vtkWin32OpenGLRenderWindow.cxx.vtk-5.10.patched new file mode 100644 index 0000000000..a58dbb9fd2 --- /dev/null +++ b/CMakeExternals/vtkWin32OpenGLRenderWindow.cxx.vtk-5.10.patched @@ -0,0 +1,1703 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: vtkWin32OpenGLRenderWindow.cxx + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWin32OpenGLRenderWindow.h" + +#include "vtkIdList.h" +#include "vtkCommand.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLTexture.h" +#include "vtkRendererCollection.h" +#include "vtkWin32RenderWindowInteractor.h" + +#include +#include + +#include "vtkOpenGL.h" +#include "vtkgl.h" + +vtkStandardNewMacro(vtkWin32OpenGLRenderWindow); + +#define VTK_MAX_LIGHTS 8 + +vtkWin32OpenGLRenderWindow::vtkWin32OpenGLRenderWindow() +{ + this->ApplicationInstance = NULL; + this->Palette = NULL; + this->ContextId = 0; + this->MultiSamples = 8; + this->WindowId = 0; + this->ParentId = 0; + this->NextWindowId = 0; + this->DeviceContext = (HDC)0; // hsr + this->MFChandledWindow = FALSE; // hsr + this->StereoType = VTK_STEREO_CRYSTAL_EYES; + this->CursorHidden = 0; + this->Capabilities = 0; + + this->ScreenDeviceContext = (HDC)0; + this->MemoryHdc = (HDC)0; + this->CreatingOffScreenWindow = 0; + this->WindowIdReferenceCount = 0; + + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; +} + +vtkWin32OpenGLRenderWindow::~vtkWin32OpenGLRenderWindow() +{ + this->Finalize(); + + vtkRenderer *ren; + vtkCollectionSimpleIterator rit; + this->Renderers->InitTraversal(rit); + while ( (ren = this->Renderers->GetNextRenderer(rit)) ) + { + ren->SetRenderWindow(NULL); + } + + delete[] this->Capabilities; +} + +void vtkWin32OpenGLRenderWindow::Clean() +{ + GLuint id; + + /* finish OpenGL rendering */ + if (this->ContextId) + { + this->MakeCurrent(); + + /* first delete all the old lights */ + for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+VTK_MAX_LIGHTS; cur_light++) + { + glDisable((GLenum)cur_light); + } + + /* now delete all textures */ + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + id = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(id)) + { + glDeleteTextures(1, &id); + } +#else + if (glIsList(id)) + { + glDeleteLists(id,1); + } +#endif + } + + this->CleanUpRenderers(); + + // Note: wglMakeCurrent(NULL,NULL) is valid according to the documentation + // and works with nVidia and ATI but not with Intel. Passing an existing + // device context works in any case. + // see VTK Bug 7119. + if(wglMakeCurrent(this->DeviceContext,NULL)!=TRUE) + { + vtkErrorMacro("wglMakeCurrent failed in Clean(), error: " << GetLastError()); + } + if (wglDeleteContext(this->ContextId) != TRUE) + { + vtkErrorMacro("wglDeleteContext failed in Clean(), error: " << GetLastError()); + } + this->ContextId = NULL; + } + if (this->Palette) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); // SVA delete the old palette + DeleteObject(this->Palette); + this->Palette = NULL; + } +} + +void vtkWin32OpenGLRenderWindow::CleanUpRenderers() +{ + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + vtkRenderer *ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(NULL); + ren->SetRenderWindow(this); + } +} + +LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message, + WPARAM wParam, + LPARAM lParam) +{ + LRESULT res; + + vtkWin32OpenGLRenderWindow *me = + (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,sizeof(vtkLONG)); + + if (me && me->GetReferenceCount()>0) + { + me->Register(me); + res = me->MessageProc(hWnd, message, wParam, lParam); + me->UnRegister(me); + } + else + { + res = DefWindowProc(hWnd, message, wParam, lParam); + } + + return res; +} + +void vtkWin32OpenGLRenderWindow::SetWindowName( const char * _arg ) +{ + vtkWindow::SetWindowName(_arg); + if (this->WindowId) + { +#ifdef UNICODE + wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; + mbstowcs(wname, this->WindowName, 32000); + SetWindowText(this->WindowId, wname); + delete [] wname; +#else + SetWindowText(this->WindowId, this->WindowName); +#endif + } +} + +int vtkWin32OpenGLRenderWindow::GetEventPending() +{ + MSG msg; + if (PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_NOREMOVE)) + { + if (msg.message == WM_MOUSEMOVE) + { + PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE); + } + if ((msg.message == WM_LBUTTONDOWN) || + (msg.message == WM_RBUTTONDOWN) || + (msg.message == WM_MBUTTONDOWN)) + { + return 1; + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::MakeCurrent() +{ + // Try to avoid doing anything (for performance). + HGLRC current = wglGetCurrentContext(); + if (this->ContextId != current) + { + if(this->IsPicking && current) + { + vtkErrorMacro("Attempting to call MakeCurrent for a different window" + " than the one doing the picking, this can causes crashes" + " and/or bad pick results"); + } + else + { + if (wglMakeCurrent(this->DeviceContext, this->ContextId) != TRUE) + { + LPVOID lpMsgBuf; + ::FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + if(lpMsgBuf) + { +#ifdef UNICODE + wchar_t *wmsg = new wchar_t [mbstowcs(NULL, (const char*)lpMsgBuf, 32000)+1]; + wchar_t *wtemp = new wchar_t [mbstowcs(NULL, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000)+1]; + mbstowcs(wmsg, (const char*)lpMsgBuf, 32000); + mbstowcs(wtemp, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000); + vtkErrorMacro(<< wcscat(wtemp, wmsg)); + delete [] wmsg; + delete [] wtemp; +#else + vtkErrorMacro("wglMakeCurrent failed in MakeCurrent(), error: " + << (LPCTSTR)lpMsgBuf); +#endif + ::LocalFree( lpMsgBuf ); + } + } + } + } +} + +// ---------------------------------------------------------------------------- +// Description: +// Tells if this window is the current OpenGL context for the calling thread. +bool vtkWin32OpenGLRenderWindow::IsCurrent() +{ + return this->ContextId!=0 && this->ContextId==wglGetCurrentContext(); +} + +// ---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::SetSize(int x, int y) +{ + static int resizing = 0; + if ((this->Size[0] != x) || (this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + + if (this->Interactor) + { + this->Interactor->SetSize(x, y); + } + + if (this->OffScreenRendering) + { + if(!this->CreatingOffScreenWindow) + { + if (!resizing) + { + resizing = 1; + this->CleanUpOffScreenRendering(); + this->CreateOffScreenWindow(x,y); + resizing = 0; + } + } + } + + else if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + if (this->ParentId) + { + SetWindowExtEx(this->DeviceContext,x,y,NULL); + SetViewportExtEx(this->DeviceContext,x,y,NULL); + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x, y, SWP_NOMOVE | SWP_NOZORDER); + } + else + { + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x+2*GetSystemMetrics(SM_CXFRAME), + y+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE | SWP_NOZORDER); + } + resizing = 0; + } + } + } +} + +void vtkWin32OpenGLRenderWindow::SetPosition(int x, int y) +{ + static int resizing = 0; + + if ((this->Position[0] != x) || (this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + SetWindowPos(this->WindowId,HWND_TOP,x,y, + 0, 0, SWP_NOSIZE | SWP_NOZORDER); + resizing = 0; + } + } + } +} + + +// End the rendering process and display the image. +void vtkWin32OpenGLRenderWindow::Frame(void) +{ + this->MakeCurrent(); + if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers) + { + // If this check is not enforced, we crash in offscreen rendering + if (this->DeviceContext) + { + // use global scope to get Win32 API SwapBuffers and not be + // confused with this->SwapBuffers + ::SwapBuffers(this->DeviceContext); + vtkDebugMacro(<< " SwapBuffers\n"); + } + } + else + { + glFlush(); + } +} + +int vtkWin32OpenGLRenderWindow::SupportsOpenGL() +{ + MakeCurrent(); + if (!this->DeviceContext) + { + return 0; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, + sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + return (pfd.dwFlags & PFD_SUPPORT_OPENGL) ? 1:0; + +} + + +int vtkWin32OpenGLRenderWindow::IsDirect() +{ + + MakeCurrent(); + if (!this->DeviceContext) + { + return 0; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, + sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + return (pfd.dwFlags & PFD_GENERIC_FORMAT) ? 0:1; + +} + + +const char* vtkWin32OpenGLRenderWindow::ReportCapabilities() +{ + MakeCurrent(); + + if (!this->DeviceContext) + { + return "no device context"; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, + sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + const char *glVendor = (const char *) glGetString(GL_VENDOR); + const char *glRenderer = (const char *) glGetString(GL_RENDERER); + const char *glVersion = (const char *) glGetString(GL_VERSION); + const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS); + + vtksys_ios::ostringstream strm; + strm << "OpenGL vendor string: " << glVendor << endl; + strm << "OpenGL renderer string: " << glRenderer << endl; + strm << "OpenGL version string: " << glVersion << endl; + strm << "OpenGL extensions: " << glExtensions << endl; + strm << "PixelFormat Descriptor:" << endl; + strm << "depth: " << static_cast(pfd.cDepthBits) << endl; + if (pfd.cColorBits <= 8) + { + strm << "class: PseudoColor" << endl; + } + else + { + strm << "class: TrueColor" << endl; + } + strm << "buffer size: " << static_cast(pfd.cColorBits) << endl; + strm << "level: " << static_cast(pfd.bReserved) << endl; + if (pfd.iPixelType == PFD_TYPE_RGBA) + { + strm << "renderType: rgba" << endl; + } + else + { + strm <<"renderType: ci" << endl; + } + if (pfd.dwFlags & PFD_DOUBLEBUFFER) { + strm << "double buffer: True" << endl; + } else { + strm << "double buffer: False" << endl; + } + if (pfd.dwFlags & PFD_STEREO) { + strm << "stereo: True" << endl; + } else { + strm << "stereo: False" << endl; + } + if (pfd.dwFlags & PFD_GENERIC_FORMAT) { + strm << "hardware acceleration: False" << endl; + } else { + strm << "hardware acceleration: True" << endl; + } + strm << "rgba: redSize=" << static_cast(pfd.cRedBits) << " greenSize=" << static_cast(pfd.cGreenBits) << "blueSize=" << static_cast(pfd.cBlueBits) << "alphaSize=" << static_cast(pfd.cAlphaBits) << endl; + strm << "aux buffers: " << static_cast(pfd.cAuxBuffers)<< endl; + strm << "depth size: " << static_cast(pfd.cDepthBits) << endl; + strm << "stencil size: " << static_cast(pfd.cStencilBits) << endl; + strm << "accum: redSize=" << static_cast(pfd.cAccumRedBits) << " greenSize=" << static_cast(pfd.cAccumGreenBits) << "blueSize=" << static_cast(pfd.cAccumBlueBits) << "alphaSize=" << static_cast(pfd.cAccumAlphaBits) << endl; + + delete[] this->Capabilities; + + size_t len = strm.str().length() + 1; + this->Capabilities = new char[len]; + strncpy(this->Capabilities, strm.str().c_str(), len); + + return this->Capabilities; +} + +typedef bool (APIENTRY *wglChoosePixelFormatARBType)(HDC, const int*, const float*, unsigned int, int*, unsigned int*); + +bool WGLisExtensionSupported(const char *extension) +{ + const size_t extlen = strlen(extension); + const char *supported = NULL; + + // Try To Use wglGetExtensionStringARB On Current DC, If Possible + PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB"); + + if (wglGetExtString) + { + supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC()); + } + + // If That Failed, Try Standard Opengl Extensions String + if (supported == NULL) + { + supported = (char*)glGetString(GL_EXTENSIONS); + } + + // If That Failed Too, Must Be No Extensions Supported + if (supported == NULL) + { + return false; + } + + // Begin Examination At Start Of String, Increment By 1 On False Match + for (const char* p = supported; ; p++) + { + // Advance p Up To The Next Possible Match + p = strstr(p, extension); + + if (p == NULL) + { + return false; // No Match + } + + // Make Sure That Match Is At The Start Of The String Or That + // The Previous Char Is A Space, Or Else We Could Accidentally + // Match "wglFunkywglExtension" With "wglExtension" + + // Also, Make Sure That The Following Character Is Space Or NULL + // Or Else "wglExtensionTwo" Might Match "wglExtension" + if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' ')) + { + return true; // Match + } + } +} + +void vtkWin32OpenGLRenderWindow::SetupPixelFormat(HDC hDC, DWORD dwFlags, + int debug, int bpp, + int zbpp) +{ + // Create a dummy window, needed for calling wglGetProcAddress. +#ifdef UNICODE + HWND tempId = CreateWindow(L"vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0); +#else + HWND tempId = CreateWindow("vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0); +#endif + HDC tempDC = GetDC(tempId); + PIXELFORMATDESCRIPTOR tempPfd; + memset(&tempPfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + tempPfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + tempPfd.nVersion = 1; + tempPfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + tempPfd.iPixelType = PFD_TYPE_RGBA; + int tempPixelFormat = ChoosePixelFormat(tempDC, &tempPfd); + SetPixelFormat(tempDC, tempPixelFormat, &tempPfd); + HGLRC tempContext = wglCreateContext(tempDC); + wglMakeCurrent(tempDC, tempContext); + + // First we try to use the newer wglChoosePixelFormatARB which enables + // features like multisamples. + int pixelFormat = 0; + wglChoosePixelFormatARBType wglChoosePixelFormatARB = + reinterpret_cast(wglGetProcAddress("wglChoosePixelFormatARB")); + if ((dwFlags & PFD_DRAW_TO_WINDOW) && wglChoosePixelFormatARB) + { + int attrib[] = { + vtkwgl::ACCELERATION_ARB, vtkwgl::FULL_ACCELERATION_ARB, + vtkwgl::SUPPORT_OPENGL_ARB, TRUE, + vtkwgl::DRAW_TO_WINDOW_ARB, TRUE, + vtkwgl::DOUBLE_BUFFER_ARB, TRUE, + vtkwgl::COLOR_BITS_ARB, bpp/4*3, + vtkwgl::DEPTH_BITS_ARB, zbpp/4*3, + vtkwgl::PIXEL_TYPE_ARB, vtkwgl::TYPE_RGBA_ARB, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned int n = 14; + if (this->AlphaBitPlanes) + { + attrib[n] = vtkwgl::ALPHA_BITS_ARB; + attrib[n+1] = bpp/4; + n += 2; + } + if (this->StencilCapable) + { + attrib[n] = vtkwgl::STENCIL_BITS_ARB; + attrib[n+1] = 8; + n += 2; + } + if (dwFlags & PFD_STEREO) + { + attrib[n] = vtkwgl::STEREO_ARB; + attrib[n+1] = TRUE; + n += 2; + } + unsigned int multiSampleAttributeIndex = 0; + if (this->MultiSamples > 1 && WGLisExtensionSupported("WGL_ARB_multisample")) + { + attrib[n] = vtkwgl::SAMPLE_BUFFERS_ARB; + attrib[n+1] = 1; + attrib[n+2] = vtkwgl::SAMPLES_ARB; + attrib[n+3] = this->MultiSamples; + multiSampleAttributeIndex = n+3; + n += 4; + } + unsigned int numFormats; + if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)) + { + // If the requested number of multisamples does not work, try + // scaling down the number of multisamples a few times. + if (multiSampleAttributeIndex) + { + attrib[multiSampleAttributeIndex] /= 2; + if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)) + { + attrib[multiSampleAttributeIndex] /= 2; + wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats); + } + } + } + PIXELFORMATDESCRIPTOR pfd; + DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd); + if (!SetPixelFormat(hDC, pixelFormat, &pfd)) + { + pixelFormat = 0; + } + } + + // Delete the dummy window + wglMakeCurrent(tempDC, 0); + wglDeleteContext(tempContext); + ReleaseDC(tempId, tempDC); + ::DestroyWindow(tempId); + + // If we got a valid pixel format in the process, we are done. + // Otherwise, we use the old approach of using ChoosePixelFormat. + if (pixelFormat) + { + return; + } + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size */ + 1, /* version */ + dwFlags , /* support double-buffering */ + PFD_TYPE_RGBA, /* color type */ + bpp, /* prefered color depth */ + 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ + this->AlphaBitPlanes ? bpp/4 : 0, /* no alpha buffer */ + 0, /* alpha bits (ignored) */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits (ignored) */ + zbpp, /* depth buffer */ + this->StencilCapable, /* stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0, /* no layer, visible, damage masks */ + }; + // Only try to set pixel format if we do not currently have one + int currentPixelFormat = GetPixelFormat(hDC); + // if there is a current pixel format, then make sure it + // supports OpenGL + if (currentPixelFormat != 0) + { + DescribePixelFormat(hDC, currentPixelFormat,sizeof(pfd), &pfd); + if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)) + { +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), + L"Invalid pixel format, no OpenGL support", + L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), + "Invalid pixel format, no OpenGL support", + "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + } + else + { + // hDC has no current PixelFormat, so + pixelFormat = ChoosePixelFormat(hDC, &pfd); + if (pixelFormat == 0) + { +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), L"ChoosePixelFormat failed.", L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + DescribePixelFormat(hDC, pixelFormat,sizeof(pfd), &pfd); + if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) + { + // int err = GetLastError(); +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), L"SetPixelFormat failed.", L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + } + if (debug && (dwFlags & PFD_STEREO) && !(pfd.dwFlags & PFD_STEREO)) + { + vtkGenericWarningMacro("No Stereo Available!"); + this->StereoCapableWindow = 0; + } +} + +void vtkWin32OpenGLRenderWindow::SetupPalette(HDC hDC) +{ + int pixelFormat = GetPixelFormat(hDC); + PIXELFORMATDESCRIPTOR pfd; + LOGPALETTE* pPal; + int paletteSize; + + DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + if (pfd.dwFlags & PFD_NEED_PALETTE) { + paletteSize = 1 << pfd.cColorBits; + } else { + return; + } + + pPal = (LOGPALETTE*) + malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); + pPal->palVersion = 0x300; + pPal->palNumEntries = paletteSize; + + /* build a simple RGB color palette */ + { + int redMask = (1 << pfd.cRedBits) - 1; + int greenMask = (1 << pfd.cGreenBits) - 1; + int blueMask = (1 << pfd.cBlueBits) - 1; + int i; + + for (i=0; ipalPalEntry[i].peRed = + (((i >> pfd.cRedShift) & redMask) * 255) / redMask; + pPal->palPalEntry[i].peGreen = + (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; + pPal->palPalEntry[i].peBlue = + (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; + pPal->palPalEntry[i].peFlags = 0; + } + } + + this->Palette = CreatePalette(pPal); + free(pPal); + + if (this->Palette) { + this->OldPalette = SelectPalette(hDC, this->Palette, FALSE); + RealizePalette(hDC); + } +} + + +LRESULT vtkWin32OpenGLRenderWindow::MessageProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + { + // nothing to be done here, opengl is initilized after the call to + // create now + return 0; + } + case WM_DESTROY: + this->Clean(); + if (this->DeviceContext) + { + ReleaseDC(this->WindowId, this->DeviceContext); + this->DeviceContext = NULL; + this->WindowId = NULL; + } + return 0; + case WM_SIZE: + /* track window size changes */ + if (this->ContextId) + { + this->SetSize((int) LOWORD(lParam),(int) HIWORD(lParam)); + return 0; + } + case WM_PALETTECHANGED: + /* realize palette if this is *not* the current window */ + if (this->ContextId && this->Palette && (HWND) wParam != hWnd) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); + UnrealizeObject(this->Palette); + this->OldPalette = SelectPalette(this->DeviceContext, + this->Palette, FALSE); + RealizePalette(this->DeviceContext); + this->Render(); + } + break; + case WM_QUERYNEWPALETTE: + /* realize palette if this is the current window */ + if (this->ContextId && this->Palette) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); + UnrealizeObject(this->Palette); + this->OldPalette = SelectPalette(this->DeviceContext, + this->Palette, FALSE); + RealizePalette(this->DeviceContext); + this->Render(); + return TRUE; + } + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + if (this->ContextId) + { + this->Render(); + } + EndPaint(hWnd, &ps); + return 0; + } + break; + case WM_ERASEBKGND: + return TRUE; + case WM_SETCURSOR: + if (HTCLIENT == LOWORD(lParam)) + { + this->SetCurrentCursor(this->GetCurrentCursor()); + return TRUE; + } + break; + default: + this->InvokeEvent(vtkCommand::RenderWindowMessageEvent, &message); + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +void vtkWin32OpenGLRenderWindow::InitializeApplication() +{ + // get the applicaiton instance if we don't have one already + if (!this->ApplicationInstance) + { + // if we have a parent window get the app instance from it + if (this->ParentId) + { + this->ApplicationInstance = (HINSTANCE)vtkGetWindowLong(this->ParentId,vtkGWL_HINSTANCE); + } + else + { + this->ApplicationInstance = GetModuleHandle(NULL); /*AfxGetInstanceHandle();*/ + } + } +} + +void vtkWin32OpenGLRenderWindow::CreateAWindow() +{ + if(this->WindowIdReferenceCount == 0) + { + static int count = 1; + char *windowName; + + if (!this->WindowId) + { + WNDCLASS wndClass; + this->DeviceContext = 0; + + int len = static_cast(strlen("Visualization Toolkit - Win32OpenGL #")) + + (int)ceil( (double) log10( (double)(count+1) ) ) + + 1; + windowName = new char [ len ]; + sprintf(windowName,"Visualization Toolkit - Win32OpenGL #%i",count++); + this->SetWindowName(windowName); + delete [] windowName; + + // has the class been registered ? +#ifdef UNICODE + if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass)) +#else + if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass)) +#endif + { + wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc; + wndClass.cbClsExtra = 0; + wndClass.hInstance = this->ApplicationInstance; + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndClass.lpszMenuName = NULL; +#ifdef UNICODE + wndClass.lpszClassName = L"vtkOpenGL"; +#else + wndClass.lpszClassName = "vtkOpenGL"; +#endif + // vtk doesn't use the first extra vtkLONG's worth of bytes, + // but app writers may want them, so we provide them. VTK + // does use the second vtkLONG's worth of bytes of extra space. + wndClass.cbWndExtra = 2 * sizeof(vtkLONG); + RegisterClass(&wndClass); + } + +#ifdef UNICODE + wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; + mbstowcs(wname, this->WindowName, 32000); +#endif + int x = ((this->Position[0] >= 0) ? this->Position[0] : 5); + int y = ((this->Position[1] >= 0) ? this->Position[1] : 5); + int height = ((this->Size[1] > 0) ? this->Size[1] : 300); + int width = ((this->Size[0] > 0) ? this->Size[0] : 300); + + /* create window */ + if (this->ParentId) + { +#ifdef UNICODE + this->WindowId = CreateWindow( + L"vtkOpenGL", wname, + WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, + x, y, width, height, + this->ParentId, NULL, this->ApplicationInstance, NULL); +#else + this->WindowId = CreateWindow( + "vtkOpenGL", this->WindowName, + WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, + x, y, width, height, + this->ParentId, NULL, this->ApplicationInstance, NULL); +#endif + } + else + { + DWORD style; + if (this->Borders) + { + style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } + else + { + style = WS_POPUP | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } + RECT r; + r.left = x; + r.top = y; + r.right = r.left + width; + r.bottom = r.top + height; + BOOL result = AdjustWindowRect( &r, style, FALSE ); + if (!result) + { + vtkErrorMacro("AdjustWindowRect failed, error: " << GetLastError()); + } +#ifdef UNICODE + this->WindowId = CreateWindow( + L"vtkOpenGL", wname, style, + x, y, r.right-r.left, r.bottom-r.top, + NULL, NULL, this->ApplicationInstance, NULL); +#else + this->WindowId = CreateWindow( + "vtkOpenGL", this->WindowName, style, + x, y, r.right-r.left, r.bottom-r.top, + NULL, NULL, this->ApplicationInstance, NULL); +#endif + } +#ifdef UNICODE + delete [] wname; +#endif + + if (!this->WindowId) + { + vtkErrorMacro("Could not create window, error: " << GetLastError()); + return; + } + // extract the create info + + /* display window */ + if(!this->OffScreenRendering) + { + ShowWindow(this->WindowId, SW_SHOW); + } + //UpdateWindow(this->WindowId); + this->OwnWindow = 1; + vtkSetWindowLong(this->WindowId,sizeof(vtkLONG),(intptr_t)this); + } + if (!this->DeviceContext) + { + this->DeviceContext = GetDC(this->WindowId); + } + if (this->StereoCapableWindow) + { + this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | + PFD_STEREO, this->GetDebug(), 32, 32); + } + else + { + this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, + this->GetDebug(), 32, 32); + } + this->SetupPalette(this->DeviceContext); + this->ContextId = wglCreateContext(this->DeviceContext); + if (this->ContextId == NULL) + { + vtkErrorMacro("wglCreateContext failed in CreateAWindow(), error: " << GetLastError()); + } + this->MakeCurrent(); + + // wipe out any existing display lists + vtkRenderer* ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(0); + ren->SetRenderWindow(this); + } + this->OpenGLInit(); + this->Mapped = 1; + this->WindowIdReferenceCount = 1; + } + else + { + ++this->WindowIdReferenceCount; + } +} + +// Initialize the window for rendering. +void vtkWin32OpenGLRenderWindow::WindowInitialize() +{ + // create our own window if not already set + this->OwnWindow = 0; + if (!this->MFChandledWindow) + { + this->InitializeApplication(); + this->CreateAWindow(); + } + else + { + this->MakeCurrent(); // hsr + this->OpenGLInit(); + } + + // set the DPI + this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY)); +} + +// Initialize the rendering window. +void vtkWin32OpenGLRenderWindow::Initialize (void) +{ + // make sure we havent already been initialized + if (!this->OffScreenRendering && !this->ContextId) + { + this->WindowInitialize(); + } + else + { + if(this->OffScreenRendering && !(this->ContextId || + this->OffScreenUseFrameBuffer)) + { + this->InitializeApplication(); + int width = ((this->Size[0] > 0) ? this->Size[0] : 300); + int height = ((this->Size[1] > 0) ? this->Size[1] : 300); + this->CreateOffScreenWindow(width,height); + } + } +} + +void vtkWin32OpenGLRenderWindow::Finalize (void) +{ + if (this->CursorHidden) + { + this->ShowCursor(); + } + + if (this->OffScreenRendering) + { + this->CleanUpOffScreenRendering(); + } + this->DestroyWindow(); +} + +void vtkWin32OpenGLRenderWindow::DestroyWindow() +{ + if(this->WindowIdReferenceCount > 0) + { + --this->WindowIdReferenceCount; + if(this->WindowIdReferenceCount == 0) + { + this->Clean(); + if (this->WindowId) + { + ReleaseDC(this->WindowId, this->DeviceContext); + // can't set WindowId=NULL, needed for DestroyWindow + this->DeviceContext = NULL; + + // clear the extra data before calling destroy + vtkSetWindowLong(this->WindowId,sizeof(vtkLONG),(vtkLONG)0); + if(this->OwnWindow) + { + ::DestroyWindow(this->WindowId); + this->WindowId=0; + } + } + } + } +} + +// Get the current size of the window. +int *vtkWin32OpenGLRenderWindow::GetSize(void) +{ + // if we aren't mapped then just return the ivar + if (this->Mapped) + { + RECT rect; + + // Find the current window size + if (GetClientRect(this->WindowId, &rect)) + { + this->Size[0] = rect.right; + this->Size[1] = rect.bottom; + } + else + { + this->Size[0] = 0; + this->Size[1] = 0; + } + + } + + return this->vtkOpenGLRenderWindow::GetSize(); +} + +// Get the current size of the window. +int *vtkWin32OpenGLRenderWindow::GetScreenSize(void) +{ + RECT rect; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + this->Size[0] = rect.right - rect.left; + this->Size[1] = rect.bottom - rect.top; + + return this->Size; +} + +// Get the position in screen coordinates of the window. +int *vtkWin32OpenGLRenderWindow::GetPosition(void) +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + // Find the current window position + // x,y,&this->Position[0],&this->Position[1],&child); + + return this->Position; +} + +// Change the window to fill the entire screen. +void vtkWin32OpenGLRenderWindow::SetFullScreen(int arg) +{ + int *temp; + + if (this->FullScreen == arg) + { + return; + } + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + temp = this->GetPosition(); + this->OldScreen[0] = temp[0]; + this->OldScreen[1] = temp[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + this->Modified(); +} + +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkWin32OpenGLRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->ContextId == 0) + { + vtkRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + + +// Set the preferred window size to full screen. +void vtkWin32OpenGLRenderWindow::PrefFullScreen() +{ + int *size; + + size = this->GetScreenSize(); + + // use full screen + this->Position[0] = 0; + this->Position[1] = 0; + this->Size[0] = size[0] - 2*GetSystemMetrics(SM_CXFRAME); + this->Size[1] = size[1] - + 2*GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION); + + // don't show borders + this->Borders = 0; +} + +// Remap the window. +void vtkWin32OpenGLRenderWindow::WindowRemap() +{ + // close everything down + this->Finalize(); + + // set the default windowid + this->WindowId = this->NextWindowId; + this->NextWindowId = 0; + + // and set it up! + this->Initialize(); +} + +void vtkWin32OpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ContextId: " << this->ContextId << "\n"; + os << indent << "Next Window Id: " << this->NextWindowId << "\n"; + os << indent << "Window Id: " << this->WindowId << "\n"; +} + +// Get the window id. +HWND vtkWin32OpenGLRenderWindow::GetWindowId() +{ + vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n"); + + return this->WindowId; +} + +// Set the window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting WindowId to " << arg << "\n"); + + if (arg != this->WindowId) + { + this->WindowId = arg; + if (this->ContextId) + { + wglDeleteContext(this->ContextId); + } + this->ContextId = 0; + this->DeviceContext = 0; + } +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->WindowId = (HWND)tmp; + vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n"); +} + +void vtkWin32OpenGLRenderWindow::SetNextWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->SetNextWindowId((HWND)tmp); +} + +void vtkWin32OpenGLRenderWindow::SetDisplayId(void * arg) +{ + this->DeviceContext = (HDC) arg; +} + +void vtkWin32OpenGLRenderWindow::SetContextId(HGLRC arg) +{ + this->ContextId = arg; +} + +void vtkWin32OpenGLRenderWindow::SetDeviceContext(HDC arg) +{ + this->DeviceContext = arg; + this->MFChandledWindow = TRUE; +} + +// Sets the HWND id of the window that WILL BE created. +void vtkWin32OpenGLRenderWindow::SetParentInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->ParentId = (HWND)tmp; + vtkDebugMacro(<< "Setting ParentId to " << this->ParentId << "\n"); +} + +// Set the window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetParentId(HWND arg) +{ + vtkDebugMacro(<< "Setting ParentId to " << arg << "\n"); + + this->ParentId = arg; +} + +// Set the window id of the new window once a WindowRemap is done. +void vtkWin32OpenGLRenderWindow::SetNextWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting NextWindowId to " << arg << "\n"); + + this->NextWindowId = arg; +} + +void vtkWin32OpenGLRenderWindow::SetNextWindowId(void *arg) +{ + this->SetNextWindowId((HWND)arg); +} + +// Begin the rendering process. +void vtkWin32OpenGLRenderWindow::Start(void) +{ + // if the renderer has not been initialized, do so now + if (!this->ContextId) + { + this->Initialize(); + } + + // set the current window + this->MakeCurrent(); +} + + +void vtkWin32OpenGLRenderWindow::SetOffScreenRendering(int offscreen) +{ + if (offscreen == this->OffScreenRendering) + { + return; + } + + this->vtkRenderWindow::SetOffScreenRendering(offscreen); + + if (offscreen) + { + int size[2]; + size[0] = (this->Size[0] > 0) ? this->Size[0] : 300; + size[1] = (this->Size[1] > 0) ? this->Size[1] : 300; + this->SaveScreenRendering(); + this->CreateOffScreenWindow(size[0],size[1]); + } + else + { + this->CleanUpOffScreenRendering(); + if (!this->WindowId) + { + this->WindowInitialize(); + this->OpenGLInit(); + if (this->Interactor) + { + this->Interactor->ReInitialize(); + } + this->DoubleBuffer = 1; + } + else + { + this->ResumeScreenRendering(); + } + } +} + +void vtkWin32OpenGLRenderWindow::SaveScreenRendering() +{ + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; +} + +void vtkWin32OpenGLRenderWindow::CreateOffScreenWindow(int width, + int height) +{ + int status = this->CreatingOffScreenWindow; + this->CreatingOffScreenWindow = 1; + if(!this->CreateHardwareOffScreenWindow(width,height)) + { +#ifdef UNICODE + HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); +#else + HDC dc = CreateDC("DISPLAY", 0, 0, 0); +#endif + this->CreateOffScreenDC(width,height,dc); + DeleteDC(dc); + } + this->CreatingOffScreenWindow = status; +} + +void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(int xsize, int ysize, + HDC aHdc) +{ + int dataWidth = ((xsize*3+3)/4)*4; + + this->MemoryDataHeader.bmiHeader.biSize = 40; + this->MemoryDataHeader.bmiHeader.biWidth = xsize; + this->MemoryDataHeader.bmiHeader.biHeight = ysize; + this->MemoryDataHeader.bmiHeader.biPlanes = 1; + this->MemoryDataHeader.bmiHeader.biBitCount = 24; + this->MemoryDataHeader.bmiHeader.biCompression = BI_RGB; + this->MemoryDataHeader.bmiHeader.biClrUsed = 0; + this->MemoryDataHeader.bmiHeader.biClrImportant = 0; + this->MemoryDataHeader.bmiHeader.biSizeImage = dataWidth*ysize; + this->MemoryDataHeader.bmiHeader.biXPelsPerMeter = 10000; + this->MemoryDataHeader.bmiHeader.biYPelsPerMeter = 10000; + + HBITMAP dib = CreateDIBSection(aHdc, + &this->MemoryDataHeader, DIB_RGB_COLORS, + (void **)(&(this->MemoryData)), NULL, 0); + SIZE oldSize; + SetBitmapDimensionEx(dib, xsize, ysize, &oldSize); + // try using a DIBsection + this->CreateOffScreenDC(dib, aHdc); +} + +void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(HBITMAP hbmp, HDC aHdc) +{ + BITMAP bm; + GetObject(hbmp, sizeof(BITMAP), &bm); + + this->MemoryBuffer = hbmp; + + // Create a compatible device context + this->MemoryHdc = (HDC)CreateCompatibleDC(aHdc); + + // Put the bitmap into the device context + SelectObject(this->MemoryHdc, this->MemoryBuffer); + + // Renderers will need to redraw anything cached in display lists + this->CleanUpRenderers(); + + // adjust settings for renderwindow + this->Mapped =0; + this->Size[0] = bm.bmWidth; + this->Size[1] = bm.bmHeight; + + this->DeviceContext = this->MemoryHdc; + this->DoubleBuffer = 0; + this->SetupPixelFormat(this->DeviceContext, + PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI | + PFD_DRAW_TO_BITMAP, this->GetDebug(), 24, 32); + this->SetupPalette(this->DeviceContext); + this->ContextId = wglCreateContext(this->DeviceContext); + if (this->ContextId == NULL) + { + vtkErrorMacro("wglCreateContext failed in CreateOffScreenDC(), error: " << GetLastError()); + } + this->MakeCurrent(); + this->OpenGLInit(); +} + +void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(int xsize, int ysize, + HDC aHdc) +{ + // save the current state + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; + + this->CreateOffScreenDC(xsize, ysize, aHdc); +} + +void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(HBITMAP hbmp) +{ +#ifdef UNICODE + HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); +#else + HDC dc = CreateDC("DISPLAY", 0, 0, 0); +#endif + + // save the current state + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; + + this->CreateOffScreenDC(hbmp, dc); + DeleteDC(dc); +} + +HDC vtkWin32OpenGLRenderWindow::GetMemoryDC() +{ + return this->MemoryHdc; +} + +void vtkWin32OpenGLRenderWindow::CleanUpOffScreenRendering(void) +{ + if(this->OffScreenUseFrameBuffer) + { + this->DestroyHardwareOffScreenWindow(); + } + else + { + if (!this->MemoryHdc) + { + return; + } + + GdiFlush(); + + // we need to release resources + this->CleanUpRenderers(); + DeleteDC(this->MemoryHdc); + this->MemoryHdc = (HDC)0; + DeleteObject(this->MemoryBuffer); + if (wglDeleteContext(this->ContextId) != TRUE) + { + vtkErrorMacro("wglDeleteContext failed in CleanUpOffScreenRendering(), error: " << GetLastError()); + } + this->ContextId=0; + } +} + +void vtkWin32OpenGLRenderWindow::ResumeScreenRendering(void) +{ + // release OpenGL graphics resources before switch back to on-screen. + if(this->ContextId!=0) + { + this->MakeCurrent(); + this->CleanUpRenderers(); + } + + this->Mapped = this->ScreenMapped; + this->Size[0] = this->ScreenWindowSize[0]; + this->Size[1] = this->ScreenWindowSize[1]; + this->DeviceContext = this->ScreenDeviceContext; + this->DoubleBuffer = this->ScreenDoubleBuffer; + this->ContextId = this->ScreenContextId; + this->MakeCurrent(); +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::HideCursor() +{ + if (this->CursorHidden) + { + return; + } + this->CursorHidden = 1; + + ::ShowCursor(!this->CursorHidden); +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::ShowCursor() +{ + if (!this->CursorHidden) + { + return; + } + this->CursorHidden = 0; + + ::ShowCursor(!this->CursorHidden); +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::SetCursorPosition(int x, int y) +{ + int *size = this->GetSize(); + + POINT point; + point.x = x; + point.y = size[1] - y - 1; + + if (ClientToScreen(this->WindowId, &point)) + { + SetCursorPos(point.x, point.y); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::SetCurrentCursor(int shape) +{ + if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) ) + { + return; + } + this->Superclass::SetCurrentCursor(shape); + LPCTSTR cursorName = 0; + switch (shape) + { + case VTK_CURSOR_DEFAULT: + case VTK_CURSOR_ARROW: + cursorName = IDC_ARROW; + break; + case VTK_CURSOR_SIZENE: + case VTK_CURSOR_SIZESW: + cursorName = IDC_SIZENESW; + break; + case VTK_CURSOR_SIZENW: + case VTK_CURSOR_SIZESE: + cursorName = IDC_SIZENWSE; + break; + case VTK_CURSOR_SIZENS: + cursorName = IDC_SIZENS; + break; + case VTK_CURSOR_SIZEWE: + cursorName = IDC_SIZEWE; + break; + case VTK_CURSOR_SIZEALL: + cursorName = IDC_SIZEALL; + break; + case VTK_CURSOR_HAND: +#if(WINVER >= 0x0500) + cursorName = IDC_HAND; +#else + cursorName = IDC_ARROW; +#endif + break; + case VTK_CURSOR_CROSSHAIR: + cursorName = IDC_CROSS; + break; + } + + if (cursorName) + { + HANDLE cursor = + LoadImage(0,cursorName,IMAGE_CURSOR,0,0,LR_SHARED | LR_DEFAULTSIZE); + SetCursor((HCURSOR)cursor); + } +} diff --git a/Core/Code/Testing/files.cmake b/Core/Code/Testing/files.cmake index 61f65fd36f..50b17149b7 100644 --- a/Core/Code/Testing/files.cmake +++ b/Core/Code/Testing/files.cmake @@ -1,168 +1,173 @@ # tests with no extra command line parameter set(MODULE_TESTS mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry2DTest.cpp mitkGeometry3DTest.cpp mitkGeometry3DEqualTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageEqualTest.cpp mitkImageDataItemTest.cpp #mitkImageMapper2DTest.cpp mitkImageGeneratorTest.cpp mitkBaseDataTest.cpp #mitkImageToItkTest.cpp mitkImportItkImageTest.cpp mitkGrabItkImageMemoryTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp #mitkITKThreadingTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp #mitkPipelineSmartPointerCorrectnessTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetEqualTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp #mitkRegistrationBaseTest.cpp #mitkSegmentationInterpolationTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp ##mitkStateMachineContainerTest.cpp ## rewrite test, indirect since no longer exported Bug 14529 mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceEqualTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeSlicedGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp #mitkAbstractTransformGeometryTest.cpp mitkStepperTest.cpp itkTotalVariationDenoisingImageFilterTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp mitkShaderRepositoryTest.cpp mitkPlanePositionManagerTest.cpp mitkAffineTransformBaseTest.cpp mitkPropertyAliasesTest.cpp mitkPropertyDescriptionsTest.cpp mitkPropertyExtensionsTest.cpp mitkPropertyFiltersTest.cpp ) # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkImageTimeSelectorTest.cpp #only runs on images mitkImageAccessorTest.cpp #only runs on images mitkDataNodeFactoryTest.cpp #runs on all types of data ) set(MODULE_SURFACE_TESTS mitkSurfaceVtkWriterTest.cpp #only runs on surfaces mitkDataNodeFactoryTest.cpp #runs on all types of data ) # list of images for which the tests are run set(MODULE_TESTIMAGES US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) set(MODULE_TESTSURFACES binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS #mitkLabeledImageToSurfaceFilterTest.cpp #mitkExternalToolsTest.cpp mitkDataStorageTest.cpp mitkDataNodeTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkEventMapperTest.cpp mitkEventConfigTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkImageVtkMapper2DTransferFunctionTest.cpp mitkIOUtilTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp mitkSurfaceGLMapper2DColorTest.cpp mitkSurfaceGLMapper2DOpacityTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp mitkPointSetVtkMapper2DTest.cpp mitkPointSetVtkMapper2DImageTest.cpp mitkPointSetVtkMapper2DGlyphTypeTest.cpp mitkLabelOverlay3DRendering2DTest.cpp mitkLabelOverlay3DRendering3DTest.cpp mitkTextOverlay2DRenderingTest.cpp mitkTextOverlay2DLayouterRenderingTest.cpp mitkTextOverlay3DRendering2DTest.cpp mitkTextOverlay3DRendering3DTest.cpp mitkTextOverlay3DColorRenderingTest.cpp + mitkVTKRenderWindowSizeTest.cpp ) +if (${VTK_MAJOR_VERSION} VERSION_LESS 6) # test can be removed with VTK 6 + set(MODULE_TESTS ${MODULE_TESTS} mitkVTKRenderWindowSizeTest.cpp) +endif() + set(MODULE_RESOURCE_FILES Interactions/AddAndRemovePoints.xml Interactions/globalConfig.xml Interactions/StatemachineTest.xml Interactions/StatemachineConfigTest.xml ) # Create an artificial module initializing class for # the usServiceListenerTest.cpp usFunctionGenerateExecutableInit(testdriver_init_file IDENTIFIER ${MODULE_NAME}TestDriver ) # Embed the resources set(testdriver_resources ) usFunctionEmbedResources(testdriver_resources EXECUTABLE_NAME ${MODULE_NAME}TestDriver ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Resources FILES ${MODULE_RESOURCE_FILES} ) set(TEST_CPP_FILES ${testdriver_init_file} ${testdriver_resources}) diff --git a/Core/Code/Testing/mitkVTKRenderWindowSizeTest.cpp b/Core/Code/Testing/mitkVTKRenderWindowSizeTest.cpp new file mode 100644 index 0000000000..c5a968808c --- /dev/null +++ b/Core/Code/Testing/mitkVTKRenderWindowSizeTest.cpp @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "mitkTestingMacros.h" + +void CheckRWSize(unsigned int width, unsigned int height) +{ + MITK_TEST_OUTPUT(<<"Requesting VTK render window of size " << width << "x" << height ); + vtkSmartPointer renderWindowVTK = vtkRenderWindow::New(); + renderWindowVTK->SetSize( width, height ); + renderWindowVTK->SetOffScreenRendering(1); // seems to be related to off-screen rendering (only?) + + int* renderWindowSize = renderWindowVTK->GetSize(); + + MITK_TEST_CONDITION( renderWindowSize[0] >= width, " Window is at least " << width << "px wide (actually:" << renderWindowSize[0] << ")" ); + MITK_TEST_CONDITION( renderWindowSize[1] >= height, " Window is at least " << height << "px high (actually:" << renderWindowSize[1] << ")" ); +} + +/** + Check if a patch to VTK is applied as in http://paraview.org/Bug/view.php?id=14122 + + Bug description from there: + + " + After moving over to Visual Studio 2012, we found a strange problem where vtkRenderWindow GetSize() + returns something different than what was provided to SetSize(). + Specifically, width and height are 8 pixels less than expected. + I found a problem report which appears to describe what we are seeing. The problem goes away if we change the desktop theme to Windows Classic. + " + + the patch from this bug should be applied to MITK's default VTK version. + + Test can be removed with VTK 6. +*/ +int mitkVTKRenderWindowSizeTest(int /*argc*/, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("mitkVTKRenderWindowSizeTest") + + // some power of two default sizes + CheckRWSize(128, 128); + CheckRWSize(256, 256); + CheckRWSize(512, 512); + + // some other size + CheckRWSize(300, 200); + CheckRWSize(150, 243); + + MITK_TEST_END() +}