Line data Source code
1 :
2 : /* Copyright (c) 2012-2017, Stefan Eilemann <eile@eyescale.ch>
3 : * Julio Delgado Mangas <julio.delgadomangas@epfl.ch>
4 : * Daniel Nachbaur <danielnachbaur@gmail.com>
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 : #include "../image.h"
22 : #include "../resultImageListener.h"
23 : #include "fileFrameWriter.h"
24 :
25 : #ifdef EQUALIZER_USE_DEFLECT
26 : #include "../deflect/proxy.h"
27 : #endif
28 :
29 : namespace eq
30 : {
31 : namespace detail
32 : {
33 : enum State
34 : {
35 : STATE_STOPPED,
36 : STATE_INITIALIZING,
37 : STATE_RUNNING,
38 : STATE_FAILED
39 : };
40 :
41 : class Channel
42 : {
43 : public:
44 2 : Channel()
45 2 : : state(STATE_STOPPED)
46 : #ifdef EQUALIZER_USE_DEFLECT
47 : , _deflectProxy(0)
48 : #endif
49 2 : , _updateFrameBuffer(false)
50 : {
51 4 : lunchbox::RNG rng;
52 1 : color.r() = rng.get<uint8_t>();
53 2 : color.g() = rng.get<uint8_t>();
54 2 : color.b() = rng.get<uint8_t>();
55 1 : }
56 :
57 2 : ~Channel() { statistics->clear(); }
58 0 : void addResultImageListener(ResultImageListener* listener)
59 : {
60 0 : LBASSERT(std::find(resultImageListeners.begin(),
61 : resultImageListeners.end(),
62 : listener) == resultImageListeners.end());
63 :
64 0 : resultImageListeners.push_back(listener);
65 0 : }
66 :
67 1 : void removeResultImageListener(ResultImageListener* listener)
68 : {
69 : ResultImageListeners::iterator i =
70 : std::find(resultImageListeners.begin(), resultImageListeners.end(),
71 1 : listener);
72 1 : if (i != resultImageListeners.end())
73 0 : resultImageListeners.erase(i);
74 1 : }
75 :
76 1 : void frameViewFinish(eq::Channel& channel)
77 : {
78 1 : if (channel.getSAttribute(channel.SATTR_DUMP_IMAGE).empty())
79 1 : removeResultImageListener(&frameWriter);
80 : else
81 : {
82 : ResultImageListeners::iterator i =
83 : std::find(resultImageListeners.begin(),
84 0 : resultImageListeners.end(), &frameWriter);
85 0 : if (i == resultImageListeners.end())
86 0 : addResultImageListener(&frameWriter);
87 : }
88 :
89 : #ifdef EQUALIZER_USE_DEFLECT
90 1 : if (_deflectProxy && !_deflectProxy->isRunning())
91 : {
92 0 : delete _deflectProxy;
93 0 : _deflectProxy = 0;
94 : }
95 : #endif
96 :
97 1 : eq::View* view = channel.getView();
98 1 : eq::Frame::Buffer buffers = view->getScreenshotBuffers();
99 1 : if (!resultImageListeners.empty())
100 0 : buffers |= eq::Frame::Buffer::color;
101 :
102 1 : if (buffers == eq::Frame::Buffer::none)
103 1 : return;
104 :
105 0 : downloadFramebuffer(channel, buffers);
106 0 : for (ResultImageListener* listener : resultImageListeners)
107 0 : listener->notifyNewImage(channel, framebufferImage);
108 0 : _finishImageListeners = true;
109 :
110 0 : if (view->getScreenshotBuffers() != eq::Frame::Buffer::none)
111 : {
112 0 : view->sendScreenshotEvent(channel.getViewport(),
113 : channel.getPipe()->getCurrentFrame(),
114 0 : framebufferImage);
115 : }
116 : }
117 :
118 2 : void frameFinish()
119 : {
120 2 : if (_finishImageListeners)
121 0 : for (ResultImageListener* listener : resultImageListeners)
122 0 : listener->notifyFinishFrame();
123 2 : _finishImageListeners = false;
124 2 : }
125 :
126 0 : void downloadFramebuffer(eq::Channel& channel,
127 : const eq::Frame::Buffer buffers)
128 : {
129 0 : framebufferImage.setAlphaUsage(true);
130 0 : framebufferImage.setQuality(eq::Frame::Buffer::color, 1.0f);
131 0 : framebufferImage.setStorageType(eq::Frame::TYPE_MEMORY);
132 0 : framebufferImage.setInternalFormat(eq::Frame::Buffer::color, GL_RGBA);
133 :
134 0 : if (buffers & eq::Frame::Buffer::color)
135 0 : framebufferImage.startReadback(eq::Frame::Buffer::color,
136 : channel.getPixelViewport(),
137 : channel.getContext(),
138 : channel.getZoom(),
139 0 : channel.getObjectManager());
140 :
141 0 : if (buffers & eq::Frame::Buffer::depth)
142 0 : framebufferImage.startReadback(eq::Frame::Buffer::depth,
143 : channel.getPixelViewport(),
144 : channel.getContext(),
145 : channel.getZoom(),
146 0 : channel.getObjectManager());
147 :
148 0 : framebufferImage.finishReadback(channel.glewGetContext());
149 0 : }
150 :
151 : /** The configInit/configExit state. */
152 : State state;
153 :
154 : /** A random, unique color for this channel. */
155 : Vector3ub color;
156 :
157 : typedef std::vector<Statistic> Statistics;
158 8 : struct FrameStatistics
159 : {
160 : Statistics data; //!< all events for one frame
161 : eq::Viewport region; //!< from draw for equalizers
162 : /** reference count by pipe and transmit thread */
163 : lunchbox::a_int32_t used;
164 : };
165 :
166 : typedef std::vector<FrameStatistics> StatisticsRB;
167 : typedef StatisticsRB::const_iterator StatisticsRBCIter;
168 :
169 : /** Global statistics events, index per frame and channel. */
170 : lunchbox::Lockable<StatisticsRB, lunchbox::SpinLock> statistics;
171 :
172 : /** The initial channel size, used for view resize events. */
173 : Vector2i initialSize;
174 :
175 : /** The application-declared regions of interest, merged if
176 : necessary to be non overlapping. */
177 : PixelViewports regions;
178 :
179 : /** The number of the last finished frame. */
180 : lunchbox::Monitor<uint32_t> finishedFrame;
181 :
182 : /** Listeners that get notified on each new rendered image */
183 : typedef std::vector<ResultImageListener*> ResultImageListeners;
184 : ResultImageListeners resultImageListeners;
185 :
186 : /** Image of the current framebuffer if result listeners are present */
187 : eq::Image framebufferImage;
188 :
189 : #ifdef EQUALIZER_USE_DEFLECT
190 : deflect::Proxy* _deflectProxy;
191 : #endif
192 :
193 : /** Dumps images when the channel is configured to do so */
194 : FileFrameWriter frameWriter;
195 :
196 : bool _updateFrameBuffer;
197 : bool _finishImageListeners = false;
198 : };
199 : }
200 : }
|