OLD | NEW |
| (Empty) |
1 // Copyright 2010 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/layers/texture_layer.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback_helpers.h" | |
9 #include "base/location.h" | |
10 #include "base/synchronization/lock.h" | |
11 #include "cc/base/simple_enclosed_region.h" | |
12 #include "cc/layers/texture_layer_client.h" | |
13 #include "cc/layers/texture_layer_impl.h" | |
14 #include "cc/resources/single_release_callback.h" | |
15 #include "cc/resources/single_release_callback_impl.h" | |
16 #include "cc/trees/blocking_task_runner.h" | |
17 #include "cc/trees/layer_tree_host.h" | |
18 | |
19 namespace cc { | |
20 | |
21 scoped_refptr<TextureLayer> TextureLayer::CreateForMailbox( | |
22 TextureLayerClient* client) { | |
23 return scoped_refptr<TextureLayer>(new TextureLayer(client)); | |
24 } | |
25 | |
26 TextureLayer::TextureLayer(TextureLayerClient* client) | |
27 : Layer(), | |
28 client_(client), | |
29 flipped_(true), | |
30 nearest_neighbor_(false), | |
31 uv_top_left_(0.f, 0.f), | |
32 uv_bottom_right_(1.f, 1.f), | |
33 premultiplied_alpha_(true), | |
34 blend_background_color_(false), | |
35 rate_limit_context_(false), | |
36 needs_set_mailbox_(false) { | |
37 vertex_opacity_[0] = 1.0f; | |
38 vertex_opacity_[1] = 1.0f; | |
39 vertex_opacity_[2] = 1.0f; | |
40 vertex_opacity_[3] = 1.0f; | |
41 } | |
42 | |
43 TextureLayer::~TextureLayer() { | |
44 } | |
45 | |
46 void TextureLayer::ClearClient() { | |
47 if (rate_limit_context_ && client_ && layer_tree_host()) | |
48 layer_tree_host()->StopRateLimiter(); | |
49 client_ = nullptr; | |
50 ClearTexture(); | |
51 UpdateDrawsContent(HasDrawableContent()); | |
52 } | |
53 | |
54 void TextureLayer::ClearTexture() { | |
55 SetTextureMailbox(TextureMailbox(), nullptr); | |
56 } | |
57 | |
58 scoped_ptr<LayerImpl> TextureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { | |
59 return TextureLayerImpl::Create(tree_impl, id()); | |
60 } | |
61 | |
62 void TextureLayer::SetFlipped(bool flipped) { | |
63 if (flipped_ == flipped) | |
64 return; | |
65 flipped_ = flipped; | |
66 SetNeedsCommit(); | |
67 } | |
68 | |
69 void TextureLayer::SetNearestNeighbor(bool nearest_neighbor) { | |
70 if (nearest_neighbor_ == nearest_neighbor) | |
71 return; | |
72 nearest_neighbor_ = nearest_neighbor; | |
73 SetNeedsCommit(); | |
74 } | |
75 | |
76 void TextureLayer::SetUV(const gfx::PointF& top_left, | |
77 const gfx::PointF& bottom_right) { | |
78 if (uv_top_left_ == top_left && uv_bottom_right_ == bottom_right) | |
79 return; | |
80 uv_top_left_ = top_left; | |
81 uv_bottom_right_ = bottom_right; | |
82 SetNeedsCommit(); | |
83 } | |
84 | |
85 void TextureLayer::SetVertexOpacity(float bottom_left, | |
86 float top_left, | |
87 float top_right, | |
88 float bottom_right) { | |
89 // Indexing according to the quad vertex generation: | |
90 // 1--2 | |
91 // | | | |
92 // 0--3 | |
93 if (vertex_opacity_[0] == bottom_left && | |
94 vertex_opacity_[1] == top_left && | |
95 vertex_opacity_[2] == top_right && | |
96 vertex_opacity_[3] == bottom_right) | |
97 return; | |
98 vertex_opacity_[0] = bottom_left; | |
99 vertex_opacity_[1] = top_left; | |
100 vertex_opacity_[2] = top_right; | |
101 vertex_opacity_[3] = bottom_right; | |
102 SetNeedsCommit(); | |
103 } | |
104 | |
105 void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) { | |
106 if (premultiplied_alpha_ == premultiplied_alpha) | |
107 return; | |
108 premultiplied_alpha_ = premultiplied_alpha; | |
109 SetNeedsCommit(); | |
110 } | |
111 | |
112 void TextureLayer::SetBlendBackgroundColor(bool blend) { | |
113 if (blend_background_color_ == blend) | |
114 return; | |
115 blend_background_color_ = blend; | |
116 SetNeedsCommit(); | |
117 } | |
118 | |
119 void TextureLayer::SetRateLimitContext(bool rate_limit) { | |
120 if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host()) | |
121 layer_tree_host()->StopRateLimiter(); | |
122 | |
123 rate_limit_context_ = rate_limit; | |
124 } | |
125 | |
126 void TextureLayer::SetTextureMailboxInternal( | |
127 const TextureMailbox& mailbox, | |
128 scoped_ptr<SingleReleaseCallback> release_callback, | |
129 bool requires_commit, | |
130 bool allow_mailbox_reuse) { | |
131 DCHECK(!mailbox.IsValid() || !holder_ref_ || | |
132 !mailbox.Equals(holder_ref_->holder()->mailbox()) || | |
133 allow_mailbox_reuse); | |
134 DCHECK_EQ(mailbox.IsValid(), !!release_callback); | |
135 | |
136 // If we never commited the mailbox, we need to release it here. | |
137 if (mailbox.IsValid()) { | |
138 holder_ref_ = | |
139 TextureMailboxHolder::Create(mailbox, release_callback.Pass()); | |
140 } else { | |
141 holder_ref_ = nullptr; | |
142 } | |
143 needs_set_mailbox_ = true; | |
144 // If we are within a commit, no need to do it again immediately after. | |
145 if (requires_commit) | |
146 SetNeedsCommit(); | |
147 else | |
148 SetNeedsPushProperties(); | |
149 | |
150 UpdateDrawsContent(HasDrawableContent()); | |
151 // The active frame needs to be replaced and the mailbox returned before the | |
152 // commit is called complete. | |
153 SetNextCommitWaitsForActivation(); | |
154 } | |
155 | |
156 void TextureLayer::SetTextureMailbox( | |
157 const TextureMailbox& mailbox, | |
158 scoped_ptr<SingleReleaseCallback> release_callback) { | |
159 bool requires_commit = true; | |
160 bool allow_mailbox_reuse = false; | |
161 SetTextureMailboxInternal( | |
162 mailbox, release_callback.Pass(), requires_commit, allow_mailbox_reuse); | |
163 } | |
164 | |
165 static void IgnoreReleaseCallback(uint32 sync_point, bool lost) {} | |
166 | |
167 void TextureLayer::SetTextureMailboxWithoutReleaseCallback( | |
168 const TextureMailbox& mailbox) { | |
169 // We allow reuse of the mailbox if there is a new sync point signalling new | |
170 // content, and the release callback goes nowhere since we'll be calling it | |
171 // multiple times for the same mailbox. | |
172 DCHECK(!mailbox.IsValid() || !holder_ref_ || | |
173 !mailbox.Equals(holder_ref_->holder()->mailbox()) || | |
174 mailbox.sync_point() != holder_ref_->holder()->mailbox().sync_point()); | |
175 scoped_ptr<SingleReleaseCallback> release; | |
176 bool requires_commit = true; | |
177 bool allow_mailbox_reuse = true; | |
178 if (mailbox.IsValid()) | |
179 release = SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback)); | |
180 SetTextureMailboxInternal( | |
181 mailbox, release.Pass(), requires_commit, allow_mailbox_reuse); | |
182 } | |
183 | |
184 void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) { | |
185 Layer::SetNeedsDisplayRect(dirty_rect); | |
186 | |
187 if (rate_limit_context_ && client_ && layer_tree_host() && DrawsContent()) | |
188 layer_tree_host()->StartRateLimiter(); | |
189 } | |
190 | |
191 void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) { | |
192 if (layer_tree_host() == host) { | |
193 Layer::SetLayerTreeHost(host); | |
194 return; | |
195 } | |
196 | |
197 if (layer_tree_host()) { | |
198 if (rate_limit_context_ && client_) | |
199 layer_tree_host()->StopRateLimiter(); | |
200 } | |
201 // If we're removed from the tree, the TextureLayerImpl will be destroyed, and | |
202 // we will need to set the mailbox again on a new TextureLayerImpl the next | |
203 // time we push. | |
204 if (!host && holder_ref_) { | |
205 needs_set_mailbox_ = true; | |
206 // The active frame needs to be replaced and the mailbox returned before the | |
207 // commit is called complete. | |
208 SetNextCommitWaitsForActivation(); | |
209 } | |
210 Layer::SetLayerTreeHost(host); | |
211 } | |
212 | |
213 bool TextureLayer::HasDrawableContent() const { | |
214 return (client_ || holder_ref_) && Layer::HasDrawableContent(); | |
215 } | |
216 | |
217 bool TextureLayer::Update(ResourceUpdateQueue* queue, | |
218 const OcclusionTracker<Layer>* occlusion) { | |
219 bool updated = Layer::Update(queue, occlusion); | |
220 if (client_) { | |
221 TextureMailbox mailbox; | |
222 scoped_ptr<SingleReleaseCallback> release_callback; | |
223 if (client_->PrepareTextureMailbox( | |
224 &mailbox, | |
225 &release_callback, | |
226 layer_tree_host()->UsingSharedMemoryResources())) { | |
227 // Already within a commit, no need to do another one immediately. | |
228 bool requires_commit = false; | |
229 bool allow_mailbox_reuse = false; | |
230 SetTextureMailboxInternal(mailbox, | |
231 release_callback.Pass(), | |
232 requires_commit, | |
233 allow_mailbox_reuse); | |
234 updated = true; | |
235 } | |
236 } | |
237 | |
238 // SetTextureMailbox could be called externally and the same mailbox used for | |
239 // different textures. Such callers notify this layer that the texture has | |
240 // changed by calling SetNeedsDisplay, so check for that here. | |
241 return updated || !update_rect_.IsEmpty(); | |
242 } | |
243 | |
244 void TextureLayer::PushPropertiesTo(LayerImpl* layer) { | |
245 Layer::PushPropertiesTo(layer); | |
246 | |
247 TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer); | |
248 texture_layer->SetFlipped(flipped_); | |
249 texture_layer->SetNearestNeighbor(nearest_neighbor_); | |
250 texture_layer->SetUVTopLeft(uv_top_left_); | |
251 texture_layer->SetUVBottomRight(uv_bottom_right_); | |
252 texture_layer->SetVertexOpacity(vertex_opacity_); | |
253 texture_layer->SetPremultipliedAlpha(premultiplied_alpha_); | |
254 texture_layer->SetBlendBackgroundColor(blend_background_color_); | |
255 if (needs_set_mailbox_) { | |
256 TextureMailbox texture_mailbox; | |
257 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl; | |
258 if (holder_ref_) { | |
259 TextureMailboxHolder* holder = holder_ref_->holder(); | |
260 texture_mailbox = holder->mailbox(); | |
261 release_callback_impl = holder->GetCallbackForImplThread(); | |
262 } | |
263 texture_layer->SetTextureMailbox(texture_mailbox, | |
264 release_callback_impl.Pass()); | |
265 needs_set_mailbox_ = false; | |
266 } | |
267 } | |
268 | |
269 SimpleEnclosedRegion TextureLayer::VisibleContentOpaqueRegion() const { | |
270 if (contents_opaque()) | |
271 return SimpleEnclosedRegion(visible_content_rect()); | |
272 | |
273 if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF)) | |
274 return SimpleEnclosedRegion(visible_content_rect()); | |
275 | |
276 return SimpleEnclosedRegion(); | |
277 } | |
278 | |
279 TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference( | |
280 TextureMailboxHolder* holder) | |
281 : holder_(holder) { | |
282 holder_->InternalAddRef(); | |
283 } | |
284 | |
285 TextureLayer::TextureMailboxHolder::MainThreadReference:: | |
286 ~MainThreadReference() { | |
287 holder_->InternalRelease(); | |
288 } | |
289 | |
290 TextureLayer::TextureMailboxHolder::TextureMailboxHolder( | |
291 const TextureMailbox& mailbox, | |
292 scoped_ptr<SingleReleaseCallback> release_callback) | |
293 : internal_references_(0), | |
294 mailbox_(mailbox), | |
295 release_callback_(release_callback.Pass()), | |
296 sync_point_(mailbox.sync_point()), | |
297 is_lost_(false) { | |
298 } | |
299 | |
300 TextureLayer::TextureMailboxHolder::~TextureMailboxHolder() { | |
301 DCHECK_EQ(0u, internal_references_); | |
302 } | |
303 | |
304 scoped_ptr<TextureLayer::TextureMailboxHolder::MainThreadReference> | |
305 TextureLayer::TextureMailboxHolder::Create( | |
306 const TextureMailbox& mailbox, | |
307 scoped_ptr<SingleReleaseCallback> release_callback) { | |
308 return make_scoped_ptr(new MainThreadReference( | |
309 new TextureMailboxHolder(mailbox, release_callback.Pass()))); | |
310 } | |
311 | |
312 void TextureLayer::TextureMailboxHolder::Return(uint32 sync_point, | |
313 bool is_lost) { | |
314 base::AutoLock lock(arguments_lock_); | |
315 sync_point_ = sync_point; | |
316 is_lost_ = is_lost; | |
317 } | |
318 | |
319 scoped_ptr<SingleReleaseCallbackImpl> | |
320 TextureLayer::TextureMailboxHolder::GetCallbackForImplThread() { | |
321 // We can't call GetCallbackForImplThread if we released the main thread | |
322 // reference. | |
323 DCHECK_GT(internal_references_, 0u); | |
324 InternalAddRef(); | |
325 return SingleReleaseCallbackImpl::Create( | |
326 base::Bind(&TextureMailboxHolder::ReturnAndReleaseOnImplThread, this)); | |
327 } | |
328 | |
329 void TextureLayer::TextureMailboxHolder::InternalAddRef() { | |
330 ++internal_references_; | |
331 } | |
332 | |
333 void TextureLayer::TextureMailboxHolder::InternalRelease() { | |
334 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
335 if (!--internal_references_) { | |
336 release_callback_->Run(sync_point_, is_lost_); | |
337 mailbox_ = TextureMailbox(); | |
338 release_callback_ = nullptr; | |
339 } | |
340 } | |
341 | |
342 void TextureLayer::TextureMailboxHolder::ReturnAndReleaseOnImplThread( | |
343 uint32 sync_point, | |
344 bool is_lost, | |
345 BlockingTaskRunner* main_thread_task_runner) { | |
346 Return(sync_point, is_lost); | |
347 main_thread_task_runner->PostTask( | |
348 FROM_HERE, base::Bind(&TextureMailboxHolder::InternalRelease, this)); | |
349 } | |
350 | |
351 } // namespace cc | |
OLD | NEW |