1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "FakeComposerClient.h"
20 
21 #include <gui/SurfaceComposerClient.h>
22 
23 #include <hardware/hwcomposer_defs.h>
24 
25 #include <log/log.h>
26 
27 #include <gtest/gtest.h>
28 
29 // clang-format off
30 // Note: This needs to reside in the global namespace for the GTest to use it
31 inline ::std::ostream& operator<<(::std::ostream& os, const hwc_rect_t& rect) {
32     return os << "(" << rect.left << ","
33               << rect.top << ","
34               << rect.right << ","
35               << rect.bottom << ")";
36 }
37 
38 inline ::std::ostream& operator<<(::std::ostream& os, const hwc_frect_t& rect) {
39     return os << "(" << rect.left << ","
40               << rect.top << ","
41               << rect.right << ","
42               << rect.bottom << ")";
43 }
44 // clang-format on
45 
46 namespace sftest {
47 
48 class RenderState;
49 
50 // clang-format off
51 inline bool operator==(const hwc_rect_t& a, const hwc_rect_t& b) {
52     return a.top == b.top &&
53             a.left == b.left &&
54             a.bottom == b.bottom &&
55             a.right == b.right;
56 }
57 
58 inline bool operator==(const hwc_frect_t& a, const hwc_frect_t& b) {
59     return a.top == b.top &&
60             a.left == b.left &&
61             a.bottom == b.bottom &&
62             a.right == b.right;
63 }
64 // clang-format on
65 
66 inline bool operator!=(const hwc_rect_t& a, const hwc_rect_t& b) {
67     return !(a == b);
68 }
69 
70 inline bool operator!=(const hwc_frect_t& a, const hwc_frect_t& b) {
71     return !(a == b);
72 }
73 
74 ::testing::AssertionResult rectsAreSame(const RenderState& ref, const RenderState& val);
75 ::testing::AssertionResult framesAreSame(const std::vector<RenderState>& ref,
76                                          const std::vector<RenderState>& val);
77 
78 void startSurfaceFlinger();
79 void stopSurfaceFlinger();
80 
81 class FakeHwcEnvironment : public ::testing::Environment {
82 public:
~FakeHwcEnvironment()83     virtual ~FakeHwcEnvironment() {}
84     void SetUp() override;
85     void TearDown() override;
86 };
87 
88 /*
89  * All surface state changes are supposed to happen inside a global
90  * transaction. TransactionScope object at the beginning of
91  * scope automates the process. The resulting scope gives a visual cue
92  * on the span of the transaction as well.
93  *
94  * Closing the transaction is synchronous, i.e., it waits for
95  * SurfaceFlinger to composite one frame. Now, the FakeComposerClient
96  * is built to explicitly request vsyncs one at the time. A delayed
97  * request must be made before closing the transaction or the test
98  * thread stalls until SurfaceFlinger does an emergency vsync by
99  * itself. TransactionScope encapsulates this vsync magic.
100  */
101 class TransactionScope : public android::SurfaceComposerClient::Transaction {
102 public:
TransactionScope(FakeComposerClient & composer)103     TransactionScope(FakeComposerClient& composer) :
104             Transaction(),
105             mComposer(composer) {
106     }
107 
~TransactionScope()108     ~TransactionScope() {
109         int frameCount = mComposer.getFrameCount();
110         mComposer.runVSyncAfter(1ms);
111         LOG_ALWAYS_FATAL_IF(android::NO_ERROR != apply());
112         // Make sure that exactly one frame has been rendered.
113         mComposer.waitUntilFrame(frameCount + 1);
114         LOG_ALWAYS_FATAL_IF(frameCount + 1 != mComposer.getFrameCount(),
115                             "Unexpected frame advance. Delta: %d",
116                             mComposer.getFrameCount() - frameCount);
117     }
118 
119     FakeComposerClient& mComposer;
120 };
121 
122 } // namespace sftest
123