From 72763ddc11bf8e4e9d6e371a0c44e1af8e5ea7de Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 1 Jan 2021 18:41:28 -0800 Subject: [PATCH] Create offscreen context at startup and reuse it. --- common/lc_application.cpp | 5 ++ common/lc_context.cpp | 81 ++++++++++++++++++++++++++++--- common/lc_context.h | 19 ++++++-- common/lc_model.cpp | 7 ++- common/lc_partselectionwidget.cpp | 5 ++ common/lc_view.cpp | 66 +++++++++---------------- common/lc_view.h | 9 +++- common/lc_viewwidget.cpp | 4 +- qt/qtmain.cpp | 5 ++ 9 files changed, 143 insertions(+), 58 deletions(-) diff --git a/common/lc_application.cpp b/common/lc_application.cpp index 53e6dbad..1a05ea97 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -772,6 +772,11 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath #endif } +#ifdef LC_USE_QOPENGLWIDGET + if (!lcContext::CreateOffscreenContext()) + return lcStartupMode::Error; +#endif + gMainWindow = new lcMainWindow(); lcLoadDefaultKeyboardShortcuts(); lcLoadDefaultMouseShortcuts(); diff --git a/common/lc_context.cpp b/common/lc_context.cpp index fae5f296..9a165a95 100644 --- a/common/lc_context.cpp +++ b/common/lc_context.cpp @@ -27,6 +27,10 @@ #define GL_STATIC_DRAW_ARB GL_STATIC_DRAW #endif +#ifdef LC_USE_QOPENGLWIDGET +std::unique_ptr lcContext::mOffscreenContext; +std::unique_ptr lcContext::mOffscreenSurface; +#endif lcProgram lcContext::mPrograms[static_cast(lcMaterialType::Count)]; int lcContext::mValidContexts; @@ -93,6 +97,47 @@ lcContext::~lcContext() } } +#ifdef LC_USE_QOPENGLWIDGET + +bool lcContext::CreateOffscreenContext() +{ + std::unique_ptr OffscreenContext(new QOpenGLContext()); + + if (!OffscreenContext) + return false; + + OffscreenContext->setShareContext(QOpenGLContext::globalShareContext()); + + if (!OffscreenContext->create() || !OffscreenContext->isValid()) + return false; + + std::unique_ptr OffscreenSurface(new QOffscreenSurface()); + + if (!OffscreenSurface) + return false; + + OffscreenSurface->create(); + + if (!OffscreenSurface->isValid()) + return false; + + if (!OffscreenContext->makeCurrent(OffscreenSurface.get())) + return false; + + mOffscreenContext = std::move(OffscreenContext); + mOffscreenSurface = std::move(OffscreenSurface); + + return true; +} + +void lcContext::DestroyOffscreenContext() +{ + mOffscreenSurface.reset(); + mOffscreenContext.reset(); +} + +#endif + void lcContext::CreateShaderPrograms() { const char* ShaderPrefix = @@ -255,20 +300,33 @@ void lcContext::DestroyResources() } } +void lcContext::MakeCurrent() +{ + if (mWidget) + mWidget->makeCurrent(); #ifdef LC_USE_QOPENGLWIDGET -void lcContext::SetGLContext(QOpenGLContext* GLContext) + else + mOffscreenContext->makeCurrent(mOffscreenSurface.get()); +#endif +} + +#ifdef LC_USE_QOPENGLWIDGET +void lcContext::SetGLContext(QOpenGLContext* Context, QOpenGLWidget* Widget) #else -void lcContext::SetGLContext(const QGLContext* GLContext) +void lcContext::SetGLContext(const QGLContext* Context, QGLWidget* Widget) #endif { + mContext = Context; + mWidget = Widget; + #ifdef LC_USE_QOPENGLWIDGET + MakeCurrent(); initializeOpenGLFunctions(); - mGLContext = GLContext; #endif if (!mValidContexts) { - lcInitializeGLExtensions(GLContext); + lcInitializeGLExtensions(Context); // TODO: Find a better place for the grid texture and font gStringCache.Initialize(this); @@ -289,6 +347,15 @@ void lcContext::SetGLContext(const QGLContext* GLContext) mValidContexts++; } +#ifdef LC_USE_QOPENGLWIDGET + +void lcContext::SetOffscreenContext() +{ + SetGLContext(mOffscreenContext.get(), nullptr); +} + +#endif + void lcContext::SetDefaultState() { #ifdef LC_USE_QOPENGLWIDGET @@ -610,7 +677,7 @@ void lcContext::ClearFramebuffer() return; #ifdef LC_USE_QOPENGLWIDGET - glBindFramebuffer(GL_FRAMEBUFFER, mGLContext->defaultFramebufferObject()); + glBindFramebuffer(GL_FRAMEBUFFER, mContext->defaultFramebufferObject()); #else if (gSupportsFramebufferObjectARB) glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -664,7 +731,7 @@ lcFramebuffer lcContext::CreateFramebuffer(int Width, int Height, bool Depth, bo #ifdef LC_USE_QOPENGLWIDGET else { - QOpenGLFunctions_3_2_Core* Funcs = mGLContext->versionFunctions(); + QOpenGLFunctions_3_2_Core* Funcs = mContext->versionFunctions(); BindTexture2DMS(Framebuffer.mColorTexture); Funcs->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE); @@ -824,7 +891,7 @@ void lcContext::GetRenderFramebufferImage(const std::pairversionFunctions(); + QOpenGLFunctions_3_2_Core* Funcs = mContext->versionFunctions(); Funcs->glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR); #else glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR); diff --git a/common/lc_context.h b/common/lc_context.h index 9c7f5924..92db7777 100644 --- a/common/lc_context.h +++ b/common/lc_context.h @@ -120,16 +120,23 @@ public: lcContext(const lcContext&) = delete; lcContext& operator=(const lcContext&) = delete; +#ifdef LC_USE_QOPENGLWIDGET + static bool CreateOffscreenContext(); + static void DestroyOffscreenContext(); +#endif + void CreateResources(); void DestroyResources(); void SetDefaultState(); void ClearResources(); + void MakeCurrent(); #ifdef LC_USE_QOPENGLWIDGET - void SetGLContext(QOpenGLContext* GLContext); + void SetGLContext(QOpenGLContext* GLContext, QOpenGLWidget* Widget); + void SetOffscreenContext(); #else - void SetGLContext(const QGLContext* GLContext); + void SetGLContext(const QGLContext* GLContext, QGLWidget* Widget); #endif void ClearColorAndDepth(const lcVector4& ClearColor); @@ -234,7 +241,8 @@ protected: void FlushState(); #ifdef LC_USE_QOPENGLWIDGET - QOpenGLContext* mGLContext = nullptr; + QOpenGLWidget* mWidget = nullptr; + QOpenGLContext* mContext = nullptr; #endif bool mValid = false; @@ -273,6 +281,11 @@ protected: GLuint mFramebufferObject; +#ifdef LC_USE_QOPENGLWIDGET + static std::unique_ptr mOffscreenContext; + static std::unique_ptr mOffscreenSurface; +#endif + static lcProgram mPrograms[static_cast(lcMaterialType::Count)]; static int mValidContexts; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index e863e513..61114dab 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1276,9 +1276,12 @@ QImage lcModel::GetStepImage(bool Zoom, int Width, int Height, lcStep Step) lcCamera* Camera = ActiveView->GetCamera(); lcView View(lcViewType::View, this); - View.SetCamera(Camera, false); + View.SetCamera(Camera, true); -#ifndef LC_USE_QOPENGLWIDGET +#ifdef LC_USE_QOPENGLWIDGET + View.SetOffscreenContext(); + View.MakeCurrent(); +#else ActiveView->MakeCurrent(); lcContext* Context = ActiveView->mContext; View.SetContext(Context); diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index 5c2813c3..447839b2 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -398,6 +398,9 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex) { mView = std::unique_ptr(new lcView(lcViewType::PartsList, nullptr)); + mView->SetOffscreenContext(); + mView->MakeCurrent(); + if (!mView->BeginRenderToImage(Width, Height)) { mView.reset(); @@ -406,6 +409,7 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex) } mView->MakeCurrent(); + mView->BindRenderFramebuffer(); lcContext* Context = mView->mContext; #else @@ -456,6 +460,7 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex) Scene.Draw(Context); #ifdef LC_USE_QOPENGLWIDGET + mView->UnbindRenderFramebuffer(); QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32); #else QImage Image = Context->GetRenderFramebufferImage(mRenderFramebuffer); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 37a61257..0be58821 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -76,12 +76,7 @@ void lcView::UpdateAllViews() void lcView::MakeCurrent() { - if (mWidget) - mWidget->makeCurrent(); -#ifdef LC_USE_QOPENGLWIDGET - else if (mOffscreenContext) - mOffscreenContext->makeCurrent(mOffscreenSurface.get()); -#endif + mContext->MakeCurrent(); } void lcView::Redraw() @@ -90,6 +85,15 @@ void lcView::Redraw() mWidget->update(); } +#ifdef LC_USE_QOPENGLWIDGET + +void lcView::SetOffscreenContext() +{ + mContext->SetOffscreenContext(); +} + +#else + void lcView::SetContext(lcContext* Context) { if (mDeleteContext) @@ -99,6 +103,8 @@ void lcView::SetContext(lcContext* Context) mDeleteContext = false; } +#endif + void lcView::SetFocus(bool Focus) { if (Focus) @@ -725,36 +731,6 @@ lcArray lcView::FindObjectsInBox(float x1, float y1, float x2, float bool lcView::BeginRenderToImage(int Width, int Height) { -#ifdef LC_USE_QOPENGLWIDGET - std::unique_ptr OffscreenContext(new QOpenGLContext()); - - if (!OffscreenContext) - return false; - - OffscreenContext->setShareContext(QOpenGLContext::globalShareContext()); - - if (!OffscreenContext->create() || !OffscreenContext->isValid()) - return false; - - std::unique_ptr OffscreenSurface(new QOffscreenSurface()); - - if (!OffscreenSurface) - return false; - - OffscreenSurface->create(); - - if (!OffscreenSurface->isValid()) - return false; - - if (!OffscreenContext->makeCurrent(OffscreenSurface.get())) - return false; - - mContext->SetGLContext(OffscreenContext.get()); - - mOffscreenContext = std::move(OffscreenContext); - mOffscreenSurface = std::move(OffscreenSurface); -#endif - GLint MaxTexture; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture); @@ -795,8 +771,6 @@ bool lcView::BeginRenderToImage(int Width, int Height) void lcView::EndRenderToImage() { #ifdef LC_USE_QOPENGLWIDGET - mOffscreenContext.reset(); - mOffscreenSurface.reset(); mRenderFramebuffer.reset(); #else mRenderImage = QImage(); @@ -812,13 +786,19 @@ QImage lcView::GetRenderImage() const #ifdef LC_USE_QOPENGLWIDGET -QImage lcView::GetRenderFramebufferImage() const +void lcView::BindRenderFramebuffer() +{ + mRenderFramebuffer->bind(); +} + +void lcView::UnbindRenderFramebuffer() { mRenderFramebuffer->release(); - QImage Image = mRenderFramebuffer->toImage(); - mRenderFramebuffer->bind(); +} - return Image; +QImage lcView::GetRenderFramebufferImage() const +{ + return mRenderFramebuffer->toImage(); } #endif @@ -918,7 +898,9 @@ void lcView::OnDraw() if (!mRenderImage.isNull()) { #ifdef LC_USE_QOPENGLWIDGET + UnbindRenderFramebuffer(); QImage TileImage = GetRenderFramebufferImage(); + BindRenderFramebuffer(); quint8* Buffer = TileImage.bits(); #else quint8* Buffer = (quint8*)malloc(mWidth * mHeight * 4); diff --git a/common/lc_view.h b/common/lc_view.h index 95f52cbf..c1173f6c 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -176,7 +176,12 @@ public: void MakeCurrent(); void Redraw(); + +#ifdef LC_USE_QOPENGLWIDGET + void SetOffscreenContext(); +#else void SetContext(lcContext* Context); +#endif void SetFocus(bool Focus); void SetMousePosition(int MouseX, int MouseY); @@ -236,6 +241,8 @@ public: void EndRenderToImage(); QImage GetRenderImage() const; #ifdef LC_USE_QOPENGLWIDGET + void BindRenderFramebuffer(); + void UnbindRenderFramebuffer(); QImage GetRenderFramebufferImage() const; #endif @@ -300,8 +307,6 @@ protected: QImage mRenderImage; #ifdef LC_USE_QOPENGLWIDGET - std::unique_ptr mOffscreenContext; - std::unique_ptr mOffscreenSurface; std::unique_ptr mRenderFramebuffer; #else std::pair mRenderFramebuffer; diff --git a/common/lc_viewwidget.cpp b/common/lc_viewwidget.cpp index c81e04d6..c48993fe 100644 --- a/common/lc_viewwidget.cpp +++ b/common/lc_viewwidget.cpp @@ -56,7 +56,7 @@ void lcViewWidget::SetView(lcView* View) if (context()) { makeCurrent(); - View->mContext->SetGLContext(context()); + View->mContext->SetGLContext(context(), this); } View->SetWidget(this); @@ -73,7 +73,7 @@ void lcViewWidget::SetView(lcView* View) void lcViewWidget::initializeGL() { - mView->mContext->SetGLContext(context()); + mView->mContext->SetGLContext(context(), this); } void lcViewWidget::resizeGL(int Width, int Height) diff --git a/qt/qtmain.cpp b/qt/qtmain.cpp index 3d43ef71..cf6018a0 100644 --- a/qt/qtmain.cpp +++ b/qt/qtmain.cpp @@ -3,6 +3,7 @@ #include "lc_qupdatedialog.h" #include "lc_mainwindow.h" #include "lc_profile.h" +#include "lc_context.h" #include #include @@ -197,6 +198,10 @@ int main(int argc, char *argv[]) ExecReturn = Application.exec(); } +#ifdef LC_USE_QOPENGLWIDGET + lcContext::DestroyOffscreenContext(); +#endif + delete gMainWindow; gMainWindow = nullptr;