gpu_channel_host.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/gpu_channel_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop_proxy.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/command_buffer_proxy_impl.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/common/mailbox.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/sandbox_init.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::AutoLock;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::MessageLoopProxy;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuListenerInfo::GpuListenerInfo() {}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuListenerInfo::~GpuListenerInfo() {}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannelHost::GpuChannelHost(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelHostFactory* factory, int gpu_host_id, int client_id)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : factory_(factory),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_id_(client_id),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gpu_host_id_(gpu_host_id),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(kUnconnected) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next_transfer_buffer_id_.GetNext();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::Connect(
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(factory_->IsMainThread());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open a channel to the GPU process. We pass NULL as the main listener here
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since we need to filter everything to route it to the right thread.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_.reset(new IPC::SyncChannel(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_handle, IPC::Channel::MODE_CLIENT, NULL,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_loop, true,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factory_->GetShutDownEvent()));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_filter_ = new IPC::SyncMessageFilter(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factory_->GetShutDownEvent());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(sync_filter_.get());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  channel_filter_ = new MessageFilter(AsWeakPtr(), factory_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Install the filter last, because we intercept all leftover
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // messages.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(channel_filter_.get());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is safe to send IPC messages before the channel completes the connection
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and receives the hello message from the GPU process. The messages get
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cached.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kConnected;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::set_gpu_info(const GPUInfo& gpu_info) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu_info_ = gpu_info;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::SetStateLost() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kLost;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const GPUInfo& GpuChannelHost::gpu_info() const {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gpu_info_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::OnMessageReceived(const IPC::Message& message) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool handled = true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(GpuChannelHost, message)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesReply,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          OnGenerateMailboxNamesReply)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(handled);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::OnChannelError() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kLost;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Channel is invalid and will be reinitialized if this host is requested
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // again.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_.reset();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::Send(IPC::Message* message) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The GPU process never sends synchronous IPCs so clear the unblock flag to
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preserve order.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message->set_unblock(false);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently we need to choose between two different mechanisms for sending.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On the main thread we use the regular channel Send() method, on another
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread we use SyncMessageFilter. We also have to be careful interpreting
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IsMainThread() since it might return false during shutdown,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // impl we are actually calling from the main thread (discard message then).
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: Can we just always use sync_filter_ since we setup the channel
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       without a main listener?
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (factory_->IsMainThread()) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (channel_.get()) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // http://crbug.com/125264
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ThreadRestrictions::ScopedAllowWait allow_wait;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return channel_->Send(message);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (MessageLoop::current()) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sync_filter_->Send(message);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callee takes ownership of message, regardless of whether Send is
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // successful. See IPC::Sender.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete message;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateViewCommandBuffer(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 surface_id,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& allowed_extensions,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannelHost::CreateViewCommandBuffer",
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "surface_id",
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               surface_id);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An error occurred. Need to get the host again to reinitialize it.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_.get())
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.allowed_extensions = allowed_extensions;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id = factory_->CreateViewCommandBuffer(surface_id, init_params);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateOffscreenCommandBuffer(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& allowed_extensions,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CreateOffscreenCommandBuffer");
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An error occurred. Need to get the host again to reinitialize it.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_.get())
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.allowed_extensions = allowed_extensions;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           init_params,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           &route_id))) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int command_buffer_route_id,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCodecProfile profile,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoDecodeAccelerator::Client* client) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyMap::iterator it = proxies_.find(command_buffer_route_id);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != proxies_.end());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* proxy = it->second;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy->CreateVideoDecoder(profile, client);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::DestroyCommandBuffer(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* command_buffer) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::DestroyCommandBuffer");
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id = command_buffer->GetRouteID();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuChannelMsg_DestroyCommandBuffer(route_id));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the proxy has not already been removed after a channel error.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxies_.find(route_id) != proxies_.end())
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxies_.erase(route_id);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveRoute(route_id);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete command_buffer;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::CollectRenderingStatsForSurface(
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int surface_id, GpuRenderingStats* stats) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CollectRenderingStats");
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new GpuChannelMsg_CollectRenderingStatsForSurface(surface_id,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                stats));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::AddRoute(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id, base::WeakPtr<IPC::Listener> listener) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(MessageLoopProxy::current());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::AddRoute,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id, listener,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               MessageLoopProxy::current()));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::RemoveRoute(int route_id) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemory* shared_memory) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(context_lock_);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!channel_.get())
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SharedMemoryHandle handle;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Windows needs to explicitly duplicate the handle out to another process.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BrokerDuplicateHandle(shared_memory->handle(),
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             channel_->peer_pid(),
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             &handle,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             FILE_MAP_WRITE,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             0)) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!shared_memory->ShareToProcess(channel_->peer_pid(), &handle))
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return handle;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::GenerateMailboxNames(unsigned num,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          std::vector<gpu::Mailbox>* names) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GenerateMailboxName");
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num > mailbox_name_pool_.size()) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Send(new GpuChannelMsg_GenerateMailboxNames(num, names)))
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    names->insert(names->begin(),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  mailbox_name_pool_.end() - num,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  mailbox_name_pool_.end());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mailbox_name_pool_.erase(mailbox_name_pool_.end() - num,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             mailbox_name_pool_.end());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned ideal_mailbox_pool_size = 100;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mailbox_name_pool_.size() < ideal_mailbox_pool_size / 2) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new GpuChannelMsg_GenerateMailboxNamesAsync(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ideal_mailbox_pool_size - mailbox_name_pool_.size()));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::OnGenerateMailboxNamesReply(
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<gpu::Mailbox>& names) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "OnGenerateMailboxNamesReply");
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mailbox_name_pool_.insert(mailbox_name_pool_.end(),
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            names.begin(),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            names.end());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 GpuChannelHost::ReserveTransferBufferId() {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return next_transfer_buffer_id_.GetNext();
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannelHost::~GpuChannelHost() {}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuChannelHost::MessageFilter::MessageFilter(
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<GpuChannelHost> parent,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuChannelHostFactory* factory)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : parent_(parent),
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      factory_(factory) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannelHost::MessageFilter::~MessageFilter() {}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::AddRoute(
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IPC::Listener> listener,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<MessageLoopProxy> loop) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(factory_->IsIOThread());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listeners_.find(route_id) == listeners_.end());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuListenerInfo info;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.listener = listener;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.loop = loop;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_[route_id] = info;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(factory_->IsIOThread());
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(route_id);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != listeners_.end())
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listeners_.erase(it);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::MessageFilter::OnMessageReceived(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message) {
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(factory_->IsIOThread());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never handle sync message replies or we will deadlock here.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.is_reply())
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.routing_id() == MSG_ROUTING_CONTROL) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessageLoop* main_loop = factory_->GetMainLoop();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    main_loop->PostTask(FROM_HERE,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base::Bind(&GpuChannelHost::OnMessageReceived,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   parent_,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   message));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(message.routing_id());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != listeners_.end()) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuListenerInfo& info = it->second;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.loop->PostTask(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::IgnoreResult(&IPC::Listener::OnMessageReceived),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            info.listener,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            message));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::OnChannelError() {
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(factory_->IsIOThread());
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post the task to signal the GpuChannelHost before the proxies. That way, if
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they themselves post a task to recreate the context, they will not try to
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-use this channel host before it has a chance to mark itself lost.
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MessageLoop* main_loop = factory_->GetMainLoop();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_loop->PostTask(FROM_HERE,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::Bind(&GpuChannelHost::OnChannelError, parent_));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform all the proxies that an error has occurred. This will be reported
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // via OpenGL as a lost context.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ListenerMap::iterator it = listeners_.begin();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners_.end();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it++) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuListenerInfo& info = it->second;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.loop->PostTask(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&IPC::Listener::OnChannelError, info.listener));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_.clear();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
404