1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/gpu/frame_swap_message_queue.h" 6 7 #include <limits> 8 9 #include "base/containers/hash_tables.h" 10 #include "base/logging.h" 11 #include "base/stl_util.h" 12 #include "ipc/ipc_message.h" 13 14 using std::vector; 15 16 namespace content { 17 18 class FrameSwapMessageSubQueue { 19 public: 20 FrameSwapMessageSubQueue() {} 21 virtual ~FrameSwapMessageSubQueue() {} 22 virtual bool Empty() const = 0; 23 virtual void QueueMessage(int source_frame_number, 24 scoped_ptr<IPC::Message> msg, 25 bool* is_first) = 0; 26 virtual void DrainMessages(int source_frame_number, 27 ScopedVector<IPC::Message>* messages) = 0; 28 29 private: 30 DISALLOW_COPY_AND_ASSIGN(FrameSwapMessageSubQueue); 31 }; 32 33 namespace { 34 35 // Queue specific to MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE. 36 class SendMessageScopeImpl : public FrameSwapMessageQueue::SendMessageScope { 37 public: 38 SendMessageScopeImpl(base::Lock* lock) : auto_lock_(*lock) {} 39 virtual ~SendMessageScopeImpl() OVERRIDE {} 40 41 private: 42 base::AutoLock auto_lock_; 43 }; 44 45 class VisualStateQueue : public FrameSwapMessageSubQueue { 46 public: 47 VisualStateQueue() {} 48 49 virtual ~VisualStateQueue() { 50 for (VisualStateQueueMap::iterator i = queue_.begin(); i != queue_.end(); 51 i++) { 52 STLDeleteElements(&i->second); 53 } 54 } 55 56 virtual bool Empty() const OVERRIDE { return queue_.empty(); } 57 58 virtual void QueueMessage(int source_frame_number, 59 scoped_ptr<IPC::Message> msg, 60 bool* is_first) OVERRIDE { 61 if (is_first) 62 *is_first = (queue_.count(source_frame_number) == 0); 63 64 queue_[source_frame_number].push_back(msg.release()); 65 } 66 67 virtual void DrainMessages(int source_frame_number, 68 ScopedVector<IPC::Message>* messages) OVERRIDE { 69 VisualStateQueueMap::iterator end = queue_.upper_bound(source_frame_number); 70 for (VisualStateQueueMap::iterator i = queue_.begin(); i != end; i++) { 71 DCHECK(i->first <= source_frame_number); 72 messages->insert(messages->end(), i->second.begin(), i->second.end()); 73 i->second.clear(); 74 } 75 queue_.erase(queue_.begin(), end); 76 } 77 78 private: 79 typedef std::map<int, std::vector<IPC::Message*> > VisualStateQueueMap; 80 VisualStateQueueMap queue_; 81 82 DISALLOW_COPY_AND_ASSIGN(VisualStateQueue); 83 }; 84 85 // Queue specific to MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP. 86 class SwapQueue : public FrameSwapMessageSubQueue { 87 public: 88 SwapQueue() {} 89 virtual bool Empty() const OVERRIDE { return queue_.empty(); } 90 91 virtual void QueueMessage(int source_frame_number, 92 scoped_ptr<IPC::Message> msg, 93 bool* is_first) OVERRIDE { 94 if (is_first) 95 *is_first = Empty(); 96 queue_.push_back(msg.release()); 97 } 98 99 virtual void DrainMessages(int source_frame_number, 100 ScopedVector<IPC::Message>* messages) OVERRIDE { 101 messages->insert(messages->end(), queue_.begin(), queue_.end()); 102 queue_.weak_clear(); 103 } 104 105 private: 106 ScopedVector<IPC::Message> queue_; 107 108 DISALLOW_COPY_AND_ASSIGN(SwapQueue); 109 }; 110 111 } // namespace 112 113 FrameSwapMessageQueue::FrameSwapMessageQueue() 114 : visual_state_queue_(new VisualStateQueue()), 115 swap_queue_(new SwapQueue()) { 116 } 117 118 FrameSwapMessageQueue::~FrameSwapMessageQueue() { 119 } 120 121 bool FrameSwapMessageQueue::Empty() const { 122 base::AutoLock lock(lock_); 123 return next_drain_messages_.empty() && visual_state_queue_->Empty() && 124 swap_queue_->Empty(); 125 } 126 127 FrameSwapMessageSubQueue* FrameSwapMessageQueue::GetSubQueue( 128 MessageDeliveryPolicy policy) { 129 switch (policy) { 130 case MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP: 131 return swap_queue_.get(); 132 break; 133 case MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE: 134 return visual_state_queue_.get(); 135 break; 136 } 137 NOTREACHED(); 138 return NULL; 139 } 140 141 void FrameSwapMessageQueue::QueueMessageForFrame(MessageDeliveryPolicy policy, 142 int source_frame_number, 143 scoped_ptr<IPC::Message> msg, 144 bool* is_first) { 145 base::AutoLock lock(lock_); 146 GetSubQueue(policy)->QueueMessage(source_frame_number, msg.Pass(), is_first); 147 } 148 149 void FrameSwapMessageQueue::DidSwap(int source_frame_number) { 150 base::AutoLock lock(lock_); 151 152 visual_state_queue_->DrainMessages(source_frame_number, 153 &next_drain_messages_); 154 } 155 156 void FrameSwapMessageQueue::DidNotSwap(int source_frame_number, 157 cc::SwapPromise::DidNotSwapReason reason, 158 ScopedVector<IPC::Message>* messages) { 159 base::AutoLock lock(lock_); 160 switch (reason) { 161 case cc::SwapPromise::SWAP_FAILS: 162 case cc::SwapPromise::COMMIT_NO_UPDATE: 163 swap_queue_->DrainMessages(source_frame_number, messages); 164 // fallthrough 165 case cc::SwapPromise::COMMIT_FAILS: 166 visual_state_queue_->DrainMessages(source_frame_number, messages); 167 break; 168 default: 169 NOTREACHED(); 170 } 171 } 172 173 void FrameSwapMessageQueue::DrainMessages( 174 ScopedVector<IPC::Message>* messages) { 175 lock_.AssertAcquired(); 176 177 swap_queue_->DrainMessages(0, messages); 178 messages->insert(messages->end(), 179 next_drain_messages_.begin(), 180 next_drain_messages_.end()); 181 next_drain_messages_.weak_clear(); 182 } 183 184 scoped_ptr<FrameSwapMessageQueue::SendMessageScope> 185 FrameSwapMessageQueue::AcquireSendMessageScope() { 186 return make_scoped_ptr(new SendMessageScopeImpl(&lock_)) 187 .PassAs<SendMessageScope>(); 188 } 189 190 // static 191 void FrameSwapMessageQueue::TransferMessages(ScopedVector<IPC::Message>& source, 192 vector<IPC::Message>* dest) { 193 for (vector<IPC::Message*>::iterator i = source.begin(); i != source.end(); 194 ++i) { 195 IPC::Message* m(*i); 196 dest->push_back(*m); 197 delete m; 198 } 199 source.weak_clear(); 200 } 201 202 } // namespace content 203