| 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..e8c2704aacfb3dd4ace05a17edcca3752b75bd3f 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());
|
| + should_handle_swapbuffer_msgs_immediate =
|
| + matched_messages_num > 0 && stub;
|
| + } else {
|
| + DCHECK_GT(matched_messages_num, 0u);
|
| + --matched_messages_num;
|
| + if (!stub || 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();
|
|
|