Line data Source code
1 :
2 : /* Copyright (c) 2013-2017, Daniel Nachbaur <daniel.nachbaur@epfl.ch>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "proxy.h"
19 : #include "eventHandler.h"
20 :
21 : #include "../channel.h"
22 : #include "../gl.h"
23 : #include "../image.h"
24 : #include "../pipe.h"
25 : #include "../systemWindow.h"
26 : #include "../view.h"
27 : #include "../window.h"
28 : #include "../windowSystem.h"
29 :
30 : #include <eq/fabric/drawableConfig.h>
31 : #include <eq/util/objectManager.h>
32 : #include <eq/util/texture.h>
33 :
34 : #include <deflect/Stream.h>
35 : #include <lunchbox/buffer.h>
36 :
37 : namespace eq
38 : {
39 : namespace deflect
40 : {
41 : class Proxy::Impl : public boost::noncopyable
42 : {
43 : public:
44 1 : explicit Impl(Channel& ch)
45 2 : : channel(ch)
46 : {
47 1 : const DrawableConfig& dc = channel.getDrawableConfig();
48 1 : if (dc.colorBits != 8)
49 : {
50 0 : LBWARN << "Can only stream 8-bit RGB(A) framebuffers to "
51 0 : << "Deflect host, got " << dc.colorBits << " color bits"
52 0 : << std::endl;
53 0 : return;
54 : }
55 :
56 : const std::string& deflectHost =
57 1 : channel.getView()->getSAttribute(View::SATTR_DEFLECT_HOST);
58 : const std::string& name =
59 1 : channel.getView()->getSAttribute(View::SATTR_DEFLECT_ID);
60 2 : stream.reset(new ::deflect::Stream(name, deflectHost));
61 0 : if (!stream->isConnected())
62 : {
63 0 : LBWARN << "Could not connect to Deflect host: " << deflectHost
64 0 : << std::endl;
65 0 : stream.reset();
66 : }
67 : }
68 :
69 0 : ~Impl()
70 0 : {
71 0 : for (size_t i = 0; i < NUM_EYES; ++i)
72 0 : if (_sendFuture[i].valid())
73 0 : _sendFuture[i].wait();
74 0 : if (_finishFuture.valid())
75 0 : _finishFuture.wait();
76 0 : }
77 :
78 0 : void notifyNewImage(Channel&, const Image& image)
79 : {
80 0 : switch (channel.getEye())
81 : {
82 : case eq::EYE_LEFT:
83 0 : _send(::deflect::View::left_eye, EYE_LEFT_BIT, image);
84 0 : return;
85 :
86 : case eq::EYE_RIGHT:
87 0 : _send(::deflect::View::right_eye, EYE_RIGHT_BIT, image);
88 0 : return;
89 :
90 : default:
91 0 : _send(::deflect::View::mono, EYE_CYCLOP_BIT, image);
92 0 : return;
93 : }
94 : }
95 :
96 0 : void finishFrame()
97 : {
98 0 : if (_finishFuture.valid() && !_finishFuture.get())
99 0 : stream.reset();
100 0 : if (!stream)
101 0 : return;
102 :
103 0 : for (size_t i = 0; i < NUM_EYES; ++i)
104 : {
105 0 : if (_sendFuture[i].valid())
106 : {
107 0 : _finishFuture = stream->finishFrame();
108 0 : return;
109 : }
110 : }
111 : }
112 :
113 : Channel& channel;
114 : std::unique_ptr<::deflect::Stream> stream;
115 : std::unique_ptr<EventHandler> eventHandler;
116 :
117 : private:
118 0 : void _send(const ::deflect::View view, const Eye eye, const Image& image)
119 : {
120 0 : if (_sendFuture[eye].valid() && !_sendFuture[eye].get())
121 0 : stream.reset();
122 0 : if (!stream)
123 0 : return;
124 :
125 : // copy pixels to perform swapYAxis()
126 0 : const size_t dataSize = image.getPixelDataSize(Frame::Buffer::color);
127 0 : _buffer[eye].replace(image.getPixelPointer(Frame::Buffer::color),
128 0 : dataSize);
129 0 : const PixelViewport& pvp = image.getPixelViewport();
130 0 : ::deflect::ImageWrapper::swapYAxis(_buffer[eye].getData(), pvp.w, pvp.h,
131 : image.getPixelSize(
132 0 : Frame::Buffer::color));
133 :
134 : // determine image offset wrt global view
135 0 : const Viewport& vp = channel.getViewport();
136 0 : const int32_t width = pvp.w / vp.w;
137 0 : const int32_t height = pvp.h / vp.h;
138 0 : const int32_t offsX = vp.x * width;
139 0 : const int32_t offsY = height - (vp.y * height + vp.h * height);
140 :
141 0 : ::deflect::ImageWrapper imageWrapper(_buffer[eye].getData(), pvp.w,
142 0 : pvp.h, ::deflect::BGRA, offsX,
143 0 : offsY);
144 0 : imageWrapper.compressionPolicy = ::deflect::COMPRESSION_ON;
145 0 : imageWrapper.compressionQuality = 100;
146 0 : imageWrapper.view = view;
147 :
148 0 : _sendFuture[eye] = stream->send(imageWrapper);
149 : }
150 :
151 : lunchbox::Bufferb _buffer[NUM_EYES];
152 : ::deflect::Stream::Future _sendFuture[NUM_EYES];
153 : ::deflect::Stream::Future _finishFuture;
154 : };
155 :
156 1 : Proxy::Proxy(Channel& channel)
157 : : ResultImageListener()
158 2 : , _impl(new Impl(channel))
159 : {
160 0 : channel.addResultImageListener(this);
161 0 : }
162 :
163 0 : Proxy::~Proxy()
164 : {
165 0 : _impl->channel.removeResultImageListener(this);
166 0 : }
167 :
168 0 : void Proxy::notifyNewImage(Channel& channel, const Image& image)
169 : {
170 0 : _impl->notifyNewImage(channel, image);
171 :
172 0 : if (!_impl->eventHandler && _impl->stream->registerForEvents(true))
173 : {
174 0 : _impl->eventHandler.reset(new EventHandler(this));
175 0 : LBDEBUG << "Installed event handler for Deflect proxy" << std::endl;
176 : }
177 0 : }
178 :
179 0 : void Proxy::notifyFinishFrame()
180 : {
181 0 : _impl->finishFrame();
182 0 : }
183 :
184 0 : Channel& Proxy::getChannel()
185 : {
186 0 : return _impl->channel;
187 : }
188 :
189 0 : int Proxy::getSocketDescriptor() const
190 : {
191 0 : return _impl->stream->getDescriptor();
192 : }
193 :
194 0 : bool Proxy::hasNewEvent() const
195 : {
196 0 : return _impl->stream->hasEvent();
197 : }
198 :
199 0 : bool Proxy::isRunning() const
200 : {
201 0 : return _impl->stream != nullptr;
202 : }
203 :
204 0 : void Proxy::stopRunning()
205 : {
206 0 : _impl->stream.reset();
207 0 : }
208 :
209 0 : ::deflect::Event Proxy::getEvent() const
210 : {
211 0 : return _impl->stream->getEvent();
212 : }
213 : }
214 30 : }
|