Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: chrome/gpu/gpu_thread.cc

Issue 6684015: Move chrome\gpu to content\gpu. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/gpu/gpu_thread.h ('k') | chrome/gpu/gpu_video_decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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.
4
5 #include "chrome/gpu/gpu_thread.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "app/gfx/gl/gl_context.h"
11 #include "app/gfx/gl/gl_implementation.h"
12 #include "app/win/scoped_com_initializer.h"
13 #include "base/command_line.h"
14 #include "base/threading/worker_pool.h"
15 #include "build/build_config.h"
16 #include "chrome/gpu/gpu_info_collector.h"
17 #include "chrome/gpu/gpu_watchdog_thread.h"
18 #include "content/common/child_process.h"
19 #include "content/common/content_client.h"
20 #include "content/common/content_switches.h"
21 #include "content/common/gpu_messages.h"
22 #include "ipc/ipc_channel_handle.h"
23
24 #if defined(OS_MACOSX)
25 #include "content/common/sandbox_init_wrapper.h"
26 #include "content/common/sandbox_mac.h"
27 #elif defined(OS_WIN)
28 #include "sandbox/src/sandbox.h"
29 #endif
30
31 const int kGpuTimeout = 10000;
32
33 namespace {
34
35 bool InitializeGpuSandbox() {
36 #if defined(OS_MACOSX)
37 CommandLine* parsed_command_line = CommandLine::ForCurrentProcess();
38 SandboxInitWrapper sandbox_wrapper;
39 return sandbox_wrapper.InitializeSandbox(*parsed_command_line,
40 switches::kGpuProcess);
41 #else
42 // TODO(port): Create GPU sandbox for linux.
43 return true;
44 #endif
45 }
46
47 } // namespace
48
49 #if defined(OS_WIN)
50 GpuThread::GpuThread(sandbox::TargetServices* target_services)
51 : target_services_(target_services) {
52 }
53 #else
54 GpuThread::GpuThread() {
55 }
56 #endif
57
58 GpuThread::GpuThread(const std::string& channel_id)
59 : ChildThread(channel_id) {
60 #if defined(OS_WIN)
61 target_services_ = NULL;
62 #endif
63 }
64
65
66 GpuThread::~GpuThread() {
67 logging::SetLogMessageHandler(NULL);
68 }
69
70 void GpuThread::Init(const base::Time& process_start_time) {
71 process_start_time_ = process_start_time;
72 }
73
74 void GpuThread::RemoveChannel(int renderer_id) {
75 gpu_channels_.erase(renderer_id);
76 }
77
78 bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
79 bool msg_is_ok = true;
80 bool handled = true;
81 IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
82 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
83 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
84 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
85 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
86 OnCreateViewCommandBuffer);
87 IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize)
88 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
89 #if defined(OS_MACOSX)
90 IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK,
91 OnAcceleratedSurfaceBuffersSwappedACK)
92 IPC_MESSAGE_HANDLER(GpuMsg_DidDestroyAcceleratedSurface,
93 OnDidDestroyAcceleratedSurface)
94 #endif
95 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
96 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
97 IPC_MESSAGE_UNHANDLED(handled = false)
98 IPC_END_MESSAGE_MAP_EX()
99 return handled;
100 }
101
102 namespace {
103
104 bool GpuProcessLogMessageHandler(int severity,
105 const char* file, int line,
106 size_t message_start,
107 const std::string& str) {
108 std::string header = str.substr(0, message_start);
109 std::string message = str.substr(message_start);
110 ChildThread::current()->Send(
111 new GpuHostMsg_OnLogMessage(severity, header, message));
112 return false;
113 }
114
115 } // namespace
116
117 void GpuThread::OnInitialize() {
118 // Redirect LOG messages to the GpuProcessHost
119 bool single_process = CommandLine::ForCurrentProcess()->HasSwitch(
120 switches::kSingleProcess);
121 if (!single_process)
122 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
123
124 // Load the GL implementation and locate the bindings before starting the GPU
125 // watchdog because this can take a lot of time and the GPU watchdog might
126 // terminate the GPU process.
127 if (!gfx::GLContext::InitializeOneOff()) {
128 LOG(INFO) << "GLContext::InitializeOneOff failed";
129 MessageLoop::current()->Quit();
130 return;
131 }
132 bool gpu_info_result = gpu_info_collector::CollectGraphicsInfo(&gpu_info_);
133 if (!gpu_info_result) {
134 gpu_info_.collection_error = true;
135 LOG(ERROR) << "gpu_info_collector::CollectGraphicsInfo() failed";
136 }
137
138 content::GetContentClient()->SetGpuInfo(gpu_info_);
139 LOG(INFO) << "gpu_info_collector::CollectGraphicsInfo complete";
140
141 // Record initialization only after collecting the GPU info because that can
142 // take a significant amount of time.
143 gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
144
145 #if defined (OS_MACOSX)
146 // Note that kNoSandbox will also disable the GPU sandbox.
147 bool no_gpu_sandbox = CommandLine::ForCurrentProcess()->HasSwitch(
148 switches::kNoGpuSandbox);
149 if (!no_gpu_sandbox) {
150 if (!InitializeGpuSandbox()) {
151 LOG(ERROR) << "Failed to initialize the GPU sandbox";
152 MessageLoop::current()->Quit();
153 return;
154 }
155 } else {
156 LOG(ERROR) << "Running without GPU sandbox";
157 }
158 #elif defined(OS_WIN)
159 // For windows, if the target_services interface is not zero, the process
160 // is sandboxed and we must call LowerToken() before rendering untrusted
161 // content.
162 if (target_services_)
163 target_services_->LowerToken();
164 #endif
165
166 // In addition to disabling the watchdog if the command line switch is
167 // present, disable it in two other cases. OSMesa is expected to run very
168 // slowly. Also disable the watchdog on valgrind because the code is expected
169 // to run slowly in that case.
170 bool enable_watchdog =
171 !CommandLine::ForCurrentProcess()->HasSwitch(
172 switches::kDisableGpuWatchdog) &&
173 gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL &&
174 !RunningOnValgrind();
175
176 // Disable the watchdog in debug builds because they tend to only be run by
177 // developers who will not appreciate the watchdog killing the GPU process.
178 #ifndef NDEBUG
179 enable_watchdog = false;
180 #endif
181
182 // Disable the watchdog for Windows. It tends to abort when the GPU process
183 // is not hung but still taking a long time to do something. Instead, the
184 // browser process displays a dialog when it notices that the child window
185 // is hung giving the user an opportunity to terminate it. This is the
186 // same mechanism used to abort hung plugins.
187 #if defined(OS_WIN)
188 enable_watchdog = false;
189 #endif
190
191 // Start the GPU watchdog only after anything that is expected to be time
192 // consuming has completed, otherwise the process is liable to be aborted.
193 if (enable_watchdog) {
194 watchdog_thread_ = new GpuWatchdogThread(kGpuTimeout);
195 watchdog_thread_->Start();
196 }
197 }
198
199 void GpuThread::StopWatchdog() {
200 if (watchdog_thread_.get()) {
201 watchdog_thread_->Stop();
202 }
203 }
204
205 void GpuThread::OnEstablishChannel(int renderer_id) {
206 scoped_refptr<GpuChannel> channel;
207 IPC::ChannelHandle channel_handle;
208 GPUInfo gpu_info;
209
210 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
211 if (iter == gpu_channels_.end())
212 channel = new GpuChannel(this, renderer_id);
213 else
214 channel = iter->second;
215
216 DCHECK(channel != NULL);
217
218 if (channel->Init())
219 gpu_channels_[renderer_id] = channel;
220 else
221 channel = NULL;
222
223 if (channel.get()) {
224 channel_handle.name = channel->GetChannelName();
225 #if defined(OS_POSIX)
226 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
227 // that it gets closed after it has been sent.
228 int renderer_fd = channel->GetRendererFileDescriptor();
229 channel_handle.socket = base::FileDescriptor(renderer_fd, false);
230 #endif
231 }
232
233 Send(new GpuHostMsg_ChannelEstablished(channel_handle, gpu_info_));
234 }
235
236 void GpuThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) {
237 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
238 iter != gpu_channels_.end(); ++iter) {
239 if (iter->second->GetChannelName() == channel_handle.name) {
240 gpu_channels_.erase(iter);
241 return;
242 }
243 }
244 }
245
246 void GpuThread::OnSynchronize() {
247 Send(new GpuHostMsg_SynchronizeReply());
248 }
249
250 void GpuThread::OnCollectGraphicsInfo(GPUInfo::Level level) {
251 #if defined(OS_WIN)
252 if (level == GPUInfo::kComplete && gpu_info_.level <= GPUInfo::kPartial) {
253 // Prevent concurrent collection of DirectX diagnostics.
254 gpu_info_.level = GPUInfo::kCompleting;
255
256 // Asynchronously collect the DirectX diagnostics because this can take a
257 // couple of seconds.
258 if (!base::WorkerPool::PostTask(
259 FROM_HERE,
260 NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this),
261 true)) {
262
263 // Flag GPU info as complete if the DirectX diagnostics cannot be
264 // collected.
265 gpu_info_.level = GPUInfo::kComplete;
266 } else {
267 // Do not send response if we are still completing the GPUInfo struct
268 return;
269 }
270 }
271 #endif
272 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
273 }
274
275 void GpuThread::OnCreateViewCommandBuffer(
276 gfx::PluginWindowHandle window,
277 int32 render_view_id,
278 int32 renderer_id,
279 const GPUCreateCommandBufferConfig& init_params) {
280 int32 route_id = MSG_ROUTING_NONE;
281
282 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
283 if (iter != gpu_channels_.end()) {
284 iter->second->CreateViewCommandBuffer(
285 window, render_view_id, init_params, &route_id);
286 }
287
288 Send(new GpuHostMsg_CommandBufferCreated(route_id));
289 }
290
291 #if defined(OS_MACOSX)
292 void GpuThread::OnAcceleratedSurfaceBuffersSwappedACK(
293 int renderer_id, int32 route_id, uint64 swap_buffers_count) {
294 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
295 if (iter == gpu_channels_.end())
296 return;
297 scoped_refptr<GpuChannel> channel = iter->second;
298 channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count);
299 }
300 void GpuThread::OnDidDestroyAcceleratedSurface(
301 int renderer_id, int32 renderer_route_id) {
302 GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
303 if (iter == gpu_channels_.end())
304 return;
305 scoped_refptr<GpuChannel> channel = iter->second;
306 channel->DidDestroySurface(renderer_route_id);
307 }
308 #endif
309
310 void GpuThread::OnCrash() {
311 LOG(INFO) << "GPU: Simulating GPU crash";
312 // Good bye, cruel world.
313 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
314 *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
315 }
316
317 void GpuThread::OnHang() {
318 LOG(INFO) << "GPU: Simulating GPU hang";
319 for (;;) {
320 // Do not sleep here. The GPU watchdog timer tracks the amount of user
321 // time this thread is using and it doesn't use much while calling Sleep.
322 }
323 }
324
325 #if defined(OS_WIN)
326
327 // Runs on a worker thread. The GpuThread never terminates voluntarily so it is
328 // safe to assume that its message loop is valid.
329 void GpuThread::CollectDxDiagnostics(GpuThread* thread) {
330 app::win::ScopedCOMInitializer com_initializer;
331
332 DxDiagNode node;
333 gpu_info_collector::GetDxDiagnostics(&node);
334
335 thread->message_loop()->PostTask(
336 FROM_HERE,
337 NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node));
338 }
339
340 // Runs on the GPU thread.
341 void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) {
342 thread->gpu_info_.dx_diagnostics = node;
343 thread->gpu_info_.level = GPUInfo::kComplete;
344 thread->Send(new GpuHostMsg_GraphicsInfoCollected(thread->gpu_info_));
345 }
346
347 #endif
OLDNEW
« no previous file with comments | « chrome/gpu/gpu_thread.h ('k') | chrome/gpu/gpu_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698