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 100 : static std::string _iAttributeStrings[] = {
38 100 : MAKE_ATTR_STRING(IATTR_HINT_STATISTICS),
39 150 : MAKE_ATTR_STRING(IATTR_HINT_SENDTOKEN)};
40 :
41 100 : static std::string _sAttributeStrings[] = {MAKE_ATTR_STRING(SATTR_DUMP_IMAGE)};
42 : }
43 :
44 : template <class W, class C>
45 1652 : Channel<W, C>::Channel(W* parent)
46 : : _window(parent)
47 1652 : , _context(&_data.nativeContext)
48 : {
49 1652 : memset(_iAttributes, 0xff, IATTR_ALL * sizeof(int32_t));
50 1652 : parent->_addChannel(static_cast<C*>(this));
51 1652 : LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
52 1652 : }
53 :
54 : template <class W, class C>
55 1224 : Channel<W, C>::Channel(const Channel& from)
56 : : Object(from)
57 1224 : , _window(from._window)
58 : , _data(from._data)
59 2448 : , _context(&_data.nativeContext)
60 : {
61 1224 : _window->_addChannel(static_cast<C*>(this));
62 :
63 9792 : for (int i = 0; i < IATTR_ALL; ++i)
64 8568 : _iAttributes[i] = from._iAttributes[i];
65 8568 : for (int i = 0; i < SATTR_ALL; ++i)
66 7344 : _sAttributes[i] = from._sAttributes[i];
67 1224 : LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
68 1224 : }
69 :
70 : template <class W, class C>
71 2872 : void Channel<W, C>::init()
72 : {
73 2872 : notifyViewportChanged();
74 2872 : unsetDirty(DIRTY_VIEWPORT | DIRTY_PIXELVIEWPORT);
75 2872 : }
76 :
77 : template <class W, class C>
78 2872 : Channel<W, C>::~Channel()
79 : {
80 2872 : _window->_removeChannel(static_cast<C*>(this));
81 5744 : }
82 :
83 : template <class W, class C>
84 113400 : VisitorResult Channel<W, C>::accept(Visitor& visitor)
85 : {
86 113400 : return visitor.visit(static_cast<C*>(this));
87 : }
88 :
89 : template <class W, class C>
90 0 : VisitorResult Channel<W, C>::accept(Visitor& visitor) const
91 : {
92 0 : return visitor.visit(static_cast<const C*>(this));
93 : }
94 :
95 : template <class W, class C>
96 18 : void Channel<W, C>::backup()
97 : {
98 18 : Object::backup();
99 18 : _backup = _data;
100 18 : }
101 :
102 : template <class W, class C>
103 0 : void Channel<W, C>::restore()
104 : {
105 0 : _data = _backup;
106 0 : Object::restore();
107 0 : notifyViewportChanged();
108 0 : setDirty(DIRTY_VIEWPORT | DIRTY_PIXELVIEWPORT | DIRTY_MEMBER |
109 : DIRTY_FRUSTUM);
110 0 : }
111 :
112 : template <class W, class C>
113 13 : void Channel<W, C>::serialize(co::DataOStream& os, const uint64_t dirtyBits)
114 : {
115 13 : LBASSERT(dirtyBits == DIRTY_ALL ||
116 : getWindow()->Serializable::isDirty(W::DIRTY_CHANNELS));
117 13 : Object::serialize(os, dirtyBits);
118 13 : if (dirtyBits & DIRTY_ATTRIBUTES)
119 4 : os << co::Array<int32_t>(_iAttributes, IATTR_ALL)
120 8 : << co::Array<std::string>(_sAttributes, SATTR_ALL);
121 13 : if (dirtyBits & DIRTY_VIEWPORT)
122 4 : os << _data.nativeContext.vp << _data.fixedVP;
123 13 : if (dirtyBits & DIRTY_PIXELVIEWPORT)
124 7 : os << _data.nativeContext.pvp << _data.fixedVP;
125 13 : if (dirtyBits & DIRTY_MEMBER)
126 10 : os << _data.nativeContext.view << _data.nativeContext.overdraw;
127 13 : if (dirtyBits & DIRTY_FRUSTUM)
128 4 : os << _data.nativeContext.frustum;
129 13 : if (dirtyBits & DIRTY_CAPABILITIES)
130 4 : os << _data.capabilities;
131 13 : }
132 :
133 : template <class W, class C>
134 7 : void Channel<W, C>::deserialize(co::DataIStream& is, const uint64_t dirtyBits)
135 : {
136 7 : Object::deserialize(is, dirtyBits);
137 7 : if (dirtyBits & DIRTY_ATTRIBUTES)
138 2 : is >> co::Array<int32_t>(_iAttributes, IATTR_ALL) >>
139 : co::Array<std::string>(_sAttributes, SATTR_ALL);
140 7 : if (dirtyBits & DIRTY_VIEWPORT)
141 : {
142 : // Ignore data from master (server) if we have local changes
143 2 : if (!Serializable::isDirty(DIRTY_VIEWPORT) || isMaster())
144 : {
145 2 : is >> _data.nativeContext.vp >> _data.fixedVP;
146 2 : notifyViewportChanged();
147 : }
148 : else // consume unused data
149 0 : is.getRemainingBuffer(sizeof(_data.nativeContext.vp) +
150 : sizeof(_data.fixedVP));
151 : }
152 7 : if (dirtyBits & DIRTY_PIXELVIEWPORT)
153 : {
154 : // Ignore data from master (server) if we have local changes
155 5 : if (!Serializable::isDirty(DIRTY_PIXELVIEWPORT) || isMaster())
156 : {
157 5 : is >> _data.nativeContext.pvp >> _data.fixedVP;
158 5 : notifyViewportChanged();
159 : }
160 : else // consume unused data
161 0 : is.getRemainingBuffer(sizeof(_data.nativeContext.pvp) +
162 : sizeof(_data.fixedVP));
163 : }
164 7 : if (dirtyBits & DIRTY_MEMBER)
165 4 : is >> _data.nativeContext.view >> _data.nativeContext.overdraw;
166 7 : if (dirtyBits & DIRTY_FRUSTUM)
167 2 : is >> _data.nativeContext.frustum;
168 7 : if (dirtyBits & DIRTY_CAPABILITIES)
169 : {
170 2 : is >> _data.capabilities;
171 2 : updateCapabilities();
172 : }
173 7 : }
174 :
175 : template <class W, class C>
176 26479 : void Channel<W, C>::setDirty(const uint64_t dirtyBits)
177 : {
178 26479 : Object::setDirty(dirtyBits);
179 26479 : _window->setDirty(W::DIRTY_CHANNELS);
180 26479 : }
181 :
182 : //----------------------------------------------------------------------
183 : // viewport
184 : //----------------------------------------------------------------------
185 : template <class W, class C>
186 392 : void Channel<W, C>::setPixelViewport(const PixelViewport& pvp)
187 : {
188 392 : LBASSERT(pvp.isValid());
189 392 : if (!pvp.isValid())
190 0 : return;
191 :
192 392 : _data.fixedVP = false;
193 :
194 392 : if (_data.nativeContext.pvp == pvp && _data.nativeContext.vp.hasArea())
195 350 : return;
196 :
197 42 : _data.nativeContext.pvp = pvp;
198 42 : _data.nativeContext.vp.invalidate();
199 :
200 42 : notifyViewportChanged();
201 42 : setDirty(DIRTY_PIXELVIEWPORT);
202 : }
203 :
204 : template <class W, class C>
205 2110 : void Channel<W, C>::setViewport(const Viewport& vp)
206 : {
207 2110 : if (!vp.hasArea())
208 0 : return;
209 :
210 2110 : _data.fixedVP = true;
211 :
212 2110 : if (_data.nativeContext.vp == vp && _data.nativeContext.pvp.hasArea())
213 954 : return;
214 :
215 1156 : _data.nativeContext.vp = vp;
216 1156 : _data.nativeContext.pvp.invalidate();
217 :
218 1156 : notifyViewportChanged();
219 1156 : setDirty(DIRTY_VIEWPORT);
220 : }
221 :
222 : template <class W, class C>
223 4080 : void Channel<W, C>::notifyViewportChanged()
224 : {
225 4080 : if (!_window)
226 906 : return;
227 :
228 4080 : PixelViewport windowPVP = _window->getPixelViewport();
229 4080 : if (!windowPVP.isValid())
230 906 : return;
231 :
232 3174 : windowPVP.x = 0;
233 3174 : windowPVP.y = 0;
234 :
235 3174 : if (_data.fixedVP) // update pixel viewport
236 : {
237 3120 : const PixelViewport oldPVP = _data.nativeContext.pvp;
238 3120 : _data.nativeContext.pvp = windowPVP;
239 3120 : _data.nativeContext.pvp.apply(_data.nativeContext.vp);
240 3120 : if (oldPVP != _data.nativeContext.pvp)
241 2055 : setDirty(DIRTY_PIXELVIEWPORT);
242 : }
243 : else // update viewport
244 : {
245 54 : const Viewport oldVP = _data.nativeContext.vp;
246 54 : _data.nativeContext.vp = _data.nativeContext.pvp / windowPVP;
247 54 : if (oldVP != _data.nativeContext.vp)
248 44 : setDirty(DIRTY_VIEWPORT);
249 : }
250 :
251 3174 : LBVERB << getName() << " viewport update: " << _data.nativeContext.vp << ":"
252 0 : << _data.nativeContext.pvp << std::endl;
253 : }
254 :
255 : template <class W, class C>
256 0 : void Channel<W, C>::setNearFar(const float nearPlane, const float farPlane)
257 : {
258 0 : LBASSERT(_context);
259 0 : if (_data.nativeContext.frustum.nearPlane() != nearPlane ||
260 0 : _data.nativeContext.frustum.farPlane() != farPlane)
261 : {
262 0 : _data.nativeContext.frustum.adjustNearPlane(nearPlane);
263 0 : _data.nativeContext.frustum.farPlane() = farPlane;
264 0 : _data.nativeContext.ortho.nearPlane() = nearPlane;
265 0 : _data.nativeContext.ortho.farPlane() = farPlane;
266 0 : setDirty(DIRTY_FRUSTUM);
267 : }
268 :
269 0 : if (_context == &_data.nativeContext)
270 0 : return;
271 :
272 0 : if (_context->frustum.nearPlane() != nearPlane ||
273 0 : _context->frustum.farPlane() != farPlane)
274 : {
275 0 : _context->frustum.adjustNearPlane(nearPlane);
276 0 : _context->frustum.farPlane() = farPlane;
277 0 : _context->ortho.nearPlane() = nearPlane;
278 0 : _context->ortho.farPlane() = farPlane;
279 : }
280 : }
281 :
282 : template <class W, class C>
283 1300 : void Channel<W, C>::setViewVersion(const co::ObjectVersion& view)
284 : {
285 1300 : if (_data.nativeContext.view == view)
286 1250 : return;
287 50 : LBASSERTINFO(view.identifier != 0 ||
288 : _data.nativeContext.view.version <= view.version,
289 : _data.nativeContext.view << " != " << view);
290 :
291 50 : _data.nativeContext.view = view;
292 50 : setDirty(DIRTY_MEMBER);
293 : }
294 :
295 : template <class W, class C>
296 650 : uint64_t Channel<W, C>::getCapabilities() const
297 : {
298 650 : return _data.capabilities;
299 : }
300 :
301 : template <class W, class C>
302 0 : void Channel<W, C>::setCapabilities(const uint64_t bitmask)
303 : {
304 0 : if (bitmask == _data.capabilities)
305 0 : return;
306 :
307 0 : _data.capabilities = bitmask;
308 0 : setDirty(DIRTY_CAPABILITIES);
309 : }
310 :
311 : template <class W, class C>
312 118 : void Channel<W, C>::setOverdraw(const Vector4i& overdraw)
313 : {
314 118 : if (_data.nativeContext.overdraw == overdraw)
315 118 : return;
316 0 : _data.nativeContext.overdraw = overdraw;
317 0 : setDirty(DIRTY_MEMBER);
318 : }
319 :
320 : template <class W, class C>
321 0 : ChannelPath Channel<W, C>::getPath() const
322 : {
323 0 : const W* window = getWindow();
324 0 : LBASSERT(window);
325 0 : ChannelPath path(window->getPath());
326 :
327 0 : const typename W::Channels& channels = window->getChannels();
328 : typename W::Channels::const_iterator i =
329 0 : std::find(channels.begin(), channels.end(), this);
330 0 : LBASSERT(i != channels.end());
331 0 : path.channelIndex = std::distance(channels.begin(), i);
332 0 : return path;
333 : }
334 :
335 : template <class W, class C>
336 9 : int32_t Channel<W, C>::getIAttribute(const IAttribute attr) const
337 : {
338 9 : LBASSERT(attr < IATTR_ALL);
339 9 : return _iAttributes[attr];
340 : }
341 :
342 : template <class W, class C>
343 1 : const std::string& Channel<W, C>::getSAttribute(const SAttribute attr) const
344 : {
345 1 : LBASSERT(attr < SATTR_ALL);
346 1 : return _sAttributes[attr];
347 : }
348 :
349 : template <class W, class C>
350 1222 : const std::string& Channel<W, C>::getIAttributeString(const IAttribute attr)
351 : {
352 1222 : return _iAttributeStrings[attr];
353 : }
354 :
355 : template <class W, class C>
356 612 : const std::string& Channel<W, C>::getSAttributeString(const SAttribute attr)
357 : {
358 612 : return _sAttributeStrings[attr];
359 : }
360 :
361 : template <class W, class C>
362 1462 : std::ostream& operator<<(std::ostream& os, const Channel<W, C>& channel)
363 : {
364 1462 : if (channel.omitOutput())
365 632 : return os;
366 :
367 830 : os << lunchbox::disableFlush << lunchbox::disableHeader << "channel"
368 : << std::endl;
369 830 : os << "{" << std::endl << lunchbox::indent;
370 :
371 830 : const std::string& name = channel.getName();
372 830 : if (!name.empty())
373 830 : os << "name \"" << name << "\"" << std::endl;
374 :
375 830 : const Viewport& vp = channel.getViewport();
376 830 : const PixelViewport& pvp = channel.getPixelViewport();
377 830 : if (vp.hasArea() && channel.hasFixedViewport())
378 : {
379 824 : if (pvp.hasArea())
380 368 : os << "viewport " << pvp << std::endl;
381 824 : os << "viewport " << vp << std::endl;
382 : }
383 6 : else if (pvp.hasArea() && !channel.hasFixedViewport())
384 : {
385 6 : if (vp.hasArea())
386 6 : os << "viewport " << vp << std::endl;
387 6 : os << "viewport " << pvp << std::endl;
388 : }
389 :
390 1660 : os << lunchbox::exdent << "}" << std::endl
391 830 : << lunchbox::enableHeader << lunchbox::enableFlush;
392 :
393 830 : return os;
394 : }
395 : }
396 : }
|