Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / cc / layers / texture_layer.cc
blobcf1149b5161ac63a1f818d7c760cf4a938efbe74
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 TextureLayerClient* client) {
23 return scoped_refptr<TextureLayer>(new TextureLayer(client));
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;
43 TextureLayer::~TextureLayer() {
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());
54 void TextureLayer::ClearTexture() {
55 SetTextureMailbox(TextureMailbox(), nullptr);
58 scoped_ptr<LayerImpl> TextureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
59 return TextureLayerImpl::Create(tree_impl, id());
62 void TextureLayer::SetFlipped(bool flipped) {
63 if (flipped_ == flipped)
64 return;
65 flipped_ = flipped;
66 SetNeedsCommit();
69 void TextureLayer::SetNearestNeighbor(bool nearest_neighbor) {
70 if (nearest_neighbor_ == nearest_neighbor)
71 return;
72 nearest_neighbor_ = nearest_neighbor;
73 SetNeedsCommit();
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();
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();
105 void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) {
106 if (premultiplied_alpha_ == premultiplied_alpha)
107 return;
108 premultiplied_alpha_ = premultiplied_alpha;
109 SetNeedsCommit();
112 void TextureLayer::SetBlendBackgroundColor(bool blend) {
113 if (blend_background_color_ == blend)
114 return;
115 blend_background_color_ = blend;
116 SetNeedsCommit();
119 void TextureLayer::SetRateLimitContext(bool rate_limit) {
120 if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host())
121 layer_tree_host()->StopRateLimiter();
123 rate_limit_context_ = rate_limit;
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);
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;
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();
150 UpdateDrawsContent(HasDrawableContent());
151 // The active frame needs to be replaced and the mailbox returned before the
152 // commit is called complete.
153 SetNextCommitWaitsForActivation();
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);
165 static void IgnoreReleaseCallback(uint32 sync_point, bool lost) {}
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);
184 void TextureLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
185 Layer::SetNeedsDisplayRect(dirty_rect);
187 if (rate_limit_context_ && client_ && layer_tree_host() && DrawsContent())
188 layer_tree_host()->StartRateLimiter();
191 void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
192 if (layer_tree_host() == host) {
193 Layer::SetLayerTreeHost(host);
194 return;
197 if (layer_tree_host()) {
198 if (rate_limit_context_ && client_)
199 layer_tree_host()->StopRateLimiter();
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();
210 Layer::SetLayerTreeHost(host);
213 bool TextureLayer::HasDrawableContent() const {
214 return (client_ || holder_ref_) && Layer::HasDrawableContent();
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;
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();
244 void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
245 Layer::PushPropertiesTo(layer);
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();
263 texture_layer->SetTextureMailbox(texture_mailbox,
264 release_callback_impl.Pass());
265 needs_set_mailbox_ = false;
269 SimpleEnclosedRegion TextureLayer::VisibleContentOpaqueRegion() const {
270 if (contents_opaque())
271 return SimpleEnclosedRegion(visible_content_rect());
273 if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF))
274 return SimpleEnclosedRegion(visible_content_rect());
276 return SimpleEnclosedRegion();
279 TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference(
280 TextureMailboxHolder* holder)
281 : holder_(holder) {
282 holder_->InternalAddRef();
285 TextureLayer::TextureMailboxHolder::MainThreadReference::
286 ~MainThreadReference() {
287 holder_->InternalRelease();
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) {
300 TextureLayer::TextureMailboxHolder::~TextureMailboxHolder() {
301 DCHECK_EQ(0u, internal_references_);
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())));
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;
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));
329 void TextureLayer::TextureMailboxHolder::InternalAddRef() {
330 ++internal_references_;
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;
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));
351 } // namespace cc