// 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/resources/prioritized_resource.h" #include <algorithm> #include "cc/resources/platform_color.h" #include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/priority_calculator.h" #include "cc/trees/proxy.h" namespace cc { PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager, gfx::Size size, ResourceFormat format) : size_(size), format_(format), bytes_(0), contents_swizzled_(false), priority_(PriorityCalculator::LowestPriority()), is_above_priority_cutoff_(false), is_self_managed_(false), backing_(NULL), manager_(NULL) { bytes_ = Resource::MemorySizeBytes(size, format); if (manager) manager->RegisterTexture(this); } PrioritizedResource::~PrioritizedResource() { if (manager_) manager_->UnregisterTexture(this); } void PrioritizedResource::SetTextureManager( PrioritizedResourceManager* manager) { if (manager_ == manager) return; if (manager_) manager_->UnregisterTexture(this); if (manager) manager->RegisterTexture(this); } void PrioritizedResource::SetDimensions(gfx::Size size, ResourceFormat format) { if (format_ != format || size_ != size) { is_above_priority_cutoff_ = false; format_ = format; size_ = size; bytes_ = Resource::MemorySizeBytes(size, format); DCHECK(manager_ || !backing_); if (manager_) manager_->ReturnBackingTexture(this); } } bool PrioritizedResource::RequestLate() { if (!manager_) return false; return manager_->RequestLate(this); } bool PrioritizedResource::BackingResourceWasEvicted() const { return backing_ ? backing_->ResourceHasBeenDeleted() : false; } void PrioritizedResource::AcquireBackingTexture( ResourceProvider* resource_provider) { DCHECK(is_above_priority_cutoff_); if (is_above_priority_cutoff_) manager_->AcquireBackingTextureIfNeeded(this, resource_provider); } void PrioritizedResource::SetPixels(ResourceProvider* resource_provider, const uint8_t* image, gfx::Rect image_rect, gfx::Rect source_rect, gfx::Vector2d dest_offset) { DCHECK(is_above_priority_cutoff_); if (is_above_priority_cutoff_) AcquireBackingTexture(resource_provider); DCHECK(backing_); resource_provider->SetPixels( resource_id(), image, image_rect, source_rect, dest_offset); // 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. contents_swizzled_ = !PlatformColor::SameComponentOrder(format_); } void PrioritizedResource::Link(Backing* backing) { DCHECK(backing); DCHECK(!backing->owner_); DCHECK(!backing_); backing_ = backing; backing_->owner_ = this; } void PrioritizedResource::Unlink() { DCHECK(backing_); DCHECK(backing_->owner_ == this); backing_->owner_ = NULL; backing_ = NULL; } void PrioritizedResource::SetToSelfManagedMemoryPlaceholder(size_t bytes) { SetDimensions(gfx::Size(), RGBA_8888); set_is_self_managed(true); bytes_ = bytes; } PrioritizedResource::Backing::Backing(unsigned id, ResourceProvider* resource_provider, gfx::Size size, ResourceFormat format) : Resource(id, size, format), owner_(NULL), priority_at_last_priority_update_(PriorityCalculator::LowestPriority()), was_above_priority_cutoff_at_last_priority_update_(false), in_drawing_impl_tree_(false), in_parent_compositor_(false), #ifdef NDEBUG resource_has_been_deleted_(false) {} #else resource_has_been_deleted_(false), resource_provider_(resource_provider) {} #endif PrioritizedResource::Backing::~Backing() { DCHECK(!owner_); DCHECK(resource_has_been_deleted_); } void PrioritizedResource::Backing::DeleteResource( ResourceProvider* resource_provider) { DCHECK(!proxy() || proxy()->IsImplThread()); DCHECK(!resource_has_been_deleted_); #ifndef NDEBUG DCHECK(resource_provider == resource_provider_); #endif resource_provider->DeleteResource(id()); set_id(0); resource_has_been_deleted_ = true; } bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const { DCHECK(!proxy() || proxy()->IsImplThread()); return resource_has_been_deleted_; } bool PrioritizedResource::Backing::CanBeRecycledIfNotInExternalUse() const { DCHECK(!proxy() || proxy()->IsImplThread()); return !was_above_priority_cutoff_at_last_priority_update_ && !in_drawing_impl_tree_; } void PrioritizedResource::Backing::UpdatePriority() { DCHECK(!proxy() || (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); if (owner_) { priority_at_last_priority_update_ = owner_->request_priority(); was_above_priority_cutoff_at_last_priority_update_ = owner_->is_above_priority_cutoff(); } else { priority_at_last_priority_update_ = PriorityCalculator::LowestPriority(); was_above_priority_cutoff_at_last_priority_update_ = false; } } void PrioritizedResource::Backing::UpdateState( ResourceProvider* resource_provider) { DCHECK(!proxy() || (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); in_drawing_impl_tree_ = !!owner(); in_parent_compositor_ = resource_provider->InUseByConsumer(id()); if (!in_drawing_impl_tree_) { DCHECK_EQ(priority_at_last_priority_update_, PriorityCalculator::LowestPriority()); } } void PrioritizedResource::ReturnBackingTexture() { DCHECK(manager_ || !backing_); if (manager_) manager_->ReturnBackingTexture(this); } const Proxy* PrioritizedResource::Backing::proxy() const { if (!owner_ || !owner_->resource_manager()) return NULL; return owner_->resource_manager()->ProxyForDebug(); } } // namespace cc