| // 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, |
| const 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(const 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, |
| const gfx::Rect& image_rect, |
| const gfx::Rect& source_rect, |
| const 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, |
| const 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), |
| #if !DCHECK_IS_ON() |
| 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_); |
| #if DCHECK_IS_ON() |
| 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 |