Line data Source code
1 :
2 : /* Copyright (c) 2007-2014, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "compoundUpdateOutputVisitor.h"
20 :
21 : #include "config.h"
22 : #include "frame.h"
23 : #include "frameData.h"
24 : #include "server.h"
25 : #include "tileQueue.h"
26 : #include "window.h"
27 :
28 : #include "tiles/zigzagStrategy.h"
29 :
30 : #include <eq/client/log.h>
31 : #include <eq/fabric/iAttribute.h>
32 : #include <eq/fabric/tile.h>
33 :
34 : namespace eq
35 : {
36 : namespace server
37 : {
38 72 : CompoundUpdateOutputVisitor::CompoundUpdateOutputVisitor(
39 : const uint32_t frameNumber )
40 72 : : _frameNumber( frameNumber )
41 72 : {}
42 :
43 171 : VisitorResult CompoundUpdateOutputVisitor::visit( Compound* compound )
44 : {
45 171 : if( !compound->isActive( ))
46 68 : return TRAVERSE_PRUNE;
47 :
48 103 : _updateQueues( compound );
49 103 : _updateFrames( compound );
50 103 : _updateSwapBarriers( compound );
51 :
52 103 : return TRAVERSE_CONTINUE;
53 : }
54 :
55 103 : void CompoundUpdateOutputVisitor::_updateQueues( Compound* compound )
56 : {
57 103 : const TileQueues& queues = compound->getOutputTileQueues();
58 103 : for( TileQueuesCIter i = queues.begin(); i != queues.end(); ++i )
59 : {
60 : //----- Check uniqueness of output queue name
61 0 : TileQueue* queue = *i;
62 0 : const std::string& name = queue->getName();
63 :
64 0 : if( _outputTileQueues.find( name ) != _outputTileQueues.end( ))
65 : {
66 0 : LBWARN << "Multiple output queues of the same name are unsupported"
67 0 : << ", ignoring output queue " << name << std::endl;
68 0 : queue->unsetData();
69 0 : continue;
70 : }
71 :
72 0 : queue->cycleData( _frameNumber, compound );
73 :
74 : //----- Generate tile task commands
75 0 : _generateTiles( queue, compound );
76 0 : _outputTileQueues[name] = queue;
77 : }
78 103 : }
79 :
80 103 : void CompoundUpdateOutputVisitor::_updateFrames( Compound* compound )
81 : {
82 103 : const Frames& outputFrames = compound->getOutputFrames();
83 103 : if( outputFrames.empty( ))
84 94 : compound->unsetInheritTask( fabric::TASK_READBACK );
85 :
86 103 : const Channel* channel = compound->getChannel();
87 103 : if( !compound->testInheritTask( fabric::TASK_READBACK ) || !channel )
88 197 : return;
89 :
90 18 : for( FramesCIter i = outputFrames.begin(); i != outputFrames.end(); ++i )
91 : {
92 : //----- Check uniqueness of output frame name
93 9 : Frame* frame = *i;
94 9 : const std::string& name = frame->getName();
95 :
96 9 : if( _outputFrames.find( name ) != _outputFrames.end())
97 : {
98 0 : LBWARN << "Multiple output frames of the same name are unsupported"
99 0 : << ", ignoring output frame " << name << std::endl;
100 0 : frame->unsetData();
101 0 : continue;
102 : }
103 :
104 : //----- compute readback area
105 9 : const Viewport& frameVP = frame->getViewport();
106 9 : const PixelViewport& inheritPVP = compound->getInheritPixelViewport();
107 9 : PixelViewport framePVP( inheritPVP );
108 9 : framePVP.apply( frameVP );
109 :
110 9 : if( !framePVP.hasArea( )) // output frame has no pixels
111 : {
112 0 : LBINFO << "Skipping output frame " << name << ", no pixels"
113 0 : << std::endl;
114 0 : frame->unsetData();
115 0 : continue;
116 : }
117 :
118 : //----- Create new frame datas
119 : // * one frame data used for each eye pass
120 : // * data is set only on master frame data (will copy to all others)
121 9 : frame->cycleData( _frameNumber, compound );
122 9 : FrameData* frameData = frame->getMasterData();
123 9 : LBASSERT( frameData );
124 :
125 9 : LBLOG( LOG_ASSEMBLY )
126 0 : << lunchbox::disableFlush << "Output frame \"" << name << "\" id "
127 9 : << frame->getID() << " v" << frame->getVersion()+1
128 0 : << " data id " << frameData->getID() << " v"
129 9 : << frameData->getVersion() + 1 << " on channel \""
130 0 : << channel->getName() << "\" tile pos " << framePVP.x << ", "
131 27 : << framePVP.y;
132 :
133 : //----- Set frame data parameters:
134 : // 1) offset is position wrt destination view, used only by input frames
135 9 : const bool tiled = !compound->getInputTileQueues().empty();
136 : frameData->setOffset( tiled ? Vector2i( 0 , 0 ) :
137 9 : Vector2i( framePVP.x, framePVP.y ));
138 :
139 : // 2) pvp is area within channel
140 9 : framePVP.x = static_cast< int32_t >( frameVP.x * inheritPVP.w );
141 9 : framePVP.y = static_cast< int32_t >( frameVP.y * inheritPVP.h );
142 9 : frameData->setPixelViewport( framePVP );
143 :
144 : // 3) image buffers and storage type
145 9 : uint32_t buffers = frame->getBuffers();
146 :
147 9 : frameData->setType( frame->getType() );
148 : frameData->setBuffers( buffers == eq::Frame::BUFFER_UNDEFINED ?
149 9 : compound->getInheritBuffers() : buffers );
150 :
151 : // 4) (source) render context
152 9 : frameData->setRange( compound->getInheritRange( ));
153 9 : frameData->setPixel( compound->getInheritPixel( ));
154 9 : frameData->setSubPixel( compound->getInheritSubPixel( ));
155 9 : frameData->setPeriod( compound->getInheritPeriod( ));
156 9 : frameData->setPhase( compound->getInheritPhase( ));
157 :
158 : //----- Set frame parameters:
159 : // 1) offset is position wrt window, i.e., the channel position
160 9 : if( compound->getInheritChannel() == channel )
161 0 : frame->setOffset( Vector2i( inheritPVP.x, inheritPVP.y ));
162 : else
163 : {
164 9 : const PixelViewport& nativePVP = channel->getPixelViewport();
165 9 : frame->setOffset( Vector2i( nativePVP.x, nativePVP.y ));
166 : }
167 :
168 : // 2) zoom
169 9 : _updateZoom( compound, frame );
170 :
171 : //----- Commit
172 9 : frame->commitData();
173 :
174 9 : _outputFrames[name] = frame;
175 9 : LBLOG( LOG_ASSEMBLY )
176 0 : << " buffers " << frameData->getBuffers() << " read area "
177 0 : << framePVP << " readback " << frame->getZoom() << " assemble "
178 9 : << frameData->getZoom()<< lunchbox::enableFlush << std::endl ;
179 : }
180 : }
181 :
182 0 : void CompoundUpdateOutputVisitor::_generateTiles( TileQueue* queue,
183 : Compound* compound )
184 : {
185 0 : const Vector2i& tileSize = queue->getTileSize();
186 0 : const PixelViewport pvp = compound->getInheritPixelViewport();
187 0 : if( !pvp.hasArea( ))
188 0 : return;
189 :
190 0 : const Vector2i dim( pvp.w / tileSize.x() + ((pvp.w%tileSize.x()) ? 1 : 0),
191 0 : pvp.h / tileSize.y() + ((pvp.h%tileSize.y()) ? 1 : 0));
192 :
193 0 : std::vector< Vector2i > tiles;
194 0 : tiles.reserve( dim.x() * dim.y() );
195 :
196 0 : tiles::generateZigzag( tiles, dim );
197 0 : _addTilesToQueue( queue, compound, tiles );
198 : }
199 :
200 0 : void CompoundUpdateOutputVisitor::_addTilesToQueue( TileQueue* queue,
201 : Compound* compound,
202 : const std::vector< Vector2i >& tiles )
203 : {
204 :
205 0 : const Vector2i& tileSize = queue->getTileSize();
206 0 : PixelViewport pvp = compound->getInheritPixelViewport();
207 0 : const double xFraction = 1.0 / pvp.w;
208 0 : const double yFraction = 1.0 / pvp.h;
209 :
210 0 : for( std::vector< Vector2i >::const_iterator i = tiles.begin();
211 0 : i != tiles.end(); ++i )
212 : {
213 0 : const Vector2i& tile = *i;
214 0 : PixelViewport tilePVP( tile.x() * tileSize.x(), tile.y() * tileSize.y(),
215 0 : tileSize.x(), tileSize.y( ));
216 :
217 0 : if ( tilePVP.x + tileSize.x() > pvp.w ) // no full tile
218 0 : tilePVP.w = pvp.w - tilePVP.x;
219 :
220 0 : if ( tilePVP.y + tileSize.y() > pvp.h ) // no full tile
221 0 : tilePVP.h = pvp.h - tilePVP.y;
222 :
223 0 : const Viewport tileVP( tilePVP.x * xFraction, tilePVP.y * yFraction,
224 0 : tilePVP.w * xFraction, tilePVP.h * yFraction );
225 :
226 0 : for( fabric::Eye eye = fabric::EYE_CYCLOP; eye < fabric::EYES_ALL;
227 0 : eye = fabric::Eye(eye<<1) )
228 : {
229 0 : if ( !(compound->getInheritEyes() & eye) ||
230 0 : !compound->isInheritActive( eye ))
231 : {
232 0 : continue;
233 : }
234 :
235 0 : Tile tileItem( tilePVP, tileVP );
236 : compound->computeTileFrustum( tileItem.frustum, eye, tileItem.vp,
237 0 : false );
238 : compound->computeTileFrustum( tileItem.ortho, eye, tileItem.vp,
239 0 : true );
240 0 : queue->addTile( tileItem, eye );
241 0 : }
242 : }
243 0 : }
244 :
245 9 : void CompoundUpdateOutputVisitor::_updateZoom( const Compound* compound,
246 : Frame* frame )
247 : {
248 9 : Zoom zoom = frame->getNativeZoom();
249 9 : Zoom zoom_1;
250 :
251 9 : if( !zoom.isValid( )) // if zoom is not set, auto-calculate from parent
252 : {
253 9 : zoom_1 = compound->getInheritZoom();
254 9 : LBASSERT( zoom_1.isValid( ));
255 9 : zoom.x() = 1.0f / zoom_1.x();
256 9 : zoom.y() = 1.0f / zoom_1.y();
257 : }
258 : else
259 : {
260 0 : zoom_1.x() = 1.0f / zoom.x();
261 0 : zoom_1.y() = 1.0f / zoom.y();
262 : }
263 :
264 9 : if( frame->getType( ) == eq::Frame::TYPE_TEXTURE )
265 : {
266 0 : FrameData* frameData = frame->getMasterData();
267 0 : frameData->setZoom( zoom_1 ); // textures are zoomed by input frame
268 0 : frame->setZoom( Zoom::NONE );
269 : }
270 : else
271 : {
272 9 : Zoom inputZoom;
273 : /* Output frames downscale pixel data during readback, and upscale it on
274 : * the input frame by setting the input frame's inherit zoom. */
275 9 : if( zoom.x() > 1.0f )
276 : {
277 0 : inputZoom.x() = zoom_1.x();
278 0 : zoom.x() = 1.f;
279 : }
280 9 : if( zoom.y() > 1.0f )
281 : {
282 0 : inputZoom.y() = zoom_1.y();
283 0 : zoom.y() = 1.f;
284 : }
285 :
286 9 : FrameData* frameData = frame->getMasterData();
287 9 : frameData->setZoom( inputZoom );
288 9 : frame->setZoom( zoom );
289 : }
290 9 : }
291 :
292 103 : void CompoundUpdateOutputVisitor::_updateSwapBarriers( Compound* compound )
293 : {
294 103 : SwapBarrierConstPtr swapBarrier = compound->getSwapBarrier();
295 103 : if( !swapBarrier )
296 103 : return;
297 :
298 0 : Window* window = compound->getWindow();
299 0 : LBASSERT( window );
300 0 : if( !window )
301 0 : return;
302 :
303 0 : if( swapBarrier->isNvSwapBarrier( ))
304 : {
305 0 : if( !window->hasNVSwapBarrier( ))
306 : {
307 0 : const std::string name( "__NV_swap_group_protection_barrier__" );
308 0 : _swapBarriers[name] =
309 0 : window->joinNVSwapBarrier( swapBarrier, _swapBarriers[name] );
310 : }
311 : }
312 : else
313 : {
314 0 : const std::string& name = swapBarrier->getName();
315 0 : _swapBarriers[name] = window->joinSwapBarrier( _swapBarriers[name] );
316 0 : }
317 : }
318 :
319 : }
320 27 : }
321 :
|