Commit c4c12c1d authored by hongbo.min's avatar hongbo.min Committed by Commit bot

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, it should always
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.

BUG=407529

Review URL: https://codereview.chromium.org/495313003

Cr-Commit-Position: refs/heads/master@{#292768}
parent a3b92cfc
......@@ -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();
......
......@@ -167,6 +167,12 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
// Decrement the count of unhandled IPC messages and defer preemption.
void MessageProcessed();
// Try to match the messages pattern for GL SwapBuffers operation in the
// deferred message queue starting from the current processing message.
// Return the number of messages that matches the given pattern, e.g.
// SetLatencyInfo -> AsyncFlush -> Echo sequence.
size_t MatchSwapBufferMessagesPattern(IPC::Message* current_message);
// The lifetime of objects of this class is managed by a GpuChannelManager.
// The GpuChannelManager destroy all the GpuChannels that they own when they
// are destroyed. So a raw pointer is safe.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment