| 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
|
|
|