CoordinatedImageBacking.cpp [plain text]
#include "config.h"
#if USE(COORDINATED_GRAPHICS)
#include "CoordinatedImageBacking.h"
#include "CoordinatedGraphicsState.h"
#include "GraphicsContext.h"
namespace WebCore {
class ImageBackingSurfaceClient : public CoordinatedSurface::Client {
public:
ImageBackingSurfaceClient(Image* image, const IntRect& rect)
: m_image(image)
, m_rect(rect)
{
}
virtual void paintToSurfaceContext(GraphicsContext* context) override
{
context->drawImage(m_image, ColorSpaceDeviceRGB, m_rect, m_rect);
}
private:
Image* m_image;
IntRect m_rect;
};
CoordinatedImageBackingID CoordinatedImageBacking::getCoordinatedImageBackingID(Image* image)
{
return reinterpret_cast<CoordinatedImageBackingID>(image);
}
PassRefPtr<CoordinatedImageBacking> CoordinatedImageBacking::create(Client* client, PassRefPtr<Image> image)
{
return adoptRef(new CoordinatedImageBacking(client, image));
}
CoordinatedImageBacking::CoordinatedImageBacking(Client* client, PassRefPtr<Image> image)
: m_client(client)
, m_image(image)
, m_id(getCoordinatedImageBackingID(m_image.get()))
, m_clearContentsTimer(this, &CoordinatedImageBacking::clearContentsTimerFired)
, m_isDirty(false)
, m_isVisible(false)
{
m_client->createImageBacking(id());
}
CoordinatedImageBacking::~CoordinatedImageBacking()
{
}
void CoordinatedImageBacking::addHost(Host* host)
{
ASSERT(!m_hosts.contains(host));
m_hosts.append(host);
}
void CoordinatedImageBacking::removeHost(Host* host)
{
size_t position = m_hosts.find(host);
ASSERT(position != notFound);
m_hosts.remove(position);
if (m_hosts.isEmpty())
m_client->removeImageBacking(id());
}
void CoordinatedImageBacking::markDirty()
{
m_isDirty = true;
}
void CoordinatedImageBacking::update()
{
releaseSurfaceIfNeeded();
bool changedToVisible;
updateVisibilityIfNeeded(changedToVisible);
if (!m_isVisible)
return;
if (!changedToVisible) {
if (!m_isDirty)
return;
if (m_nativeImagePtr == m_image->nativeImageForCurrentFrame()) {
m_isDirty = false;
return;
}
}
m_surface = CoordinatedSurface::create(IntSize(m_image->size()), !m_image->currentFrameKnownToBeOpaque() ? CoordinatedSurface::SupportsAlpha : CoordinatedSurface::NoFlags);
if (!m_surface) {
m_isDirty = false;
return;
}
IntRect rect(IntPoint::zero(), IntSize(m_image->size()));
ImageBackingSurfaceClient surfaceClient(m_image.get(), rect);
m_surface->paintToSurface(rect, &surfaceClient);
m_nativeImagePtr = m_image->nativeImageForCurrentFrame();
m_client->updateImageBacking(id(), m_surface);
m_isDirty = false;
}
void CoordinatedImageBacking::releaseSurfaceIfNeeded()
{
m_surface.clear();
}
static const double clearContentsTimerInterval = 3;
void CoordinatedImageBacking::updateVisibilityIfNeeded(bool& changedToVisible)
{
bool previousIsVisible = m_isVisible;
m_isVisible = false;
for (size_t i = 0; i < m_hosts.size(); ++i) {
if (m_hosts[i]->imageBackingVisible()) {
m_isVisible = true;
break;
}
}
bool changedToInvisible = previousIsVisible && !m_isVisible;
if (changedToInvisible) {
ASSERT(!m_clearContentsTimer.isActive());
m_clearContentsTimer.startOneShot(clearContentsTimerInterval);
}
changedToVisible = !previousIsVisible && m_isVisible;
if (m_isVisible && m_clearContentsTimer.isActive()) {
m_clearContentsTimer.stop();
changedToVisible = false;
}
}
void CoordinatedImageBacking::clearContentsTimerFired(Timer<CoordinatedImageBacking>*)
{
m_client->clearImageBackingContents(id());
}
} #endif