Compute can_use_lcd_text using property trees.
[chromium-blink-merge.git] / cc / layers / texture_layer.cc
blob20741fddad839cd6813193fc578a3fe06f3756cf
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.
5 #include "cc/layers/texture_layer.h"
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"
19 namespace cc {
21 scoped_refptr<TextureLayer> TextureLayer::CreateForMailbox(
22 const LayerSettings& settings,
23 TextureLayerClient* client) {
24 return scoped_refptr<TextureLayer>(new TextureLayer(settings, client));
27 TextureLayer::TextureLayer(const LayerSettings& settings,
28 TextureLayerClient* client)
29 : Layer(settings),
30 client_(client),
31 flipped_(true),
32 nearest_neighbor_(false),
33 uv_top_left_(0.f, 0.f),
34 uv_bottom_right_(1.f, 1.f),
35 premultiplied_alpha_(true),
36 blend_background_color_(false),
37 rate_limit_context_(false),
38 needs_set_mailbox_(false) {
39 vertex_opacity_[0] = 1.0f;
40 vertex_opacity_[1] = 1.0f;
41 vertex_opacity_[2] = 1.0f;
42 vertex_opacity_[3] = 1.0f;
45 TextureLayer::~TextureLayer() {
48 void TextureLayer::ClearClient() {
49 if (rate_limit_context_ && client_ && layer_tree_host())
50 layer_tree_host()->StopRateLimiter();
51 client_ = nullptr;
52 ClearTexture();
53 UpdateDrawsContent(HasDrawableContent());
56 void TextureLayer::ClearTexture() {
57 SetTextureMailbox(TextureMailbox(), nullptr);
60 scoped_ptr<LayerImpl> TextureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
61 return TextureLayerImpl::Create(tree_impl, id());
64 void TextureLayer::SetFlipped(bool flipped) {
65 if (flipped_ == flipped)
66 return;
67 flipped_ = flipped;
68 SetNeedsCommit();
71 void TextureLayer::SetNearestNeighbor(bool nearest_neighbor) {
72 if (nearest_neighbor_ == nearest_neighbor)
73 return;
74 nearest_neighbor_ = nearest_neighbor;
75 SetNeedsCommit();
78 void TextureLayer::SetUV(const gfx::PointF& top_left,
79 const gfx::PointF& bottom_right) {
80 if (uv_top_left_ == top_left && uv_bottom_right_ == bottom_right)
81 return;
82 uv_top_left_ = top_left;
83 uv_bottom_right_ = bottom_right;
84 SetNeedsCommit();
87 void TextureLayer::SetVertexOpacity(float bottom_left,
88 float top_left,
89 float top_right,
90 float bottom_right) {
91 // Indexing according to the quad vertex generation:
92 // 1--2
93 // | |
94 // 0--3
95 if (vertex_opacity_[0] == bottom_left &&
96 vertex_opacity_[1] == top_left &&
97 vertex_opacity_[2] == top_right &&
98 vertex_opacity_[3] == bottom_right)
99 return;
100 vertex_opacity_[0] = bottom_left;
101 vertex_opacity_[1] = top_left;
102 vertex_opacity_[2] = top_right;
103 vertex_opacity_[3] = bottom_right;
104 SetNeedsCommit();
107 void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) {
108 if (premultiplied_alpha_ == premultiplied_alpha)
109 return;
110 premultiplied_alpha_ = premultiplied_alpha;
111 SetNeedsCommit();
114 void TextureLayer::SetBlendBackgroundColor(bool blend) {
115 if (blend_background_color_ == blend)
116 return;
117 blend_background_color_ = blend;
118 SetNeedsCommit();
121 void TextureLayer::SetRateLimitContext(bool rate_limit) {
122 if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host())
123 layer_tree_host()->StopRateLimiter();
125 rate_limit_context_ = rate_limit;
128 void TextureLayer::SetTextureMailboxInternal(
129 const TextureMailbox& mailbox,
130 scoped_ptr<SingleReleaseCallback> release_callback,
131 bool requires_commit,
132 bool allow_mailbox_reuse) {
133 DCHECK(!mailbox.IsValid() || !holder_ref_ ||
134 !mailbox.Equals(holder_ref_->holder()->mailbox()) ||
135 allow_mailbox_reuse);
136 DCHECK_EQ(mailbox.IsValid(), !!release_callback);
138 // If we never commited the mailbox, we need to release it here.
139 if (mailbox.IsValid()) {
140 holder_ref_ =
141 TextureMailboxHolder::Create(mailbox, release_callback.Pass());
142 } else {
143 holder_ref_ = nullptr;
145 needs_set_mailbox_ = true;
146 // If we are within a commit, no need to do it again immediately after.
147 if (requires_commit)
148 SetNeedsCommit();
149 else
150 SetNeedsPushProperties();
152 UpdateDrawsContent(HasDrawableContent());
153 // The active frame needs to be replaced and the mailbox returned before the
154 // commit is called complete.
155 SetNextCommitWaitsForActivation();
158 void TextureLayer::SetTextureMailbox(
159 const TextureMailbox& mailbox,
160 scoped_ptr<SingleReleaseCallback> release_callback) {
161 bool requires_commit = true;
162 bool allow_mailbox_reuse = false;
163 SetTextureMailboxInternal(
164 mailbox, release_callback.Pass(), requires_commit, allow_mailbox_reuse);
167 static void IgnoreReleaseCallback(uint32 sync_point, bool lost) {}
169 void TextureLayer::SetTextureMailboxWithoutReleaseCallback(
170 const TextureMailbox& mailbox) {
171 // We allow reuse of the mailbox if there is a new sync point signalling new
172 // content, and the release callback goes nowhere since we'll be calling it
173 // multiple times for the same mailbox.
174 DCHECK(!mailbox.IsValid() || !holder_ref_ ||
175 !mailbox.Equals(holder_ref_->holder()->mailbox()) ||
176 mailbox.sync_point() != holder_ref_->holder()->mailbox().sync_point());
177 scoped_ptr<SingleReleaseCallback> release;
178 bool requires_commit = true;
179 bool allow_mailbox_reuse = true;
180 if (mailbox.IsValid())
181 release = SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback));
182 SetTextureMailboxInternal(
183 mailbox, release.Pass(), requires_commit, allow_mailbox_reuse);
186 void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
187 Layer::SetNeedsDisplayRect(dirty_rect);
189 if (rate_limit_context_ && client_ && layer_tree_host() && DrawsContent())
190 layer_tree_host()->StartRateLimiter();
193 void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
194 if (layer_tree_host() == host) {
195 Layer::SetLayerTreeHost(host);
196 return;
199 if (layer_tree_host()) {
200 if (rate_limit_context_ && client_)
201 layer_tree_host()->StopRateLimiter();
203 // If we're removed from the tree, the TextureLayerImpl will be destroyed, and
204 // we will need to set the mailbox again on a new TextureLayerImpl the next
205 // time we push.
206 if (!host && holder_ref_) {
207 needs_set_mailbox_ = true;
208 // The active frame needs to be replaced and the mailbox returned before the
209 // commit is called complete.
210 SetNextCommitWaitsForActivation();
212 Layer::SetLayerTreeHost(host);
215 bool TextureLayer::HasDrawableContent() const {
216 return (client_ || holder_ref_) && Layer::HasDrawableContent();
219 bool TextureLayer::Update() {
220 bool updated = Layer::Update();
221 if (client_) {
222 TextureMailbox mailbox;
223 scoped_ptr<SingleReleaseCallback> release_callback;
224 if (client_->PrepareTextureMailbox(
225 &mailbox,
226 &release_callback,
227 layer_tree_host()->UsingSharedMemoryResources())) {
228 // Already within a commit, no need to do another one immediately.
229 bool requires_commit = false;
230 bool allow_mailbox_reuse = false;
231 SetTextureMailboxInternal(mailbox,
232 release_callback.Pass(),
233 requires_commit,
234 allow_mailbox_reuse);
235 updated = true;
239 // SetTextureMailbox could be called externally and the same mailbox used for
240 // different textures. Such callers notify this layer that the texture has
241 // changed by calling SetNeedsDisplay, so check for that here.
242 return updated || !update_rect_.IsEmpty();
245 void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
246 Layer::PushPropertiesTo(layer);
248 TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
249 texture_layer->SetFlipped(flipped_);
250 texture_layer->SetNearestNeighbor(nearest_neighbor_);
251 texture_layer->SetUVTopLeft(uv_top_left_);
252 texture_layer->SetUVBottomRight(uv_bottom_right_);
253 texture_layer->SetVertexOpacity(vertex_opacity_);
254 texture_layer->SetPremultipliedAlpha(premultiplied_alpha_);
255 texture_layer->SetBlendBackgroundColor(blend_background_color_);
256 if (needs_set_mailbox_) {
257 TextureMailbox texture_mailbox;
258 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl;
259 if (holder_ref_) {
260 TextureMailboxHolder* holder = holder_ref_->holder();
261 texture_mailbox = holder->mailbox();
262 release_callback_impl = holder->GetCallbackForImplThread();
264 texture_layer->SetTextureMailbox(texture_mailbox,
265 release_callback_impl.Pass());
266 needs_set_mailbox_ = false;
270 TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference(
271 TextureMailboxHolder* holder)
272 : holder_(holder) {
273 holder_->InternalAddRef();
276 TextureLayer::TextureMailboxHolder::MainThreadReference::
277 ~MainThreadReference() {
278 holder_->InternalRelease();
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) {
291 TextureLayer::TextureMailboxHolder::~TextureMailboxHolder() {
292 DCHECK_EQ(0u, internal_references_);
295 scoped_ptr<TextureLayer::TextureMailboxHolder::MainThreadReference>
296 TextureLayer::TextureMailboxHolder::Create(
297 const TextureMailbox& mailbox,
298 scoped_ptr<SingleReleaseCallback> release_callback) {
299 return make_scoped_ptr(new MainThreadReference(
300 new TextureMailboxHolder(mailbox, release_callback.Pass())));
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;
310 scoped_ptr<SingleReleaseCallbackImpl>
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));
320 void TextureLayer::TextureMailboxHolder::InternalAddRef() {
321 ++internal_references_;
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_ = nullptr;
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));
342 } // namespace cc