Index: content/common/gpu/client/gpu_channel_host.cc |
diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc |
index a87051af7dff62756f832c1099e98287a02e083f..b637624153c494fa6bb9a324497f7eedde07135a 100644 |
--- a/content/common/gpu/client/gpu_channel_host.cc |
+++ b/content/common/gpu/client/gpu_channel_host.cc |
@@ -35,10 +35,14 @@ base::StaticAtomicSequenceNumber g_next_transfer_buffer_id; |
} // namespace |
GpuChannelHost::StreamFlushInfo::StreamFlushInfo() |
- : flush_pending(false), |
+ : next_stream_flush_id(1), |
+ flushed_stream_flush_id(0), |
+ verified_stream_flush_id(0), |
+ flush_pending(false), |
route_id(MSG_ROUTING_NONE), |
put_offset(0), |
- flush_count(0) {} |
+ flush_count(0), |
+ flush_id(0) {} |
GpuChannelHost::StreamFlushInfo::~StreamFlushInfo() {} |
@@ -127,7 +131,7 @@ bool GpuChannelHost::Send(IPC::Message* msg) { |
return result; |
} |
-void GpuChannelHost::OrderingBarrier( |
+uint32_t GpuChannelHost::OrderingBarrier( |
int32 route_id, |
int32 stream_id, |
int32 put_offset, |
@@ -138,30 +142,38 @@ void GpuChannelHost::OrderingBarrier( |
AutoLock lock(context_lock_); |
StreamFlushInfo& flush_info = stream_flush_info_[stream_id]; |
if (flush_info.flush_pending && flush_info.route_id != route_id) |
- InternalFlush(stream_id); |
+ InternalFlush(&flush_info); |
if (put_offset_changed) { |
+ const uint32_t flush_id = flush_info.next_stream_flush_id++; |
flush_info.flush_pending = true; |
flush_info.route_id = route_id; |
flush_info.put_offset = put_offset; |
flush_info.flush_count = flush_count; |
+ flush_info.flush_id = flush_id; |
flush_info.latency_info.insert(flush_info.latency_info.end(), |
latency_info.begin(), latency_info.end()); |
if (do_flush) |
- InternalFlush(stream_id); |
+ InternalFlush(&flush_info); |
+ |
+ return flush_id; |
} |
+ return 0; |
} |
-void GpuChannelHost::InternalFlush(int32 stream_id) { |
+void GpuChannelHost::InternalFlush(StreamFlushInfo* flush_info) { |
context_lock_.AssertAcquired(); |
- StreamFlushInfo& flush_info = stream_flush_info_[stream_id]; |
- DCHECK(flush_info.flush_pending); |
+ DCHECK(flush_info); |
+ DCHECK(flush_info->flush_pending); |
+ DCHECK_LT(flush_info->flushed_stream_flush_id, flush_info->flush_id); |
Send(new GpuCommandBufferMsg_AsyncFlush( |
- flush_info.route_id, flush_info.put_offset, flush_info.flush_count, |
- flush_info.latency_info)); |
- flush_info.latency_info.clear(); |
- flush_info.flush_pending = false; |
+ flush_info->route_id, flush_info->put_offset, flush_info->flush_count, |
+ flush_info->latency_info)); |
+ flush_info->latency_info.clear(); |
+ flush_info->flush_pending = false; |
+ |
+ flush_info->flushed_stream_flush_id = flush_info->flush_id; |
} |
scoped_ptr<CommandBufferProxyImpl> GpuChannelHost::CreateViewCommandBuffer( |
@@ -290,8 +302,9 @@ void GpuChannelHost::DestroyCommandBuffer( |
RemoveRoute(route_id); |
AutoLock lock(context_lock_); |
- if (stream_flush_info_[stream_id].route_id == route_id) |
- stream_flush_info_.erase(stream_id); |
+ StreamFlushInfo& flush_info = stream_flush_info_[stream_id]; |
+ if (flush_info.flush_pending && flush_info.route_id == route_id) |
+ flush_info.flush_pending = false; |
} |
void GpuChannelHost::DestroyChannel() { |
@@ -384,6 +397,62 @@ int32 GpuChannelHost::GenerateStreamID() { |
return next_stream_id_.GetNext(); |
} |
+uint32_t GpuChannelHost::ValidateFlushIDReachedServer(int32 stream_id) { |
+ // Store what flush ids we will be validating for all streams. |
+ base::hash_map<int32, uint32_t> validate_flushes; |
+ uint32_t flushed_stream_flush_id = 0; |
+ uint32_t verified_stream_flush_id = 0; |
+ { |
+ AutoLock lock(context_lock_); |
+ for (const auto& iter : stream_flush_info_) { |
+ const int32 iter_stream_id = iter.first; |
+ const StreamFlushInfo& flush_info = iter.second; |
+ if (iter_stream_id == stream_id) { |
+ flushed_stream_flush_id = flush_info.flushed_stream_flush_id; |
+ verified_stream_flush_id = flush_info.verified_stream_flush_id; |
+ } |
+ |
+ if (flush_info.flushed_stream_flush_id > |
+ flush_info.verified_stream_flush_id) { |
+ validate_flushes.insert( |
+ std::make_pair(iter_stream_id, flush_info.flushed_stream_flush_id)); |
+ } |
+ } |
+ } |
+ |
+ if (flushed_stream_flush_id == verified_stream_flush_id) { |
+ // Current stream has no unverified flushes. |
+ return verified_stream_flush_id; |
+ } |
+ |
+ if (Send(new GpuChannelMsg_Nop())) { |
+ // Update verified flush id for all streams. |
+ uint32_t highest_flush_id = 0; |
+ AutoLock lock(context_lock_); |
+ for (const auto& iter : validate_flushes) { |
+ const int32 validated_stream_id = iter.first; |
+ const uint32_t validated_flush_id = iter.second; |
+ StreamFlushInfo& flush_info = stream_flush_info_[validated_stream_id]; |
+ if (flush_info.verified_stream_flush_id < validated_flush_id) { |
+ flush_info.verified_stream_flush_id = validated_flush_id; |
+ } |
+ |
+ if (validated_stream_id == stream_id) |
+ highest_flush_id = flush_info.verified_stream_flush_id; |
+ } |
+ |
+ return highest_flush_id; |
+ } |
+ |
+ return 0; |
+} |
+ |
+uint32_t GpuChannelHost::GetHighestValidatedFlushID(int32 stream_id) { |
+ AutoLock lock(context_lock_); |
+ StreamFlushInfo& flush_info = stream_flush_info_[stream_id]; |
+ return flush_info.verified_stream_flush_id; |
+} |
+ |
GpuChannelHost::~GpuChannelHost() { |
#if DCHECK_IS_ON() |
AutoLock lock(context_lock_); |