TextureMapperPlatformLayerProxy.cpp [plain text]
#include "config.h"
#include "TextureMapperPlatformLayerProxy.h"
#if USE(COORDINATED_GRAPHICS_THREADED)
#include "BitmapTextureGL.h"
#include "TextureMapperGL.h"
#include "TextureMapperLayer.h"
#include "TextureMapperPlatformLayerBuffer.h"
const double s_releaseUnusedSecondsTolerance = 1;
const double s_releaseUnusedBuffersTimerInterval = 0.5;
namespace WebCore {
TextureMapperPlatformLayerProxy::TextureMapperPlatformLayerProxy()
: m_compositor(nullptr)
, m_targetLayer(nullptr)
, m_releaseUnusedBuffersTimer(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired)
{
}
TextureMapperPlatformLayerProxy::~TextureMapperPlatformLayerProxy()
{
LockHolder locker(m_lock);
if (m_targetLayer)
m_targetLayer->setContentsLayer(nullptr);
}
void TextureMapperPlatformLayerProxy::activateOnCompositingThread(Compositor* compositor, TextureMapperLayer* targetLayer)
{
#ifndef NDEBUG
m_compositorThreadID = m_compositorThreadID ? m_compositorThreadID : WTF::currentThread();
#endif
ASSERT(m_compositorThreadID == WTF::currentThread());
ASSERT(compositor);
ASSERT(targetLayer);
LockHolder locker(m_lock);
m_compositor = compositor;
m_targetLayer = targetLayer;
if (m_targetLayer && m_currentBuffer)
m_targetLayer->setContentsLayer(m_currentBuffer.get());
m_compositorThreadUpdateTimer = std::make_unique<RunLoop::Timer<TextureMapperPlatformLayerProxy>>(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired);
}
void TextureMapperPlatformLayerProxy::invalidate()
{
ASSERT(m_compositorThreadID == WTF::currentThread());
LockHolder locker(m_lock);
m_compositor = nullptr;
m_targetLayer = nullptr;
}
bool TextureMapperPlatformLayerProxy::isActive()
{
ASSERT(m_lock.isHeld());
return !!m_targetLayer && !!m_compositor;
}
void TextureMapperPlatformLayerProxy::pushNextBuffer(std::unique_ptr<TextureMapperPlatformLayerBuffer> newBuffer)
{
ASSERT(m_lock.isHeld());
m_pendingBuffer = WTFMove(newBuffer);
if (m_compositor)
m_compositor->onNewBufferAvailable();
}
std::unique_ptr<TextureMapperPlatformLayerBuffer> TextureMapperPlatformLayerProxy::getAvailableBuffer(const IntSize& size, GC3Dint internalFormat)
{
ASSERT(m_lock.isHeld());
std::unique_ptr<TextureMapperPlatformLayerBuffer> availableBuffer;
auto buffers = WTFMove(m_usedBuffers);
for (auto& buffer : buffers) {
if (!buffer)
continue;
if (!availableBuffer && buffer->canReuseWithoutReset(size, internalFormat)) {
availableBuffer = WTFMove(buffer);
availableBuffer->markUsed();
continue;
}
m_usedBuffers.append(WTFMove(buffer));
}
if (!m_usedBuffers.isEmpty())
scheduleReleaseUnusedBuffers();
return availableBuffer;
}
void TextureMapperPlatformLayerProxy::scheduleReleaseUnusedBuffers()
{
if (!m_releaseUnusedBuffersTimer.isActive())
m_releaseUnusedBuffersTimer.startOneShot(s_releaseUnusedBuffersTimerInterval);
}
void TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired()
{
LockHolder locker(m_lock);
if (m_usedBuffers.isEmpty())
return;
auto buffers = WTFMove(m_usedBuffers);
double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
for (auto& buffer : buffers) {
if (buffer && buffer->lastUsedTime() >= minUsedTime)
m_usedBuffers.append(WTFMove(buffer));
}
}
void TextureMapperPlatformLayerProxy::swapBuffer()
{
ASSERT(m_compositorThreadID == WTF::currentThread());
std::unique_ptr<TextureMapperPlatformLayerBuffer> prevBuffer;
{
LockHolder locker(m_lock);
if (!m_targetLayer || !m_pendingBuffer)
return;
prevBuffer = WTFMove(m_currentBuffer);
m_currentBuffer = WTFMove(m_pendingBuffer);
m_targetLayer->setContentsLayer(m_currentBuffer.get());
}
if (prevBuffer && prevBuffer->hasManagedTexture())
m_usedBuffers.append(WTFMove(prevBuffer));
}
bool TextureMapperPlatformLayerProxy::scheduleUpdateOnCompositorThread(std::function<void()>&& updateFunction)
{
LockHolder locker(m_lock);
if (!m_compositorThreadUpdateTimer)
return false;
m_compositorThreadUpdateFunction = WTFMove(updateFunction);
m_compositorThreadUpdateTimer->startOneShot(0);
return true;
}
void TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired()
{
std::function<void()> updateFunction;
{
LockHolder locker(m_lock);
if (!m_compositorThreadUpdateFunction)
return;
updateFunction = WTFMove(m_compositorThreadUpdateFunction);
}
updateFunction();
}
}
#endif // USE(COORDINATED_GRAPHICS_THREADED)