1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkParallelRenderManager.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 Copyright 2003 Sandia Corporation. Under the terms of Contract 11 DE-AC04-94AL85000, there is a non-exclusive license for use of this work by 12 or on behalf of the U.S. Government. Redistribution and use in source and 13 binary forms, with or without modification, are permitted provided that this 14 Notice and any statement of authorship are reproduced on all copies. 15 16 This software is distributed WITHOUT ANY WARRANTY; without even 17 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 18 PURPOSE. See the above copyright notice for more information. 19 20 =========================================================================*/ 21 /** 22 * @class vtkParallelRenderManager 23 * @brief An object to control parallel rendering. 24 * 25 * 26 * vtkParallelRenderManager operates in multiple processes. It provides 27 * proper renderers and render windows for performing the parallel 28 * rendering correctly. It can also attach itself to render windows and 29 * propagate rendering events and camera views. 30 * 31 * @attention 32 * Many parallel rendering schemes do not correctly handle transparency. 33 * Unless otherwise documented, assume a sub class does not. 34 * 35 * @todo 36 * Synchronization/barrier primitives. 37 * 38 * @todo 39 * Query ranges of scalar values of objects in addition to the boundary in 40 * three-space 41 * 42 */ 43 44 #ifndef vtkParallelRenderManager_h 45 #define vtkParallelRenderManager_h 46 47 #include "vtkRenderingParallelModule.h" // For export macro 48 #include "vtkObject.h" 49 50 class vtkDoubleArray; 51 class vtkMultiProcessController; 52 class vtkMultiProcessStream; 53 class vtkRenderer; 54 class vtkRendererCollection; 55 class vtkRenderWindow; 56 class vtkTimerLog; 57 class vtkUnsignedCharArray; 58 59 class VTKRENDERINGPARALLEL_EXPORT vtkParallelRenderManager : public vtkObject 60 { 61 public: 62 vtkTypeMacro(vtkParallelRenderManager, vtkObject); 63 void PrintSelf(ostream &os, vtkIndent indent) override; 64 65 /** 66 * Builds a vtkRenderWindow compatible with this render manager. The 67 * user program is responsible for registering the render window with the 68 * SetRenderWindow method and calling Delete. It is not advisable to use 69 * a parallel render manager with a render window that was not built with 70 * this method. 71 */ 72 virtual vtkRenderWindow *MakeRenderWindow(); 73 74 /** 75 * Builds a vtkRenderer compatible with this render manager. (Should we 76 * also register it?) The user program is responsible for calling 77 * Delete. It is not advisable to use a parallel render manager with a 78 * renderer that was not built with this method. 79 */ 80 virtual vtkRenderer *MakeRenderer(); 81 82 //@{ 83 /** 84 * Set/Get the RenderWindow to use for compositing. 85 * We add a start and end observer to the window. 86 */ 87 vtkGetObjectMacro(RenderWindow, vtkRenderWindow); 88 virtual void SetRenderWindow(vtkRenderWindow *renWin); 89 //@} 90 91 //@{ 92 /** 93 * Set/Get the vtkMultiProcessController which will handle communications 94 * for the parallel rendering. 95 */ 96 vtkGetObjectMacro(Controller, vtkMultiProcessController); 97 virtual void SetController(vtkMultiProcessController *controller); 98 //@} 99 100 /** 101 * This method sets the piece and number of pieces for each 102 * actor with a polydata mapper. 103 */ 104 virtual void InitializePieces(); 105 106 /** 107 * Make all rendering windows not viewable set as off screen rendering. 108 * To make all renderwindows on screen rendering again, call 109 * OffScreenRenderingOff on all the render windows. This class assumes 110 * the window on root node is the only one viewable. Subclasses should 111 * change this as necessary. 112 */ 113 virtual void InitializeOffScreen(); 114 115 /** 116 * Initializes the RMIs and then, if on root node, starts the interactor 117 * on the attached render window. Otherwise, starts processing RMIs. 118 * When the interactor returns, it breaks the RMI listening on all other 119 * processors. 120 */ 121 virtual void StartInteractor(); 122 123 /** 124 * If on node other than root, starts serving RMI requests for parallel 125 * renders. 126 */ 127 virtual void StartServices(); 128 129 /** 130 * If on root node, stops the RMI processing on all service nodes. 131 */ 132 virtual void StopServices(); 133 134 //@{ 135 /** 136 * Callbacks that initialize and finish rendering and other tasks. 137 */ 138 virtual void StartRender(); 139 virtual void EndRender(); 140 virtual void SatelliteStartRender(); 141 virtual void SatelliteEndRender(); 142 virtual void RenderRMI(); 143 virtual void ResetCamera(vtkRenderer *ren); 144 virtual void ResetCameraClippingRange(vtkRenderer *ren); 145 virtual void ComputeVisiblePropBoundsRMI(int renderId); 146 //@} 147 148 virtual void InitializeRMIs(); 149 150 /** 151 * Resets the camera of each renderer contained in the RenderWindow. 152 * Should only be called in the "root" process, and all remote processes 153 * must be processing RMIs for this method to complete. 154 */ 155 virtual void ResetAllCameras(); 156 157 /** 158 * Calculates the bounds by gathering information from all processes. 159 */ 160 virtual void ComputeVisiblePropBounds(vtkRenderer *ren, double bounds[6]); 161 162 //@{ 163 /** 164 * Turns on/off parallel rendering. When on (the default) the object 165 * responds to render events of the attached window, propagates the 166 * render event to other processors, and otherwise enables the parallel 167 * rendering process. 168 */ 169 vtkSetMacro(ParallelRendering, int); 170 vtkGetMacro(ParallelRendering, int); 171 vtkBooleanMacro(ParallelRendering, int); 172 //@} 173 174 //@{ 175 /** 176 * Turns on/off render event propagation. When on (the default) and 177 * ParallelRendering is on, process 0 will send an RMI call to all remote 178 * processes to perform a synchronized render. When off, render must be 179 * manually called on each process. 180 */ 181 vtkSetMacro(RenderEventPropagation, int); 182 vtkGetMacro(RenderEventPropagation, int); 183 vtkBooleanMacro(RenderEventPropagation, int); 184 //@} 185 186 /** 187 * Get/Set the default value used for RenderEventPropagation when a new 188 * instance of vtkParallelRenderManager is created. 189 * Set to true by default. 190 */ SetDefaultRenderEventPropagation(bool val)191 static void SetDefaultRenderEventPropagation(bool val) 192 { vtkParallelRenderManager::DefaultRenderEventPropagation = val; } GetDefaultRenderEventPropagation()193 static bool GetDefaultRenderEventPropagation() 194 { return vtkParallelRenderManager::DefaultRenderEventPropagation; } 195 196 //@{ 197 /** 198 * This is used for tiled display rendering. When data has been 199 * duplicated on all processes, then we do not need to compositing. 200 * Cameras and renders are still propagated though. 201 */ 202 vtkSetMacro(UseCompositing, int); 203 vtkGetMacro(UseCompositing, int); 204 vtkBooleanMacro(UseCompositing, int); 205 //@} 206 207 //@{ 208 /** 209 * Set/Get the reduction factor (for sort-last based parallel renderers). 210 * The size of rendered image is divided by the reduction factor and then 211 * is blown up to the size of the current vtkRenderWindow. Setting 212 * higher reduction factors enables shorter image transfer times (which 213 * is often the bottleneck) but will greatly reduce image quality. A 214 * reduction factor of 2 or greater should only be used for intermediate 215 * images in interactive applications. A reduction factor of 1 (or less) 216 * will result in no change in image quality. A parallel render manager 217 * may ignore the image reduction factor if it will result in little or 218 * no performance enhancements (eg. it does not do image space 219 * manipulations). 220 */ 221 virtual void SetImageReductionFactor(double factor); 222 vtkGetMacro(ImageReductionFactor, double); 223 //@} 224 225 vtkSetMacro(MaxImageReductionFactor, double); 226 vtkGetMacro(MaxImageReductionFactor, double); 227 228 /** 229 * Sets the ReductionFactor based on the given desired update rate and 230 * the rendering metrics taken from the last time UpdateServerInfo was 231 * called. Note that if AutoReductionFactor is on, this function is called 232 * with the desired update rate of the render window automatically. 233 */ 234 virtual void SetImageReductionFactorForUpdateRate(double DesiredUpdateRate); 235 236 //@{ 237 /** 238 * If on, the ReductionFactor is automatically adjusted to best meet the 239 * the DesiredUpdateRate in the current RenderWindow based on metrics 240 * from the last render. 241 */ 242 vtkSetMacro(AutoImageReductionFactor, int); 243 vtkGetMacro(AutoImageReductionFactor, int); 244 vtkBooleanMacro(AutoImageReductionFactor, int); 245 //@} 246 247 //@{ 248 /** 249 * Get rendering metrics. 250 */ 251 vtkGetMacro(RenderTime, double); 252 vtkGetMacro(ImageProcessingTime, double); 253 //@} 254 255 //@{ 256 /** 257 * By default, the state of all renderers in the root's render window is 258 * propagated to the rest of the processes. In order for this to work, all 259 * render windows must have the same renderers in the same order. If this is 260 * not the case, you can turn off the SyncRenderWindowRenderers. When this 261 * flag is off, the list of renderers held by this parallel render manager 262 * (initially empty) is synced. You can modify the list of renderers with the 263 * AddRenderer, RemoveRenderer, and RemoveAllRenderers methods. 264 */ 265 vtkGetMacro(SyncRenderWindowRenderers, int); 266 vtkSetMacro(SyncRenderWindowRenderers, int); 267 vtkBooleanMacro(SyncRenderWindowRenderers, int); 268 virtual void AddRenderer(vtkRenderer *); 269 virtual void RemoveRenderer(vtkRenderer *); 270 virtual void RemoveAllRenderers(); 271 //@} 272 273 //@{ 274 /** 275 * If on (the default), the result of any image space manipulations are 276 * written back to the render window frame buffer. If off, the image 277 * stored in the frame buffer may not be correct. Either way, the 278 * correct frame buffer images may be read with 279 * vtkParallelRenderManager::GetPixelData. Turning WriteBackImages off 280 * may result in a speedup if the render window is not visible to the user 281 * and images are read back for further processing or transit. 282 */ 283 vtkSetMacro(WriteBackImages, int); 284 vtkGetMacro(WriteBackImages, int); 285 vtkBooleanMacro(WriteBackImages, int); 286 //@} 287 288 //@{ 289 /** 290 * If on (the default), when the ImageReductionFactor is greater than 1 291 * and WriteBackImages is on, the image will be magnified to fill the 292 * entire render window. 293 */ 294 vtkSetMacro(MagnifyImages, int); 295 vtkGetMacro(MagnifyImages, int); 296 vtkBooleanMacro(MagnifyImages, int); 297 //@} 298 299 enum { NEAREST, LINEAR }; 300 301 //@{ 302 /** 303 * Sets the method used to magnify images. Nearest simply replicates 304 * each pixel enough times to fill the image. Linear performs linear 305 * interpolation between the pixels. 306 */ 307 virtual void SetMagnifyImageMethod(int method); 308 vtkGetMacro(MagnifyImageMethod, int); SetMagnifyImageMethodToNearest()309 void SetMagnifyImageMethodToNearest() { 310 this->SetMagnifyImageMethod(NEAREST); 311 } SetMagnifyImageMethodToLinear()312 void SetMagnifyImageMethodToLinear() { 313 this->SetMagnifyImageMethod(LINEAR); 314 } 315 //@} 316 317 //@{ 318 /** 319 * Convenience functions for magnifying images. 320 */ 321 virtual void MagnifyImage(vtkUnsignedCharArray *fullImage, 322 const int fullImageSize[2], 323 vtkUnsignedCharArray *reducedImage, 324 const int reducedImageSize[2], 325 const int fullImageViewport[4] = nullptr, 326 const int reducedImageViewport[4] = nullptr); 327 static void MagnifyImageNearest(vtkUnsignedCharArray *fullImage, 328 const int fullImageSize[2], 329 vtkUnsignedCharArray *reducedImage, 330 const int reducedImageSize[2], 331 const int fullImageViewport[4] = nullptr, 332 const int reducedImageViewport[4] = nullptr); 333 static void MagnifyImageLinear(vtkUnsignedCharArray *fullImage, 334 const int fullImageSize[2], 335 vtkUnsignedCharArray *reducedImage, 336 const int reducedImageSize[2], 337 const int fullImageViewport[4] = nullptr, 338 const int reducedImageViewport[4] = nullptr); 339 //@} 340 341 //@{ 342 /** 343 * The most appropriate way to retrieve full size image data after a 344 * render. Will work regardless of whether WriteBackImages or 345 * MagnifyImage is on or off. The data returned may be a shallow copy of 346 * an internal array. Therefore, the data may be invalid after the next 347 * render or if the ParallelRenderManager is destroyed. 348 */ 349 virtual void GetPixelData(vtkUnsignedCharArray *data); 350 virtual void GetPixelData(int x1, int y1, int x2, int y2, 351 vtkUnsignedCharArray *data); 352 //@} 353 354 //@{ 355 /** 356 * The most appropriate way to retrieve reduced size image data after a 357 * render. Will work regardless of whether WriteBackImages or 358 * MagnifyImage is on or off. The data returned may be a shallow copy of 359 * an internal array. Therefore, the data may be invalid after the next 360 * render or if the ParallelRenderManager is destroyed. 361 */ 362 virtual void GetReducedPixelData(vtkUnsignedCharArray *data); 363 virtual void GetReducedPixelData(int x1, int y1, int x2, int y2, 364 vtkUnsignedCharArray *data); 365 //@} 366 367 //@{ 368 /** 369 * Returns the full image size calculated at the last render. 370 */ 371 vtkGetVector2Macro(FullImageSize, int); 372 //@} 373 //@{ 374 /** 375 * Returns the reduced image size calculated at the last render. 376 */ 377 vtkGetVector2Macro(ReducedImageSize, int); 378 //@} 379 380 /** 381 * Given the x and y size of the render windows, reposition them 382 * in a tile of n columns. 383 */ 384 void TileWindows(int xsize, int ysize, int nColumns); 385 386 //@{ 387 /** 388 * Get/Set if all Images must use RGBA instead of RGB. By default, 389 * this flag is on. 390 */ 391 vtkSetMacro(UseRGBA, int); 392 vtkGetMacro(UseRGBA, int); 393 //@} 394 395 //@{ 396 /** 397 * If ForceRenderWindowSize is set to true, the render manager will use 398 * the RenderWindowSize ivar instead of getting the size from the render window. 399 */ 400 vtkSetMacro(ForceRenderWindowSize, int); 401 vtkGetMacro(ForceRenderWindowSize, int); 402 //@} 403 404 //@{ 405 /** 406 * If ForceRenderWindowSize is set to true, the render manager will use 407 * the Size ivar instead of getting the size from the render window. 408 */ 409 vtkSetVector2Macro(ForcedRenderWindowSize, int); 410 vtkGetVector2Macro(ForcedRenderWindowSize, int); 411 //@} 412 413 enum Tags { 414 RENDER_RMI_TAG=34532, 415 COMPUTE_VISIBLE_PROP_BOUNDS_RMI_TAG=54636, 416 WIN_INFO_TAG=87834, 417 REN_INFO_TAG=87836, 418 LIGHT_INFO_TAG=87838, 419 REN_ID_TAG=58794, 420 BOUNDS_TAG=23543 421 }; 422 CheckForAbortRender()423 virtual void CheckForAbortRender() {} CheckForAbortComposite()424 virtual int CheckForAbortComposite() {return 0;} 425 426 //@{ 427 /** 428 * The default is to allow the use of the back buffer for compositing. 429 * If set to false, this will prevent to manager from swapping buffers. 430 * This allows something else (for instance VisibleCellSelection) to 431 * control front/back buffer swapping. 432 */ 433 vtkSetMacro(UseBackBuffer, int); 434 vtkGetMacro(UseBackBuffer, int); 435 vtkBooleanMacro(UseBackBuffer, int); 436 //@} 437 438 //@{ 439 /** 440 * When set the render manager will synchronize the TileViewport and TileScale 441 * properties. This may not be desirable in cases where there's some other 442 * mechanism to set the tile dimensions eg. Tile displays. 443 */ 444 vtkSetMacro(SynchronizeTileProperties, int); 445 vtkGetMacro(SynchronizeTileProperties, int); 446 vtkBooleanMacro(SynchronizeTileProperties, int); 447 //@} 448 449 //@{ 450 /** 451 * INTERNAL METHODS (DON NOT USE). 452 * There are internal methods made public so that they can be called from 453 * callback functions. 454 */ 455 virtual void GenericStartRenderCallback(); 456 virtual void GenericEndRenderCallback(); 457 //@} 458 459 protected: 460 vtkParallelRenderManager(); 461 ~vtkParallelRenderManager() override; 462 463 464 //@{ 465 /** 466 * Add/Remove event handlers for the render window. 467 */ 468 void AddRenderWindowEventHandlers(); 469 void RemoveRenderWindowEventHandlers(); 470 //@} 471 472 vtkRenderWindow *RenderWindow; 473 vtkMultiProcessController *Controller; 474 vtkRendererCollection *Renderers; 475 476 virtual vtkRendererCollection *GetRenderers(); 477 478 int ForceRenderWindowSize; 479 int ForcedRenderWindowSize[2]; 480 481 /** 482 * The "root" node's process id. This is the node which is listening for 483 * and propagating new render events from the RenderWindow. All 484 * processes on the controller must have the same value. This value must 485 * be set before SetRenderWindow method is called. In the constructor or 486 * the SetController methods are good places. By default this is set to 487 * 0. 488 */ 489 int RootProcessId; 490 491 int ObservingRenderWindow; 492 int ObservingAbort; 493 494 unsigned long StartRenderTag; 495 unsigned long EndRenderTag; 496 unsigned long ResetCameraTag; 497 unsigned long ResetCameraClippingRangeTag; 498 unsigned long AbortRenderCheckTag; 499 500 double ImageReductionFactor; 501 double MaxImageReductionFactor; 502 int AutoImageReductionFactor; 503 504 int WriteBackImages; 505 int MagnifyImages; 506 int MagnifyImageMethod; 507 508 int UseRGBA; 509 int SynchronizeTileProperties; 510 int FullImageSize[2]; 511 int ReducedImageSize[2]; 512 513 vtkUnsignedCharArray *FullImage; 514 vtkUnsignedCharArray *ReducedImage; 515 516 int FullImageUpToDate; 517 int ReducedImageUpToDate; 518 int RenderWindowImageUpToDate; 519 520 vtkDoubleArray *Viewports; 521 522 int Lock; 523 int ParallelRendering; 524 int RenderEventPropagation; 525 int UseCompositing; 526 int SyncRenderWindowRenderers; 527 528 vtkTimerLog *Timer; 529 530 double RenderTime; 531 double ImageProcessingTime; 532 533 /** 534 * Used by SetImageReductionFactorForUpdateRate to smooth transitions 535 * transitions between image reduction factors. 536 */ 537 double AverageTimePerPixel; 538 539 /** 540 * Used to synchronize rendering information per frame. 541 * These are old methods provided for backward compatibility. One should look 542 * at using CollectWindowInformation(), ProcessWindowInformation() etc. for 543 * bufferred sending of information over. 544 */ SendWindowInformation()545 virtual void SendWindowInformation() {} ReceiveWindowInformation()546 virtual void ReceiveWindowInformation() {} SendRendererInformation(vtkRenderer *)547 virtual void SendRendererInformation(vtkRenderer *) {} ReceiveRendererInformation(vtkRenderer *)548 virtual void ReceiveRendererInformation(vtkRenderer *) {} 549 550 /** 551 * Subclass should override these methods (instead of 552 * SendWindowInformation/ReceiveWindowInformation or 553 * SendRendererInformation/ReceiveRendererInformation) to collect or process 554 * meta-data to synchronize rendering information per frame. 555 * Subclass should not use the Controller directly to send receive messages 556 * in any of these methods otherwise deadlocks may ensue. 557 */ CollectWindowInformation(vtkMultiProcessStream &)558 virtual void CollectWindowInformation(vtkMultiProcessStream&) {} ProcessWindowInformation(vtkMultiProcessStream &)559 virtual bool ProcessWindowInformation(vtkMultiProcessStream&) 560 { return true; } CollectRendererInformation(vtkRenderer *,vtkMultiProcessStream &)561 virtual void CollectRendererInformation(vtkRenderer*, 562 vtkMultiProcessStream&) {} ProcessRendererInformation(vtkRenderer *,vtkMultiProcessStream &)563 virtual bool ProcessRendererInformation(vtkRenderer*, 564 vtkMultiProcessStream&) { return true; } 565 566 //@{ 567 /** 568 * Here is a good place to handle processing of data before and after 569 * render. 570 */ 571 virtual void PreRenderProcessing() = 0; 572 virtual void PostRenderProcessing() = 0; 573 //@} 574 575 /** 576 * Called in satellites to set the render window size to the current 577 * FullImageSize and ReducedImageSize (or vice versa). 578 */ 579 virtual void SetRenderWindowSize(); 580 581 /** 582 * Called by ComputeVisiblePropBoundsRMI to get the bounds of a local 583 * renderer. Override this method if the true bounds are different than 584 * those reported by the renderer. 585 */ 586 virtual void LocalComputeVisiblePropBounds(vtkRenderer *ren, double bounds[6]); 587 588 /** 589 * When called, fills FullImage. 590 */ 591 virtual void MagnifyReducedImage(); 592 593 /** 594 * Write the full image back to the RenderWindow. 595 */ 596 virtual void WriteFullImage(); 597 598 /** 599 * Reads in the reduced image from the RenderWindow. 600 */ 601 virtual void ReadReducedImage(); 602 603 /** 604 * Returns 1 if the RenderWindow's last image is in the front buffer, 0 605 * if it is in the back. 606 */ 607 virtual int LastRenderInFrontBuffer(); 608 609 /** 610 * Select buffer to read from / render into. 611 */ 612 virtual int ChooseBuffer(); 613 614 /** 615 * Sets the current render window's pixel data. 616 */ 617 virtual void SetRenderWindowPixelData(vtkUnsignedCharArray *pixels, 618 const int pixelDimensions[2]); 619 620 /** 621 * Returns true if the image for the given renderer should be rendered at a 622 * reduced size to be magnified later. This method always returns true, but 623 * subclasses may render some renderers at a reduced size, magnify them, and 624 * then render the other renderers at full resolution. 625 */ ImageReduceRenderer(vtkRenderer *)626 virtual int ImageReduceRenderer(vtkRenderer *) { return 1; } 627 628 struct RenderWindowInfo 629 { 630 int FullSize[2]; 631 int ReducedSize[2]; 632 int NumberOfRenderers; 633 int UseCompositing; 634 int TileScale[2]; 635 double ImageReductionFactor; 636 double DesiredUpdateRate; 637 double TileViewport[4]; 638 639 // Initialize members RenderWindowInfoRenderWindowInfo640 RenderWindowInfo() {} 641 642 // Save/restore the struct to/from a stream. 643 void Save(vtkMultiProcessStream& stream); 644 bool Restore(vtkMultiProcessStream& stream); 645 }; 646 647 struct RendererInfo 648 { 649 int Draw; 650 int NumberOfLights; 651 double Viewport[4]; 652 double CameraPosition[3]; 653 double CameraFocalPoint[3]; 654 double CameraViewUp[3]; 655 double WindowCenter[2]; 656 double CameraClippingRange[2]; 657 double CameraViewAngle; 658 double Background[3]; 659 double Background2[3]; 660 bool GradientBackground; 661 662 double ParallelScale; 663 664 // Initialize members RendererInfoRendererInfo665 RendererInfo() {} 666 667 // Save/restore the struct to/from a stream. 668 void Save(vtkMultiProcessStream& stream); 669 bool Restore(vtkMultiProcessStream& stream); 670 }; 671 672 struct LightInfo 673 { 674 double Position[3]; 675 double FocalPoint[3]; 676 double Type; 677 678 // Initialize members LightInfoLightInfo679 LightInfo() {} 680 681 // Save/restore the struct to/from a stream. 682 void Save(vtkMultiProcessStream& stream); 683 bool Restore(vtkMultiProcessStream& stream); 684 }; 685 686 int AddedRMIs; 687 unsigned long RenderRMIId; 688 unsigned long BoundsRMIId; 689 int UseBackBuffer; 690 691 static bool DefaultRenderEventPropagation; 692 693 private: 694 vtkParallelRenderManager(const vtkParallelRenderManager &) = delete; 695 void operator=(const vtkParallelRenderManager &) = delete; 696 697 }; 698 699 #endif //vtkParalleRenderManager_h 700