diff --git a/app/main.cpp b/app/main.cpp index db80b28f1..cdc7f0a87 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -37,7 +37,16 @@ extern "C" { #include "core.h" #include "common/debug.h" -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) { + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + + // Set OpenGL display profile (3.2 Core) + QSurfaceFormat format; + format.setVersion(3, 2); + format.setDepthBufferSize(24); + format.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(format); + // Create application instance QApplication a(argc, argv); @@ -63,13 +72,6 @@ int main(int argc, char *argv[]) { // Set up debug handler qInstallMessageHandler(DebugHandler); - // Set OpenGL display profile (3.2 Core) - QSurfaceFormat format; - format.setVersion(3, 2); - format.setDepthBufferSize(24); - format.setProfile(QSurfaceFormat::CoreProfile); - QSurfaceFormat::setDefaultFormat(format); - // Register FFmpeg codecs and filters (deprecated in 4.0+) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) av_register_all(); diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/renderer/renderer.cpp index d2b3bb376..86965b448 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/renderer/renderer.cpp @@ -254,6 +254,10 @@ void RendererProcessor::Start() int background_thread_count = QThread::idealThreadCount(); + // Some OpenGL implementations (notably wgl) require the context not to be current before sharing + QSurface* old_surface = ctx->surface(); + ctx->doneCurrent(); + threads_.resize(background_thread_count); for (int i=0;imakeCurrent(old_surface); + // Create master texture (the one sent to the viewer) master_texture_ = std::make_shared(); master_texture_->Create(ctx, effective_width_, effective_height_, format_); diff --git a/app/node/processor/renderer/rendererthreadbase.cpp b/app/node/processor/renderer/rendererthreadbase.cpp index 6a20a237a..fbd3965a8 100644 --- a/app/node/processor/renderer/rendererthreadbase.cpp +++ b/app/node/processor/renderer/rendererthreadbase.cpp @@ -24,19 +24,14 @@ RendererThreadBase::RendererThreadBase(QOpenGLContext *share_ctx, const int &width, const int &height, const int ÷r, const olive::PixelFormat &format, const olive::RenderMode &mode) : share_ctx_(share_ctx), - width_(width), - height_(height), - divider_(divider), - format_(format), - mode_(mode), - render_instance_(nullptr) + render_instance_(width, height, divider, format, mode) { connect(share_ctx_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Cancel())); } RenderInstance *RendererThreadBase::render_instance() { - return render_instance_; + return &render_instance_; } void RendererThreadBase::run() @@ -44,18 +39,15 @@ void RendererThreadBase::run() // Lock mutex for main loop mutex_.lock(); - // Signal that main thread can continue now - caller_mutex_.lock(); - wait_cond_.wakeAll(); - caller_mutex_.unlock(); - - RenderInstance instance(width_, height_, divider_, format_, mode_); - render_instance_ = &instance; - - instance.SetShareContext(share_ctx_); + render_instance_.SetShareContext(share_ctx_); // Allocate and create resources - if (instance.Start()) { + bool started = render_instance_.Start(); + + // Signal that main thread can continue now + WakeCaller(); + + if (started) { // Main loop (use Cancel() to exit it) ProcessLoop(); @@ -63,13 +55,20 @@ void RendererThreadBase::run() } // Free all resources - render_instance_ = nullptr; - instance.Stop(); + render_instance_.Stop(); // Unlock mutex before exiting mutex_.unlock(); } +void RendererThreadBase::WakeCaller() +{ + // Signal that main thread can continue now + caller_mutex_.lock(); + wait_cond_.wakeAll(); + caller_mutex_.unlock(); +} + void RendererThreadBase::StartThread(QThread::Priority priority) { caller_mutex_.lock(); diff --git a/app/node/processor/renderer/rendererthreadbase.h b/app/node/processor/renderer/rendererthreadbase.h index 311f626d1..88c1fe68d 100644 --- a/app/node/processor/renderer/rendererthreadbase.h +++ b/app/node/processor/renderer/rendererthreadbase.h @@ -59,19 +59,11 @@ protected: QMutex caller_mutex_; private: + void WakeCaller(); + QOpenGLContext* share_ctx_; - const int& width_; - - const int& height_; - - const int& divider_; - - const olive::PixelFormat& format_; - - const olive::RenderMode& mode_; - - RenderInstance* render_instance_; + RenderInstance render_instance_; }; diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index 3a0a6a23b..1d783b95f 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -29,6 +29,8 @@ set(OLIVE_SOURCES render/rendermodes.h render/renderframebuffer.h render/renderframebuffer.cpp + render/renderservice.h + render/renderservice.cpp render/rendertexture.h render/rendertexture.cpp render/sampleformat.h diff --git a/app/render/renderinstance.cpp b/app/render/renderinstance.cpp index f0cbc93ea..c22f80765 100644 --- a/app/render/renderinstance.cpp +++ b/app/render/renderinstance.cpp @@ -26,7 +26,7 @@ RenderInstance::RenderInstance(const int& width, const int& height, - const int ÷r, + const int& divider, const olive::PixelFormat& format, const olive::RenderMode& mode) : share_ctx_(nullptr), @@ -36,6 +36,14 @@ RenderInstance::RenderInstance(const int& width, mode_(mode), divider_(divider) { + // Create offscreen surface + surface_.create(); +} + +RenderInstance::~RenderInstance() +{ + // Destroy offscreen surface + surface_.destroy(); } void RenderInstance::SetShareContext(QOpenGLContext *share) @@ -65,13 +73,9 @@ bool RenderInstance::Start() return false; } - // Create offscreen surface - surface_.create(); - // Make context current on that surface if (!ctx_->makeCurrent(&surface_)) { qWarning() << tr("Failed to makeCurrent() on offscreen surface in thread %1").arg(reinterpret_cast(this)); - surface_.destroy(); return false; } @@ -100,11 +104,7 @@ void RenderInstance::Stop() buffer_.Destroy(); // Destroy context - delete ctx_; - - // Destroy offscreen surface - surface_.destroy(); } bool RenderInstance::IsStarted() diff --git a/app/render/renderinstance.h b/app/render/renderinstance.h index a7edf005b..12e488cf0 100644 --- a/app/render/renderinstance.h +++ b/app/render/renderinstance.h @@ -34,7 +34,8 @@ * * RenderInstance contains everything that Nodes will need to draw with on a per-thread basis. * - * In OpenGL, + * Due to its usage of QOffscreenSurface, a RenderInstance instance must be constructed in the main (GUI) thread. From + * there it is safe to call Start() on in another thread. */ class RenderInstance : public QObject { @@ -45,6 +46,28 @@ public: const olive::PixelFormat& format, const olive::RenderMode& mode); + virtual ~RenderInstance() override; + + /** + * @brief Deleted copy constructor + */ + RenderInstance(const RenderInstance& other) = delete; + + /** + * @brief Deleted move constructor + */ + RenderInstance(RenderInstance&& other) = delete; + + /** + * @brief Deleted copy assignment + */ + RenderInstance& operator=(const RenderInstance& other) = delete; + + /** + * @brief Deleted move assignment + */ + RenderInstance& operator=(RenderInstance&& other) = delete; + void SetShareContext(QOpenGLContext* share); bool Start(); diff --git a/app/render/renderservice.cpp b/app/render/renderservice.cpp new file mode 100644 index 000000000..29ec74a37 --- /dev/null +++ b/app/render/renderservice.cpp @@ -0,0 +1,8 @@ +#include "renderservice.h" + +RenderService* RenderService::render_service_; + +RenderService::RenderService() +{ + +} diff --git a/app/render/renderservice.h b/app/render/renderservice.h new file mode 100644 index 000000000..fc55c1cbe --- /dev/null +++ b/app/render/renderservice.h @@ -0,0 +1,19 @@ +#ifndef RENDERSERVICE_H +#define RENDERSERVICE_H + + +class RenderService +{ +public: + RenderService(); + + static RenderService* CreateInstance(); + static RenderService* GetInstance(); + static RenderService* DestroyInstance(); + +private: + static RenderService* render_service_; + +}; + +#endif // RENDERSERVICE_H diff --git a/app/ui/style/style.cpp b/app/ui/style/style.cpp index f57d1bc01..c24c513bf 100644 --- a/app/ui/style/style.cpp +++ b/app/ui/style/style.cpp @@ -37,6 +37,8 @@ void olive::style::AppSetDefault() void olive::style::SetOliveStyle(const QString &style_name) { + qApp->setStyle(QStyleFactory::create("Fusion")); + // Set CSS style for this QFile css_file(QString(":/style/%1/style.css").arg(style_name));