gpu_channel_host.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle,
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WaitableEvent* shutdown_event) {
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(factory->IsMainThread());
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<GpuChannelHost> host = new GpuChannelHost(factory, gpu_info);
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->Connect(channel_handle, shutdown_event);
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)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle,
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             base::WaitableEvent* shutdown_event) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open a channel to the GPU process. We pass NULL as the main listener here
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since we need to filter everything to route it to the right thread.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  channel_.reset(new IPC::SyncChannel(channel_handle,
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      IPC::Channel::MODE_CLIENT,
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      NULL,
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      io_loop.get(),
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      true,
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      shutdown_event));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  sync_filter_ = new IPC::SyncMessageFilter(shutdown_event);
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;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool result = channel_->Send(message.release());
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!result)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << "GpuChannelHost::Send failed: Channel::Send failed";
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return result;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (base::MessageLoop::current()) {
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool result = sync_filter_->Send(message.release());
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!result)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1) << "GpuChannelHost::Send failed: SyncMessageFilter::Send failed";
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return result;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateViewCommandBuffer(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 surface_id,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "GpuChannelHost::CreateViewCommandBuffer",
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "surface_id",
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               surface_id);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id = factory_->CreateViewCommandBuffer(surface_id, init_params);
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE) {
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "GpuChannelHost::CreateViewCommandBuffer failed.";
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl* GpuChannelHost::CreateOffscreenCommandBuffer(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* share_group,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CreateOffscreenCommandBuffer");
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCreateCommandBufferConfig init_params;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.share_group_id =
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group ? share_group->GetRouteID() : MSG_ROUTING_NONE;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.attribs = attribs;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.active_url = active_url;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_params.gpu_preference = gpu_preference;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 route_id;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(size,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           init_params,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           &route_id))) {
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Failed to send GpuChannelMsg_CreateOffscreenCommandBuffer.";
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE) {
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR)
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        << "GpuChannelMsg_CreateOffscreenCommandBuffer returned failure.";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* command_buffer =
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new CommandBufferProxyImpl(this, route_id);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRoute(route_id, command_buffer->AsWeakPtr());
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_[route_id] = command_buffer;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_buffer;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<media::VideoDecodeAccelerator> GpuChannelHost::CreateVideoDecoder(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int command_buffer_route_id,
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media::VideoCodecProfile profile) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(context_lock_);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyMap::iterator it = proxies_.find(command_buffer_route_id);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != proxies_.end());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferProxyImpl* proxy = it->second;
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return proxy->CreateVideoDecoder(profile).Pass();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<media::VideoEncodeAccelerator> GpuChannelHost::CreateVideoEncoder() {
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::CreateVideoEncoder");
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<media::VideoEncodeAccelerator> vea;
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int32 route_id = MSG_ROUTING_NONE;
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!Send(new GpuChannelMsg_CreateVideoEncoder(&route_id)))
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return vea.Pass();
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (route_id == MSG_ROUTING_NONE)
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return vea.Pass();
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  vea.reset(new GpuVideoEncodeAcceleratorHost(this, route_id));
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return vea.Pass();
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::DestroyCommandBuffer(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferProxyImpl* command_buffer) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuChannelHost::DestroyCommandBuffer");
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int route_id = command_buffer->GetRouteID();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuChannelMsg_DestroyCommandBuffer(route_id));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveRoute(route_id);
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(context_lock_);
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  proxies_.erase(route_id);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete command_buffer;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::AddRoute(
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id, base::WeakPtr<IPC::Listener> listener) {
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(MessageLoopProxy::current().get());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::AddRoute,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id, listener,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               MessageLoopProxy::current()));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::RemoveRoute(int route_id) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop->PostTask(FROM_HERE,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               channel_filter_.get(), route_id));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::SharedMemoryHandle source_handle) {
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (IsLost())
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Windows needs to explicitly duplicate the handle out to another process.
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::SharedMemoryHandle target_handle;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!BrokerDuplicateHandle(source_handle,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             channel_->peer_pid(),
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &target_handle,
2590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                             FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                             0)) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return target_handle;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int duped_handle = HANDLE_EINTR(dup(source_handle.fd));
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (duped_handle < 0)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::SharedMemory::NULLHandle();
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::FileDescriptor(duped_handle, true);
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 GpuChannelHost::ReserveTransferBufferId() {
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return next_transfer_buffer_id_.GetNext();
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    gfx::GpuMemoryBufferHandle source_handle) {
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (source_handle.type) {
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case gfx::SHARED_MEMORY_BUFFER: {
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      gfx::GpuMemoryBufferHandle handle;
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      handle.type = gfx::SHARED_MEMORY_BUFFER;
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      handle.handle = ShareToGpuProcess(source_handle.handle);
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return handle;
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX)
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case gfx::IO_SURFACE_BUFFER:
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return source_handle;
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTREACHED();
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return gfx::GpuMemoryBufferHandle();
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int32 GpuChannelHost::ReserveGpuMemoryBufferId() {
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return next_gpu_memory_buffer_id_.GetNext();
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuChannelHost::~GpuChannelHost() {
3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // channel_ must be destroyed on the main thread.
3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!factory_->IsMainThread())
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    factory_->GetMainLoop()->DeleteSoon(FROM_HERE, channel_.release());
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GpuChannelHost::MessageFilter::MessageFilter()
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : lost_(false) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuChannelHost::MessageFilter::~MessageFilter() {}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::AddRoute(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IPC::Listener> listener,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<MessageLoopProxy> loop) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(listeners_.find(route_id) == listeners_.end());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuListenerInfo info;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.listener = listener;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info.loop = loop;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_[route_id] = info;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(route_id);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != listeners_.end())
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listeners_.erase(it);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuChannelHost::MessageFilter::OnMessageReceived(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never handle sync message replies or we will deadlock here.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message.is_reply())
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListenerMap::iterator it = listeners_.find(message.routing_id());
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (it == listeners_.end())
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GpuListenerInfo& info = it->second;
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  info.loop->PostTask(
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::IgnoreResult(&IPC::Listener::OnMessageReceived),
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          info.listener,
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          message));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuChannelHost::MessageFilter::OnChannelError() {
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Set the lost state before signalling the proxies. That way, if they
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // themselves post a task to recreate the context, they will not try to re-use
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // this channel host.
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AutoLock lock(lock_);
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    lost_ = true;
3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform all the proxies that an error has occurred. This will be reported
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // via OpenGL as a lost context.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ListenerMap::iterator it = listeners_.begin();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners_.end();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it++) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuListenerInfo& info = it->second;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.loop->PostTask(
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&IPC::Listener::OnChannelError, info.listener));
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_.clear();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GpuChannelHost::MessageFilter::IsLost() const {
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoLock lock(lock_);
3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return lost_;
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
380