fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Cluster / Window / SortLast / OSGBinarySwapComposer.inl
blob8663ac4c36a7e18824d57af2a7aa96b2946d8330
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 template<class DepthT,class ColorT>
44 void BinarySwapComposer::sendToClient(DepthT &depth,
45                                       ColorT &color,
46                                       UInt32 left,
47                                       UInt32 bottom,
48                                       UInt32 right,
49                                       UInt32 top)
51     // send the resulting tile to the client
52     Connection *client = 
53         clusterWindow()->getNetwork()->getConnection(clusterId());
55     UInt32      tx,ty;
56     TileBuffer *tile;
57     UInt32      lastx = right + 1;
58     UInt32      lasty = top   + 1;
60     for(ty = bottom; ty <= top ; ++ty)
61     {
62         for(tx = left; tx <= right ; ++tx)
63         {
64             if(!getTileBuffer(tx,ty)->empty)
65             {
66                 lastx=tx;
67                 lasty=ty;
68             }
69         }
70     }
72     for(ty = bottom; ty <= top ; ++ty)
73     {
74         for(tx = left; tx <= right ; ++tx)
75         {
76             tile = getTileBuffer(tx,ty);
78             if(!tile->empty)
79             {
80                 if(ty == lasty && tx == lastx)
81                     tile->header.x^=0x8000;
83                 client->put(&(tile->header),
84                             tile->colorSize +
85                             sizeof(tile->header));
87                 client->flush();
89                 _statistics.bytesOut +=
90                     tile->colorSize + sizeof(tile->header);
91             }
92         }
93     }
95     if(lastx == right + 1)
96     {
97         TileBuffer t;
99         t.header.x=0x8000;
100         t.header.y=0x8000;
102         client->put(&(t.header),
103                     sizeof(t.header));
105         client->flush();
107         _statistics.bytesOut += sizeof(t.header);
108     }
111 template<class DepthT,class ColorT>
112 void BinarySwapComposer::recvFromServers(DepthT &depth,
113                                          ColorT &color,
114                                          UInt32 colorType,
115                                          UInt32 colorFormat,
116                                          Viewport *port)
118     UInt32      missing  = _usableServers;
119     TileBuffer *readTile = getTileReadBuffer();
120     GroupConnection *servers  = 
121         clusterWindow()->getNetwork()->getGroupConnection(clusterId());
123     Connection::Channel channel;
125     while(missing)
126     {
127         channel = servers->selectChannel();
129         servers->get(&(readTile->header),
130                      sizeof(readTile->header));
132         _statistics.bytesIn += sizeof(readTile->header);
134         if(readTile->header.x & 0x8000)
135         {
136             readTile->header.x ^= 0x8000;
137             servers->subSelection(channel);
138             missing--;
139         }
141         if(!(readTile->header.y & 0x8000))
142         {
143             servers->get(readTile->data,
144                          readTile->header.w*readTile->header.h*
145                          sizeof(ColorT));
147             _statistics.bytesIn += 
148                 readTile->header.w * readTile->header.h * sizeof(ColorT);
150             glRasterPos2f(readTile->header.x * getTileSize(),
151                           readTile->header.y * getTileSize());
152             glDrawPixels(readTile->header.w, 
153                          readTile->header.h,
154                          colorType, colorFormat,readTile->data);
155         }
156     }
158     servers->resetSelection();
161 template<class DepthT,class ColorT>
162 void BinarySwapComposer::writeCombine(DepthT &depthDummy,ColorT &colorDummy)
164     UInt32 tx,ty;
165     TileBuffer *tile;
166     UInt32 lastx,lasty;
168     for(;;)
169     {
170         _barrier->enter(2);
171         _barrier->enter(2);
173         if(_swapWith >= _usableServers)
174             break;
176         lastx = _writeRight + 1;
177         lasty = _writeTop   + 1;
179         for(ty = _writeBottom; ty <= _writeTop ; ++ty)
180         {
181             for(tx = _writeLeft; tx <= _writeRight ; ++tx)
182             {
183                 if(!getTileBuffer(tx,ty)->empty)
184                 {
185                     lastx=tx;
186                     lasty=ty;
187                 }
188             }
189         }
191         for(ty = _writeBottom; ty <= _writeTop ; ++ty)
192         {
193             for(tx = _writeLeft; tx <= _writeRight ; ++tx)
194             {
195                 tile = getTileBuffer(tx,ty);
197                 if(!tile->empty)
198                 {
199                     if(ty == lasty &&
200                        tx == lastx)
201                         tile->header.x^=0x8000;
203                     _swapConnection->put(&(tile->header),
204                                          tile->dataSize +
205                                          sizeof(tile->header));
207                     _swapConnection->flush();
209                     _statistics.bytesOut += 
210                         tile->dataSize + sizeof(tile->header);
212                     if(ty == lasty && tx == lastx)
213                         tile->header.x^=0x8000;
214                 }                    
215             }
216         }
217         // no data, write single header
218         if(lastx == _writeRight + 1)
219         {
220             TileBuffer t;
221             t.header.x=0x8000;
222             t.header.y=0x8000;
223             _swapConnection->put(&(t.header),
224                                  sizeof(t.header));
225             _statistics.bytesOut += sizeof(t.header);
226         }
227     }
230 template<class DepthT,class ColorT>
231 void BinarySwapComposer::readCombine(DepthT &depth,
232                                      ColorT &color,
233                                      UInt32 colorType,
234                                      UInt32 colorFormat,
235                                      UInt32 left,
236                                      UInt32 bottom,
237                                      UInt32 right,
238                                      UInt32 top,
239                                      UInt32 level)
241     UInt32      w,h;
242     UInt32      aRight,bLeft,aTop,bBottom;
243     UInt32      readLeft,readRight,readTop,readBottom;
244     TileBuffer *tile;
245     TileBuffer *readTile=getTileReadBuffer();
246     DepthT     *srcDepth,*dstDepth,*srcDepthEnd;
247     ColorT     *srcColor,*dstColor;
248     bool        last=false;
249     ColorT      nullColor;
251     memset(&nullColor,0,sizeof(ColorT));
252     _barrier->enter(2);
253     _swapWith = clusterId() ^ level;
255     if(_swapWith >= _usableServers)
256     {
257         _barrier->enter(2);
258         // send the resulting tile to the client
259         sendToClient(depth,color,
260                      left,bottom,right,top);
261         return;
262     }
263     _swapConnection = clusterWindow()->getNetwork()->getConnection(_swapWith);
265     w = right - left   + 1;
266     h = top   - bottom + 1;
268     if(w > h)
269     {
270         aRight  = left + (w/2);
271         aTop    = top;
272         bLeft   = aRight + 1;
273         bBottom = bottom;
274     }
275     else
276     {
277         aRight  = right;
278         aTop    = bottom + (h/2);
279         bLeft   = left;
280         bBottom = aTop + 1;
281     }
282     if(clusterId() > _swapWith)
283     {
284         _writeLeft   = left;
285         _writeBottom = bottom;
286         _writeRight  = aRight;
287         _writeTop    = aTop;
289         readLeft     = bLeft;
290         readBottom   = bBottom;
291         readRight    = right;
292         readTop      = top;
293     }
294     else
295     {
296         _writeLeft   = bLeft;
297         _writeBottom = bBottom;
298         _writeRight  = right;
299         _writeTop    = top;
301         readLeft     = left;
302         readBottom   = bottom;
303         readRight    = aRight;
304         readTop      = aTop;
305     }
306     _barrier->enter(2);
307     // send
308     _swapConnection->selectChannel();
309     do
310     {
311         _swapConnection->get(&(readTile->header),
312                              sizeof(readTile->header));
313         _statistics.bytesIn += sizeof(readTile->header);
314         if(readTile->header.x&0x8000)
315         {
316             last = true;
317             readTile->header.x^=0x8000;
318         }
319         if(!(readTile->header.y & 0x8000))
320         {
321             tile = getTileBuffer(readTile->header.x,
322                                  readTile->header.y);
323             if(tile->empty)
324             {
325                 // dest is empty, overwrite
326                 _swapConnection->get(tile->data,
327                                      tile->dataSize);
328                 _statistics.bytesIn += tile->dataSize;
329                 if(sizeof(ColorT) == 4)
330                 {
331                     glRasterPos2f(tile->header.x * getTileSize(),
332                                   tile->header.y * getTileSize());
333                     glDrawPixels(tile->header.w,tile->header.h,
334                                  colorType, colorFormat,
335                                  tile->data);
336                 }
337                 tile->empty = false;
338             }
339             else
340             {
341                 // read 
342                 _swapConnection->get(readTile->data,
343                                      tile->dataSize);
344                 _statistics.bytesIn += tile->dataSize;
345                 // depth compose
346                 srcDepth    = 
347                     reinterpret_cast<DepthT*>(readTile->data + tile->colorSize);
349                 srcDepthEnd = reinterpret_cast<DepthT*>(readTile->data + 
350                                                         tile->dataSize);
351                 srcColor    = reinterpret_cast<ColorT*>(readTile->data);
352                 dstDepth    = 
353                     reinterpret_cast<DepthT*>(tile->data + tile->colorSize);
354                 dstColor    = reinterpret_cast<ColorT*>(tile->data);
355                 // compose
356                 if(sizeof(ColorT) == 4)
357                 {
358                     // with alpha
359                     while(srcDepth < srcDepthEnd)
360                     {
361                         if(*srcDepth <= *dstDepth)
362                             *dstDepth = *srcDepth;
363                         else
364                             *srcColor = nullColor;
365                         srcDepth++;
366                         dstDepth++;
367                         srcColor++;
368                     }
369                     // hardware alpha combine
370                     glRasterPos2f(tile->header.x * getTileSize(),
371                                   tile->header.y * getTileSize());
372                     glDrawPixels(tile->header.w,tile->header.h,
373                                  colorType, colorFormat,
374                                  readTile->data);
375                     glReadPixels(tile->header.x * getTileSize(),
376                                  tile->header.y * getTileSize(),
377                                  tile->header.w,tile->header.h,
378                                  colorType, colorFormat,
379                                  tile->data);
380                 }
381                 else
382                 {
383                     // no alpha
384                     while(srcDepth < srcDepthEnd)
385                     {
386                         if(*srcDepth < *dstDepth)
387                         {
388                             *dstColor = *srcColor;
389                             *dstDepth = *srcDepth;
390                         }
391                         srcDepth++;
392                         dstDepth++;
393                         srcColor++;
394                         dstColor++;
395                     }
396                 }
397             }
398         }
399     }
400     while(!last);
401     readCombine(depth,color,
402                 colorType,colorFormat,
403                 readLeft,readBottom,readRight,readTop,level<<1);
406 template<class DepthT,class ColorT>
407 void BinarySwapComposer::startReader(DepthT &depthMax,
408                                      ColorT &color,
409                                      UInt32 depthFormat,
410                                      UInt32 colorType,
411                                      UInt32 colorFormat,
412                                      Viewport *port)
414     UInt32      tx,ty,x,y,w,h;
415     TileBuffer *tile;
416     UInt32      left,bottom,top,right,front,back;
417 #ifdef OPTIMIZED_BINARY_SWAP
418     DepthT     *depthStart,*depthEnd;
419 #endif
420     UInt8      *c,*cEnd;
422     if(!getScreenAlignedBBox(port->getRoot(),
423                              port,
424                              left,bottom,right,top,front,back))
425     {
426         left=right=clusterWindow()->getWidth();
427         top=bottom=clusterWindow()->getHeight();
428         front=back=UInt32(-1);
429     }
431     for(ty = 0; ty < _tilesY ; ++ty)
432     {
433         for(tx = 0; tx < _tilesX ; ++tx)
434         {
435             x = tx * getTileSize();
436             y = ty * getTileSize();
437             w = osgMin(getTileSize(),port->calcPixelWidth() - x);
438             h = osgMin(getTileSize(),port->calcPixelHeight() - y);
439             tile = getTileBuffer(tx,ty);
440             tile->header.x = tx;
441             tile->header.y = ty;
442             tile->header.w = w;
443             tile->header.h = h;
444             tile->colorSize = sizeof(ColorT)*w*h;
445             tile->depthSize = sizeof(DepthT)*w*h;
446             tile->dataSize  = tile->colorSize + tile->depthSize;
447             if(x > right ||
448                (x+w) <= left ||
449                y > top ||
450                (y+h) <= bottom)
451             {
452                 tile->empty = true;
453                 continue;
454             }
455             tile->empty = false;
456             glReadPixels(x, y, w, h, 
457                          GL_DEPTH_COMPONENT, depthFormat,
458                          tile->data+tile->colorSize);
459 #ifdef OPTIMIZED_BINARY_SWAP
460             if(sizeof(ColorT) != 4)
461             {
462                 depthStart = (DepthT*)(tile->data + tile->colorSize);
463                 depthEnd   = (DepthT*)(tile->data + 
464                                        tile->colorSize +
465                                        tile->depthSize);
466                 // empty if no depth
467                 while(depthStart < depthEnd &&
468                       *depthStart == (DepthT)depthMax)
469                     ++depthStart;
470                 if(depthStart == depthEnd)
471                     tile->empty = true;
472             }
473 #endif
474             if(!tile->empty)
475             {
476                 glReadPixels(x, y, w, h, 
477                              colorType, colorFormat,
478                              tile->data);
479                 if(sizeof(ColorT) == 4)
480                 {
481                     // in alpha mode, only empty if alpha is 0
482                     c    = tile->data + 3;
483                     cEnd = tile->data + 3 + w * h * 4;
484                     while(c != cEnd && *c == 0)
485                         c += 4;
486                     if(c == cEnd)
487                         tile->empty = true;
488                 }
489             }
490         }
491     }
493     _barrier->enter(2);
494     readCombine(depthMax,color,
495                 colorType,colorFormat,
496                 0,0,_tilesX-1,_tilesY-1,1);
500 OSG_END_NAMESPACE