vcl: fix lifecycle errors & memory corruption.
FixedTextureAtlasManager should use ref-counted textures properly. Also - dispose embedded textures early in VCL shutdown while we have a valid OpenGLContext. Also - dispose the native widget control cache earlier too. Change-Id: Id3f7a1c3b331496616f36cbf02f83737505278a5 Reviewed-on: https://gerrit.libreoffice.org/21148 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
|
||||
{
|
||||
std::vector<std::unique_ptr<ImplOpenGLTexture>> mpTextures;
|
||||
std::vector<ImplOpenGLTexture *> mpTextures;
|
||||
|
||||
int mWidthFactor;
|
||||
int mHeightFactor;
|
||||
@@ -26,6 +26,7 @@ class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
|
||||
|
||||
public:
|
||||
FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nTextureSize);
|
||||
~FixedTextureAtlasManager();
|
||||
OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
|
||||
|
||||
int GetSubtextureSize()
|
||||
|
@@ -31,8 +31,8 @@
|
||||
|
||||
class ImplOpenGLTexture
|
||||
{
|
||||
public:
|
||||
int mnRefCount;
|
||||
public:
|
||||
GLuint mnTexture;
|
||||
int mnWidth;
|
||||
int mnHeight;
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, void const * pData );
|
||||
ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
|
||||
~ImplOpenGLTexture();
|
||||
void Dispose();
|
||||
|
||||
bool InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
|
||||
|
||||
@@ -69,11 +70,14 @@ public:
|
||||
if (mpSlotReferences->at(nSlotNumber) == 0)
|
||||
mnFreeSlots++;
|
||||
}
|
||||
|
||||
if (mnRefCount <= 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool ExistRefs()
|
||||
bool IsUnique()
|
||||
{
|
||||
return mnRefCount > 0;
|
||||
return mnRefCount == 1;
|
||||
}
|
||||
|
||||
bool InitializeSlots(int nSlotSize);
|
||||
|
@@ -24,11 +24,21 @@ FixedTextureAtlasManager::FixedTextureAtlasManager(int nWidthFactor, int nHeight
|
||||
{
|
||||
}
|
||||
|
||||
FixedTextureAtlasManager::~FixedTextureAtlasManager()
|
||||
{
|
||||
for (auto i = mpTextures.begin(); i != mpTextures.end(); ++i)
|
||||
{
|
||||
// Free texture early in VCL shutdown while we have a context.
|
||||
(*i)->Dispose();
|
||||
(*i)->DecreaseRefCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTextureAtlasManager::CreateNewTexture()
|
||||
{
|
||||
int nTextureWidth = mWidthFactor * mSubTextureSize;
|
||||
int nTextureHeight = mHeightFactor * mSubTextureSize;
|
||||
mpTextures.push_back(std::unique_ptr<ImplOpenGLTexture>(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true)));
|
||||
mpTextures.push_back(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true));
|
||||
mpTextures.back()->InitializeSlots(mWidthFactor * mHeightFactor);
|
||||
}
|
||||
|
||||
@@ -36,21 +46,21 @@ OpenGLTexture FixedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, in
|
||||
{
|
||||
ImplOpenGLTexture* pTexture = nullptr;
|
||||
|
||||
auto funFreeSlot = [] (std::unique_ptr<ImplOpenGLTexture>& mpTexture)
|
||||
auto funFreeSlot = [] (ImplOpenGLTexture *mpTexture)
|
||||
{
|
||||
return mpTexture->mnFreeSlots > 0;
|
||||
};
|
||||
|
||||
auto aIterator = std::find_if(mpTextures.begin(), mpTextures.end(), funFreeSlot);
|
||||
auto it = std::find_if(mpTextures.begin(), mpTextures.end(), funFreeSlot);
|
||||
|
||||
if (aIterator != mpTextures.end())
|
||||
if (it != mpTextures.end())
|
||||
{
|
||||
pTexture = (*aIterator).get();
|
||||
pTexture = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateNewTexture();
|
||||
pTexture = mpTextures.back().get();
|
||||
pTexture = mpTextures.back();
|
||||
}
|
||||
|
||||
int nSlot = pTexture->FindFreeSlot();
|
||||
|
@@ -157,6 +157,11 @@ GLuint ImplOpenGLTexture::AddStencil()
|
||||
ImplOpenGLTexture::~ImplOpenGLTexture()
|
||||
{
|
||||
VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void ImplOpenGLTexture::Dispose()
|
||||
{
|
||||
if( mnTexture != 0 )
|
||||
{
|
||||
OpenGLVCLContextZone aContextZone;
|
||||
@@ -173,8 +178,12 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
|
||||
}
|
||||
|
||||
if( mnOptStencil != 0 )
|
||||
{
|
||||
glDeleteRenderbuffers( 1, &mnOptStencil );
|
||||
mnOptStencil = 0;
|
||||
}
|
||||
glDeleteTextures( 1, &mnTexture );
|
||||
mnTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,16 +294,12 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
|
||||
OpenGLTexture::~OpenGLTexture()
|
||||
{
|
||||
if (mpImpl)
|
||||
{
|
||||
mpImpl->DecreaseRefCount(mnSlotNumber);
|
||||
if (!mpImpl->ExistRefs())
|
||||
delete mpImpl;
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGLTexture::IsUnique() const
|
||||
{
|
||||
return ( mpImpl == nullptr || mpImpl->mnRefCount == 1 );
|
||||
return mpImpl == nullptr || mpImpl->IsUnique();
|
||||
}
|
||||
|
||||
GLuint OpenGLTexture::Id() const
|
||||
@@ -484,11 +489,7 @@ OpenGLTexture& OpenGLTexture::operator=( const OpenGLTexture& rTexture )
|
||||
}
|
||||
|
||||
if (mpImpl)
|
||||
{
|
||||
mpImpl->DecreaseRefCount(mnSlotNumber);
|
||||
if (!mpImpl->ExistRefs())
|
||||
delete mpImpl;
|
||||
}
|
||||
|
||||
maRect = rTexture.maRect;
|
||||
mpImpl = rTexture.mpImpl;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <vcl/salbtype.hxx>
|
||||
#include <vcl/lazydelete.hxx>
|
||||
|
||||
#include <svdata.hxx>
|
||||
|
||||
@@ -105,7 +106,7 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
|
||||
typedef typename std::pair<ControlCacheKey, std::unique_ptr<TextureCombo>> ControlCachePair;
|
||||
typedef o3tl::lru_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
|
||||
|
||||
ControlCacheType gTextureCache(200);
|
||||
vcl::DeleteOnDeinit<ControlCacheType> gTextureCache(new ControlCacheType(200));
|
||||
|
||||
bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo)
|
||||
{
|
||||
@@ -190,12 +191,12 @@ bool X11OpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& rCo
|
||||
{
|
||||
static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE");
|
||||
|
||||
if (!gbCacheEnabled)
|
||||
if (!gbCacheEnabled || !gTextureCache.get())
|
||||
return false;
|
||||
|
||||
ControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
|
||||
ControlCacheType::const_iterator iterator = gTextureCache.get()->find(rControlCacheKey);
|
||||
|
||||
if (iterator == gTextureCache.end())
|
||||
if (iterator == gTextureCache.get()->end())
|
||||
return false;
|
||||
|
||||
const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
|
||||
@@ -229,7 +230,8 @@ bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X
|
||||
return true;
|
||||
|
||||
ControlCachePair pair(aControlCacheKey, std::move(pCombo));
|
||||
gTextureCache.insert(std::move(pair));
|
||||
if (gTextureCache.get())
|
||||
gTextureCache.get()->insert(std::move(pair));
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
Reference in New Issue
Block a user