Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / cc / surfaces / display_unittest.cc
blob6058f159b22b0e53f84fa45fcaba35285923ffb0
1 // Copyright 2015 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.
5 #include "base/test/null_task_runner.h"
6 #include "cc/output/compositor_frame.h"
7 #include "cc/output/copy_output_result.h"
8 #include "cc/output/delegated_frame_data.h"
9 #include "cc/quads/render_pass.h"
10 #include "cc/resources/shared_bitmap_manager.h"
11 #include "cc/surfaces/display.h"
12 #include "cc/surfaces/display_client.h"
13 #include "cc/surfaces/surface.h"
14 #include "cc/surfaces/surface_factory.h"
15 #include "cc/surfaces/surface_factory_client.h"
16 #include "cc/surfaces/surface_id_allocator.h"
17 #include "cc/surfaces/surface_manager.h"
18 #include "cc/test/fake_output_surface.h"
19 #include "cc/test/scheduler_test_common.h"
20 #include "cc/test/test_shared_bitmap_manager.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using testing::AnyNumber;
26 namespace cc {
27 namespace {
29 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
30 public:
31 void ReturnResources(const ReturnedResourceArray& resources) override {}
34 class TestSoftwareOutputDevice : public SoftwareOutputDevice {
35 public:
36 TestSoftwareOutputDevice() {}
38 gfx::Rect damage_rect() const { return damage_rect_; }
39 gfx::Size viewport_pixel_size() const { return viewport_pixel_size_; }
42 class DisplayTest : public testing::Test {
43 public:
44 DisplayTest()
45 : factory_(&manager_, &empty_client_),
46 software_output_device_(nullptr),
47 task_runner_(new base::NullTaskRunner) {}
49 protected:
50 void SetUpContext(scoped_ptr<TestWebGraphicsContext3D> context) {
51 if (context) {
52 output_surface_ = FakeOutputSurface::Create3d(
53 TestContextProvider::Create(context.Pass()));
54 } else {
55 scoped_ptr<TestSoftwareOutputDevice> output_device(
56 new TestSoftwareOutputDevice);
57 software_output_device_ = output_device.get();
58 output_surface_ = FakeOutputSurface::CreateSoftware(output_device.Pass());
60 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
61 output_surface_ptr_ = output_surface_.get();
64 void SubmitCompositorFrame(RenderPassList* pass_list, SurfaceId surface_id) {
65 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
66 pass_list->swap(frame_data->render_pass_list);
68 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
69 frame->delegated_frame_data = frame_data.Pass();
71 factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
72 SurfaceFactory::DrawCallback());
75 SurfaceManager manager_;
76 EmptySurfaceFactoryClient empty_client_;
77 SurfaceFactory factory_;
78 TestSoftwareOutputDevice* software_output_device_;
79 scoped_ptr<FakeOutputSurface> output_surface_;
80 FakeOutputSurface* output_surface_ptr_;
81 FakeBeginFrameSource fake_begin_frame_source_;
82 scoped_refptr<base::NullTaskRunner> task_runner_;
83 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
86 class TestDisplayClient : public DisplayClient {
87 public:
88 TestDisplayClient() {}
89 ~TestDisplayClient() override {}
91 void CommitVSyncParameters(base::TimeTicks timebase,
92 base::TimeDelta interval) override {}
93 void OutputSurfaceLost() override {}
94 void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override {}
97 class TestDisplayScheduler : public DisplayScheduler {
98 public:
99 TestDisplayScheduler(DisplaySchedulerClient* client,
100 BeginFrameSource* begin_frame_source,
101 base::NullTaskRunner* task_runner)
102 : DisplayScheduler(client, begin_frame_source, task_runner, 1),
103 damaged(false),
104 display_resized_(false),
105 has_new_root_surface(false),
106 swapped(false) {}
108 ~TestDisplayScheduler() override {}
110 void DisplayResized() override { display_resized_ = true; }
112 void SetNewRootSurface(SurfaceId root_surface_id) override {
113 has_new_root_surface = true;
116 void SurfaceDamaged(SurfaceId surface_id) override {
117 damaged = true;
118 needs_draw_ = true;
121 void DidSwapBuffers() override { swapped = true; }
123 void ResetDamageForTest() {
124 damaged = false;
125 display_resized_ = false;
126 has_new_root_surface = false;
129 bool damaged;
130 bool display_resized_;
131 bool has_new_root_surface;
132 bool swapped;
135 void CopyCallback(bool* called, scoped_ptr<CopyOutputResult> result) {
136 *called = true;
139 // Check that frame is damaged and swapped only under correct conditions.
140 TEST_F(DisplayTest, DisplayDamaged) {
141 SetUpContext(nullptr);
142 TestDisplayClient client;
143 RendererSettings settings;
144 settings.partial_swap_enabled = true;
145 settings.finish_rendering_on_resize = true;
146 Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr,
147 settings);
149 TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_,
150 task_runner_.get());
151 display.Initialize(output_surface_.Pass(), &scheduler);
153 SurfaceId surface_id(7u);
154 EXPECT_FALSE(scheduler.damaged);
155 EXPECT_FALSE(scheduler.has_new_root_surface);
156 display.SetSurfaceId(surface_id, 1.f);
157 EXPECT_FALSE(scheduler.damaged);
158 EXPECT_FALSE(scheduler.display_resized_);
159 EXPECT_TRUE(scheduler.has_new_root_surface);
161 scheduler.ResetDamageForTest();
162 display.Resize(gfx::Size(100, 100));
163 EXPECT_FALSE(scheduler.damaged);
164 EXPECT_TRUE(scheduler.display_resized_);
165 EXPECT_FALSE(scheduler.has_new_root_surface);
167 factory_.Create(surface_id);
169 // First draw from surface should have full damage.
170 RenderPassList pass_list;
171 scoped_ptr<RenderPass> pass = RenderPass::Create();
172 pass->output_rect = gfx::Rect(0, 0, 100, 100);
173 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
174 pass->id = RenderPassId(1, 1);
175 pass_list.push_back(pass.Pass());
177 scheduler.ResetDamageForTest();
178 SubmitCompositorFrame(&pass_list, surface_id);
179 EXPECT_TRUE(scheduler.damaged);
180 EXPECT_FALSE(scheduler.display_resized_);
181 EXPECT_FALSE(scheduler.has_new_root_surface);
183 EXPECT_FALSE(scheduler.swapped);
184 EXPECT_EQ(0u, output_surface_ptr_->num_sent_frames());
185 display.DrawAndSwap();
186 EXPECT_TRUE(scheduler.swapped);
187 EXPECT_EQ(1u, output_surface_ptr_->num_sent_frames());
188 EXPECT_EQ(gfx::Size(100, 100),
189 software_output_device_->viewport_pixel_size());
190 EXPECT_EQ(gfx::Rect(0, 0, 100, 100), software_output_device_->damage_rect());
193 // Only damaged portion should be swapped.
194 pass = RenderPass::Create();
195 pass->output_rect = gfx::Rect(0, 0, 100, 100);
196 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
197 pass->id = RenderPassId(1, 1);
199 pass_list.push_back(pass.Pass());
200 scheduler.ResetDamageForTest();
201 SubmitCompositorFrame(&pass_list, surface_id);
202 EXPECT_TRUE(scheduler.damaged);
203 EXPECT_FALSE(scheduler.display_resized_);
204 EXPECT_FALSE(scheduler.has_new_root_surface);
206 scheduler.swapped = false;
207 display.DrawAndSwap();
208 EXPECT_TRUE(scheduler.swapped);
209 EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames());
210 EXPECT_EQ(gfx::Size(100, 100),
211 software_output_device_->viewport_pixel_size());
212 EXPECT_EQ(gfx::Rect(10, 10, 1, 1), software_output_device_->damage_rect());
216 // Pass has no damage so shouldn't be swapped.
217 pass = RenderPass::Create();
218 pass->output_rect = gfx::Rect(0, 0, 100, 100);
219 pass->damage_rect = gfx::Rect(10, 10, 0, 0);
220 pass->id = RenderPassId(1, 1);
222 pass_list.push_back(pass.Pass());
223 scheduler.ResetDamageForTest();
224 SubmitCompositorFrame(&pass_list, surface_id);
225 EXPECT_TRUE(scheduler.damaged);
226 EXPECT_FALSE(scheduler.display_resized_);
227 EXPECT_FALSE(scheduler.has_new_root_surface);
229 scheduler.swapped = false;
230 display.DrawAndSwap();
231 EXPECT_TRUE(scheduler.swapped);
232 EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames());
236 // Pass is wrong size so shouldn't be swapped.
237 pass = RenderPass::Create();
238 pass->output_rect = gfx::Rect(0, 0, 99, 99);
239 pass->damage_rect = gfx::Rect(10, 10, 10, 10);
240 pass->id = RenderPassId(1, 1);
242 pass_list.push_back(pass.Pass());
243 scheduler.ResetDamageForTest();
244 SubmitCompositorFrame(&pass_list, surface_id);
245 EXPECT_TRUE(scheduler.damaged);
246 EXPECT_FALSE(scheduler.display_resized_);
247 EXPECT_FALSE(scheduler.has_new_root_surface);
249 scheduler.swapped = false;
250 display.DrawAndSwap();
251 EXPECT_TRUE(scheduler.swapped);
252 EXPECT_EQ(2u, output_surface_ptr_->num_sent_frames());
256 // Previous frame wasn't swapped, so next swap should have full damage.
257 pass = RenderPass::Create();
258 pass->output_rect = gfx::Rect(0, 0, 100, 100);
259 pass->damage_rect = gfx::Rect(10, 10, 0, 0);
260 pass->id = RenderPassId(1, 1);
262 pass_list.push_back(pass.Pass());
263 scheduler.ResetDamageForTest();
264 SubmitCompositorFrame(&pass_list, surface_id);
265 EXPECT_TRUE(scheduler.damaged);
266 EXPECT_FALSE(scheduler.display_resized_);
267 EXPECT_FALSE(scheduler.has_new_root_surface);
269 scheduler.swapped = false;
270 display.DrawAndSwap();
271 EXPECT_TRUE(scheduler.swapped);
272 EXPECT_EQ(3u, output_surface_ptr_->num_sent_frames());
273 EXPECT_EQ(gfx::Rect(0, 0, 100, 100),
274 software_output_device_->damage_rect());
278 // Pass has copy output request so should be swapped.
279 pass = RenderPass::Create();
280 pass->output_rect = gfx::Rect(0, 0, 100, 100);
281 pass->damage_rect = gfx::Rect(10, 10, 0, 0);
282 bool copy_called = false;
283 pass->copy_requests.push_back(CopyOutputRequest::CreateRequest(
284 base::Bind(&CopyCallback, &copy_called)));
285 pass->id = RenderPassId(1, 1);
287 pass_list.push_back(pass.Pass());
288 scheduler.ResetDamageForTest();
289 SubmitCompositorFrame(&pass_list, surface_id);
290 EXPECT_TRUE(scheduler.damaged);
291 EXPECT_FALSE(scheduler.display_resized_);
292 EXPECT_FALSE(scheduler.has_new_root_surface);
294 scheduler.swapped = false;
295 display.DrawAndSwap();
296 EXPECT_TRUE(scheduler.swapped);
297 EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
298 EXPECT_TRUE(copy_called);
301 // Pass has latency info so should be swapped.
303 pass = RenderPass::Create();
304 pass->output_rect = gfx::Rect(0, 0, 100, 100);
305 pass->damage_rect = gfx::Rect(10, 10, 0, 0);
306 pass->id = RenderPassId(1, 1);
308 pass_list.push_back(pass.Pass());
309 scheduler.ResetDamageForTest();
310 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
311 pass_list.swap(frame_data->render_pass_list);
313 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
314 frame->delegated_frame_data = frame_data.Pass();
315 frame->metadata.latency_info.push_back(ui::LatencyInfo());
317 factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
318 SurfaceFactory::DrawCallback());
319 EXPECT_TRUE(scheduler.damaged);
320 EXPECT_FALSE(scheduler.display_resized_);
321 EXPECT_FALSE(scheduler.has_new_root_surface);
323 scheduler.swapped = false;
324 display.DrawAndSwap();
325 EXPECT_TRUE(scheduler.swapped);
326 EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
329 // Resize should cause a swap if no frame was swapped at the previous size.
331 scheduler.swapped = false;
332 display.Resize(gfx::Size(200, 200));
333 EXPECT_FALSE(scheduler.swapped);
334 EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
336 pass = RenderPass::Create();
337 pass->output_rect = gfx::Rect(0, 0, 200, 200);
338 pass->damage_rect = gfx::Rect(10, 10, 10, 10);
339 pass->id = RenderPassId(1, 1);
341 pass_list.push_back(pass.Pass());
342 scheduler.ResetDamageForTest();
343 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
344 pass_list.swap(frame_data->render_pass_list);
346 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
347 frame->delegated_frame_data = frame_data.Pass();
349 factory_.SubmitCompositorFrame(surface_id, frame.Pass(),
350 SurfaceFactory::DrawCallback());
351 EXPECT_TRUE(scheduler.damaged);
352 EXPECT_FALSE(scheduler.display_resized_);
353 EXPECT_FALSE(scheduler.has_new_root_surface);
355 scheduler.swapped = false;
356 display.Resize(gfx::Size(100, 100));
357 EXPECT_TRUE(scheduler.swapped);
358 EXPECT_EQ(6u, output_surface_ptr_->num_sent_frames());
361 factory_.Destroy(surface_id);
364 class MockedContext : public TestWebGraphicsContext3D {
365 public:
366 MOCK_METHOD0(shallowFinishCHROMIUM, void());
369 TEST_F(DisplayTest, Finish) {
370 scoped_ptr<MockedContext> context(new MockedContext());
371 MockedContext* context_ptr = context.get();
372 SetUpContext(context.Pass());
374 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
375 TestDisplayClient client;
376 RendererSettings settings;
377 settings.partial_swap_enabled = true;
378 settings.finish_rendering_on_resize = true;
379 Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr,
380 settings);
382 TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_,
383 task_runner_.get());
384 display.Initialize(output_surface_.Pass(), &scheduler);
386 SurfaceId surface_id(7u);
387 display.SetSurfaceId(surface_id, 1.f);
389 display.Resize(gfx::Size(100, 100));
390 factory_.Create(surface_id);
393 RenderPassList pass_list;
394 scoped_ptr<RenderPass> pass = RenderPass::Create();
395 pass->output_rect = gfx::Rect(0, 0, 100, 100);
396 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
397 pass->id = RenderPassId(1, 1);
398 pass_list.push_back(pass.Pass());
400 SubmitCompositorFrame(&pass_list, surface_id);
403 display.DrawAndSwap();
405 // First resize and draw shouldn't finish.
406 testing::Mock::VerifyAndClearExpectations(context_ptr);
408 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
409 display.Resize(gfx::Size(150, 150));
410 testing::Mock::VerifyAndClearExpectations(context_ptr);
412 // Another resize without a swap doesn't need to finish.
413 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
414 display.Resize(gfx::Size(200, 200));
415 testing::Mock::VerifyAndClearExpectations(context_ptr);
417 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
419 RenderPassList pass_list;
420 scoped_ptr<RenderPass> pass = RenderPass::Create();
421 pass->output_rect = gfx::Rect(0, 0, 200, 200);
422 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
423 pass->id = RenderPassId(1, 1);
424 pass_list.push_back(pass.Pass());
426 SubmitCompositorFrame(&pass_list, surface_id);
429 display.DrawAndSwap();
431 testing::Mock::VerifyAndClearExpectations(context_ptr);
433 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
434 display.Resize(gfx::Size(250, 250));
435 testing::Mock::VerifyAndClearExpectations(context_ptr);
437 factory_.Destroy(surface_id);
440 } // namespace
441 } // namespace cc