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
|
class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<ImplOpenGLTexture>> mpTextures;
|
std::vector<ImplOpenGLTexture *> mpTextures;
|
||||||
|
|
||||||
int mWidthFactor;
|
int mWidthFactor;
|
||||||
int mHeightFactor;
|
int mHeightFactor;
|
||||||
@@ -26,6 +26,7 @@ class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nTextureSize);
|
FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nTextureSize);
|
||||||
|
~FixedTextureAtlasManager();
|
||||||
OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
|
OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
|
||||||
|
|
||||||
int GetSubtextureSize()
|
int GetSubtextureSize()
|
||||||
|
@@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
class ImplOpenGLTexture
|
class ImplOpenGLTexture
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
int mnRefCount;
|
int mnRefCount;
|
||||||
|
public:
|
||||||
GLuint mnTexture;
|
GLuint mnTexture;
|
||||||
int mnWidth;
|
int mnWidth;
|
||||||
int mnHeight;
|
int mnHeight;
|
||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, void const * pData );
|
ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, void const * pData );
|
||||||
ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
|
ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
|
||||||
~ImplOpenGLTexture();
|
~ImplOpenGLTexture();
|
||||||
|
void Dispose();
|
||||||
|
|
||||||
bool InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
|
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)
|
if (mpSlotReferences->at(nSlotNumber) == 0)
|
||||||
mnFreeSlots++;
|
mnFreeSlots++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mnRefCount <= 0)
|
||||||
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExistRefs()
|
bool IsUnique()
|
||||||
{
|
{
|
||||||
return mnRefCount > 0;
|
return mnRefCount == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InitializeSlots(int nSlotSize);
|
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()
|
void FixedTextureAtlasManager::CreateNewTexture()
|
||||||
{
|
{
|
||||||
int nTextureWidth = mWidthFactor * mSubTextureSize;
|
int nTextureWidth = mWidthFactor * mSubTextureSize;
|
||||||
int nTextureHeight = mHeightFactor * 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);
|
mpTextures.back()->InitializeSlots(mWidthFactor * mHeightFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,21 +46,21 @@ OpenGLTexture FixedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, in
|
|||||||
{
|
{
|
||||||
ImplOpenGLTexture* pTexture = nullptr;
|
ImplOpenGLTexture* pTexture = nullptr;
|
||||||
|
|
||||||
auto funFreeSlot = [] (std::unique_ptr<ImplOpenGLTexture>& mpTexture)
|
auto funFreeSlot = [] (ImplOpenGLTexture *mpTexture)
|
||||||
{
|
{
|
||||||
return mpTexture->mnFreeSlots > 0;
|
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
|
else
|
||||||
{
|
{
|
||||||
CreateNewTexture();
|
CreateNewTexture();
|
||||||
pTexture = mpTextures.back().get();
|
pTexture = mpTextures.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
int nSlot = pTexture->FindFreeSlot();
|
int nSlot = pTexture->FindFreeSlot();
|
||||||
|
@@ -157,6 +157,11 @@ GLuint ImplOpenGLTexture::AddStencil()
|
|||||||
ImplOpenGLTexture::~ImplOpenGLTexture()
|
ImplOpenGLTexture::~ImplOpenGLTexture()
|
||||||
{
|
{
|
||||||
VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
|
VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImplOpenGLTexture::Dispose()
|
||||||
|
{
|
||||||
if( mnTexture != 0 )
|
if( mnTexture != 0 )
|
||||||
{
|
{
|
||||||
OpenGLVCLContextZone aContextZone;
|
OpenGLVCLContextZone aContextZone;
|
||||||
@@ -173,8 +178,12 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( mnOptStencil != 0 )
|
if( mnOptStencil != 0 )
|
||||||
|
{
|
||||||
glDeleteRenderbuffers( 1, &mnOptStencil );
|
glDeleteRenderbuffers( 1, &mnOptStencil );
|
||||||
|
mnOptStencil = 0;
|
||||||
|
}
|
||||||
glDeleteTextures( 1, &mnTexture );
|
glDeleteTextures( 1, &mnTexture );
|
||||||
|
mnTexture = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,16 +294,12 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
|
|||||||
OpenGLTexture::~OpenGLTexture()
|
OpenGLTexture::~OpenGLTexture()
|
||||||
{
|
{
|
||||||
if (mpImpl)
|
if (mpImpl)
|
||||||
{
|
|
||||||
mpImpl->DecreaseRefCount(mnSlotNumber);
|
mpImpl->DecreaseRefCount(mnSlotNumber);
|
||||||
if (!mpImpl->ExistRefs())
|
|
||||||
delete mpImpl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLTexture::IsUnique() const
|
bool OpenGLTexture::IsUnique() const
|
||||||
{
|
{
|
||||||
return ( mpImpl == nullptr || mpImpl->mnRefCount == 1 );
|
return mpImpl == nullptr || mpImpl->IsUnique();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint OpenGLTexture::Id() const
|
GLuint OpenGLTexture::Id() const
|
||||||
@@ -484,11 +489,7 @@ OpenGLTexture& OpenGLTexture::operator=( const OpenGLTexture& rTexture )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mpImpl)
|
if (mpImpl)
|
||||||
{
|
|
||||||
mpImpl->DecreaseRefCount(mnSlotNumber);
|
mpImpl->DecreaseRefCount(mnSlotNumber);
|
||||||
if (!mpImpl->ExistRefs())
|
|
||||||
delete mpImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
maRect = rTexture.maRect;
|
maRect = rTexture.maRect;
|
||||||
mpImpl = rTexture.mpImpl;
|
mpImpl = rTexture.mpImpl;
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vcl/salbtype.hxx>
|
#include <vcl/salbtype.hxx>
|
||||||
|
#include <vcl/lazydelete.hxx>
|
||||||
|
|
||||||
#include <svdata.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 typename std::pair<ControlCacheKey, std::unique_ptr<TextureCombo>> ControlCachePair;
|
||||||
typedef o3tl::lru_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
|
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)
|
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");
|
static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE");
|
||||||
|
|
||||||
if (!gbCacheEnabled)
|
if (!gbCacheEnabled || !gTextureCache.get())
|
||||||
return false;
|
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;
|
return false;
|
||||||
|
|
||||||
const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
|
const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
|
||||||
@@ -229,7 +230,8 @@ bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
ControlCachePair pair(aControlCacheKey, std::move(pCombo));
|
ControlCachePair pair(aControlCacheKey, std::move(pCombo));
|
||||||
gTextureCache.insert(std::move(pair));
|
if (gTextureCache.get())
|
||||||
|
gTextureCache.get()->insert(std::move(pair));
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user