Add ICU message format support
[chromium-blink-merge.git] / cc / surfaces / display_unittest.cc
blobb7b50c3b5b488fb3bb4e2b0d3aa268bd8382b459
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 SubmitFrame(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_.SubmitFrame(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 SubmitFrame(&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 SubmitFrame(&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 SubmitFrame(&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 SubmitFrame(&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 // Pass has copy output request so should be swapped.
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 bool copy_called = false;
261 pass->copy_requests.push_back(CopyOutputRequest::CreateRequest(
262 base::Bind(&CopyCallback, &copy_called)));
263 pass->id = RenderPassId(1, 1);
265 pass_list.push_back(pass.Pass());
266 scheduler.ResetDamageForTest();
267 SubmitFrame(&pass_list, surface_id);
268 EXPECT_TRUE(scheduler.damaged);
269 EXPECT_FALSE(scheduler.display_resized_);
270 EXPECT_FALSE(scheduler.has_new_root_surface);
272 scheduler.swapped = false;
273 display.DrawAndSwap();
274 EXPECT_TRUE(scheduler.swapped);
275 EXPECT_EQ(3u, output_surface_ptr_->num_sent_frames());
276 EXPECT_TRUE(copy_called);
279 // Pass has latency info so should be swapped.
281 pass = RenderPass::Create();
282 pass->output_rect = gfx::Rect(0, 0, 100, 100);
283 pass->damage_rect = gfx::Rect(10, 10, 0, 0);
284 pass->id = RenderPassId(1, 1);
286 pass_list.push_back(pass.Pass());
287 scheduler.ResetDamageForTest();
288 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
289 pass_list.swap(frame_data->render_pass_list);
291 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
292 frame->delegated_frame_data = frame_data.Pass();
293 frame->metadata.latency_info.push_back(ui::LatencyInfo());
295 factory_.SubmitFrame(surface_id, frame.Pass(),
296 SurfaceFactory::DrawCallback());
297 EXPECT_TRUE(scheduler.damaged);
298 EXPECT_FALSE(scheduler.display_resized_);
299 EXPECT_FALSE(scheduler.has_new_root_surface);
301 scheduler.swapped = false;
302 display.DrawAndSwap();
303 EXPECT_TRUE(scheduler.swapped);
304 EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
307 // Resize should cause a swap if no frame was swapped at the previous size.
309 scheduler.swapped = false;
310 display.Resize(gfx::Size(200, 200));
311 EXPECT_FALSE(scheduler.swapped);
312 EXPECT_EQ(4u, output_surface_ptr_->num_sent_frames());
314 pass = RenderPass::Create();
315 pass->output_rect = gfx::Rect(0, 0, 200, 200);
316 pass->damage_rect = gfx::Rect(10, 10, 10, 10);
317 pass->id = RenderPassId(1, 1);
319 pass_list.push_back(pass.Pass());
320 scheduler.ResetDamageForTest();
321 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
322 pass_list.swap(frame_data->render_pass_list);
324 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
325 frame->delegated_frame_data = frame_data.Pass();
327 factory_.SubmitFrame(surface_id, frame.Pass(),
328 SurfaceFactory::DrawCallback());
329 EXPECT_TRUE(scheduler.damaged);
330 EXPECT_FALSE(scheduler.display_resized_);
331 EXPECT_FALSE(scheduler.has_new_root_surface);
333 scheduler.swapped = false;
334 display.Resize(gfx::Size(100, 100));
335 EXPECT_TRUE(scheduler.swapped);
336 EXPECT_EQ(5u, output_surface_ptr_->num_sent_frames());
339 factory_.Destroy(surface_id);
342 class MockedContext : public TestWebGraphicsContext3D {
343 public:
344 MOCK_METHOD0(shallowFinishCHROMIUM, void());
347 TEST_F(DisplayTest, Finish) {
348 scoped_ptr<MockedContext> context(new MockedContext());
349 MockedContext* context_ptr = context.get();
350 SetUpContext(context.Pass());
352 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
353 TestDisplayClient client;
354 RendererSettings settings;
355 settings.partial_swap_enabled = true;
356 settings.finish_rendering_on_resize = true;
357 Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr,
358 settings);
360 TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_,
361 task_runner_.get());
362 display.Initialize(output_surface_.Pass(), &scheduler);
364 SurfaceId surface_id(7u);
365 display.SetSurfaceId(surface_id, 1.f);
367 display.Resize(gfx::Size(100, 100));
368 factory_.Create(surface_id);
371 RenderPassList pass_list;
372 scoped_ptr<RenderPass> pass = RenderPass::Create();
373 pass->output_rect = gfx::Rect(0, 0, 100, 100);
374 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
375 pass->id = RenderPassId(1, 1);
376 pass_list.push_back(pass.Pass());
378 SubmitFrame(&pass_list, surface_id);
381 display.DrawAndSwap();
383 // First resize and draw shouldn't finish.
384 testing::Mock::VerifyAndClearExpectations(context_ptr);
386 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
387 display.Resize(gfx::Size(150, 150));
388 testing::Mock::VerifyAndClearExpectations(context_ptr);
390 // Another resize without a swap doesn't need to finish.
391 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
392 display.Resize(gfx::Size(200, 200));
393 testing::Mock::VerifyAndClearExpectations(context_ptr);
395 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
397 RenderPassList pass_list;
398 scoped_ptr<RenderPass> pass = RenderPass::Create();
399 pass->output_rect = gfx::Rect(0, 0, 200, 200);
400 pass->damage_rect = gfx::Rect(10, 10, 1, 1);
401 pass->id = RenderPassId(1, 1);
402 pass_list.push_back(pass.Pass());
404 SubmitFrame(&pass_list, surface_id);
407 display.DrawAndSwap();
409 testing::Mock::VerifyAndClearExpectations(context_ptr);
411 EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
412 display.Resize(gfx::Size(250, 250));
413 testing::Mock::VerifyAndClearExpectations(context_ptr);
415 factory_.Destroy(surface_id);
418 } // namespace
419 } // namespace cc