blob: ebc8378229575cf4c7e96f68c3f66a7bc0889a58 [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/prioritized_resource.h"
#include "cc/platform_color.h"
#include "cc/prioritized_resource_manager.h"
#include "cc/priority_calculator.h"
#include "cc/proxy.h"
#include <algorithm>
using namespace std;
namespace cc {
PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager, gfx::Size size, GLenum format)
: m_size(size)
, m_format(format)
, m_bytes(0)
, m_contentsSwizzled(false)
, m_priority(PriorityCalculator::lowestPriority())
, m_isAbovePriorityCutoff(false)
, m_isSelfManaged(false)
, m_backing(0)
, m_manager(0)
{
// m_manager is set in registerTexture() so validity can be checked.
DCHECK(format || size.IsEmpty());
if (format)
m_bytes = Resource::MemorySizeBytes(size, format);
if (manager)
manager->registerTexture(this);
}
PrioritizedResource::~PrioritizedResource()
{
if (m_manager)
m_manager->unregisterTexture(this);
}
void PrioritizedResource::setTextureManager(PrioritizedResourceManager* manager)
{
if (m_manager == manager)
return;
if (m_manager)
m_manager->unregisterTexture(this);
if (manager)
manager->registerTexture(this);
}
void PrioritizedResource::setDimensions(gfx::Size size, GLenum format)
{
if (m_format != format || m_size != size) {
m_isAbovePriorityCutoff = false;
m_format = format;
m_size = size;
m_bytes = Resource::MemorySizeBytes(size, format);
DCHECK(m_manager || !m_backing);
if (m_manager)
m_manager->returnBackingTexture(this);
}
}
bool PrioritizedResource::requestLate()
{
if (!m_manager)
return false;
return m_manager->requestLate(this);
}
bool PrioritizedResource::backingResourceWasEvicted() const
{
return m_backing ? m_backing->resourceHasBeenDeleted() : false;
}
void PrioritizedResource::acquireBackingTexture(ResourceProvider* resourceProvider)
{
DCHECK(m_isAbovePriorityCutoff);
if (m_isAbovePriorityCutoff)
m_manager->acquireBackingTextureIfNeeded(this, resourceProvider);
}
ResourceProvider::ResourceId PrioritizedResource::resourceId() const
{
if (m_backing)
return m_backing->id();
return 0;
}
void PrioritizedResource::setPixels(ResourceProvider* resourceProvider,
const uint8_t* image, const gfx::Rect& imageRect,
const gfx::Rect& sourceRect, const gfx::Vector2d& destOffset)
{
DCHECK(m_isAbovePriorityCutoff);
if (m_isAbovePriorityCutoff)
acquireBackingTexture(resourceProvider);
DCHECK(m_backing);
resourceProvider->setPixels(resourceId(), image, imageRect, sourceRect, destOffset);
// The component order may be bgra if we uploaded bgra pixels to rgba
// texture. Mark contents as swizzled if image component order is
// different than texture format.
m_contentsSwizzled = !PlatformColor::sameComponentOrder(m_format);
}
void PrioritizedResource::link(Backing* backing)
{
DCHECK(backing);
CHECK(!backing->m_owner);
CHECK(!m_backing);
m_backing = backing;
m_backing->m_owner = this;
}
void PrioritizedResource::unlink()
{
DCHECK(m_backing);
CHECK(m_backing->m_owner == this);
m_backing->m_owner = 0;
m_backing = 0;
}
void PrioritizedResource::setToSelfManagedMemoryPlaceholder(size_t bytes)
{
setDimensions(gfx::Size(), GL_RGBA);
setIsSelfManaged(true);
m_bytes = bytes;
}
PrioritizedResource::Backing::Backing(unsigned id, ResourceProvider* resourceProvider, gfx::Size size, GLenum format)
: Resource(id, size, format)
, m_owner(0)
, m_priorityAtLastPriorityUpdate(PriorityCalculator::lowestPriority())
, m_wasAbovePriorityCutoffAtLastPriorityUpdate(false)
, m_inDrawingImplTree(false)
, m_resourceHasBeenDeleted(false)
, m_inMainThreadEvictedList(false)
#ifndef NDEBUG
, m_resourceProvider(resourceProvider)
#endif
{
}
PrioritizedResource::Backing::~Backing()
{
DCHECK(!m_owner);
DCHECK(m_resourceHasBeenDeleted);
CHECK(!m_inMainThreadEvictedList);
}
void PrioritizedResource::Backing::deleteResource(ResourceProvider* resourceProvider)
{
DCHECK(!proxy() || proxy()->isImplThread());
DCHECK(!m_resourceHasBeenDeleted);
#ifndef NDEBUG
DCHECK(resourceProvider == m_resourceProvider);
#endif
resourceProvider->deleteResource(id());
set_id(0);
m_resourceHasBeenDeleted = true;
}
bool PrioritizedResource::Backing::resourceHasBeenDeleted() const
{
DCHECK(!proxy() || proxy()->isImplThread());
return m_resourceHasBeenDeleted;
}
bool PrioritizedResource::Backing::canBeRecycled() const
{
DCHECK(!proxy() || proxy()->isImplThread());
return !m_wasAbovePriorityCutoffAtLastPriorityUpdate && !m_inDrawingImplTree;
}
void PrioritizedResource::Backing::updatePriority()
{
DCHECK(!proxy() || proxy()->isImplThread() && proxy()->isMainThreadBlocked());
if (m_owner) {
m_priorityAtLastPriorityUpdate = m_owner->requestPriority();
m_wasAbovePriorityCutoffAtLastPriorityUpdate = m_owner->isAbovePriorityCutoff();
} else {
m_priorityAtLastPriorityUpdate = PriorityCalculator::lowestPriority();
m_wasAbovePriorityCutoffAtLastPriorityUpdate = false;
}
}
void PrioritizedResource::Backing::updateInDrawingImplTree()
{
DCHECK(!proxy() || proxy()->isImplThread() && proxy()->isMainThreadBlocked());
m_inDrawingImplTree = !!owner();
if (!m_inDrawingImplTree)
DCHECK(m_priorityAtLastPriorityUpdate == PriorityCalculator::lowestPriority());
}
void PrioritizedResource::returnBackingTexture()
{
DCHECK(m_manager || !m_backing);
if (m_manager)
m_manager->returnBackingTexture(this);
}
const Proxy* PrioritizedResource::Backing::proxy() const
{
if (!m_owner || !m_owner->resourceManager())
return 0;
return m_owner->resourceManager()->proxyForDebug();
}
} // namespace cc