1 // Copyright 2021 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "tests/unittests/wire/WireTest.h"
16
17 #include "dawn_wire/WireClient.h"
18 #include "dawn_wire/WireServer.h"
19
20 using namespace testing;
21 using namespace dawn_wire;
22
23 class WireInjectSwapChainTests : public WireTest {
24 public:
WireInjectSwapChainTests()25 WireInjectSwapChainTests() {
26 }
27 ~WireInjectSwapChainTests() override = default;
28 };
29
30 // Test that reserving and injecting a swapchain makes calls on the client object forward to the
31 // server object correctly.
TEST_F(WireInjectSwapChainTests, CallAfterReserveInject)32 TEST_F(WireInjectSwapChainTests, CallAfterReserveInject) {
33 ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
34
35 WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
36 EXPECT_CALL(api, SwapChainReference(apiSwapchain));
37 ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
38 reservation.generation, reservation.deviceId,
39 reservation.deviceGeneration));
40
41 wgpuSwapChainPresent(reservation.swapchain);
42 EXPECT_CALL(api, SwapChainPresent(apiSwapchain));
43 FlushClient();
44 }
45
46 // Test that reserve correctly returns different IDs each time.
TEST_F(WireInjectSwapChainTests, ReserveDifferentIDs)47 TEST_F(WireInjectSwapChainTests, ReserveDifferentIDs) {
48 ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device);
49 ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device);
50
51 ASSERT_NE(reservation1.id, reservation2.id);
52 ASSERT_NE(reservation1.swapchain, reservation2.swapchain);
53 }
54
55 // Test that injecting the same id without a destroy first fails.
TEST_F(WireInjectSwapChainTests, InjectExistingID)56 TEST_F(WireInjectSwapChainTests, InjectExistingID) {
57 ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
58
59 WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
60 EXPECT_CALL(api, SwapChainReference(apiSwapchain));
61 ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
62 reservation.generation, reservation.deviceId,
63 reservation.deviceGeneration));
64
65 // ID already in use, call fails.
66 ASSERT_FALSE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
67 reservation.generation, reservation.deviceId,
68 reservation.deviceGeneration));
69 }
70
71 // Test that the server only borrows the swapchain and does a single reference-release
TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime)72 TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime) {
73 ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
74
75 // Injecting the swapchain adds a reference
76 WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
77 EXPECT_CALL(api, SwapChainReference(apiSwapchain));
78 ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
79 reservation.generation, reservation.deviceId,
80 reservation.deviceGeneration));
81
82 // Releasing the swapchain removes a single reference.
83 wgpuSwapChainRelease(reservation.swapchain);
84 EXPECT_CALL(api, SwapChainRelease(apiSwapchain));
85 FlushClient();
86
87 // Deleting the server doesn't release a second reference.
88 DeleteServer();
89 Mock::VerifyAndClearExpectations(&api);
90 }
91
92 // Test that a swapchain reservation can be reclaimed. This is necessary to
93 // avoid leaking ObjectIDs for reservations that are never injected.
TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation)94 TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation) {
95 // Test that doing a reservation and full release is an error.
96 {
97 ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
98 wgpuSwapChainRelease(reservation.swapchain);
99 FlushClient(false);
100 }
101
102 // Test that doing a reservation and then reclaiming it recycles the ID.
103 {
104 ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device);
105 GetWireClient()->ReclaimSwapChainReservation(reservation1);
106
107 ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device);
108
109 // The ID is the same, but the generation is still different.
110 ASSERT_EQ(reservation1.id, reservation2.id);
111 ASSERT_NE(reservation1.generation, reservation2.generation);
112
113 // No errors should occur.
114 FlushClient();
115 }
116 }
117