Create offscreen context at startup and reuse it.

This commit is contained in:
Leonardo Zide 2021-01-01 18:41:28 -08:00
parent 6b2f8fa68c
commit 72763ddc11
9 changed files with 143 additions and 58 deletions

View file

@ -772,6 +772,11 @@ lcStartupMode lcApplication::Initialize(QList<QPair<QString, bool>>& LibraryPath
#endif #endif
} }
#ifdef LC_USE_QOPENGLWIDGET
if (!lcContext::CreateOffscreenContext())
return lcStartupMode::Error;
#endif
gMainWindow = new lcMainWindow(); gMainWindow = new lcMainWindow();
lcLoadDefaultKeyboardShortcuts(); lcLoadDefaultKeyboardShortcuts();
lcLoadDefaultMouseShortcuts(); lcLoadDefaultMouseShortcuts();

View file

@ -27,6 +27,10 @@
#define GL_STATIC_DRAW_ARB GL_STATIC_DRAW #define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
#endif #endif
#ifdef LC_USE_QOPENGLWIDGET
std::unique_ptr<QOpenGLContext> lcContext::mOffscreenContext;
std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
#endif
lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)]; lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
int lcContext::mValidContexts; int lcContext::mValidContexts;
@ -93,6 +97,47 @@ lcContext::~lcContext()
} }
} }
#ifdef LC_USE_QOPENGLWIDGET
bool lcContext::CreateOffscreenContext()
{
std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
if (!OffscreenContext)
return false;
OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
if (!OffscreenContext->create() || !OffscreenContext->isValid())
return false;
std::unique_ptr<QOffscreenSurface> 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() void lcContext::CreateShaderPrograms()
{ {
const char* ShaderPrefix = const char* ShaderPrefix =
@ -255,20 +300,33 @@ void lcContext::DestroyResources()
} }
} }
void lcContext::MakeCurrent()
{
if (mWidget)
mWidget->makeCurrent();
#ifdef LC_USE_QOPENGLWIDGET #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 #else
void lcContext::SetGLContext(const QGLContext* GLContext) void lcContext::SetGLContext(const QGLContext* Context, QGLWidget* Widget)
#endif #endif
{ {
mContext = Context;
mWidget = Widget;
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
MakeCurrent();
initializeOpenGLFunctions(); initializeOpenGLFunctions();
mGLContext = GLContext;
#endif #endif
if (!mValidContexts) if (!mValidContexts)
{ {
lcInitializeGLExtensions(GLContext); lcInitializeGLExtensions(Context);
// TODO: Find a better place for the grid texture and font // TODO: Find a better place for the grid texture and font
gStringCache.Initialize(this); gStringCache.Initialize(this);
@ -289,6 +347,15 @@ void lcContext::SetGLContext(const QGLContext* GLContext)
mValidContexts++; mValidContexts++;
} }
#ifdef LC_USE_QOPENGLWIDGET
void lcContext::SetOffscreenContext()
{
SetGLContext(mOffscreenContext.get(), nullptr);
}
#endif
void lcContext::SetDefaultState() void lcContext::SetDefaultState()
{ {
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
@ -610,7 +677,7 @@ void lcContext::ClearFramebuffer()
return; return;
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
glBindFramebuffer(GL_FRAMEBUFFER, mGLContext->defaultFramebufferObject()); glBindFramebuffer(GL_FRAMEBUFFER, mContext->defaultFramebufferObject());
#else #else
if (gSupportsFramebufferObjectARB) if (gSupportsFramebufferObjectARB)
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -664,7 +731,7 @@ lcFramebuffer lcContext::CreateFramebuffer(int Width, int Height, bool Depth, bo
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
else else
{ {
QOpenGLFunctions_3_2_Core* Funcs = mGLContext->versionFunctions<QOpenGLFunctions_3_2_Core>(); QOpenGLFunctions_3_2_Core* Funcs = mContext->versionFunctions<QOpenGLFunctions_3_2_Core>();
BindTexture2DMS(Framebuffer.mColorTexture); BindTexture2DMS(Framebuffer.mColorTexture);
Funcs->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE); Funcs->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE);
@ -824,7 +891,7 @@ void lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFrame
glBindFramebuffer(GL_READ_FRAMEBUFFER, RenderFramebuffer.first.mObject); glBindFramebuffer(GL_READ_FRAMEBUFFER, RenderFramebuffer.first.mObject);
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
QOpenGLFunctions_3_2_Core* Funcs = mGLContext->versionFunctions<QOpenGLFunctions_3_2_Core>(); QOpenGLFunctions_3_2_Core* Funcs = mContext->versionFunctions<QOpenGLFunctions_3_2_Core>();
Funcs->glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR); Funcs->glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
#else #else
glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);

View file

@ -120,16 +120,23 @@ public:
lcContext(const lcContext&) = delete; lcContext(const lcContext&) = delete;
lcContext& operator=(const lcContext&) = delete; lcContext& operator=(const lcContext&) = delete;
#ifdef LC_USE_QOPENGLWIDGET
static bool CreateOffscreenContext();
static void DestroyOffscreenContext();
#endif
void CreateResources(); void CreateResources();
void DestroyResources(); void DestroyResources();
void SetDefaultState(); void SetDefaultState();
void ClearResources(); void ClearResources();
void MakeCurrent();
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
void SetGLContext(QOpenGLContext* GLContext); void SetGLContext(QOpenGLContext* GLContext, QOpenGLWidget* Widget);
void SetOffscreenContext();
#else #else
void SetGLContext(const QGLContext* GLContext); void SetGLContext(const QGLContext* GLContext, QGLWidget* Widget);
#endif #endif
void ClearColorAndDepth(const lcVector4& ClearColor); void ClearColorAndDepth(const lcVector4& ClearColor);
@ -234,7 +241,8 @@ protected:
void FlushState(); void FlushState();
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
QOpenGLContext* mGLContext = nullptr; QOpenGLWidget* mWidget = nullptr;
QOpenGLContext* mContext = nullptr;
#endif #endif
bool mValid = false; bool mValid = false;
@ -273,6 +281,11 @@ protected:
GLuint mFramebufferObject; GLuint mFramebufferObject;
#ifdef LC_USE_QOPENGLWIDGET
static std::unique_ptr<QOpenGLContext> mOffscreenContext;
static std::unique_ptr<QOffscreenSurface> mOffscreenSurface;
#endif
static lcProgram mPrograms[static_cast<int>(lcMaterialType::Count)]; static lcProgram mPrograms[static_cast<int>(lcMaterialType::Count)];
static int mValidContexts; static int mValidContexts;

View file

@ -1276,9 +1276,12 @@ QImage lcModel::GetStepImage(bool Zoom, int Width, int Height, lcStep Step)
lcCamera* Camera = ActiveView->GetCamera(); lcCamera* Camera = ActiveView->GetCamera();
lcView View(lcViewType::View, this); 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(); ActiveView->MakeCurrent();
lcContext* Context = ActiveView->mContext; lcContext* Context = ActiveView->mContext;
View.SetContext(Context); View.SetContext(Context);

View file

@ -398,6 +398,9 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex)
{ {
mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, nullptr)); mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, nullptr));
mView->SetOffscreenContext();
mView->MakeCurrent();
if (!mView->BeginRenderToImage(Width, Height)) if (!mView->BeginRenderToImage(Width, Height))
{ {
mView.reset(); mView.reset();
@ -406,6 +409,7 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex)
} }
mView->MakeCurrent(); mView->MakeCurrent();
mView->BindRenderFramebuffer();
lcContext* Context = mView->mContext; lcContext* Context = mView->mContext;
#else #else
@ -456,6 +460,7 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex)
Scene.Draw(Context); Scene.Draw(Context);
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
mView->UnbindRenderFramebuffer();
QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32); QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32);
#else #else
QImage Image = Context->GetRenderFramebufferImage(mRenderFramebuffer); QImage Image = Context->GetRenderFramebufferImage(mRenderFramebuffer);

View file

@ -76,12 +76,7 @@ void lcView::UpdateAllViews()
void lcView::MakeCurrent() void lcView::MakeCurrent()
{ {
if (mWidget) mContext->MakeCurrent();
mWidget->makeCurrent();
#ifdef LC_USE_QOPENGLWIDGET
else if (mOffscreenContext)
mOffscreenContext->makeCurrent(mOffscreenSurface.get());
#endif
} }
void lcView::Redraw() void lcView::Redraw()
@ -90,6 +85,15 @@ void lcView::Redraw()
mWidget->update(); mWidget->update();
} }
#ifdef LC_USE_QOPENGLWIDGET
void lcView::SetOffscreenContext()
{
mContext->SetOffscreenContext();
}
#else
void lcView::SetContext(lcContext* Context) void lcView::SetContext(lcContext* Context)
{ {
if (mDeleteContext) if (mDeleteContext)
@ -99,6 +103,8 @@ void lcView::SetContext(lcContext* Context)
mDeleteContext = false; mDeleteContext = false;
} }
#endif
void lcView::SetFocus(bool Focus) void lcView::SetFocus(bool Focus)
{ {
if (Focus) if (Focus)
@ -725,36 +731,6 @@ lcArray<lcObject*> lcView::FindObjectsInBox(float x1, float y1, float x2, float
bool lcView::BeginRenderToImage(int Width, int Height) bool lcView::BeginRenderToImage(int Width, int Height)
{ {
#ifdef LC_USE_QOPENGLWIDGET
std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
if (!OffscreenContext)
return false;
OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
if (!OffscreenContext->create() || !OffscreenContext->isValid())
return false;
std::unique_ptr<QOffscreenSurface> 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; GLint MaxTexture;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture);
@ -795,8 +771,6 @@ bool lcView::BeginRenderToImage(int Width, int Height)
void lcView::EndRenderToImage() void lcView::EndRenderToImage()
{ {
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
mOffscreenContext.reset();
mOffscreenSurface.reset();
mRenderFramebuffer.reset(); mRenderFramebuffer.reset();
#else #else
mRenderImage = QImage(); mRenderImage = QImage();
@ -812,13 +786,19 @@ QImage lcView::GetRenderImage() const
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
QImage lcView::GetRenderFramebufferImage() const void lcView::BindRenderFramebuffer()
{
mRenderFramebuffer->bind();
}
void lcView::UnbindRenderFramebuffer()
{ {
mRenderFramebuffer->release(); mRenderFramebuffer->release();
QImage Image = mRenderFramebuffer->toImage(); }
mRenderFramebuffer->bind();
return Image; QImage lcView::GetRenderFramebufferImage() const
{
return mRenderFramebuffer->toImage();
} }
#endif #endif
@ -918,7 +898,9 @@ void lcView::OnDraw()
if (!mRenderImage.isNull()) if (!mRenderImage.isNull())
{ {
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
UnbindRenderFramebuffer();
QImage TileImage = GetRenderFramebufferImage(); QImage TileImage = GetRenderFramebufferImage();
BindRenderFramebuffer();
quint8* Buffer = TileImage.bits(); quint8* Buffer = TileImage.bits();
#else #else
quint8* Buffer = (quint8*)malloc(mWidth * mHeight * 4); quint8* Buffer = (quint8*)malloc(mWidth * mHeight * 4);

View file

@ -176,7 +176,12 @@ public:
void MakeCurrent(); void MakeCurrent();
void Redraw(); void Redraw();
#ifdef LC_USE_QOPENGLWIDGET
void SetOffscreenContext();
#else
void SetContext(lcContext* Context); void SetContext(lcContext* Context);
#endif
void SetFocus(bool Focus); void SetFocus(bool Focus);
void SetMousePosition(int MouseX, int MouseY); void SetMousePosition(int MouseX, int MouseY);
@ -236,6 +241,8 @@ public:
void EndRenderToImage(); void EndRenderToImage();
QImage GetRenderImage() const; QImage GetRenderImage() const;
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
void BindRenderFramebuffer();
void UnbindRenderFramebuffer();
QImage GetRenderFramebufferImage() const; QImage GetRenderFramebufferImage() const;
#endif #endif
@ -300,8 +307,6 @@ protected:
QImage mRenderImage; QImage mRenderImage;
#ifdef LC_USE_QOPENGLWIDGET #ifdef LC_USE_QOPENGLWIDGET
std::unique_ptr<QOpenGLContext> mOffscreenContext;
std::unique_ptr<QOffscreenSurface> mOffscreenSurface;
std::unique_ptr<QOpenGLFramebufferObject> mRenderFramebuffer; std::unique_ptr<QOpenGLFramebufferObject> mRenderFramebuffer;
#else #else
std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer; std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer;

View file

@ -56,7 +56,7 @@ void lcViewWidget::SetView(lcView* View)
if (context()) if (context())
{ {
makeCurrent(); makeCurrent();
View->mContext->SetGLContext(context()); View->mContext->SetGLContext(context(), this);
} }
View->SetWidget(this); View->SetWidget(this);
@ -73,7 +73,7 @@ void lcViewWidget::SetView(lcView* View)
void lcViewWidget::initializeGL() void lcViewWidget::initializeGL()
{ {
mView->mContext->SetGLContext(context()); mView->mContext->SetGLContext(context(), this);
} }
void lcViewWidget::resizeGL(int Width, int Height) void lcViewWidget::resizeGL(int Width, int Height)

View file

@ -3,6 +3,7 @@
#include "lc_qupdatedialog.h" #include "lc_qupdatedialog.h"
#include "lc_mainwindow.h" #include "lc_mainwindow.h"
#include "lc_profile.h" #include "lc_profile.h"
#include "lc_context.h"
#include <QApplication> #include <QApplication>
#include <locale.h> #include <locale.h>
@ -197,6 +198,10 @@ int main(int argc, char *argv[])
ExecReturn = Application.exec(); ExecReturn = Application.exec();
} }
#ifdef LC_USE_QOPENGLWIDGET
lcContext::DestroyOffscreenContext();
#endif
delete gMainWindow; delete gMainWindow;
gMainWindow = nullptr; gMainWindow = nullptr;