Index: content/renderer/gpu/frame_update_message_queue.cc |
diff --git a/content/renderer/gpu/frame_update_message_queue.cc b/content/renderer/gpu/frame_update_message_queue.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2990bb5660e4418e608a70195382e6cd8ebb03f3 |
--- /dev/null |
+++ b/content/renderer/gpu/frame_update_message_queue.cc |
@@ -0,0 +1,221 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/renderer/gpu/frame_update_message_queue.h" |
+ |
+#include <limits> |
+ |
+#include "base/containers/hash_tables.h" |
+#include "base/logging.h" |
+#include "base/stl_util.h" |
+#include "ipc/ipc_message.h" |
+ |
+using std::vector; |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+// Queue specific to MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE. |
+class SendMessageScopeImpl : public FrameUpdateMessageQueue::SendMessageScope { |
+ public: |
+ SendMessageScopeImpl(base::Lock* lock) : auto_lock_(*lock) {} |
+ ~SendMessageScopeImpl() override {} |
+ |
+ private: |
+ base::AutoLock auto_lock_; |
+}; |
+ |
+} // namespace |
+ |
+class FrameUpdateMessageSubQueue { |
+ typedef std::vector<IPC::Message*> MessageQueue; |
+ typedef std::map<int, MessageQueue> FrameNumberQueueMap; |
+ |
+ public: |
+ FrameUpdateMessageSubQueue() {} |
+ |
+ ~FrameUpdateMessageSubQueue() { |
+ for (FrameNumberQueueMap::iterator i = queue_.begin(); i != queue_.end(); |
+ i++) { |
+ STLDeleteElements(&i->second); |
+ } |
+ } |
+ |
+ bool Empty() const { |
+ return std::find_if(queue_.begin(), queue_.end(), |
+ [](const FrameNumberQueueMap::value_type& val) -> bool { |
+ return val.second.size() > 0; |
+ }) == queue_.end(); |
+ } |
+ |
+ void QueueMessage(int source_frame_number, |
+ scoped_ptr<IPC::Message> msg, |
+ bool* is_first) { |
+ auto &frame_queue = queue_[source_frame_number]; |
+ if (is_first) |
+ *is_first = frame_queue.size() == 0; |
+ |
+ frame_queue.push_back(msg.release()); |
+ } |
+ |
+ MessageQueue &GetFrameQueue(int source_frame_number) { |
+ return queue_[source_frame_number]; |
+ } |
+ |
+ template <typename out_iter> |
+ void DrainMessages(int source_frame_number, out_iter out) { |
+ FrameNumberQueueMap::iterator end = queue_.upper_bound(source_frame_number); |
+ for (FrameNumberQueueMap::iterator i = queue_.begin(); i != end; i++) { |
+ DCHECK(i->first <= source_frame_number); |
+ std::copy(i->second.begin(), i->second.end(), out); |
+ i->second.clear(); |
+ } |
+ queue_.erase(queue_.begin(), end); |
+ } |
+ |
+ void DrainMessages(int source_frame_number, |
+ ScopedVector<IPC::Message>* messages) { |
+ DrainMessages(source_frame_number, std::back_inserter(*messages)); |
+ } |
+ |
+ private: |
+ FrameNumberQueueMap queue_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FrameUpdateMessageSubQueue); |
+}; |
+ |
+FrameUpdateMessageQueue::FrameUpdateMessageQueue() |
+ : visual_state_queue_(new FrameUpdateMessageSubQueue()), |
+ swap_queue_(new FrameUpdateMessageSubQueue()), |
+ activation_queue_(new FrameUpdateMessageSubQueue()) { |
+} |
+ |
+FrameUpdateMessageQueue::~FrameUpdateMessageQueue() { |
+} |
+ |
+bool FrameUpdateMessageQueue::Empty() const { |
+ base::AutoLock lock(lock_); |
+ return visual_state_queue_->Empty() && swap_queue_->Empty() && |
+ activation_queue_->Empty(); |
+} |
+ |
+FrameUpdateMessageSubQueue* FrameUpdateMessageQueue::GetSubQueue( |
+ MessageDeliveryPolicy policy) { |
+ switch (policy) { |
+ case MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP: |
+ return swap_queue_.get(); |
+ break; |
+ case MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE: |
+ return visual_state_queue_.get(); |
+ break; |
+ case MESSAGE_DELIVERY_POLICY_WITH_ACTIVATION: |
+ return activation_queue_.get(); |
+ break; |
+ } |
+ NOTREACHED(); |
+ return NULL; |
+} |
+ |
+void FrameUpdateMessageQueue::QueueMessageForFrame(MessageDeliveryPolicy policy, |
+ int source_frame_number, |
+ scoped_ptr<IPC::Message> msg, |
+ bool* is_first) { |
+ base::AutoLock lock(lock_); |
+ if (is_first) *is_first = false; |
+ switch (policy) { |
+ case MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP: |
+ swap_queue_->QueueMessage(0, msg.Pass(), is_first); |
+ return; |
+ case MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE: |
+ visual_state_queue_->QueueMessage(source_frame_number, msg.Pass(), is_first); |
+ return; |
+ case MESSAGE_DELIVERY_POLICY_WITH_ACTIVATION: |
+ activation_queue_->QueueMessage(source_frame_number, msg.Pass(), is_first); |
+ return; |
+ } |
+ NOTREACHED(); |
+} |
+ |
+void FrameUpdateMessageQueue::DidSwap(int source_frame_number) { |
+ base::AutoLock lock(lock_); |
+ |
+ visual_state_queue_->DrainMessages( |
+ source_frame_number, std::back_inserter(swap_queue_->GetFrameQueue(0))); |
+} |
+ |
+void FrameUpdateMessageQueue::DidNotSwap(int source_frame_number, |
+ cc::Promise::DidNotSwap::Reason reason, |
+ ScopedVector<IPC::Message>* messages) { |
+ base::AutoLock lock(lock_); |
+ switch (reason) { |
+ case cc::Promise::DidNotSwap::SWAP_FAILS: |
+ case cc::Promise::DidNotSwap::COMMIT_NO_UPDATE: |
+ swap_queue_->DrainMessages(0, messages); |
+ visual_state_queue_->DrainMessages(source_frame_number, messages); |
+ break; |
+ case cc::Promise::DidNotSwap::COMMIT_FAILS: |
+ // Do not queue any responses here. |
+ // If COMMIT_FAILS the renderer is shutting down, which will |
+ // result in the RenderFrameHostImpl destructor firing the |
+ // remaining response callbacks itself. |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+} |
+ |
+void FrameUpdateMessageQueue::DidActivate( |
+ int source_frame_number, |
+ ScopedVector<IPC::Message>* messages) { |
+ base::AutoLock lock(lock_); |
+ activation_queue_->DrainMessages(source_frame_number, messages); |
+} |
+ |
+void FrameUpdateMessageQueue::DidNotActivate( |
+ int source_frame_number, |
+ cc::Promise::DidNotActivate::Reason reason, |
+ ScopedVector<IPC::Message>* messages) { |
+ base::AutoLock lock(lock_); |
+ switch (reason) { |
+ case cc::Promise::DidNotActivate::ACTIVATION_FAILS: |
+ case cc::Promise::DidNotActivate::COMMIT_NO_UPDATE: |
+ activation_queue_->DrainMessages(source_frame_number, messages); |
+ break; |
+ case cc::Promise::DidNotActivate::COMMIT_FAILS: |
+ // Do not queue any responses here. |
+ // If COMMIT_FAILS the renderer is shutting down, which will |
+ // result in the RenderFrameHostImpl destructor firing the |
+ // remaining response callbacks itself. |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+} |
+ |
+void FrameUpdateMessageQueue::DrainMessagesForSwap( |
+ ScopedVector<IPC::Message>* messages) { |
+ lock_.AssertAcquired(); |
+ |
+ swap_queue_->DrainMessages(0, messages); |
+} |
+ |
+scoped_ptr<FrameUpdateMessageQueue::SendMessageScope> |
+FrameUpdateMessageQueue::AcquireSendMessageScope() { |
+ return make_scoped_ptr(new SendMessageScopeImpl(&lock_)); |
+} |
+ |
+// static |
+void FrameUpdateMessageQueue::TransferMessages(ScopedVector<IPC::Message>& source, |
+ vector<IPC::Message>* dest) { |
+ for (vector<IPC::Message*>::iterator i = source.begin(); i != source.end(); |
+ ++i) { |
+ IPC::Message* m(*i); |
+ dest->push_back(*m); |
+ delete m; |
+ } |
+ source.weak_clear(); |
+} |
+ |
+} // namespace content |