Line data Source code
1 :
2 : /* Copyright (c) 2010-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : * Julio Delgado Mangas <julio.delgadomangas@epfl.ch>
5 : * Enrique <egparedes@ifi.uzh.ch>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "channel.h"
22 :
23 : #include "leafVisitor.h"
24 : #include "log.h"
25 : #include "task.h"
26 :
27 : #include <co/dataIStream.h>
28 : #include <co/dataOStream.h>
29 :
30 : namespace eq
31 : {
32 : namespace fabric
33 : {
34 : namespace
35 : {
36 : #define MAKE_ATTR_STRING( attr ) ( std::string("EQ_CHANNEL_") + #attr )
37 140 : static std::string _iAttributeStrings[] = {
38 : MAKE_ATTR_STRING( IATTR_HINT_STATISTICS ),
39 : MAKE_ATTR_STRING( IATTR_HINT_SENDTOKEN )
40 70 : };
41 :
42 140 : static std::string _sAttributeStrings[] = {
43 : MAKE_ATTR_STRING( SATTR_DUMP_IMAGE )
44 70 : };
45 : }
46 :
47 2461 : template< class W, class C > Channel< W, C >::Channel( W* parent )
48 : : _window( parent )
49 : , _context( &_data.nativeContext )
50 2461 : , _maxSize( Vector2i::ZERO )
51 : {
52 2461 : memset( _iAttributes, 0xff, IATTR_ALL * sizeof( int32_t ));
53 2461 : parent->_addChannel( static_cast< C* >( this ));
54 2461 : LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
55 2461 : }
56 :
57 1174 : template< class W, class C > Channel< W, C >::Channel( const Channel& from )
58 : : Object( from )
59 : , _window( from._window )
60 : , _data( from._data )
61 : , _context( &_data.nativeContext )
62 1174 : , _maxSize( from._maxSize )
63 : {
64 1174 : _window->_addChannel( static_cast< C* >( this ));
65 :
66 9392 : for( int i = 0; i < IATTR_ALL; ++i )
67 8218 : _iAttributes[i] = from._iAttributes[i];
68 8218 : for( int i = 0; i < SATTR_ALL; ++i )
69 7044 : _sAttributes[i] = from._sAttributes[i];
70 1174 : LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
71 1174 : }
72 :
73 2825 : template< class W, class C > void Channel< W, C >::init()
74 : {
75 2825 : notifyViewportChanged();
76 2825 : unsetDirty( DIRTY_VIEWPORT );
77 2825 : }
78 :
79 2821 : template< class W, class C > Channel< W, C >::~Channel()
80 : {
81 2821 : _window->_removeChannel( static_cast< C* >( this ));
82 5642 : }
83 :
84 : template< class W, class C >
85 103682 : VisitorResult Channel< W, C >::accept( Visitor& visitor )
86 : {
87 103682 : return visitor.visit( static_cast< C* >( this ));
88 : }
89 :
90 : template< class W, class C >
91 0 : VisitorResult Channel< W, C >::accept( Visitor& visitor ) const
92 : {
93 0 : return visitor.visit( static_cast< const C* >( this ));
94 : }
95 :
96 : template< class W, class C >
97 8 : void Channel< W, C >::backup()
98 : {
99 8 : Object::backup();
100 8 : _backup = _data;
101 8 : }
102 :
103 : template< class W, class C >
104 8 : void Channel< W, C >::restore()
105 : {
106 8 : _data = _backup;
107 8 : Object::restore();
108 8 : notifyViewportChanged();
109 8 : setDirty( DIRTY_VIEWPORT | DIRTY_MEMBER | DIRTY_FRUSTUM );
110 8 : }
111 :
112 : template< class W, class C >
113 2 : void Channel< W, C >::serialize( co::DataOStream& os, const uint64_t dirtyBits )
114 : {
115 2 : LBASSERT( dirtyBits == DIRTY_ALL ||
116 : getWindow()->Serializable::isDirty( W::DIRTY_CHANNELS ));
117 2 : Object::serialize( os, dirtyBits );
118 2 : if( dirtyBits & DIRTY_ATTRIBUTES )
119 2 : os << co::Array< int32_t >( _iAttributes, IATTR_ALL )
120 4 : << co::Array< std::string >( _sAttributes, SATTR_ALL );
121 2 : if( dirtyBits & DIRTY_VIEWPORT )
122 4 : os << _data.nativeContext.vp << _data.nativeContext.pvp
123 4 : << _data.fixedVP << _maxSize;
124 2 : if( dirtyBits & DIRTY_MEMBER )
125 2 : os << _data.nativeContext.view << _data.nativeContext.overdraw;
126 2 : if( dirtyBits & DIRTY_FRUSTUM )
127 2 : os << _data.nativeContext.frustum;
128 2 : if( dirtyBits & DIRTY_CAPABILITIES )
129 2 : os << _data.capabilities;
130 2 : }
131 :
132 : template< class W, class C >
133 1 : void Channel< W, C >::deserialize( co::DataIStream& is,
134 : const uint64_t dirtyBits )
135 : {
136 1 : Object::deserialize( is, dirtyBits );
137 1 : if( dirtyBits & DIRTY_ATTRIBUTES )
138 1 : is >> co::Array< int32_t >( _iAttributes, IATTR_ALL )
139 2 : >> co::Array< std::string >( _sAttributes, SATTR_ALL );
140 1 : if( dirtyBits & DIRTY_VIEWPORT )
141 : {
142 : // Ignore data from master (server) if we have local changes
143 1 : if( !Serializable::isDirty( DIRTY_VIEWPORT ) || isMaster( ))
144 : {
145 2 : is >> _data.nativeContext.vp >> _data.nativeContext.pvp
146 2 : >> _data.fixedVP >> _maxSize;
147 1 : notifyViewportChanged();
148 : }
149 : else // consume unused data
150 0 : is.getRemainingBuffer( sizeof( _data.nativeContext.vp ) +
151 : sizeof( _data.nativeContext.pvp ) +
152 0 : sizeof( _data.fixedVP ) +sizeof( _maxSize ));
153 : }
154 1 : if( dirtyBits & DIRTY_MEMBER )
155 1 : is >> _data.nativeContext.view >> _data.nativeContext.overdraw;
156 1 : if( dirtyBits & DIRTY_FRUSTUM )
157 1 : is >> _data.nativeContext.frustum;
158 1 : if( dirtyBits & DIRTY_CAPABILITIES )
159 : {
160 1 : is >> _data.capabilities;
161 1 : updateCapabilities();
162 : }
163 1 : }
164 :
165 : template< class W, class C >
166 26378 : void Channel< W, C >::setDirty( const uint64_t dirtyBits )
167 : {
168 26378 : Object::setDirty( dirtyBits );
169 26378 : _window->setDirty( W::DIRTY_CHANNELS );
170 26378 : }
171 :
172 : //----------------------------------------------------------------------
173 : // viewport
174 : //----------------------------------------------------------------------
175 : template< class W, class C >
176 362 : void Channel< W, C >::setPixelViewport( const PixelViewport& pvp )
177 : {
178 362 : LBASSERT( pvp.isValid( ));
179 362 : if( !pvp.isValid( ))
180 0 : return;
181 :
182 362 : _data.fixedVP = false;
183 :
184 362 : if( _data.nativeContext.pvp == pvp && _data.nativeContext.vp.hasArea( ))
185 320 : return;
186 :
187 42 : _data.nativeContext.pvp = pvp;
188 42 : _data.nativeContext.vp.invalidate();
189 :
190 42 : notifyViewportChanged();
191 42 : setDirty( DIRTY_VIEWPORT );
192 : }
193 :
194 : template< class W, class C >
195 2060 : void Channel< W, C >::setViewport( const Viewport& vp )
196 : {
197 2060 : if( !vp.hasArea( ))
198 0 : return;
199 :
200 2060 : _data.fixedVP = true;
201 :
202 2060 : if( _data.nativeContext.vp == vp && _data.nativeContext.pvp.hasArea( ))
203 890 : return;
204 :
205 1170 : _data.nativeContext.vp = vp;
206 1170 : _data.nativeContext.pvp.invalidate();
207 :
208 1170 : notifyViewportChanged();
209 1170 : setDirty( DIRTY_VIEWPORT );
210 : }
211 :
212 : template< class W, class C >
213 4062 : void Channel< W, C >::notifyViewportChanged()
214 : {
215 4062 : if( !_window )
216 984 : return;
217 :
218 4062 : PixelViewport windowPVP = _window->getPixelViewport();
219 4062 : if( !windowPVP.isValid( ))
220 984 : return;
221 :
222 3078 : windowPVP.x = 0;
223 3078 : windowPVP.y = 0;
224 :
225 3078 : if( _data.fixedVP ) // update pixel viewport
226 : {
227 3024 : const PixelViewport oldPVP = _data.nativeContext.pvp;
228 3024 : _data.nativeContext.pvp = windowPVP;
229 3024 : _data.nativeContext.pvp.apply( _data.nativeContext.vp );
230 3024 : if( oldPVP != _data.nativeContext.pvp )
231 1992 : setDirty( DIRTY_VIEWPORT );
232 : }
233 : else // update viewport
234 : {
235 54 : const Viewport oldVP = _data.nativeContext.vp;
236 54 : _data.nativeContext.vp = _data.nativeContext.pvp / windowPVP;
237 54 : if( oldVP != _data.nativeContext.vp )
238 44 : setDirty( DIRTY_VIEWPORT );
239 : }
240 :
241 3078 : LBVERB << getName() << " viewport update: " << _data.nativeContext.vp << ":"
242 0 : << _data.nativeContext.pvp << std::endl;
243 : }
244 :
245 : template< class W, class C >
246 0 : void Channel< W, C >::setNearFar( const float nearPlane, const float farPlane )
247 : {
248 0 : LBASSERT( _context );
249 0 : if( _data.nativeContext.frustum.nearPlane() != nearPlane ||
250 0 : _data.nativeContext.frustum.farPlane() != farPlane )
251 : {
252 0 : _data.nativeContext.frustum.adjustNearPlane( nearPlane );
253 0 : _data.nativeContext.frustum.farPlane() = farPlane;
254 0 : _data.nativeContext.ortho.nearPlane() = nearPlane;
255 0 : _data.nativeContext.ortho.farPlane() = farPlane;
256 0 : setDirty( DIRTY_FRUSTUM );
257 : }
258 :
259 0 : if( _context == &_data.nativeContext )
260 0 : return;
261 :
262 0 : if( _context->frustum.nearPlane() != nearPlane ||
263 0 : _context->frustum.farPlane() != farPlane )
264 : {
265 0 : _context->frustum.adjustNearPlane( nearPlane );
266 0 : _context->frustum.farPlane() = farPlane;
267 0 : _context->ortho.nearPlane() = nearPlane;
268 0 : _context->ortho.farPlane() = farPlane;
269 : }
270 : }
271 :
272 : template< class W, class C >
273 1196 : void Channel< W, C >::setViewVersion( const co::ObjectVersion& view )
274 : {
275 1196 : if( _data.nativeContext.view == view )
276 2382 : return;
277 10 : LBASSERTINFO( view.identifier != 0 ||
278 : _data.nativeContext.view.version <= view.version,
279 : _data.nativeContext.view << " != " << view );
280 :
281 10 : _data.nativeContext.view = view;
282 10 : setDirty( DIRTY_MEMBER );
283 : }
284 :
285 : template< class W, class C >
286 2 : uint64_t Channel< W, C >::getCapabilities() const
287 : {
288 2 : return _data.capabilities;
289 : }
290 :
291 : template< class W, class C >
292 0 : void Channel< W, C >::setCapabilities( const uint64_t bitmask )
293 : {
294 0 : if ( bitmask == _data.capabilities )
295 0 : return;
296 :
297 0 : _data.capabilities = bitmask;
298 0 : setDirty( DIRTY_CAPABILITIES );
299 : }
300 :
301 : template< class W, class C >
302 0 : void Channel< W, C >::setMaxSize( const Vector2i& size )
303 : {
304 0 : _maxSize = size;
305 0 : setDirty( DIRTY_VIEWPORT );
306 0 : }
307 :
308 : template< class W, class C >
309 4 : void Channel< W, C >::setOverdraw( const Vector4i& overdraw )
310 : {
311 4 : if( _data.nativeContext.overdraw == overdraw )
312 8 : return;
313 0 : _data.nativeContext.overdraw = overdraw;
314 0 : setDirty( DIRTY_MEMBER );
315 : }
316 :
317 : template< class W, class C >
318 0 : ChannelPath Channel< W, C >::getPath() const
319 : {
320 0 : const W* window = getWindow();
321 0 : LBASSERT( window );
322 0 : ChannelPath path( window->getPath( ));
323 :
324 0 : const typename W::Channels& channels = window->getChannels();
325 : typename W::Channels::const_iterator i = std::find( channels.begin(),
326 0 : channels.end(), this );
327 0 : LBASSERT( i != channels.end( ));
328 0 : path.channelIndex = std::distance( channels.begin(), i );
329 0 : return path;
330 : }
331 :
332 :
333 : template< class W, class C >
334 0 : int32_t Channel< W, C >::getIAttribute( const IAttribute attr ) const
335 : {
336 0 : LBASSERT( attr < IATTR_ALL );
337 0 : return _iAttributes[ attr ];
338 : }
339 :
340 : template< class W, class C >
341 0 : const std::string& Channel< W, C >::getSAttribute( const SAttribute attr ) const
342 : {
343 0 : LBASSERT( attr < SATTR_ALL );
344 0 : return _sAttributes[ attr ];
345 : }
346 :
347 : template< class W, class C >
348 1362 : const std::string& Channel< W, C >::getIAttributeString( const IAttribute attr )
349 : {
350 1362 : return _iAttributeStrings[attr];
351 : }
352 :
353 : template< class W, class C >
354 682 : const std::string& Channel< W, C >::getSAttributeString( const SAttribute attr )
355 : {
356 682 : return _sAttributeStrings[attr];
357 : }
358 :
359 : template< class W, class C >
360 1414 : std::ostream& operator << ( std::ostream& os,
361 : const Channel< W, C >& channel)
362 : {
363 1414 : if( channel.omitOutput( ))
364 588 : return os;
365 :
366 826 : os << lunchbox::disableFlush << lunchbox::disableHeader << "channel"
367 : << std::endl;
368 826 : os << "{" << std::endl << lunchbox::indent;
369 :
370 826 : const std::string& name = channel.getName();
371 826 : if( !name.empty( ))
372 826 : os << "name \"" << name << "\"" << std::endl;
373 :
374 826 : const Viewport& vp = channel.getViewport();
375 826 : const PixelViewport& pvp = channel.getPixelViewport();
376 826 : if( vp.hasArea() && channel.hasFixedViewport( ))
377 : {
378 820 : if( pvp.hasArea( ))
379 338 : os << "viewport " << pvp << std::endl;
380 820 : os << "viewport " << vp << std::endl;
381 : }
382 6 : else if( pvp.hasArea() && !channel.hasFixedViewport( ))
383 : {
384 6 : if( vp.hasArea( ))
385 6 : os << "viewport " << vp << std::endl;
386 6 : os << "viewport " << pvp << std::endl;
387 : }
388 :
389 826 : os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
390 : << lunchbox::enableFlush;
391 :
392 826 : return os;
393 : }
394 :
395 : }
396 : }
|