TextureCacheCompositingThread.cpp [plain text]
#include "config.h"
#include "TextureCacheCompositingThread.h"
#if USE(ACCELERATED_COMPOSITING)
#include "IntRect.h"
#include <GLES2/gl2.h>
#include <wtf/Assertions.h>
using BlackBerry::Platform::Graphics::Buffer;
using BlackBerry::Platform::Graphics::BufferType;
#define DEBUG_TEXTURE_MEMORY_USAGE 0
namespace WebCore {
static const int defaultMemoryLimit = 64 * 1024 * 1024;
class TextureProtector {
public:
TextureProtector(LayerTexture* texture)
: m_texture(texture)
{
m_texture->protect();
}
~TextureProtector()
{
m_texture->unprotect();
}
private:
LayerTexture* m_texture;
};
TextureCacheCompositingThread::TextureCacheCompositingThread()
: m_memoryUsage(0)
, m_memoryLimit(defaultMemoryLimit)
{
}
Buffer* TextureCacheCompositingThread::createBuffer(const IntSize& size, BufferType type)
{
return BlackBerry::Platform::Graphics::createBuffer(size, type);
}
void TextureCacheCompositingThread::collectGarbage()
{
for (Garbage::iterator it = m_garbage.begin(); it != m_garbage.end(); ++it)
BlackBerry::Platform::Graphics::destroyBuffer((*it).buffer);
m_garbage.clear();
}
void TextureCacheCompositingThread::textureResized(LayerTexture* texture, const IntSize& oldSize)
{
int delta = (texture->width() * texture->height() - oldSize.width() * oldSize.height()) * LayerTexture::bytesPerPixel();
incMemoryUsage(delta);
if (delta > 0)
prune();
}
void TextureCacheCompositingThread::textureSizeInBytesChanged(LayerTexture*, int delta)
{
incMemoryUsage(delta);
if (delta > 0)
prune();
}
void TextureCacheCompositingThread::textureDestroyed(LayerTexture* texture)
{
if (texture->isColor()) {
m_garbage.append(ZombieTexture(texture));
return;
}
TextureSet::iterator it = m_textures.find(texture);
evict(it);
m_textures.remove(it);
}
bool TextureCacheCompositingThread::install(LayerTexture* texture, const IntSize& size, BufferType type)
{
if (!texture)
return true;
if (!texture->buffer() && !size.isEmpty()) {
Buffer* buffer = createBuffer(size, type);
ASSERT(buffer);
texture->setBuffer(buffer);
texture->setSize(size);
textureResized(texture, IntSize());
}
if (!texture->isColor())
m_textures.add(texture);
return true;
}
bool TextureCacheCompositingThread::resizeTexture(LayerTexture* texture, const IntSize& size, BufferType type)
{
IntSize oldSize = texture->size();
Buffer* buffer = createBuffer(size, type);
ASSERT(buffer);
BlackBerry::Platform::Graphics::destroyBuffer(texture->buffer());
texture->setBuffer(buffer);
texture->setSize(size);
textureResized(texture, oldSize);
return true;
}
void TextureCacheCompositingThread::evict(const TextureSet::iterator& it)
{
if (it == m_textures.end())
return;
LayerTexture* texture = *it;
if (texture->buffer()) {
int delta = 0;
delta += texture->width() * texture->height() * LayerTexture::bytesPerPixel();
delta += texture->sizeInBytes();
if (delta)
decMemoryUsage(delta);
m_garbage.append(ZombieTexture(texture));
}
texture->setBuffer(0);
}
void TextureCacheCompositingThread::textureAccessed(LayerTexture* texture)
{
if (texture->isColor())
return;
TextureSet::iterator it = m_textures.find(texture);
if (it == m_textures.end())
return;
m_textures.remove(it);
m_textures.add(texture);
}
TextureCacheCompositingThread* textureCacheCompositingThread()
{
static TextureCacheCompositingThread* staticCache = new TextureCacheCompositingThread;
return staticCache;
}
void TextureCacheCompositingThread::prune(size_t limit)
{
while (m_memoryUsage > limit) {
bool found = false;
for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) {
LayerTexture* texture = *it;
if (texture->isProtected() || (texture->size().isEmpty() && !texture->sizeInBytes()))
continue;
evict(it);
found = true;
break;
}
if (!found)
break;
}
}
void TextureCacheCompositingThread::clear()
{
m_colors.clear();
collectGarbage();
}
void TextureCacheCompositingThread::setMemoryUsage(size_t memoryUsage)
{
m_memoryUsage = memoryUsage;
#if DEBUG_TEXTURE_MEMORY_USAGE
fprintf(stderr, "Texture memory usage %u kB\n", m_memoryUsage / 1024);
#endif
}
PassRefPtr<LayerTexture> TextureCacheCompositingThread::textureForContents(Buffer* contents)
{
RefPtr<LayerTexture> texture = createTexture();
TextureProtector protector(texture.get());
texture->updateContents(contents);
return texture.release();
}
PassRefPtr<LayerTexture> TextureCacheCompositingThread::textureForColor(const Color& color)
{
if (m_colors.size() > 100)
m_colors.clear();
ColorTextureMap::iterator it = m_colors.find(color);
RefPtr<LayerTexture> texture;
if (it == m_colors.end()) {
texture = LayerTexture::create(true );
#if DEBUG_TEXTURE_MEMORY_USAGE
fprintf(stderr, "Creating texture 0x%x for color 0x%x\n", texture.get(), color.rgb());
#endif
m_colors.set(color, texture);
} else
texture = (*it).value;
if (texture->size() != IntSize(1, 1))
texture->setContentsToColor(color);
return texture.release();
}
PassRefPtr<LayerTexture> TextureCacheCompositingThread::updateContents(const RefPtr<LayerTexture>& textureIn, Buffer* contents)
{
RefPtr<LayerTexture> texture(textureIn);
if (!texture || texture->isColor())
texture = createTexture();
TextureProtector protector(texture.get());
texture->updateContents(contents);
return texture.release();
}
}
#endif