OpenGL: Improve logic when bitmap cache memory is exhausted.
Don't remove the front entry, as it will likely be needed for the next bitmap.
Instead, implement neuristics based on access times.
(cherry picked from commit 71d0c7f6af
)
This commit is contained in:
parent
75c758e5f4
commit
b461a3b64d
|
@ -97,6 +97,7 @@ private:
|
||||||
GLuint id;
|
GLuint id;
|
||||||
int w, h;
|
int w, h;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
long long int accessTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
GLuint cacheBitmap( const BITMAP_BASE* aBitmap );
|
GLuint cacheBitmap( const BITMAP_BASE* aBitmap );
|
||||||
|
@ -130,6 +131,7 @@ GLuint GL_BITMAP_CACHE::RequestBitmap( const BITMAP_BASE* aBitmap )
|
||||||
// A bitmap is found in cache bitmap. Ensure the associated texture is still valid.
|
// A bitmap is found in cache bitmap. Ensure the associated texture is still valid.
|
||||||
if( glIsTexture( it->second.id ) )
|
if( glIsTexture( it->second.id ) )
|
||||||
{
|
{
|
||||||
|
it->second.accessTime = wxGetUTCTimeMillis().GetValue();
|
||||||
return it->second.id;
|
return it->second.id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -243,26 +245,52 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||||
|
|
||||||
|
long long currentTime = wxGetUTCTimeMillis().GetValue();
|
||||||
|
|
||||||
bmp.id = textureID;
|
bmp.id = textureID;
|
||||||
|
bmp.accessTime = currentTime;
|
||||||
|
|
||||||
#ifndef DISABLE_BITMAP_CACHE
|
#ifndef DISABLE_BITMAP_CACHE
|
||||||
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
if( m_cacheLru.size() + 1 > m_cacheMaxElements || m_cacheSize + bmp.size > m_cacheMaxSize )
|
||||||
m_cacheSize += bmp.size;
|
|
||||||
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
|
||||||
|
|
||||||
if( m_cacheLru.size() > m_cacheMaxElements
|
|
||||||
|| m_cacheSize > m_cacheMaxSize )
|
|
||||||
{
|
{
|
||||||
KIID last = m_cacheLru.front();
|
KIID toRemove( 0 );
|
||||||
CACHED_BITMAP& cachedBitmap = m_bitmaps[last];
|
auto toRemoveLru = m_cacheLru.end();
|
||||||
|
|
||||||
|
// Remove entries accessed > 1s ago first
|
||||||
|
for( const auto& [kiid, bmp] : m_bitmaps )
|
||||||
|
{
|
||||||
|
const int cacheTimeoutMillis = 1000L;
|
||||||
|
|
||||||
|
if( currentTime - bmp.accessTime > cacheTimeoutMillis )
|
||||||
|
{
|
||||||
|
toRemove = kiid;
|
||||||
|
toRemoveLru = std::find( m_cacheLru.begin(), m_cacheLru.end(), toRemove );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, remove the latest entry (it's less likely to be needed soon)
|
||||||
|
if( toRemove == niluuid )
|
||||||
|
{
|
||||||
|
toRemoveLru = m_cacheLru.end();
|
||||||
|
toRemoveLru--;
|
||||||
|
|
||||||
|
toRemove = *toRemoveLru;
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHED_BITMAP& cachedBitmap = m_bitmaps[toRemove];
|
||||||
|
|
||||||
m_cacheSize -= cachedBitmap.size;
|
m_cacheSize -= cachedBitmap.size;
|
||||||
glDeleteTextures( 1, &cachedBitmap.id );
|
glDeleteTextures( 1, &cachedBitmap.id );
|
||||||
m_freedTextureIds.emplace_back( cachedBitmap.id );
|
m_freedTextureIds.emplace_back( cachedBitmap.id );
|
||||||
|
|
||||||
m_bitmaps.erase( last );
|
m_bitmaps.erase( toRemove );
|
||||||
m_cacheLru.pop_front();
|
m_cacheLru.erase( toRemoveLru );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
||||||
|
m_cacheSize += bmp.size;
|
||||||
|
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return textureID;
|
return textureID;
|
||||||
|
|
Loading…
Reference in New Issue