Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(434)

Side by Side Diff: services/ui/ws/frame_generator_unittest.cc

Issue 2755573002: Add FrameGenerator Unit Tests (Closed)
Patch Set: FrameGenerator ignores MISSED BeginFrameArgs Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « services/ui/ws/frame_generator.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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 "services/ui/ws/frame_generator.h"
6
7 #include "base/macros.h"
8 #include "cc/output/compositor_frame_sink.h"
9 #include "cc/scheduler/begin_frame_source.h"
10 #include "cc/test/begin_frame_args_test.cc"
11 #include "cc/test/fake_external_begin_frame_source.h"
12 #include "services/ui/ws/frame_generator_delegate.h"
13 #include "services/ui/ws/server_window.h"
14 #include "services/ui/ws/server_window_delegate.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace ui {
18 namespace ws {
19 namespace test {
20
21 class TestFrameGeneratorDelegate : public FrameGeneratorDelegate {
22 public:
23 TestFrameGeneratorDelegate() {}
24 ~TestFrameGeneratorDelegate() override {}
25
26 // FrameGeneratorDelegate implementation:
27 bool IsInHighContrastMode() override { return false; }
28 };
29
30 class TestServerWindowDelegate : public ServerWindowDelegate {
31 public:
32 TestServerWindowDelegate() {}
33 ~TestServerWindowDelegate() override {}
34
35 // ServerWindowDelegate implementation:
36 cc::mojom::DisplayCompositor* GetDisplayCompositor() override {
37 return nullptr;
38 }
39
40 ServerWindow* GetRootWindow(const ServerWindow* window) override {
41 return nullptr;
42 }
43 };
44
45 // FakeCompositorFrameSink observes a FakeExternalBeginFrameSource and receives
46 // CompositorFrame from a FrameGenerator.
47 class FakeCompositorFrameSink : public cc::CompositorFrameSink,
48 public cc::BeginFrameObserver,
49 public cc::ExternalBeginFrameSourceClient {
50 public:
51 FakeCompositorFrameSink()
52 : cc::CompositorFrameSink(nullptr, nullptr, nullptr, nullptr) {}
53
54 // cc::CompositorFrameSink implementation:
55 bool BindToClient(cc::CompositorFrameSinkClient* client) override {
56 if (!cc::CompositorFrameSink::BindToClient(client))
57 return false;
58
59 external_begin_frame_source_ =
60 base::MakeUnique<cc::ExternalBeginFrameSource>(this);
61 client_->SetBeginFrameSource(external_begin_frame_source_.get());
62 return true;
63 }
64
65 void DetachFromClient() override {
66 cc::CompositorFrameSink::DetachFromClient();
67 }
68
69 void SubmitCompositorFrame(cc::CompositorFrame frame) override {
70 ++number_frames_received_;
71 last_frame_ = std::move(frame);
72 }
73
74 // cc::BeginFrameObserver implementation.
75 void OnBeginFrame(const cc::BeginFrameArgs& args) override {
76 external_begin_frame_source_->OnBeginFrame(args);
77 last_begin_frame_args_ = args;
78 }
79
80 const cc::BeginFrameArgs& LastUsedBeginFrameArgs() const override {
81 return last_begin_frame_args_;
82 }
83
84 void OnBeginFrameSourcePausedChanged(bool paused) override {}
85
86 // cc::ExternalBeginFrameSourceClient implementation:
87 void OnNeedsBeginFrames(bool needs_begin_frames) override {
88 needs_begin_frames_ = needs_begin_frames;
89 UpdateNeedsBeginFramesInternal();
90 }
91
92 void OnDidFinishFrame(const cc::BeginFrameAck& ack) override {
93 external_begin_frame_source_->DidFinishFrame(this, ack);
94 }
95
96 void SetBeginFrameSource(cc::BeginFrameSource* source) {
97 if (begin_frame_source_ && observing_begin_frames_) {
98 begin_frame_source_->RemoveObserver(this);
99 observing_begin_frames_ = false;
100 }
101 begin_frame_source_ = source;
102 UpdateNeedsBeginFramesInternal();
103 }
104
105 const cc::CompositorFrame& last_frame() { return last_frame_; }
106
107 int number_frames_received() { return number_frames_received_; }
108
109 private:
110 void UpdateNeedsBeginFramesInternal() {
111 if (!begin_frame_source_)
112 return;
113
114 if (needs_begin_frames_ == observing_begin_frames_)
115 return;
116
117 observing_begin_frames_ = needs_begin_frames_;
118 if (needs_begin_frames_) {
119 begin_frame_source_->AddObserver(this);
120 } else {
121 begin_frame_source_->RemoveObserver(this);
122 }
123 }
124
125 int number_frames_received_ = 0;
126 std::unique_ptr<cc::ExternalBeginFrameSource> external_begin_frame_source_;
127 cc::BeginFrameSource* begin_frame_source_ = nullptr;
128 cc::BeginFrameArgs last_begin_frame_args_;
129 cc::CompositorFrame last_frame_;
130 bool observing_begin_frames_ = false;
131 bool needs_begin_frames_ = false;
132 };
133
134 class FrameGeneratorTest : public testing::Test {
135 public:
136 FrameGeneratorTest() {}
137 ~FrameGeneratorTest() override {}
138
139 // testing::Test overrides:
140 void SetUp() override {
141 testing::Test::SetUp();
142
143 std::unique_ptr<FakeCompositorFrameSink> compositor_frame_sink =
144 base::MakeUnique<FakeCompositorFrameSink>();
145 compositor_frame_sink_ = compositor_frame_sink.get();
146
147 constexpr float kRefreshRate = 0.f;
148 constexpr bool kTickAutomatically = false;
149 begin_frame_source_ = base::MakeUnique<cc::FakeExternalBeginFrameSource>(
150 kRefreshRate, kTickAutomatically);
151 compositor_frame_sink_->SetBeginFrameSource(begin_frame_source_.get());
152 delegate_ = base::MakeUnique<TestFrameGeneratorDelegate>();
153 server_window_delegate_ = base::MakeUnique<TestServerWindowDelegate>();
154 root_window_ = base::MakeUnique<ServerWindow>(server_window_delegate_.get(),
155 WindowId());
156 root_window_->SetVisible(true);
157 frame_generator_ = base::MakeUnique<FrameGenerator>(
158 delegate_.get(), root_window_.get(), std::move(compositor_frame_sink));
159 };
160
161 int NumberOfFramesReceived() {
162 return compositor_frame_sink_->number_frames_received();
163 }
164
165 void IssueBeginFrame() {
166 begin_frame_source_->TestOnBeginFrame(cc::CreateBeginFrameArgsForTesting(
167 BEGINFRAME_FROM_HERE, 0, next_sequence_number_));
168 ++next_sequence_number_;
169 }
170
171 FrameGenerator* frame_generator() { return frame_generator_.get(); }
172
173 const cc::SurfaceId& id_last_frame() {
174 return compositor_frame_sink_->last_frame()
175 .metadata.referenced_surfaces.front();
176 }
177
178 private:
179 FakeCompositorFrameSink* compositor_frame_sink_ = nullptr;
180 std::unique_ptr<cc::FakeExternalBeginFrameSource> begin_frame_source_;
181 std::unique_ptr<TestFrameGeneratorDelegate> delegate_;
182 std::unique_ptr<TestServerWindowDelegate> server_window_delegate_;
183 std::unique_ptr<ServerWindow> root_window_;
184 std::unique_ptr<FrameGenerator> frame_generator_;
185 int next_sequence_number_ = 1;
186
187 DISALLOW_COPY_AND_ASSIGN(FrameGeneratorTest);
188 };
189
190 TEST_F(FrameGeneratorTest, OnSurfaceCreated) {
191 DCHECK_EQ(0, NumberOfFramesReceived());
192
193 // FrameGenerator does not request BeginFrames upon creation.
194 IssueBeginFrame();
195 EXPECT_EQ(0, NumberOfFramesReceived());
196
197 const cc::SurfaceId kArbitrarySurfaceId(
198 cc::FrameSinkId(1, 1),
199 cc::LocalSurfaceId(1, base::UnguessableToken::Create()));
200 const cc::SurfaceInfo kArbitrarySurfaceInfo(kArbitrarySurfaceId, 1.0f,
201 gfx::Size(100, 100));
202 frame_generator()->OnSurfaceCreated(kArbitrarySurfaceInfo);
203 // FrameGenerator gets the missed BeginFrame when AddObserver() is called.
204 EXPECT_EQ(0, NumberOfFramesReceived());
brianderson 2017/03/16 20:46:07 @staraz mentioned this is 1 when MISSED frames are
205
206 IssueBeginFrame();
207 EXPECT_EQ(1, NumberOfFramesReceived());
brianderson 2017/03/16 20:46:07 @staraz mentioned this is 2 when MISSED frames are
Alex Z. 2017/03/16 20:52:16 We got 2 here because in FrameGenerator::SetNeedsB
Fady Samuel 2017/03/16 21:06:35 Ohh, yea, that's a bug. I think you're right. We s
Alex Z. 2017/03/17 13:50:43 Done.
208
209 // Verify that the CompositorFrame refers to the window manager's surface via
210 // referenced_surfaces.
211 cc::SurfaceId id = id_last_frame();
212 EXPECT_EQ(kArbitrarySurfaceId, id);
213
214 // FrameGenerator stops requesting BeginFrames after submitting a
215 // CompositorFrame.
216 IssueBeginFrame();
217 EXPECT_EQ(1, NumberOfFramesReceived());
218 }
219
220 TEST_F(FrameGeneratorTest, SetDeviceScaleFactor) {
221 DCHECK_EQ(0, NumberOfFramesReceived());
222 const cc::SurfaceId kArbitrarySurfaceId(
223 cc::FrameSinkId(1, 1),
224 cc::LocalSurfaceId(1, base::UnguessableToken::Create()));
225 const cc::SurfaceInfo kArbitrarySurfaceInfo(kArbitrarySurfaceId, 1.0f,
226 gfx::Size(100, 100));
227 constexpr float kDefaultScaleFactor = 1.0f;
228 constexpr float kArbitraryScaleFactor = 0.5f;
229
230 // A valid SurfaceInfo is required before setting device scale factor.
231 frame_generator()->OnSurfaceCreated(kArbitrarySurfaceInfo);
232 IssueBeginFrame();
233 DCHECK_EQ(1, NumberOfFramesReceived());
234
235 IssueBeginFrame();
236 DCHECK_EQ(1, NumberOfFramesReceived());
237
238 // FrameGenerator does not request BeginFrames if its device scale factor
239 // remains unchanged.
240 frame_generator()->SetDeviceScaleFactor(kDefaultScaleFactor);
241 IssueBeginFrame();
242 EXPECT_EQ(1, NumberOfFramesReceived());
243
244 frame_generator()->SetDeviceScaleFactor(kArbitraryScaleFactor);
245 IssueBeginFrame();
246 EXPECT_EQ(2, NumberOfFramesReceived());
247 }
248
249 } // namespace test
250 } // namespace ws
251 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/ws/frame_generator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698