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