| 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..61be09791119819d13b0a87a4183e6a39da1bb73
|
| --- /dev/null
|
| +++ b/content/renderer/browser_plugin/browser_plugin_texture_provider.cc
|
| @@ -0,0 +1,277 @@
|
| +// 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 {
|
| +int GetMessageInstanceId(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 message_instance;
|
| +}
|
| +}
|
| +
|
| +namespace content {
|
| +
|
| +// Called on main therad
|
| +BrowserPluginTextureProvider::BrowserPluginTextureProvider(
|
| + int instance_id,
|
| + int host_routing_id,
|
| + IPC::ChannelProxy* channel_proxy)
|
| + : client_(0),
|
| + texture_id_(0),
|
| + filter_(0),
|
| + instance_id_(instance_id),
|
| + main_loop_(base::MessageLoopProxy::current()),
|
| + channel_proxy_(channel_proxy),
|
| + host_routing_id_(host_routing_id),
|
| + has_delayed_swap_(false) {
|
| + // Once we get a fake ChannelProxy for testing, this should be enabled
|
| + // DCHECK(channel_proxy_);
|
| +}
|
| +
|
| +// 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
|
| +
|
| + RemoveFilter();
|
| + if (client_)
|
| + client_->stopUsingProvider();
|
| +}
|
| +
|
| +// Called on the main thread; ends the lifetime on this thread
|
| +void BrowserPluginTextureProvider::Destroy() {
|
| + // We need to release the lock before destruction, so this is
|
| + // not a scoped lock
|
| + lock_.Acquire();
|
| +
|
| + if (impl_loop_) {
|
| + lock_.Release();
|
| + impl_loop_->PostTask(FROM_HERE, base::Bind(
|
| + &BrowserPluginTextureProvider::DestroyImpl,
|
| + base::Unretained(this)));
|
| + } else {
|
| + lock_.Release();
|
| + 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) {
|
| + base::AutoLock scoped_lock(lock_);
|
| +
|
| + if (client_) {
|
| + client_->stopUsingProvider();
|
| + }
|
| +
|
| + if (client) {
|
| + if (!impl_loop_) {
|
| + impl_loop_ = base::MessageLoopProxy::current();
|
| +
|
| + SetUpFilter();
|
| + 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 are
|
| + // 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_) {
|
| + RemoveFilter();
|
| + }
|
| +
|
| + impl_loop_ = 0;
|
| + }
|
| +
|
| + client_ = client;
|
| +}
|
| +
|
| +// Called on main thread
|
| +void BrowserPluginTextureProvider::SignalReady(int instance_id) {
|
| + BrowserPluginManagerImpl::Get()->SignalTextureProviderIsReady(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,
|
| + (static_cast<float>(container_size_.width())) / texture_size_.width(),
|
| + (static_cast<float>(container_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();
|
| + Send(new BrowserPluginHostMsg_BuffersSwappedACK(
|
| + host_routing_id_,
|
| + 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_);
|
| + OnSurfaceResize(instance_id_, 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 any thread
|
| +bool BrowserPluginTextureProvider::Send(IPC::Message* message) {
|
| + DCHECK(channel_proxy_);
|
| + return channel_proxy_->Send(message);
|
| +}
|
| +
|
| +
|
| +// Called on impl thread if we have one, otherwise main thread
|
| +void BrowserPluginTextureProvider::ResizeImpl(const gfx::Size& size) {
|
| + container_size_ = size;
|
| +}
|
| +
|
| +// Called on impl thread to create a new filter and attach it to the
|
| +// ChannelProxy
|
| +void BrowserPluginTextureProvider::SetUpFilter() {
|
| + DCHECK(channel_proxy_);
|
| +
|
| + static const uint32 messages[] = {
|
| + BrowserPluginMsg_BuffersSwapped::ID,
|
| + BrowserPluginMsg_SurfaceResize::ID,
|
| + };
|
| +
|
| + filter_ = new IPC::ForwardingMessageFilter(
|
| + messages,
|
| + arraysize(messages),
|
| + impl_loop_);
|
| + filter_->AddRoute(
|
| + instance_id_,
|
| + base::Bind(
|
| + &BrowserPluginTextureProvider::OnMessageReceived,
|
| + base::Unretained(this)));
|
| + filter_->SetIDCallback(base::Bind(&GetMessageInstanceId));
|
| + channel_proxy_->AddFilter(filter_);
|
| +}
|
| +
|
| +// Called on impl thread to clear the filter
|
| +void BrowserPluginTextureProvider::RemoveFilter() {
|
| + if (filter_) {
|
| + DCHECK(impl_loop_);
|
| + DCHECK(impl_loop_ == base::MessageLoopProxy::current());
|
| + channel_proxy_->RemoveFilter(filter_);
|
| + }
|
| +}
|
| +
|
| +} // namespace content
|
|
|