1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
45 #include "OSGConfig.h"
47 #include "OSGViewport.h"
48 #include "OSGTileCameraDecorator.h"
49 #include "OSGBaseFunctions.h"
50 #include "OSGStereoBufferViewport.h"
51 #include "OSGFieldContainerFields.h"
52 #include "OSGMultiDisplayWindow.h"
53 #include "OSGConnection.h"
55 #include "OSGClusterNetwork.h"
56 #include "OSGImageComposer.h"
62 /*! \class OSG::MultiDisplayWindow
63 * \ingroup GrpSystemCluster
66 /*----------------------- constructors & destructors ----------------------*/
71 MultiDisplayWindow::MultiDisplayWindow(void) :
79 MultiDisplayWindow::MultiDisplayWindow(const MultiDisplayWindow
&source
) :
87 MultiDisplayWindow::~MultiDisplayWindow(void)
91 /*----------------------------- class specific ----------------------------*/
93 /*! initialize the static features of the class, e.g. action callbacks
95 void MultiDisplayWindow::initMethod(InitPhase ePhase
)
97 Inherited::initMethod(ePhase
);
100 /*! react to field changes
103 void MultiDisplayWindow::changed(ConstFieldMaskArg whichField
,
107 Inherited::changed(whichField
, origin
, details
);
110 /*! output the instance for debug purposes
113 void MultiDisplayWindow::dump( UInt32
,
114 const BitVector
) const
116 SLOG
<< "hServers:" << getHServers() << " "
117 << "vServers:" << getVServers() << std::endl
;
120 /*----------------------------- server methods ----------------------------*/
122 /*! initialise the cluster window on the server side. This method is
123 called after the first sync.
126 void MultiDisplayWindow::serverInit(Window
* ,
131 #ifdef OSG_OLD_RENDER_ACTION
132 /*! render server window
134 * update all viewport parameters and render local viewports
135 * Width and height of the whole window are calculated by
136 * multiplieing the local window size by hServers and vServers.
139 void MultiDisplayWindow::serverRender(WindowPtr serverWindow
,
141 DrawActionBase
*action
)
143 TileCameraDecoratorPtr deco
;
144 ViewportPtr serverPort
;
145 ViewportPtr clientPort
;
146 StereoBufferViewportPtr clientStereoPort
;
149 Int32 cleft
,cright
,ctop
,cbottom
;
151 // sync, otherwise viewports will be out of date
155 setHServers(getServers().size());
162 UInt32 row
=id
/getHServers();
163 UInt32 column
=id
%getHServers();
165 // calculate width and height from local width and height
166 UInt32 width
= serverWindow
->getWidth() ;
167 UInt32 height
= serverWindow
->getHeight();
171 setWidth( width
*getHServers() );
175 setHeight( height
*getVServers() );
178 Int32 left
= column
* width
- column
* getXOverlap();
179 Int32 bottom
= row
* height
- row
* getYOverlap();
180 Int32 right
= left
+ width
- 1;
181 Int32 top
= bottom
+ height
- 1;
183 ((width
- getXOverlap()) * (getHServers() - 1) + width
) /
185 Real64 scaleCHeight
=
186 ((height
- getYOverlap())* (getVServers() - 1) + height
)/
189 bool isVirtualPort
= false;
191 // duplicate viewports
192 for(cv
= 0, sv
= 0; cv
< getPort().size(); ++cv
)
194 clientPort
= getPort()[cv
];
197 isVirtualPort
= clientPort
->getType().isDerivedFrom(FBOViewport::getClassType());
201 // TODO -- seems wrong to render this on all servers, though rendering
202 // then transmitting the texture doesn't seem like a good idea either.
203 if(serverWindow
->getPort().size() <= sv
)
205 serverPort
= ViewportPtr::dcast(clientPort
->shallowCopy());
206 beginEditCP(serverWindow
);
207 serverWindow
->addPort(serverPort
);
208 endEditCP(serverWindow
);
212 serverPort
= serverWindow
->getPort()[sv
];
213 if(serverPort
->getType() != clientPort
->getType())
215 // there is a viewport with the wrong type
216 subRefCP(serverWindow
->getPort()[sv
]);
217 serverPort
= ViewportPtr::dcast(clientPort
->shallowCopy());
218 beginEditCP(serverWindow
);
220 serverWindow
->getPort()[sv
] = serverPort
;
222 endEditCP(serverWindow
);
225 // update changed viewport fields
226 updateViewport(serverPort
,clientPort
);
232 dynamic_cast<StereoBufferViewportPtr
>(clientPort
);
234 cleft
= (Int32
)(clientPort
->getPixelLeft() * scaleCWidth
) ;
235 cbottom
= (Int32
)(clientPort
->getPixelBottom() * scaleCHeight
) ;
236 cright
= (Int32
)((clientPort
->getPixelRight()+1) * scaleCWidth
) -1;
237 ctop
= (Int32
)((clientPort
->getPixelTop()+1) * scaleCHeight
)-1;
244 // invisible on this server screen
248 // calculate overlapping viewport
249 l
= osgMax(cleft
,left
) - left
;
250 b
= osgMax(cbottom
,bottom
) - bottom
;
251 r
= osgMin(cright
,right
) - left
;
252 t
= osgMin(ctop
,top
) - bottom
;
254 if(serverWindow
->getPort().size() <= sv
)
257 dynamic_cast<ViewportPtr
>(clientPort
->shallowCopy());
259 deco
= TileCameraDecorator::create();
261 serverWindow
->addPort(serverPort
);
263 serverPort
->setCamera(deco
);
267 serverPort
= serverWindow
->getPort()[sv
];
269 deco
= dynamic_cast<TileCameraDecoratorPtr
>(
270 serverPort
->getCamera());
272 if(serverPort
->getType() != clientPort
->getType())
274 // there is a viewport with the wrong type
276 dynamic_cast<ViewportPtr
>(clientPort
->shallowCopy());
279 deco
= TileCameraDecorator::create();
281 serverPort
->setCamera(deco
);
283 serverWindow
->replacePort(sv
, serverPort
);
287 // update changed viewport fields
288 updateViewport(serverPort
,clientPort
);
291 serverPort
->setSize(Real32(l
),Real32(b
),Real32(r
),Real32(t
));
293 // use pixel even if pixel = 1
294 if(serverPort
->getLeft() == 1.0)
295 serverPort
->setLeft(1.0001);
297 if(serverPort
->getRight() == 1.0)
298 serverPort
->setRight(1.0001);
300 if(serverPort
->getTop() == 1.0)
301 serverPort
->setTop(1.0001);
303 if(serverPort
->getBottom() == 1.0)
304 serverPort
->setBottom(1.0001);
306 // calculate tile parameters
307 deco
->setFullWidth ( cright
-cleft
);
308 deco
->setFullHeight( ctop
-cbottom
);
309 deco
->setSize( ( l
+left
-cleft
) / (float)( cright
-cleft
),
310 ( b
+bottom
-cbottom
) / (float)( ctop
-cbottom
),
311 ( r
+left
-cleft
) / (float)( cright
-cleft
),
312 ( t
+bottom
-cbottom
) / (float)( ctop
-cbottom
) );
313 deco
->setDecoratee( clientPort
->getCamera() );
318 // remove unused ports
319 while(serverWindow
->getPort().size()>sv
)
321 serverWindow
->subPort(sv
);
324 Inherited::serverRender(serverWindow
,id
,action
);
328 void MultiDisplayWindow::serverRender(Window
*window
,
330 RenderActionBase
*action
)
332 TileCameraDecoratorUnrecPtr deco
;
333 ViewportUnrecPtr serverPort
;
334 Viewport
* clientPort
;
337 Int32 cleft
,cright
,ctop
,cbottom
;
341 setHServers(getMFServers()->size32());
348 UInt32 row
=id
/getHServers();
349 UInt32 column
=id
%getHServers();
351 // calculate width and height from local width and height
352 UInt32 width
= window
->getWidth() ;
353 UInt32 height
= window
->getHeight();
357 setWidth( width
*getHServers() );
361 setHeight( height
*getVServers() );
364 Int32 left
= column
* width
- column
* getXOverlap();
365 Int32 bottom
= row
* height
- row
* getYOverlap();
366 Int32 right
= left
+ width
- 1;
367 Int32 top
= bottom
+ height
- 1;
369 ((width
- getXOverlap()) * (getHServers() - 1) + width
) /
371 Real64 scaleCHeight
=
372 ((height
- getYOverlap())* (getVServers() - 1) + height
)/
375 // duplicate viewports
376 for(cv
=0,sv
=0;cv
<getMFPort()->size();cv
++)
378 clientPort
= getPort(cv
);
380 cleft
= Int32(clientPort
->calcPixelLeft() * scaleCWidth
) ;
381 cbottom
= Int32(clientPort
->calcPixelBottom() * scaleCHeight
) ;
382 cright
= Int32((clientPort
->calcPixelRight()+1) * scaleCWidth
) -1;
383 ctop
= Int32((clientPort
->calcPixelTop()+1) * scaleCHeight
)-1;
390 // invisible on this server screen
394 // calculate overlapping viewport
395 l
= osgMax(cleft
,left
) - left
;
396 b
= osgMax(cbottom
,bottom
) - bottom
;
397 r
= osgMin(cright
,right
) - left
;
398 t
= osgMin(ctop
,top
) - bottom
;
400 if(window
->getMFPort()->size() <= sv
)
402 serverPort
= dynamic_pointer_cast
<Viewport
>(
403 clientPort
->shallowCopy());
405 deco
= TileCameraDecorator::create();
407 window
->addPort(serverPort
);
409 serverPort
->setCamera(deco
);
413 serverPort
= window
->getPort(sv
);
415 deco
= dynamic_cast<TileCameraDecorator
*>(
416 serverPort
->getCamera());
418 if(window
->getPort(sv
)->getType() != clientPort
->getType())
420 // there is a viewport with the wrong type
422 dynamic_pointer_cast
<Viewport
>(clientPort
->shallowCopy());
424 window
->replacePort(sv
,
425 serverPort
);//[sv] = serverPort;
426 serverPort
->setCamera(deco
);
430 deco
= dynamic_cast<TileCameraDecorator
*>(
431 serverPort
->getCamera());
435 // update changed viewport fields
436 updateViewport(serverPort
, clientPort
);
439 serverPort
->setSize(Real32(l
),Real32(b
),Real32(r
),Real32(t
));
441 // use pixel even if pixel = 1
442 if(serverPort
->getLeft() == 1.0)
443 serverPort
->setLeft(1.0001f
);
445 if(serverPort
->getRight() == 1.0)
446 serverPort
->setRight(1.0001f
);
448 if(serverPort
->getTop() == 1.0)
449 serverPort
->setTop(1.0001f
);
451 if(serverPort
->getBottom() == 1.0)
452 serverPort
->setBottom(1.0001f
);
454 // calculate tile parameters
455 deco
->setFullWidth ( cright
-cleft
);
456 deco
->setFullHeight( ctop
-cbottom
);
457 deco
->setSize( ( l
+left
-cleft
) / float( cright
-cleft
),
458 ( b
+bottom
-cbottom
) / float( ctop
-cbottom
),
459 ( r
+left
-cleft
) / float( cright
-cleft
),
460 ( t
+bottom
-cbottom
) / float( ctop
-cbottom
) );
461 deco
->setDecoratee( clientPort
->getCamera() );
466 // remove unused ports
467 while(window
->getMFPort()->size()>sv
)
472 Inherited::serverRender(window
,id
,action
);
475 /*! swap server window
478 void MultiDisplayWindow::serverSwap(Window
*window
, UInt32 id
)
480 Connection
*connection
;
482 // clear command buffers
486 GL_RGB
,GL_UNSIGNED_BYTE
,
491 connection
=getNetwork()->getMainConnection();
494 // tell client that we are finish
495 connection
->signal();
501 Inherited::serverSwap(window
,id
);
504 /*----------------------------- client methods ----------------------------*/
506 /*! init client window
508 * If manageClientViewports is set, then all viewports from the
509 * cluster window are duplcated to the client window.
512 void MultiDisplayWindow::clientInit(void)
514 bool bChanged
= false;
517 if(getManageClientViewports() == false ||
518 getClientWindow () == NULL
)
523 // check if something changed
524 if(getMFPort()->size() == getClientWindow()->getMFPort()->size())
526 for(UInt32 v
= 0 ; v
< getMFPort()->size() && !bChanged
; v
++)
530 cvp
= getClientWindow()->getPort(v
);
532 if( vp
->getRoot() != cvp
->getRoot() ||
533 vp
->getLeft() != cvp
->getLeft() ||
534 vp
->getRight() != cvp
->getRight() ||
535 vp
->getBottom() != cvp
->getBottom() ||
536 vp
->getTop() != cvp
->getTop() ||
537 vp
->getBackground() != cvp
->getBackground() ||
538 vp
->getMFForegrounds()->size() !=
539 cvp
->getMFForegrounds()->size() )
552 // remove all viewports
554 while(getClientWindow()->getMFPort()-size())
556 vp
= getClientWindow()->getPort(0);
558 getClientWindow()->subPort(0U);
562 getClientWindow()->clearPorts();
564 // duplicate viewports
565 for(UInt32 v
=0 ; v
<getMFPort()->size() ;v
++)
567 ViewportUnrecPtr pTmpPort
=
568 dynamic_pointer_cast
<Viewport
>(getPort(v
)->shallowCopy());
570 getClientWindow()->addPort(pTmpPort
);
575 /*! render client window
577 void MultiDisplayWindow::clientSwap( void )
579 Connection
*connection
= getNetwork()->getMainConnection();
582 connection
->selectChannel();
586 // wait for all servers to finish
589 connection
->signal();
593 // show client window
594 Inherited::clientSwap();
597 /*-------------------------------------------------------------------------*/
600 /*! update all changed viewport field from the client port
603 void MultiDisplayWindow::updateViewport(Viewport
*serverPort
,
604 Viewport
*clientPort
)
607 // Compare the pointers.
608 if(serverPort
== clientPort
)
611 if(serverPort
== NULL
|| clientPort
== NULL
)
614 if(serverPort
->getType() != serverPort
->getType())
617 const FieldContainerType
&type
= serverPort
->getType();
619 UInt32 fcount
= osgMin(serverPort
->getType().getNumFieldDescs(),
620 clientPort
->getType().getNumFieldDescs());
622 for(UInt32 i
= 1;i
<= fcount
; ++i
)
624 const FieldDescriptionBase
*fdesc
= type
.getFieldDesc(i
);
626 // ignore attachments
627 if(strcmp(fdesc
->getCName(), "parent" ) == 0 ||
628 strcmp(fdesc
->getCName(), "camera" ) == 0 ||
629 strcmp(fdesc
->getCName(), "attachments") == 0)
634 BitVector mask
= fdesc
->getFieldMask();
636 mask
&= serverPort
->getFieldFlags()->_bClusterLocalFlags
;
641 const FieldDescriptionBase
*dst_desc
=
642 serverPort
->getType().getFieldDesc(i
);
644 const FieldDescriptionBase
*src_desc
=
645 clientPort
->getType().getFieldDesc(i
);
648 GetFieldHandlePtr cdst_field
= serverPort
->getField(i
);
649 GetFieldHandlePtr src_field
= clientPort
->getField(i
);
651 const FieldType
&dst_ftype
= dst_desc
->getFieldType();
652 const FieldType
&src_ftype
= src_desc
->getFieldType();
654 if(dst_ftype
!= src_ftype
)
657 if(cdst_field
== NULL
|| src_field
== NULL
)
660 if(src_field
->isPointerField() == true)
662 if(src_field
->equal(cdst_field
) == false)
664 EditFieldHandlePtr dst_field
= serverPort
->editField(i
);
666 dst_field
->shareValues(src_field
);
671 if(src_field
->equal(cdst_field
) == false)
673 EditFieldHandlePtr dst_field
= serverPort
->editField(i
);
675 dst_field
->copyValues(src_field
);