上一节,我们讲到最后:不知道它是否属于,这里的xml_name为RenderView
rendering.__dict__[xmlName]
然而我在Paraview的源代码中找到这样一个类,它叫做vtkSMRenderViewProxy,它的父类为vtkSMViewProxy,这个类在ParaviewCore/Servermanager/Rendering/文件夹下。在它的父类中有这个方法StillRender()。它的代码如下
头文件中:
// Renders the view using full resolution.
virtual void StillRender();
可以看到这个方法是采用全分辨率渲染view
源文件中:
void vtkSMViewProxy::StillRender()
{
// bug 0013947
// on Mac OSX don't render into invalid drawable, all subsequent
// OpenGL calls fail with invalid framebuffer operation.
if (this->IsContextReadyForRendering() == false)//判断当前window是否可画
{
return;
}
int interactive = 0;
this->InvokeEvent(vtkCommand::StartEvent, &interactive);
this->GetSession()->PrepareProgress();
// We call update separately from the render. This is done so that we don't//我们单独调用render的更新。这样做之后,我们不会得到GUI的任何同步的信息,这归咎
// get any synchronization issues with GUI responding to the data-updated于数>//据更新事件,它是由一些数据信息请求而实现的。如果这些发生时,在服务器端正在
// event by making some data information requests(for example). If those执行StillRender或者InteractiveRender,则将会造成死锁。
// happen while StillRender/InteractiveRender is being executed on the server
// side then we get deadlocks.
this->Update();
vtkTypeUInt32 render_location = this->PreRender(interactive==1);
if (this->ObjectsCreated)
{
vtkClientServerStream stream;
stream << vtkClientServerStream::Invoke
<< VTKOBJECT(this)
<< "StillRender"
<< vtkClientServerStream::End;
this->ExecuteStream(stream, false, render_location);
}
this->PostRender(interactive==1);
this->GetSession()->CleanupPendingProgress();
this->InvokeEvent(vtkCommand::EndEvent, &interactive);
}
接下来执行this->Update,在vtkSMRenderViewProxy这个类中,它是这样的:
void vtkSMRenderViewProxy::Update()
{
this->NeedsUpdateLOD |= this->NeedsUpdate;
this->Superclass::Update();
}
在vtkSMViewProxy中为:
void vtkSMViewProxy::Update()
{
if (this->ObjectsCreated && this->NeedsUpdate)
{
vtkClientServerStream stream;
// To avoid race conditions in multi-client modes, we are taking a peculiar
// approach. Any ivar that affect parallel communication are overridden任何影响并行传输交流的ivar都通过使用客户端在相同执行流的值重载了
// using the client-side values in the same ExecuteStream() call. That
// ensures that two clients cannot enter race condition. This results in minor保证两个clients不会进入竞争状态
// increase in the size of the messages sent, but overall the benefits are
// greater.
vtkPVView* pvview = vtkPVView::SafeDownCast(this->GetClientSideObject());
if (pvview)
{
int use_cache = pvview->GetUseCache()? 1 : 0;
stream << vtkClientServerStream::Invoke
<< VTKOBJECT(this)
<< "SetUseCache" << use_cache
<< vtkClientServerStream::End;
}
stream << vtkClientServerStream::Invoke
<< VTKOBJECT(this)
<< "Update"
<< vtkClientServerStream::End;
this->GetSession()->PrepareProgress();
this->ExecuteStream(stream);
this->GetSession()->CleanupPendingProgress();
unsigned int numProducers = this->GetNumberOfProducers();
for (unsigned int i=0; iGetProducerProxy(i));
if (repr)
{
repr->ViewUpdated(this);
}
else
{
//this->GetProducerProxy(i)->PostUpdateData();
}
}
this->PostUpdateData();
}
}
下面就是要搞清楚:
if (this->ObjectsCreated)
{
vtkClientServerStream stream;
stream << vtkClientServerStream::Invoke
<< VTKOBJECT(this)
<< "StillRender"
<< vtkClientServerStream::End;
this->ExecuteStream(stream, false, render_location);
}
这段代码啥意思,大致理解为把stream赋值成这个,通过以前的经验,感觉应该stream是把里面的内容当做字节流赋值进去,然后执行这段stream程序:
this->ExecuteStream(stream, false, render_location);
vtkTypeUInt32 render_location = this->PreRender(interactive==1);render_location由这个函数赋值。
在子类vtkSMRenderViewProxy中,对PreRender这个方法进行了重载:
vtkTypeUInt32 vtkSMRenderViewProxy::PreRender(bool interactive)
{
this->Superclass::PreRender(interactive);
vtkPVRenderView* rv = vtkPVRenderView::SafeDownCast(
this->GetClientSideObject());
assert(rv != NULL);
if (interactive && rv->GetUseLODForInteractiveRender())
{
// for interactive renders, we need to determine if we are going to use LOD.
// If so, we may need to update the LOD geometries.
this->UpdateLOD();
}
this->DeliveryManager->Deliver(interactive);
return interactive? rv->GetInteractiveRenderProcesses():
rv->GetStillRenderProcesses();
}
这里传过去的bool interactive明显为false。则返回的是
rv->GetStillRenderProcesses();这个函数在vtkPVRenderView中 vtkGetMacro(StillRenderProcesses, vtkTypeUInt32);获得这个类的一个变量StillRenderProcesses
显然是获得执行StillRender的进程。这个rv为vtkPVRenderView的类的一个实例,这个类是在/ParaviewCore/ClientServerCore/Rendering。可以推测,这个类是用于后台服务器端渲染的。所以这就从客户端转到了服务器端。
this->ExecuteStream(stream, false, render_location);
所以很显然,接下来在执行StillRender()的进程执行这段stream程序。我们来看ExecuteStream这个函数:这个函数是继承自vtkSMViewProxy的父类vtkSMProxy的。void vtkSMProxy::ExecuteStream(const vtkClientServerStream& stream,
bool ignore_errors/*=false*/, vtkTypeUInt32 location/*=0*/)
{
if (location == 0)
{
location = this->Location;
}
if (location == 0 || stream.GetNumberOfMessages() == 0)
{
return;
}
if (this->GetSession())
{
this->GetSession()->ExecuteStream(location, stream, ignore_errors);//可以看出它又调用了vtkPVSessionBase类下的ExecuteStream方法。
}
// if no session, nothing to do.
}
vtkPVSessionBase在/ParaviewCore/ServerImplementation/core下
void vtkPVSessionBase::ExecuteStream(//在所给的进程上执行该命令。当这个命令执行之后,使用GetLastResult()获得之后的结果。如果设置为true则,忽 vtkTypeUInt32 location, const vtkClientServerStream& stream//视任何打断进程的错误
{
this->Activate();
// This class does not handle remote sessions, so all messages are directly//这个类不控制远程sessions,所有的信息都直接本地执行
// processes locally.
this->SessionCore->ExecuteStream(location, stream, ignore_errors);//这个类可以看出又调用了下面的一个类vtkPVSessionCore的该方法
this->DeActivate();
}
vtkPVSessionCore在/ParaviewCore/ServerImplementation/core下
void vtkPVSessionCore::ExecuteStream( vtkTypeUInt32 location,
const vtkClientServerStream& stream,
bool ignore_errors/*=false*/)
{
if (stream.GetNumberOfMessages() == 0)
{
return;
}
// This can only be called on the root node.
assert( this->ParallelController == NULL ||
this->ParallelController->GetLocalProcessId() == 0 ||
this->SymmetricMPIMode );
if ( (location & vtkProcessModule::SERVERS) != 0 &&
!this->SymmetricMPIMode)
{
// send message to satellites and then start processing.
if ( this->ParallelController &&
this->ParallelController->GetNumberOfProcesses() > 1 &&
this->ParallelController->GetLocalProcessId() == 0 )//当前为头结点
{
// Forward the message to the satellites if the object is expected to exist//传输到其他卫星进程
// on the satellites.
size_t byte_size;
const unsigned char *raw_data;
stream.GetData(&raw_data, &byte_size);//获取数据
// FIXME: There's one flaw in this logic. If a object is to be created on//这里有一个缺陷,如果一个对象是在DATA_SERVER_ROOT创建的,但是在所有
// DATA_SERVER_ROOT, but on all RENDER_SERVER nodes, then in render-serverRENDER_SERVER//节点上运行,在render-server配置,信息将也会结束为被传输
// configuration, the message will end up being send to all data-server//到所有的数据服务器节点 // nodes as well. Although we never do that presently, it's a possibility
// and we should fix this.
unsigned char type = EXECUTE_STREAM;
this->ParallelController->TriggerRMIOnAllChildren(&type, 1,//TriggerRMI在所有的子节点
ROOT_SATELLITE_RMI_TAG);
int size[2];
size[0] = static_cast(byte_size);
size[1] = (ignore_errors? 1 : 0);
this->ParallelController->Broadcast(size, 2, 0);
this->ParallelController->Broadcast(
const_cast(raw_data), size[0], 0);
}
}
this->ExecuteStreamInternal(stream, ignore_errors);
}