| 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 |