mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
1948 lines
60 KiB
C++
1948 lines
60 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
Module: vtkPVSynchronizedRenderWindows.cxx
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkPVSynchronizedRenderWindows.h"
|
|
|
|
#include "vtkBoundingBox.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkDebugLeaks.h"
|
|
#include "vtkMultiProcessStream.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkProcessModule.h"
|
|
#include "vtkPVAxesWidget.h"
|
|
#include "vtkPVServerInformation.h"
|
|
#include "vtkPVSession.h"
|
|
#include "vtkRendererCollection.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkSelectionSerializer.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkSocketController.h"
|
|
#include "vtkTilesHelper.h"
|
|
#include "vtkTuple.h"
|
|
|
|
#include <vtksys/SystemTools.hxx>
|
|
#include <sstream>
|
|
#include <assert.h>
|
|
#include <map>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
class vtkPVSynchronizedRenderWindows::vtkInternals
|
|
{
|
|
public:
|
|
typedef std::pair<vtkSmartPointer<vtkRenderer>, vtkTuple<double, 4> > RendererInfo;
|
|
typedef std::vector<RendererInfo> VectorOfRenderers;
|
|
|
|
struct RenderWindowInfo
|
|
{
|
|
int Size[2];
|
|
int Position[2];
|
|
unsigned long StartRenderTag;
|
|
unsigned long EndRenderTag;
|
|
vtkSmartPointer<vtkRenderWindow> RenderWindow;
|
|
|
|
VectorOfRenderers Renderers;
|
|
|
|
RenderWindowInfo()
|
|
{
|
|
this->Size[0] = this->Size[1] = 0;
|
|
this->Position[0] = this->Position[1] = 0;
|
|
this->StartRenderTag = this->EndRenderTag = 0;
|
|
}
|
|
};
|
|
|
|
struct CallbackInfo
|
|
{
|
|
unsigned long ParallelHandle;
|
|
unsigned long ClientServerHandle;
|
|
unsigned long ClientDataServerHandle;
|
|
CallbackInfo()
|
|
{
|
|
this->ParallelHandle = 0;
|
|
this->ClientServerHandle = 0;
|
|
this->ClientDataServerHandle = 0;
|
|
}
|
|
};
|
|
|
|
std::vector<CallbackInfo> RMICallbacks;
|
|
|
|
typedef std::map<unsigned int, RenderWindowInfo> RenderWindowsMap;
|
|
RenderWindowsMap RenderWindows;
|
|
|
|
unsigned int GetKey(vtkRenderWindow* win)
|
|
{
|
|
RenderWindowsMap::iterator iter;
|
|
for (iter = this->RenderWindows.begin(); iter != this->RenderWindows.end();
|
|
++iter)
|
|
{
|
|
if (iter->second.RenderWindow == win)
|
|
{
|
|
return iter->first;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Updates the viewport for all the renderers in the collection.
|
|
void UpdateViewports(VectorOfRenderers& renderers, const double viewport[4])
|
|
{
|
|
double dx = (viewport[2] - viewport[0]);
|
|
double dy = (viewport[3] - viewport[1]);
|
|
VectorOfRenderers::iterator iter;
|
|
for (iter = renderers.begin(); iter != renderers.end(); ++iter)
|
|
{
|
|
// HACK: This allows us to skip changing the viewport for orientation
|
|
// widget for now.
|
|
if ((*iter).first->GetLayer() != vtkPVAxesWidget::RendererLayer)
|
|
{
|
|
const vtkTuple<double, 4> &rViewport = iter->second;
|
|
(*iter).first->SetViewport(
|
|
viewport[0] + dx * rViewport[0], // xmin
|
|
viewport[1] + dy * rViewport[1], // ymin
|
|
viewport[0] + dx * rViewport[2], // xmax
|
|
viewport[1] + dy * rViewport[3] // ymax
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ExpandTowardMin(unsigned int me, const int* my_size, int* my_pos,
|
|
int dimension)
|
|
{
|
|
int cur_dim_min_offset = dimension;
|
|
int cur_dim_max_offset = dimension+2;
|
|
int other_dim_min_offset = (dimension+1)%2;
|
|
int other_dim_max_offset = other_dim_min_offset + 2;
|
|
int my_extents[4] = {my_pos[0], my_pos[1], my_pos[0] + my_size[0] -1,
|
|
my_pos[1] + my_size[1] - 1};
|
|
|
|
int &position = my_pos[dimension];
|
|
position = 0;
|
|
RenderWindowsMap::iterator iter;
|
|
for (iter = this->RenderWindows.begin(); iter != this->RenderWindows.end(); ++iter)
|
|
{
|
|
if (iter->first == me)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Only interested in boxes entirely to our left (or top)
|
|
const int *size = iter->second.Size;
|
|
const int *pos = iter->second.Position;
|
|
int extents[4] = {pos[0], pos[1], pos[0] + size[0] -1,
|
|
pos[1] + size[1] - 1};
|
|
|
|
if (extents[cur_dim_max_offset] > my_extents[cur_dim_min_offset] ||
|
|
extents[other_dim_min_offset] > my_extents[other_dim_max_offset] ||
|
|
extents[other_dim_max_offset] < my_extents[other_dim_min_offset])
|
|
{
|
|
continue;
|
|
}
|
|
if (position <= extents[cur_dim_max_offset])
|
|
{
|
|
position = extents[cur_dim_max_offset] + 1;
|
|
}
|
|
}
|
|
return (position != my_extents[dimension]);
|
|
}
|
|
bool ExpandTop(unsigned int me, const int* my_size, int* my_pos)
|
|
{ return this->ExpandTowardMin(me, my_size, my_pos, 1); }
|
|
bool ExpandLeft(unsigned int me, const int* my_size, int* my_pos)
|
|
{ return this->ExpandTowardMin(me, my_size, my_pos, 0); }
|
|
|
|
bool ExpandTowardMax(unsigned int me, const int *max, int* my_size, const int *my_pos,
|
|
int dimension)
|
|
{
|
|
|
|
int cur_dim_min_offset = dimension;
|
|
int cur_dim_max_offset = dimension+2;
|
|
int other_dim_min_offset = (dimension+1)%2;
|
|
int other_dim_max_offset = other_dim_min_offset + 2;
|
|
int my_extents[4] = {my_pos[0], my_pos[1], my_pos[0] + my_size[0] -1,
|
|
my_pos[1] + my_size[1] - 1};
|
|
|
|
int &size = my_size[dimension];
|
|
size = (max[dimension] - my_extents[cur_dim_min_offset]);
|
|
RenderWindowsMap::iterator iter;
|
|
for (iter = this->RenderWindows.begin(); iter != this->RenderWindows.end(); ++iter)
|
|
{
|
|
if (iter->first == me)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Only interested in boxes entirely to our right (or bottom)
|
|
const int *_size = iter->second.Size;
|
|
const int *pos = iter->second.Position;
|
|
int extents[4] = {pos[0], pos[1], pos[0] + _size[0] -1,
|
|
pos[1] + _size[1] - 1};
|
|
|
|
if (extents[cur_dim_min_offset] <= my_extents[cur_dim_max_offset] ||
|
|
extents[other_dim_min_offset] > my_extents[other_dim_max_offset] ||
|
|
extents[other_dim_max_offset] < my_extents[other_dim_min_offset])
|
|
{
|
|
continue;
|
|
}
|
|
int my_extent_max = my_extents[cur_dim_min_offset] + size - 1;
|
|
if ( my_extent_max >= extents[cur_dim_min_offset])
|
|
{
|
|
size = extents[cur_dim_min_offset] - my_extents[cur_dim_min_offset];
|
|
}
|
|
}
|
|
return (size != (my_extents[cur_dim_max_offset] - my_extents[cur_dim_min_offset] + 1));
|
|
}
|
|
bool ExpandRight(unsigned int me, const int *max, int* my_size, const int *my_pos)
|
|
{ return this->ExpandTowardMax(me, max, my_size, my_pos, 0); }
|
|
bool ExpandBottom(unsigned int me, const int *max, int* my_size, const int *my_pos)
|
|
{ return this->ExpandTowardMax(me, max, my_size, my_pos, 1); }
|
|
|
|
vtkSmartPointer<vtkRenderWindow> SharedRenderWindow;
|
|
unsigned long SharedWindowStartRenderTag;
|
|
unsigned long SharedWindowEndRenderTag;
|
|
unsigned int ActiveId;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
class vtkPVSynchronizedRenderWindows::vtkObserver : public vtkCommand
|
|
{
|
|
public:
|
|
static vtkObserver* New()
|
|
{
|
|
vtkObserver* obs = new vtkObserver();
|
|
obs->Target = NULL;
|
|
return obs;
|
|
}
|
|
|
|
virtual void Execute(vtkObject *ocaller, unsigned long eventId, void *)
|
|
{
|
|
vtkRenderWindow* renWin = vtkRenderWindow::SafeDownCast(ocaller);
|
|
if (this->Target && this->Target->GetEnabled())
|
|
{
|
|
switch (eventId)
|
|
{
|
|
case vtkCommand::StartEvent:
|
|
this->Target->HandleStartRender(renWin);
|
|
break;
|
|
|
|
case vtkCommand::EndEvent:
|
|
this->Target->HandleEndRender(renWin);
|
|
break;
|
|
|
|
case vtkCommand::AbortCheckEvent:
|
|
this->Target->HandleAbortRender(renWin);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
vtkPVSynchronizedRenderWindows* Target;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
void RenderRMI(void *localArg,
|
|
void *remoteArg, int remoteArgLength, int vtkNotUsed(remoteProcessId))
|
|
{
|
|
vtkMultiProcessStream stream;
|
|
stream.SetRawData(reinterpret_cast<unsigned char*>(remoteArg),
|
|
remoteArgLength);
|
|
unsigned int id = 0;
|
|
stream >> id;
|
|
vtkPVSynchronizedRenderWindows* self =
|
|
reinterpret_cast<vtkPVSynchronizedRenderWindows*>(localArg);
|
|
self->Render(id);
|
|
}
|
|
|
|
void GetZBufferValue(void *localArg,
|
|
void *remoteArg, int remoteArgLength, int vtkNotUsed(remoteProcessId))
|
|
{
|
|
vtkMultiProcessStream stream;
|
|
stream.SetRawData(reinterpret_cast<unsigned char*>(remoteArg),
|
|
remoteArgLength);
|
|
unsigned int id = 0;
|
|
int x, y;
|
|
stream >> id >> x >> y;
|
|
vtkPVSynchronizedRenderWindows* self =
|
|
reinterpret_cast<vtkPVSynchronizedRenderWindows*>(localArg);
|
|
self->OnGetZBufferValue(id, x, y);
|
|
}
|
|
};
|
|
|
|
vtkCxxSetObjectMacro(vtkPVSynchronizedRenderWindows, ClientDataServerController,
|
|
vtkMultiProcessController);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPVSynchronizedRenderWindows* vtkPVSynchronizedRenderWindows::New(
|
|
vtkPVSession* session/*=NULL*/)
|
|
{
|
|
#ifdef VTK_DEBUG_LEAKS
|
|
vtkDebugLeaks::ConstructClass("vtkPVSynchronizedRenderWindows");
|
|
#endif
|
|
|
|
// Ensure vtkProcessModule is setup correctly.
|
|
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
|
|
if (!pm)
|
|
{
|
|
vtkGenericWarningMacro(
|
|
"vtkPVSynchronizedRenderWindows cannot be used in the current\n"
|
|
"setup.");
|
|
return NULL;
|
|
}
|
|
|
|
vtkPVSession* activeSession = session? session :
|
|
vtkPVSession::SafeDownCast(pm->GetActiveSession());
|
|
if (!activeSession)
|
|
{
|
|
vtkGenericWarningMacro(
|
|
"vtkPVSynchronizedRenderWindows cannot be created with a valid session");
|
|
return NULL;
|
|
}
|
|
|
|
return new vtkPVSynchronizedRenderWindows(activeSession);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPVSynchronizedRenderWindows::vtkPVSynchronizedRenderWindows(
|
|
vtkPVSession* activeSession /*NULL*/) : Session(activeSession)
|
|
{
|
|
this->Mode = INVALID;
|
|
this->ClientServerController = 0;
|
|
this->ClientDataServerController = 0;
|
|
this->ParallelController = 0;
|
|
this->ClientServerRMITag = 0;
|
|
this->ClientServerGetZBufferValueRMITag = 0;
|
|
this->ParallelRMITag = 0;
|
|
this->Internals = new vtkInternals();
|
|
this->Internals->ActiveId = 0;
|
|
this->Internals->SharedWindowStartRenderTag = 0;
|
|
this->Internals->SharedWindowEndRenderTag = 0;
|
|
this->Observer = vtkObserver::New();
|
|
this->Observer->Target = this;
|
|
this->Enabled = false;
|
|
|
|
// we no longer support render even propagation. This leads to unnecessary
|
|
// complications since it results in code have different paths on client and
|
|
// servers.
|
|
this->RenderEventPropagation = false;
|
|
this->RenderOneViewAtATime = false;
|
|
|
|
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
|
|
int processtype = pm->GetProcessType();
|
|
switch (processtype)
|
|
{
|
|
case vtkProcessModule::PROCESS_BATCH:
|
|
this->Mode = BATCH;
|
|
this->RenderOneViewAtATime = true;
|
|
break;
|
|
|
|
case vtkProcessModule::PROCESS_RENDER_SERVER:
|
|
case vtkProcessModule::PROCESS_SERVER:
|
|
this->Mode = RENDER_SERVER;
|
|
break;
|
|
|
|
case vtkProcessModule::PROCESS_DATA_SERVER:
|
|
this->Mode = DATA_SERVER;
|
|
break;
|
|
|
|
case vtkProcessModule::PROCESS_CLIENT:
|
|
this->Mode = BUILTIN;
|
|
if (this->Session->IsA("vtkSMSessionClient"))
|
|
{
|
|
this->Mode = CLIENT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Setup the controllers for the communication.
|
|
switch (this->Mode)
|
|
{
|
|
case BUILTIN:
|
|
// nothing to do.
|
|
break;
|
|
|
|
case DATA_SERVER:
|
|
this->SetClientDataServerController(
|
|
this->Session->GetController(vtkPVSession::CLIENT));
|
|
break;
|
|
|
|
case BATCH:
|
|
this->SetParallelController(vtkMultiProcessController::GetGlobalController());
|
|
if (pm->GetSymmetricMPIMode())
|
|
{
|
|
this->RenderEventPropagation = false;
|
|
}
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
this->SetParallelController(vtkMultiProcessController::GetGlobalController());
|
|
// this will be NULL on satellites.
|
|
this->SetClientServerController(
|
|
this->Session->GetController(vtkPVSession::CLIENT));
|
|
break;
|
|
|
|
case CLIENT:
|
|
this->SetClientServerController(
|
|
this->Session->GetController(vtkPVSession::RENDER_SERVER_ROOT));
|
|
this->SetClientDataServerController(
|
|
this->Session->GetController(vtkPVSession::DATA_SERVER_ROOT));
|
|
if (this->ClientDataServerController == this->ClientServerController)
|
|
{
|
|
this->SetClientDataServerController(0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
vtkErrorMacro("Invalid process type.");
|
|
abort();
|
|
}
|
|
|
|
if (this->ClientDataServerController != NULL)
|
|
{
|
|
// ClientDataServerController is non-null on pvdataserver and client in
|
|
// data-server/render-server mode.
|
|
|
|
// synchronize tile-display parameters viz. tile-dimensions between
|
|
// data-server and render-server.
|
|
if (this->Mode == CLIENT)
|
|
{
|
|
int tile_dims[2], tile_mullions[2];
|
|
bool tile_display_mode =
|
|
this->GetTileDisplayParameters(tile_dims, tile_mullions);
|
|
vtkMultiProcessStream stream;
|
|
stream << (tile_display_mode? 1 : 0)
|
|
<< tile_dims[0] << tile_dims[1]
|
|
<< tile_mullions[0] << tile_mullions[1];
|
|
this->ClientDataServerController->Send(stream, 1,
|
|
SYNC_TILE_DISPLAY_PARAMATERS);
|
|
}
|
|
else if (this->Mode == DATA_SERVER)
|
|
{
|
|
vtkMultiProcessStream stream;
|
|
this->ClientDataServerController->Receive(stream, 1,
|
|
SYNC_TILE_DISPLAY_PARAMATERS);
|
|
int tile_dims[2], tile_mullions[2], tile_display_mode;
|
|
stream >> tile_display_mode
|
|
>> tile_dims[0] >> tile_dims[1]
|
|
>> tile_mullions[0] >> tile_mullions[1];
|
|
if (tile_display_mode == 1)
|
|
{
|
|
this->Session->GetServerInformation()->SetTileDimensions(tile_dims);
|
|
this->Session->GetServerInformation()->SetTileMullions(tile_mullions);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPVSynchronizedRenderWindows::~vtkPVSynchronizedRenderWindows()
|
|
{
|
|
this->SetClientServerController(0);
|
|
this->SetClientDataServerController(0);
|
|
this->SetParallelController(0);
|
|
|
|
if (this->Internals->SharedRenderWindow)
|
|
{
|
|
if (this->Internals->SharedWindowStartRenderTag)
|
|
{
|
|
this->Internals->SharedRenderWindow->RemoveObserver(
|
|
this->Internals->SharedWindowStartRenderTag);
|
|
}
|
|
if (this->Internals->SharedWindowEndRenderTag)
|
|
{
|
|
this->Internals->SharedRenderWindow->RemoveObserver(
|
|
this->Internals->SharedWindowEndRenderTag);
|
|
}
|
|
}
|
|
delete this->Internals;
|
|
this->Internals = 0;
|
|
|
|
this->Observer->Target = NULL;
|
|
this->Observer->Delete();
|
|
this->Observer = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPVSession* vtkPVSynchronizedRenderWindows::GetSession()
|
|
{
|
|
return this->Session;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::GetLocalProcessIsDriver()
|
|
{
|
|
switch (this->Mode)
|
|
{
|
|
case BUILTIN:
|
|
return true;
|
|
|
|
case CLIENT:
|
|
return true;
|
|
|
|
case RENDER_SERVER:
|
|
return false;
|
|
|
|
case BATCH:
|
|
if (this->ParallelController &&
|
|
this->ParallelController->GetLocalProcessId() == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
case DATA_SERVER:
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SetClientServerController(
|
|
vtkMultiProcessController* controller)
|
|
{
|
|
if (this->ClientServerController == controller)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (this->ClientServerController && this->ClientServerRMITag)
|
|
{
|
|
this->ClientServerController->RemoveRMICallback(this->ClientServerRMITag);
|
|
}
|
|
if (this->ClientServerController && this->ClientServerGetZBufferValueRMITag)
|
|
{
|
|
this->ClientServerController->RemoveRMICallback(
|
|
this->ClientServerGetZBufferValueRMITag);
|
|
}
|
|
|
|
vtkSetObjectBodyMacro(
|
|
ClientServerController, vtkMultiProcessController, controller);
|
|
this->ClientServerRMITag = 0;
|
|
this->ClientServerGetZBufferValueRMITag = 0;
|
|
|
|
// Only the RENDER_SERVER processes needs to listen to SYNC_MULTI_RENDER_WINDOW_TAG
|
|
// triggers from the client.
|
|
if (controller && this->Mode == RENDER_SERVER)
|
|
{
|
|
// Only one RMICallback for PVSynchronizedRenderWindow can live at a time
|
|
controller->RemoveAllRMICallbacks(SYNC_MULTI_RENDER_WINDOW_TAG);
|
|
controller->RemoveAllRMICallbacks(GET_ZBUFFER_VALUE_TAG);
|
|
|
|
// Attach the one
|
|
this->ClientServerRMITag =
|
|
controller->AddRMICallback(::RenderRMI, this, SYNC_MULTI_RENDER_WINDOW_TAG);
|
|
this->ClientServerGetZBufferValueRMITag =
|
|
controller->AddRMICallback(::GetZBufferValue, this, GET_ZBUFFER_VALUE_TAG);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SetParallelController(
|
|
vtkMultiProcessController* controller)
|
|
{
|
|
if (this->ParallelController == controller)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (this->ParallelController && this->ParallelRMITag)
|
|
{
|
|
this->ParallelController->RemoveRMICallback(this->ParallelRMITag);
|
|
}
|
|
|
|
vtkSetObjectBodyMacro(
|
|
ParallelController, vtkMultiProcessController, controller);
|
|
this->ParallelRMITag = 0;
|
|
|
|
// Only satellites listen to the SYNC_MULTI_RENDER_WINDOW_TAG
|
|
// triggers from the root.
|
|
if (controller &&
|
|
(this->Mode == RENDER_SERVER || this->Mode == BATCH) &&
|
|
controller->GetLocalProcessId() > 0)
|
|
{
|
|
this->ParallelRMITag =
|
|
controller->AddRMICallback(::RenderRMI, this, SYNC_MULTI_RENDER_WINDOW_TAG);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkRenderWindow* vtkPVSynchronizedRenderWindows::NewRenderWindow()
|
|
{
|
|
switch (this->Mode)
|
|
{
|
|
case DATA_SERVER:
|
|
{
|
|
// we could very return a dummy window here.
|
|
vtkRenderWindow* window = vtkRenderWindow::New();
|
|
window->SetWindowName("ParaView Data-Server");
|
|
return window;
|
|
}
|
|
|
|
case BUILTIN:
|
|
case CLIENT:
|
|
{
|
|
// client always creates new window for each view in the multi layout
|
|
// configuration.
|
|
vtkRenderWindow* window = vtkRenderWindow::New();
|
|
window->DoubleBufferOn();
|
|
window->AlphaBitPlanesOn();
|
|
window->SetWindowName("ParaView");
|
|
window->SetSize(400, 400); // set some default size for the window.
|
|
return window;
|
|
}
|
|
|
|
case RENDER_SERVER:
|
|
case BATCH:
|
|
// all views share the same render window.
|
|
if (!this->Internals->SharedRenderWindow)
|
|
{
|
|
vtkRenderWindow* window = vtkRenderWindow::New();
|
|
window->DoubleBufferOn();
|
|
window->AlphaBitPlanesOn();
|
|
std::ostringstream name_stream;
|
|
if (this->Mode == BATCH)
|
|
{
|
|
name_stream << "ParaView (batch)";
|
|
}
|
|
else
|
|
{
|
|
name_stream << "ParaView Server";
|
|
}
|
|
if (this->ParallelController->GetNumberOfProcesses() > 1)
|
|
{
|
|
name_stream << " #" << this->ParallelController->GetLocalProcessId();
|
|
}
|
|
window->SetWindowName(name_stream.str().c_str());
|
|
// SwapBuffers should be ON only on root node in BATCH mode
|
|
// or when operating in tile-display mode.
|
|
bool swap_buffers = false;
|
|
swap_buffers |= (this->Mode == BATCH &&
|
|
this->ParallelController->GetLocalProcessId() == 0);
|
|
int not_used[2];
|
|
swap_buffers |= this->GetTileDisplayParameters(not_used, not_used);
|
|
swap_buffers |= this->GetIsInCave();
|
|
window->SetSwapBuffers(swap_buffers? 1 : 0);
|
|
//window->SetSwapBuffers(1); // for debugging FIXME.
|
|
this->Internals->SharedRenderWindow.TakeReference(window);
|
|
this->Internals->SharedRenderWindow->SetSize(400, 400); // set some default size for the window.
|
|
}
|
|
else
|
|
{
|
|
// cout << "Using shared render window" << endl;
|
|
}
|
|
this->Internals->SharedRenderWindow->Register(this);
|
|
return this->Internals->SharedRenderWindow;
|
|
|
|
case INVALID:
|
|
abort();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::AddRenderWindow(
|
|
unsigned int id, vtkRenderWindow* renWin)
|
|
{
|
|
assert(renWin != NULL && id != 0);
|
|
|
|
if (this->Internals->RenderWindows.find(id) !=
|
|
this->Internals->RenderWindows.end() &&
|
|
this->Internals->RenderWindows[id].RenderWindow != NULL)
|
|
{
|
|
vtkErrorMacro("ID for render window already in use: " << id);
|
|
return;
|
|
}
|
|
|
|
this->Internals->RenderWindows[id].RenderWindow = renWin;
|
|
unsigned long start_tag = 0, end_tag = 0;
|
|
if (!renWin->HasObserver(vtkCommand::StartEvent, this->Observer))
|
|
{
|
|
start_tag = renWin->AddObserver(vtkCommand::StartEvent, this->Observer);
|
|
}
|
|
if (!renWin->HasObserver(vtkCommand::EndEvent, this->Observer))
|
|
{
|
|
end_tag = renWin->AddObserver(vtkCommand::EndEvent, this->Observer);
|
|
}
|
|
if (renWin == this->Internals->SharedRenderWindow)
|
|
{
|
|
if (start_tag)
|
|
{
|
|
this->Internals->SharedWindowStartRenderTag = start_tag;
|
|
}
|
|
if (end_tag)
|
|
{
|
|
this->Internals->SharedWindowStartRenderTag = end_tag;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->Internals->RenderWindows[id].StartRenderTag = start_tag;
|
|
this->Internals->RenderWindows[id].EndRenderTag = end_tag;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::RemoveRenderWindow(unsigned int id)
|
|
{
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
if (iter->second.StartRenderTag)
|
|
{
|
|
iter->second.RenderWindow->RemoveObserver(iter->second.StartRenderTag);
|
|
}
|
|
if (iter->second.EndRenderTag)
|
|
{
|
|
iter->second.RenderWindow->RemoveObserver(iter->second.EndRenderTag);
|
|
}
|
|
this->Internals->RenderWindows.erase(iter);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::AddRenderer(unsigned int id,
|
|
vtkRenderer* renderer)
|
|
{
|
|
double viewport[4] = {0, 0, 1, 1 };
|
|
this->AddRenderer(id, renderer, viewport);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::AddRenderer(unsigned int id,
|
|
vtkRenderer* renderer, const double viewport[4])
|
|
{
|
|
this->Internals->RenderWindows[id].Renderers.push_back(
|
|
vtkInternals::RendererInfo(renderer, vtkTuple<double, 4>(viewport)));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::UpdateRendererViewport(unsigned int id,
|
|
vtkRenderer* renderer, const double viewport[4])
|
|
{
|
|
this->Internals->RenderWindows[id].Renderers.push_back(
|
|
vtkInternals::RendererInfo(renderer, vtkTuple<double, 4>(viewport)));
|
|
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter == this->Internals->RenderWindows.end())
|
|
{
|
|
return false;
|
|
}
|
|
vtkInternals::VectorOfRenderers::iterator iterRen;
|
|
for (iterRen = iter->second.Renderers.begin();
|
|
iterRen != iter->second.Renderers.end(); ++iterRen)
|
|
{
|
|
if (iterRen->first.GetPointer() == renderer)
|
|
{
|
|
iterRen->second = vtkTuple<double, 4>(viewport);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::RemoveAllRenderers(unsigned int id)
|
|
{
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
iter->second.Renderers.clear();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkRenderWindow* vtkPVSynchronizedRenderWindows::GetRenderWindow(unsigned int id)
|
|
{
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
return iter->second.RenderWindow;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SetWindowSize(unsigned int id,
|
|
int width, int height)
|
|
{
|
|
this->Internals->RenderWindows[id].Size[0] = width;
|
|
this->Internals->RenderWindows[id].Size[1] = height;
|
|
|
|
// Make sure none of the dimension is 0
|
|
width = width ? width : 10;
|
|
height = height ? height : 10;
|
|
|
|
if (this->Mode == BUILTIN || this->Mode == CLIENT)
|
|
{
|
|
vtkRenderWindow* window = this->GetRenderWindow(id);
|
|
if (window && (window->GetSize()[0] != width ||
|
|
window->GetSize()[1] != height) )
|
|
{
|
|
window->SetSize(width, height);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SetWindowPosition(unsigned int id,
|
|
int px, int py)
|
|
{
|
|
this->Internals->RenderWindows[id].Position[0] = px;
|
|
this->Internals->RenderWindows[id].Position[1] = py;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const int *vtkPVSynchronizedRenderWindows::GetWindowSize(unsigned int id)
|
|
{
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
return iter->second.Size;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const int *vtkPVSynchronizedRenderWindows::GetWindowPosition(unsigned int id)
|
|
{
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
return iter->second.Position;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::UpdateRendererDrawStates(unsigned int id)
|
|
{
|
|
if (this->Internals->SharedRenderWindow == NULL)
|
|
{
|
|
// If there's no shared render window, we don't need to hide any renders
|
|
// since each view is rendering in a separate render-window.
|
|
return;
|
|
}
|
|
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter == this->Internals->RenderWindows.end())
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::set<vtkRenderer*> to_enable;
|
|
vtkInternals::VectorOfRenderers::iterator iterRen;
|
|
for (iterRen = iter->second.Renderers.begin();
|
|
iterRen != iter->second.Renderers.end(); ++iterRen)
|
|
{
|
|
to_enable.insert(iterRen->first.GetPointer());
|
|
}
|
|
|
|
// disable all other renderers.
|
|
vtkRendererCollection* renderers = iter->second.RenderWindow->GetRenderers();
|
|
renderers->InitTraversal();
|
|
while (vtkRenderer* ren = renderers->GetNextItem())
|
|
{
|
|
if (to_enable.find(ren) != to_enable.end())
|
|
{
|
|
ren->DrawOn();
|
|
}
|
|
else
|
|
{
|
|
ren->DrawOff();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::Render(unsigned int id)
|
|
{
|
|
// cout << "Rendering: " << id << endl;
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(id);
|
|
if (iter == this->Internals->RenderWindows.end())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// FIXME: When root node tries to communicate to the satellites the active
|
|
// id, there's no clean way of determining the active id since on root node
|
|
// the render window is shared among all views. Hence, we have this hack :(.
|
|
this->Internals->ActiveId = id;
|
|
iter->second.RenderWindow->Render();
|
|
this->Internals->ActiveId = 0;
|
|
// cout << "Done Rendering: " << id << endl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::HandleStartRender(vtkRenderWindow* renWin)
|
|
{
|
|
// This method is called when a render window starts rendering. This is called
|
|
// on all processes. The response is different on all the processes based on
|
|
// the mode/configuration.
|
|
|
|
switch (this->Mode)
|
|
{
|
|
case CLIENT:
|
|
this->ClientStartRender(renWin);
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
case BATCH:
|
|
if (this->ParallelController->GetLocalProcessId() == 0)
|
|
{
|
|
// root node.
|
|
this->RootStartRender(renWin);
|
|
}
|
|
else
|
|
{
|
|
this->SatelliteStartRender(renWin);
|
|
}
|
|
break;
|
|
|
|
case BUILTIN:
|
|
case DATA_SERVER:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::HandleEndRender(vtkRenderWindow*)
|
|
{
|
|
switch (this->Mode)
|
|
{
|
|
case CLIENT:
|
|
this->ClientServerController->Barrier();
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
if (this->ParallelController->GetLocalProcessId() == 0)
|
|
{
|
|
this->ClientServerController->Barrier();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::ClientStartRender(vtkRenderWindow* renWin)
|
|
{
|
|
// In client-server mode, the client needs to collect the window layouts and
|
|
// then the active window specific parameters.
|
|
|
|
this->Internals->ActiveId = this->Internals->GetKey(renWin);
|
|
if (this->RenderEventPropagation)
|
|
{
|
|
// Tell the server-root to start rendering.
|
|
vtkMultiProcessStream stream;
|
|
stream << this->Internals->ActiveId;
|
|
std::vector<unsigned char> data;
|
|
stream.GetRawData(data);
|
|
this->ClientServerController->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), SYNC_MULTI_RENDER_WINDOW_TAG);
|
|
}
|
|
// when this->RenderEventPropagation, we assume that the server activates the
|
|
// correct render window somehow.
|
|
|
|
vtkMultiProcessStream stream;
|
|
|
|
// Pass in the information about the layout for all the windows.
|
|
// TODO: This gets called when rendering each render window. However, this
|
|
// information does not necessarily get invalidated that frequently. Can we be
|
|
// smart about it?
|
|
this->SaveWindowAndLayout(renWin, stream);
|
|
|
|
this->ClientServerController->Send(stream, 1, 22222);
|
|
|
|
this->UpdateWindowLayout();
|
|
|
|
this->Internals->ActiveId = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::BeginRender(unsigned int id)
|
|
{
|
|
this->Internals->ActiveId = id;
|
|
|
|
// BeginRender() is needed to be explicitly called in cases where there's a
|
|
// SharedRenderWindow.
|
|
if (this->Internals->SharedRenderWindow)
|
|
{
|
|
// BUG #14280 and BUG #13797.
|
|
// When vtkPVSynchronizedRenderWindows is enabled, the
|
|
// vtkPVSynchronizedRenderWindows will take care for updating the layout of
|
|
// all render windows and renderer at the start of render.
|
|
// However, in cases when the vtkPVSynchronizedRenderWindows is not enabled
|
|
// e.g. chart-views or other views that don't do parallel rendering (except
|
|
// in tile-display mode), we still need to relay out the windows and
|
|
// activate correct renderers. This piece of code takes care of that.
|
|
if (!this->GetEnabled() && this->GetLocalProcessIsDriver())
|
|
{
|
|
this->UpdateWindowLayout();
|
|
}
|
|
|
|
// Ensure the right renderers are visible in shared windows.
|
|
this->UpdateRendererDrawStates(this->Internals->ActiveId);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::RootStartRender(vtkRenderWindow* renWin)
|
|
{
|
|
if (this->ClientServerController)
|
|
{
|
|
// * Get window layout from the server. $CODE_GET_LAYOUT_AND_UPDATE$
|
|
vtkMultiProcessStream stream;
|
|
this->ClientServerController->Receive(stream, 1, 22222);
|
|
|
|
// Load the layout for all the windows from the client.
|
|
this->LoadWindowAndLayout(renWin, stream);
|
|
}
|
|
|
|
this->ShinkGaps();
|
|
|
|
// * Ensure layout i.e. all renders have correct viewports and hide inactive
|
|
// renderers.
|
|
this->UpdateWindowLayout();
|
|
|
|
if (this->ParallelController->GetNumberOfProcesses() <= 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (this->RenderEventPropagation)
|
|
{
|
|
// * Tell the satellites to start rendering.
|
|
vtkMultiProcessStream stream;
|
|
stream << this->Internals->ActiveId;
|
|
std::vector<unsigned char> data;
|
|
stream.GetRawData(data);
|
|
this->ParallelController->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), SYNC_MULTI_RENDER_WINDOW_TAG);
|
|
}
|
|
|
|
// * Send the layout and window params to the satellites.
|
|
vtkMultiProcessStream stream;
|
|
// Pass in the information about the layout for all the windows.
|
|
// TODO: This gets called when rendering each render window. However, this
|
|
// information does not necessarily get invalidated that frequently. Can we be
|
|
// smart about it?
|
|
this->SaveWindowAndLayout(renWin, stream);
|
|
|
|
this->ParallelController->Broadcast(stream, 0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SatelliteStartRender(
|
|
vtkRenderWindow* renWin)
|
|
{
|
|
// * Get window layout from the server. $CODE_GET_LAYOUT_AND_UPDATE$
|
|
if (this->ParallelController)
|
|
{
|
|
vtkMultiProcessStream stream;
|
|
this->ParallelController->Broadcast(stream, 0);
|
|
|
|
// Load the layout for all the windows from the root.
|
|
this->LoadWindowAndLayout(renWin, stream);
|
|
}
|
|
|
|
// * Ensure layout i.e. all renders have correct viewports and hide inactive
|
|
// renderers.
|
|
this->UpdateWindowLayout();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::SaveWindowAndLayout(
|
|
vtkRenderWindow* window, vtkMultiProcessStream& stream)
|
|
{
|
|
int full_size[2] = {0, 0};
|
|
stream << static_cast<unsigned int>(this->Internals->RenderWindows.size());
|
|
|
|
vtkInternals::RenderWindowsMap::iterator iter;
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
const int *actual_size = iter->second.Size;
|
|
const int *position = iter->second.Position;
|
|
|
|
full_size[0] = full_size[0] > (position[0] + actual_size[0])?
|
|
full_size[0] : position[0] + actual_size[0];
|
|
full_size[1] = full_size[1] > (position[1] + actual_size[1])?
|
|
full_size[1] : position[1] + actual_size[1];
|
|
|
|
stream << iter->first << position[0] << position[1]
|
|
<< actual_size[0] << actual_size[1];
|
|
}
|
|
|
|
// Now push the full size.
|
|
stream << full_size[0] << full_size[1];
|
|
|
|
// Now save the window's tile scale and tile-viewport.
|
|
int tileScale[2];
|
|
double tileViewport[4];
|
|
window->GetTileScale(tileScale);
|
|
window->GetTileViewport(tileViewport);
|
|
stream << tileScale[0] << tileScale[1]
|
|
<< tileViewport[0] << tileViewport[1] << tileViewport[2]
|
|
<< tileViewport[3]
|
|
<< window->GetDesiredUpdateRate();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::LoadWindowAndLayout(
|
|
vtkRenderWindow* window, vtkMultiProcessStream& stream)
|
|
{
|
|
unsigned int number_of_windows = 0;
|
|
stream >> number_of_windows;
|
|
|
|
if (number_of_windows != static_cast<unsigned int>(
|
|
this->Internals->RenderWindows.size()))
|
|
{
|
|
vtkErrorMacro("Mismatch is render windows on different processes. "
|
|
"Aborting for debugging purposes.");
|
|
abort();
|
|
}
|
|
|
|
for (unsigned int cc=0; cc < number_of_windows; cc++)
|
|
{
|
|
int actual_size[2];
|
|
int position[2];
|
|
unsigned int key;
|
|
stream >> key >> position[0] >> position[1]
|
|
>> actual_size[0] >> actual_size[1];
|
|
|
|
vtkInternals::RenderWindowsMap::iterator iter =
|
|
this->Internals->RenderWindows.find(key);
|
|
if (iter == this->Internals->RenderWindows.end())
|
|
{
|
|
vtkErrorMacro("Don't know anything about windows with key: " << key);
|
|
continue;
|
|
}
|
|
|
|
iter->second.Size[0] = actual_size[0];
|
|
iter->second.Size[1] = actual_size[1];
|
|
iter->second.Position[0] = position[0];
|
|
iter->second.Position[1] = position[1];
|
|
}
|
|
|
|
// Now load the full size.
|
|
int full_size[2];
|
|
stream >> full_size[0] >> full_size[1];
|
|
|
|
// Now load the window's tile scale and tile-viewport.
|
|
// tile-scale and viewport are overloaded. They are used when rendering large
|
|
// images as well as when rendering in tile-display mode. The code here
|
|
// handles the case when rendering large images.
|
|
int tileScale[2];
|
|
double tileViewport[4];
|
|
double desiredUpdateRate;
|
|
|
|
stream >> tileScale[0] >> tileScale[1]
|
|
>> tileViewport[0] >> tileViewport[1] >> tileViewport[2]
|
|
>> tileViewport[3]
|
|
>> desiredUpdateRate;
|
|
window->SetTileScale(tileScale);
|
|
window->SetTileViewport(tileViewport);
|
|
window->SetDesiredUpdateRate(desiredUpdateRate);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::UpdateWindowLayout()
|
|
{
|
|
int full_size[2] = {0, 0};
|
|
vtkInternals::RenderWindowsMap::iterator iter;
|
|
|
|
if (this->RenderOneViewAtATime)
|
|
{
|
|
iter = this->Internals->RenderWindows.find(this->Internals->ActiveId);
|
|
if (iter != this->Internals->RenderWindows.end())
|
|
{
|
|
iter->second.RenderWindow->SetSize(iter->second.Size);
|
|
double viewport[4] = {0, 0, 1, 1};
|
|
this->Internals->UpdateViewports(
|
|
iter->second.Renderers, viewport);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Compute full_size.
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
const int *actual_size = iter->second.Size;
|
|
const int *position = iter->second.Position;
|
|
|
|
full_size[0] = full_size[0] > (position[0] + actual_size[0])?
|
|
full_size[0] : position[0] + actual_size[0];
|
|
full_size[1] = full_size[1] > (position[1] + actual_size[1])?
|
|
full_size[1] : position[1] + actual_size[1];
|
|
}
|
|
|
|
switch (this->Mode)
|
|
{
|
|
case CLIENT:
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
//const int *actual_size = iter->second.Size;
|
|
//const int *position = iter->second.Position;
|
|
// This class only supports full-viewports.
|
|
double viewport[4] = {0, 0, 1, 1};
|
|
this->Internals->UpdateViewports(
|
|
iter->second.Renderers, viewport);
|
|
}
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
case BATCH:
|
|
{
|
|
// If we are in tile-display mode, we should update the tile-scale
|
|
// and tile-viewport for the render window. That is required for the camera
|
|
// as well as for the annotations to show correctly.
|
|
int tile_dims[2], tile_mullions[2];
|
|
bool in_tile_display_mode = this->GetTileDisplayParameters(tile_dims,
|
|
tile_mullions);
|
|
bool in_cave_mode = this->GetIsInCave();
|
|
if (in_tile_display_mode)
|
|
{
|
|
if (vtksys::SystemTools::GetEnv("PV_ICET_WINDOW_BORDERS"))
|
|
{
|
|
this->Internals->SharedRenderWindow->SetSize(400, 400);
|
|
}
|
|
else
|
|
{
|
|
this->Internals->SharedRenderWindow->SetFullScreen(1);
|
|
}
|
|
|
|
// TileScale and TileViewport must be setup on render window correctly
|
|
// so that 2D props show up correctly in tile display mode.
|
|
double tile_viewport[4];
|
|
vtkTilesHelper* helper = vtkTilesHelper::New();
|
|
helper->SetTileDimensions(tile_dims);
|
|
helper->SetTileMullions(tile_mullions);
|
|
helper->SetTileWindowSize(this->Internals->SharedRenderWindow->GetActualSize());
|
|
helper->GetNormalizedTileViewport(NULL,
|
|
this->ParallelController->GetLocalProcessId(), tile_viewport);
|
|
helper->Delete();
|
|
|
|
this->Internals->SharedRenderWindow->SetTileScale(tile_dims);
|
|
this->Internals->SharedRenderWindow->SetTileViewport(tile_viewport);
|
|
}
|
|
else if (in_cave_mode)
|
|
{
|
|
// Check if a custom window geometry was requested
|
|
int *geometry = NULL;
|
|
bool fullscreen = true;
|
|
bool showborders = false;
|
|
if (this->ParallelController)
|
|
{
|
|
int idx = this->ParallelController->GetLocalProcessId();
|
|
fullscreen = this->Session->GetServerInformation()->GetFullScreen(idx);
|
|
showborders = this->Session->GetServerInformation()->GetShowBorders(idx);
|
|
if (!fullscreen)
|
|
{
|
|
geometry = this->Session->GetServerInformation()->GetGeometry(idx);
|
|
// If the geometry has not been defined, it will be 0 0 0 0. Unset the
|
|
// geometry pointer in this case.
|
|
if (geometry[0] <= 0 && geometry[1] <= 0 && geometry[2] <= 0 &&
|
|
geometry[3] <= 0)
|
|
{
|
|
geometry = NULL;
|
|
}
|
|
}
|
|
|
|
int stereoType = this->Session->GetServerInformation()->GetStereoType(idx);
|
|
if (stereoType != -1)
|
|
{
|
|
this->Internals->SharedRenderWindow->SetStereoRender(stereoType!=0);
|
|
if (stereoType > 0)
|
|
{
|
|
this->Internals->SharedRenderWindow->SetStereoType(stereoType);
|
|
}
|
|
}
|
|
}
|
|
this->Internals->SharedRenderWindow->SetBorders(showborders ? 1 : 0);
|
|
// Preserve old behavior for PV_ICET_WINDOW_BORDERS env var
|
|
if (vtksys::SystemTools::GetEnv("PV_ICET_WINDOW_BORDERS"))
|
|
{
|
|
this->Internals->SharedRenderWindow->SetSize(400, 400);
|
|
}
|
|
else
|
|
{
|
|
if (fullscreen)
|
|
{
|
|
this->Internals->SharedRenderWindow->SetFullScreen(1);
|
|
}
|
|
else
|
|
{
|
|
// Use the specified geometry
|
|
int x = geometry ? geometry[0] : 0;
|
|
int y = geometry ? geometry[1] : 0;
|
|
int w = geometry ? geometry[2] : 400;
|
|
int h = geometry ? geometry[3] : 400;
|
|
this->Internals->SharedRenderWindow->SetFullScreen(0);
|
|
this->Internals->SharedRenderWindow->SetPosition(x, y);
|
|
this->Internals->SharedRenderWindow->SetSize(w, h);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// NOTE: if you want to render a higher resolution image on the server,
|
|
// you can very easily do that simply set that size here. Just ensure
|
|
// that the aspect ratio remains the same.
|
|
this->Internals->SharedRenderWindow->SetSize(full_size);
|
|
//this->Internals->SharedRenderWindow->SetPosition(0, 0);
|
|
}
|
|
|
|
// Iterate over all (logical) windows and set the viewport on the
|
|
// renderers to reflect the position and size of the actual window on the
|
|
// client side.
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
const int *actual_size = iter->second.Size;
|
|
const int *position = iter->second.Position;
|
|
|
|
// This class only supports full-viewports.
|
|
double viewport[4];
|
|
viewport[0] = position[0]/static_cast<double>(full_size[0]);
|
|
viewport[1] = position[1]/static_cast<double>(full_size[1]);
|
|
viewport[2] = (position[0] + actual_size[0])/
|
|
static_cast<double>(full_size[0]);
|
|
viewport[3] = (position[1] + actual_size[1])/
|
|
static_cast<double>(full_size[1]);
|
|
|
|
// As far as window-positions go, (0,0) is top-left corner, while for
|
|
// viewport (0, 0) is bottom-left corner. So we flip the Y viewport.
|
|
viewport[1] = 1.0 - viewport[1];
|
|
viewport[3] = 1.0 - viewport[3];
|
|
double temp = viewport[1];
|
|
viewport[1] = viewport[3];
|
|
viewport[3] = temp;
|
|
|
|
// This viewport is the viewport for the renderers treating the all the
|
|
// tiles as one large display.
|
|
//cout << "Current Viewport:" << viewport[0]
|
|
// << ", " << viewport[1] << ", " << viewport[2]
|
|
// << ", " << viewport[3] << endl;
|
|
this->Internals->UpdateViewports(
|
|
iter->second.Renderers, viewport);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BUILTIN:
|
|
case DATA_SERVER:
|
|
case INVALID:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// We use the following approach:
|
|
// "Top-left corner for every box is moved up-and-left till it intersects
|
|
// another box"
|
|
// This works well for the way ParaView splits view.
|
|
void vtkPVSynchronizedRenderWindows::ShinkGaps()
|
|
{
|
|
bool something_expanded;
|
|
int max_size[2];
|
|
do
|
|
{
|
|
something_expanded = false;
|
|
max_size[0] = max_size[1] = 0;
|
|
vtkInternals::RenderWindowsMap::iterator iter;
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
const int *size = iter->second.Size;
|
|
int *position = iter->second.Position;
|
|
if (this->Internals->ExpandLeft(iter->first, size, position))
|
|
{
|
|
something_expanded = true;
|
|
}
|
|
if (this->Internals->ExpandTop(iter->first, size, position))
|
|
{
|
|
something_expanded = true;
|
|
}
|
|
if (max_size[0] < position[0] + size[0]-1)
|
|
{
|
|
max_size[0] = position[0] + size[0]-1;
|
|
}
|
|
if (max_size[1] < position[1] + size[1]-1)
|
|
{
|
|
max_size[1] = position[1] + size[1]-1;
|
|
}
|
|
}
|
|
}
|
|
while (something_expanded);
|
|
|
|
int temp[2];
|
|
if (!this->GetTileDisplayParameters(temp, temp))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// The above code can result in small gaps at the
|
|
// very ends (bottom/right) in some configurations. We expand those gaps only
|
|
// in tile-display mode, since otherwise it messes up the aspect ratio and
|
|
// would end up delivering image with wrong aspect ratio of images sent to the
|
|
// client.
|
|
vtkInternals::RenderWindowsMap::iterator iter;
|
|
for (iter = this->Internals->RenderWindows.begin();
|
|
iter != this->Internals->RenderWindows.end(); ++iter)
|
|
{
|
|
int *size = iter->second.Size;
|
|
const int *position = iter->second.Position;
|
|
this->Internals->ExpandRight(iter->first, max_size, size, position);
|
|
this->Internals->ExpandBottom(iter->first, max_size, size, position);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::GetIsInCave()
|
|
{
|
|
vtkPVServerInformation* server_info = this->Session->GetServerInformation();
|
|
|
|
int temp[2];
|
|
if (!this->GetTileDisplayParameters(temp, temp))
|
|
{
|
|
return server_info->GetNumberOfMachines() > 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::GetTileDisplayParameters(
|
|
int tile_dims[2], int tile_mullions[2])
|
|
{
|
|
vtkPVServerInformation* info = this->Session->GetServerInformation();
|
|
|
|
tile_dims[0] = info->GetTileDimensions()[0];
|
|
tile_dims[1] = info->GetTileDimensions()[1];
|
|
bool in_tile_display_mode = (tile_dims[0] > 0 || tile_dims[1] > 0);
|
|
tile_dims[0] = (tile_dims[0] == 0)? 1 : tile_dims[0];
|
|
tile_dims[1] = (tile_dims[1] == 0)? 1 : tile_dims[1];
|
|
info->GetTileMullions(tile_mullions);
|
|
return in_tile_display_mode;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
template <class T>
|
|
T vtkEvaluateReductionOperation(T val0, T val1,
|
|
vtkPVSynchronizedRenderWindows::StandardOperations operation)
|
|
{
|
|
switch (operation)
|
|
{
|
|
case vtkPVSynchronizedRenderWindows::MAX_OP:
|
|
return val0 > val1? val0 : val1;
|
|
|
|
case vtkPVSynchronizedRenderWindows::MIN_OP:
|
|
return val0 < val1? val0 : val1;
|
|
|
|
case vtkPVSynchronizedRenderWindows::SUM_OP:
|
|
return val0 + val1;
|
|
}
|
|
return val0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
bool vtkPVSynchronizedRenderWindows::ReduceTemplate(T& size,
|
|
vtkPVSynchronizedRenderWindows::StandardOperations operation)
|
|
{
|
|
// handle trivial case.
|
|
if (this->Mode == BUILTIN || this->Mode == INVALID)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
vtkMultiProcessController* parallelController =
|
|
vtkMultiProcessController::GetGlobalController();
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
|
|
// The strategy is reduce the value to client then broadcast it out to
|
|
// render-server and data-server.
|
|
if (parallelController)
|
|
{
|
|
T result = size;
|
|
parallelController->Reduce(&size, &result, 1, operation, 0);
|
|
size = result;
|
|
}
|
|
|
|
// on pvdataserver/pvrenderserver/pvserver/pvbatch, we now have collected the
|
|
// size-sum on root node.
|
|
switch (this->Mode)
|
|
{
|
|
case CLIENT:
|
|
{
|
|
if (c_ds_controller)
|
|
{
|
|
T other_size;
|
|
c_ds_controller->Receive(&other_size, 1, 1, 41232);
|
|
size = vtkEvaluateReductionOperation(size, other_size, operation);
|
|
}
|
|
if (c_rs_controller)
|
|
{
|
|
T other_size;
|
|
c_rs_controller->Receive(&other_size, 1, 1, 41232);
|
|
size = vtkEvaluateReductionOperation(size, other_size, operation);
|
|
}
|
|
if (c_ds_controller)
|
|
{
|
|
c_ds_controller->Send(&size, 1, 1, 41232);
|
|
}
|
|
if (c_rs_controller)
|
|
{
|
|
c_rs_controller->Send(&size, 1, 1, 41232);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DATA_SERVER:
|
|
// both can't be set on a server process.
|
|
if (c_ds_controller)
|
|
{
|
|
c_ds_controller->Send(&size, 1, 1, 41232);
|
|
c_ds_controller->Receive(&size, 1, 1, 41232);
|
|
}
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
if (c_rs_controller)
|
|
{
|
|
c_rs_controller->Send(&size, 1, 1, 41232);
|
|
c_rs_controller->Receive(&size, 1, 1, 41232);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(c_ds_controller==NULL && c_rs_controller == NULL);
|
|
}
|
|
|
|
if (parallelController)
|
|
{
|
|
parallelController->Broadcast(&size, 1, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::SynchronizeSize(double& size)
|
|
{
|
|
return this->ReduceTemplate<double>(size, SUM_OP);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::SynchronizeSize(unsigned int& size)
|
|
{
|
|
return this->ReduceTemplate<unsigned int>(size, SUM_OP);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::Reduce(
|
|
vtkIdType& value, vtkPVSynchronizedRenderWindows::StandardOperations operation)
|
|
{
|
|
return this->ReduceTemplate<vtkIdType>(value, operation);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::SynchronizeBounds(double bounds[6])
|
|
{
|
|
// handle trivial case.
|
|
if (this->Mode == BUILTIN || this->Mode == INVALID)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
vtkMultiProcessController* parallelController =
|
|
vtkMultiProcessController::GetGlobalController();
|
|
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
|
|
// The strategy is reduce the value to client then broadcast it out to
|
|
// render-server and data-server.
|
|
if (parallelController)
|
|
{
|
|
double min_bounds[3] = {bounds[0], bounds[2], bounds[4]};
|
|
double max_bounds[3] = {bounds[1], bounds[3], bounds[5]};
|
|
double min_result[3], max_result[3];
|
|
parallelController->Reduce(min_bounds, min_result, 3,
|
|
vtkCommunicator::MIN_OP, 0);
|
|
parallelController->Reduce(max_bounds, max_result, 3,
|
|
vtkCommunicator::MAX_OP, 0);
|
|
bounds[0] = min_result[0];
|
|
bounds[2] = min_result[1];
|
|
bounds[4] = min_result[2];
|
|
bounds[1] = max_result[0];
|
|
bounds[3] = max_result[1];
|
|
bounds[5] = max_result[2];
|
|
}
|
|
|
|
// on pvdataserver/pvrenderserver/pvserver/pvbatch, we now have collected the
|
|
// size-sum on root node.
|
|
switch (this->Mode)
|
|
{
|
|
case CLIENT:
|
|
{
|
|
vtkBoundingBox bbox;
|
|
bbox.AddBounds(bounds);
|
|
|
|
if (c_ds_controller)
|
|
{
|
|
c_ds_controller->Receive(bounds, 6, 1, 41232);
|
|
bbox.AddBounds(bounds);
|
|
}
|
|
if (c_rs_controller)
|
|
{
|
|
c_rs_controller->Receive(bounds, 6, 1, 41232);
|
|
bbox.AddBounds(bounds);
|
|
}
|
|
bbox.GetBounds(bounds);
|
|
if (c_ds_controller)
|
|
{
|
|
c_ds_controller->Send(bounds, 6, 1, 41232);
|
|
}
|
|
if (c_rs_controller)
|
|
{
|
|
c_rs_controller->Send(bounds, 6, 1, 41232);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DATA_SERVER:
|
|
// both can't be set on a server process.
|
|
if (c_ds_controller != NULL)
|
|
{
|
|
c_ds_controller->Send(bounds, 6, 1, 41232);
|
|
c_ds_controller->Receive(bounds, 6, 1, 41232);
|
|
}
|
|
break;
|
|
|
|
case RENDER_SERVER:
|
|
if (c_rs_controller != NULL)
|
|
{
|
|
c_rs_controller->Send(bounds, 6, 1, 41232);
|
|
c_rs_controller->Receive(bounds, 6, 1, 41232);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(c_ds_controller==NULL && c_rs_controller == NULL);
|
|
}
|
|
|
|
if (parallelController)
|
|
{
|
|
parallelController->Broadcast(bounds, 6, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::BroadcastToDataServer(vtkSelection* selection)
|
|
{
|
|
// handle trivial case.
|
|
if (this->Mode == BUILTIN || this->Mode == INVALID)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (vtkProcessModule::GetProcessType() == vtkProcessModule::PROCESS_RENDER_SERVER)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
vtkMultiProcessController* parallelController =
|
|
this->GetParallelController();
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
if (!c_ds_controller)
|
|
{
|
|
c_ds_controller = c_rs_controller;
|
|
}
|
|
|
|
if (this->Mode == BATCH &&
|
|
parallelController->GetNumberOfProcesses() <= 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::ostringstream xml_stream;
|
|
vtkSelectionSerializer::PrintXML(xml_stream, vtkIndent(), 1, selection);
|
|
vtkMultiProcessStream stream;
|
|
stream << xml_stream.str();
|
|
|
|
if (this->Mode == CLIENT && c_ds_controller)
|
|
{
|
|
c_ds_controller->Send(stream, 1, 41233);
|
|
return true;
|
|
}
|
|
else if (c_ds_controller)
|
|
{
|
|
c_ds_controller->Receive(stream, 1, 41233);
|
|
}
|
|
|
|
if (parallelController && parallelController->GetNumberOfProcesses() > 1)
|
|
{
|
|
parallelController->Broadcast(stream, 0);
|
|
}
|
|
|
|
std::string xml;
|
|
stream >> xml;
|
|
vtkSelectionSerializer::Parse(xml.c_str(), selection);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::BroadcastToRenderServer(
|
|
vtkDataObject* dataObject)
|
|
{
|
|
// handle trivial case.
|
|
if (this->Mode == BUILTIN || this->Mode == INVALID)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (vtkProcessModule::GetProcessType() ==
|
|
vtkProcessModule::PROCESS_DATA_SERVER)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
vtkMultiProcessController* parallelController =
|
|
this->GetParallelController();
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
|
|
if (this->Mode == BATCH &&
|
|
parallelController->GetNumberOfProcesses() <= 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (this->Mode == CLIENT && c_rs_controller)
|
|
{
|
|
c_rs_controller->Send(dataObject, 1, 41234);
|
|
return true;
|
|
}
|
|
else if (c_rs_controller)
|
|
{
|
|
c_rs_controller->Receive(dataObject, 1, 41234);
|
|
}
|
|
|
|
if (parallelController && parallelController->GetNumberOfProcesses() > 1)
|
|
{
|
|
parallelController->Broadcast(dataObject, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::TriggerRMI(
|
|
vtkMultiProcessStream& stream, int tag)
|
|
{
|
|
if (this->Mode == BUILTIN)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// don't use this->GetParallelController() since that only works on rendering
|
|
// nodes.
|
|
vtkMultiProcessController* parallelController =
|
|
vtkMultiProcessController::GetGlobalController();
|
|
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
|
|
std::vector<unsigned char> data;
|
|
stream.GetRawData(data);
|
|
|
|
if (this->Mode == CLIENT)
|
|
{
|
|
if (c_ds_controller)
|
|
{
|
|
c_ds_controller->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), tag);
|
|
}
|
|
if (c_rs_controller)
|
|
{
|
|
c_rs_controller->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), tag);
|
|
}
|
|
}
|
|
|
|
if (parallelController && parallelController->GetNumberOfProcesses() > 1
|
|
&& parallelController->GetLocalProcessId() == 0)
|
|
{
|
|
parallelController->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), tag);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned long vtkPVSynchronizedRenderWindows::AddRMICallback(
|
|
vtkRMIFunctionType callback, void* localArg, int tag)
|
|
{
|
|
// don't use this->GetParallelController() since that only works on rendering
|
|
// nodes.
|
|
vtkMultiProcessController* parallelController =
|
|
vtkMultiProcessController::GetGlobalController();
|
|
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
|
|
vtkInternals::CallbackInfo info;
|
|
info.ParallelHandle = parallelController?
|
|
parallelController->AddRMICallback(callback, localArg, tag) : 0;
|
|
info.ClientServerHandle = c_rs_controller?
|
|
c_rs_controller->AddRMICallback(callback, localArg, tag) : 0;
|
|
info.ClientDataServerHandle = c_ds_controller?
|
|
c_ds_controller->AddRMICallback(callback, localArg, tag) : 0;
|
|
|
|
unsigned long handle = static_cast<unsigned long>(
|
|
this->Internals->RMICallbacks.size());
|
|
this->Internals->RMICallbacks.push_back(info);
|
|
return handle;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkPVSynchronizedRenderWindows::RemoveRMICallback(unsigned long id)
|
|
{
|
|
// don't use this->GetParallelController() since that only works on rendering
|
|
// nodes.
|
|
vtkMultiProcessController* parallelController =
|
|
vtkMultiProcessController::GetGlobalController();
|
|
|
|
vtkMultiProcessController* c_rs_controller =
|
|
this->GetClientServerController();
|
|
// c_ds_controller is non-null only in client-dataserver-renderserver
|
|
// configuratrions.
|
|
vtkMultiProcessController* c_ds_controller =
|
|
this->GetClientDataServerController();
|
|
assert(c_ds_controller == NULL || c_ds_controller != c_rs_controller);
|
|
|
|
if (this->Internals->RMICallbacks.size() > id)
|
|
{
|
|
vtkInternals::CallbackInfo &info = this->Internals->RMICallbacks[id];
|
|
if (info.ParallelHandle && parallelController)
|
|
{
|
|
parallelController->RemoveRMICallback(info.ParallelHandle);
|
|
}
|
|
if (info.ClientServerHandle && c_rs_controller)
|
|
{
|
|
c_rs_controller->RemoveRMICallback(info.ClientServerHandle);
|
|
}
|
|
if (info.ClientDataServerHandle && c_ds_controller)
|
|
{
|
|
c_ds_controller->RemoveRMICallback(info.ClientDataServerHandle);
|
|
}
|
|
info = vtkInternals::CallbackInfo();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkPVSynchronizedRenderWindows::GetZbufferDataAtPoint(int x, int y,
|
|
unsigned int id)
|
|
{
|
|
vtkRenderWindow* window = this->GetRenderWindow(id);
|
|
if (!this->Enabled ||
|
|
(this->Mode != vtkPVSynchronizedRenderWindows::CLIENT) ||
|
|
window == NULL)
|
|
{
|
|
return window? window->GetZbufferDataAtPoint(x, y) : 1.0;
|
|
}
|
|
|
|
assert(this->Mode == CLIENT && window != NULL);
|
|
if (this->ClientServerController)
|
|
{
|
|
vtkMultiProcessStream stream;
|
|
stream << id << x << y;
|
|
|
|
std::vector<unsigned char> data;
|
|
stream.GetRawData(data);
|
|
this->ClientServerController->TriggerRMIOnAllChildren(
|
|
&data[0], static_cast<int>(data.size()), GET_ZBUFFER_VALUE_TAG);
|
|
double value = 1.0;
|
|
this->ClientServerController->Receive(&value, 1, 1, GET_ZBUFFER_VALUE_TAG);
|
|
return value;
|
|
}
|
|
|
|
return 1.0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::OnGetZBufferValue(
|
|
unsigned int id, int x, int y)
|
|
{
|
|
double value = this->GetZbufferDataAtPoint(x, y, id);
|
|
// FIXME: need to get the value from IceT.
|
|
this->ClientServerController->Send(&value, 1, 1, GET_ZBUFFER_VALUE_TAG);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkPVSynchronizedRenderWindows::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
}
|