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.
 
 
 
 
 
 

1202 lines
34 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkCarbonRenderWindow.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 "vtkCarbonRenderWindow.h"
#include "vtkCarbonRenderWindowInteractor.h"
#include "vtkIdList.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 <math.h>
vtkCxxRevisionMacro(vtkCarbonRenderWindow, "$Revision: 1.39 $");
vtkStandardNewMacro(vtkCarbonRenderWindow);
//----------------------------------------------------------------------------
// Dump agl errors to string, return error code
OSStatus aglReportError ()
{
GLenum err = aglGetError();
if (AGL_NO_ERROR != err)
cout << ((char *)aglErrorString(err));
// ensure we are returning an OSStatus noErr if no error condition
if (err == AGL_NO_ERROR)
return noErr;
else
return (OSStatus) err;
}
//----------------------------------------------------------------------------
// if error dump gl errors, return error
OSStatus glReportError ()
{
GLenum err = glGetError();
switch (err)
{
case GL_NO_ERROR:
break;
case GL_INVALID_ENUM:
cout << "GL Error: Invalid enumeration\n";
break;
case GL_INVALID_VALUE:
cout << "GL Error: Invalid value\n";
break;
case GL_INVALID_OPERATION:
cout << "GL Error: Invalid operation\n";
break;
case GL_STACK_OVERFLOW:
cout << "GL Error: Stack overflow\n";
break;
case GL_STACK_UNDERFLOW:
cout << "GL Error: Stack underflow\n";
break;
case GL_OUT_OF_MEMORY:
cout << "GL Error: Out of memory\n";
break;
}
// ensure we are returning an OSStatus noErr if no error condition
if (err == GL_NO_ERROR)
return noErr;
else
return (OSStatus) err;
}
//----------------------------------------------------------------------------
// CheckRenderer
// looks at renderer attributes it has at least the VRAM is accelerated
// Inputs: hGD: GDHandle to device to look at
// pVRAM: pointer to VRAM in bytes required; out is actual VRAM if
// a renderer was found, otherwise it is the input parameter
// pTextureRAM: pointer to texture RAM in bytes required; out is same
// (implementation assume VRAM returned by card is total
// so we add texture and VRAM)
// fAccelMust: do we check for acceleration
// Returns: true if renderer for the requested device complies, false otherwise
static Boolean CheckRenderer (GDHandle hGD, long* pVRAM, long* pTextureRAM,
GLint* pDepthSizeSupport, Boolean fAccelMust)
{
AGLRendererInfo info, head_info;
GLint inum;
GLint dAccel = 0;
GLint dVRAM = 0, dMaxVRAM = 0;
Boolean canAccel = false, found = false;
head_info = aglQueryRendererInfo(&hGD, 1);
aglReportError();
if(!head_info)
{
cout << "aglQueryRendererInfo error.\n";
return false;
}
else
{
info = head_info;
inum = 0;
// Check for accelerated renderer, if so ignore non-accelerated ones
// Prevents returning info on software renderer when get a hardware one
while (info)
{
aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
aglReportError ();
if (dAccel)
canAccel = true;
info = aglNextRendererInfo(info);
aglReportError ();
inum++;
}
info = head_info;
inum = 0;
while (info)
{
aglDescribeRenderer (info, AGL_ACCELERATED, &dAccel);
aglReportError ();
// if we can accel then we will choose the accelerated renderer
// how about compliant renderers???
if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel)))
{
aglDescribeRenderer (info, AGL_VIDEO_MEMORY, &dVRAM);
// we assume that VRAM returned is total thus add
// texture and VRAM required
aglReportError ();
if (dVRAM >= (*pVRAM + *pTextureRAM))
{
if (dVRAM >= dMaxVRAM) // find card with max VRAM
{
aglDescribeRenderer (info, AGL_DEPTH_MODES, pDepthSizeSupport);
// which depth buffer modes are supported
aglReportError ();
dMaxVRAM = dVRAM; // store max
found = true;
}
}
}
info = aglNextRendererInfo(info);
aglReportError ();
inum++;
}
}
aglDestroyRendererInfo(head_info);
if (found) // if found a card with enough VRAM and meets the accel criteria
{
*pVRAM = dMaxVRAM; // return VRAM
return true;
}
// VRAM will remain to same as it did when sent in
return false;
}
//----------------------------------------------------------------------------
// CheckAllDeviceRenderers
// looks at renderer attributes and each device must have at least one
// renderer that fits the profile.
// Inputs: pVRAM: pointer to VRAM in bytes required;
// out is actual min VRAM of all renderers found,
// otherwise it is the input parameter
// pTextureRAM: pointer to texture RAM in bytes required;
// out is same (implementation assumes VRAM returned
// by card is total so we add texture and VRAM)
// fAccelMust: do we check fro acceleration
// Returns: true if any renderer on each device complies (not necessarily
// the same renderer), false otherwise
static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM,
GLint* pDepthSizeSupport,
Boolean fAccelMust)
{
AGLRendererInfo info, head_info;
GLint inum;
GLint dAccel = 0;
GLint dVRAM = 0, dMaxVRAM = 0;
Boolean canAccel = false, found = false, goodCheck = true;
long MinVRAM = 0x8FFFFFFF; // max long
GDHandle hGD = GetDeviceList (); // get the first screen
while (hGD && goodCheck)
{
head_info = aglQueryRendererInfo(&hGD, 1);
aglReportError ();
if(!head_info)
{
cout << "aglQueryRendererInfo error";
return false;
}
else
{
info = head_info;
inum = 0;
// if accelerated renderer, ignore non-accelerated ones
// prevents returning info on software renderer when get hardware one
while (info)
{
aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
aglReportError ();
if (dAccel)
canAccel = true;
info = aglNextRendererInfo(info);
aglReportError ();
inum++;
}
info = head_info;
inum = 0;
while (info)
{
aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
aglReportError ();
// if we can accel then we will choose the accelerated renderer
// how about compliant renderers???
if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel)))
{
aglDescribeRenderer(info, AGL_VIDEO_MEMORY, &dVRAM);
aglReportError ();
if (dVRAM >= (*pVRAM + *pTextureRAM))
{
if (dVRAM >= dMaxVRAM) // find card with max VRAM
{// which depth buffer modes are supported
aglDescribeRenderer(info, AGL_DEPTH_MODES, pDepthSizeSupport);
aglReportError ();
dMaxVRAM = dVRAM; // store max
found = true;
}
}
}
info = aglNextRendererInfo(info);
aglReportError ();
inum++;
}
}
aglDestroyRendererInfo(head_info);
if (found) // found card with enough VRAM and meets the accel criteria
{
if (MinVRAM > dMaxVRAM)
{
MinVRAM = dMaxVRAM; // return VRAM
}
}
else
goodCheck = false; // one device failed thus entire requirement fails
hGD = GetNextDevice (hGD); // get next device
} // while
if (goodCheck) // we check all devices and each was good
{
*pVRAM = MinVRAM; // return VRAM
return true;
}
return false; //at least one device failed to have mins
}
//--------------------------------------------------------------------------
// FindGDHandleFromWindow
// Inputs: a valid WindowPtr
// Outputs: the GDHandle that that window is mostly on
// returns the number of devices that the windows content touches
short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice)
{
GrafPtr pgpSave;
Rect rectWind, rectSect;
long greatestArea, sectArea;
short numDevices = 0;
GDHandle hgdNthDevice;
if (!pWindow || !phgdOnThisDevice)
return 0;
*phgdOnThisDevice = NULL;
GetPort (&pgpSave);
SetPortWindowPort (pWindow);
GetWindowPortBounds (pWindow, &rectWind);
LocalToGlobal ((Point*)& rectWind.top);
LocalToGlobal ((Point*)& rectWind.bottom);
hgdNthDevice = GetDeviceList ();
greatestArea = 0;
// check window against all gdRects in gDevice list and remember
// which gdRect contains largest area of window
while (hgdNthDevice)
{
if (TestDeviceAttribute (hgdNthDevice, screenDevice))
if (TestDeviceAttribute (hgdNthDevice, screenActive))
{
// The SectRect routine calculates the intersection
// of the window rectangle and this gDevice
// rectangle and returns TRUE if the rectangles intersect,
// FALSE if they don't.
SectRect (&rectWind, &(**hgdNthDevice).gdRect, &rectSect);
// determine which screen holds greatest window area
// first, calculate area of rectangle on current device
sectArea = (long) ((rectSect.right - rectSect.left) *
(rectSect.bottom - rectSect.top));
if (sectArea > 0)
numDevices++;
if (sectArea > greatestArea)
{
greatestArea = sectArea; // set greatest area so far
*phgdOnThisDevice = hgdNthDevice; // set zoom device
}
hgdNthDevice = GetNextDevice(hgdNthDevice);
}
}
SetPort (pgpSave);
return numDevices;
}
//--------------------------------------------------------------------------
vtkCarbonRenderWindow::vtkCarbonRenderWindow()
{
this->ApplicationInitialized = 0;
this->ContextId = 0;
this->MultiSamples = 8;
this->WindowId = 0;
this->ParentId = 0;
this->RootWindow = 0;
this->SetWindowName("Visualization Toolkit - Carbon");
this->CursorHidden = 0;
this->ForceMakeCurrent = 0;
this->RegionEventHandlerUPP = 0;
this->RegionEventHandler = 0;
}
// --------------------------------------------------------------------------
vtkCarbonRenderWindow::~vtkCarbonRenderWindow()
{
this->Finalize();
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::Clean()
{
GLuint txId;
/* finish OpenGL rendering */
if (this->ContextId)
{
this->MakeCurrent();
/* now delete all textures */
glDisable(GL_TEXTURE_2D);
for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++)
{
txId = (GLuint) this->TextureResourceIds->GetId(i);
#ifdef GL_VERSION_1_1
if (glIsTexture(txId))
{
glDeleteTextures(1, &txId);
}
#else
if (glIsList(txId))
{
glDeleteLists(txId,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;
vtkRenderer *ren;
for ( this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
}
aglSetCurrentContext(this->ContextId);
aglDestroyContext(this->ContextId);
this->ContextId = NULL;
}
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetWindowName( const char * _arg )
{
vtkWindow::SetWindowName(_arg);
if(this->OwnWindow)
{
CFStringRef newTitle =
CFStringCreateWithCString(kCFAllocatorDefault, _arg,
kCFStringEncodingASCII);
SetWindowTitleWithCFString(this->RootWindow, newTitle);
CFRelease(newTitle);
}
}
//--------------------------------------------------------------------------
int vtkCarbonRenderWindow::GetEventPending()
{
return 0;
}
//--------------------------------------------------------------------------
// Set the window id to a pre-existing window.
void vtkCarbonRenderWindow::SetParentId(HIViewRef arg)
{
vtkDebugMacro(<< "Setting ParentId to " << arg << "\n");
this->ParentId = arg;
}
//--------------------------------------------------------------------------
// Begin the rendering process.
void vtkCarbonRenderWindow::Start()
{
// if the renderer has not been initialized, do so now
if (!this->ContextId)
{
this->Initialize();
}
// set the current window
this->MakeCurrent();
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::MakeCurrent()
{
if (this->ContextId || this->ForceMakeCurrent)
{
aglSetCurrentContext(this->ContextId);
this->ForceMakeCurrent = 0;
}
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetForceMakeCurrent()
{
this->ForceMakeCurrent = 1;
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetSize(int a[2])
{
this->SetSize(a[0], a[1]);
}
void vtkCarbonRenderWindow::UpdateGLRegion()
{
// if WindowId is a child window
if(this->WindowId)
{
// Determine the AGL_BUFFER_RECT for the view. The coordinate
// system for this rectangle is relative to the owning window, with
// the origin at the bottom left corner and the y-axis inverted.
HIRect viewBounds, winBounds;
HIViewGetBounds(this->WindowId, &viewBounds);
HIViewRef root = HIViewGetRoot(this->GetRootWindow());
HIViewRef content_root;
HIViewFindByID(root, kHIViewWindowContentID, &content_root);
HIViewGetBounds(content_root, &winBounds);
HIViewConvertRect(&viewBounds, this->WindowId, content_root);
GLint bufferRect[4] = { GLint(viewBounds.origin.x),
GLint((winBounds.size.height) - (viewBounds.origin.y + viewBounds.size.height)),
GLint(viewBounds.size.width),
GLint(viewBounds.size.height) };
if(!HIViewIsVisible(this->WindowId))
{
bufferRect[0] = 0;
bufferRect[1] = 0;
bufferRect[2] = 0;
bufferRect[3] = 0;
}
// Associate the OpenGL context with the control's window, and establish the buffer rect.
aglSetDrawable(this->ContextId, GetWindowPort(this->GetRootWindow()));
aglSetInteger(this->ContextId, AGL_BUFFER_RECT, bufferRect);
aglEnable(this->ContextId, AGL_BUFFER_RECT);
// Establish the clipping region for the OpenGL context. To properly handle clipping
// within the view hierarchy, walk the hierarchy to determine the intersection
// of this view's bounds with its children, siblings, and parents also taking into
// account z-ordering of the views
RgnHandle rgn = NewRgn();
RgnHandle tmp_rgn = NewRgn();
GetControlRegion(this->WindowId, kControlStructureMetaPart, rgn);
HIViewConvertRegion(rgn, this->WindowId, content_root);
HIViewRef current_view = NULL;
HIViewRef child = NULL;
HIViewRef last = NULL;
for(current_view = this->WindowId;
(current_view != NULL);
current_view = HIViewGetSuperview(current_view))
{
if(last)
{
// clip view within parent bounds
GetControlRegion(current_view, kControlStructureMetaPart, tmp_rgn);
HIViewConvertRegion(tmp_rgn, current_view, content_root);
DiffRgn(rgn, tmp_rgn, tmp_rgn);
DiffRgn(rgn, tmp_rgn, rgn);
}
for(child = HIViewGetFirstSubview(current_view);
(child != last) && (child != NULL);
child = HIViewGetNextView(child))
{
if(child != last && HIViewIsVisible(child))
{
GetControlRegion(child, kControlStructureMetaPart, tmp_rgn);
HIViewConvertRegion(tmp_rgn, child, content_root);
DiffRgn(rgn, tmp_rgn, rgn);
}
}
last = current_view;
}
GetControlRegion(this->WindowId, kControlStructureMetaPart, tmp_rgn);
if(EqualRgn(rgn,tmp_rgn))
{
if(aglIsEnabled(this->ContextId, AGL_CLIP_REGION))
aglDisable(this->ContextId, AGL_CLIP_REGION);
}
else
{
if(!aglIsEnabled(this->ContextId, AGL_CLIP_REGION))
aglEnable(this->ContextId, AGL_CLIP_REGION);
aglSetInteger(this->ContextId, AGL_CLIP_REGION, reinterpret_cast<const GLint*>(rgn));
}
DisposeRgn(rgn);
DisposeRgn(tmp_rgn);
}
// this is provided for backwards compatibility
else if(this->WindowId == 0 && this->RootWindow && this->ParentId)
{
GLint bufRect[4];
Rect windowRect;
GetWindowBounds(this->RootWindow, kWindowContentRgn, &windowRect);
bufRect[0] = this->Position[0];
bufRect[1] = (int) (windowRect.bottom-windowRect.top)
- (this->Position[1]+this->Size[1]);
bufRect[2] = this->Size[0];
bufRect[3] = this->Size[1];
aglEnable(this->ContextId, AGL_BUFFER_RECT);
aglSetInteger(this->ContextId, AGL_BUFFER_RECT, bufRect);
}
aglUpdateContext(this->ContextId);
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::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->Mapped)
{
if (!resizing)
{
resizing = 1;
if(this->ParentId && this->RootWindow && !this->WindowId)
{
// backwards compatiblity with Tk and who else?
UpdateGLRegion();
}
else if(this->OwnWindow || !this->WindowId)
{
SizeWindow(this->RootWindow, x, y, TRUE);
}
resizing = 0;
}
}
}
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetPosition(int a[2])
{
this->SetPosition(a[0], a[1]);
}
// --------------------------------------------------------------------------
void vtkCarbonRenderWindow::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;
if(this->ParentId && this->RootWindow && !this->WindowId)
{
// backwards compatiblity with Tk and who else?
UpdateGLRegion();
}
else if(this->OwnWindow || !this->WindowId)
{
MoveWindow(this->RootWindow, x, y, FALSE);
}
resizing = 0;
}
}
}
}
//--------------------------------------------------------------------------
// End the rendering process and display the image.
void vtkCarbonRenderWindow::Frame()
{
if (!this->AbortRender && this->DoubleBuffer)
{
aglSwapBuffers(this->ContextId);
vtkDebugMacro(<< " SwapBuffers\n");
}
}
//--------------------------------------------------------------------------
// Specify various window parameters.
void vtkCarbonRenderWindow::WindowConfigure()
{
// this is all handled by the desiredVisualInfo method
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetupPixelFormat(void*, void*, int, int, int)
{
cout << "vtkCarbonRenderWindow::SetupPixelFormat - IMPLEMENT\n";
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::SetupPalette(void*)
{
cout << "vtkCarbonRenderWindow::SetupPalette - IMPLEMENT\n";
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::InitializeApplication()
{
if (!this->ApplicationInitialized)
{
if (this->OwnWindow)
{ // Initialize the Toolbox managers if we are running the show
InitCursor();
DrawMenuBar();
this->ApplicationInitialized=1;
}
}
}
//--------------------------------------------------------------------------
// Initialize the window for rendering.
void vtkCarbonRenderWindow::CreateAWindow(int vtkNotUsed(x), int vtkNotUsed(y),
int vtkNotUsed(width), int vtkNotUsed(height))
{
GDHandle hGD = NULL;
GLint depthSizeSupport;
static int count = 1;
short i;
char *windowName;
short numDevices; // number of graphics devices our window covers
if ((this->Size[0]+this->Size[1])==0)
{
this->Size[0]=300;
this->Size[1]=300;
}
if ((this->Position[0]+this->Position[1])==0)
{
this->Position[0]=50;
this->Position[1]=50;
}
// Rect is defined as {top, left, bottom, right} (really)
Rect rectWin = {this->Position[1], this->Position[0],
this->Position[1]+this->Size[1],
this->Position[0]+this->Size[0]};
// if a Window and HIView wasn't given, make a Window and HIView
if (!this->WindowId && !this->RootWindow)
{
WindowAttributes windowAttrs = (kWindowStandardDocumentAttributes |
kWindowLiveResizeAttribute |
kWindowStandardHandlerAttribute |
kWindowCompositingAttribute);
if (noErr != CreateNewWindow (kDocumentWindowClass,
windowAttrs,
&rectWin, &(this->RootWindow)))
{
vtkErrorMacro("Could not create window, serious error!");
return;
}
// get the content view
HIViewFindByID(HIViewGetRoot(this->RootWindow),
kHIViewWindowContentID,
&this->WindowId);
int len = (strlen("vtkX - Carbon #")
+ (int) ceil((double)log10((double)(count+1)))
+ 1);
windowName = new char [ len ];
sprintf(windowName,"vtkX - Carbon #%i",count++);
this->SetWindowName(windowName);
delete [] windowName;
this->OwnWindow = 1;
ShowWindow(this->RootWindow);
}
// install event handler for updating gl region
// this works for a supplied HIView and an HIView made here
if(this->WindowId && !this->RegionEventHandler)
{
EventTypeSpec region_events [] =
{
{ kEventClassControl, kEventControlOwningWindowChanged},
{ kEventClassControl, kEventControlVisibilityChanged },
{ kEventClassControl, kEventControlBoundsChanged }
};
this->RegionEventHandlerUPP = NewEventHandlerUPP(vtkCarbonRenderWindow::RegionEventProcessor);
InstallControlEventHandler(this->WindowId, this->RegionEventHandlerUPP,
GetEventTypeCount(region_events), region_events,
reinterpret_cast<void*>(this), &this->RegionEventHandler);
}
SetPortWindowPort(this->GetRootWindow());
this->fAcceleratedMust = false; //must renderer be accelerated?
this->VRAM = 0 * 1048576; // minimum VRAM
this->textureRAM = 0 * 1048576; // minimum texture RAM
this->fmt = 0; // output pixel format
i = 0;
this->aglAttributes [i++] = AGL_RGBA;
this->aglAttributes [i++] = AGL_DOUBLEBUFFER;
this->aglAttributes [i++] = AGL_DEPTH_SIZE;
this->aglAttributes [i++] = 32;
this->aglAttributes [i++] = AGL_PIXEL_SIZE;
this->aglAttributes [i++] = 32;
this->aglAttributes [i++] = AGL_ACCELERATED;
if (this->AlphaBitPlanes)
{
this->aglAttributes [i++] = AGL_ALPHA_SIZE;
this->aglAttributes [i++] = 8;
}
this->aglAttributes [i++] = AGL_NONE;
this->draggable = true;
numDevices = FindGDHandleFromWindow(this->GetRootWindow(), &hGD);
if (!this->draggable)
{
if ((numDevices > 1) || (numDevices == 0)) // multiple or no devices
{
// software renderer
// infinite VRAM, infinite textureRAM, not accelerated
if (this->fAcceleratedMust)
{
vtkErrorMacro ("Window spans multiple devices-no HW accel");
return;
}
}
else // not draggable on single device
{
if (!CheckRenderer (hGD, &(this->VRAM), &(this->textureRAM),
&depthSizeSupport, this->fAcceleratedMust))
{
vtkErrorMacro ("Renderer check failed");
return;
}
}
}
// else if draggable - must check all devices for presence of
// at least one renderer that meets the requirements
else if(!CheckAllDeviceRenderers(&(this->VRAM), &(this->textureRAM),
&depthSizeSupport, this->fAcceleratedMust))
{
vtkErrorMacro ("Renderer check failed");
return;
}
// do agl
if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat)
{
vtkErrorMacro ("OpenGL not installed");
return;
}
// we successfully passed the renderer checks!
if ((!this->draggable && (numDevices == 1)))
{// not draggable on a single device
this->fmt = aglChoosePixelFormat (&hGD, 1, this->aglAttributes);
}
else
{
this->fmt = aglChoosePixelFormat (NULL, 0, this->aglAttributes);
}
aglReportError (); // cough up any errors encountered
if (NULL == this->fmt)
{
vtkErrorMacro("Could not find valid pixel format");
return;
}
this->ContextId = aglCreateContext (this->fmt, 0); // create without sharing
aglReportError (); // cough up errors
if (NULL == this->ContextId)
{
vtkErrorMacro ("Could not create context");
return;
}
// attach the CGrafPtr to the context
if (!aglSetDrawable (this->ContextId, GetWindowPort (this->GetRootWindow())))
{
aglReportError();
return;
}
if(!aglSetCurrentContext (this->ContextId))
// make the context the current context
{
aglReportError();
return;
}
this->OpenGLInit();
this->Mapped = 1;
UpdateGLRegion();
}
//--------------------------------------------------------------------------
// Initialize the window for rendering.
void vtkCarbonRenderWindow::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;
this->InitializeApplication();
this->CreateAWindow(x,y,width,height);
// tell our renderers about us
vtkRenderer* ren;
for (this->Renderers->InitTraversal();
(ren = this->Renderers->GetNextItem());)
{
ren->SetRenderWindow(0);
ren->SetRenderWindow(this);
}
// set the DPI
this->SetDPI(72); // this may need to be more clever some day
}
//--------------------------------------------------------------------------
// Initialize the rendering window.
void vtkCarbonRenderWindow::Initialize ()
{
// make sure we havent already been initialized
if (this->ContextId)
{
return;
}
this->WindowInitialize();
}
void vtkCarbonRenderWindow::Finalize(void)
{
if (this->CursorHidden)
{
this->ShowCursor();
}
if (this->OffScreenRendering) // does not exist yet
{
//this->CleanUpOffScreenRendering()
}
this->Clean();
// remove event filters if we have them
if(this->RegionEventHandler)
{
RemoveEventHandler(this->RegionEventHandler);
DisposeEventHandlerUPP(this->RegionEventHandlerUPP);
this->RegionEventHandler = 0;
this->RegionEventHandlerUPP = 0;
}
if (this->RootWindow && this->OwnWindow)
{
DisposeWindow(this->RootWindow);
}
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::UpdateSizeAndPosition(int xPos, int yPos,
int xSize, int ySize)
{
this->Size[0]=xSize;
this->Size[1]=ySize;
this->Position[0]=xPos;
this->Position[1]=yPos;
this->Modified();
}
//--------------------------------------------------------------------------
// Get the current size of the window.
int *vtkCarbonRenderWindow::GetSize()
{
// if we aren't mapped then just return the ivar
if (!this->Mapped)
{
return this->Superclass::GetSize();
}
if(this->WindowId)
{
HIRect viewBounds;
HIViewGetBounds(this->WindowId, &viewBounds);
this->Size[0] = (int)viewBounds.size.width;
this->Size[1] = (int)viewBounds.size.height;
}
return this->Superclass::GetSize();
}
//--------------------------------------------------------------------------
// Get the current size of the screen.
int *vtkCarbonRenderWindow::GetScreenSize()
{
cout << "Inside vtkCarbonRenderWindow::GetScreenSize - MUST IMPLEMENT\n";
this->Size[0] = 0;
this->Size[1] = 0;
return this->Size;
}
//--------------------------------------------------------------------------
// Get the position in screen coordinates of the window.
int *vtkCarbonRenderWindow::GetPosition()
{
// if we aren't mapped then just return the ivar
if (!this->Mapped)
{
return this->Position;
}
if(!this->WindowId && !this->ParentId)
{
// Find the current window position
Rect windowRect;
GetWindowBounds(this->GetRootWindow(), kWindowContentRgn, &windowRect);
this->Position[0] = windowRect.left;
this->Position[1] = windowRect.top;
}
else
{
HIRect viewBounds;
HIViewGetBounds(this->WindowId, &viewBounds);
Rect windowRect;
GetWindowBounds(this->GetRootWindow(), kWindowContentRgn, &windowRect);
this->Position[0] = ((int)viewBounds.origin.x) + windowRect.left;
this->Position[1] = ((int)viewBounds.origin.y) + windowRect.top;
}
return this->Position;
}
//--------------------------------------------------------------------------
// Change the window to fill the entire screen.
void vtkCarbonRenderWindow::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 vtkCarbonRenderWindow::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 vtkCarbonRenderWindow::PrefFullScreen()
{
vtkWarningMacro(<< "Can't get full screen window.");
}
//--------------------------------------------------------------------------
// Remap the window.
void vtkCarbonRenderWindow::WindowRemap()
{
vtkWarningMacro(<< "Can't remap the window.");
}
//--------------------------------------------------------------------------
void vtkCarbonRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "ContextId: " << this->ContextId << "\n";
os << indent << "MultiSamples: " << this->MultiSamples << "\n";
}
//--------------------------------------------------------------------------
int vtkCarbonRenderWindow::GetDepthBufferSize()
{
GLint size;
if ( this->Mapped )
{
size = 0;
glGetIntegerv( GL_DEPTH_BITS, &size );
return (int) size;
}
else
{
vtkDebugMacro(<< "Window is not mapped yet!" );
return 24;
}
}
//--------------------------------------------------------------------------
// Get the window id.
HIViewRef vtkCarbonRenderWindow::GetWindowId()
{
vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n");
return this->WindowId;
}
//--------------------------------------------------------------------------
// Set the window id to a pre-existing window.
void vtkCarbonRenderWindow::SetWindowId(HIViewRef theWindow)
{
vtkDebugMacro(<< "Setting WindowId to " << theWindow << "\n");
this->WindowId = theWindow;
}
//--------------------------------------------------------------------------
// Set this RenderWindow's Carbon window id to a pre-existing window.
void vtkCarbonRenderWindow::SetWindowInfo(char *info)
{
long tmp;
sscanf(info,"%ld",&tmp);
this->WindowId = (HIViewRef)tmp;
vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n");
}
void vtkCarbonRenderWindow::SetRootWindow(WindowPtr win)
{
vtkDebugMacro(<< "Setting RootWindow to " << win << "\n");
this->RootWindow = win;
}
WindowPtr vtkCarbonRenderWindow::GetRootWindow()
{
// take into account whether the user set the root window or not.
// if not, then WindowId is set and we're using HIViews.
// Instead of storing the RootWindow, we ask for it in case of a dynamic
// GUI where the root window can change
return this->RootWindow ? this->RootWindow : HIViewGetWindow(this->WindowId);
}
//----------------------------------------------------------------------------
void vtkCarbonRenderWindow::HideCursor()
{
if (this->CursorHidden)
{
return;
}
this->CursorHidden = 1;
HideCursor();
}
//----------------------------------------------------------------------------
void vtkCarbonRenderWindow::ShowCursor()
{
if (!this->CursorHidden)
{
return;
}
this->CursorHidden = 0;
ShowCursor();
}
OSStatus vtkCarbonRenderWindow::RegionEventProcessor(EventHandlerCallRef,
EventRef event, void* win)
{
vtkCarbonRenderWindow* vtk_win = reinterpret_cast<vtkCarbonRenderWindow*>(win);
UInt32 event_kind = GetEventKind(event);
UInt32 event_class = GetEventClass(event);
switch(event_class)
{
case kEventClassControl:
{
switch (event_kind)
{
case kEventControlVisibilityChanged:
case kEventControlOwningWindowChanged:
case kEventControlBoundsChanged:
vtk_win->UpdateGLRegion();
break;
default:
break;
}
}
break;
default:
break;
}
return eventNotHandledErr;
}