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 \*---------------------------------------------------------------------------*/
38 //---------------------------------------------------------------------------
40 //---------------------------------------------------------------------------
45 #include "OSGConfig.h"
48 #include "OSGBaseFunctions.h"
50 #include "OSGClusterViewBuffer.h"
51 #include "OSGImageFileHandler.h"
52 #include "OSGImageFileType.h"
53 #include "OSGPointConnection.h"
54 #include "OSGGroupConnection.h"
58 /*! \class OSG::ClusterViewBuffer
59 \ingroup GrpSystemCluster
60 \brief Viewbuffer functions
62 This class provides an interface to an OpenGL view buffer.
63 The Buffer contents can be transfered over a Connection.
64 All Image types can be used for image compression. The
65 ClusterViewBuffer can access RGBA, Stencil and Z-Buffer values.
67 The whole imagebuffer is divided into subtiles. Each subtile
68 is read from the buffer, compressed and send over the nertwork.
69 In most cases, the buffer read and the network send of the previous
70 tile is done in parallel.
72 todo: currently ClusterViewBuffer works on the activated window.
73 Is this a good idea. Better WindowPtr as parameter and then
74 call activate before send,recv? MR
77 /*-------------------------------------------------------------------------*/
78 /* Constructors/Destructor */
80 /*! Initialize a ClusterViewBuffer. By default, no image compression
81 is set and the subtile size is set to 32. The viewbuffer contents
82 is send in packages. If the package size is not too large, then
83 network transmission of the last and graphics card read of the current
84 package is done in parallel.
87 ClusterViewBuffer::ClusterViewBuffer(void) :
88 _imgTransType (NULL
),
90 _rgbDataType (GL_UNSIGNED_BYTE
),
92 _rgbaDataType (GL_UNSIGNED_BYTE
),
94 _depthDataType(GL_UNSIGNED_INT
),
102 ClusterViewBuffer::~ClusterViewBuffer(void)
106 /*-------------------------------------------------------------------------*/
109 /*! Receive image data from all channels of a conneciton. The receive is
110 * finished, when the last channel signals a transmission end.
113 void ClusterViewBuffer::recv(GroupConnection
&connection
)
115 UInt32 tx
, ty
, tw
, th
;
123 Connection::Channel channel
;
125 missing
= connection
.getChannelCount();
129 glMatrixMode(GL_PROJECTION
);
132 gluOrtho2D(0, getBufferWidth(), 0, getBufferHeight());
133 glDisable(GL_DEPTH_TEST
);
134 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
136 // we expect tiles form all connected servers
139 channel
= connection
.selectChannel();
140 connection
.getValue(component
);
143 connection
.subSelection(channel
);
149 connection
.getValue(tx
);
150 connection
.getValue(ty
);
151 connection
.getValue(tw
);
152 connection
.getValue(th
);
153 glRasterPos2i(tx
, ty
);
155 // =========== recv stencil =====================================
156 if(component
& STENCIL
)
158 data
.resize(tw
* th
);
159 connection
.get(&data
[0], tw
* th
);
160 glDrawPixels(tw
, th
, GL_STENCIL_INDEX
, GL_UNSIGNED_BYTE
, &data
[0]);
161 glEnable(GL_STENCIL_TEST
);
164 // =========== recv depth =======================================
165 if(component
& DEPTH
)
167 glEnable(GL_DEPTH_TEST
);
168 glEnable(GL_STENCIL_TEST
);
169 glStencilFunc(GL_ALWAYS
, 1, 1);
170 glStencilOp(GL_KEEP
, GL_ZERO
, GL_REPLACE
);
171 data
.resize(tw
* th
* sizeof(float));
172 connection
.get(&data
[0], tw
* th
* sizeof(float));
173 glDrawPixels(tw
, th
, GL_DEPTH_COMPONENT
, GL_FLOAT
, &data
[0]);
174 glDisable(GL_DEPTH_TEST
);
177 // =========== recv RGBA ========================================
180 if(component
& (DEPTH
| STENCIL
))
182 glStencilFunc(GL_EQUAL
, 1, 1);
185 switch(component
& RGBA
)
196 SFATAL
<< "Component combination not supported"
201 connection
.getValue(dataSize
);
209 data
.resize(dataSize
);
210 connection
.get(&data
[0], dataSize
);
211 imageData
.resize(tw
* th
* componentCnt
);
212 ImageFileType::restore(*pImage
, (UChar8
*) &data
[0], dataSize
);
213 glDrawPixels(tw
, th
, glformat
, GL_UNSIGNED_BYTE
,
219 data
.resize(tw
* th
* componentCnt
);
220 connection
.get(&data
[0], tw
* th
* componentCnt
);
221 glDrawPixels(tw
, th
, glformat
, GL_UNSIGNED_BYTE
, &data
[0]);
225 if(component
& (DEPTH
| STENCIL
))
227 glDisable(GL_STENCIL_TEST
);
230 connection
.resetSelection();
232 glMatrixMode(GL_MODELVIEW
);
234 glEnable(GL_DEPTH_TEST
);
237 /*! Send parts of a view buffer to a Connection
239 \a connection defines the connection to use, \a component which color
240 channels (RGB/RGBA) should be transferred, \a x1, \a y1, \a x2, \a y2
241 (inclusive) define the source area and \a toX and \a toY the lower left
242 corner of the destination area.
244 void ClusterViewBuffer::send(PointConnection
&connection
,
253 UInt32 tx
, ty
, tw
, th
;
259 // Image::PixelFormat imgformat;
261 int imgtranssize
= 0;
263 switch(component
& RGBA
)
267 // imgformat = Image::OSG_RGB_PF;
272 // imgformat = Image::OSG_RGBA_PF;
276 SFATAL
<< "Component combination not supported"
281 // resize image buffer
282 imageData
.resize(_subTileSize
* _subTileSize
* componentCnt
);
284 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
286 for(ty
= y1
; ty
<= y2
; ty
+= _subTileSize
)
288 for(tx
= x1
; tx
<= x2
; tx
+= _subTileSize
)
290 tw
= osgMin(_subTileSize
, x2
+ 1 - tx
);
291 th
= osgMin(_subTileSize
, y2
+ 1 - ty
);
293 connection
.putValue(component
);
294 connection
.putValue(tx
+ toX
);
295 connection
.putValue(ty
+ toY
);
296 connection
.putValue(tw
);
297 connection
.putValue(th
);
299 // =========== send STENCIL =======================================
300 if(component
& STENCIL
)
302 // read stencil buffer
303 data
.resize(tw
* th
);
312 connection
.put(&data
[0], tw
* th
);
315 // =========== send DEPTH =======================================
316 if(component
& DEPTH
)
318 // read stencil buffer
319 data
.resize(tw
* th
* sizeof(float));
320 glReadPixels(tx
, ty
, tw
, th
, GL_DEPTH_COMPONENT
, GL_FLOAT
,
322 connection
.put(&data
[0], tw
* th
* sizeof(float));
325 // =========== send RGBA ========================================
335 pImage
->set(imgformat
, tw
, th
, 1, 1, 1, 0.0,
336 (UChar8
*) &imageData
[0]);
338 // read buffer data into image
339 glReadPixels(tx
, ty
, tw
, th
, glformat
, GL_UNSIGNED_BYTE
,
342 // bug maxsize is not big enugh
343 data
.resize(_imgTransType
->maxBufferSize(*pImage
) + 1000);
344 dataSize
= _imgTransType
->store(*pImage
, (UChar8
*) &data
[0],
346 connection
.putValue(dataSize
);
347 connection
.put(&data
[0], dataSize
);
348 imgtranssize
+= dataSize
;
353 data
.resize(tw
* th
* componentCnt
);
356 glReadPixels(tx
, ty
, tw
, th
, glformat
, GL_UNSIGNED_BYTE
,
359 connection
.putValue(dataSize
);
360 connection
.put(&data
[0], tw
* th
* componentCnt
);
361 imgtranssize
+= tw
* th
* componentCnt
;
370 connection
.putValue(component
);
374 /*! Send parts of a view buffer to a Connection
376 void ClusterViewBuffer::send(PointConnection
&connection
,
386 getBufferHeight(), toX
,
390 /*-------------------------------------------------------------------------*/
393 /*! Set compression type. By default, no compression is used for image
394 * transmission. The given mime type identifies an ImageType e.g. "JPEG".
395 * This image type is used for compression.
398 void ClusterViewBuffer::setImgTransType(const Char8
*mimeType
)
402 _imgTransType
= NULL
;
406 _imgTransType
= ImageFileHandler::the()->getFileType(mimeType
);
410 /*! Set subtile size. The whole buffer is transfered as small subtiles.
411 Increasing or decreasing the subtile size will result in changes to the
412 performance. The best size depends on network package size and the
413 ration between network performance and buffer read/write performance.
416 void ClusterViewBuffer::setSubtileSize(UInt32 size
)
421 /*! Set opengl datatype for rgb tramsmission
424 void ClusterViewBuffer::setRGBADataType(UInt32 type
, UInt32 size
)
426 _rgbaDataType
= type
;
427 _rgbaDataSize
= size
;
430 /*! Set opengl datatype for rgba tramsmission
433 void ClusterViewBuffer::setRGBDataType(UInt32 type
, UInt32 size
)
439 /*! Set opengl datatype for Z-Buffer tramsmission
442 void ClusterViewBuffer::setDepthDataType(UInt32 type
, UInt32 size
)
444 _depthDataType
= type
;
445 _depthDataSize
= size
;
448 /*-------------------------------------------------------------------------*/
454 UInt32
ClusterViewBuffer::getBufferWidth(void)
457 glGetIntegerv(GL_VIEWPORT
, view
);
465 UInt32
ClusterViewBuffer::getBufferHeight(void)
468 glGetIntegerv(GL_VIEWPORT
, view
);