vcl: Use std::list to manage OpenGLContexts in ImplSVGDIData

... instead of manually implementing a doubly-linked
list.

(All entries are non-null, so no need for
keeping null checks where they were previously only
used to check whether there is a previous/next element.)

Change-Id: Iff56b21e36b705803718b594e6d9ec66a85fa698
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/202455
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
This commit is contained in:
Michael Weghorn
2026-03-24 21:39:56 +01:00
parent 2a2db37b56
commit 75d1ea1171
4 changed files with 21 additions and 50 deletions
-6
View File
@@ -117,12 +117,6 @@ protected:
bool mbInitialized;
int mnRefCount;
bool mbRequestLegacyContext;
public:
// Don't hold references to ourselves:
OpenGLContext *mpPrevContext;
OpenGLContext *mpNextContext;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+2 -1
View File
@@ -51,6 +51,7 @@
#include "displayconnectiondispatch.hxx"
#include <atomic>
#include <list>
#include <mutex>
#include <optional>
#include <vector>
@@ -229,7 +230,7 @@ struct ImplSVGDIData
VclPtr<Printer> mpFirstPrnGraphics; // First OutputDevice with an InfoPrinter Graphics
VclPtr<Printer> mpLastPrnGraphics; // Last OutputDevice with an InfoPrinter Graphics
VclPtr<VirtualDevice> mpFirstVirDev; // First VirtualDevice
OpenGLContext* mpLastContext = nullptr; // Last OpenGLContext
std::list<OpenGLContext*> maOpenGLContexts; // OpenGL contexts
VclPtr<Printer> mpFirstPrinter; // First Printer
std::unique_ptr<ImplPrnQueueList> mpPrinterQueueList; // List of all printer queue
std::shared_ptr<vcl::font::PhysicalFontCollection> mxScreenFontList; // Screen-Font-List
+15 -38
View File
@@ -45,19 +45,12 @@ OpenGLContext::OpenGLContext():
m_pChildWindow(nullptr),
mbInitialized(false),
mnRefCount(0),
mbRequestLegacyContext(false),
mpPrevContext(nullptr),
mpNextContext(nullptr)
mbRequestLegacyContext(false)
{
VCL_GL_INFO("new context: " << this);
ImplSVData* pSVData = ImplGetSVData();
if( pSVData->maGDIData.mpLastContext )
{
pSVData->maGDIData.mpLastContext->mpNextContext = this;
mpPrevContext = pSVData->maGDIData.mpLastContext;
}
pSVData->maGDIData.mpLastContext = this;
pSVData->maGDIData.maOpenGLContexts.push_back(this);
// FIXME: better hope we call 'makeCurrent' soon to preserve
// the invariant that the last item is the current context.
@@ -72,13 +65,7 @@ OpenGLContext::~OpenGLContext()
reset();
ImplSVData* pSVData = ImplGetSVData();
if( mpPrevContext )
mpPrevContext->mpNextContext = mpNextContext;
if( mpNextContext )
mpNextContext->mpPrevContext = mpPrevContext;
else
pSVData->maGDIData.mpLastContext = mpPrevContext;
ImplGetSVData()->maGDIData.maOpenGLContexts.remove(this);
m_pChildWindow.disposeAndClear();
assert (mnRefCount == 1);
@@ -379,8 +366,10 @@ bool OpenGLContext::isAnyCurrent()
bool OpenGLContext::hasCurrent()
{
ImplSVData* pSVData = ImplGetSVData();
rtl::Reference<OpenGLContext> pCurrentCtx = pSVData->maGDIData.mpLastContext;
return pCurrentCtx.is() && pCurrentCtx->isAnyCurrent();
if (pSVData->maGDIData.maOpenGLContexts.empty())
return false;
return pSVData->maGDIData.maOpenGLContexts.back()->isAnyCurrent();
}
void OpenGLContext::prepareForYield()
@@ -389,25 +378,22 @@ void OpenGLContext::prepareForYield()
// release all framebuffers from the old context so we can re-attach the
// texture in the new context
rtl::Reference<OpenGLContext> pCurrentCtx = pSVData->maGDIData.mpLastContext;
if ( !pCurrentCtx.is() )
return; // Not using OpenGL
if (pSVData->maGDIData.maOpenGLContexts.empty())
return; // Not using OpenGL
SAL_INFO("vcl.opengl", "Unbinding contexts in preparation for yield");
// Find the first context that is current and reset it.
// Usually the last context is the current, but not in case a new
// OpenGLContext is created already but not yet initialized.
while (pCurrentCtx.is())
for (auto aContextIt = pSVData->maGDIData.maOpenGLContexts.rbegin();
aContextIt != pSVData->maGDIData.maOpenGLContexts.rend(); ++aContextIt)
{
if (pCurrentCtx->isCurrent())
if ((*aContextIt)->isCurrent())
{
pCurrentCtx->resetCurrent();
(*aContextIt)->resetCurrent();
break;
}
pCurrentCtx = pCurrentCtx->mpPrevContext;
}
assert (!hasCurrent());
@@ -420,17 +406,8 @@ void OpenGLContext::registerAsCurrent()
// move the context to the end of the contexts list
static int nSwitch = 0;
VCL_GL_INFO("******* CONTEXT SWITCH " << ++nSwitch << " *********");
if( mpNextContext )
{
if( mpPrevContext )
mpPrevContext->mpNextContext = mpNextContext;
mpNextContext->mpPrevContext = mpPrevContext;
mpPrevContext = pSVData->maGDIData.mpLastContext;
mpNextContext = nullptr;
pSVData->maGDIData.mpLastContext->mpNextContext = this;
pSVData->maGDIData.mpLastContext = this;
}
pSVData->maGDIData.maOpenGLContexts.remove(this);
pSVData->maGDIData.maOpenGLContexts.push_back(this);
}
void OpenGLContext::resetCurrent()
+4 -5
View File
@@ -814,12 +814,11 @@ X11SalFrame::~X11SalFrame()
pFreeGraphics_.reset();
// reset all OpenGL contexts using this window
rtl::Reference<OpenGLContext> pContext = ImplGetSVData()->maGDIData.mpLastContext;
while( pContext.is() )
const std::list<OpenGLContext*>& rContexts = ImplGetSVData()->maGDIData.maOpenGLContexts;
for (auto aContextIt = rContexts.rbegin(); aContextIt != rContexts.rend(); ++aContextIt)
{
if (static_cast<const GLX11Window&>(pContext->getOpenGLWindow()).win == mhWindow)
pContext->reset();
pContext = pContext->mpPrevContext;
if (static_cast<const GLX11Window&>((*aContextIt)->getOpenGLWindow()).win == mhWindow)
(*aContextIt)->reset();
}
if (mpSurface)