1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
7 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
13 * This library is free software; you can redistribute it and/or modify it *
14 * under the terms of the GNU Library General Public License as published *
15 * by the Free Software Foundation, version 2. *
17 * This library is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * Library General Public License for more details. *
22 * You should have received a copy of the GNU Library General Public *
23 * License along with this library; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
35 \*---------------------------------------------------------------------------*/
37 //---------------------------------------------------------------------------
39 //---------------------------------------------------------------------------
46 template<class DepthT,class ColorT>
47 UInt32 PipelineComposer::getMinMaxOcclude(DepthT &depth,
54 DepthInfo *first = result;
55 DepthInfo *reuseEmpty=NULL;
59 for(y = 0; y < _composeTilesY ; ++y)
61 for(x = 0; x < _composeTilesX ; ++x)
63 tile = getComposeTileBuffer(x,y);
65 if(tile->depth.min == DepthT(-1) &&
66 tile->depth.max == DepthT(-1)) {
71 reuseEmpty->min = DepthT(-1);
76 *result = tile->depth;
83 // printf("compr %f\n",count*100.0/(_composeTilesX*_composeTilesY));
89 template<class DepthT,class ColorT>
90 void PipelineComposer::setTransInfo(DepthT &depth,ColorT &color)
93 Connection *client,*readCon;
94 std::vector<DepthInfo> depthInfo;
96 std::vector<TransInfo> transInfo;
97 std::vector<TransInfo> transInfoDummy;
100 transInfo.resize(_composeTilesX * _composeTilesY * serverCount());
101 depthInfo.resize(_composeTilesX * _composeTilesY + 1);
102 count = getMinMaxOcclude(depth,color,&depthInfo[0]);
104 _statistics.sortTime = -getSystemTime();
107 client = clusterWindow()->getNetwork()->getMainConnection();
109 client->put(&depthInfo[0],sizeof(DepthInfo)*count);
110 _statistics.bytesOut += sizeof(DepthInfo)*count;
113 // read transmit info
114 readCon = clusterWindow()->getNetwork()->getMainConnection();
115 readCon->selectChannel();
118 readCon->getValue(infoCount);
119 readCon->get(&transInfo[0],sizeof(TransInfo)*infoCount);
120 _statistics.bytesIn += sizeof(TransInfo)*infoCount +sizeof(UInt32);
121 uncompressTransInfo(transInfo,infoCount);
122 for(y = 0; y < _composeTilesY ; ++y)
124 for(x = 0; x < _composeTilesX ; ++x)
126 tile = getComposeTileBuffer(x,y);
127 tile->trans = transInfo[x + y*_composeTilesX +
128 clusterId()*_composeTilesX*_composeTilesY];
130 if(tile->trans.empty)
135 clusterWindow()->getNetwork()->getMainConnection()->signal();
136 clusterWindow()->getNetwork()->getMainConnection()->wait();
138 _statistics.sortTime += getSystemTime();
141 template<class DepthT,class ColorT>
142 void PipelineComposer::calculateTransInfo(DepthT &depth,ColorT &color)
144 Connection::Channel channel;
146 GroupConnection *servers;
147 UInt32 count = serverCount();
150 GroupInfo *nextGroup;
151 std::vector<DepthInfo> depthInfo;
152 std::vector<TransInfo> transInfo;
153 std::vector<DepthInfo> depthInfoTmp;
156 depthInfo.resize(_composeTilesX * _composeTilesY * count);
157 depthInfoTmp.resize(_composeTilesX * _composeTilesY);
158 transInfo.resize(_composeTilesX * _composeTilesY * count);
160 double tr=-getSystemTime();
162 // read all min max values
163 servers = clusterWindow()->getNetwork()->getMainGroupConnection();
164 while(servers->getSelectionCount())
166 DepthInfo depthCount;
167 channel = servers->selectChannel();
168 servers->get(&depthCount,sizeof(DepthInfo));
169 servers->get(&depthInfoTmp[0],sizeof(DepthInfo)*depthCount.min);
170 DepthInfo *src = &depthInfoTmp[0];
171 DepthInfo *dst = &depthInfo[_composeTilesX * _composeTilesY * channel];
172 for(c=0; c<depthCount.min ; ++c) {
173 if(src->min == DepthT(-1)) {
175 dst->min = DepthT(-1);
176 dst->max = DepthT(-1);
177 dst->occlude = false;
186 _statistics.bytesIn += sizeof(DepthInfo)*(depthCount.min+1);
187 servers->subSelection(channel);
189 servers->resetSelection();
190 tr += getSystemTime();
192 double t=-getSystemTime();
195 for(y = 0; y < _composeTilesY ; ++y)
197 for(x = 0; x < _composeTilesX ; ++x)
199 for(id = 0 ; id < Int32(count) ; ++id)
201 _groupInfo[id]->id = id;
202 _groupInfo[id]->depth =
203 depthInfo[x+_composeTilesX*y + _composeTilesX*_composeTilesY*id];
205 if(_groupInfo[id]->depth.min == DepthT(-1))
209 for(UInt32 id1 = 0 ; id1 < count ; ++id1)
211 if(_groupInfo[id1]->depth.occlude) {
212 for(UInt32 id2 = 0 ; id2 < count ; ++id2) {
214 _groupInfo[id1]->depth.max <
215 _groupInfo[id2]->depth.min &&
216 _groupInfo[id2]->depth.min != DepthT(-1))
218 _groupInfo[id2]->depth.max = DepthT(-1);
219 _groupInfo[id2]->depth.min = DepthT(-1);
220 _groupInfo[id2]->depth.occlude = false;
221 _statistics.occluded++;
227 std::sort(_groupInfo.begin(),
231 // cummulate min through the pipeline
232 dmin = _groupInfo[0]->depth.min;
233 for(id = 1 ; id < Int32(count) ; ++id)
235 if(_groupInfo[id]->depth.min != DepthT(-1))
237 if(dmin < _groupInfo[id]->depth.min)
238 _groupInfo[id]->depth.min = dmin;
240 dmin = _groupInfo[id]->depth.min;
244 getComposeTileBuffer(x,y)->empty = true;
247 for(id = count-1 ; id >= 0 ; --id)
249 _groupInfo[id]->trans.sendDepth = true;
250 _groupInfo[id]->trans.first = true;
251 _groupInfo[id]->trans.empty = false;
252 if(_groupInfo[id]->depth.min == DepthT(-1))
254 _groupInfo[id]->trans.empty = true;
260 _groupInfo[id]->trans.sendTo = nextGroup->id;
261 nextGroup->trans.first = false;
262 if(_groupInfo[id]->depth.min >
263 nextGroup->depth.max)
265 _groupInfo[id]->trans.sendDepth = false;
266 _statistics.noDepth++;
272 _groupInfo[id]->trans.sendTo = count;
273 _groupInfo[id]->trans.sendDepth = false;
274 getComposeTileBuffer(x,y)->empty = false;
275 _statistics.noDepth++;
277 nextGroup = _groupInfo[id];
281 for(id = 0 ; id < Int32(count) ; ++id)
283 transInfo[_groupInfo[id]->id * _composeTilesX * _composeTilesY +
284 x + y * _composeTilesX] = _groupInfo[id]->trans;
287 for(id = 0 ; id < count ; ++id)
288 printf("%d -> %d | ",_groupInfo[id]->id,_groupInfo[id]->trans.sendTo);
298 for(id = 0 ; id < count ; ++id)
300 if(!_groupInfo[id]->trans.empty)
307 // std::vector<TransInfo> ti=transInfo;
308 UInt32 infoCount = compressTransInfo(transInfo);
312 printf("\nsetup time %lf\n",t);
313 printf("read time %lf\n",tr);
316 clusterWindow()->getNetwork()->getMainConnection()->putValue(infoCount);
317 clusterWindow()->getNetwork()->getMainConnection()->put(
318 &transInfo[0],infoCount*sizeof(TransInfo));
319 _statistics.bytesOut += infoCount*_composeTilesY*count*sizeof(TransInfo);
320 clusterWindow()->getNetwork()->getMainConnection()->flush();
323 template<class DepthT,class ColorT>
324 void PipelineComposer::clientCompose(DepthT &depth,ColorT &color)
326 GroupConnection *servers;
329 TileBuffer *readTile = getWorkingTileBuffer();
330 #ifdef COMPRESS_IMAGES
331 std::vector<UInt32> src;
332 src.resize(512*512*8);
333 UInt32 dstLen,srcLen;
336 servers = clusterWindow()->getNetwork()->getGroupConnection(clusterId());
338 for(ty = 0; ty < _composeTilesY ; ++ty)
339 for(tx = 0; tx < _composeTilesX ; ++tx)
340 if(!getComposeTileBuffer(tx,ty)->empty)
343 // printf("expect %d \n",recvCount);
347 /*Connection::Channel c = */servers->selectChannel();
348 #ifdef COMPRESS_IMAGES
349 servers->get(&srcLen,sizeof(UInt32));
350 servers->get(&src[0],srcLen);
351 dstLen = lzf_decompress (&src[0],srcLen,
352 &(readTile->header),512*512*8);
354 servers->get(&(readTile->header),
355 sizeof(readTile->header));
357 // printf("%d from %d %d\n",recvCount,c,readTile->header.count);
359 #ifndef COMPRESS_IMAGES
360 servers->get(&(readTile->data),
365 _statistics.bytesIn +=
366 sizeof(readTile->header)+
372 glRasterPos2f(readTile->header.x * getTileSize(),
373 readTile->header.y * getTileSize());
375 glDrawPixels(readTile->header.w,
383 template<class DepthT,class ColorT>
384 void PipelineComposer::serverCompose(DepthT &depth,ColorT &color)
390 GroupConnection *srcConn;
391 TileBuffer *readTile = getWorkingTileBuffer();
392 DepthT *srcDepth,*dstDepth,*srcDepthEnd,*dstDepthEnd;
393 ColorT *srcColor=NULL,*dstColor=NULL;
394 #ifdef COMPRESS_IMAGES
395 std::vector<UInt32> src;
396 src.resize(512*512*8);
401 for(ty = 0; ty < _composeTilesY ; ++ty)
402 for(tx = 0; tx < _composeTilesX ; ++tx)
404 tile = getComposeTileBuffer(tx,ty);
408 if(!tile->trans.first)
414 for(ty = 0; ty < _composeTilesY ; ++ty)
416 for(tx = 0; tx < _composeTilesX ; ++tx)
418 tile = getComposeTileBuffer(tx,ty);
419 if(!tile->empty && tile->trans.first)
423 tile->header.count = --sendCount;
424 tile->dstConnection = clusterWindow()->
425 getNetwork()->getConnection(tile->trans.sendTo);
426 _queue.push_back(tile);
437 if(tile->trans.sendDepth)
438 _statistics.bytesOut += tile->dataSize + sizeof(tile->header);
440 _statistics.bytesOut += tile->colorSize + sizeof(tile->header);
445 srcConn = clusterWindow()->getNetwork()->getGroupConnection(clusterId());
450 srcConn->selectChannel();
451 #ifdef COMPRESS_IMAGES
452 srcConn->get(&srcLen,sizeof(UInt32));
453 srcConn->get(&src[0],srcLen);
454 dstLen = lzf_decompress (&src[0],srcLen,
455 &(readTile->header),512*512*8);
456 _statistics.bytesIn += srcLen + sizeof(UInt32);
457 // printf("Ratio %f\n",srcLen*100.0/dstLen);
459 srcConn->get(&readTile->header,sizeof(readTile->header));
460 _statistics.bytesIn += sizeof(readTile->header);
463 tile = getComposeTileBuffer(readTile->header.x,readTile->header.y);
465 reinterpret_cast<DepthT*>(readTile->data + tile->colorSize);
466 srcColor = reinterpret_cast<ColorT*>(readTile->data);
467 dstDepth = reinterpret_cast<DepthT*>(tile->data + tile->colorSize);
468 dstColor = reinterpret_cast<ColorT*>(tile->data);
469 if(readTile->header.depth)
471 // compose with depth
472 #ifndef COMPRESS_IMAGES
473 srcConn->get(readTile->data,tile->dataSize);
474 _statistics.bytesIn += tile->dataSize;
478 srcDepthEnd = reinterpret_cast<DepthT*>(readTile->data +
480 while(srcDepth < srcDepthEnd)
482 // *(char*)srcColor -=22;
483 // *(char*)dstColor +=22;
484 if(*srcDepth <= *dstDepth)
486 *dstColor = *srcColor;
487 *dstDepth = *srcDepth;
497 // compose without depth
498 #ifndef COMPRESS_IMAGES
499 srcConn->get(readTile->data,tile->colorSize);
500 _statistics.bytesIn += tile->colorSize;
504 dstDepthEnd = reinterpret_cast<DepthT*>(tile->data +
506 while(dstDepth < dstDepthEnd)
508 if(*dstDepth == DepthT(-1))
509 *dstColor = *srcColor;
518 tile->header.count = --sendCount;
519 tile->dstConnection = clusterWindow()->
520 getNetwork()->getConnection(tile->trans.sendTo);
521 _queue.push_back(tile);
531 #ifndef COMPRESS_IMAGES
532 if(tile->trans.sendDepth)
533 _statistics.bytesOut += tile->dataSize + sizeof(tile->header);
535 _statistics.bytesOut += tile->colorSize + sizeof(tile->header);
539 // wake up sender thread, so it can finish transmitting queued tiles
552 template<class DepthT,class ColorT>
553 void PipelineComposer::writeResult(DepthT &depth,ColorT &color)
557 #ifdef COMPRESS_IMAGES
558 std::vector<UInt32> dst;
559 dst.resize(512*512*8);
564 while(_queue.empty())
573 tile = _queue.front();
580 if(tile->trans.sendDepth)
582 tile->header.depth = true;
583 #ifdef COMPRESS_IMAGES
584 dst[0] = lzf_compress(&(tile->header),
585 tile->dataSize + sizeof(tile->header),
587 tile->dstConnection->put(&dst[0],dst[0]+sizeof(UInt32));
588 _statistics.bytesOut += dst[0]+sizeof(UInt32);
591 tile->dstConnection->put(&(tile->header),
593 sizeof(tile->header));
598 tile->header.depth = false;
599 #ifdef COMPRESS_IMAGES
600 dst[0] = lzf_compress(&(tile->header),
601 tile->colorSize + sizeof(tile->header),
603 tile->dstConnection->put(&dst[0],dst[0]+sizeof(UInt32));
604 _statistics.bytesOut += dst[0]+sizeof(UInt32);
606 tile->dstConnection->put(&(tile->header),
608 sizeof(tile->header));
611 tile->dstConnection->flush();
615 template<class DepthT,class ColorT>
616 void PipelineComposer::readBuffer(DepthT &depth,ColorT &color,
619 UInt32 left,bottom,top,right,front,back;
621 UInt32 tx,ty,x,y,w,h;
633 width = port->calcPixelWidth();
634 height = port->calcPixelHeight();
635 if(!getScreenAlignedBBox(port->getRoot(),
637 left,bottom,right,top,front,back))
639 left = right = width;
640 top = bottom = height;
642 width = port->calcPixelWidth();
643 height = port->calcPixelHeight();
645 _statistics.pixelReadTime = -getSystemTime();
646 #ifdef USE_NV_OCCLUSION
647 glEnable(GL_DEPTH_TEST);
648 glDepthFunc(GL_LEQUAL);
649 glColorMask(false,false,false,false);
653 for(ty = 0; ty < _readTilesY ; ++ty)
655 for(tx = 0; tx < _readTilesX ; ++tx)
659 x = tx * getTileSize();
660 y = ty * getTileSize();
661 w = osgMin(getTileSize(),width - x);
662 h = osgMin(getTileSize(),height - y);
664 tile = getReadTileBuffer(tx,ty);
669 tile->colorSize = sizeof(ColorT)*w*h;
670 tile->depthSize = sizeof(DepthT)*w*h;
671 tile->dataSize = tile->colorSize + tile->depthSize;
673 if(x > right || (x+w) <= left ||
674 y > top || (y+h) <= bottom)
676 tile->depth.min = DepthT(-1);
677 tile->depth.max = DepthT(-1);
678 tile->depth.occlude = false;
680 _statistics.clipped++;
686 #ifdef USE_NV_OCCLUSION
688 glBeginOcclusionQueryNV(_occlusionQuery);
691 glVertex3f(x ,y ,-1);
692 glVertex3f(x+w ,y ,-1);
693 glVertex3f(x+w ,y+h ,-1);
694 glVertex3f(x ,y+h ,-1);
696 glEndOcclusionQueryNV();
698 glGetOcclusionQueryuivNV(_occlusionQuery, GL_PIXEL_COUNT_NV, &samples);
699 _statistics.occluded+=samples - w*h;
702 tile->depth.min = (DepthT)-1;
703 tile->depth.max = (DepthT)-1;
704 tile->depth.occlude = false;
707 glColorMask(true,true,true,true);
710 glVertex3f(x ,y ,-1);
711 glVertex3f(x+w ,y ,-1);
712 glVertex3f(x+w ,y+h ,-1);
713 glVertex3f(x ,y+h ,-1);
715 glColorMask(false,false,false,false);
721 glReadPixels(x, y, w, h,
722 GL_DEPTH_COMPONENT, _depthType,
723 tile->data+tile->colorSize);
727 depthPtr = (DepthT*)(tile->data + tile->colorSize);
728 depthEnd = (DepthT*)(tile->data +
732 for( ; depthPtr != depthEnd && *depthPtr == (DepthT)(-1) ; ++depthPtr)
734 if(depthPtr != depthEnd)
736 depthMin = depthMax = *depthPtr;
737 for( ; depthPtr != depthEnd ; ++depthPtr)
739 if(*depthPtr > depthMax)
740 if(*depthPtr != (DepthT)(-1))
741 depthMax = *depthPtr;
745 if(*depthPtr < depthMin)
746 depthMin = *depthPtr;
751 depthMin = depthMax = (DepthT)-1;
755 depthPtr = reinterpret_cast<DepthT*>(tile->data + tile->colorSize);
757 occlude = checkDepth<DepthT, DepthT(-1)>(
763 if(depthMin == DepthT(-1))
768 tile->depth.min = depthMin;
769 tile->depth.max = depthMax;
770 tile->depth.occlude = occlude;
774 glReadPixels(x, y, w, h,
775 _colorFormat,_colorType,
781 #ifdef USE_NV_OCCLUSION
782 glEnable(GL_DEPTH_TEST);
783 glDepthFunc(GL_LEQUAL);
784 glColorMask(true,true,true,true);
787 _statistics.pixelReadTime += getSystemTime();
789 // sync with compose thread
791 _composeBarrier->enter(2);
794 std::vector<UInt8> *save = _composeTilePtr;
795 _composeTilePtr = _readTilePtr;
798 // transfer tile size
799 _composeTilesX = _readTilesX;
800 _composeTilesY = _readTilesY;
804 template<class DepthT,class ColorT>
805 void PipelineComposer::composeBuffer(DepthT &depth,ColorT &color)
807 // TODO use firstframe flag!!
808 if(getPipelined() && _firstFrame)
812 _composeBarrier->enter(2);
813 _composeBarrier->enter(2);
820 calculateTransInfo(depth,color);
821 _statistics.composeTime = -getSystemTime();
822 clientCompose(depth,color);
823 _statistics.composeTime += getSystemTime();
827 // sync with read thread
829 _composeBarrier->enter(2);
830 setTransInfo(depth,color);
831 serverCompose(depth,color);
833 _composeBarrier->enter(2);
837 /*! check depth of a tile.
839 template <class T,T empty>
840 bool PipelineComposer::checkDepth(T *buffer,T &front,T &back,int size)
843 T *end = buffer+size-1;
847 // start with last value
867 // check for empty tile
873 back = front = empty;