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