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 : std::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 0 : , _running( false )
56 : {
57 0 : const DrawableConfig& dc = _channel.getDrawableConfig();
58 0 : if( dc.colorBits != 8 )
59 : {
60 0 : LBWARN << "Can only stream 8-bit RGB(A) framebuffers to "
61 0 : << "Deflect host, got " << dc.colorBits << " color bits"
62 0 : << std::endl;
63 0 : return;
64 : }
65 :
66 : const std::string& deflectHost =
67 0 : _channel.getView()->getSAttribute( View::SATTR_DEFLECT_HOST );
68 : const std::string& name =
69 0 : _channel.getView()->getSAttribute( View::SATTR_DEFLECT_ID );
70 0 : _stream.reset( new ::deflect::Stream( name, deflectHost ));
71 0 : if( !_stream->isConnected( ))
72 : {
73 0 : LBWARN << "Could not connect to Deflect host: " << deflectHost
74 0 : << std::endl;
75 0 : return;
76 : }
77 :
78 0 : _running = true;
79 0 : _sendFuture = make_ready_future( true );
80 : }
81 :
82 0 : ~Impl()
83 0 : {
84 : // wait for completion of previous send
85 0 : _sendFuture.wait();
86 0 : }
87 :
88 0 : void notifyNewImage( Channel& channel, const Image& image )
89 : {
90 0 : LBASSERT( &channel == &_channel );
91 :
92 : // wait for completion of previous send
93 0 : _running = _sendFuture.get();
94 :
95 : // copy pixels to perform swapYAxis()
96 0 : const size_t dataSize = image.getPixelDataSize( Frame::BUFFER_COLOR );
97 0 : _buffer.replace( image.getPixelPointer( Frame::BUFFER_COLOR ), dataSize);
98 0 : const PixelViewport& pvp = image.getPixelViewport();
99 0 : ::deflect::ImageWrapper::swapYAxis( _buffer.getData(), pvp.w, pvp.h,
100 0 : image.getPixelSize( Frame::BUFFER_COLOR ));
101 :
102 : // determine image offset wrt global view
103 0 : const Viewport& vp = channel.getViewport();
104 0 : const int32_t width = pvp.w / vp.w;
105 0 : const int32_t height = pvp.h / vp.h;
106 0 : const int32_t offsX = vp.x * width;
107 0 : const int32_t offsY = height - (vp.y * height + vp.h * height);
108 :
109 0 : ::deflect::ImageWrapper imageWrapper( _buffer.getData(), pvp.w, pvp.h,
110 0 : ::deflect::BGRA, offsX, offsY );
111 0 : imageWrapper.compressionPolicy = ::deflect::COMPRESSION_ON;
112 0 : imageWrapper.compressionQuality = 100;
113 :
114 0 : _sendFuture = _stream->asyncSend( imageWrapper );
115 0 : }
116 :
117 : std::unique_ptr< ::deflect::Stream > _stream;
118 : std::unique_ptr< EventHandler > _eventHandler;
119 : Channel& _channel;
120 : lunchbox::Bufferb _buffer;
121 : ::deflect::Stream::Future _sendFuture;
122 : bool _running;
123 : };
124 :
125 0 : Proxy::Proxy( Channel& channel )
126 : : ResultImageListener()
127 0 : , _impl( new Impl( channel ))
128 : {
129 0 : channel.addResultImageListener( this );
130 0 : }
131 :
132 0 : Proxy::~Proxy()
133 : {
134 0 : _impl->_channel.removeResultImageListener( this );
135 0 : }
136 :
137 0 : void Proxy::notifyNewImage( Channel& channel, const Image& image )
138 : {
139 0 : _impl->notifyNewImage( channel, image );
140 :
141 0 : if( !_impl->_eventHandler && _impl->_stream->registerForEvents( true ))
142 : {
143 0 : _impl->_eventHandler.reset( new EventHandler( this ));
144 0 : LBDEBUG << "Installed event handler for Deflect proxy" << std::endl;
145 : }
146 0 : }
147 :
148 0 : Channel& Proxy::getChannel()
149 : {
150 0 : return _impl->_channel;
151 : }
152 :
153 0 : int Proxy::getSocketDescriptor() const
154 : {
155 0 : return _impl->_stream->getDescriptor();
156 : }
157 :
158 0 : bool Proxy::hasNewEvent() const
159 : {
160 0 : return _impl->_stream->hasEvent();
161 : }
162 :
163 0 : bool Proxy::isRunning() const
164 : {
165 0 : return _impl->_running;
166 : }
167 :
168 0 : void Proxy::stopRunning()
169 : {
170 0 : _impl->_running = false;
171 0 : }
172 :
173 0 : ::deflect::Event Proxy::getEvent() const
174 : {
175 0 : return _impl->_stream->getEvent();
176 : }
177 :
178 : }
179 42 : }
|