Chromium Code Reviews| Index: content/renderer/browser_plugin/browser_plugin_texture_provider.cc |
| diff --git a/content/renderer/browser_plugin/browser_plugin_texture_provider.cc b/content/renderer/browser_plugin/browser_plugin_texture_provider.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8e091d3519e6e753867f2c7f406d338117c37811 |
| --- /dev/null |
| +++ b/content/renderer/browser_plugin/browser_plugin_texture_provider.cc |
| @@ -0,0 +1,244 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/renderer/browser_plugin/browser_plugin_texture_provider.h" |
| + |
| +#include "base/message_loop.h" |
| +#include "content/common/browser_plugin_messages.h" |
| +#include "content/renderer/browser_plugin/browser_plugin_manager.h" |
| +#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" |
| +#include "content/renderer/render_view_impl.h" |
| +#include "content/renderer/render_thread_impl.h" |
| + |
| +using WebKit::WebFloatRect; |
| + |
| +namespace { |
| +bool MessageHasInstanceId(int instance_id, const IPC::Message& message) { |
| + int message_instance; |
| + DCHECK(!message.is_sync()); |
| + PickleIterator iter(message); |
| + // TODO(scshunt): is there a way to do this that doesn't rely on an int |
| + // to work? |
| + bool success = iter.ReadInt(&message_instance); |
| + DCHECK(success); |
| + return instance_id == message_instance; |
| +} |
| +} |
| + |
|
scshunt
2012/08/12 01:42:45
Explanation of the key sequences here would probab
|
| +namespace content { |
| + |
| +// Called on main thread |
| +BrowserPluginTextureProvider::BrowserPluginTextureProvider( |
| + int instance_id, |
| + RenderViewImpl* render_view) |
| + : client_(0), |
| + texture_id_(0), |
| + filter_(0), |
| + instance_id_(instance_id), |
| + main_loop_( |
| + RenderThreadImpl::current()->GetMessageLoop()->message_loop_proxy()), |
| + channel_proxy_(RenderThread::Get()->GetChannel()), |
| + render_view_(render_view) { |
| +} |
| + |
| +// Called on impl thread if we have one, main thread otherwise |
| +BrowserPluginTextureProvider::~BrowserPluginTextureProvider() { |
| +#ifndef NDBEUG |
| + // Destroy() ends our lifetime on the main thread, so this should |
| + // not be in use. |
| + bool locked = lock_.Try(); |
| + DCHECK(locked); |
| + lock_.Release(); |
| +#endif |
| + |
| + if (client_) |
| + client_->stopUsingProvider(); |
| + channel_proxy_->RemoveFilter(filter_); |
| +} |
| + |
| +// Called on the main thread; ends the lifetime on this thread |
| +void BrowserPluginTextureProvider::Destroy() { |
| + base::AutoLock scoped_lock(lock_); |
| + |
| + if (impl_loop_) |
| + impl_loop_->PostTask(FROM_HERE, base::Bind( |
| + &BrowserPluginTextureProvider::DestroyImpl, |
| + base::Unretained(this))); |
| + else |
| + DestroyImpl(); |
| +} |
| + |
| +// Called on impl thread if we have one, main thread otherwise |
| +void BrowserPluginTextureProvider::DestroyImpl() { |
| + delete this; |
| +} |
| + |
| +// Called on impl thread (we store our impl thread loop here) |
| +void BrowserPluginTextureProvider::setTextureProviderClient(Client* client) { |
| + static const uint32 messages[] = { |
| + BrowserPluginMsg_BuffersSwapped::ID, |
| + BrowserPluginMsg_SurfaceResize::ID, |
| + }; |
| + |
| + base::AutoLock scoped_lock(lock_); |
| + |
| + if (client_) { |
| + client_->stopUsingProvider(); |
| + } |
| + |
| + if (client) { |
| + if (!impl_loop_) { |
| + impl_loop_ = base::MessageLoopProxy::current(); |
| + |
| + filter_ = new IPC::ForwardingMessageFilter( |
| + messages, |
| + arraysize(messages), |
| + impl_loop_, |
| + base::Bind( |
| + &BrowserPluginTextureProvider::OnMessageReceived, |
| + base::Unretained(this))); |
| + filter_->AddRoute(MSG_ROUTING_CONTROL); |
| + filter_->SetPredicate(base::Bind(&MessageHasInstanceId, instance_id_)); |
| + channel_proxy_->AddFilter(filter_); |
| + main_loop_->PostTask(FROM_HERE, base::Bind( |
| + &BrowserPluginTextureProvider::SignalReady, |
| + instance_id_)); |
| + } |
| + // This is tautological if we took the above branch, but |
| + // if we already had a loop, we want to verify that we should be |
| + // on the same one. |
| + DCHECK(impl_loop_ == base::MessageLoopProxy::current()); |
| + |
| + if (has_delayed_swap_) { |
| + impl_loop_->PostTask(FROM_HERE, base::Bind( |
| + &BrowserPluginTextureProvider::OnBuffersSwapped, |
| + base::Unretained(this), |
| + instance_id_, |
| + texture_id_, |
| + delayed_swap_info_)); |
| + } |
| + } else { |
| + if (impl_loop_) { |
| + channel_proxy_->RemoveFilter(filter_); |
| + } |
| + |
| + impl_loop_ = 0; |
| + } |
| + |
| + client_ = client; |
| +} |
| + |
| +// Called on main thread |
| +void BrowserPluginTextureProvider::SignalReady(int instance_id) { |
| + BrowserPluginManagerImpl::Get()->TextureProviderIsReady(instance_id); |
| +} |
| + |
| +// Called on impl thread |
| +unsigned BrowserPluginTextureProvider::textureId() const { |
| + return texture_id_; |
| +} |
| + |
| +// Called on impl thread |
| +bool BrowserPluginTextureProvider::premultipliedAlpha() const { |
| + return true; |
| +} |
| + |
| +// Called on impl thread |
| +bool BrowserPluginTextureProvider::flipped() const { |
| + return true; |
| +} |
| + |
| +// Called on impl thread |
| +WebFloatRect BrowserPluginTextureProvider::uvRect() const { |
| + if (texture_size_.width() == 0 || texture_size_.height() == 0) |
| + return WebFloatRect(0, 0, 1, 1); |
| + |
| + return WebFloatRect( |
| + 0, |
| + 0, |
| + ((long double)(size_.width())) / texture_size_.width(), |
| + ((long double)(size_.height())) / texture_size_.height()); |
| +} |
| + |
| +// Called on impl thread |
| +void BrowserPluginTextureProvider::OnMessageReceived( |
| + const IPC::Message& message) { |
| + IPC_BEGIN_MESSAGE_MAP(BrowserPluginTextureProvider, message) |
| + IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped) |
| + IPC_MESSAGE_HANDLER(BrowserPluginMsg_SurfaceResize, OnSurfaceResize) |
| + IPC_END_MESSAGE_MAP() |
| +} |
| + |
| +// Called on impl thread |
| +void BrowserPluginTextureProvider::OnBuffersSwapped( |
| + int instance_id, |
| + uint64 surface_handle, |
| + const BrowserPlugin_SwapInfo& info) { |
| + DCHECK(surface_handle != 0); |
| + DCHECK(client_); |
| + DCHECK(instance_id == instance_id_); |
| + |
| + texture_id_ = surface_handle; |
| + client_->didReceiveFrame(); |
| + channel_proxy_->Send(new BrowserPluginHostMsg_BuffersSwappedACK( |
| + render_view_->GetRoutingID(), |
| + info, |
| + client_->insertSyncPoint())); |
| +} |
| + |
| +// Called on impl thread |
| +void BrowserPluginTextureProvider::OnSurfaceResize( |
| + int instance_id, |
| + const gfx::Size& size) { |
| + DCHECK(instance_id == instance_id_); |
| + texture_size_ = size; |
| +} |
| + |
| +// Called on main thread prior to attaching client |
| +void BrowserPluginTextureProvider::SurfaceResize(const gfx::Size& size) { |
| + DCHECK(!client_); |
| + DCHECK(!impl_loop_); |
| + size_ = size; |
| +} |
| + |
| +// Called on any thread |
| +void BrowserPluginTextureProvider::Resize(const gfx::Size& size) { |
| + base::AutoLock scoped_lock(lock_); |
| + |
| + if (impl_loop_) |
| + impl_loop_->PostTask(FROM_HERE, base::Bind( |
| + &BrowserPluginTextureProvider::ResizeImpl, |
| + base::Unretained(this), |
| + size)); |
| + else |
| + ResizeImpl(size); |
| +} |
| + |
| +// Called on main thread |
| +void BrowserPluginTextureProvider::SetDelayedSwap( |
| + uint64 surface_handle, |
| + const BrowserPlugin_SwapInfo& info) { |
| + base::AutoLock scoped_lock(lock_); |
| + |
| + if (impl_loop_) { |
| + impl_loop_->PostTask(FROM_HERE, base::Bind( |
| + &BrowserPluginTextureProvider::OnBuffersSwapped, |
| + base::Unretained(this), |
| + instance_id_, |
| + surface_handle, |
| + info)); |
| + } else { |
| + has_delayed_swap_ = true; |
| + delayed_swap_info_ = info; |
| + texture_id_ = surface_handle; |
| + // TODO(scshunt): Fix this |
| + } |
| +} |
| + |
| +// Called on impl thread if we have one, otherwise main thread |
| +void BrowserPluginTextureProvider::ResizeImpl(const gfx::Size& size) { |
| + size_ = size; |
| +} |
| + |
| +} // namespace content |