diff --git a/.gitsubprojects b/.gitsubprojects index 0ec9773c..fa65acc1 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -1,5 +1,5 @@ # -*- mode: cmake -*- git_subproject(ZeroEQ https://github.com/HBPVIS/ZeroEQ.git 1019277) -git_subproject(Deflect https://github.com/BlueBrain/Deflect.git fd77ea4) +git_subproject(Deflect https://github.com/BlueBrain/Deflect.git 7d2918e) git_subproject(TUIO https://github.com/BlueBrain/TUIO.git fdf5cf7) git_subproject(VirtualKeyboard https://github.com/rdumusc/QtFreeVirtualKeyboard.git e3ee94d) diff --git a/apps/Whiteboard/Whiteboard.cpp b/apps/Whiteboard/Whiteboard.cpp index 8b0d9fff..7301b7c1 100644 --- a/apps/Whiteboard/Whiteboard.cpp +++ b/apps/Whiteboard/Whiteboard.cpp @@ -59,6 +59,7 @@ Whiteboard::Whiteboard( int& argc, char* argv[] ) _qmlStreamer.reset( new deflect::qt::QmlStreamer( deflectQmlFile, deflectHost, deflectStreamId )); + _qmlStreamer->useAsyncSend( true ); connect( _qmlStreamer.get(), &deflect::qt::QmlStreamer::streamClosed, this, &QCoreApplication::quit ); diff --git a/tide/wall/CMakeLists.txt b/tide/wall/CMakeLists.txt index 07b70666..b3cfad2d 100644 --- a/tide/wall/CMakeLists.txt +++ b/tide/wall/CMakeLists.txt @@ -9,6 +9,7 @@ set(TIDEWALL_LINK_LIBRARIES TideCore Qt5::Widgets PRIVATE + DeflectQt Qt5::Svg ) @@ -66,7 +67,6 @@ list(APPEND TIDEWALL_PUBLIC_HEADERS PixelStreamUpdater.h QmlWindowRenderer.h QuadLineNode.h - QuickRenderer.h RenderController.h StreamImage.h SVGGpuImage.h @@ -103,7 +103,6 @@ list(APPEND TIDEWALL_SOURCES PixelStreamUpdater.cpp QmlWindowRenderer.cpp QuadLineNode.cpp - QuickRenderer.cpp RenderController.cpp StreamImage.cpp SVGGpuImage.cpp diff --git a/tide/wall/QuickRenderer.cpp b/tide/wall/QuickRenderer.cpp deleted file mode 100644 index e7c4bc69..00000000 --- a/tide/wall/QuickRenderer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/*********************************************************************/ -/* Copyright (c) 2016, EPFL/Blue Brain Project */ -/* Daniel.Nachbaur@epfl.ch */ -/* All rights reserved. */ -/* */ -/* Redistribution and use in source and binary forms, with or */ -/* without modification, are permitted provided that the following */ -/* conditions are met: */ -/* */ -/* 1. Redistributions of source code must retain the above */ -/* copyright notice, this list of conditions and the following */ -/* disclaimer. */ -/* */ -/* 2. Redistributions in binary form must reproduce the above */ -/* copyright notice, this list of conditions and the following */ -/* disclaimer in the documentation and/or other materials */ -/* provided with the distribution. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */ -/* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */ -/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ -/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ -/* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */ -/* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ -/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ -/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ -/* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */ -/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ -/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ -/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */ -/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ -/* POSSIBILITY OF SUCH DAMAGE. */ -/* */ -/* The views and conclusions contained in the software and */ -/* documentation are those of the authors and should not be */ -/* interpreted as representing official policies, either expressed */ -/* or implied, of Ecole polytechnique federale de Lausanne. */ -/*********************************************************************/ - -#include "QuickRenderer.h" - -#include "network/WallToWallChannel.h" -#include "WallWindow.h" - -#include -#include -#include -#include - -QuickRenderer::QuickRenderer( WallWindow& window ) - : _glContext( window.getOpenGLContext( )) - , _renderControl( window.getRenderControl( )) - , _surface( window ) - , _wallChannel( window.getWallChannel( )) - , _initialized( false ) -{ - connect( this, &QuickRenderer::init, this, - &QuickRenderer::_onInit, Qt::BlockingQueuedConnection ); - connect( this, &QuickRenderer::stop, this, - &QuickRenderer::_onStop, Qt::BlockingQueuedConnection ); -} - -void QuickRenderer::render() -{ - QMutexLocker lock( &_mutex ); - QCoreApplication::postEvent( this, new QEvent( QEvent::User )); - - // the main thread has to be blocked for sync() - _cond.wait( &_mutex ); -} - -bool QuickRenderer::event( QEvent* e ) -{ - if( e->type() == QEvent::User ) - { - _onRender(); - return true; - } - return QObject::event( e ); -} - -void QuickRenderer::_onInit() -{ - _glContext.makeCurrent( &_surface ); - _renderControl.initialize( &_glContext ); - _initialized = true; -} - -void QuickRenderer::_onStop() -{ - _glContext.makeCurrent( &_surface ); - - _renderControl.invalidate(); - - _glContext.doneCurrent(); - _glContext.moveToThread( QCoreApplication::instance()->thread( )); -} - -void QuickRenderer::_onRender() -{ - if( !_initialized ) - return; - - { - QMutexLocker lock( &_mutex ); - - _glContext.makeCurrent( &_surface ); - - _renderControl.sync(); - - // unblock main thread after sync in render thread is done - _cond.wakeOne(); - } - - _renderControl.render(); - _glContext.functions()->glFinish(); - - _wallChannel.globalBarrier(); - - _glContext.swapBuffers( &_surface ); - _glContext.functions()->glFlush(); - - emit frameSwapped(); -} diff --git a/tide/wall/QuickRenderer.h b/tide/wall/QuickRenderer.h deleted file mode 100644 index 577f73bc..00000000 --- a/tide/wall/QuickRenderer.h +++ /dev/null @@ -1,109 +0,0 @@ -/*********************************************************************/ -/* Copyright (c) 2016, EPFL/Blue Brain Project */ -/* Daniel.Nachbaur@epfl.ch */ -/* All rights reserved. */ -/* */ -/* Redistribution and use in source and binary forms, with or */ -/* without modification, are permitted provided that the following */ -/* conditions are met: */ -/* */ -/* 1. Redistributions of source code must retain the above */ -/* copyright notice, this list of conditions and the following */ -/* disclaimer. */ -/* */ -/* 2. Redistributions in binary form must reproduce the above */ -/* copyright notice, this list of conditions and the following */ -/* disclaimer in the documentation and/or other materials */ -/* provided with the distribution. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */ -/* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */ -/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ -/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ -/* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */ -/* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ -/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ -/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ -/* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */ -/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ -/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ -/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */ -/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ -/* POSSIBILITY OF SUCH DAMAGE. */ -/* */ -/* The views and conclusions contained in the software and */ -/* documentation are those of the authors and should not be */ -/* interpreted as representing official policies, either expressed */ -/* or implied, of Ecole polytechnique federale de Lausanne. */ -/*********************************************************************/ - -#ifndef QUICKRENDERER_H -#define QUICKRENDERER_H - -#include "types.h" - -#include -#include -#include - -class QOpenGLContext; -class QQuickRenderControl; -class QSurface; - -/** - * Renders the QML scene from the given window using QQuickRenderControl onto - * the surface of the window and synchronizes the swapBuffers() with all other - * wall processes. Note that this object needs to be moved to a seperate - * (render)thread to function properly. - * - * Inspired by http://doc.qt.io/qt-5/qtquick-rendercontrol-window-multithreaded-cpp.html - */ -class QuickRenderer : public QObject -{ - Q_OBJECT - -public: - QuickRenderer( WallWindow& window ); - - /** - * To be called from GUI/main thread to trigger rendering and swapBuffers(). - * This call is blocking until sync() is done in render thread and must be - * executed on all wall processes for non-deadlocking swap barrier. - */ - void render(); - -signals: - /** Emitted after swapBuffers(). Originates from render thread */ - void frameSwapped(); - - /** - * To be called from GUI/main thread to initialize this object on render - * thread. Blocks until operation on render thread is done. - */ - void init(); - - /** - * To be called from GUI/main thread to stop using this object on the render - * thread. Blocks until operation on render thread is done. - */ - void stop(); - -private: - bool event( QEvent* qtEvent ) final; - void _onInit(); - void _onRender(); - void _onStop(); - - QOpenGLContext& _glContext; - QQuickRenderControl& _renderControl; - QSurface& _surface; - - WallToWallChannel& _wallChannel; - - bool _initialized; - - QMutex _mutex; - QWaitCondition _cond; -}; - -#endif diff --git a/tide/wall/TextureUploader.cpp b/tide/wall/TextureUploader.cpp index be500794..23776685 100644 --- a/tide/wall/TextureUploader.cpp +++ b/tide/wall/TextureUploader.cpp @@ -139,7 +139,7 @@ void TextureUploader::_upload( const Image& image, const uint textureID ) // which originates from glFinish() in upload & render thread. For now // we use 'slow&easy' texture upload. This probably points out the problem // and a potential solution: - // http://stackoverflow.com/questions/31941385/opengl-driver-seems-to-be-ridiculously-slow-from-glunmapbuffer-this-cant-be-ri + // http://stackoverflow.com/questions/31941385 #if 0 // make PBO big enough _gl->glBindBuffer( GL_PIXEL_UNPACK_BUFFER, _pbo ); diff --git a/tide/wall/WallWindow.cpp b/tide/wall/WallWindow.cpp index c53124c2..d3d7c9e1 100644 --- a/tide/wall/WallWindow.cpp +++ b/tide/wall/WallWindow.cpp @@ -43,13 +43,14 @@ #include "DisplayGroupRenderer.h" #include "log.h" #include "qmlUtils.h" -#include "QuickRenderer.h" #include "scene/Options.h" #include "TestPattern.h" #include "TextureUploader.h" #include "WallConfiguration.h" +#include #include +#include #include #include #include @@ -66,9 +67,8 @@ WallWindow::WallWindow( const WallConfiguration& config, , _displayGroupRenderer( nullptr ) , _testPattern( nullptr ) , _wallChannel( wallChannel ) - , _glContext( new QOpenGLContext ) , _renderControl( renderControl ) - , _quickRenderer( new QuickRenderer( *this )) + , _quickRenderer( new deflect::qt::QuickRenderer( *this, *_renderControl )) , _quickRendererThread( new QThread ) , _qmlEngine( new QQmlEngine ) , _qmlComponent( nullptr ) @@ -117,7 +117,6 @@ WallWindow::~WallWindow() delete _displayGroupRenderer; delete _qmlComponent; delete _qmlEngine; - delete _glContext; delete _quickRenderer; delete _uploader; } @@ -129,13 +128,6 @@ void WallWindow::exposeEvent( QExposeEvent* ) // Initialize the renderer once the window is shown for correct GL context // realisiation - QSurfaceFormat format_; - format_.setDepthBufferSize( 16 ); - format_.setStencilBufferSize( 8 ); - - _glContext->setFormat( format_ ); - _glContext->create(); - #if QT_VERSION >= 0x050500 // Call required to make QtGraphicalEffects work in the initial scene. _renderControl->prepareThread( _quickRendererThread ); @@ -145,7 +137,6 @@ void WallWindow::exposeEvent( QExposeEvent* ) "QtGraphicalEffects." ); #endif - _glContext->moveToThread( _quickRendererThread ); _quickRenderer->moveToThread( _quickRendererThread ); _quickRendererThread->setObjectName( "Render" ); @@ -157,7 +148,7 @@ void WallWindow::exposeEvent( QExposeEvent* ) _uploadThread->setObjectName( "Upload" ); _uploadThread->start(); - _uploader->init( _glContext ); + _uploader->init( _quickRenderer->context( )); _wallChannel.globalBarrier(); _rendererInitialized = true; @@ -180,9 +171,16 @@ void WallWindow::_startQuick( const WallConfiguration& config ) const QRect& screenRect = config.getScreenRect( screenIndex ); _displayGroupRenderer = new DisplayGroupRenderer( *this, *_provider, screenRect ); - connect( _quickRenderer, &QuickRenderer::frameSwapped, - _displayGroupRenderer, - &DisplayGroupRenderer::updateRenderedFrames ); + connect( _quickRenderer, &deflect::qt::QuickRenderer::afterRender, + [&] + { + _wallChannel.globalBarrier(); + _quickRenderer->context()->swapBuffers( this ); + _quickRenderer->context()->functions()->glFlush(); + QMetaObject::invokeMethod( _displayGroupRenderer, + "updateRenderedFrames", + Qt::QueuedConnection ); + }); _testPattern = new TestPattern( config, _rootItem ); _testPattern->setPosition( -screenRect.topLeft( )); @@ -237,16 +235,6 @@ QQuickItem* WallWindow::rootObject() const return _rootItem; } -QOpenGLContext& WallWindow::getOpenGLContext() -{ - return *_glContext; -} - -QQuickRenderControl& WallWindow::getRenderControl() -{ - return *_renderControl; -} - WallToWallChannel& WallWindow::getWallChannel() { return _wallChannel; diff --git a/tide/wall/WallWindow.h b/tide/wall/WallWindow.h index 80b07334..ed03aac4 100644 --- a/tide/wall/WallWindow.h +++ b/tide/wall/WallWindow.h @@ -45,7 +45,6 @@ #include -class QuickRenderer; class QQuickRenderControl; class QQmlEngine; class QQmlComponent; @@ -93,12 +92,6 @@ class WallWindow : public QQuickWindow /** @return the communication channel to synchronize with other windows. */ WallToWallChannel& getWallChannel(); - /** @return the OpenGL context. */ - QOpenGLContext& getOpenGLContext(); - - /** @return the Qt quick render control. */ - QQuickRenderControl& getRenderControl(); - /** @return the texture uploader. */ TextureUploader& getUploader(); @@ -111,9 +104,8 @@ class WallWindow : public QQuickWindow TestPattern* _testPattern; WallToWallChannel& _wallChannel; - QOpenGLContext* _glContext; QQuickRenderControl* _renderControl; - QuickRenderer* _quickRenderer; + deflect::qt::QuickRenderer* _quickRenderer; QThread* _quickRendererThread; QQmlEngine* _qmlEngine; QQmlComponent* _qmlComponent;