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
PrioritizedResource(PrioritizedResourceManager * manager,gfx::Size size,ResourceFormat format)16 PrioritizedResource::PrioritizedResource(PrioritizedResourceManager* manager,
17 gfx::Size size,
18 ResourceFormat 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 bytes_ = Resource::MemorySizeBytes(size, format);
29 if (manager)
30 manager->RegisterTexture(this);
31 }
32
~PrioritizedResource()33 PrioritizedResource::~PrioritizedResource() {
34 if (manager_)
35 manager_->UnregisterTexture(this);
36 }
37
SetTextureManager(PrioritizedResourceManager * manager)38 void PrioritizedResource::SetTextureManager(
39 PrioritizedResourceManager* manager) {
40 if (manager_ == manager)
41 return;
42 if (manager_)
43 manager_->UnregisterTexture(this);
44 if (manager)
45 manager->RegisterTexture(this);
46 }
47
SetDimensions(gfx::Size size,ResourceFormat format)48 void PrioritizedResource::SetDimensions(gfx::Size size, ResourceFormat format) {
49 if (format_ != format || size_ != size) {
50 is_above_priority_cutoff_ = false;
51 format_ = format;
52 size_ = size;
53 bytes_ = Resource::MemorySizeBytes(size, format);
54 DCHECK(manager_ || !backing_);
55 if (manager_)
56 manager_->ReturnBackingTexture(this);
57 }
58 }
59
RequestLate()60 bool PrioritizedResource::RequestLate() {
61 if (!manager_)
62 return false;
63 return manager_->RequestLate(this);
64 }
65
BackingResourceWasEvicted() const66 bool PrioritizedResource::BackingResourceWasEvicted() const {
67 return backing_ ? backing_->ResourceHasBeenDeleted() : false;
68 }
69
AcquireBackingTexture(ResourceProvider * resource_provider)70 void PrioritizedResource::AcquireBackingTexture(
71 ResourceProvider* resource_provider) {
72 DCHECK(is_above_priority_cutoff_);
73 if (is_above_priority_cutoff_)
74 manager_->AcquireBackingTextureIfNeeded(this, resource_provider);
75 }
76
SetPixels(ResourceProvider * resource_provider,const uint8_t * image,gfx::Rect image_rect,gfx::Rect source_rect,gfx::Vector2d dest_offset)77 void PrioritizedResource::SetPixels(ResourceProvider* resource_provider,
78 const uint8_t* image,
79 gfx::Rect image_rect,
80 gfx::Rect source_rect,
81 gfx::Vector2d dest_offset) {
82 DCHECK(is_above_priority_cutoff_);
83 if (is_above_priority_cutoff_)
84 AcquireBackingTexture(resource_provider);
85 DCHECK(backing_);
86 resource_provider->SetPixels(
87 resource_id(), image, image_rect, source_rect, dest_offset);
88
89 // The component order may be bgra if we uploaded bgra pixels to rgba
90 // texture. Mark contents as swizzled if image component order is
91 // different than texture format.
92 contents_swizzled_ = !PlatformColor::SameComponentOrder(format_);
93 }
94
Link(Backing * backing)95 void PrioritizedResource::Link(Backing* backing) {
96 DCHECK(backing);
97 DCHECK(!backing->owner_);
98 DCHECK(!backing_);
99
100 backing_ = backing;
101 backing_->owner_ = this;
102 }
103
Unlink()104 void PrioritizedResource::Unlink() {
105 DCHECK(backing_);
106 DCHECK(backing_->owner_ == this);
107
108 backing_->owner_ = NULL;
109 backing_ = NULL;
110 }
111
SetToSelfManagedMemoryPlaceholder(size_t bytes)112 void PrioritizedResource::SetToSelfManagedMemoryPlaceholder(size_t bytes) {
113 SetDimensions(gfx::Size(), RGBA_8888);
114 set_is_self_managed(true);
115 bytes_ = bytes;
116 }
117
Backing(unsigned id,ResourceProvider * resource_provider,gfx::Size size,ResourceFormat format)118 PrioritizedResource::Backing::Backing(unsigned id,
119 ResourceProvider* resource_provider,
120 gfx::Size size,
121 ResourceFormat format)
122 : Resource(id, size, format),
123 owner_(NULL),
124 priority_at_last_priority_update_(PriorityCalculator::LowestPriority()),
125 was_above_priority_cutoff_at_last_priority_update_(false),
126 in_drawing_impl_tree_(false),
127 in_parent_compositor_(false),
128 #ifdef NDEBUG
129 resource_has_been_deleted_(false) {}
130 #else
131 resource_has_been_deleted_(false),
132 resource_provider_(resource_provider) {}
133 #endif
134
~Backing()135 PrioritizedResource::Backing::~Backing() {
136 DCHECK(!owner_);
137 DCHECK(resource_has_been_deleted_);
138 }
139
DeleteResource(ResourceProvider * resource_provider)140 void PrioritizedResource::Backing::DeleteResource(
141 ResourceProvider* resource_provider) {
142 DCHECK(!proxy() || proxy()->IsImplThread());
143 DCHECK(!resource_has_been_deleted_);
144 #ifndef NDEBUG
145 DCHECK(resource_provider == resource_provider_);
146 #endif
147
148 resource_provider->DeleteResource(id());
149 set_id(0);
150 resource_has_been_deleted_ = true;
151 }
152
ResourceHasBeenDeleted() const153 bool PrioritizedResource::Backing::ResourceHasBeenDeleted() const {
154 DCHECK(!proxy() || proxy()->IsImplThread());
155 return resource_has_been_deleted_;
156 }
157
CanBeRecycledIfNotInExternalUse() const158 bool PrioritizedResource::Backing::CanBeRecycledIfNotInExternalUse() const {
159 DCHECK(!proxy() || proxy()->IsImplThread());
160 return !was_above_priority_cutoff_at_last_priority_update_ &&
161 !in_drawing_impl_tree_;
162 }
163
UpdatePriority()164 void PrioritizedResource::Backing::UpdatePriority() {
165 DCHECK(!proxy() ||
166 (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked()));
167 if (owner_) {
168 priority_at_last_priority_update_ = owner_->request_priority();
169 was_above_priority_cutoff_at_last_priority_update_ =
170 owner_->is_above_priority_cutoff();
171 } else {
172 priority_at_last_priority_update_ = PriorityCalculator::LowestPriority();
173 was_above_priority_cutoff_at_last_priority_update_ = false;
174 }
175 }
176
UpdateState(ResourceProvider * resource_provider)177 void PrioritizedResource::Backing::UpdateState(
178 ResourceProvider* resource_provider) {
179 DCHECK(!proxy() ||
180 (proxy()->IsImplThread() && proxy()->IsMainThreadBlocked()));
181 in_drawing_impl_tree_ = !!owner();
182 in_parent_compositor_ = resource_provider->InUseByConsumer(id());
183 if (!in_drawing_impl_tree_) {
184 DCHECK_EQ(priority_at_last_priority_update_,
185 PriorityCalculator::LowestPriority());
186 }
187 }
188
ReturnBackingTexture()189 void PrioritizedResource::ReturnBackingTexture() {
190 DCHECK(manager_ || !backing_);
191 if (manager_)
192 manager_->ReturnBackingTexture(this);
193 }
194
proxy() const195 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