browser_gpu_channel_host_factory.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/debug/trace_event.h"
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/gpu/gpu_data_manager_impl.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/gpu/gpu_process_host.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/gpu/gpu_surface_tracker.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/child_process_host_impl.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/gpu_data_manager.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/common/content_client.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ipc/ipc_forwarding_message_filter.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace content {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)BrowserGpuChannelHostFactory::CreateRequest::CreateRequest()
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : event(true, false),
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gpu_host_id(0),
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      route_id(MSG_ROUTING_NONE) {
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochBrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() {
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CauseForGpuLaunch cause,
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int gpu_client_id,
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int gpu_host_id)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : event_(false, false),
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      cause_for_gpu_launch_(cause),
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gpu_client_id_(gpu_client_id),
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gpu_host_id_(gpu_host_id),
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reused_gpu_process_(false),
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      finished_(false),
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      main_loop_(base::MessageLoopProxy::current()) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> loop =
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  loop->PostTask(
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 this));
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!host) {
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               cause_for_gpu_launch_);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!host) {
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      LOG(ERROR) << "Failed to launch GPU process.";
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FinishOnIO();
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_host_id_ = host->host_id();
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    reused_gpu_process_ = false;
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (reused_gpu_process_) {
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // We come here if we retried to establish the channel because of a
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // failure in ChannelEstablishedOnIO, but we ended up with the same
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // process ID, meaning the failure was not because of a channel error,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // but another reason. So fail now.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << "Failed to create channel.";
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FinishOnIO();
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    reused_gpu_process_ = true;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->EstablishGpuChannel(
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gpu_client_id_,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      true,
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          this));
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO(
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle,
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const gpu::GPUInfo& gpu_info) {
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (channel_handle.name.empty() && reused_gpu_process_) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // We failed after re-using the GPU process, but it may have died in the
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // mean time. Retry to have a chance to create a fresh GPU process.
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "Failed to create channel on existing GPU process. Trying to "
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                "restart GPU process.";
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EstablishOnIO();
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    channel_handle_ = channel_handle;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gpu_info_ = gpu_info;
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FinishOnIO();
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() {
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_.Signal();
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  main_loop_->PostTask(
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FROM_HERE,
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain,
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 this));
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!finished_) {
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserGpuChannelHostFactory* factory =
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        BrowserGpuChannelHostFactory::instance();
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    factory->GpuChannelEstablished();
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    finished_ = true;
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // We're blocking the UI thread, which is generally undesirable.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // In this case we need to wait for this before we can show any UI
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // /anyway/, so it won't cause additional jank.
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // TODO(piman): Make this asynchronous (http://crbug.com/125248).
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TRACE_EVENT0("browser",
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 "BrowserGpuChannelHostFactory::EstablishGpuChannelSync");
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::ThreadRestrictions::ScopedAllowWait allow_wait;
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    event_.Wait();
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FinishOnMain();
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() {
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  finished_ = true;
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool BrowserGpuChannelHostFactory::CanUseForTesting() {
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return GpuDataManager::GetInstance()->GpuAccessAllowed(NULL);
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!instance_);
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  instance_ = new BrowserGpuChannelHostFactory(establish_gpu_channel);
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void BrowserGpuChannelHostFactory::Terminate() {
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(instance_);
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delete instance_;
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  instance_ = NULL;
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory(
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool establish_gpu_channel)
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      shutdown_event_(new base::WaitableEvent(true, false)),
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gpu_host_id_(0) {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (establish_gpu_channel) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_request_ = new EstablishRequest(
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP, gpu_client_id_, gpu_host_id_);
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsMainThread());
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pending_request_)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_request_->Cancel();
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t n = 0; n < established_callbacks_.size(); n++)
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    established_callbacks_[n].Run();
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  shutdown_event_->Signal();
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool BrowserGpuChannelHostFactory::IsMainThread() {
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return BrowserThread::CurrentlyOn(BrowserThread::UI);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::MessageLoop* BrowserGpuChannelHostFactory::GetMainLoop() {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::UI);
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<base::MessageLoopProxy>
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserGpuChannelHostFactory::GetIOLoopProxy() {
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::SharedMemory>
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BrowserGpuChannelHostFactory::AllocateSharedMemory(size_t size) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!shm->CreateAnonymous(size))
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return scoped_ptr<base::SharedMemory>();
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return shm.Pass();
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO(
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateRequest* request,
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int32 surface_id,
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GPUCreateCommandBufferConfig& init_params) {
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!host) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->event.Signal();
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::GLSurfaceHandle surface =
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GpuSurfaceTracker::Get()->GetSurfaceHandle(surface_id);
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->CreateViewCommandBuffer(
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      surface,
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      surface_id,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gpu_client_id_,
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      init_params,
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->route_id,
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO,
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 request));
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO(
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CreateRequest* request, bool succeeded) {
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request->succeeded = succeeded;
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request->event.Signal();
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      int32 surface_id,
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const GPUCreateCommandBufferConfig& init_params,
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      int32 route_id) {
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateRequest request;
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request.route_id = route_id;
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO,
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Unretained(this),
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        &request,
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        surface_id,
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        init_params));
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We're blocking the UI thread, which is generally undesirable.
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // In this case we need to wait for this before we can show any UI /anyway/,
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // so it won't cause additional jank.
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(piman): Make this asynchronous (http://crbug.com/125248).
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TRACE_EVENT0("browser",
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               "BrowserGpuChannelHostFactory::CreateViewCommandBuffer");
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowWait allow_wait;
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request.event.Wait();
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return request.succeeded;
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserGpuChannelHostFactory::CreateImageOnIO(
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::PluginWindowHandle window,
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int32 image_id,
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CreateImageCallback& callback) {
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!host) {
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ImageCreatedOnIO(callback, gfx::Size());
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->CreateImage(
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window,
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gpu_client_id_,
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      image_id,
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&BrowserGpuChannelHostFactory::ImageCreatedOnIO, callback));
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::ImageCreatedOnIO(
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CreateImageCallback& callback, const gfx::Size size) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI,
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&BrowserGpuChannelHostFactory::OnImageCreated,
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 callback, size));
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::OnImageCreated(
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CreateImageCallback& callback, const gfx::Size size) {
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(size);
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::CreateImage(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::PluginWindowHandle window,
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int32 image_id,
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CreateImageCallback& callback) {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &BrowserGpuChannelHostFactory::CreateImageOnIO,
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Unretained(this),
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        window,
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        image_id,
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback));
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::DeleteImageOnIO(
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int32 image_id, int32 sync_point) {
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!host) {
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host->DeleteImage(gpu_client_id_, image_id, sync_point);
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::DeleteImage(
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int32 image_id, int32 sync_point) {
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &BrowserGpuChannelHostFactory::DeleteImageOnIO,
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Unretained(this),
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        image_id,
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sync_point));
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CauseForGpuLaunch cause_for_gpu_launch) {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pending_request_)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_request_->Wait();
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return gpu_channel_.get();
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserGpuChannelHostFactory::EstablishGpuChannel(
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CauseForGpuLaunch cause_for_gpu_launch,
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Closure& callback) {
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (gpu_channel_.get() && gpu_channel_->IsLost()) {
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!pending_request_);
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Recreate the channel if it has been lost.
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu_channel_ = NULL;
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
336  if (!gpu_channel_ && !pending_request_) {
337    // We should only get here if the context was lost.
338    pending_request_ = new EstablishRequest(
339        cause_for_gpu_launch, gpu_client_id_, gpu_host_id_);
340  }
341
342  if (!callback.is_null()) {
343    if (gpu_channel_)
344      callback.Run();
345    else
346      established_callbacks_.push_back(callback);
347  }
348}
349
350GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
351  if (gpu_channel_ && !gpu_channel_->IsLost())
352    return gpu_channel_;
353
354  return NULL;
355}
356
357void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
358  DCHECK(IsMainThread());
359  DCHECK(pending_request_);
360  if (pending_request_->channel_handle().name.empty())
361    return;
362
363  GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
364  gpu_channel_ = GpuChannelHost::Create(this,
365                                        pending_request_->gpu_info(),
366                                        pending_request_->channel_handle(),
367                                        shutdown_event_.get());
368  gpu_host_id_ = pending_request_->gpu_host_id();
369  pending_request_ = NULL;
370
371  for (size_t n = 0; n < established_callbacks_.size(); n++)
372    established_callbacks_[n].Run();
373
374  established_callbacks_.clear();
375}
376
377scoped_ptr<gfx::GpuMemoryBuffer>
378    BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(
379        size_t width,
380        size_t height,
381        unsigned internalformat) {
382  if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
383    return scoped_ptr<gfx::GpuMemoryBuffer>();
384
385  size_t size = width * height *
386      GpuMemoryBufferImpl::BytesPerPixel(internalformat);
387  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
388  if (!shm->CreateAnonymous(size))
389    return scoped_ptr<gfx::GpuMemoryBuffer>();
390
391  scoped_ptr<GpuMemoryBufferImplShm> buffer(
392      new GpuMemoryBufferImplShm(gfx::Size(width, height), internalformat));
393  if (!buffer->InitializeFromSharedMemory(shm.Pass()))
394    return scoped_ptr<gfx::GpuMemoryBuffer>();
395
396  return buffer.PassAs<gfx::GpuMemoryBuffer>();
397}
398
399// static
400void BrowserGpuChannelHostFactory::AddFilterOnIO(
401    int host_id,
402    scoped_refptr<IPC::ChannelProxy::MessageFilter> filter) {
403  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
404
405  GpuProcessHost* host = GpuProcessHost::FromID(host_id);
406  if (host)
407    host->AddFilter(filter.get());
408}
409
410void BrowserGpuChannelHostFactory::SetHandlerForControlMessages(
411      const uint32* message_ids,
412      size_t num_messages,
413      const base::Callback<void(const IPC::Message&)>& handler,
414      base::TaskRunner* target_task_runner) {
415  DCHECK(gpu_host_id_)
416      << "Do not call"
417      << " BrowserGpuChannelHostFactory::SetHandlerForControlMessages()"
418      << " until the GpuProcessHost has been set up.";
419
420  scoped_refptr<IPC::ForwardingMessageFilter> filter =
421      new IPC::ForwardingMessageFilter(message_ids,
422                                       num_messages,
423                                       target_task_runner);
424  filter->AddRoute(MSG_ROUTING_CONTROL, handler);
425
426  GetIOLoopProxy()->PostTask(
427      FROM_HERE,
428      base::Bind(&BrowserGpuChannelHostFactory::AddFilterOnIO,
429                 gpu_host_id_,
430                 filter));
431}
432
433}  // namespace content
434