Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1477 lines
40 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkWin32OpenGLRenderWindow.cxx,v $
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 <math.h>
#if defined(_MSC_VER) || defined (__BORLANDC__)
# include "vtkWindows.h"
# include <GL/glaux.h>
#else
# include "vtkOpenGL.h"
#endif
vtkCxxRevisionMacro(vtkWin32OpenGLRenderWindow, "$Revision: 1.130 $");
vtkStandardNewMacro(vtkWin32OpenGLRenderWindow);
#define VTK_MAX_LIGHTS 8
#if ( _MSC_VER >= 1300 ) // Visual studio .NET
#pragma warning ( disable : 4311 )
#pragma warning ( disable : 4312 )
# define vtkGWLP_HINSTANCE GWLP_HINSTANCE
# define vtkGetWindowLong GetWindowLongPtr
# define vtkSetWindowLong SetWindowLongPtr
#else // regular Visual studio
# define vtkGWLP_HINSTANCE GWL_HINSTANCE
# define vtkGetWindowLong GetWindowLong
# define vtkSetWindowLong SetWindowLong
#endif //
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;
}
vtkWin32OpenGLRenderWindow::~vtkWin32OpenGLRenderWindow()
{
this->Finalize();
delete[] this->Capabilities;
}
void vtkWin32OpenGLRenderWindow::Clean()
{
vtkRenderer *ren;
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
}
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
vtkCollectionSimpleIterator rsit;
this->Renderers->InitTraversal(rsit);
for ( ren = (vtkOpenGLRenderer *) this->Renderers->GetNextRenderer(rsit);
ren != NULL;
ren = (vtkOpenGLRenderer *) this->Renderers->GetNextRenderer(rsit) )
{
ren->SetRenderWindow(NULL);
}
if (wglMakeCurrent(NULL, 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;
}
}
LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message,
WPARAM wParam,
LPARAM lParam)
{
vtkWin32OpenGLRenderWindow *me =
(vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,4);
// forward to actual object
if (me)
{
return me->MessageProc(hWnd, message, wParam, lParam);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
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 );
}
}
}
}
}
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->OffScreenRendering)
{
if (!resizing)
{
resizing = 1;
this->CleanUpOffScreenRendering();
#ifdef UNICODE
HDC dc = CreateDC(L"DISPLAY", 0, 0, 0);
#else
HDC dc = CreateDC("DISPLAY", 0, 0, 0);
#endif
this->CreateOffScreenDC(x, y, dc);
DeleteDC(dc);
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)
{
// 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);
ostrstream 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<int>(pfd.cDepthBits) << endl;
if (pfd.cColorBits <= 8)
{
strm << "class: PseudoColor" << endl;
}
else
{
strm << "class: TrueColor" << endl;
}
strm << "buffer size: " << static_cast<int>(pfd.cColorBits) << endl;
strm << "level: " << static_cast<int>(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<int>(pfd.cRedBits) << " greenSize=" << static_cast<int>(pfd.cGreenBits) << "blueSize=" << static_cast<int>(pfd.cBlueBits) << "alphaSize=" << static_cast<int>(pfd.cAlphaBits) << endl;
strm << "aux buffers: " << static_cast<int>(pfd.cAuxBuffers)<< endl;
strm << "depth size: " << static_cast<int>(pfd.cDepthBits) << endl;
strm << "stencil size: " << static_cast<int>(pfd.cStencilBits) << endl;
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;
strm << ends;
delete[] this->Capabilities;
this->Capabilities = strm.str();
return this->Capabilities;
}
void vtkWin32OpenGLRenderWindow::SetupPixelFormat(HDC hDC, DWORD dwFlags,
int debug, int bpp,
int zbpp)
{
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 */
0, /* no stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0, /* no layer, visible, damage masks */
};
int pixelFormat;
// 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; i<paletteSize; ++i) {
pPal->palPalEntry[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;
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,vtkGWLP_HINSTANCE);
}
else
{
this->ApplicationInstance = GetModuleHandle(NULL); /*AfxGetInstanceHandle();*/
}
}
}
void vtkWin32OpenGLRenderWindow::CreateAWindow(int x, int y, int width,
int height)
{
static int count=1;
char *windowName;
if (!this->WindowId)
{
WNDCLASS wndClass;
this->DeviceContext = 0;
int len = static_cast<int>(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 4 bytes, but app writers
// may want them, so we provide them. VTK does use the second
// four bytes of extra space.
wndClass.cbWndExtra = 8;
RegisterClass(&wndClass);
}
#ifdef UNICODE
wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1];
mbstowcs(wname, this->WindowName, 32000);
#endif
/* 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*/;
}
#ifdef UNICODE
this->WindowId = CreateWindow(
L"vtkOpenGL", wname, style,
x,y, width+2*GetSystemMetrics(SM_CXFRAME),
height+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION),
NULL, NULL, this->ApplicationInstance, NULL);
#else
this->WindowId = CreateWindow(
"vtkOpenGL", this->WindowName, style,
x,y, width+2*GetSystemMetrics(SM_CXFRAME),
height+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION),
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 */
ShowWindow(this->WindowId, SW_SHOW);
//UpdateWindow(this->WindowId);
this->OwnWindow = 1;
vtkSetWindowLong(this->WindowId,4,(LONG)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;
}
// Initialize the window for rendering.
void vtkWin32OpenGLRenderWindow::WindowInitialize()
{
int x, y, width, height;
x = ((this->Position[0] >= 0) ? this->Position[0] : 5);
y = ((this->Position[1] >= 0) ? this->Position[1] : 5);
height = ((this->Size[1] > 0) ? this->Size[1] : 300);
width = ((this->Size[0] > 0) ? this->Size[0] : 300);
// create our own window if not already set
this->OwnWindow = 0;
if (!this->MFChandledWindow)
{
this->InitializeApplication();
this->CreateAWindow(x,y,width,height);
}
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->ContextId)
{
return;
}
// now initialize the window
if (this->OffScreenRendering)
{
this->InitializeApplication();
}
else
{
this->WindowInitialize();
}
}
void vtkWin32OpenGLRenderWindow::Finalize (void)
{
if (this->CursorHidden)
{
this->ShowCursor();
}
if (this->OffScreenRendering)
{
this->CleanUpOffScreenRendering();
}
if (this->WindowId)
{
this->Clean();
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,4,(LONG)0);
if(this->OwnWindow)
{
DestroyWindow(this->WindowId);
}
}
}
// 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->WindowId == 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;
#ifdef UNICODE
HDC dc = CreateDC(L"DISPLAY", 0, 0, 0);
#else
HDC dc = CreateDC("DISPLAY", 0, 0, 0);
#endif
this->SetupMemoryRendering(size[0], size[1], dc);
DeleteDC(dc);
}
else
{
if (!this->WindowId)
{
vtkRenderer* ren;
this->CleanUpOffScreenRendering();
this->WindowInitialize();
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(this);
}
this->OpenGLInit();
if (this->Interactor)
{
this->Interactor->ReInitialize();
}
this->DoubleBuffer = 1;
}
else
{
this->ResumeScreenRendering();
}
}
}
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
vtkRenderer *ren;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
}
// 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();
// Renderers will need to redraw anything cached in display lists
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(this);
}
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->MemoryHdc)
{
return;
}
GdiFlush();
// we need to release resources
vtkRenderer *ren;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
}
DeleteDC(this->MemoryHdc);
this->MemoryHdc = (HDC)0;
DeleteObject(this->MemoryBuffer);
if (wglDeleteContext(this->ContextId) != TRUE)
{
vtkErrorMacro("wglDeleteContext failed in CleanUpOffScreenRendering(), error: " << GetLastError());
}
}
void vtkWin32OpenGLRenderWindow::ResumeScreenRendering(void)
{
this->CleanUpOffScreenRendering();
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();
vtkRenderer* ren;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(this);
}
}
//----------------------------------------------------------------------------
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;
}
if (cursorName)
{
HANDLE cursor =
LoadImage(0,cursorName,IMAGE_CURSOR,0,0,LR_SHARED | LR_DEFAULTSIZE);
SetCursor((HCURSOR)cursor);
}
}