Chromium Code Reviews| 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 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/bind_helpers.h" | 6 #include "base/bind_helpers.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/hash.h" | 8 #include "base/hash.h" |
| 9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
| 10 #include "base/memory/shared_memory.h" | 10 #include "base/memory/shared_memory.h" |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 gpu_preference_(gpu_preference), | 192 gpu_preference_(gpu_preference), |
| 193 use_virtualized_gl_context_(use_virtualized_gl_context), | 193 use_virtualized_gl_context_(use_virtualized_gl_context), |
| 194 stream_id_(stream_id), | 194 stream_id_(stream_id), |
| 195 route_id_(route_id), | 195 route_id_(route_id), |
| 196 surface_id_(surface_id), | 196 surface_id_(surface_id), |
| 197 software_(software), | 197 software_(software), |
| 198 last_flush_count_(0), | 198 last_flush_count_(0), |
| 199 last_memory_allocation_valid_(false), | 199 last_memory_allocation_valid_(false), |
| 200 watchdog_(watchdog), | 200 watchdog_(watchdog), |
| 201 sync_point_wait_count_(0), | 201 sync_point_wait_count_(0), |
| 202 delayed_work_scheduled_(false), | |
| 203 previous_messages_processed_(0), | 202 previous_messages_processed_(0), |
| 204 active_url_(active_url), | 203 active_url_(active_url), |
| 205 total_gpu_memory_(0) { | 204 total_gpu_memory_(0) { |
| 206 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); | 205 active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); |
| 207 FastSetActiveURL(active_url_, active_url_hash_); | 206 FastSetActiveURL(active_url_, active_url_hash_); |
| 208 | 207 |
| 209 gpu::gles2::ContextCreationAttribHelper attrib_parser; | 208 gpu::gles2::ContextCreationAttribHelper attrib_parser; |
| 210 attrib_parser.Parse(requested_attribs_); | 209 attrib_parser.Parse(requested_attribs_); |
| 211 | 210 |
| 212 if (share_group) { | 211 if (share_group) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 306 OnSetClientHasMemoryAllocationChangedCallback) | 305 OnSetClientHasMemoryAllocationChangedCallback) |
| 307 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage); | 306 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage); |
| 308 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage); | 307 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage); |
| 309 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture, | 308 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture, |
| 310 OnCreateStreamTexture) | 309 OnCreateStreamTexture) |
| 311 IPC_MESSAGE_UNHANDLED(handled = false) | 310 IPC_MESSAGE_UNHANDLED(handled = false) |
| 312 IPC_END_MESSAGE_MAP() | 311 IPC_END_MESSAGE_MAP() |
| 313 | 312 |
| 314 CheckCompleteWaits(); | 313 CheckCompleteWaits(); |
| 315 | 314 |
| 315 // Ensure that any delayed work that was created will be handled. | |
| 316 if (have_context) { | 316 if (have_context) { |
| 317 // Ensure that any delayed work that was created will be handled. | 317 if (scheduler_) |
| 318 ScheduleDelayedWork(kHandleMoreWorkPeriodMs); | 318 scheduler_->ProcessPendingQueries(); |
| 319 ScheduleDelayedWork( | |
| 320 base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodMs)); | |
| 319 } | 321 } |
| 320 | 322 |
| 321 DCHECK(handled); | 323 DCHECK(handled); |
| 322 return handled; | 324 return handled; |
| 323 } | 325 } |
| 324 | 326 |
| 325 bool GpuCommandBufferStub::Send(IPC::Message* message) { | 327 bool GpuCommandBufferStub::Send(IPC::Message* message) { |
| 326 return channel_->Send(message); | 328 return channel_->Send(message); |
| 327 } | 329 } |
| 328 | 330 |
| 329 bool GpuCommandBufferStub::IsScheduled() { | 331 bool GpuCommandBufferStub::IsScheduled() { |
| 330 return (!scheduler_.get() || scheduler_->IsScheduled()); | 332 return (!scheduler_.get() || scheduler_->IsScheduled()); |
| 331 } | 333 } |
| 332 | 334 |
| 333 bool GpuCommandBufferStub::HasMoreWork() { | 335 void GpuCommandBufferStub::PollWork() { |
| 334 return scheduler_.get() && scheduler_->HasMoreWork(); | 336 // Post another delayed task if we have not yet reached the time at which |
| 337 // we should process delayed work. | |
| 338 base::TimeTicks current_time = base::TimeTicks::Now(); | |
| 339 DCHECK(!process_delayed_work_time_.is_null()); | |
| 340 if (process_delayed_work_time_ > current_time) { | |
| 341 task_runner_->PostDelayedTask( | |
|
dshwang
2015/09/01 08:56:10
do we have to delay one more?
PollWork() is alread
reveman
2015/09/01 15:54:11
That's what this patch is supposed to improve. If
dshwang
2015/09/01 16:15:50
How is it possible |process_delayed_work_time_ > c
reveman
2015/09/01 16:25:17
ScheduleDelayedWork is called as a result of perfo
dshwang
2015/09/01 16:32:17
I understand, thx for explanation.
dshwang
2015/09/01 16:37:00
Is it possible for idle tasks and pending query to
reveman
2015/09/01 17:02:07
Pending queries are processed each time we process
| |
| 342 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), | |
| 343 process_delayed_work_time_ - current_time); | |
| 344 return; | |
| 345 } | |
| 346 process_delayed_work_time_ = base::TimeTicks(); | |
| 347 | |
| 348 PerformWork(); | |
| 335 } | 349 } |
| 336 | 350 |
| 337 void GpuCommandBufferStub::PollWork() { | 351 void GpuCommandBufferStub::PerformWork() { |
| 338 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PollWork"); | 352 TRACE_EVENT0("gpu", "GpuCommandBufferStub::PerformWork"); |
| 339 delayed_work_scheduled_ = false; | 353 |
| 340 FastSetActiveURL(active_url_, active_url_hash_); | 354 FastSetActiveURL(active_url_, active_url_hash_); |
| 341 if (decoder_.get() && !MakeCurrent()) | 355 if (decoder_.get() && !MakeCurrent()) |
| 342 return; | 356 return; |
| 343 | 357 |
| 344 if (scheduler_) { | 358 if (scheduler_) { |
| 345 uint64 current_messages_processed = | 359 uint64 current_messages_processed = |
| 346 channel()->gpu_channel_manager()->MessagesProcessed(); | 360 channel()->gpu_channel_manager()->MessagesProcessed(); |
| 347 // We're idle when no messages were processed or scheduled. | 361 // We're idle when no messages were processed or scheduled. |
| 348 bool is_idle = | 362 bool is_idle = |
| 349 (previous_messages_processed_ == current_messages_processed) && | 363 (previous_messages_processed_ == current_messages_processed) && |
| 350 !channel()->gpu_channel_manager()->HandleMessagesScheduled(); | 364 !channel()->gpu_channel_manager()->HandleMessagesScheduled(); |
| 351 if (!is_idle && !last_idle_time_.is_null()) { | 365 if (!is_idle && !last_idle_time_.is_null()) { |
| 352 base::TimeDelta time_since_idle = | 366 base::TimeDelta time_since_idle = |
| 353 base::TimeTicks::Now() - last_idle_time_; | 367 base::TimeTicks::Now() - last_idle_time_; |
| 354 base::TimeDelta max_time_since_idle = | 368 base::TimeDelta max_time_since_idle = |
| 355 base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs); | 369 base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs); |
| 356 | 370 |
| 357 // Force idle when it's been too long since last time we were idle. | 371 // Force idle when it's been too long since last time we were idle. |
| 358 if (time_since_idle > max_time_since_idle) | 372 if (time_since_idle > max_time_since_idle) |
| 359 is_idle = true; | 373 is_idle = true; |
| 360 } | 374 } |
| 361 | 375 |
| 362 if (is_idle) { | 376 if (is_idle) { |
| 363 last_idle_time_ = base::TimeTicks::Now(); | 377 last_idle_time_ = base::TimeTicks::Now(); |
| 364 scheduler_->PerformIdleWork(); | 378 scheduler_->PerformIdleWork(); |
| 365 } | 379 } |
| 380 | |
| 381 scheduler_->ProcessPendingQueries(); | |
|
no sievers
2015/09/16 21:04:35
Why do we really treat pending queries different f
reveman
2015/09/16 23:12:08
I'm not that familiar with the current use cases f
no sievers
2015/09/17 00:34:38
ok sounds good. i was just thinking that because w
| |
| 366 } | 382 } |
| 367 ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs); | 383 |
| 384 ScheduleDelayedWork( | |
| 385 base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodBusyMs)); | |
| 368 } | 386 } |
| 369 | 387 |
| 370 bool GpuCommandBufferStub::HasUnprocessedCommands() { | 388 bool GpuCommandBufferStub::HasUnprocessedCommands() { |
| 371 if (command_buffer_) { | 389 if (command_buffer_) { |
| 372 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); | 390 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); |
| 373 return command_buffer_->GetPutOffset() != state.get_offset && | 391 return command_buffer_->GetPutOffset() != state.get_offset && |
| 374 !gpu::error::IsError(state.error); | 392 !gpu::error::IsError(state.error); |
| 375 } | 393 } |
| 376 return false; | 394 return false; |
| 377 } | 395 } |
| 378 | 396 |
| 379 void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) { | 397 void GpuCommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) { |
| 380 if (!HasMoreWork()) { | 398 bool has_more_work = scheduler_.get() && (scheduler_->HasPendingQueries() || |
| 399 scheduler_->HasMoreIdleWork()); | |
|
dshwang
2015/09/01 08:56:10
very nice :)
| |
| 400 if (!has_more_work) { | |
| 381 last_idle_time_ = base::TimeTicks(); | 401 last_idle_time_ = base::TimeTicks(); |
| 382 return; | 402 return; |
| 383 } | 403 } |
| 384 | 404 |
| 385 if (delayed_work_scheduled_) | 405 base::TimeTicks current_time = base::TimeTicks::Now(); |
| 406 // |process_delayed_work_time_| is set if processing of delayed work is | |
| 407 // already scheduled. Just update the time if already scheduled. | |
| 408 if (!process_delayed_work_time_.is_null()) { | |
| 409 process_delayed_work_time_ = current_time + delay; | |
|
no sievers
2015/09/16 21:04:35
This keeps pushing out the time though if called r
reveman
2015/09/16 23:12:08
Improved the comment in the header file to make th
| |
| 386 return; | 410 return; |
| 387 delayed_work_scheduled_ = true; | 411 } |
| 388 | 412 |
| 389 // Idle when no messages are processed between now and when | 413 // Idle when no messages are processed between now and when |
| 390 // PollWork is called. | 414 // PollWork is called. |
| 391 previous_messages_processed_ = | 415 previous_messages_processed_ = |
| 392 channel()->gpu_channel_manager()->MessagesProcessed(); | 416 channel()->gpu_channel_manager()->MessagesProcessed(); |
| 393 if (last_idle_time_.is_null()) | 417 if (last_idle_time_.is_null()) |
| 394 last_idle_time_ = base::TimeTicks::Now(); | 418 last_idle_time_ = current_time; |
| 395 | 419 |
| 396 // IsScheduled() returns true after passing all unschedule fences | 420 // IsScheduled() returns true after passing all unschedule fences |
| 397 // and this is when we can start performing idle work. Idle work | 421 // and this is when we can start performing idle work. Idle work |
| 398 // is done synchronously so we can set delay to 0 and instead poll | 422 // is done synchronously so we can set delay to 0 and instead poll |
| 399 // for more work at the rate idle work is performed. This also ensures | 423 // for more work at the rate idle work is performed. This also ensures |
| 400 // that idle work is done as efficiently as possible without any | 424 // that idle work is done as efficiently as possible without any |
| 401 // unnecessary delays. | 425 // unnecessary delays. |
| 402 if (scheduler_.get() && | 426 if (scheduler_.get() && |
| 403 scheduler_->IsScheduled() && | 427 scheduler_->IsScheduled() && |
| 404 scheduler_->HasMoreIdleWork()) { | 428 scheduler_->HasMoreIdleWork()) { |
|
dshwang
2015/09/01 08:56:10
Don't we need to check (scheduler_->HasPendingQuer
reveman
2015/09/01 15:54:11
This code is only for handling idle work. Pending
| |
| 405 delay = 0; | 429 delay = base::TimeDelta(); |
| 406 } | 430 } |
| 407 | 431 |
| 432 process_delayed_work_time_ = current_time + delay; | |
| 408 task_runner_->PostDelayedTask( | 433 task_runner_->PostDelayedTask( |
| 409 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), | 434 FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()), |
| 410 base::TimeDelta::FromMilliseconds(delay)); | 435 delay); |
| 411 } | 436 } |
| 412 | 437 |
| 413 bool GpuCommandBufferStub::MakeCurrent() { | 438 bool GpuCommandBufferStub::MakeCurrent() { |
| 414 if (decoder_->MakeCurrent()) | 439 if (decoder_->MakeCurrent()) |
| 415 return true; | 440 return true; |
| 416 DLOG(ERROR) << "Context lost because MakeCurrent failed."; | 441 DLOG(ERROR) << "Context lost because MakeCurrent failed."; |
| 417 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); | 442 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); |
| 418 command_buffer_->SetParseError(gpu::error::kLostContext); | 443 command_buffer_->SetParseError(gpu::error::kLostContext); |
| 419 CheckContextLost(); | 444 CheckContextLost(); |
| 420 return false; | 445 return false; |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1180 result)); | 1205 result)); |
| 1181 } | 1206 } |
| 1182 | 1207 |
| 1183 void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase, | 1208 void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase, |
| 1184 base::TimeDelta interval) { | 1209 base::TimeDelta interval) { |
| 1185 Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase, | 1210 Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase, |
| 1186 interval)); | 1211 interval)); |
| 1187 } | 1212 } |
| 1188 | 1213 |
| 1189 } // namespace content | 1214 } // namespace content |
| OLD | NEW |