fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Cluster / Window / SortLast / OSGPipelineComposer.inl
blob16c52a48d22fdb48d9a459825a3ba39e38d86d42
1 /*---------------------------------------------------------------------------*\
2  *                                OpenSG                                     *
3  *                                                                           *
4  *                                                                           *
5  *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
6  *                                                                           *
7  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
8  *                                                                           *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
11  *                                License                                    *
12  *                                                                           *
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.                               *
16  *                                                                           *
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.                          *
21  *                                                                           *
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.                 *
25  *                                                                           *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
28  *                                Changes                                    *
29  *                                                                           *
30  *                                                                           *
31  *                                                                           *
32  *                                                                           *
33  *                                                                           *
34  *                                                                           *
35 \*---------------------------------------------------------------------------*/
37 //---------------------------------------------------------------------------
38 //  Includes
39 //---------------------------------------------------------------------------
41 OSG_BEGIN_NAMESPACE
43 #define COMBINE
44 #define TOCLIENT
46 template<class DepthT,class ColorT>
47 UInt32 PipelineComposer::getMinMaxOcclude(DepthT    &depth,
48                                           ColorT    &color,
49                                           DepthInfo *result)
51     UInt32             x,y;
52     TileBuffer        *tile;
53     UInt32             count=0;
54     DepthInfo         *first = result;
55     DepthInfo         *reuseEmpty=NULL;
57     first->min=0;
58     result++;
59     for(y = 0; y < _composeTilesY ; ++y)
60     {
61         for(x = 0; x < _composeTilesX ; ++x)
62         {
63             tile = getComposeTileBuffer(x,y);
65             if(tile->depth.min == DepthT(-1) &&
66                tile->depth.max == DepthT(-1)) {
67                 if(!reuseEmpty) {
68                     reuseEmpty=result;
69                     result++;
70                     count++;
71                     reuseEmpty->min = DepthT(-1);
72                     reuseEmpty->max = 0;
73                 }
74                 reuseEmpty->max++;
75             } else {
76                 *result = tile->depth;
77                 result++;
78                 count++;
79                 reuseEmpty=NULL;
80             }
81         }
82     }
83 //    printf("compr %f\n",count*100.0/(_composeTilesX*_composeTilesY));
85     first->min = count;
86     return count+1;
89 template<class DepthT,class ColorT>
90 void PipelineComposer::setTransInfo(DepthT &depth,ColorT &color)
92     UInt32                      x,y;
93     Connection                 *client,*readCon;
94     std::vector<DepthInfo>      depthInfo;
95     TileBuffer                 *tile;
96     std::vector<TransInfo>      transInfo;
97     std::vector<TransInfo>      transInfoDummy;
98     UInt32                      count;
100     transInfo.resize(_composeTilesX * _composeTilesY * serverCount());
101     depthInfo.resize(_composeTilesX * _composeTilesY + 1);
102     count = getMinMaxOcclude(depth,color,&depthInfo[0]);
104     _statistics.sortTime = -getSystemTime();
106     // send depth info
107     client = clusterWindow()->getNetwork()->getMainConnection();
109     client->put(&depthInfo[0],sizeof(DepthInfo)*count);
110     _statistics.bytesOut += sizeof(DepthInfo)*count;
111     client->flush();
113     // read transmit info
114     readCon = clusterWindow()->getNetwork()->getMainConnection();
115     readCon->selectChannel();
117     UInt32 infoCount;
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)
123     {
124         for(x = 0; x < _composeTilesX ; ++x)
125         {
126             tile = getComposeTileBuffer(x,y);
127             tile->trans = transInfo[x + y*_composeTilesX + 
128                                     clusterId()*_composeTilesX*_composeTilesY];
129             // occluded
130             if(tile->trans.empty)
131                 tile->empty = true;
132         }
133     }
135     clusterWindow()->getNetwork()->getMainConnection()->signal();
136     clusterWindow()->getNetwork()->getMainConnection()->wait();
138     _statistics.sortTime += getSystemTime();
139 }    
141 template<class DepthT,class ColorT>
142 void PipelineComposer::calculateTransInfo(DepthT &depth,ColorT &color)
144     Connection::Channel         channel;
145     Int32                       id;
146     GroupConnection            *servers;
147     UInt32                      count = serverCount();
148     UInt32                      x,y;
149     DepthT                      dmin;
150     GroupInfo                  *nextGroup;
151     std::vector<DepthInfo>      depthInfo;
152     std::vector<TransInfo>      transInfo;
153     std::vector<DepthInfo>      depthInfoTmp;
154     UInt32                      c;
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())
165     {
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)) {
174                 while(src->max--) {
175                     dst->min = DepthT(-1);
176                     dst->max = DepthT(-1);
177                     dst->occlude = false;
178                     dst++;
179                 }
180             } else {
181                 *dst = *src;
182                 dst++;
183             }
184             src++;
185         }
186         _statistics.bytesIn += sizeof(DepthInfo)*(depthCount.min+1);
187         servers->subSelection(channel);
188     }
189     servers->resetSelection();
190     tr += getSystemTime();
192     double t=-getSystemTime();
194     // sort each group
195     for(y = 0; y < _composeTilesY ; ++y)
196     {
197         for(x = 0; x < _composeTilesX ; ++x)
198         {
199             for(id = 0 ; id < Int32(count) ; ++id)
200             {
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))
206                     _statistics.noGeo++;
207             }
208             // remove occluders
209             for(UInt32 id1 = 0 ; id1 < count ; ++id1)
210             {
211                 if(_groupInfo[id1]->depth.occlude) {
212                     for(UInt32 id2 = 0 ; id2 < count ; ++id2) {
213                         if(id1 != id2 &&
214                            _groupInfo[id1]->depth.max < 
215                            _groupInfo[id2]->depth.min &&
216                            _groupInfo[id2]->depth.min != DepthT(-1))
217                         {
218                             _groupInfo[id2]->depth.max = DepthT(-1);
219                             _groupInfo[id2]->depth.min = DepthT(-1);
220                             _groupInfo[id2]->depth.occlude = false;
221                             _statistics.occluded++;
222                         }
223                     }
224                 }
225             }
226             // sort
227             std::sort(_groupInfo.begin(),
228                       _groupInfo.end(),
229                       GroupInfoOrder());
230             
231             // cummulate min through the pipeline
232             dmin = _groupInfo[0]->depth.min;
233             for(id = 1 ; id < Int32(count) ; ++id)
234             {
235                 if(_groupInfo[id]->depth.min != DepthT(-1))
236                 {
237                     if(dmin < _groupInfo[id]->depth.min)
238                         _groupInfo[id]->depth.min = dmin;
239                     else
240                         dmin = _groupInfo[id]->depth.min;
241                 }
242             }
244             getComposeTileBuffer(x,y)->empty = true;
245             // determine send to
246             nextGroup = NULL;
247             for(id = count-1 ; id >= 0 ; --id)
248             {
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))
253                 {
254                     _groupInfo[id]->trans.empty = true;
255                 }        
256                 else
257                 {
258                     if(nextGroup)
259                     {
260                         _groupInfo[id]->trans.sendTo = nextGroup->id;
261                         nextGroup->trans.first = false;
262                         if(_groupInfo[id]->depth.min >
263                            nextGroup->depth.max)
264                         {
265                             _groupInfo[id]->trans.sendDepth = false;
266                             _statistics.noDepth++;
267                         }
268                     }
269                     else
270                     {
271                         // send to client
272                         _groupInfo[id]->trans.sendTo    = count;
273                         _groupInfo[id]->trans.sendDepth = false;
274                         getComposeTileBuffer(x,y)->empty = false;
275                         _statistics.noDepth++;
276                     }
277                     nextGroup = _groupInfo[id];
278                 }
279             }
281             for(id = 0 ; id < Int32(count) ; ++id)
282             {
283                 transInfo[_groupInfo[id]->id * _composeTilesX * _composeTilesY +
284                           x + y * _composeTilesX] = _groupInfo[id]->trans;
285             }
286 #if 0
287             for(id = 0 ; id < count ; ++id)
288                 printf("%d -> %d | ",_groupInfo[id]->id,_groupInfo[id]->trans.sendTo);
289             printf("\n");
290 #endif
292 #if 0
293             int sum=0;
294             if(y==0 && x==0)
295                 printf("\n");
296             if(x==0)
297                 printf("\n");
298             for(id = 0 ; id < count ; ++id)
299             {
300                 if(!_groupInfo[id]->trans.empty)
301                     sum++;
302             }
303             printf("%d ",sum);
304 #endif
305         }
306     }
307 //    std::vector<TransInfo> ti=transInfo;
308     UInt32 infoCount = compressTransInfo(transInfo);
310     t+=getSystemTime();
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;
327     UInt32             tx,ty;
328     UInt32             recvCount=0;
329     TileBuffer        *readTile = getWorkingTileBuffer();
330 #ifdef COMPRESS_IMAGES
331     std::vector<UInt32> src;
332     src.resize(512*512*8);
333     UInt32 dstLen,srcLen;
334 #endif
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)
341                 recvCount++;
343 //    printf("expect %d \n",recvCount);
345     while(recvCount--)
346     {
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);
353 #else
354         servers->get(&(readTile->header),
355                      sizeof(readTile->header));
356 #endif
357         // printf("%d from %d %d\n",recvCount,c,readTile->header.count);
359 #ifndef COMPRESS_IMAGES
360         servers->get(&(readTile->data),
361                      readTile->header.w*
362                      readTile->header.h*
363                      sizeof(ColorT));
364 #endif
365         _statistics.bytesIn += 
366                      sizeof(readTile->header)+
367                      readTile->header.w*
368                      readTile->header.h*
369                      sizeof(ColorT);
371         // draw
372         glRasterPos2f(readTile->header.x * getTileSize(),
373                       readTile->header.y * getTileSize());
375         glDrawPixels(readTile->header.w, 
376                      readTile->header.h,
377                      _colorFormat,
378                      _colorType,
379                      readTile->data);
380     }
383 template<class DepthT,class ColorT>
384 void PipelineComposer::serverCompose(DepthT &depth,ColorT &color)
386     UInt32             tx,ty;
387     TileBuffer        *tile;
388     UInt32             sendCount=0;
389     UInt32             recvCount=0;
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);
397     UInt32 dstLen;
398     UInt32 srcLen;
399 #endif
401     for(ty = 0; ty < _composeTilesY ; ++ty)
402         for(tx = 0; tx < _composeTilesX ; ++tx)
403         {
404             tile = getComposeTileBuffer(tx,ty);
405             if(!tile->empty)
406             {
407                 sendCount++;
408                 if(!tile->trans.first)
409                     recvCount++;
410             }
411         }
413     // semd all tiles 
414     for(ty = 0; ty < _composeTilesY ; ++ty)
415     {
416         for(tx = 0; tx < _composeTilesX ; ++tx)
417         {
418             tile = getComposeTileBuffer(tx,ty);
419             if(!tile->empty && tile->trans.first)
420             {
421                 // send first tiles 
422                 _lock->acquire();
423                 tile->header.count = --sendCount;
424                 tile->dstConnection = clusterWindow()->
425                     getNetwork()->getConnection(tile->trans.sendTo);
426                 _queue.push_back(tile);
427                 if(_waiting)
428                 {
429                     _lock   ->release( );
430                     _barrier->enter  (2);
431                 }
432                 else
433                 {
434                     _lock->release();
435                 }
437                 if(tile->trans.sendDepth)
438                     _statistics.bytesOut += tile->dataSize + sizeof(tile->header);
439                 else
440                     _statistics.bytesOut += tile->colorSize + sizeof(tile->header);
441             }
442         }
443     }
445     srcConn = clusterWindow()->getNetwork()->getGroupConnection(clusterId());
447     // recv all tiles
448     while(recvCount--)
449     {
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);
458 #else
459         srcConn->get(&readTile->header,sizeof(readTile->header));
460         _statistics.bytesIn += sizeof(readTile->header);
461 #endif
463         tile = getComposeTileBuffer(readTile->header.x,readTile->header.y);
464         srcDepth    = 
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)
470         {
471             // compose with depth
472 #ifndef COMPRESS_IMAGES
473             srcConn->get(readTile->data,tile->dataSize);
474             _statistics.bytesIn += tile->dataSize;
475 #endif
477             // compose
478             srcDepthEnd = reinterpret_cast<DepthT*>(readTile->data + 
479                                                     tile->dataSize);
480             while(srcDepth < srcDepthEnd)
481             {
482 //                *(char*)srcColor -=22;
483 //                *(char*)dstColor +=22;
484                 if(*srcDepth <= *dstDepth)
485                 {
486                     *dstColor = *srcColor;
487                     *dstDepth = *srcDepth;
488                 }
489                 srcDepth++;
490                 dstDepth++;
491                 srcColor++;
492                 dstColor++;
493             }
494         }
495         else
496         {
497             // compose without depth
498 #ifndef COMPRESS_IMAGES
499             srcConn->get(readTile->data,tile->colorSize);
500             _statistics.bytesIn += tile->colorSize;
501 #endif
503             // compose
504             dstDepthEnd = reinterpret_cast<DepthT*>(tile->data + 
505                                                     tile->dataSize);
506             while(dstDepth < dstDepthEnd)
507             {
508                 if(*dstDepth == DepthT(-1))
509                     *dstColor = *srcColor;
510                 dstDepth++;
511                 srcColor++;
512                 dstColor++;
513             }
514         }
516         // put to send queue
517         _lock->acquire();
518         tile->header.count = --sendCount;
519         tile->dstConnection = clusterWindow()->
520             getNetwork()->getConnection(tile->trans.sendTo);
521         _queue.push_back(tile);
522         if(_waiting)
523         {
524             _lock   ->release( );
525             _barrier->enter  (2);
526         }
527         else
528         {
529             _lock->release();
530         }
531 #ifndef COMPRESS_IMAGES
532         if(tile->trans.sendDepth)
533             _statistics.bytesOut += tile->dataSize + sizeof(tile->header);
534         else
535             _statistics.bytesOut += tile->colorSize + sizeof(tile->header);
536 #endif
537     }
539     // wake up sender thread, so it can finish transmitting queued tiles
540     _lock->acquire();
541     if(_waiting)
542     {
543         _lock   ->release( );
544         _barrier->enter  (2);
545     }
546     else
547     {
548         _lock->release();
549     }
552 template<class DepthT,class ColorT>
553 void PipelineComposer::writeResult(DepthT &depth,ColorT &color)
555     TileBuffer   *tile;
557 #ifdef COMPRESS_IMAGES
558     std::vector<UInt32> dst;
559     dst.resize(512*512*8);
560 #endif
561     for(;;)
562     {
563         _lock->acquire();
564         while(_queue.empty())
565         {
566             _waiting = true;
567             _lock   ->release( );
568             _barrier->enter  (2);
569             _lock   ->acquire( );
570         }
572         _waiting = false;
573         tile     = _queue.front();
574         _queue.pop_front();
575         _lock->release();
577         if(tile == NULL)
578             break;
580         if(tile->trans.sendDepth)
581         {
582             tile->header.depth = true;
583 #ifdef COMPRESS_IMAGES
584             dst[0] = lzf_compress(&(tile->header),
585                                   tile->dataSize + sizeof(tile->header),
586                                   &dst[1],512*512*8);
587             tile->dstConnection->put(&dst[0],dst[0]+sizeof(UInt32));
588             _statistics.bytesOut += dst[0]+sizeof(UInt32);
589 #else
591             tile->dstConnection->put(&(tile->header),
592                                      tile->dataSize +
593                                      sizeof(tile->header));
594 #endif
595         }
596         else
597         {
598             tile->header.depth = false;
599 #ifdef COMPRESS_IMAGES
600             dst[0] = lzf_compress(&(tile->header),
601                                   tile->colorSize + sizeof(tile->header),
602                                   &dst[1],512*512*8);
603             tile->dstConnection->put(&dst[0],dst[0]+sizeof(UInt32));
604             _statistics.bytesOut += dst[0]+sizeof(UInt32);
605 #else
606             tile->dstConnection->put(&(tile->header),
607                                      tile->colorSize +
608                                      sizeof(tile->header));
609 #endif
610         }
611         tile->dstConnection->flush();
612     }
615 template<class DepthT,class ColorT>
616 void PipelineComposer::readBuffer(DepthT &depth,ColorT &color,
617                                   Viewport *port)
619     UInt32      left,bottom,top,right,front,back;
620     UInt32      width,height;
621     UInt32      tx,ty,x,y,w,h;
622     TileBuffer *tile;
623 #if 0
624     DepthT     *depthEnd;
625 #endif
626     DepthT     *depthPtr;
627     DepthT      depthMin;
628     DepthT      depthMax;
629     bool        occlude;
631     if(isClient())
632         return;
633     width  = port->calcPixelWidth();
634     height = port->calcPixelHeight();
635     if(!getScreenAlignedBBox(port->getRoot(),
636                              port,
637                              left,bottom,right,top,front,back))
638     {
639         left = right = width;
640         top = bottom = height;
641     }
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);
650     glDepthMask(false);
651 #endif
653     for(ty = 0; ty < _readTilesY ; ++ty)
654     {
655         for(tx = 0; tx < _readTilesX ; ++tx)
656         {
657             occlude = true;
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);
665             tile->header.x = tx;
666             tile->header.y = ty;
667             tile->header.w = w;
668             tile->header.h = h;
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)
675             {
676                 tile->depth.min     = DepthT(-1);
677                 tile->depth.max     = DepthT(-1);
678                 tile->depth.occlude = false;
679                 tile->empty = true;
680                 _statistics.clipped++;
681                 continue;
682             }
684             tile->empty = false;
686 #ifdef USE_NV_OCCLUSION
687             // fast empty test
688             glBeginOcclusionQueryNV(_occlusionQuery);
689             glBegin(GL_QUADS);
690             glColor3f(0,1,0);
691             glVertex3f(x    ,y    ,-1);
692             glVertex3f(x+w  ,y    ,-1);
693             glVertex3f(x+w  ,y+h  ,-1);
694             glVertex3f(x    ,y+h  ,-1);
695             glEnd();
696             glEndOcclusionQueryNV();
697             GLuint samples=-1;
698             glGetOcclusionQueryuivNV(_occlusionQuery, GL_PIXEL_COUNT_NV, &samples);
699             _statistics.occluded+=samples - w*h;
700             if(samples == w*h)
701             {
702                 tile->depth.min     = (DepthT)-1;
703                 tile->depth.max     = (DepthT)-1;
704                 tile->depth.occlude = false;
705                 tile->empty = true;
706 #if 1
707                 glColorMask(true,true,true,true);
708                 glBegin(GL_QUADS);
709                 glColor3f(1,0,0);
710                 glVertex3f(x    ,y    ,-1);
711                 glVertex3f(x+w  ,y    ,-1);
712                 glVertex3f(x+w  ,y+h  ,-1);
713                 glVertex3f(x    ,y+h  ,-1);
714                 glEnd();
715                 glColorMask(false,false,false,false);
716 #endif
717                 continue;
718             }
719 #endif
720             // read depth
721             glReadPixels(x, y, w, h, 
722                          GL_DEPTH_COMPONENT, _depthType,
723                          tile->data+tile->colorSize);
725             // old version
726 #if 0
727             depthPtr = (DepthT*)(tile->data + tile->colorSize);
728             depthEnd = (DepthT*)(tile->data + 
729                                  tile->colorSize +
730                                  tile->depthSize);
732             for( ; depthPtr != depthEnd && *depthPtr == (DepthT)(-1) ; ++depthPtr)
733                 occlude = false;
734             if(depthPtr != depthEnd)
735             {
736                 depthMin = depthMax = *depthPtr;
737                 for( ; depthPtr != depthEnd ; ++depthPtr)
738                 {
739                     if(*depthPtr > depthMax)
740                         if(*depthPtr != (DepthT)(-1))
741                             depthMax = *depthPtr;
742                         else
743                             occlude = false;
744                     else
745                         if(*depthPtr < depthMin)
746                             depthMin = *depthPtr;
747                 }
748             }
749             else
750             {
751                 depthMin = depthMax = (DepthT)-1;
752                 occlude  = false;
753             }
754 #else
755             depthPtr = reinterpret_cast<DepthT*>(tile->data + tile->colorSize);
756             // new version
757             occlude = checkDepth<DepthT, DepthT(-1)>(
758                 depthPtr,
759                 depthMin,
760                 depthMax,
761                 w*h);
762 #endif
763             if(depthMin == DepthT(-1))
764                 tile->empty = true;
765             else
766                 tile->empty = false;
768             tile->depth.min     = depthMin;
769             tile->depth.max     = depthMax;
770             tile->depth.occlude = occlude;
772             if(!tile->empty)
773             {
774                 glReadPixels(x, y, w, h, 
775                              _colorFormat,_colorType,
776                              tile->data);
777             }
778         }
779     }
781 #ifdef USE_NV_OCCLUSION
782     glEnable(GL_DEPTH_TEST);
783     glDepthFunc(GL_LEQUAL);
784     glColorMask(true,true,true,true);
785     glDepthMask(true);
786 #endif
787     _statistics.pixelReadTime += getSystemTime();
789     // sync with compose thread
790     if(getPipelined()) 
791         _composeBarrier->enter(2);
793     // swap buffers
794     std::vector<UInt8> *save = _composeTilePtr;
795     _composeTilePtr = _readTilePtr;
796     _readTilePtr = save;
798     // transfer tile size
799     _composeTilesX  = _readTilesX;
800     _composeTilesY  = _readTilesY;
801     
804 template<class DepthT,class ColorT>
805 void PipelineComposer::composeBuffer(DepthT &depth,ColorT &color)
807     // TODO use firstframe flag!!
808     if(getPipelined() && _firstFrame) 
809     {
810         if(!isClient()) 
811         {
812             _composeBarrier->enter(2);
813             _composeBarrier->enter(2);
814         }
815         _firstFrame = false;
816         return;
817     }
818     if(isClient())
819     {
820         calculateTransInfo(depth,color);
821         _statistics.composeTime = -getSystemTime();
822         clientCompose(depth,color);
823         _statistics.composeTime += getSystemTime();
824     }
825     else
826     {
827         // sync with read thread
828         if(getPipelined()) 
829             _composeBarrier->enter(2);
830         setTransInfo(depth,color);
831         serverCompose(depth,color);
832         if(getPipelined()) 
833             _composeBarrier->enter(2);
834     }
837 /*! check depth of a tile.
838  */
839 template <class T,T empty>
840 bool PipelineComposer::checkDepth(T *buffer,T &front,T &back,int size)
842     T    *i        = buffer;
843     T    *end      = buffer+size-1;
844     bool  occlude  = true;
845     T     endValue = *end;
847     // start with last value
848     back = front = *end;
849     if(*end == empty) {
850         back = 0;
851         occlude = false;
852     }
853     while(i != end) {
854         // check not empty
855         *end = empty;
856         while(*i != empty) {
857             if(*i < front)
858                 front = *i;
859             if(*i > back)
860                 back = *i;
861             ++i;
862         }
863         if(i!=end) {
864             occlude = false;
865             // check empty
866             *end = 0;
867             // check for empty tile
868             while(*i == empty) 
869                 ++i;
870         }
871     }
872     if(front > back) {
873         back = front = empty;
874     }    
875     *end = endValue;
876     return occlude;
879 OSG_END_NAMESPACE