Chromium Code Reviews| Index: content/common/gpu/gpu_channel.cc |
| diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc |
| index 0759e5d00f961569894377ec1e49bd3a7d2267fa..1f7974c21aed49c049919d29d67b36d8d6c85fdc 100644 |
| --- a/content/common/gpu/gpu_channel.cc |
| +++ b/content/common/gpu/gpu_channel.cc |
| @@ -662,16 +662,66 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { |
| return handled; |
| } |
| +size_t GpuChannel::MatchSwapBufferMessagesPattern( |
| + IPC::Message* current_message) { |
| + DCHECK(current_message); |
| + if (deferred_messages_.empty() || !current_message) |
| + return 0; |
| + // Only care about SetLatencyInfo and AsyncFlush message. |
| + if (current_message->type() != GpuCommandBufferMsg_SetLatencyInfo::ID && |
| + current_message->type() != GpuCommandBufferMsg_AsyncFlush::ID) |
| + return 0; |
| + |
| + size_t index = 0; |
| + int32 routing_id = current_message->routing_id(); |
| + |
| + // In case of the current message is SetLatencyInfo, we try to look ahead one |
| + // more deferred messages. |
| + IPC::Message *first_message = NULL; |
| + IPC::Message *second_message = NULL; |
| + |
| + // Fetch the first message and move index to point to the second message. |
| + first_message = deferred_messages_[index++]; |
| + |
| + // If the current message is AsyncFlush, the expected message sequence for |
| + // SwapBuffer should be AsyncFlush->Echo. We only try to match Echo message. |
| + if (current_message->type() == GpuCommandBufferMsg_AsyncFlush::ID && |
| + first_message->type() == GpuCommandBufferMsg_Echo::ID && |
| + first_message->routing_id() == routing_id) { |
| + return 1; |
| + } |
| + |
| + // If the current message is SetLatencyInfo, the expected message sequence |
| + // for SwapBuffer should be SetLatencyInfo->AsyncFlush->Echo (optional). |
| + if (current_message->type() == GpuCommandBufferMsg_SetLatencyInfo::ID && |
| + first_message->type() == GpuCommandBufferMsg_AsyncFlush::ID && |
| + first_message->routing_id() == routing_id) { |
| + if (deferred_messages_.size() >= 2) |
| + second_message = deferred_messages_[index]; |
| + if (!second_message) |
| + return 1; |
| + if (second_message->type() == GpuCommandBufferMsg_Echo::ID && |
| + second_message->routing_id() == routing_id) { |
| + return 2; |
| + } |
| + } |
| + // No matched message is found. |
| + return 0; |
| +} |
| + |
| void GpuChannel::HandleMessage() { |
| handle_messages_scheduled_ = false; |
| if (deferred_messages_.empty()) |
| return; |
| - bool should_fast_track_ack = false; |
| - IPC::Message* m = deferred_messages_.front(); |
| - GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id()); |
| + size_t matched_messages_num = 0; |
| + bool should_handle_swapbuffer_msgs_immediate = false; |
| + IPC::Message* m = NULL; |
| + GpuCommandBufferStub* stub = NULL; |
| do { |
| + m = deferred_messages_.front(); |
| + stub = stubs_.Lookup(m->routing_id()); |
| if (stub) { |
| if (!stub->IsScheduled()) |
| return; |
| @@ -715,17 +765,29 @@ void GpuChannel::HandleMessage() { |
| if (message_processed) |
| MessageProcessed(); |
| - // We want the EchoACK following the SwapBuffers to be sent as close as |
| - // possible, avoiding scheduling other channels in the meantime. |
| - should_fast_track_ack = false; |
| - if (!deferred_messages_.empty()) { |
| - m = deferred_messages_.front(); |
| - stub = stubs_.Lookup(m->routing_id()); |
| - should_fast_track_ack = |
| - (m->type() == GpuCommandBufferMsg_Echo::ID) && |
| - stub && stub->IsScheduled(); |
| + if (deferred_messages_.empty()) |
| + break; |
| + |
| + // We process the pending messages immediately if these messages matches |
| + // the pattern of SwapBuffers, for example, GLRenderer always issues |
| + // SwapBuffers calls with a specific IPC message patterns, for example, |
| + // it should be SetLatencyInfo->AsyncFlush->Echo sequence. |
| + // |
| + // Instead of posting a task to message loop, it could avoid the possibility |
| + // of being blocked by other channels, and make SwapBuffers executed as soon |
| + // as possible. |
| + if (!should_handle_swapbuffer_msgs_immediate) { |
| + // Start from the current processing message to match SwapBuffer pattern. |
| + matched_messages_num = MatchSwapBufferMessagesPattern(message.get()); |
|
Ken Russell (switch to Gerrit)
2014/08/26 18:18:55
This isn't the same logic as in the previous patch
Hongbo Min
2014/08/27 01:54:00
Russell, thanks for your time.
On 2014/08/26 18:1
Ken Russell (switch to Gerrit)
2014/08/27 22:16:56
Thanks for pointing that out. I now see that messa
|
| + should_handle_swapbuffer_msgs_immediate = |
| + matched_messages_num > 0 && stub && stub->IsScheduled(); |
|
jbauman
2014/08/27 20:46:41
I don't think you need to check for "stub && stub-
Hongbo Min
2014/08/29 01:11:10
Seems stub->IsScheduled is not needed since the ab
|
| + } else { |
| + DCHECK_GT(matched_messages_num, 0); |
| + --matched_messages_num; |
| + if (!stub || !stub->IsScheduled() || matched_messages_num == 0) |
| + should_handle_swapbuffer_msgs_immediate = false; |
| } |
| - } while (should_fast_track_ack); |
| + } while (should_handle_swapbuffer_msgs_immediate); |
| if (!deferred_messages_.empty()) { |
| OnScheduled(); |