gpu_channel_host.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <algorithm>
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/command_buffer_proxy_impl.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/sandbox_init.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::AutoLock;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::MessageLoopProxy;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuListenerInfo::GpuListenerInfo() {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuListenerInfo::~GpuListenerInfo() {}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// static
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_refptr<GpuChannelHost> GpuChannelHost::Create(
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    GpuChannelHostFactory* factory,
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const gpu::GPUInfo& gpu_info,
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle) {
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(factory->IsMainThread());
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<GpuChannelHost> host = new GpuChannelHost(
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      factory, gpu_info);
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  host->Connect(channel_handle);
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return host;
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool GpuChannelHost::IsValidGpuMemoryBuffer(
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::GpuMemoryBufferHandle handle) {
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (handle.type) {
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case gfx::SHARED_MEMORY_BUFFER:
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX)
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case gfx::IO_SURFACE_BUFFER:
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return true;
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return false;
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory,
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               const gpu::GPUInfo& gpu_info)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : factory_(factory),
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      gpu_info_(gpu_info) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next_transfer_buffer_id_.GetNext();
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  next_gpu_memory_buffer_id_.GetNext();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open a channel to the GPU process. We pass NULL as the main listener here
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since we need to filter everything to route it to the right thread.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  channel_.reset(new IPC::SyncChannel(channel_handle,
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      IPC::Channel::MODE_CLIENT,
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      NULL,
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      io_loop.get(),
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      true,
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      factory_->GetShutDownEvent()));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_filter_ = new IPC::SyncMessageFilter(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factory_->GetShutDownEvent());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(sync_filter_.get());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  channel_filter_ = new MessageFilter();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Install the filter last, because we intercept all leftover
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // messages.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(channel_filter_.get());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GpuChannelHost::Send(IPC::Message* msg) {
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Callee takes ownership of message, regardless of whether Send is
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // successful. See IPC::Sender.
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<IPC::Message> message(msg);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The GPU process never sends synchronous IPCs so clear the unblock flag to
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preserve order.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message->set_unblock(false);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently we need to choose between two different mechanisms for sending.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On the main thread we use the regular channel Send() method, on another
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread we use SyncMessageFilter. We also have to be careful interpreting
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IsMainThread() since it might return false during shutdown,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // impl we are actually calling from the main thread (discard message then).
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: Can we just always use sync_filter_ since we setup the channel
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       without a main listener?
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (factory_->IsMainThread()) {
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // http://crbug.com/125264
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::ThreadRestrictions::ScopedAllowWait allow_wait;
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return channel_->Send(message.release());
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (base::MessageLoop::current()) {
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return sync_filter_->Send(message.release());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateViewCommandBuffer(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 surface_id,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannelHost::CreateViewCommandBuffer",
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "surface_id",
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               surface_id);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id = factory_->CreateViewCommandBuffer(surface_id, init_params);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateOffscreenCommandBuffer(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CreateOffscreenCommandBuffer");
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           init_params,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           &route_id))) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<media::VideoDecodeAccelerator> GpuChannelHost::CreateVideoDecoder(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int command_buffer_route_id,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCodecProfile profile,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoDecodeAccelerator::Client* client) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyMap::iterator it = proxies_.find(command_buffer_route_id);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != proxies_.end());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* proxy = it->second;
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return proxy->CreateVideoDecoder(profile, client).Pass();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<media::VideoEncodeAccelerator> GpuChannelHost::CreateVideoEncoder(
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::VideoEncodeAccelerator::Client* client) {
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CreateVideoEncoder");
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<media::VideoEncodeAccelerator> vea;
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32 route_id = MSG_ROUTING_NONE;
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!Send(new GpuChannelMsg_CreateVideoEncoder(&route_id)))
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return vea.Pass();
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return vea.Pass();
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  vea.reset(new GpuVideoEncodeAcceleratorHost(client, this, route_id));
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return vea.Pass();
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::DestroyCommandBuffer(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* command_buffer) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::DestroyCommandBuffer");
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id = command_buffer->GetRouteID();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuChannelMsg_DestroyCommandBuffer(route_id));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveRoute(route_id);
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  proxies_.erase(route_id);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete command_buffer;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::AddRoute(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id, base::WeakPtr<IPC::Listener> listener) {
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(MessageLoopProxy::current().get());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::AddRoute,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id, listener,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               MessageLoopProxy::current()));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::RemoveRoute(int route_id) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id));
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::SharedMemoryHandle source_handle) {
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (IsLost())
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Windows needs to explicitly duplicate the handle out to another process.
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::SharedMemoryHandle target_handle;
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!BrokerDuplicateHandle(source_handle,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             channel_->peer_pid(),
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &target_handle,
2490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                             FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                             0)) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return target_handle;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int duped_handle = HANDLE_EINTR(dup(source_handle.fd));
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (duped_handle < 0)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::FileDescriptor(duped_handle, true);
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 GpuChannelHost::ReserveTransferBufferId() {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return next_transfer_buffer_id_.GetNext();
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::GpuMemoryBufferHandle source_handle) {
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (source_handle.type) {
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case gfx::SHARED_MEMORY_BUFFER: {
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      gfx::GpuMemoryBufferHandle handle;
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      handle.type = gfx::SHARED_MEMORY_BUFFER;
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      handle.handle = ShareToGpuProcess(source_handle.handle);
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return handle;
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX)
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case gfx::IO_SURFACE_BUFFER:
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return source_handle;
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTREACHED();
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return gfx::GpuMemoryBufferHandle();
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int32 GpuChannelHost::ReserveGpuMemoryBufferId() {
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return next_gpu_memory_buffer_id_.GetNext();
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuChannelHost::~GpuChannelHost() {
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // channel_ must be destroyed on the main thread.
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!factory_->IsMainThread())
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    factory_->GetMainLoop()->DeleteSoon(FROM_HERE, channel_.release());
2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuChannelHost::MessageFilter::MessageFilter()
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : lost_(false) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannelHost::MessageFilter::~MessageFilter() {}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::AddRoute(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IPC::Listener> listener,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<MessageLoopProxy> loop) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listeners_.find(route_id) == listeners_.end());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuListenerInfo info;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.listener = listener;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.loop = loop;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_[route_id] = info;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(route_id);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != listeners_.end())
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listeners_.erase(it);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::MessageFilter::OnMessageReceived(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never handle sync message replies or we will deadlock here.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.is_reply())
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(message.routing_id());
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (it == listeners_.end())
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GpuListenerInfo& info = it->second;
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  info.loop->PostTask(
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::IgnoreResult(&IPC::Listener::OnMessageReceived),
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          info.listener,
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          message));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::OnChannelError() {
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Set the lost state before signalling the proxies. That way, if they
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // themselves post a task to recreate the context, they will not try to re-use
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // this channel host.
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AutoLock lock(lock_);
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    lost_ = true;
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform all the proxies that an error has occurred. This will be reported
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // via OpenGL as a lost context.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ListenerMap::iterator it = listeners_.begin();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners_.end();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it++) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuListenerInfo& info = it->second;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.loop->PostTask(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&IPC::Listener::OnChannelError, info.listener));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_.clear();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GpuChannelHost::MessageFilter::IsLost() const {
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(lock_);
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return lost_;
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
370