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

Side by Side Diff: content/common/gpu/gpu_channel.cc

Issue 1845563005: Refactor content/common/gpu into gpu/ipc/service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Drop ref to deleted content_tests_gypi_values.content_unittests_ozone_sources Created 4 years, 8 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
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_channel_manager.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) 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.
4
5 #include "content/common/gpu/gpu_channel.h"
6
7 #include <utility>
8
9 #if defined(OS_WIN)
10 #include <windows.h>
11 #endif
12
13 #include <algorithm>
14 #include <deque>
15 #include <set>
16 #include <vector>
17
18 #include "base/atomicops.h"
19 #include "base/bind.h"
20 #include "base/command_line.h"
21 #include "base/location.h"
22 #include "base/numerics/safe_conversions.h"
23 #include "base/single_thread_task_runner.h"
24 #include "base/stl_util.h"
25 #include "base/strings/string_util.h"
26 #include "base/synchronization/lock.h"
27 #include "base/thread_task_runner_handle.h"
28 #include "base/timer/timer.h"
29 #include "base/trace_event/memory_dump_manager.h"
30 #include "base/trace_event/process_memory_dump.h"
31 #include "base/trace_event/trace_event.h"
32 #include "build/build_config.h"
33 #include "content/common/gpu/gpu_channel_manager.h"
34 #include "content/common/gpu/gpu_channel_manager_delegate.h"
35 #include "content/common/gpu/gpu_memory_buffer_factory.h"
36 #include "gpu/command_buffer/common/mailbox.h"
37 #include "gpu/command_buffer/common/value_state.h"
38 #include "gpu/command_buffer/service/command_executor.h"
39 #include "gpu/command_buffer/service/image_factory.h"
40 #include "gpu/command_buffer/service/mailbox_manager.h"
41 #include "gpu/command_buffer/service/sync_point_manager.h"
42 #include "gpu/command_buffer/service/valuebuffer_manager.h"
43 #include "gpu/ipc/common/gpu_messages.h"
44 #include "ipc/ipc_channel.h"
45 #include "ipc/message_filter.h"
46 #include "ui/gl/gl_context.h"
47 #include "ui/gl/gl_image_shared_memory.h"
48 #include "ui/gl/gl_surface.h"
49
50 #if defined(OS_POSIX)
51 #include "ipc/ipc_channel_posix.h"
52 #endif
53
54 namespace content {
55 namespace {
56
57 // Number of milliseconds between successive vsync. Many GL commands block
58 // on vsync, so thresholds for preemption should be multiples of this.
59 const int64_t kVsyncIntervalMs = 17;
60
61 // Amount of time that we will wait for an IPC to be processed before
62 // preempting. After a preemption, we must wait this long before triggering
63 // another preemption.
64 const int64_t kPreemptWaitTimeMs = 2 * kVsyncIntervalMs;
65
66 // Once we trigger a preemption, the maximum duration that we will wait
67 // before clearing the preemption.
68 const int64_t kMaxPreemptTimeMs = kVsyncIntervalMs;
69
70 // Stop the preemption once the time for the longest pending IPC drops
71 // below this threshold.
72 const int64_t kStopPreemptThresholdMs = kVsyncIntervalMs;
73
74 } // anonymous namespace
75
76 scoped_refptr<GpuChannelMessageQueue> GpuChannelMessageQueue::Create(
77 int32_t stream_id,
78 gpu::GpuStreamPriority stream_priority,
79 GpuChannel* channel,
80 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
81 const scoped_refptr<gpu::PreemptionFlag>& preempting_flag,
82 const scoped_refptr<gpu::PreemptionFlag>& preempted_flag,
83 gpu::SyncPointManager* sync_point_manager) {
84 return new GpuChannelMessageQueue(stream_id, stream_priority, channel,
85 io_task_runner, preempting_flag,
86 preempted_flag, sync_point_manager);
87 }
88
89 scoped_refptr<gpu::SyncPointOrderData>
90 GpuChannelMessageQueue::GetSyncPointOrderData() {
91 return sync_point_order_data_;
92 }
93
94 GpuChannelMessageQueue::GpuChannelMessageQueue(
95 int32_t stream_id,
96 gpu::GpuStreamPriority stream_priority,
97 GpuChannel* channel,
98 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
99 const scoped_refptr<gpu::PreemptionFlag>& preempting_flag,
100 const scoped_refptr<gpu::PreemptionFlag>& preempted_flag,
101 gpu::SyncPointManager* sync_point_manager)
102 : stream_id_(stream_id),
103 stream_priority_(stream_priority),
104 enabled_(true),
105 scheduled_(true),
106 channel_(channel),
107 preemption_state_(IDLE),
108 max_preemption_time_(
109 base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs)),
110 timer_(new base::OneShotTimer),
111 sync_point_order_data_(gpu::SyncPointOrderData::Create()),
112 io_task_runner_(io_task_runner),
113 preempting_flag_(preempting_flag),
114 preempted_flag_(preempted_flag),
115 sync_point_manager_(sync_point_manager) {
116 timer_->SetTaskRunner(io_task_runner);
117 io_thread_checker_.DetachFromThread();
118 }
119
120 GpuChannelMessageQueue::~GpuChannelMessageQueue() {
121 DCHECK(!enabled_);
122 DCHECK(channel_messages_.empty());
123 }
124
125 void GpuChannelMessageQueue::Disable() {
126 {
127 base::AutoLock auto_lock(channel_lock_);
128 DCHECK(enabled_);
129 enabled_ = false;
130 }
131
132 // We guarantee that the queues will no longer be modified after enabled_
133 // is set to false, it is now safe to modify the queue without the lock.
134 // All public facing modifying functions check enabled_ while all
135 // private modifying functions DCHECK(enabled_) to enforce this.
136 while (!channel_messages_.empty()) {
137 const IPC::Message& msg = channel_messages_.front()->message;
138 if (msg.is_sync()) {
139 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
140 reply->set_reply_error();
141 channel_->Send(reply);
142 }
143 channel_messages_.pop_front();
144 }
145
146 sync_point_order_data_->Destroy();
147 sync_point_order_data_ = nullptr;
148
149 io_task_runner_->PostTask(
150 FROM_HERE, base::Bind(&GpuChannelMessageQueue::DisableIO, this));
151 }
152
153 void GpuChannelMessageQueue::DisableIO() {
154 DCHECK(io_thread_checker_.CalledOnValidThread());
155 timer_ = nullptr;
156 }
157
158 bool GpuChannelMessageQueue::IsScheduled() const {
159 base::AutoLock lock(channel_lock_);
160 return scheduled_;
161 }
162
163 void GpuChannelMessageQueue::OnRescheduled(bool scheduled) {
164 base::AutoLock lock(channel_lock_);
165 DCHECK(enabled_);
166 if (scheduled_ == scheduled)
167 return;
168 scheduled_ = scheduled;
169 if (scheduled)
170 channel_->PostHandleMessage(this);
171 if (preempting_flag_) {
172 io_task_runner_->PostTask(
173 FROM_HERE,
174 base::Bind(&GpuChannelMessageQueue::UpdatePreemptionState, this));
175 }
176 }
177
178 uint32_t GpuChannelMessageQueue::GetUnprocessedOrderNum() const {
179 return sync_point_order_data_->unprocessed_order_num();
180 }
181
182 uint32_t GpuChannelMessageQueue::GetProcessedOrderNum() const {
183 return sync_point_order_data_->processed_order_num();
184 }
185
186 bool GpuChannelMessageQueue::PushBackMessage(const IPC::Message& message) {
187 base::AutoLock auto_lock(channel_lock_);
188 if (enabled_) {
189 if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
190 message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
191 channel_->PostHandleOutOfOrderMessage(message);
192 return true;
193 }
194
195 uint32_t order_num = sync_point_order_data_->GenerateUnprocessedOrderNumber(
196 sync_point_manager_);
197 scoped_ptr<GpuChannelMessage> msg(
198 new GpuChannelMessage(message, order_num, base::TimeTicks::Now()));
199
200 if (channel_messages_.empty()) {
201 DCHECK(scheduled_);
202 channel_->PostHandleMessage(this);
203 }
204
205 channel_messages_.push_back(std::move(msg));
206
207 if (preempting_flag_)
208 UpdatePreemptionStateHelper();
209
210 return true;
211 }
212 return false;
213 }
214
215 const GpuChannelMessage* GpuChannelMessageQueue::BeginMessageProcessing() {
216 base::AutoLock auto_lock(channel_lock_);
217 DCHECK(enabled_);
218 // If we have been preempted by another channel, just post a task to wake up.
219 if (preempted_flag_ && preempted_flag_->IsSet()) {
220 channel_->PostHandleMessage(this);
221 return nullptr;
222 }
223 if (channel_messages_.empty())
224 return nullptr;
225 sync_point_order_data_->BeginProcessingOrderNumber(
226 channel_messages_.front()->order_number);
227 return channel_messages_.front().get();
228 }
229
230 void GpuChannelMessageQueue::PauseMessageProcessing() {
231 base::AutoLock auto_lock(channel_lock_);
232 DCHECK(!channel_messages_.empty());
233
234 // If we have been preempted by another channel, just post a task to wake up.
235 if (scheduled_)
236 channel_->PostHandleMessage(this);
237
238 sync_point_order_data_->PauseProcessingOrderNumber(
239 channel_messages_.front()->order_number);
240 }
241
242 void GpuChannelMessageQueue::FinishMessageProcessing() {
243 base::AutoLock auto_lock(channel_lock_);
244 DCHECK(!channel_messages_.empty());
245 DCHECK(scheduled_);
246
247 sync_point_order_data_->FinishProcessingOrderNumber(
248 channel_messages_.front()->order_number);
249 channel_messages_.pop_front();
250
251 if (!channel_messages_.empty())
252 channel_->PostHandleMessage(this);
253
254 if (preempting_flag_) {
255 io_task_runner_->PostTask(
256 FROM_HERE,
257 base::Bind(&GpuChannelMessageQueue::UpdatePreemptionState, this));
258 }
259 }
260
261 void GpuChannelMessageQueue::UpdatePreemptionState() {
262 DCHECK(io_thread_checker_.CalledOnValidThread());
263 DCHECK(preempting_flag_);
264 base::AutoLock lock(channel_lock_);
265 UpdatePreemptionStateHelper();
266 }
267
268 void GpuChannelMessageQueue::UpdatePreemptionStateHelper() {
269 DCHECK(io_thread_checker_.CalledOnValidThread());
270 DCHECK(preempting_flag_);
271 channel_lock_.AssertAcquired();
272 switch (preemption_state_) {
273 case IDLE:
274 UpdateStateIdle();
275 break;
276 case WAITING:
277 UpdateStateWaiting();
278 break;
279 case CHECKING:
280 UpdateStateChecking();
281 break;
282 case PREEMPTING:
283 UpdateStatePreempting();
284 break;
285 case WOULD_PREEMPT_DESCHEDULED:
286 UpdateStateWouldPreemptDescheduled();
287 break;
288 default:
289 NOTREACHED();
290 }
291 }
292
293 void GpuChannelMessageQueue::UpdateStateIdle() {
294 DCHECK(io_thread_checker_.CalledOnValidThread());
295 DCHECK(preempting_flag_);
296 channel_lock_.AssertAcquired();
297 DCHECK(!timer_->IsRunning());
298 if (!channel_messages_.empty())
299 TransitionToWaiting();
300 }
301
302 void GpuChannelMessageQueue::UpdateStateWaiting() {
303 DCHECK(io_thread_checker_.CalledOnValidThread());
304 DCHECK(preempting_flag_);
305 channel_lock_.AssertAcquired();
306 // Transition to CHECKING if timer fired.
307 if (!timer_->IsRunning())
308 TransitionToChecking();
309 }
310
311 void GpuChannelMessageQueue::UpdateStateChecking() {
312 DCHECK(io_thread_checker_.CalledOnValidThread());
313 DCHECK(preempting_flag_);
314 channel_lock_.AssertAcquired();
315 if (!channel_messages_.empty()) {
316 base::TimeTicks time_recv = channel_messages_.front()->time_received;
317 base::TimeDelta time_elapsed = base::TimeTicks::Now() - time_recv;
318 if (time_elapsed.InMilliseconds() < kPreemptWaitTimeMs) {
319 // Schedule another check for when the IPC may go long.
320 timer_->Start(
321 FROM_HERE,
322 base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs) - time_elapsed,
323 this, &GpuChannelMessageQueue::UpdatePreemptionState);
324 } else {
325 timer_->Stop();
326 if (!scheduled_)
327 TransitionToWouldPreemptDescheduled();
328 else
329 TransitionToPreempting();
330 }
331 }
332 }
333
334 void GpuChannelMessageQueue::UpdateStatePreempting() {
335 DCHECK(io_thread_checker_.CalledOnValidThread());
336 DCHECK(preempting_flag_);
337 channel_lock_.AssertAcquired();
338 // We should stop preempting if the timer fired or for other conditions.
339 if (!timer_->IsRunning() || ShouldTransitionToIdle()) {
340 TransitionToIdle();
341 } else if (!scheduled_) {
342 // Save the remaining preemption time before stopping the timer.
343 max_preemption_time_ = timer_->desired_run_time() - base::TimeTicks::Now();
344 timer_->Stop();
345 TransitionToWouldPreemptDescheduled();
346 }
347 }
348
349 void GpuChannelMessageQueue::UpdateStateWouldPreemptDescheduled() {
350 DCHECK(io_thread_checker_.CalledOnValidThread());
351 DCHECK(preempting_flag_);
352 channel_lock_.AssertAcquired();
353 DCHECK(!timer_->IsRunning());
354 if (ShouldTransitionToIdle()) {
355 TransitionToIdle();
356 } else if (scheduled_) {
357 TransitionToPreempting();
358 }
359 }
360
361 bool GpuChannelMessageQueue::ShouldTransitionToIdle() const {
362 DCHECK(io_thread_checker_.CalledOnValidThread());
363 DCHECK(preempting_flag_);
364 channel_lock_.AssertAcquired();
365 DCHECK(preemption_state_ == PREEMPTING ||
366 preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
367 if (channel_messages_.empty()) {
368 return true;
369 } else {
370 base::TimeTicks next_tick = channel_messages_.front()->time_received;
371 base::TimeDelta time_elapsed = base::TimeTicks::Now() - next_tick;
372 if (time_elapsed.InMilliseconds() < kStopPreemptThresholdMs)
373 return true;
374 }
375 return false;
376 }
377
378 void GpuChannelMessageQueue::TransitionToIdle() {
379 DCHECK(io_thread_checker_.CalledOnValidThread());
380 DCHECK(preempting_flag_);
381 channel_lock_.AssertAcquired();
382 DCHECK(preemption_state_ == PREEMPTING ||
383 preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
384
385 preemption_state_ = IDLE;
386 preempting_flag_->Reset();
387
388 max_preemption_time_ = base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs);
389 timer_->Stop();
390
391 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
392
393 UpdateStateIdle();
394 }
395
396 void GpuChannelMessageQueue::TransitionToWaiting() {
397 DCHECK(io_thread_checker_.CalledOnValidThread());
398 DCHECK(preempting_flag_);
399 channel_lock_.AssertAcquired();
400 DCHECK_EQ(preemption_state_, IDLE);
401 DCHECK(!timer_->IsRunning());
402
403 preemption_state_ = WAITING;
404
405 timer_->Start(FROM_HERE,
406 base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs), this,
407 &GpuChannelMessageQueue::UpdatePreemptionState);
408 }
409
410 void GpuChannelMessageQueue::TransitionToChecking() {
411 DCHECK(io_thread_checker_.CalledOnValidThread());
412 DCHECK(preempting_flag_);
413 channel_lock_.AssertAcquired();
414 DCHECK_EQ(preemption_state_, WAITING);
415 DCHECK(!timer_->IsRunning());
416
417 preemption_state_ = CHECKING;
418
419 UpdateStateChecking();
420 }
421
422 void GpuChannelMessageQueue::TransitionToPreempting() {
423 DCHECK(io_thread_checker_.CalledOnValidThread());
424 DCHECK(preempting_flag_);
425 channel_lock_.AssertAcquired();
426 DCHECK(preemption_state_ == CHECKING ||
427 preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
428 DCHECK(scheduled_);
429
430 preemption_state_ = PREEMPTING;
431 preempting_flag_->Set();
432 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 1);
433
434 DCHECK_LE(max_preemption_time_,
435 base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs));
436 timer_->Start(FROM_HERE, max_preemption_time_, this,
437 &GpuChannelMessageQueue::UpdatePreemptionState);
438 }
439
440 void GpuChannelMessageQueue::TransitionToWouldPreemptDescheduled() {
441 DCHECK(io_thread_checker_.CalledOnValidThread());
442 DCHECK(preempting_flag_);
443 channel_lock_.AssertAcquired();
444 DCHECK(preemption_state_ == CHECKING || preemption_state_ == PREEMPTING);
445 DCHECK(!scheduled_);
446
447 preemption_state_ = WOULD_PREEMPT_DESCHEDULED;
448 preempting_flag_->Reset();
449 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
450 }
451
452 GpuChannelMessageFilter::GpuChannelMessageFilter()
453 : sender_(nullptr), peer_pid_(base::kNullProcessId) {}
454
455 GpuChannelMessageFilter::~GpuChannelMessageFilter() {}
456
457 void GpuChannelMessageFilter::OnFilterAdded(IPC::Sender* sender) {
458 DCHECK(!sender_);
459 sender_ = sender;
460 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
461 filter->OnFilterAdded(sender_);
462 }
463 }
464
465 void GpuChannelMessageFilter::OnFilterRemoved() {
466 DCHECK(sender_);
467 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
468 filter->OnFilterRemoved();
469 }
470 sender_ = nullptr;
471 peer_pid_ = base::kNullProcessId;
472 }
473
474 void GpuChannelMessageFilter::OnChannelConnected(int32_t peer_pid) {
475 DCHECK(peer_pid_ == base::kNullProcessId);
476 peer_pid_ = peer_pid;
477 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
478 filter->OnChannelConnected(peer_pid);
479 }
480 }
481
482 void GpuChannelMessageFilter::OnChannelError() {
483 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
484 filter->OnChannelError();
485 }
486 }
487
488 void GpuChannelMessageFilter::OnChannelClosing() {
489 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
490 filter->OnChannelClosing();
491 }
492 }
493
494 void GpuChannelMessageFilter::AddChannelFilter(
495 scoped_refptr<IPC::MessageFilter> filter) {
496 channel_filters_.push_back(filter);
497 if (sender_)
498 filter->OnFilterAdded(sender_);
499 if (peer_pid_ != base::kNullProcessId)
500 filter->OnChannelConnected(peer_pid_);
501 }
502
503 void GpuChannelMessageFilter::RemoveChannelFilter(
504 scoped_refptr<IPC::MessageFilter> filter) {
505 if (sender_)
506 filter->OnFilterRemoved();
507 channel_filters_.erase(
508 std::find(channel_filters_.begin(), channel_filters_.end(), filter));
509 }
510
511 // This gets called from the main thread and assumes that all messages which
512 // lead to creation of a new route are synchronous messages.
513 // TODO(sunnyps): Create routes (and streams) on the IO thread so that we can
514 // make the CreateCommandBuffer/VideoDecoder/VideoEncoder messages asynchronous.
515 void GpuChannelMessageFilter::AddRoute(
516 int32_t route_id,
517 const scoped_refptr<GpuChannelMessageQueue>& queue) {
518 base::AutoLock lock(routes_lock_);
519 routes_.insert(std::make_pair(route_id, queue));
520 }
521
522 void GpuChannelMessageFilter::RemoveRoute(int32_t route_id) {
523 base::AutoLock lock(routes_lock_);
524 routes_.erase(route_id);
525 }
526
527 bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
528 DCHECK(sender_);
529
530 if (message.should_unblock() || message.is_reply())
531 return MessageErrorHandler(message, "Unexpected message type");
532
533 if (message.type() == GpuChannelMsg_Nop::ID) {
534 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
535 Send(reply);
536 return true;
537 }
538
539 for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
540 if (filter->OnMessageReceived(message))
541 return true;
542 }
543
544 scoped_refptr<GpuChannelMessageQueue> message_queue =
545 LookupStreamByRoute(message.routing_id());
546
547 if (!message_queue)
548 return MessageErrorHandler(message, "Could not find message queue");
549
550 if (!message_queue->PushBackMessage(message))
551 return MessageErrorHandler(message, "Channel destroyed");
552
553 return true;
554 }
555
556 bool GpuChannelMessageFilter::Send(IPC::Message* message) {
557 return sender_->Send(message);
558 }
559
560 scoped_refptr<GpuChannelMessageQueue>
561 GpuChannelMessageFilter::LookupStreamByRoute(int32_t route_id) {
562 base::AutoLock lock(routes_lock_);
563 auto it = routes_.find(route_id);
564 if (it != routes_.end())
565 return it->second;
566 return nullptr;
567 }
568
569 bool GpuChannelMessageFilter::MessageErrorHandler(const IPC::Message& message,
570 const char* error_msg) {
571 DLOG(ERROR) << error_msg;
572 if (message.is_sync()) {
573 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
574 reply->set_reply_error();
575 Send(reply);
576 }
577 return true;
578 }
579
580 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
581 gpu::SyncPointManager* sync_point_manager,
582 GpuWatchdog* watchdog,
583 gfx::GLShareGroup* share_group,
584 gpu::gles2::MailboxManager* mailbox,
585 gpu::PreemptionFlag* preempting_flag,
586 gpu::PreemptionFlag* preempted_flag,
587 base::SingleThreadTaskRunner* task_runner,
588 base::SingleThreadTaskRunner* io_task_runner,
589 int32_t client_id,
590 uint64_t client_tracing_id,
591 bool allow_view_command_buffers,
592 bool allow_real_time_streams)
593 : gpu_channel_manager_(gpu_channel_manager),
594 sync_point_manager_(sync_point_manager),
595 unhandled_message_listener_(nullptr),
596 channel_id_(IPC::Channel::GenerateVerifiedChannelID("gpu")),
597 preempting_flag_(preempting_flag),
598 preempted_flag_(preempted_flag),
599 client_id_(client_id),
600 client_tracing_id_(client_tracing_id),
601 task_runner_(task_runner),
602 io_task_runner_(io_task_runner),
603 share_group_(share_group),
604 mailbox_manager_(mailbox),
605 subscription_ref_set_(new gpu::gles2::SubscriptionRefSet),
606 pending_valuebuffer_state_(new gpu::ValueStateMap),
607 watchdog_(watchdog),
608 allow_view_command_buffers_(allow_view_command_buffers),
609 allow_real_time_streams_(allow_real_time_streams),
610 weak_factory_(this) {
611 DCHECK(gpu_channel_manager);
612 DCHECK(client_id);
613
614 filter_ = new GpuChannelMessageFilter();
615
616 scoped_refptr<GpuChannelMessageQueue> control_queue =
617 CreateStream(gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::HIGH);
618 AddRouteToStream(MSG_ROUTING_CONTROL, gpu::GPU_STREAM_DEFAULT);
619
620 subscription_ref_set_->AddObserver(this);
621 }
622
623 GpuChannel::~GpuChannel() {
624 // Clear stubs first because of dependencies.
625 stubs_.clear();
626
627 for (auto& kv : streams_)
628 kv.second->Disable();
629
630 subscription_ref_set_->RemoveObserver(this);
631 if (preempting_flag_.get())
632 preempting_flag_->Reset();
633 }
634
635 IPC::ChannelHandle GpuChannel::Init(base::WaitableEvent* shutdown_event) {
636 DCHECK(shutdown_event);
637 DCHECK(!channel_);
638
639 IPC::ChannelHandle channel_handle(channel_id_);
640
641 channel_ =
642 IPC::SyncChannel::Create(channel_handle, IPC::Channel::MODE_SERVER, this,
643 io_task_runner_, false, shutdown_event);
644
645 #if defined(OS_POSIX)
646 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
647 // that it gets closed after it has been sent.
648 base::ScopedFD renderer_fd = channel_->TakeClientFileDescriptor();
649 DCHECK(renderer_fd.is_valid());
650 channel_handle.socket = base::FileDescriptor(std::move(renderer_fd));
651 #endif
652
653 channel_->AddFilter(filter_.get());
654
655 return channel_handle;
656 }
657
658 void GpuChannel::SetUnhandledMessageListener(IPC::Listener* listener) {
659 unhandled_message_listener_ = listener;
660 }
661
662 base::WeakPtr<GpuChannel> GpuChannel::AsWeakPtr() {
663 return weak_factory_.GetWeakPtr();
664 }
665
666 base::ProcessId GpuChannel::GetClientPID() const {
667 return channel_->GetPeerPID();
668 }
669
670 uint32_t GpuChannel::GetProcessedOrderNum() const {
671 uint32_t processed_order_num = 0;
672 for (auto& kv : streams_) {
673 processed_order_num =
674 std::max(processed_order_num, kv.second->GetProcessedOrderNum());
675 }
676 return processed_order_num;
677 }
678
679 uint32_t GpuChannel::GetUnprocessedOrderNum() const {
680 uint32_t unprocessed_order_num = 0;
681 for (auto& kv : streams_) {
682 unprocessed_order_num =
683 std::max(unprocessed_order_num, kv.second->GetUnprocessedOrderNum());
684 }
685 return unprocessed_order_num;
686 }
687
688 bool GpuChannel::OnMessageReceived(const IPC::Message& msg) {
689 // All messages should be pushed to channel_messages_ and handled separately.
690 NOTREACHED();
691 return false;
692 }
693
694 void GpuChannel::OnChannelError() {
695 gpu_channel_manager_->RemoveChannel(client_id_);
696 }
697
698 bool GpuChannel::Send(IPC::Message* message) {
699 // The GPU process must never send a synchronous IPC message to the renderer
700 // process. This could result in deadlock.
701 DCHECK(!message->is_sync());
702
703 DVLOG(1) << "sending message @" << message << " on channel @" << this
704 << " with type " << message->type();
705
706 if (!channel_) {
707 delete message;
708 return false;
709 }
710
711 return channel_->Send(message);
712 }
713
714 void GpuChannel::OnAddSubscription(unsigned int target) {
715 gpu_channel_manager()->delegate()->AddSubscription(client_id_, target);
716 }
717
718 void GpuChannel::OnRemoveSubscription(unsigned int target) {
719 gpu_channel_manager()->delegate()->RemoveSubscription(client_id_, target);
720 }
721
722 void GpuChannel::OnStreamRescheduled(int32_t stream_id, bool scheduled) {
723 scoped_refptr<GpuChannelMessageQueue> queue = LookupStream(stream_id);
724 DCHECK(queue);
725 queue->OnRescheduled(scheduled);
726 }
727
728 GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32_t route_id) {
729 return stubs_.get(route_id);
730 }
731
732 void GpuChannel::LoseAllContexts() {
733 gpu_channel_manager_->LoseAllContexts();
734 }
735
736 void GpuChannel::MarkAllContextsLost() {
737 for (auto& kv : stubs_)
738 kv.second->MarkContextLost();
739 }
740
741 bool GpuChannel::AddRoute(int32_t route_id,
742 int32_t stream_id,
743 IPC::Listener* listener) {
744 if (router_.AddRoute(route_id, listener)) {
745 AddRouteToStream(route_id, stream_id);
746 return true;
747 }
748 return false;
749 }
750
751 void GpuChannel::RemoveRoute(int32_t route_id) {
752 router_.RemoveRoute(route_id);
753 RemoveRouteFromStream(route_id);
754 }
755
756 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
757 bool handled = true;
758 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg)
759 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateCommandBuffer,
760 OnCreateCommandBuffer)
761 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
762 OnDestroyCommandBuffer)
763 IPC_MESSAGE_HANDLER(GpuChannelMsg_GetDriverBugWorkArounds,
764 OnGetDriverBugWorkArounds)
765 IPC_MESSAGE_UNHANDLED(handled = false)
766 IPC_END_MESSAGE_MAP()
767 return handled;
768 }
769
770 scoped_refptr<gpu::SyncPointOrderData> GpuChannel::GetSyncPointOrderData(
771 int32_t stream_id) {
772 auto it = streams_.find(stream_id);
773 DCHECK(it != streams_.end());
774 DCHECK(it->second);
775 return it->second->GetSyncPointOrderData();
776 }
777
778 void GpuChannel::PostHandleMessage(
779 const scoped_refptr<GpuChannelMessageQueue>& queue) {
780 task_runner_->PostTask(FROM_HERE,
781 base::Bind(&GpuChannel::HandleMessage,
782 weak_factory_.GetWeakPtr(), queue));
783 }
784
785 void GpuChannel::PostHandleOutOfOrderMessage(const IPC::Message& msg) {
786 task_runner_->PostTask(FROM_HERE,
787 base::Bind(&GpuChannel::HandleOutOfOrderMessage,
788 weak_factory_.GetWeakPtr(), msg));
789 }
790
791 void GpuChannel::HandleMessage(
792 const scoped_refptr<GpuChannelMessageQueue>& message_queue) {
793 const GpuChannelMessage* channel_msg =
794 message_queue->BeginMessageProcessing();
795 if (!channel_msg)
796 return;
797
798 const IPC::Message& msg = channel_msg->message;
799 int32_t routing_id = msg.routing_id();
800 GpuCommandBufferStub* stub = stubs_.get(routing_id);
801
802 DCHECK(!stub || stub->IsScheduled());
803
804 DVLOG(1) << "received message @" << &msg << " on channel @" << this
805 << " with type " << msg.type();
806
807 HandleMessageHelper(msg);
808
809 // If we get descheduled or yield while processing a message.
810 if (stub && stub->HasUnprocessedCommands()) {
811 DCHECK_EQ((uint32_t)GpuCommandBufferMsg_AsyncFlush::ID, msg.type());
812 message_queue->PauseMessageProcessing();
813 } else {
814 message_queue->FinishMessageProcessing();
815 }
816 }
817
818 void GpuChannel::HandleMessageHelper(const IPC::Message& msg) {
819 int32_t routing_id = msg.routing_id();
820
821 bool handled = false;
822 if (routing_id == MSG_ROUTING_CONTROL) {
823 handled = OnControlMessageReceived(msg);
824 } else {
825 handled = router_.RouteMessage(msg);
826 }
827
828 if (!handled && unhandled_message_listener_)
829 handled = unhandled_message_listener_->OnMessageReceived(msg);
830
831 // Respond to sync messages even if router failed to route.
832 if (!handled && msg.is_sync()) {
833 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
834 reply->set_reply_error();
835 Send(reply);
836 }
837 }
838
839 void GpuChannel::HandleOutOfOrderMessage(const IPC::Message& msg) {
840 HandleMessageHelper(msg);
841 }
842
843 void GpuChannel::HandleMessageForTesting(const IPC::Message& msg) {
844 HandleMessageHelper(msg);
845 }
846
847 scoped_refptr<GpuChannelMessageQueue> GpuChannel::CreateStream(
848 int32_t stream_id,
849 gpu::GpuStreamPriority stream_priority) {
850 DCHECK(streams_.find(stream_id) == streams_.end());
851 scoped_refptr<GpuChannelMessageQueue> queue = GpuChannelMessageQueue::Create(
852 stream_id, stream_priority, this, io_task_runner_,
853 (stream_id == gpu::GPU_STREAM_DEFAULT) ? preempting_flag_ : nullptr,
854 preempted_flag_, sync_point_manager_);
855 streams_.insert(std::make_pair(stream_id, queue));
856 streams_to_num_routes_.insert(std::make_pair(stream_id, 0));
857 return queue;
858 }
859
860 scoped_refptr<GpuChannelMessageQueue> GpuChannel::LookupStream(
861 int32_t stream_id) {
862 auto stream_it = streams_.find(stream_id);
863 if (stream_it != streams_.end())
864 return stream_it->second;
865 return nullptr;
866 }
867
868 void GpuChannel::DestroyStreamIfNecessary(
869 const scoped_refptr<GpuChannelMessageQueue>& queue) {
870 int32_t stream_id = queue->stream_id();
871 if (streams_to_num_routes_[stream_id] == 0) {
872 queue->Disable();
873 streams_to_num_routes_.erase(stream_id);
874 streams_.erase(stream_id);
875 }
876 }
877
878 void GpuChannel::AddRouteToStream(int32_t route_id, int32_t stream_id) {
879 DCHECK(streams_.find(stream_id) != streams_.end());
880 DCHECK(routes_to_streams_.find(route_id) == routes_to_streams_.end());
881 streams_to_num_routes_[stream_id]++;
882 routes_to_streams_.insert(std::make_pair(route_id, stream_id));
883 filter_->AddRoute(route_id, streams_[stream_id]);
884 }
885
886 void GpuChannel::RemoveRouteFromStream(int32_t route_id) {
887 DCHECK(routes_to_streams_.find(route_id) != routes_to_streams_.end());
888 int32_t stream_id = routes_to_streams_[route_id];
889 DCHECK(streams_.find(stream_id) != streams_.end());
890 routes_to_streams_.erase(route_id);
891 streams_to_num_routes_[stream_id]--;
892 filter_->RemoveRoute(route_id);
893 DestroyStreamIfNecessary(streams_[stream_id]);
894 }
895
896 #if defined(OS_ANDROID)
897 const GpuCommandBufferStub* GpuChannel::GetOneStub() const {
898 for (const auto& kv : stubs_) {
899 const GpuCommandBufferStub* stub = kv.second;
900 if (stub->decoder() && !stub->decoder()->WasContextLost())
901 return stub;
902 }
903 return nullptr;
904 }
905 #endif
906
907 void GpuChannel::OnCreateCommandBuffer(
908 gpu::SurfaceHandle surface_handle,
909 const gfx::Size& size,
910 const GPUCreateCommandBufferConfig& init_params,
911 int32_t route_id,
912 bool* succeeded) {
913 TRACE_EVENT2("gpu", "GpuChannel::OnCreateCommandBuffer", "route_id", route_id,
914 "offscreen", (surface_handle == gpu::kNullSurfaceHandle));
915 *succeeded = false;
916 if (surface_handle != gpu::kNullSurfaceHandle &&
917 !allow_view_command_buffers_) {
918 DLOG(ERROR) << "GpuChannel::CreateCommandBuffer(): attempt to create a "
919 "view context on a non-priviledged channel";
920 return;
921 }
922
923 int32_t share_group_id = init_params.share_group_id;
924 GpuCommandBufferStub* share_group = stubs_.get(share_group_id);
925
926 if (!share_group && share_group_id != MSG_ROUTING_NONE) {
927 DLOG(ERROR)
928 << "GpuChannel::OnCreateCommandBuffer(): invalid share group id";
929 return;
930 }
931
932 int32_t stream_id = init_params.stream_id;
933 if (share_group && stream_id != share_group->stream_id()) {
934 DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): stream id does not "
935 "match share group stream id";
936 return;
937 }
938
939 gpu::GpuStreamPriority stream_priority = init_params.stream_priority;
940 if (!allow_real_time_streams_ &&
941 stream_priority == gpu::GpuStreamPriority::REAL_TIME) {
942 DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): real time stream "
943 "priority not allowed";
944 return;
945 }
946
947 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
948 this, sync_point_manager_, task_runner_.get(), share_group,
949 surface_handle, mailbox_manager_.get(), preempted_flag_.get(),
950 subscription_ref_set_.get(), pending_valuebuffer_state_.get(), size,
951 disallowed_features_, init_params.attribs, init_params.gpu_preference,
952 init_params.stream_id, route_id, watchdog_, init_params.active_url));
953
954 scoped_refptr<GpuChannelMessageQueue> queue = LookupStream(stream_id);
955 if (!queue)
956 queue = CreateStream(stream_id, stream_priority);
957
958 if (!AddRoute(route_id, stream_id, stub.get())) {
959 DestroyStreamIfNecessary(queue);
960 DLOG(ERROR) << "GpuChannel::OnCreateCommandBuffer(): failed to add route";
961 return;
962 }
963
964 stubs_.set(route_id, std::move(stub));
965 *succeeded = true;
966 }
967
968 void GpuChannel::OnDestroyCommandBuffer(int32_t route_id) {
969 TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer",
970 "route_id", route_id);
971
972 scoped_ptr<GpuCommandBufferStub> stub = stubs_.take_and_erase(route_id);
973 // In case the renderer is currently blocked waiting for a sync reply from the
974 // stub, we need to make sure to reschedule the correct stream here.
975 if (stub && !stub->IsScheduled()) {
976 // This stub won't get a chance to reschedule the stream so do that now.
977 OnStreamRescheduled(stub->stream_id(), true);
978 }
979
980 RemoveRoute(route_id);
981 }
982
983 void GpuChannel::OnGetDriverBugWorkArounds(
984 std::vector<std::string>* gpu_driver_bug_workarounds) {
985 // TODO(j.isorce): http://crbug.com/599964 Do the extraction of workarounds in
986 // the GpuChannelManager constructor. Currently it is done in the FeatureInfo
987 // constructor. There is no need to extract them from the command-line every
988 // time a new FeatureInfo is created (i.e. per ContextGroup) since parsing
989 // result is a constant.
990 scoped_refptr<gpu::gles2::FeatureInfo> feature_info =
991 new gpu::gles2::FeatureInfo;
992 gpu_driver_bug_workarounds->clear();
993 #define GPU_OP(type, name) \
994 if (feature_info->workarounds().name) \
995 gpu_driver_bug_workarounds->push_back(#name);
996 GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)
997 #undef GPU_OP
998 }
999
1000 void GpuChannel::CacheShader(const std::string& key,
1001 const std::string& shader) {
1002 gpu_channel_manager_->delegate()->StoreShaderToDisk(client_id_, key, shader);
1003 }
1004
1005 void GpuChannel::AddFilter(IPC::MessageFilter* filter) {
1006 io_task_runner_->PostTask(
1007 FROM_HERE, base::Bind(&GpuChannelMessageFilter::AddChannelFilter,
1008 filter_, make_scoped_refptr(filter)));
1009 }
1010
1011 void GpuChannel::RemoveFilter(IPC::MessageFilter* filter) {
1012 io_task_runner_->PostTask(
1013 FROM_HERE, base::Bind(&GpuChannelMessageFilter::RemoveChannelFilter,
1014 filter_, make_scoped_refptr(filter)));
1015 }
1016
1017 uint64_t GpuChannel::GetMemoryUsage() {
1018 // Collect the unique memory trackers in use by the |stubs_|.
1019 std::set<gpu::gles2::MemoryTracker*> unique_memory_trackers;
1020 for (auto& kv : stubs_)
1021 unique_memory_trackers.insert(kv.second->GetMemoryTracker());
1022
1023 // Sum the memory usage for all unique memory trackers.
1024 uint64_t size = 0;
1025 for (auto* tracker : unique_memory_trackers) {
1026 size += gpu_channel_manager()->gpu_memory_manager()->GetTrackerMemoryUsage(
1027 tracker);
1028 }
1029
1030 return size;
1031 }
1032
1033 scoped_refptr<gl::GLImage> GpuChannel::CreateImageForGpuMemoryBuffer(
1034 const gfx::GpuMemoryBufferHandle& handle,
1035 const gfx::Size& size,
1036 gfx::BufferFormat format,
1037 uint32_t internalformat) {
1038 switch (handle.type) {
1039 case gfx::SHARED_MEMORY_BUFFER: {
1040 if (!base::IsValueInRangeForNumericType<size_t>(handle.stride))
1041 return nullptr;
1042 scoped_refptr<gl::GLImageSharedMemory> image(
1043 new gl::GLImageSharedMemory(size, internalformat));
1044 if (!image->Initialize(handle.handle, handle.id, format, handle.offset,
1045 handle.stride)) {
1046 return nullptr;
1047 }
1048
1049 return image;
1050 }
1051 default: {
1052 GpuChannelManager* manager = gpu_channel_manager();
1053 if (!manager->gpu_memory_buffer_factory())
1054 return nullptr;
1055
1056 return manager->gpu_memory_buffer_factory()
1057 ->AsImageFactory()
1058 ->CreateImageForGpuMemoryBuffer(handle,
1059 size,
1060 format,
1061 internalformat,
1062 client_id_);
1063 }
1064 }
1065 }
1066
1067 void GpuChannel::HandleUpdateValueState(
1068 unsigned int target, const gpu::ValueState& state) {
1069 pending_valuebuffer_state_->UpdateState(target, state);
1070 }
1071
1072 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_channel_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698