mirror of
https://github.com/leozide/leocad.git
synced 2026-10-27 06:20:55 +00:00
Restore caller GL state after output rendering
Step-image and parts-list helpers switched to the shared offscreen context and left it current after rendering. Framebuffer release and destruction also replaced a caller's existing binding with the default framebuffer. This violated the output helpers' state-restoration contract on both success and failure. Capture the caller's context, surface, and framebuffer bindings in a scope guard before asset waits and rendering. Restore them after the temporary view is destroyed, preserving separate draw/read bindings where supported and leaving no context current when the caller started without one. Validation: full debug build and whitespace checks passed. A temporary OpenGL regression harness verified step-image and parts-list success and framebuffer creation failure with an alternate caller context, an alternate surface on the shared context, nondefault framebuffer bindings, and no initially current context.
This commit is contained in:
1 parent
62a84dff86
commit
a152d3442c
3 files changed
+69
No files matched your search
@@ -29,6 +29,51 @@ std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
|
||||
std::unique_ptr<lcContext> lcContext::mGlobalOffscreenContext;
|
||||
lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
|
||||
|
||||
lcScopedGLContextState::lcScopedGLContextState()
|
||||
: mContext(QOpenGLContext::currentContext()), mSurface(mContext ? mContext->surface() : nullptr)
|
||||
{
|
||||
if (!mContext)
|
||||
return;
|
||||
|
||||
QOpenGLFunctions* Functions = mContext->functions();
|
||||
mSeparateFramebuffers = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
|
||||
|
||||
if (mSeparateFramebuffers)
|
||||
{
|
||||
Functions->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &mDrawFramebuffer);
|
||||
Functions->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &mReadFramebuffer);
|
||||
}
|
||||
else
|
||||
Functions->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mDrawFramebuffer);
|
||||
}
|
||||
|
||||
lcScopedGLContextState::~lcScopedGLContextState()
|
||||
{
|
||||
QOpenGLContext* CurrentContext = QOpenGLContext::currentContext();
|
||||
|
||||
if (!mContext)
|
||||
{
|
||||
if (CurrentContext)
|
||||
CurrentContext->doneCurrent();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentContext != mContext || mContext->surface() != mSurface)
|
||||
if (!mContext->makeCurrent(mSurface))
|
||||
return;
|
||||
|
||||
QOpenGLFunctions* Functions = mContext->functions();
|
||||
|
||||
if (mSeparateFramebuffers)
|
||||
{
|
||||
Functions->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
|
||||
Functions->glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
|
||||
}
|
||||
else
|
||||
Functions->glBindFramebuffer(GL_FRAMEBUFFER, mDrawFramebuffer);
|
||||
}
|
||||
|
||||
lcContext::lcContext()
|
||||
{
|
||||
mVertexBufferObject = 0;
|
||||
|
||||
@@ -106,6 +106,24 @@ struct lcVertexAttribState
|
||||
GLuint VertexBufferObject = 0;
|
||||
};
|
||||
|
||||
// Restores caller state after temporary rendering, including a caller with no current context.
|
||||
class lcScopedGLContextState
|
||||
{
|
||||
public:
|
||||
lcScopedGLContextState();
|
||||
~lcScopedGLContextState();
|
||||
|
||||
lcScopedGLContextState(const lcScopedGLContextState&) = delete;
|
||||
lcScopedGLContextState& operator=(const lcScopedGLContextState&) = delete;
|
||||
|
||||
private:
|
||||
QOpenGLContext* mContext;
|
||||
QSurface* mSurface;
|
||||
GLint mDrawFramebuffer = 0;
|
||||
GLint mReadFramebuffer = 0;
|
||||
bool mSeparateFramebuffers = false;
|
||||
};
|
||||
|
||||
class lcContext : public QOpenGLFunctions
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1695,6 +1695,8 @@ void lcModel::AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMat
|
||||
|
||||
QImage lcModel::GetStepImage(bool Zoom, int Width, int Height, lcStep Step)
|
||||
{
|
||||
lcScopedGLContextState GLState;
|
||||
|
||||
WaitForAssets();
|
||||
|
||||
const lcResult<QImage> Image = RenderStepImageWithReadyAssets(Zoom, Width, Height, Step, nullptr);
|
||||
@@ -1712,6 +1714,8 @@ QImage lcModel::GetStepImage(bool Zoom, int Width, int Height, lcStep Step)
|
||||
|
||||
lcResult<QImage> lcModel::RenderStepImageWithReadyAssets(bool Zoom, int Width, int Height, lcStep Step, lcCamera* OutputCamera)
|
||||
{
|
||||
lcScopedGLContextState GLState;
|
||||
|
||||
const lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr;
|
||||
const lcStep CurrentStep = mCurrentStep;
|
||||
|
||||
@@ -1762,6 +1766,8 @@ lcResult<QImage> lcModel::RenderStepImageWithReadyAssets(bool Zoom, int Width, i
|
||||
|
||||
QImage lcModel::GetPartsListImage(int MaxWidth, lcStep Step, quint32 BackgroundColor, QFont Font, QColor TextColor, bool KeepMissingParts) const
|
||||
{
|
||||
lcScopedGLContextState GLState;
|
||||
|
||||
WaitForAssets();
|
||||
|
||||
lcPartsList PartsList;
|
||||
|
||||
Reference in new issue
Block a user