fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Cluster / Window / MultiDisplay / OSGMultiDisplayWindow.cpp
blob856488061f841e6fb9539e2c2dbbfdd9dee04652
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include "OSGConfig.h"
46 #include "OSGGL.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"
54 #include "OSGNode.h"
55 #include "OSGClusterNetwork.h"
56 #include "OSGImageComposer.h"
58 #define FAST_SYNC 0
60 OSG_USING_NAMESPACE
62 /*! \class OSG::MultiDisplayWindow
63 * \ingroup GrpSystemCluster
66 /*----------------------- constructors & destructors ----------------------*/
68 /*! Constructor
71 MultiDisplayWindow::MultiDisplayWindow(void) :
72 Inherited()
76 /*! Copy Constructor
79 MultiDisplayWindow::MultiDisplayWindow(const MultiDisplayWindow &source) :
80 Inherited(source)
84 /*! Destructor
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,
104 UInt32 origin,
105 BitVector details )
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 * ,
127 UInt32 )
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,
140 UInt32 id,
141 DrawActionBase *action )
143 TileCameraDecoratorPtr deco;
144 ViewportPtr serverPort;
145 ViewportPtr clientPort;
146 StereoBufferViewportPtr clientStereoPort;
147 UInt32 sv,cv;
148 Int32 l,r,t,b;
149 Int32 cleft,cright,ctop,cbottom;
151 // sync, otherwise viewports will be out of date
153 if(!getHServers())
155 setHServers(getServers().size());
157 if(!getVServers())
159 setVServers(1);
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();
169 if(getWidth()==0)
171 setWidth( width*getHServers() );
173 if(getHeight()==0)
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;
182 Real64 scaleCWidth =
183 ((width - getXOverlap()) * (getHServers() - 1) + width) /
184 (float)getWidth();
185 Real64 scaleCHeight =
186 ((height - getYOverlap())* (getVServers() - 1) + height)/
187 (float)getHeight();
189 bool isVirtualPort = false;
191 // duplicate viewports
192 for(cv = 0, sv = 0; cv < getPort().size(); ++cv)
194 clientPort = getPort()[cv];
196 #if 0
197 isVirtualPort = clientPort->getType().isDerivedFrom(FBOViewport::getClassType());
199 if(isVirtualPort)
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);
210 else
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);
228 else
229 #endif
231 clientStereoPort =
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;
239 if(cright < left ||
240 cleft > right ||
241 ctop < bottom ||
242 cbottom > top )
244 // invisible on this server screen
245 continue;
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)
256 serverPort =
257 dynamic_cast<ViewportPtr>(clientPort->shallowCopy());
259 deco = TileCameraDecorator::create();
261 serverWindow->addPort(serverPort);
263 serverPort->setCamera(deco);
265 else
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
275 serverPort =
276 dynamic_cast<ViewportPtr>(clientPort->shallowCopy());
278 if(deco == NULL)
279 deco = TileCameraDecorator::create();
281 serverPort->setCamera(deco);
283 serverWindow->replacePort(sv, serverPort);
287 // update changed viewport fields
288 updateViewport(serverPort,clientPort);
290 // set viewport size
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() );
315 sv++;
318 // remove unused ports
319 while(serverWindow->getPort().size()>sv)
321 serverWindow->subPort(sv);
324 Inherited::serverRender(serverWindow,id,action);
326 #endif
328 void MultiDisplayWindow::serverRender(Window *window,
329 UInt32 id,
330 RenderActionBase *action)
332 TileCameraDecoratorUnrecPtr deco;
333 ViewportUnrecPtr serverPort;
334 Viewport * clientPort;
335 UInt32 sv,cv;
336 Int32 l,r,t,b;
337 Int32 cleft,cright,ctop,cbottom;
339 if(!getHServers())
341 setHServers(getMFServers()->size32());
343 if(!getVServers())
345 setVServers(1);
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();
355 if(getWidth()==0)
357 setWidth( width*getHServers() );
359 if(getHeight()==0)
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;
368 Real64 scaleCWidth =
369 ((width - getXOverlap()) * (getHServers() - 1) + width) /
370 float(getWidth());
371 Real64 scaleCHeight =
372 ((height - getYOverlap())* (getVServers() - 1) + height)/
373 float(getHeight());
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;
385 if(cright < left ||
386 cleft > right ||
387 ctop < bottom ||
388 cbottom > top )
390 // invisible on this server screen
391 continue;
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);
411 else
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
421 serverPort =
422 dynamic_pointer_cast<Viewport>(clientPort->shallowCopy());
424 window->replacePort(sv,
425 serverPort);//[sv] = serverPort;
426 serverPort->setCamera(deco);
428 else
430 deco = dynamic_cast<TileCameraDecorator *>(
431 serverPort->getCamera());
435 // update changed viewport fields
436 updateViewport(serverPort, clientPort);
438 // set viewport size
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() );
463 sv++;
466 // remove unused ports
467 while(window->getMFPort()->size()>sv)
469 window->subPort(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
483 UInt8 pixel[3];
484 glReadPixels(0,0,
485 1,1,
486 GL_RGB,GL_UNSIGNED_BYTE,
487 pixel);
488 glFinish();
490 #if !FAST_SYNC
491 connection=getNetwork()->getMainConnection();
492 if(!getInterleave())
494 // tell client that we are finish
495 connection->signal();
496 // wait for swap
497 connection->wait();
499 #endif
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;
515 Viewport *vp, *cvp;
517 if(getManageClientViewports() == false ||
518 getClientWindow () == NULL)
520 return;
523 // check if something changed
524 if(getMFPort()->size() == getClientWindow()->getMFPort()->size())
526 for(UInt32 v = 0 ; v < getMFPort()->size() && !bChanged ; v++)
528 vp = getPort(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() )
541 bChanged = true;
545 else
547 bChanged = true;
550 if(bChanged)
552 // remove all viewports
553 #if 0
554 while(getClientWindow()->getMFPort()-size())
556 vp = getClientWindow()->getPort(0);
558 getClientWindow()->subPort(0U);
560 #endif
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();
581 #if FAST_SYNC
582 connection->selectChannel();
583 #else
584 if(!getInterleave())
586 // wait for all servers to finish
587 connection->wait();
588 // initiate swap
589 connection->signal();
591 #endif
593 // show client window
594 Inherited::clientSwap();
597 /*-------------------------------------------------------------------------*/
598 /* helper */
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)
609 return;
611 if(serverPort == NULL || clientPort == NULL)
612 return;
614 if(serverPort->getType() != serverPort->getType())
615 return;
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)
631 continue;
634 BitVector mask = fdesc->getFieldMask();
636 mask &= serverPort->getFieldFlags()->_bClusterLocalFlags;
638 if(!mask)
639 continue;
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)
655 continue;
657 if(cdst_field == NULL || src_field == NULL)
658 continue;
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);
669 else
671 if(src_field->equal(cdst_field) == false)
673 EditFieldHandlePtr dst_field = serverPort->editField(i);
675 dst_field->copyValues(src_field);