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