// 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 #include "cc/platform_color.h" #include "cc/prioritized_resource_manager.h" #include "cc/priority_calculator.h" #include "cc/proxy.h" 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); DCHECK(!backing->m_owner); DCHECK(!m_backing); m_backing = backing; m_backing->m_owner = this; } void PrioritizedResource::unlink() { DCHECK(m_backing); DCHECK(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) #ifndef NDEBUG , m_resourceProvider(resourceProvider) #endif { } PrioritizedResource::Backing::~Backing() { DCHECK(!m_owner); DCHECK(m_resourceHasBeenDeleted); } 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