1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/resources/prioritized_resource.h" 6 7 #include <algorithm> 8 9 #include "cc/resources/platform_color.h" 10 #include "cc/resources/prioritized_resource_manager.h" 11 #include "cc/resources/priority_calculator.h" 12 #include "cc/trees/proxy.h" 13 14 namespace cc { 15 16 PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager, 17 gfx::Size size, 18 GLenum format) 19 : size_(size), 20 format_(format), 21 bytes_(0), 22 contents_swizzled_(false), 23 priority_(PriorityCalculator::LowestPriority()), 24 is_above_priority_cutoff_(false), 25 is_self_managed_(false), 26 backing_(NULL), 27 manager_(NULL) { 28 // manager_ is set in RegisterTexture() so validity can be checked. 29 DCHECK(format || size.IsEmpty()); 30 if (format) 31 bytes_ = Resource::MemorySizeBytes(size, format); 32 if (manager) 33 manager->RegisterTexture(this); 34 } 35 36 PrioritizedResource::~PrioritizedResource() { 37 if (manager_) 38 manager_->UnregisterTexture(this); 39 } 40 41 void PrioritizedResource::SetTextureManager( 42 PrioritizedResourceManager* manager) { 43 if (manager_ == manager) 44 return; 45 if (manager_) 46 manager_->UnregisterTexture(this); 47 if (manager) 48 manager->RegisterTexture(this); 49 } 50 51 void PrioritizedResource::SetDimensions(gfx::Size size, GLenum format) { 52 if (format_ != format || size_ != size) { 53 is_above_priority_cutoff_ = false; 54 format_ = format; 55 size_ = size; 56 bytes_ = Resource::MemorySizeBytes(size, format); 57 DCHECK(manager_ || !backing_); 58 if (manager_) 59 manager_->ReturnBackingTexture(this); 60 } 61 } 62 63 bool PrioritizedResource::RequestLate() { 64 if (!manager_) 65 return false; 66 return manager_->RequestLate(this); 67 } 68 69 bool PrioritizedResource::BackingResourceWasEvicted() const { 70 return backing_ ? backing_->ResourceHasBeenDeleted() : false; 71 } 72 73 void PrioritizedResource::AcquireBackingTexture( 74 ResourceProvider* resource_provider) { 75 DCHECK(is_above_priority_cutoff_); 76 if (is_above_priority_cutoff_) 77 manager_->AcquireBackingTextureIfNeeded(this, resource_provider); 78 } 79 80 void PrioritizedResource::SetPixels(ResourceProvider* resource_provider, 81 const uint8_t* image, 82 gfx::Rect image_rect, 83 gfx::Rect source_rect, 84 gfx::Vector2d dest_offset) { 85 DCHECK(is_above_priority_cutoff_); 86 if (is_above_priority_cutoff_) 87 AcquireBackingTexture(resource_provider); 88 DCHECK(backing_); 89 resource_provider->SetPixels( 90 resource_id(), image, image_rect, source_rect, dest_offset); 91 92 // The component order may be bgra if we uploaded bgra pixels to rgba 93 // texture. Mark contents as swizzled if image component order is 94 // different than texture format. 95 contents_swizzled_ = !PlatformColor::SameComponentOrder(format_); 96 } 97 98 void PrioritizedResource::Link(Backing* backing) { 99 DCHECK(backing); 100 DCHECK(!backing->owner_); 101 DCHECK(!backing_); 102 103 backing_ = backing; 104 backing_->owner_ = this; 105 } 106 107 void PrioritizedResource::Unlink() { 108 DCHECK(backing_); 109 DCHECK(backing_->owner_ == this); 110 111 backing_->owner_ = NULL; 112 backing_ = NULL; 113 } 114 115 void PrioritizedResource::SetToSelfManagedMemoryPlaceholder(size_t bytes) { 116 SetDimensions(gfx::Size(), GL_RGBA); 117 set_is_self_managed(true); 118 bytes_ = bytes; 119 } 120 121 PrioritizedResource::Backing::Backing(unsigned id, 122 ResourceProvider* resource_provider, 123 gfx::Size size, 124 GLenum format) 125 : Resource(id, size, format), 126 owner_(NULL), 127 priority_at_last_priority_update_(PriorityCalculator::LowestPriority()), 128 was_above_priority_cutoff_at_last_priority_update_(false), 129 in_drawing_impl_tree_(false), 130 #ifdef NDEBUG 131 resource_has_been_deleted_(false) {} 132 #else 133 resource_has_been_deleted_(false), 134 resource_provider_(resource_provider) {} 135 #endif 136 137 PrioritizedResource::Backing::~Backing() { 138 DCHECK(!owner_); 139 DCHECK(resource_has_been_deleted_); 140 } 141 142 void PrioritizedResource::Backing::DeleteResource( 143 ResourceProvider* resource_provider) { 144 DCHECK(!proxy() || proxy()->IsImplThread()); 145 DCHECK(!resource_has_been_deleted_); 146 #ifndef NDEBUG 147 DCHECK(resource_provider == resource_provider_); 148 #endif 149 150 resource_provider->DeleteResource(id()); 151 set_id(0); 152 resource_has_been_deleted_ = true; 153 } 154 155 bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const { 156 DCHECK(!proxy() || proxy()->IsImplThread()); 157 return resource_has_been_deleted_; 158 } 159 160 bool PrioritizedResource::Backing::CanBeRecycled() const { 161 DCHECK(!proxy() || proxy()->IsImplThread()); 162 return !was_above_priority_cutoff_at_last_priority_update_ && 163 !in_drawing_impl_tree_; 164 } 165 166 void PrioritizedResource::Backing::UpdatePriority() { 167 DCHECK(!proxy() || 168 (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); 169 if (owner_) { 170 priority_at_last_priority_update_ = owner_->request_priority(); 171 was_above_priority_cutoff_at_last_priority_update_ = 172 owner_->is_above_priority_cutoff(); 173 } else { 174 priority_at_last_priority_update_ = PriorityCalculator::LowestPriority(); 175 was_above_priority_cutoff_at_last_priority_update_ = false; 176 } 177 } 178 179 void PrioritizedResource::Backing::UpdateInDrawingImplTree() { 180 DCHECK(!proxy() || 181 (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked())); 182 in_drawing_impl_tree_ = !!owner(); 183 if (!in_drawing_impl_tree_) { 184 DCHECK_EQ(priority_at_last_priority_update_, 185 PriorityCalculator::LowestPriority()); 186 } 187 } 188 189 void PrioritizedResource::ReturnBackingTexture() { 190 DCHECK(manager_ || !backing_); 191 if (manager_) 192 manager_->ReturnBackingTexture(this); 193 } 194 195 const Proxy* PrioritizedResource::Backing::proxy() const { 196 if (!owner_ || !owner_->resource_manager()) 197 return NULL; 198 return owner_->resource_manager()->ProxyForDebug(); 199 } 200 201 } // namespace cc 202