Chromium Code Reviews| Index: cc/layers/surface_layer.cc |
| diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc |
| index ba577a00d58e7abd952b794ed1dd04d8f98640d3..2d8b0e1baff7d54a766aada5bac2114ae688dc03 100644 |
| --- a/cc/layers/surface_layer.cc |
| +++ b/cc/layers/surface_layer.cc |
| @@ -4,10 +4,48 @@ |
| #include "cc/layers/surface_layer.h" |
| +#include "cc/base/swap_promise.h" |
| #include "cc/layers/surface_layer_impl.h" |
| +#include "cc/surfaces/surface_manager.h" |
| +#include "cc/trees/layer_tree_host.h" |
| namespace cc { |
| +// This only works with threaded compositing disabled, as the swap promise could |
| +// be destroyed on either the impl or main thread. |
|
piman
2014/11/03 23:49:26
nit: Add ThreadChecker?
What's the plan for threa
|
| +class SatisfySwapPromise : public SwapPromise, |
| + public base::SupportsWeakPtr<SatisfySwapPromise> { |
| + public: |
| + SatisfySwapPromise(SurfaceSequence sequence, |
| + LayerTreeHost* host, |
| + SurfaceHolder::SatisfyCallback satisfy_callback) |
| + : sequence_(sequence), host_(host), satisfy_callback_(satisfy_callback) {} |
| + |
| + SurfaceSequence RemoveSequence() { |
| + SurfaceSequence last_sequence = sequence_; |
| + sequence_ = SurfaceSequence(); |
| + return last_sequence; |
| + } |
| + |
| + LayerTreeHost* host() { return host_; } |
| + |
| + private: |
| + void DidSwap(CompositorFrameMetadata* metadata) override { |
| + if (!sequence_.is_null()) |
| + metadata->satisfies_sequences.push_back(sequence_.sequence); |
| + } |
| + |
| + void DidNotSwap(DidNotSwapReason reason) override { |
| + if (!sequence_.is_null()) |
| + satisfy_callback_.Run(sequence_); |
| + } |
| + int64 TraceId() const override { return 0; } |
| + |
| + SurfaceSequence sequence_; |
| + LayerTreeHost* host_; |
| + SurfaceHolder::SatisfyCallback satisfy_callback_; |
| +}; |
| + |
| scoped_refptr<SurfaceLayer> SurfaceLayer::Create() { |
| return make_scoped_refptr(new SurfaceLayer); |
| } |
| @@ -15,10 +53,17 @@ scoped_refptr<SurfaceLayer> SurfaceLayer::Create() { |
| SurfaceLayer::SurfaceLayer() : Layer() { |
| } |
| -SurfaceLayer::~SurfaceLayer() {} |
| +SurfaceLayer::~SurfaceLayer() { |
| + DCHECK(!layer_tree_host()); |
| + DCHECK(destroy_sequence_.is_null()); |
| +} |
| + |
| +void SurfaceLayer::SetSurfaceId(scoped_refptr<SurfaceHolder> surface_holder) { |
| + SatisfyDestroySequence(); |
| + surface_holder_ = surface_holder; |
| + last_swap_promise_.reset(); |
| + CreateNewDestroySequence(); |
| -void SurfaceLayer::SetSurfaceId(SurfaceId surface_id) { |
| - surface_id_ = surface_id; |
| UpdateDrawsContent(HasDrawableContent()); |
| SetNeedsPushProperties(); |
| } |
| @@ -28,14 +73,58 @@ scoped_ptr<LayerImpl> SurfaceLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { |
| } |
| bool SurfaceLayer::HasDrawableContent() const { |
| - return !surface_id_.is_null() && Layer::HasDrawableContent(); |
| + return surface_holder_.get() && !surface_holder_->surface_id().is_null() && |
| + Layer::HasDrawableContent(); |
| +} |
| + |
| +void SurfaceLayer::SetLayerTreeHost(LayerTreeHost* host) { |
| + if (layer_tree_host() == host) { |
| + Layer::SetLayerTreeHost(host); |
| + return; |
| + } |
| + |
| + SatisfyDestroySequence(); |
| + Layer::SetLayerTreeHost(host); |
| + CreateNewDestroySequence(); |
| } |
| void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) { |
| Layer::PushPropertiesTo(layer); |
| SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer); |
| - layer_impl->SetSurfaceId(surface_id_); |
| + layer_impl->SetSurfaceId(surface_holder_.get() ? surface_holder_->surface_id() |
| + : SurfaceId()); |
| +} |
| + |
| +void SurfaceLayer::CreateNewDestroySequence() { |
| + DCHECK(destroy_sequence_.is_null()); |
| + if (layer_tree_host() && surface_holder_.get()) { |
| + if (last_swap_promise_ && last_swap_promise_->host() == layer_tree_host()) { |
| + // Last swap promise hasn't been submitted yet, so reuse its |
| + // SurfaceSequence instead of creating a new one. This allows the layer |
| + // to be removed from and added back to a tree in the course of a commit |
| + // and avoid requiring a new sequence. |
| + destroy_sequence_ = last_swap_promise_->RemoveSequence(); |
| + DCHECK(!destroy_sequence_.is_null()); |
| + last_swap_promise_.reset(); |
| + } else { |
| + destroy_sequence_ = layer_tree_host()->CreateSurfaceSequence(); |
| + surface_holder_->AddSurfaceSequence(destroy_sequence_); |
| + } |
| + } |
| +} |
| + |
| +void SurfaceLayer::SatisfyDestroySequence() { |
| + if (!layer_tree_host() || !surface_holder_.get()) |
| + return; |
| + DCHECK(!destroy_sequence_.is_null()); |
| + scoped_ptr<SatisfySwapPromise> satisfy( |
| + new SatisfySwapPromise(destroy_sequence_, |
| + layer_tree_host(), |
| + surface_holder_->satisfy_callback())); |
| + last_swap_promise_ = satisfy->AsWeakPtr(); |
| + layer_tree_host()->QueueSwapPromise(satisfy.Pass()); |
| + destroy_sequence_ = SurfaceSequence(); |
| } |
| } // namespace cc |