Line data Source code
1 :
2 : /* Copyright (c) 2013-2015, 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 <lunchbox/buffer.h>
35 : #include <deflect/Stream.h>
36 :
37 : namespace eq
38 : {
39 : namespace deflect
40 : {
41 :
42 0 : ::deflect::Stream::Future make_ready_future( const bool value )
43 : {
44 0 : boost::promise< bool > promise;
45 0 : promise.set_value( value );
46 0 : return promise.get_future();
47 : }
48 :
49 : class Proxy::Impl : public boost::noncopyable
50 : {
51 : public:
52 0 : explicit Impl( Channel& channel )
53 : : _channel( channel )
54 : , _sendFuture( make_ready_future( false ))
55 : , _running( false )
56 0 : , _navigationMode( Proxy::MODE_ROTATE )
57 : {
58 0 : const DrawableConfig& dc = _channel.getDrawableConfig();
59 0 : if( dc.colorBits != 8 )
60 : {
61 0 : LBWARN << "Can only stream 8-bit RGB(A) framebuffers to "
62 0 : << "Deflect host, got " << dc.colorBits << " color bits"
63 0 : << std::endl;
64 0 : return;
65 : }
66 :
67 : const std::string& deflectHost =
68 0 : _channel.getView()->getSAttribute( View::SATTR_DEFLECT_HOST );
69 : const std::string& name =
70 0 : _channel.getView()->getSAttribute( View::SATTR_DEFLECT_ID );
71 0 : _stream.reset( new ::deflect::Stream( name, deflectHost ));
72 0 : if( !_stream->isConnected( ))
73 : {
74 0 : LBWARN << "Could not connect to Deflect host: " << deflectHost
75 0 : << std::endl;
76 0 : return;
77 : }
78 :
79 0 : _running = true;
80 0 : _sendFuture = make_ready_future( true );
81 : }
82 :
83 0 : ~Impl()
84 0 : {
85 : // wait for completion of previous send
86 0 : _sendFuture.wait();
87 0 : }
88 :
89 0 : void notifyNewImage( Channel& channel, const Image& image )
90 : {
91 0 : LBASSERT( &channel == &_channel );
92 :
93 : // wait for completion of previous send
94 0 : _running = _sendFuture.get();
95 :
96 : // copy pixels to perform swapYAxis()
97 0 : const size_t dataSize = image.getPixelDataSize( Frame::BUFFER_COLOR );
98 0 : _buffer.replace( image.getPixelPointer( Frame::BUFFER_COLOR ), dataSize);
99 0 : const PixelViewport& pvp = image.getPixelViewport();
100 0 : ::deflect::ImageWrapper::swapYAxis( _buffer.getData(), pvp.w, pvp.h,
101 0 : image.getPixelSize( Frame::BUFFER_COLOR ));
102 :
103 : // determine image offset wrt global view
104 0 : const Viewport& vp = channel.getViewport();
105 0 : const int32_t width = pvp.w / vp.w;
106 0 : const int32_t height = pvp.h / vp.h;
107 0 : const int32_t offsX = vp.x * width;
108 0 : const int32_t offsY = height - (vp.y * height + vp.h * height);
109 :
110 0 : ::deflect::ImageWrapper imageWrapper( _buffer.getData(), pvp.w, pvp.h,
111 0 : ::deflect::BGRA, offsX, offsY );
112 0 : imageWrapper.compressionPolicy = ::deflect::COMPRESSION_ON;
113 0 : imageWrapper.compressionQuality = 100;
114 :
115 0 : _sendFuture = _stream->asyncSend( imageWrapper );
116 0 : }
117 :
118 : std::unique_ptr< ::deflect::Stream > _stream;
119 : std::unique_ptr< EventHandler > _eventHandler;
120 : Channel& _channel;
121 : lunchbox::Bufferb _buffer;
122 : ::deflect::Stream::Future _sendFuture;
123 : bool _running;
124 : Proxy::NavigationMode _navigationMode;
125 : };
126 :
127 0 : Proxy::Proxy( Channel& channel )
128 : : ResultImageListener()
129 0 : , _impl( new Impl( channel ))
130 : {
131 0 : channel.addResultImageListener( this );
132 0 : }
133 :
134 0 : Proxy::~Proxy()
135 : {
136 0 : _impl->_channel.removeResultImageListener( this );
137 0 : }
138 :
139 0 : void Proxy::notifyNewImage( Channel& channel, const Image& image )
140 : {
141 0 : _impl->notifyNewImage( channel, image );
142 :
143 0 : if( !_impl->_eventHandler && _impl->_stream->registerForEvents( true ))
144 : {
145 0 : _impl->_eventHandler.reset( new EventHandler( this ));
146 0 : LBDEBUG << "Installed event handler for Deflect proxy" << std::endl;
147 : }
148 0 : }
149 :
150 0 : Channel& Proxy::getChannel()
151 : {
152 0 : return _impl->_channel;
153 : }
154 :
155 0 : int Proxy::getSocketDescriptor() const
156 : {
157 0 : return _impl->_stream->getDescriptor();
158 : }
159 :
160 0 : bool Proxy::hasNewEvent() const
161 : {
162 0 : return _impl->_stream->hasEvent();
163 : }
164 :
165 0 : bool Proxy::isRunning() const
166 : {
167 0 : return _impl->_running;
168 : }
169 :
170 0 : void Proxy::stopRunning()
171 : {
172 0 : _impl->_running = false;
173 0 : }
174 :
175 0 : ::deflect::Event Proxy::getEvent() const
176 : {
177 0 : return _impl->_stream->getEvent();
178 : }
179 :
180 0 : void Proxy::setNavigationMode( Proxy::NavigationMode mode )
181 : {
182 0 : _impl->_navigationMode = mode;
183 0 : }
184 :
185 0 : Proxy::NavigationMode Proxy::getNavigationMode() const
186 : {
187 0 : return _impl->_navigationMode;
188 : }
189 :
190 0 : std::string Proxy::getHelp() const
191 : {
192 0 : switch( _impl->_navigationMode )
193 : {
194 : case MODE_PAN:
195 0 : return "Pan mode";
196 : case MODE_ROTATE:
197 : default:
198 0 : return "Rotate mode";
199 : }
200 : }
201 :
202 : }
203 42 : }
|