LCOV - code coverage report
Current view: top level - eq/deflect - proxy.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 10 93 10.8 %
Date: 2017-12-16 05:07:20 Functions: 4 18 22.2 %

          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 : }

Generated by: LCOV version 1.11