1 // Copyright 2020 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 "components/viz/service/display_embedder/software_output_device_win.h"
6
7 #include "base/memory/unsafe_shared_memory_region.h"
8 #include "base/test/gmock_callback_support.h"
9 #include "components/viz/common/resources/resource_sizes.h"
10 #include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 using base::test::RunOnceClosure;
15 using testing::_;
16
17 namespace viz {
18 namespace {
19
20 constexpr gfx::Size kDefaultSize(100, 100);
21
22 class MockLayeredWindowUpdater : public mojom::LayeredWindowUpdater {
23 public:
24 MockLayeredWindowUpdater() = default;
25 ~MockLayeredWindowUpdater() override = default;
26
BindNewPipeAndPassRemote()27 mojo::PendingRemote<mojom::LayeredWindowUpdater> BindNewPipeAndPassRemote() {
28 return receiver_.BindNewPipeAndPassRemote();
29 }
30
FlushForTesting()31 void FlushForTesting() { receiver_.FlushForTesting(); }
32
33 // mojom::LayeredWindowUpdater implementation.
34 MOCK_METHOD(void,
35 OnAllocatedSharedMemory,
36 (const gfx::Size& size,
37 base::UnsafeSharedMemoryRegion memory_region),
38 (override));
39 MOCK_METHOD(void, Draw, (DrawCallback), (override));
40
41 private:
42 mojo::Receiver<mojom::LayeredWindowUpdater> receiver_{this};
43 };
44
45 } // namespace
46
47 class SoftwareOutputDeviceWinProxyTest : public testing::Test {
48 public:
SoftwareOutputDeviceWinProxyTest()49 SoftwareOutputDeviceWinProxyTest()
50 : device_(0, updater_.BindNewPipeAndPassRemote()) {}
51
SetUp()52 void SetUp() override {
53 // Check that calling Resize() results in the allocation of shared memory
54 // and triggers the OnAllocatedSharedMemory() IPC.
55 EXPECT_CALL(updater_, OnAllocatedSharedMemory(kDefaultSize, _))
56 .WillOnce(
57 testing::WithArg<1>([](base::UnsafeSharedMemoryRegion region) {
58 EXPECT_TRUE(region.IsValid());
59 size_t required_bytes = ResourceSizes::CheckedSizeInBytes<size_t>(
60 kDefaultSize, ResourceFormat::RGBA_8888);
61 EXPECT_GE(region.GetSize(), required_bytes);
62 }));
63 device_.Resize(kDefaultSize, 1.0f);
64 updater_.FlushForTesting();
65 testing::Mock::VerifyAndClearExpectations(&updater_);
66 }
67
68 protected:
69 MockLayeredWindowUpdater updater_;
70 SoftwareOutputDeviceWinProxy device_;
71 };
72
TEST_F(SoftwareOutputDeviceWinProxyTest,DrawWithSwap)73 TEST_F(SoftwareOutputDeviceWinProxyTest, DrawWithSwap) {
74 // Verify that calling BeginPaint() then EndPaint() triggers the Draw() IPC
75 // and then run the DrawCallback.
76 device_.BeginPaint(gfx::Rect(kDefaultSize));
77 EXPECT_CALL(updater_, Draw(_)).WillOnce(RunOnceClosure<0>());
78 device_.EndPaint();
79 updater_.FlushForTesting();
80 testing::Mock::VerifyAndClearExpectations(&updater_);
81
82 // OnSwapBuffers() is called before DrawAck() so the swap buffers callback
83 // shouldn't run yet.
84 bool called = false;
85 device_.OnSwapBuffers(base::BindOnce(
86 [](bool* val, const gfx::Size& size) { *val = true; }, &called));
87 EXPECT_FALSE(called);
88
89 // Verify that DrawAck() runs the swap buffers callback.
90 updater_.FlushForTesting();
91 EXPECT_TRUE(called);
92 }
93
TEST_F(SoftwareOutputDeviceWinProxyTest,DrawNoSwap)94 TEST_F(SoftwareOutputDeviceWinProxyTest, DrawNoSwap) {
95 // Verify that calling BeginPaint() then EndPaint() triggers the Draw() IPC
96 // and then run the DrawCallback.
97 device_.BeginPaint(gfx::Rect(kDefaultSize));
98 EXPECT_CALL(updater_, Draw(_)).WillOnce(RunOnceClosure<0>());
99 device_.EndPaint();
100 updater_.FlushForTesting();
101 testing::Mock::VerifyAndClearExpectations(&updater_);
102
103 // DrawAck() will be triggered after this second flush when the IPC response
104 // arrives. OnSwapBuffers() was never called which is allowed.
105 updater_.FlushForTesting();
106 }
107
108 } // namespace viz
109