Make touch-action apply to double-tap zoom
[chromium-blink-merge.git] / content / gpu / gpu_child_thread.cc
blob63f850fa7f288464eb8d730842b231f976e378af
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/gpu/gpu_child_thread.h"
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/worker_pool.h"
10 #include "build/build_config.h"
11 #include "content/child/child_process.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "content/gpu/gpu_watchdog_thread.h"
15 #include "content/public/common/content_client.h"
16 #include "content/public/common/content_switches.h"
17 #include "gpu/config/gpu_info_collector.h"
18 #include "ipc/ipc_channel_handle.h"
19 #include "ipc/ipc_sync_message_filter.h"
20 #include "ui/gl/gl_implementation.h"
22 namespace content {
23 namespace {
25 static base::LazyInstance<scoped_refptr<ThreadSafeSender> >
26 g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER;
28 bool GpuProcessLogMessageHandler(int severity,
29 const char* file, int line,
30 size_t message_start,
31 const std::string& str) {
32 std::string header = str.substr(0, message_start);
33 std::string message = str.substr(message_start);
35 g_thread_safe_sender.Get()->Send(new GpuHostMsg_OnLogMessage(
36 severity, header, message));
38 return false;
41 } // namespace
43 GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
44 bool dead_on_arrival,
45 const gpu::GPUInfo& gpu_info,
46 const DeferredMessages& deferred_messages)
47 : dead_on_arrival_(dead_on_arrival),
48 gpu_info_(gpu_info),
49 deferred_messages_(deferred_messages),
50 in_browser_process_(false) {
51 watchdog_thread_ = watchdog_thread;
52 #if defined(OS_WIN)
53 target_services_ = NULL;
54 #endif
55 g_thread_safe_sender.Get() = thread_safe_sender();
58 GpuChildThread::GpuChildThread(const std::string& channel_id)
59 : ChildThread(channel_id),
60 dead_on_arrival_(false),
61 in_browser_process_(true) {
62 #if defined(OS_WIN)
63 target_services_ = NULL;
64 #endif
65 DCHECK(
66 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
67 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU));
68 #if !defined(OS_ANDROID)
69 // For single process and in-process GPU mode, we need to load and
70 // initialize the GL implementation and locate the GL entry points here.
71 // On Android, GLSurface::InitializeOneOff() is called from BrowserMainLoop
72 // before getting here. crbug.com/326295
73 if (!gfx::GLSurface::InitializeOneOff())
74 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
75 #endif
76 g_thread_safe_sender.Get() = thread_safe_sender();
79 GpuChildThread::~GpuChildThread() {
82 void GpuChildThread::Shutdown() {
83 ChildThread::Shutdown();
84 logging::SetLogMessageHandler(NULL);
87 void GpuChildThread::Init(const base::Time& process_start_time) {
88 process_start_time_ = process_start_time;
91 bool GpuChildThread::Send(IPC::Message* msg) {
92 // The GPU process must never send a synchronous IPC message to the browser
93 // process. This could result in deadlock.
94 DCHECK(!msg->is_sync());
96 return ChildThread::Send(msg);
99 bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
100 bool msg_is_ok = true;
101 bool handled = true;
102 IPC_BEGIN_MESSAGE_MAP_EX(GpuChildThread, msg, msg_is_ok)
103 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
104 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
105 IPC_MESSAGE_HANDLER(GpuMsg_GetVideoMemoryUsageStats,
106 OnGetVideoMemoryUsageStats)
107 IPC_MESSAGE_HANDLER(GpuMsg_Clean, OnClean)
108 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
109 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
110 IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog)
111 IPC_MESSAGE_UNHANDLED(handled = false)
112 IPC_END_MESSAGE_MAP_EX()
114 if (handled)
115 return true;
117 return gpu_channel_manager_.get() &&
118 gpu_channel_manager_->OnMessageReceived(msg);
121 void GpuChildThread::OnInitialize() {
122 Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_));
123 while (!deferred_messages_.empty()) {
124 Send(deferred_messages_.front());
125 deferred_messages_.pop();
128 if (dead_on_arrival_) {
129 VLOG(1) << "Exiting GPU process due to errors during initialization";
130 base::MessageLoop::current()->Quit();
131 return;
134 #if defined(OS_ANDROID)
135 base::PlatformThread::SetThreadPriority(
136 base::PlatformThread::CurrentHandle(),
137 base::kThreadPriority_Display);
138 #endif
140 // We don't need to pipe log messages if we are running the GPU thread in
141 // the browser process.
142 if (!in_browser_process_)
143 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
145 // Record initialization only after collecting the GPU info because that can
146 // take a significant amount of time.
147 gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
149 // Defer creation of the render thread. This is to prevent it from handling
150 // IPC messages before the sandbox has been enabled and all other necessary
151 // initialization has succeeded.
152 gpu_channel_manager_.reset(
153 new GpuChannelManager(this,
154 watchdog_thread_.get(),
155 ChildProcess::current()->io_message_loop_proxy(),
156 ChildProcess::current()->GetShutDownEvent()));
158 // Ensure the browser process receives the GPU info before a reply to any
159 // subsequent IPC it might send.
160 if (!in_browser_process_)
161 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
164 void GpuChildThread::StopWatchdog() {
165 if (watchdog_thread_.get()) {
166 watchdog_thread_->Stop();
170 void GpuChildThread::OnCollectGraphicsInfo() {
171 #if defined(OS_WIN)
172 // GPU full info collection should only happen on un-sandboxed GPU process
173 // or single process/in-process gpu mode on Windows.
174 CommandLine* command_line = CommandLine::ForCurrentProcess();
175 DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) ||
176 in_browser_process_);
177 #endif // OS_WIN
179 if (!gpu::CollectContextGraphicsInfo(&gpu_info_))
180 VLOG(1) << "gpu::CollectGraphicsInfo failed";
181 GetContentClient()->SetGpuInfo(gpu_info_);
183 #if defined(OS_WIN)
184 // This is slow, but it's the only thing the unsandboxed GPU process does,
185 // and GpuDataManager prevents us from sending multiple collecting requests,
186 // so it's OK to be blocking.
187 gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics);
188 gpu_info_.finalized = true;
189 #endif // OS_WIN
191 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
193 #if defined(OS_WIN)
194 if (!in_browser_process_) {
195 // The unsandboxed GPU process fulfilled its duty. Rest in peace.
196 base::MessageLoop::current()->Quit();
198 #endif // OS_WIN
201 void GpuChildThread::OnGetVideoMemoryUsageStats() {
202 GPUVideoMemoryUsageStats video_memory_usage_stats;
203 if (gpu_channel_manager_)
204 gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
205 &video_memory_usage_stats);
206 Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
209 void GpuChildThread::OnClean() {
210 VLOG(1) << "GPU: Removing all contexts";
211 if (gpu_channel_manager_)
212 gpu_channel_manager_->LoseAllContexts();
215 void GpuChildThread::OnCrash() {
216 VLOG(1) << "GPU: Simulating GPU crash";
217 // Good bye, cruel world.
218 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
219 *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
222 void GpuChildThread::OnHang() {
223 VLOG(1) << "GPU: Simulating GPU hang";
224 for (;;) {
225 // Do not sleep here. The GPU watchdog timer tracks the amount of user
226 // time this thread is using and it doesn't use much while calling Sleep.
230 void GpuChildThread::OnDisableWatchdog() {
231 VLOG(1) << "GPU: Disabling watchdog thread";
232 if (watchdog_thread_.get()) {
233 // Disarm the watchdog before shutting down the message loop. This prevents
234 // the future posting of tasks to the message loop.
235 if (watchdog_thread_->message_loop())
236 watchdog_thread_->PostAcknowledge();
237 // Prevent rearming.
238 watchdog_thread_->Stop();
242 } // namespace content