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 //---------------------------------------------------------------------------
46 #define GL_GLEXT_PROTOTYPES 1
48 #include "OSGConfig.h"
49 #include "OSGConnection.h"
52 #include "OSGPipelineComposer.h"
56 /***************************************************************************\
58 \***************************************************************************/
60 /*! \class OSG::PipelineComposer
64 /***************************************************************************\
66 \***************************************************************************/
68 /***************************************************************************\
70 \***************************************************************************/
72 void PipelineComposer::initMethod(InitPhase ePhase
)
77 /***************************************************************************\
79 \***************************************************************************/
81 /*-------------------------------------------------------------------------*\
83 \*-------------------------------------------------------------------------*/
85 /*----------------------- constructors & destructors ----------------------*/
87 PipelineComposer::PipelineComposer(void) :
93 _readTilePtr (&_tileA
),
94 _composeTilePtr (&_tileB
),
104 _colorFormat (GL_NONE
),
105 _colorType (GL_NONE
),
106 _depthType (GL_NONE
),
113 _composeBarrier (NULL
),
114 _frameEndBarrier(NULL
),
118 _occlusionQuery (0 ),
123 PipelineComposer::PipelineComposer(const PipelineComposer
&source
) :
125 _tileBufferSize (0 ),
129 _readTilePtr (&_tileA
),
130 _composeTilePtr (&_tileB
),
140 _colorFormat (GL_NONE
),
141 _colorType (GL_NONE
),
142 _depthType (GL_NONE
),
149 _composeBarrier (NULL
),
150 _frameEndBarrier(NULL
),
154 _occlusionQuery (0 ),
159 PipelineComposer::~PipelineComposer(void)
163 /*----------------------------- class specific ----------------------------*/
165 void PipelineComposer::changed(ConstFieldMaskArg whichField
,
169 Inherited::changed(whichField
, origin
, details
);
172 void PipelineComposer::dump( UInt32
,
173 const BitVector
) const
175 SLOG
<< "Dump PipelineComposer NI" << std::endl
;
178 /*----------------------------- composition -------------------------------*/
180 void PipelineComposer::open()
184 // create server cross connection
185 _clusterWindow
->getNetwork()->connectAllGroupToPoint(clusterId(),
187 // do not buffer any data
188 for(UInt32 i
=0 ; i
<= serverCount() ; ++i
)
189 clusterWindow()->getNetwork()->getConnection(i
)->forceDirectIO();
193 _lock
= Lock::get("PipelineComposer", false);
195 _barrier
= Barrier::get("PipelineComposer", false);
196 _frameEndBarrier
= Barrier::get("PipelineComposerFrameEnd", false);
197 // create writer thread
198 _writer
= BaseThread::get("PipelineComposer", false);
199 // start writer thread
200 _writer
->runFunction( writeProc
, this );
202 if(!_isClient
&& getPipelined())
204 _composeBarrier
= Barrier::get("PipelineComposerCompose", false);
205 // _composer = BaseThread::get("PipelineComposerCompose");
206 _composer
= dynamic_pointer_cast
<Thread
>(
207 ThreadManager::the()->getThread(NULL
, false));
209 _composer
->runFunction( composeProc
,0, this );
212 #ifdef USE_NV_OCCLUSION
213 glGenOcclusionQueriesNV(1, &_occlusionQuery
);
217 void PipelineComposer::startViewport(Viewport
*)
223 _composeBarrier
->enter(2);
227 // transfer tile size
228 _composeTilesX
= _readTilesX
;
229 _composeTilesY
= _readTilesY
;
234 void PipelineComposer::composeViewport(Viewport
*port
)
238 pl
=port
->calcPixelLeft(),
239 pr
=port
->calcPixelRight(),
240 pb
=port
->calcPixelBottom(),
241 pt
=port
->calcPixelTop();
242 GLint pw
=pr
-pl
+1,ph
=pt
-pb
+1;
243 bool full
= port
->calcIsFullWindow();
244 glViewport(pl
, pb
, pw
, ph
);
245 glScissor(pl
, pb
, pw
, ph
);
247 glEnable(GL_SCISSOR_TEST
);
249 GLboolean depth
= glIsEnabled(GL_DEPTH_TEST
);
250 GLboolean blend
= glIsEnabled(GL_BLEND
);
252 // glDisable(GL_DEPTH_TEST);
255 glMatrixMode(GL_PROJECTION
);
258 glOrtho(0, port
->calcPixelWidth(),
259 0, port
->calcPixelHeight(),-1,1);
263 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
266 // only one buffer for the client
268 _composeTilePtr
= _readTilePtr
;
270 _readTilesX
= (port
->calcPixelWidth() - 1) / getTileSize() + 1;
271 _readTilesY
= (port
->calcPixelHeight() - 1) / getTileSize() + 1;
273 _tileBufferSize
= getTileSize()*getTileSize()*8+sizeof(TileBuffer
);
274 _workingTile
.resize(_tileBufferSize
);
277 _readTilePtr
->resize(_tileBufferSize
* _readTilesX
* _readTilesY
);
281 while(_groupInfo
.size() < serverCount())
283 _groupInfoPool
.push_back(GroupInfo());
284 _groupInfo
.push_back(&(*_groupInfoPool
.rbegin()));
286 _groupInfo
.resize(serverCount());
289 _statistics
.bytesIn
= 0;
290 _statistics
.bytesOut
= 0;
291 _statistics
.occluded
= 0;
292 _statistics
.noDepth
= 0;
293 _statistics
.noGeo
= 0;
294 _statistics
.clipped
= 0;
298 _composeTilesX
= _readTilesX
;
299 _composeTilesY
= _readTilesY
;
304 // UInt16 depthDummy;
306 // _depthType = GL_UNSIGNED_SHORT;
307 _depthType
= GL_UNSIGNED_INT
;
308 _colorFormat
= GL_RGB
;
309 _colorType
= GL_UNSIGNED_SHORT_5_6_5
;
311 readBuffer(depthDummy
,colorDummy
,port
);
312 if(!getPipelined() || isClient())
313 composeBuffer(depthDummy
,colorDummy
);
321 _depthType
= GL_UNSIGNED_INT
;
322 _colorFormat
= GL_RGBA
;
323 _colorType
= GL_UNSIGNED_BYTE
;
324 readBuffer(depthDummy
,colorDummy
,port
);
325 if(!getPipelined() || isClient())
326 composeBuffer(depthDummy
,colorDummy
);
332 _depthType
= GL_UNSIGNED_INT
;
333 _colorFormat
= GL_RGB
;
334 _colorType
= GL_UNSIGNED_BYTE
;
335 readBuffer(depthDummy
,colorDummy
,port
);
336 if(!getPipelined() || isClient())
337 composeBuffer(depthDummy
,colorDummy
);
345 double pixelReadTime
= 0;
347 UInt32 maxIn
= _statistics
.bytesIn
;
348 UInt32 maxOut
= _statistics
.bytesOut
;
349 UInt32 maxIO
= maxIn
+ maxOut
;
350 UInt32 sumOut
= _statistics
.bytesOut
;
352 Connection::Channel channel
;
353 GroupConnection
*server
;
354 Statistics statistics
;
355 server
= clusterWindow()->getNetwork()->getMainGroupConnection();
356 for(UInt32 i
=0 ; i
<serverCount() ;++i
)
358 channel
= server
->selectChannel();
359 server
->subSelection(channel
);
360 server
->get(&statistics
,sizeof(Statistics
));
361 sumOut
+= statistics
.bytesOut
;
362 if(statistics
.pixelReadTime
> pixelReadTime
) {
363 pixelReadTime
= statistics
.pixelReadTime
;
364 sortTime
= statistics
.sortTime
;
366 if(statistics
.bytesOut
> maxOut
)
367 maxOut
= statistics
.bytesOut
;
368 if(statistics
.bytesIn
> maxIn
)
369 maxIn
= statistics
.bytesIn
;
370 if(statistics
.bytesIn
+ statistics
.bytesOut
> maxIO
)
371 maxIO
= statistics
.bytesIn
+ statistics
.bytesOut
;
372 clipped
+= statistics
.clipped
;
374 server
->resetSelection();
375 printf("pixel read time : %1.5lf\n",pixelReadTime
);
376 printf("sort Time : %1.5lf\n",sortTime
);
377 printf("compose Time : %1.5lf\n",_statistics
.composeTime
);
378 printf("Transfered bytes : %10d\n",sumOut
);
379 printf("Max out : %10d\n",maxOut
);
380 printf("Max in : %10d\n",maxIn
);
381 printf("Max io : %10d\n",maxIO
);
382 printf("occluded : %10d\n",_statistics
.occluded
);
383 printf("Layerd : %10d\n",_statistics
.noDepth
);
384 printf("Empty : %10d\n",_statistics
.noGeo
-clipped
);
385 printf("Clipped : %10d\n",clipped
);
386 printf("DepthAndColor : %10d\n",serverCount()*_composeTilesX
*_composeTilesY
-
387 _statistics
.occluded
-
393 Connection
*client
= clusterWindow()->getNetwork()->getMainConnection();
394 client
->put(&_statistics
,sizeof(Statistics
));
400 glMatrixMode(GL_MODELVIEW
);
402 glEnable(GL_DEPTH_TEST
);
405 if(depth
&& !glIsEnabled(GL_DEPTH_TEST
))
406 glEnable(GL_DEPTH_TEST
);
407 if(!blend
&& glIsEnabled(GL_BLEND
))
411 void PipelineComposer::close(void)
413 if(!isClient() && _writer
)
416 _queue
.push_back(NULL
);
426 BaseThread::join(_writer
);
431 _composeBarrier
= NULL
;
432 _frameEndBarrier
= NULL
;
437 /*----------------------------- features ---------------------------------*/
441 bool PipelineComposer::getClientRendering()
446 /*----------------------------- helper ------------------------------------*/
448 PipelineComposer::TileBuffer
*PipelineComposer::getComposeTileBuffer(UInt32 x
,UInt32 y
)
450 return reinterpret_cast<TileBuffer
*>(&(*_composeTilePtr
)[(y
*_composeTilesX
+ x
)*_tileBufferSize
]);
453 PipelineComposer::TileBuffer
*PipelineComposer::getReadTileBuffer(UInt32 x
,UInt32 y
)
455 return reinterpret_cast<TileBuffer
*>(&(*_readTilePtr
)[(y
*_readTilesX
+ x
)*_tileBufferSize
]);
458 PipelineComposer::TileBuffer
*PipelineComposer::getWorkingTileBuffer(void)
460 return reinterpret_cast<TileBuffer
*>(&_workingTile
[0]);
463 /*! Depth order for pipe sort
465 bool PipelineComposer::GroupInfoOrder::operator()
466 (const GroupInfo
*a
, const GroupInfo
*b
)
468 if( a
->depth
.max
> b
->depth
.max
||
469 ( a
->depth
.max
== b
->depth
.max
&&
476 UInt32
PipelineComposer::compressTransInfo(std::vector
<TransInfo
> &transInfo
)
478 TransInfo
*src
= &transInfo
[0];
479 TransInfo
*srcEnd
= src
+ _composeTilesX
*_composeTilesY
*serverCount();
480 TransInfo
*dst
= &transInfo
[0];
481 TransInfo
*empty
= NULL
;
482 while(src
!= srcEnd
) {
490 if(empty
->sendTo
== 0) {
504 // printf("Compress %f\n",(dst - &transInfo[0])*100.0/transInfo.size());
505 return dst
- &transInfo
[0];
508 void PipelineComposer::uncompressTransInfo(std::vector
<TransInfo
> &transInfo
,UInt32 infoCount
)
510 transInfo
.resize(_composeTilesX
*_composeTilesY
*serverCount());
512 TransInfo
*src
= &transInfo
[infoCount
-1];
513 TransInfo
*srcEnd
= &transInfo
[0] - 1;
514 TransInfo
*dst
= &transInfo
[_composeTilesX
*_composeTilesY
*serverCount()-1];
515 while(src
!= srcEnd
) {
530 /*----------------------------- thread proc -------------------------------*/
532 void PipelineComposer::writeProc(void *arg
)
534 PipelineComposer
*the
=static_cast<PipelineComposer
*>(arg
);
539 the
->writeResult(depthDummy
,colorDummy
);
547 the
->writeResult(depthDummy
,colorDummy
);
553 the
->writeResult(depthDummy
,colorDummy
);
558 void PipelineComposer::composeProc(void *arg
)
560 PipelineComposer
*the
=static_cast<PipelineComposer
*>(arg
);
562 // TODO stop compose thread
569 the
->composeBuffer(depthDummy
,colorDummy
);
577 the
->composeBuffer(depthDummy
,colorDummy
);
583 the
->composeBuffer(depthDummy
,colorDummy
);