| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/gpu_process_host_ui_shim.h" | 5 #include "chrome/browser/gpu_process_host_ui_shim.h" |
| 6 | 6 |
| 7 #include "app/app_switches.h" | 7 #include "app/app_switches.h" |
| 8 #include "app/gfx/gl/gl_implementation.h" | 8 #include "app/gfx/gl/gl_implementation.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/id_map.h" | 10 #include "base/id_map.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 | 101 |
| 102 RenderWidgetHostView* view = NULL; | 102 RenderWidgetHostView* view = NULL; |
| 103 if (host) | 103 if (host) |
| 104 view = host->view(); | 104 view = host->view(); |
| 105 | 105 |
| 106 return view; | 106 return view; |
| 107 } | 107 } |
| 108 | 108 |
| 109 GpuProcessHostUIShim::GpuProcessHostUIShim() | 109 GpuProcessHostUIShim::GpuProcessHostUIShim() |
| 110 : host_id_(++g_last_host_id), | 110 : host_id_(++g_last_host_id), |
| 111 gpu_process_(NULL), |
| 111 gpu_feature_flags_set_(false) { | 112 gpu_feature_flags_set_(false) { |
| 112 g_hosts_by_id.AddWithID(this, host_id_); | 113 g_hosts_by_id.AddWithID(this, host_id_); |
| 113 } | 114 } |
| 114 | 115 |
| 115 // static | 116 // static |
| 116 GpuProcessHostUIShim* GpuProcessHostUIShim::GetForRenderer(int renderer_id) { | 117 GpuProcessHostUIShim* GpuProcessHostUIShim::GetForRenderer(int renderer_id) { |
| 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 118 | 119 |
| 119 // The current policy is to ignore the renderer ID and use a single GPU | 120 // The current policy is to ignore the renderer ID and use a single GPU |
| 120 // process for all renderers. Later this will be extended to allow the | 121 // process for all renderers. Later this will be extended to allow the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 140 return ui_shim; | 141 return ui_shim; |
| 141 } | 142 } |
| 142 | 143 |
| 143 // static | 144 // static |
| 144 void GpuProcessHostUIShim::Destroy(int host_id) { | 145 void GpuProcessHostUIShim::Destroy(int host_id) { |
| 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 146 delete FromID(host_id); | 147 delete FromID(host_id); |
| 147 } | 148 } |
| 148 | 149 |
| 149 // static | 150 // static |
| 151 void GpuProcessHostUIShim::NotifyGpuProcessLaunched( |
| 152 int host_id, |
| 153 base::ProcessHandle gpu_process) { |
| 154 DCHECK(gpu_process); |
| 155 |
| 156 GpuProcessHostUIShim* ui_shim = FromID(host_id); |
| 157 DCHECK(ui_shim); |
| 158 |
| 159 ui_shim->gpu_process_ = gpu_process; |
| 160 } |
| 161 |
| 162 // static |
| 150 GpuProcessHostUIShim* GpuProcessHostUIShim::FromID(int host_id) { | 163 GpuProcessHostUIShim* GpuProcessHostUIShim::FromID(int host_id) { |
| 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 152 if (host_id == 0) | 165 if (host_id == 0) |
| 153 return NULL; | 166 return NULL; |
| 154 | 167 |
| 155 return g_hosts_by_id.Lookup(host_id); | 168 return g_hosts_by_id.Lookup(host_id); |
| 156 } | 169 } |
| 157 | 170 |
| 158 bool GpuProcessHostUIShim::Send(IPC::Message* msg) { | 171 bool GpuProcessHostUIShim::Send(IPC::Message* msg) { |
| 159 DCHECK(CalledOnValidThread()); | 172 DCHECK(CalledOnValidThread()); |
| 160 | 173 |
| 161 BrowserThread::PostTask(BrowserThread::IO, | 174 BrowserThread::PostTask(BrowserThread::IO, |
| 162 FROM_HERE, | 175 FROM_HERE, |
| 163 new SendOnIOThreadTask(host_id_, msg)); | 176 new SendOnIOThreadTask(host_id_, msg)); |
| 164 return true; | 177 return true; |
| 165 } | 178 } |
| 166 | 179 |
| 167 // Post a Task to execute callbacks on a error conditions in order to | 180 // Post a Task to execute callbacks on a error conditions in order to |
| 168 // clear the call stacks (and aid debugging). | 181 // clear the call stacks (and aid debugging). |
| 169 namespace { | 182 namespace { |
| 170 | 183 |
| 171 void EstablishChannelCallbackDispatcher( | 184 void EstablishChannelCallbackDispatcher( |
| 172 GpuProcessHostUIShim::EstablishChannelCallback* callback, | 185 GpuProcessHostUIShim::EstablishChannelCallback* callback, |
| 173 const IPC::ChannelHandle& channel_handle, | 186 const IPC::ChannelHandle& channel_handle, |
| 187 base::ProcessHandle gpu_renderer_process, |
| 174 const GPUInfo& gpu_info) { | 188 const GPUInfo& gpu_info) { |
| 175 scoped_ptr<GpuProcessHostUIShim::EstablishChannelCallback> | 189 scoped_ptr<GpuProcessHostUIShim::EstablishChannelCallback> |
| 176 wrapped_callback(callback); | 190 wrapped_callback(callback); |
| 177 wrapped_callback->Run(channel_handle, gpu_info); | 191 wrapped_callback->Run(channel_handle, gpu_renderer_process, gpu_info); |
| 178 } | 192 } |
| 179 | 193 |
| 180 void EstablishChannelError( | 194 void EstablishChannelError( |
| 181 GpuProcessHostUIShim::EstablishChannelCallback* callback, | 195 GpuProcessHostUIShim::EstablishChannelCallback* callback, |
| 182 const IPC::ChannelHandle& channel_handle, | 196 const IPC::ChannelHandle& channel_handle, |
| 197 base::ProcessHandle gpu_renderer_process, |
| 183 const GPUInfo& gpu_info) { | 198 const GPUInfo& gpu_info) { |
| 184 BrowserThread::PostTask( | 199 BrowserThread::PostTask( |
| 185 BrowserThread::UI, FROM_HERE, | 200 BrowserThread::UI, FROM_HERE, |
| 186 NewRunnableFunction(&EstablishChannelCallbackDispatcher, | 201 NewRunnableFunction(&EstablishChannelCallbackDispatcher, |
| 187 callback, channel_handle, gpu_info)); | 202 callback, |
| 203 channel_handle, |
| 204 gpu_renderer_process, |
| 205 gpu_info)); |
| 188 } | 206 } |
| 189 | 207 |
| 190 void SynchronizeCallbackDispatcher( | 208 void SynchronizeCallbackDispatcher( |
| 191 GpuProcessHostUIShim::SynchronizeCallback* callback) { | 209 GpuProcessHostUIShim::SynchronizeCallback* callback) { |
| 192 scoped_ptr<GpuProcessHostUIShim::SynchronizeCallback> | 210 scoped_ptr<GpuProcessHostUIShim::SynchronizeCallback> |
| 193 wrapped_callback(callback); | 211 wrapped_callback(callback); |
| 194 wrapped_callback->Run(); | 212 wrapped_callback->Run(); |
| 195 } | 213 } |
| 196 | 214 |
| 197 void SynchronizeError( | 215 void SynchronizeError( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 218 callback, route_id)); | 236 callback, route_id)); |
| 219 } | 237 } |
| 220 | 238 |
| 221 } // namespace | 239 } // namespace |
| 222 | 240 |
| 223 void GpuProcessHostUIShim::SendOutstandingReplies() { | 241 void GpuProcessHostUIShim::SendOutstandingReplies() { |
| 224 // First send empty channel handles for all EstablishChannel requests. | 242 // First send empty channel handles for all EstablishChannel requests. |
| 225 while (!channel_requests_.empty()) { | 243 while (!channel_requests_.empty()) { |
| 226 linked_ptr<EstablishChannelCallback> callback = channel_requests_.front(); | 244 linked_ptr<EstablishChannelCallback> callback = channel_requests_.front(); |
| 227 channel_requests_.pop(); | 245 channel_requests_.pop(); |
| 228 EstablishChannelError(callback.release(), IPC::ChannelHandle(), GPUInfo()); | 246 EstablishChannelError(callback.release(), |
| 247 IPC::ChannelHandle(), |
| 248 NULL, |
| 249 GPUInfo()); |
| 229 } | 250 } |
| 230 | 251 |
| 231 // Now unblock all renderers waiting for synchronization replies. | 252 // Now unblock all renderers waiting for synchronization replies. |
| 232 while (!synchronize_requests_.empty()) { | 253 while (!synchronize_requests_.empty()) { |
| 233 linked_ptr<SynchronizeCallback> callback = synchronize_requests_.front(); | 254 linked_ptr<SynchronizeCallback> callback = synchronize_requests_.front(); |
| 234 synchronize_requests_.pop(); | 255 synchronize_requests_.pop(); |
| 235 SynchronizeError(callback.release()); | 256 SynchronizeError(callback.release()); |
| 236 } | 257 } |
| 237 } | 258 } |
| 238 | 259 |
| 239 bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { | 260 bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { |
| 240 DCHECK(CalledOnValidThread()); | 261 DCHECK(CalledOnValidThread()); |
| 241 | 262 |
| 242 if (message.routing_id() != MSG_ROUTING_CONTROL) | 263 if (message.routing_id() != MSG_ROUTING_CONTROL) |
| 243 return false; | 264 return false; |
| 244 | 265 |
| 245 return OnControlMessageReceived(message); | 266 return OnControlMessageReceived(message); |
| 246 } | 267 } |
| 247 | 268 |
| 248 void GpuProcessHostUIShim::EstablishGpuChannel( | 269 void GpuProcessHostUIShim::EstablishGpuChannel( |
| 249 int renderer_id, EstablishChannelCallback *callback) { | 270 int renderer_id, |
| 271 EstablishChannelCallback *callback) { |
| 250 DCHECK(CalledOnValidThread()); | 272 DCHECK(CalledOnValidThread()); |
| 251 linked_ptr<EstablishChannelCallback> wrapped_callback(callback); | 273 linked_ptr<EstablishChannelCallback> wrapped_callback(callback); |
| 252 | 274 |
| 253 // If GPU features are already blacklisted, no need to establish the channel. | 275 // If GPU features are already blacklisted, no need to establish the channel. |
| 254 if (gpu_feature_flags_.flags() != 0) { | 276 if (gpu_feature_flags_.flags() != 0) { |
| 255 EstablishChannelError( | 277 EstablishChannelError( |
| 256 wrapped_callback.release(), IPC::ChannelHandle(), GPUInfo()); | 278 wrapped_callback.release(), IPC::ChannelHandle(), NULL, GPUInfo()); |
| 257 return; | 279 return; |
| 258 } | 280 } |
| 259 | 281 |
| 260 if (Send(new GpuMsg_EstablishChannel(renderer_id))) { | 282 if (Send(new GpuMsg_EstablishChannel(renderer_id))) { |
| 261 channel_requests_.push(wrapped_callback); | 283 channel_requests_.push(wrapped_callback); |
| 262 } else { | 284 } else { |
| 263 EstablishChannelError( | 285 EstablishChannelError( |
| 264 wrapped_callback.release(), IPC::ChannelHandle(), GPUInfo()); | 286 wrapped_callback.release(), IPC::ChannelHandle(), NULL, GPUInfo()); |
| 265 } | 287 } |
| 266 } | 288 } |
| 267 | 289 |
| 268 void GpuProcessHostUIShim::Synchronize(SynchronizeCallback* callback) { | 290 void GpuProcessHostUIShim::Synchronize(SynchronizeCallback* callback) { |
| 269 DCHECK(CalledOnValidThread()); | 291 DCHECK(CalledOnValidThread()); |
| 270 linked_ptr<SynchronizeCallback> wrapped_callback(callback); | 292 linked_ptr<SynchronizeCallback> wrapped_callback(callback); |
| 271 | 293 |
| 272 if (Send(new GpuMsg_Synchronize())) { | 294 if (Send(new GpuMsg_Synchronize())) { |
| 273 synchronize_requests_.push(wrapped_callback); | 295 synchronize_requests_.push(wrapped_callback); |
| 274 } else { | 296 } else { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 } | 355 } |
| 334 | 356 |
| 335 const GPUInfo& GpuProcessHostUIShim::gpu_info() const { | 357 const GPUInfo& GpuProcessHostUIShim::gpu_info() const { |
| 336 DCHECK(CalledOnValidThread()); | 358 DCHECK(CalledOnValidThread()); |
| 337 return gpu_info_; | 359 return gpu_info_; |
| 338 } | 360 } |
| 339 | 361 |
| 340 GpuProcessHostUIShim::~GpuProcessHostUIShim() { | 362 GpuProcessHostUIShim::~GpuProcessHostUIShim() { |
| 341 DCHECK(CalledOnValidThread()); | 363 DCHECK(CalledOnValidThread()); |
| 342 g_hosts_by_id.Remove(host_id_); | 364 g_hosts_by_id.Remove(host_id_); |
| 365 |
| 366 #if defined(OS_WIN) |
| 367 if (gpu_process_) |
| 368 CloseHandle(gpu_process_); |
| 369 #endif |
| 343 } | 370 } |
| 344 | 371 |
| 345 bool GpuProcessHostUIShim::Init() { | 372 bool GpuProcessHostUIShim::Init() { |
| 346 return LoadGpuBlacklist(); | 373 return LoadGpuBlacklist(); |
| 347 } | 374 } |
| 348 | 375 |
| 349 void GpuProcessHostUIShim::AddCustomLogMessage(int level, | 376 void GpuProcessHostUIShim::AddCustomLogMessage(int level, |
| 350 const std::string& header, | 377 const std::string& header, |
| 351 const std::string& message) { | 378 const std::string& message) { |
| 352 OnLogMessage(level, header, message); | 379 OnLogMessage(level, header, message); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 383 #endif | 410 #endif |
| 384 IPC_MESSAGE_UNHANDLED_ERROR() | 411 IPC_MESSAGE_UNHANDLED_ERROR() |
| 385 IPC_END_MESSAGE_MAP() | 412 IPC_END_MESSAGE_MAP() |
| 386 | 413 |
| 387 return true; | 414 return true; |
| 388 } | 415 } |
| 389 | 416 |
| 390 void GpuProcessHostUIShim::OnChannelEstablished( | 417 void GpuProcessHostUIShim::OnChannelEstablished( |
| 391 const IPC::ChannelHandle& channel_handle, | 418 const IPC::ChannelHandle& channel_handle, |
| 392 const GPUInfo& gpu_info) { | 419 const GPUInfo& gpu_info) { |
| 420 // The GPU process should have launched at this point and this object should |
| 421 // have been notified of its process handle. |
| 422 DCHECK(gpu_process_); |
| 423 |
| 393 uint32 max_entry_id = gpu_blacklist_->max_entry_id(); | 424 uint32 max_entry_id = gpu_blacklist_->max_entry_id(); |
| 394 // max_entry_id can be zero if we failed to load the GPU blacklist, don't | 425 // max_entry_id can be zero if we failed to load the GPU blacklist, don't |
| 395 // bother with histograms then. | 426 // bother with histograms then. |
| 396 if (channel_handle.name.size() != 0 && !gpu_feature_flags_set_ && | 427 if (channel_handle.name.size() != 0 && !gpu_feature_flags_set_ && |
| 397 max_entry_id != 0) | 428 max_entry_id != 0) |
| 398 { | 429 { |
| 399 gpu_feature_flags_set_ = true; | 430 gpu_feature_flags_set_ = true; |
| 400 | 431 |
| 401 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | 432 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); |
| 402 if (!browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && | 433 if (!browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && |
| (...skipping 19 matching lines...) Expand all Loading... |
| 422 } | 453 } |
| 423 } | 454 } |
| 424 } | 455 } |
| 425 linked_ptr<EstablishChannelCallback> callback = channel_requests_.front(); | 456 linked_ptr<EstablishChannelCallback> callback = channel_requests_.front(); |
| 426 channel_requests_.pop(); | 457 channel_requests_.pop(); |
| 427 | 458 |
| 428 // Currently if any of the GPU features are blacklisted, we don't establish a | 459 // Currently if any of the GPU features are blacklisted, we don't establish a |
| 429 // GPU channel. | 460 // GPU channel. |
| 430 if (gpu_feature_flags_.flags() != 0) { | 461 if (gpu_feature_flags_.flags() != 0) { |
| 431 Send(new GpuMsg_CloseChannel(channel_handle)); | 462 Send(new GpuMsg_CloseChannel(channel_handle)); |
| 432 EstablishChannelError(callback.release(), IPC::ChannelHandle(), gpu_info); | 463 EstablishChannelError(callback.release(), |
| 464 IPC::ChannelHandle(), |
| 465 NULL, |
| 466 gpu_info); |
| 433 AddCustomLogMessage(logging::LOG_WARNING, "WARNING", "GPU is blacklisted."); | 467 AddCustomLogMessage(logging::LOG_WARNING, "WARNING", "GPU is blacklisted."); |
| 434 } else { | 468 return; |
| 435 callback->Run(channel_handle, gpu_info); | |
| 436 } | 469 } |
| 470 |
| 471 callback->Run(channel_handle, gpu_process_, gpu_info); |
| 437 } | 472 } |
| 438 | 473 |
| 439 void GpuProcessHostUIShim::OnSynchronizeReply() { | 474 void GpuProcessHostUIShim::OnSynchronizeReply() { |
| 440 // Guard against race conditions in abrupt GPU process termination. | 475 // Guard against race conditions in abrupt GPU process termination. |
| 441 if (synchronize_requests_.size() > 0) { | 476 if (synchronize_requests_.size() > 0) { |
| 442 linked_ptr<SynchronizeCallback> callback(synchronize_requests_.front()); | 477 linked_ptr<SynchronizeCallback> callback(synchronize_requests_.front()); |
| 443 synchronize_requests_.pop(); | 478 synchronize_requests_.pop(); |
| 444 callback->Run(); | 479 callback->Run(); |
| 445 } | 480 } |
| 446 } | 481 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 static const base::StringPiece gpu_blacklist_json( | 624 static const base::StringPiece gpu_blacklist_json( |
| 590 ResourceBundle::GetSharedInstance().GetRawDataResource( | 625 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 591 IDR_GPU_BLACKLIST)); | 626 IDR_GPU_BLACKLIST)); |
| 592 gpu_blacklist_.reset(new GpuBlacklist()); | 627 gpu_blacklist_.reset(new GpuBlacklist()); |
| 593 if (gpu_blacklist_->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true)) | 628 if (gpu_blacklist_->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true)) |
| 594 return true; | 629 return true; |
| 595 gpu_blacklist_.reset(NULL); | 630 gpu_blacklist_.reset(NULL); |
| 596 return false; | 631 return false; |
| 597 } | 632 } |
| 598 | 633 |
| OLD | NEW |