Home | History | Annotate | Download | only in gpu
      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/queue_message_swap_promise.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/memory/scoped_vector.h"
     10 #include "cc/base/swap_promise.h"
     11 #include "content/renderer/gpu/frame_swap_message_queue.h"
     12 #include "content/renderer/gpu/render_widget_compositor.h"
     13 #include "content/renderer/render_widget.h"
     14 #include "content/test/mock_render_process.h"
     15 #include "ipc/ipc_message.h"
     16 #include "ipc/ipc_sync_message_filter.h"
     17 #include "ipc/ipc_test_sink.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace content {
     21 
     22 class TestRenderWidget : public RenderWidget {
     23  public:
     24   using RenderWidget::QueueMessageImpl;
     25 
     26  private:
     27   virtual ~TestRenderWidget() {}
     28 
     29   DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
     30 };
     31 
     32 class TestSyncMessageFilter : public IPC::SyncMessageFilter {
     33  public:
     34   TestSyncMessageFilter() : IPC::SyncMessageFilter(NULL) {}
     35 
     36   virtual bool Send(IPC::Message* message) OVERRIDE {
     37     messages_.push_back(message);
     38     return true;
     39   }
     40 
     41   ScopedVector<IPC::Message>& messages() { return messages_; }
     42 
     43  private:
     44   virtual ~TestSyncMessageFilter() {}
     45 
     46   ScopedVector<IPC::Message> messages_;
     47 
     48   DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter);
     49 };
     50 
     51 struct QueueMessageData {
     52   MessageDeliveryPolicy policy;
     53   bool commit_requested;
     54   int source_frame_number;
     55 };
     56 
     57 class QueueMessageSwapPromiseTest : public testing::Test {
     58  public:
     59   QueueMessageSwapPromiseTest()
     60       : frame_swap_message_queue_(new FrameSwapMessageQueue()),
     61         sync_message_filter_(new TestSyncMessageFilter()) {}
     62 
     63   virtual ~QueueMessageSwapPromiseTest() {}
     64 
     65   scoped_ptr<cc::SwapPromise> QueueMessageImpl(IPC::Message* msg,
     66                                                MessageDeliveryPolicy policy,
     67                                                bool commit_requested,
     68                                                int source_frame_number) {
     69     return TestRenderWidget::QueueMessageImpl(msg,
     70                                               policy,
     71                                               frame_swap_message_queue_.get(),
     72                                               sync_message_filter_,
     73                                               commit_requested,
     74                                               source_frame_number).Pass();
     75   }
     76 
     77   ScopedVector<IPC::Message>& DirectSendMessages() {
     78     return sync_message_filter_->messages();
     79   }
     80 
     81   ScopedVector<IPC::Message>& NextSwapMessages() {
     82     next_swap_messages_.clear();
     83     scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
     84         frame_swap_message_queue_->AcquireSendMessageScope();
     85     frame_swap_message_queue_->DrainMessages(&next_swap_messages_);
     86     return next_swap_messages_;
     87   }
     88 
     89   bool ContainsMessage(const ScopedVector<IPC::Message>& messages,
     90                        const IPC::Message& message) {
     91     if (messages.empty())
     92       return false;
     93     for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
     94          i != messages.end();
     95          ++i) {
     96       if ((*i)->type() == message.type())
     97         return true;
     98     }
     99     return false;
    100   }
    101 
    102   bool NextSwapHasMessage(const IPC::Message& message) {
    103     return ContainsMessage(NextSwapMessages(), message);
    104   }
    105 
    106   void QueueMessages(QueueMessageData data[], size_t count) {
    107     for (size_t i = 0; i < count; ++i) {
    108       messages_.push_back(
    109           IPC::Message(0, i + 1, IPC::Message::PRIORITY_NORMAL));
    110       promises_.push_back(
    111           QueueMessageImpl(new IPC::Message(messages_[i]),
    112                            data[i].policy,
    113                            data[i].commit_requested,
    114                            data[i].source_frame_number).release());
    115     }
    116   }
    117 
    118   void CleanupPromises() {
    119     for (ScopedVector<cc::SwapPromise>::iterator i = promises_.begin();
    120          i != promises_.end();
    121          ++i) {
    122       if (*i)
    123         (*i)->DidSwap(NULL);
    124     }
    125   }
    126 
    127  protected:
    128   void VisualStateSwapPromiseDidNotSwap(
    129       cc::SwapPromise::DidNotSwapReason reason);
    130 
    131   scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
    132   scoped_refptr<TestSyncMessageFilter> sync_message_filter_;
    133   std::vector<IPC::Message> messages_;
    134   ScopedVector<cc::SwapPromise> promises_;
    135 
    136  private:
    137   ScopedVector<IPC::Message> next_swap_messages_;
    138 
    139   DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest);
    140 };
    141 
    142 TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) {
    143   QueueMessageData data[] = {
    144     /* { policy, commit_requested, source_frame_number } */
    145     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    146   };
    147   QueueMessages(data, arraysize(data));
    148 
    149   ASSERT_TRUE(promises_[0]);
    150   EXPECT_TRUE(DirectSendMessages().empty());
    151   EXPECT_FALSE(frame_swap_message_queue_->Empty());
    152   EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
    153 
    154   CleanupPromises();
    155 }
    156 
    157 TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyNeedsAtMostOnePromise) {
    158   QueueMessageData data[] = {
    159     /* { policy, commit_requested, source_frame_number } */
    160     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    161     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    162   };
    163   QueueMessages(data, arraysize(data));
    164 
    165   ASSERT_TRUE(promises_[0]);
    166   ASSERT_FALSE(promises_[1]);
    167 
    168   CleanupPromises();
    169 }
    170 
    171 TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnNoUpdate) {
    172   QueueMessageData data[] = {
    173     /* { policy, commit_requested, source_frame_number } */
    174     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    175   };
    176   QueueMessages(data, arraysize(data));
    177 
    178   promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
    179   EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
    180   EXPECT_TRUE(NextSwapMessages().empty());
    181   EXPECT_TRUE(frame_swap_message_queue_->Empty());
    182 }
    183 
    184 TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnSwapFails) {
    185   QueueMessageData data[] = {
    186     /* { policy, commit_requested, source_frame_number } */
    187     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    188   };
    189   QueueMessages(data, arraysize(data));
    190 
    191   promises_[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS);
    192   EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
    193   EXPECT_TRUE(NextSwapMessages().empty());
    194   EXPECT_TRUE(frame_swap_message_queue_->Empty());
    195 }
    196 
    197 TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyRetainsMessageOnCommitFails) {
    198   QueueMessageData data[] = {
    199     /* { policy, commit_requested, source_frame_number } */
    200     {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
    201   };
    202   QueueMessages(data, arraysize(data));
    203 
    204   promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS);
    205   EXPECT_TRUE(DirectSendMessages().empty());
    206   EXPECT_FALSE(frame_swap_message_queue_->Empty());
    207   EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
    208 }
    209 
    210 TEST_F(QueueMessageSwapPromiseTest, VisualStateDirectSend) {
    211   QueueMessageData data[] = {
    212     /* { policy, commit_requested, source_frame_number } */
    213     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
    214   };
    215   QueueMessages(data, arraysize(data));
    216 
    217   ASSERT_FALSE(promises_[0]);
    218   EXPECT_FALSE(DirectSendMessages().empty());
    219   EXPECT_TRUE(frame_swap_message_queue_->Empty());
    220   EXPECT_TRUE(NextSwapMessages().empty());
    221 }
    222 
    223 TEST_F(QueueMessageSwapPromiseTest,
    224        VisualStateQueuesMessageWhenCommitRequested) {
    225   QueueMessageData data[] = {
    226     /* { policy, commit_requested, source_frame_number } */
    227     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
    228   };
    229   QueueMessages(data, arraysize(data));
    230 
    231   ASSERT_TRUE(promises_[0]);
    232   EXPECT_TRUE(DirectSendMessages().empty());
    233   EXPECT_FALSE(frame_swap_message_queue_->Empty());
    234   EXPECT_TRUE(NextSwapMessages().empty());
    235 
    236   CleanupPromises();
    237 }
    238 
    239 TEST_F(QueueMessageSwapPromiseTest,
    240        VisualStateQueuesMessageWhenOtherMessageAlreadyQueued) {
    241   QueueMessageData data[] = {
    242     /* { policy, commit_requested, source_frame_number } */
    243     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
    244     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
    245   };
    246   QueueMessages(data, arraysize(data));
    247 
    248   EXPECT_TRUE(DirectSendMessages().empty());
    249   EXPECT_FALSE(frame_swap_message_queue_->Empty());
    250   EXPECT_FALSE(NextSwapHasMessage(messages_[1]));
    251 
    252   CleanupPromises();
    253 }
    254 
    255 TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidSwap) {
    256   QueueMessageData data[] = {
    257     /* { policy, commit_requested, source_frame_number } */
    258     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
    259     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
    260     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 2},
    261   };
    262   QueueMessages(data, arraysize(data));
    263 
    264   promises_[0]->DidSwap(NULL);
    265   ASSERT_FALSE(promises_[1]);
    266   ScopedVector<IPC::Message> messages;
    267   messages.swap(NextSwapMessages());
    268   EXPECT_EQ(2u, messages.size());
    269   EXPECT_TRUE(ContainsMessage(messages, messages_[0]));
    270   EXPECT_TRUE(ContainsMessage(messages, messages_[1]));
    271   EXPECT_FALSE(ContainsMessage(messages, messages_[2]));
    272 
    273   promises_[2]->DidSwap(NULL);
    274   messages.swap(NextSwapMessages());
    275   EXPECT_EQ(1u, messages.size());
    276   EXPECT_TRUE(ContainsMessage(messages, messages_[2]));
    277 
    278   EXPECT_TRUE(DirectSendMessages().empty());
    279   EXPECT_TRUE(NextSwapMessages().empty());
    280   EXPECT_TRUE(frame_swap_message_queue_->Empty());
    281 }
    282 
    283 void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
    284     cc::SwapPromise::DidNotSwapReason reason) {
    285   QueueMessageData data[] = {
    286     /* { policy, commit_requested, source_frame_number } */
    287     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
    288     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
    289     {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 2},
    290   };
    291   QueueMessages(data, arraysize(data));
    292 
    293   promises_[0]->DidNotSwap(reason);
    294   ASSERT_FALSE(promises_[1]);
    295   EXPECT_TRUE(NextSwapMessages().empty());
    296   EXPECT_EQ(2u, DirectSendMessages().size());
    297   EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
    298   EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[1]));
    299   EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_[2]));
    300 
    301   promises_[2]->DidNotSwap(reason);
    302   EXPECT_TRUE(NextSwapMessages().empty());
    303   EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[2]));
    304 
    305   EXPECT_TRUE(NextSwapMessages().empty());
    306   EXPECT_TRUE(frame_swap_message_queue_->Empty());
    307 }
    308 
    309 TEST_F(QueueMessageSwapPromiseTest, VisalStateSwapPromiseDidNotSwapNoUpdate) {
    310   VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
    311 }
    312 
    313 TEST_F(QueueMessageSwapPromiseTest,
    314        VisalStateSwapPromiseDidNotSwapCommitFails) {
    315   VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_FAILS);
    316 }
    317 
    318 TEST_F(QueueMessageSwapPromiseTest, VisalStateSwapPromiseDidNotSwapSwapFails) {
    319   VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS);
    320 }
    321 
    322 }  // namespace content
    323