| Index: cc/layers/texture_layer.cc
|
| diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
|
| index d09963139101e955de76cb914513e31d51777b6f..7dc0acfbb1adefa862281853d13385329a98a236 100644
|
| --- a/cc/layers/texture_layer.cc
|
| +++ b/cc/layers/texture_layer.cc
|
| @@ -4,6 +4,9 @@
|
|
|
| #include "cc/layers/texture_layer.h"
|
|
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| #include "cc/base/thread.h"
|
| #include "cc/layers/texture_layer_client.h"
|
| #include "cc/layers/texture_layer_impl.h"
|
| @@ -12,28 +15,6 @@
|
|
|
| namespace cc {
|
|
|
| -namespace {
|
| -
|
| -void RunCallback(
|
| - const TextureMailbox::ReleaseCallback& callback,
|
| - unsigned sync_point,
|
| - bool lost_resource) {
|
| - callback.Run(sync_point, lost_resource);
|
| -}
|
| -
|
| -void PostCallbackToThread(
|
| - Thread* thread,
|
| - const TextureMailbox::ReleaseCallback& callback,
|
| - unsigned sync_point,
|
| - bool lost_resource) {
|
| - if (!callback.is_null()) {
|
| - thread->PostTask(base::Bind(&RunCallback, callback,
|
| - sync_point, lost_resource));
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| scoped_refptr<TextureLayer> TextureLayer::Create(TextureLayerClient* client) {
|
| return scoped_refptr<TextureLayer>(new TextureLayer(client, false));
|
| }
|
| @@ -55,7 +36,7 @@ TextureLayer::TextureLayer(TextureLayerClient* client, bool uses_mailbox)
|
| context_lost_(false),
|
| content_committed_(false),
|
| texture_id_(0),
|
| - own_mailbox_(false) {
|
| + needs_set_mailbox_(false) {
|
| vertex_opacity_[0] = 1.0f;
|
| vertex_opacity_[1] = 1.0f;
|
| vertex_opacity_[2] = 1.0f;
|
| @@ -69,8 +50,6 @@ TextureLayer::~TextureLayer() {
|
| if (rate_limit_context_ && client_)
|
| layer_tree_host()->StopRateLimiter(client_->Context3d());
|
| }
|
| - if (own_mailbox_)
|
| - texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
|
| }
|
|
|
| void TextureLayer::ClearClient() {
|
| @@ -147,13 +126,14 @@ void TextureLayer::SetTextureId(unsigned id) {
|
|
|
| void TextureLayer::SetTextureMailbox(const TextureMailbox& mailbox) {
|
| DCHECK(uses_mailbox_);
|
| - if (own_mailbox_)
|
| - DCHECK(!mailbox.IsValid() || !mailbox.Equals(texture_mailbox_));
|
| - // If we never commited the mailbox, we need to release it here
|
| - if (own_mailbox_)
|
| - texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
|
| - texture_mailbox_ = mailbox;
|
| - own_mailbox_ = true;
|
| + DCHECK(!mailbox.IsValid() || !holder_ref_ ||
|
| + !mailbox.Equals(holder_ref_->holder()->mailbox()));
|
| + // If we never commited the mailbox, we need to release it here.
|
| + if (mailbox.IsValid())
|
| + holder_ref_ = MailboxHolder::Create(mailbox);
|
| + else
|
| + holder_ref_.reset();
|
| + needs_set_mailbox_ = true;
|
| SetNeedsCommit();
|
| }
|
|
|
| @@ -174,11 +154,16 @@ void TextureLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) {
|
| void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
|
| if (texture_id_ && layer_tree_host() && host != layer_tree_host())
|
| layer_tree_host()->AcquireLayerTextures();
|
| + // If we're removed from the tree, the TextureLayerImpl will be destroyed, and
|
| + // we will need to set the mailbox again on a new TextureLayerImpl the next
|
| + // time we push.
|
| + if (!host && uses_mailbox_ && holder_ref_)
|
| + needs_set_mailbox_ = true;
|
| Layer::SetLayerTreeHost(host);
|
| }
|
|
|
| bool TextureLayer::DrawsContent() const {
|
| - return (client_ || texture_id_ || texture_mailbox_.IsValid()) &&
|
| + return (client_ || texture_id_ || holder_ref_) &&
|
| !context_lost_ && Layer::DrawsContent();
|
| }
|
|
|
| @@ -213,13 +198,16 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
|
| texture_layer->set_uv_bottom_right(uv_bottom_right_);
|
| texture_layer->set_vertex_opacity(vertex_opacity_);
|
| texture_layer->set_premultiplied_alpha(premultiplied_alpha_);
|
| - if (uses_mailbox_ && own_mailbox_) {
|
| - Thread* main_thread = layer_tree_host()->proxy()->MainThread();
|
| - TextureMailbox::ReleaseCallback callback = base::Bind(
|
| - &PostCallbackToThread, main_thread, texture_mailbox_.callback());
|
| - texture_layer->SetTextureMailbox(
|
| - texture_mailbox_.CopyWithNewCallback(callback));
|
| - own_mailbox_ = false;
|
| + if (uses_mailbox_ && needs_set_mailbox_) {
|
| + TextureMailbox texture_mailbox;
|
| + if (holder_ref_) {
|
| + MailboxHolder* holder = holder_ref_->holder();
|
| + TextureMailbox::ReleaseCallback callback =
|
| + holder->GetCallbackForImplThread();
|
| + texture_mailbox = holder->mailbox().CopyWithNewCallback(callback);
|
| + }
|
| + texture_layer->SetTextureMailbox(texture_mailbox);
|
| + needs_set_mailbox_ = false;
|
| } else {
|
| texture_layer->set_texture_id(texture_id_);
|
| }
|
| @@ -237,4 +225,72 @@ bool TextureLayer::CanClipSelf() const {
|
| return true;
|
| }
|
|
|
| +TextureLayer::MailboxHolder::MainThreadReference::MainThreadReference(
|
| + MailboxHolder* holder)
|
| + : holder_(holder) {
|
| + holder_->InternalAddRef();
|
| +}
|
| +
|
| +TextureLayer::MailboxHolder::MainThreadReference::~MainThreadReference() {
|
| + holder_->InternalRelease();
|
| +}
|
| +
|
| +TextureLayer::MailboxHolder::MailboxHolder(const TextureMailbox& mailbox)
|
| + : message_loop_(base::MessageLoopProxy::current()),
|
| + internal_references_(0),
|
| + mailbox_(mailbox),
|
| + sync_point_(mailbox.sync_point()),
|
| + is_lost_(false) {
|
| +}
|
| +
|
| +TextureLayer::MailboxHolder::~MailboxHolder() {
|
| + DCHECK_EQ(0u, internal_references_);
|
| +}
|
| +
|
| +scoped_ptr<TextureLayer::MailboxHolder::MainThreadReference>
|
| +TextureLayer::MailboxHolder::Create(const TextureMailbox& mailbox) {
|
| + return scoped_ptr<MainThreadReference>(new MainThreadReference(
|
| + new MailboxHolder(mailbox)));
|
| +}
|
| +
|
| +void TextureLayer::MailboxHolder::Return(unsigned sync_point, bool is_lost) {
|
| + sync_point_ = sync_point;
|
| + is_lost_ = is_lost;
|
| +}
|
| +
|
| +TextureMailbox::ReleaseCallback
|
| +TextureLayer::MailboxHolder::GetCallbackForImplThread() {
|
| + // We can't call GetCallbackForImplThread if we released the main thread
|
| + // reference.
|
| + DCHECK_GT(internal_references_, 0u);
|
| + InternalAddRef();
|
| + return base::Bind(&MailboxHolder::ReturnAndReleaseOnImplThread, this);
|
| +}
|
| +
|
| +void TextureLayer::MailboxHolder::InternalAddRef() {
|
| + ++internal_references_;
|
| +}
|
| +
|
| +void TextureLayer::MailboxHolder::InternalRelease() {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + if (!--internal_references_) {
|
| + mailbox_.RunReleaseCallback(sync_point_, is_lost_);
|
| + mailbox_ = TextureMailbox();
|
| + }
|
| +}
|
| +
|
| +void TextureLayer::MailboxHolder::ReturnAndReleaseOnMainThread(
|
| + unsigned sync_point, bool is_lost) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + Return(sync_point, is_lost);
|
| + InternalRelease();
|
| +}
|
| +
|
| +void TextureLayer::MailboxHolder::ReturnAndReleaseOnImplThread(
|
| + unsigned sync_point, bool is_lost) {
|
| + message_loop_->PostTask(FROM_HERE, base::Bind(
|
| + &MailboxHolder::ReturnAndReleaseOnMainThread,
|
| + this, sync_point, is_lost));
|
| +}
|
| +
|
| } // namespace cc
|
|
|