| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #if defined(OS_WIN) | 5 #if defined(OS_WIN) |
| 6 #include <windows.h> | 6 #include <windows.h> |
| 7 #endif | 7 #endif |
| 8 | 8 |
| 9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
| 10 | 10 |
| 11 #include <queue> | 11 #include <queue> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/debug/trace_event.h" | 16 #include "base/debug/trace_event.h" |
| 17 #include "base/message_loop/message_loop_proxy.h" | 17 #include "base/message_loop/message_loop_proxy.h" |
| 18 #include "base/stl_util.h" |
| 18 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 19 #include "base/timer/timer.h" | 20 #include "base/timer/timer.h" |
| 20 #include "content/common/gpu/devtools_gpu_agent.h" | 21 #include "content/common/gpu/devtools_gpu_agent.h" |
| 21 #include "content/common/gpu/gpu_channel_manager.h" | 22 #include "content/common/gpu/gpu_channel_manager.h" |
| 22 #include "content/common/gpu/gpu_messages.h" | 23 #include "content/common/gpu/gpu_messages.h" |
| 23 #include "content/common/gpu/sync_point_manager.h" | 24 #include "content/common/gpu/sync_point_manager.h" |
| 24 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
| 25 #include "gpu/command_buffer/common/mailbox.h" | 26 #include "gpu/command_buffer/common/mailbox.h" |
| 26 #include "gpu/command_buffer/service/gpu_scheduler.h" | 27 #include "gpu/command_buffer/service/gpu_scheduler.h" |
| 27 #include "gpu/command_buffer/service/image_manager.h" | 28 #include "gpu/command_buffer/service/image_manager.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 // process. To guarantee fairness, we must wait a minimum amount of time | 65 // process. To guarantee fairness, we must wait a minimum amount of time |
| 65 // before preempting and we limit the amount of time that we can preempt in | 66 // before preempting and we limit the amount of time that we can preempt in |
| 66 // one shot (see constants above). | 67 // one shot (see constants above). |
| 67 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO | 68 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO |
| 68 // thread, generating the sync point ID and responding immediately, and then | 69 // thread, generating the sync point ID and responding immediately, and then |
| 69 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message | 70 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message |
| 70 // into the channel's queue. | 71 // into the channel's queue. |
| 71 // - it generates mailbox names for clients of the GPU process on the IO thread. | 72 // - it generates mailbox names for clients of the GPU process on the IO thread. |
| 72 class GpuChannelMessageFilter : public IPC::MessageFilter { | 73 class GpuChannelMessageFilter : public IPC::MessageFilter { |
| 73 public: | 74 public: |
| 74 // Takes ownership of gpu_channel (see below). | 75 GpuChannelMessageFilter(base::WeakPtr<GpuChannel> gpu_channel, |
| 75 GpuChannelMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, | |
| 76 scoped_refptr<SyncPointManager> sync_point_manager, | 76 scoped_refptr<SyncPointManager> sync_point_manager, |
| 77 scoped_refptr<base::MessageLoopProxy> message_loop) | 77 scoped_refptr<base::MessageLoopProxy> message_loop) |
| 78 : preemption_state_(IDLE), | 78 : preemption_state_(IDLE), |
| 79 gpu_channel_(gpu_channel), | 79 gpu_channel_(gpu_channel), |
| 80 channel_(NULL), | 80 channel_(NULL), |
| 81 sync_point_manager_(sync_point_manager), | 81 sync_point_manager_(sync_point_manager), |
| 82 message_loop_(message_loop), | 82 message_loop_(message_loop), |
| 83 messages_forwarded_to_channel_(0), | 83 messages_forwarded_to_channel_(0), |
| 84 a_stub_is_descheduled_(false) { | 84 a_stub_is_descheduled_(false) {} |
| 85 } | |
| 86 | 85 |
| 87 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { | 86 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { |
| 88 DCHECK(!channel_); | 87 DCHECK(!channel_); |
| 89 channel_ = channel; | 88 channel_ = channel; |
| 90 } | 89 } |
| 91 | 90 |
| 92 virtual void OnFilterRemoved() OVERRIDE { | 91 virtual void OnFilterRemoved() OVERRIDE { |
| 93 DCHECK(channel_); | 92 DCHECK(channel_); |
| 94 channel_ = NULL; | 93 channel_ = NULL; |
| 95 } | 94 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 void UpdateStubSchedulingState(bool a_stub_is_descheduled) { | 145 void UpdateStubSchedulingState(bool a_stub_is_descheduled) { |
| 147 a_stub_is_descheduled_ = a_stub_is_descheduled; | 146 a_stub_is_descheduled_ = a_stub_is_descheduled; |
| 148 UpdatePreemptionState(); | 147 UpdatePreemptionState(); |
| 149 } | 148 } |
| 150 | 149 |
| 151 bool Send(IPC::Message* message) { | 150 bool Send(IPC::Message* message) { |
| 152 return channel_->Send(message); | 151 return channel_->Send(message); |
| 153 } | 152 } |
| 154 | 153 |
| 155 protected: | 154 protected: |
| 156 virtual ~GpuChannelMessageFilter() { | 155 virtual ~GpuChannelMessageFilter() {} |
| 157 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 158 &GpuChannelMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); | |
| 159 } | |
| 160 | 156 |
| 161 private: | 157 private: |
| 162 enum PreemptionState { | 158 enum PreemptionState { |
| 163 // Either there's no other channel to preempt, there are no messages | 159 // Either there's no other channel to preempt, there are no messages |
| 164 // pending processing, or we just finished preempting and have to wait | 160 // pending processing, or we just finished preempting and have to wait |
| 165 // before preempting again. | 161 // before preempting again. |
| 166 IDLE, | 162 IDLE, |
| 167 // We are waiting kPreemptWaitTimeMs before checking if we should preempt. | 163 // We are waiting kPreemptWaitTimeMs before checking if we should preempt. |
| 168 WAITING, | 164 WAITING, |
| 169 // We can preempt whenever any IPC processing takes more than | 165 // We can preempt whenever any IPC processing takes more than |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 326 } |
| 331 | 327 |
| 332 preemption_state_ = WOULD_PREEMPT_DESCHEDULED; | 328 preemption_state_ = WOULD_PREEMPT_DESCHEDULED; |
| 333 preempting_flag_->Reset(); | 329 preempting_flag_->Reset(); |
| 334 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0); | 330 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0); |
| 335 | 331 |
| 336 UpdatePreemptionState(); | 332 UpdatePreemptionState(); |
| 337 } | 333 } |
| 338 | 334 |
| 339 static void InsertSyncPointOnMainThread( | 335 static void InsertSyncPointOnMainThread( |
| 340 base::WeakPtr<GpuChannel>* gpu_channel, | 336 base::WeakPtr<GpuChannel> gpu_channel, |
| 341 scoped_refptr<SyncPointManager> manager, | 337 scoped_refptr<SyncPointManager> manager, |
| 342 int32 routing_id, | 338 int32 routing_id, |
| 343 uint32 sync_point) { | 339 uint32 sync_point) { |
| 344 // This function must ensure that the sync point will be retired. Normally | 340 // This function must ensure that the sync point will be retired. Normally |
| 345 // we'll find the stub based on the routing ID, and associate the sync point | 341 // we'll find the stub based on the routing ID, and associate the sync point |
| 346 // with it, but if that fails for any reason (channel or stub already | 342 // with it, but if that fails for any reason (channel or stub already |
| 347 // deleted, invalid routing id), we need to retire the sync point | 343 // deleted, invalid routing id), we need to retire the sync point |
| 348 // immediately. | 344 // immediately. |
| 349 if (gpu_channel->get()) { | 345 if (gpu_channel) { |
| 350 GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( | 346 GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id); |
| 351 routing_id); | |
| 352 if (stub) { | 347 if (stub) { |
| 353 stub->AddSyncPoint(sync_point); | 348 stub->AddSyncPoint(sync_point); |
| 354 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); | 349 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); |
| 355 gpu_channel->get()->OnMessageReceived(message); | 350 gpu_channel->OnMessageReceived(message); |
| 356 return; | 351 return; |
| 357 } else { | 352 } else { |
| 358 gpu_channel->get()->MessageProcessed(); | 353 gpu_channel->MessageProcessed(); |
| 359 } | 354 } |
| 360 } | 355 } |
| 361 manager->RetireSyncPoint(sync_point); | 356 manager->RetireSyncPoint(sync_point); |
| 362 } | 357 } |
| 363 | 358 |
| 364 static void DeleteWeakPtrOnMainThread( | 359 // NOTE: this weak pointer is never dereferenced on the IO thread, it's only |
| 365 base::WeakPtr<GpuChannel>* gpu_channel) { | 360 // passed through - therefore the WeakPtr assumptions are respected. |
| 366 delete gpu_channel; | 361 base::WeakPtr<GpuChannel> gpu_channel_; |
| 367 } | |
| 368 | |
| 369 // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the | |
| 370 // IO thread, it's only passed through - therefore the WeakPtr assumptions are | |
| 371 // respected. | |
| 372 base::WeakPtr<GpuChannel>* gpu_channel_; | |
| 373 IPC::Channel* channel_; | 362 IPC::Channel* channel_; |
| 374 scoped_refptr<SyncPointManager> sync_point_manager_; | 363 scoped_refptr<SyncPointManager> sync_point_manager_; |
| 375 scoped_refptr<base::MessageLoopProxy> message_loop_; | 364 scoped_refptr<base::MessageLoopProxy> message_loop_; |
| 376 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; | 365 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; |
| 377 | 366 |
| 378 std::queue<PendingMessage> pending_messages_; | 367 std::queue<PendingMessage> pending_messages_; |
| 379 | 368 |
| 380 // Count of the number of IPCs forwarded to the GpuChannel. | 369 // Count of the number of IPCs forwarded to the GpuChannel. |
| 381 uint64 messages_forwarded_to_channel_; | 370 uint64 messages_forwarded_to_channel_; |
| 382 | 371 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 404 weak_factory_(this), | 393 weak_factory_(this), |
| 405 num_stubs_descheduled_(0) { | 394 num_stubs_descheduled_(0) { |
| 406 DCHECK(gpu_channel_manager); | 395 DCHECK(gpu_channel_manager); |
| 407 DCHECK(client_id); | 396 DCHECK(client_id); |
| 408 | 397 |
| 409 channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu"); | 398 channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu"); |
| 410 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 399 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 411 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | 400 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); |
| 412 } | 401 } |
| 413 | 402 |
| 403 GpuChannel::~GpuChannel() { |
| 404 STLDeleteElements(&deferred_messages_); |
| 405 if (preempting_flag_.get()) |
| 406 preempting_flag_->Reset(); |
| 407 } |
| 414 | 408 |
| 415 void GpuChannel::Init(base::MessageLoopProxy* io_message_loop, | 409 void GpuChannel::Init(base::MessageLoopProxy* io_message_loop, |
| 416 base::WaitableEvent* shutdown_event) { | 410 base::WaitableEvent* shutdown_event) { |
| 417 DCHECK(!channel_.get()); | 411 DCHECK(!channel_.get()); |
| 418 | 412 |
| 419 // Map renderer ID to a (single) channel to that process. | 413 // Map renderer ID to a (single) channel to that process. |
| 420 channel_.reset(new IPC::SyncChannel( | 414 channel_.reset(new IPC::SyncChannel( |
| 421 channel_id_, | 415 channel_id_, |
| 422 IPC::Channel::MODE_SERVER, | 416 IPC::Channel::MODE_SERVER, |
| 423 this, | 417 this, |
| 424 io_message_loop, | 418 io_message_loop, |
| 425 false, | 419 false, |
| 426 shutdown_event)); | 420 shutdown_event)); |
| 427 | 421 |
| 428 base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( | 422 filter_ = |
| 429 weak_factory_.GetWeakPtr())); | 423 new GpuChannelMessageFilter(weak_factory_.GetWeakPtr(), |
| 430 | 424 gpu_channel_manager_->sync_point_manager(), |
| 431 filter_ = new GpuChannelMessageFilter( | 425 base::MessageLoopProxy::current()); |
| 432 weak_ptr, | |
| 433 gpu_channel_manager_->sync_point_manager(), | |
| 434 base::MessageLoopProxy::current()); | |
| 435 io_message_loop_ = io_message_loop; | 426 io_message_loop_ = io_message_loop; |
| 436 channel_->AddFilter(filter_.get()); | 427 channel_->AddFilter(filter_.get()); |
| 437 | 428 |
| 438 devtools_gpu_agent_.reset(new DevToolsGpuAgent(this)); | 429 devtools_gpu_agent_.reset(new DevToolsGpuAgent(this)); |
| 439 } | 430 } |
| 440 | 431 |
| 441 std::string GpuChannel::GetChannelName() { | 432 std::string GpuChannel::GetChannelName() { |
| 442 return channel_id_; | 433 return channel_id_; |
| 443 } | 434 } |
| 444 | 435 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 gpu_channel_manager_->LoseAllContexts(); | 616 gpu_channel_manager_->LoseAllContexts(); |
| 626 } | 617 } |
| 627 | 618 |
| 628 void GpuChannel::MarkAllContextsLost() { | 619 void GpuChannel::MarkAllContextsLost() { |
| 629 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 620 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 630 !it.IsAtEnd(); it.Advance()) { | 621 !it.IsAtEnd(); it.Advance()) { |
| 631 it.GetCurrentValue()->MarkContextLost(); | 622 it.GetCurrentValue()->MarkContextLost(); |
| 632 } | 623 } |
| 633 } | 624 } |
| 634 | 625 |
| 635 void GpuChannel::DestroySoon() { | |
| 636 base::MessageLoop::current()->PostTask( | |
| 637 FROM_HERE, base::Bind(&GpuChannel::OnDestroy, this)); | |
| 638 } | |
| 639 | |
| 640 bool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { | 626 bool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { |
| 641 return router_.AddRoute(route_id, listener); | 627 return router_.AddRoute(route_id, listener); |
| 642 } | 628 } |
| 643 | 629 |
| 644 void GpuChannel::RemoveRoute(int32 route_id) { | 630 void GpuChannel::RemoveRoute(int32 route_id) { |
| 645 router_.RemoveRoute(route_id); | 631 router_.RemoveRoute(route_id); |
| 646 } | 632 } |
| 647 | 633 |
| 648 gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() { | 634 gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() { |
| 649 if (!preempting_flag_.get()) { | 635 if (!preempting_flag_.get()) { |
| 650 preempting_flag_ = new gpu::PreemptionFlag; | 636 preempting_flag_ = new gpu::PreemptionFlag; |
| 651 io_message_loop_->PostTask( | 637 io_message_loop_->PostTask( |
| 652 FROM_HERE, base::Bind( | 638 FROM_HERE, base::Bind( |
| 653 &GpuChannelMessageFilter::SetPreemptingFlagAndSchedulingState, | 639 &GpuChannelMessageFilter::SetPreemptingFlagAndSchedulingState, |
| 654 filter_, preempting_flag_, num_stubs_descheduled_ > 0)); | 640 filter_, preempting_flag_, num_stubs_descheduled_ > 0)); |
| 655 } | 641 } |
| 656 return preempting_flag_.get(); | 642 return preempting_flag_.get(); |
| 657 } | 643 } |
| 658 | 644 |
| 659 void GpuChannel::SetPreemptByFlag( | 645 void GpuChannel::SetPreemptByFlag( |
| 660 scoped_refptr<gpu::PreemptionFlag> preempted_flag) { | 646 scoped_refptr<gpu::PreemptionFlag> preempted_flag) { |
| 661 preempted_flag_ = preempted_flag; | 647 preempted_flag_ = preempted_flag; |
| 662 | 648 |
| 663 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 649 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 664 !it.IsAtEnd(); it.Advance()) { | 650 !it.IsAtEnd(); it.Advance()) { |
| 665 it.GetCurrentValue()->SetPreemptByFlag(preempted_flag_); | 651 it.GetCurrentValue()->SetPreemptByFlag(preempted_flag_); |
| 666 } | 652 } |
| 667 } | 653 } |
| 668 | 654 |
| 669 GpuChannel::~GpuChannel() { | |
| 670 if (preempting_flag_.get()) | |
| 671 preempting_flag_->Reset(); | |
| 672 } | |
| 673 | |
| 674 void GpuChannel::OnDestroy() { | 655 void GpuChannel::OnDestroy() { |
| 675 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); | 656 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); |
| 676 gpu_channel_manager_->RemoveChannel(client_id_); | 657 gpu_channel_manager_->RemoveChannel(client_id_); |
| 677 } | 658 } |
| 678 | 659 |
| 679 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | 660 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { |
| 680 bool handled = true; | 661 bool handled = true; |
| 681 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) | 662 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) |
| 682 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, | 663 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, |
| 683 OnCreateOffscreenCommandBuffer) | 664 OnCreateOffscreenCommandBuffer) |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 uint64 GpuChannel::GetMemoryUsage() { | 837 uint64 GpuChannel::GetMemoryUsage() { |
| 857 uint64 size = 0; | 838 uint64 size = 0; |
| 858 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 839 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 859 !it.IsAtEnd(); it.Advance()) { | 840 !it.IsAtEnd(); it.Advance()) { |
| 860 size += it.GetCurrentValue()->GetMemoryUsage(); | 841 size += it.GetCurrentValue()->GetMemoryUsage(); |
| 861 } | 842 } |
| 862 return size; | 843 return size; |
| 863 } | 844 } |
| 864 | 845 |
| 865 } // namespace content | 846 } // namespace content |
| OLD | NEW |