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 "cc/output/compositor_frame.h"
6 #include "cc/output/copy_output_result.h"
7 #include "cc/output/delegated_frame_data.h"
8 #include "cc/quads/render_pass.h"
9 #include "cc/resources/shared_bitmap_manager.h"
10 #include "cc/surfaces/display.h"
11 #include "cc/surfaces/display_client.h"
12 #include "cc/surfaces/surface.h"
13 #include "cc/surfaces/surface_factory.h"
14 #include "cc/surfaces/surface_factory_client.h"
15 #include "cc/surfaces/surface_id_allocator.h"
16 #include "cc/surfaces/surface_manager.h"
17 #include "cc/test/fake_output_surface.h"
18 #include "cc/test/test_shared_bitmap_manager.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
25 class EmptySurfaceFactoryClient
: public SurfaceFactoryClient
{
27 void ReturnResources(const ReturnedResourceArray
& resources
) override
{}
30 class DisplayTest
: public testing::Test
{
32 DisplayTest() : factory_(&manager_
, &empty_client_
) {}
34 void SetUp() override
{
35 output_surface_
= FakeOutputSurface::CreateSoftware(
36 make_scoped_ptr(new SoftwareOutputDevice
));
37 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
38 output_surface_ptr_
= output_surface_
.get();
42 void SubmitFrame(RenderPassList
* pass_list
, SurfaceId surface_id
) {
43 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
44 pass_list
->swap(frame_data
->render_pass_list
);
46 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
47 frame
->delegated_frame_data
= frame_data
.Pass();
49 factory_
.SubmitFrame(surface_id
, frame
.Pass(),
50 SurfaceFactory::DrawCallback());
53 SurfaceManager manager_
;
54 EmptySurfaceFactoryClient empty_client_
;
55 SurfaceFactory factory_
;
56 scoped_ptr
<FakeOutputSurface
> output_surface_
;
57 FakeOutputSurface
* output_surface_ptr_
;
58 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
61 class TestDisplayClient
: public DisplayClient
{
63 TestDisplayClient() : damaged(false), swapped(false) {}
64 ~TestDisplayClient() override
{}
66 void DisplayDamaged() override
{ damaged
= true; }
67 void DidSwapBuffers() override
{ swapped
= true; }
68 void DidSwapBuffersComplete() override
{}
69 void CommitVSyncParameters(base::TimeTicks timebase
,
70 base::TimeDelta interval
) override
{}
71 void OutputSurfaceLost() override
{}
72 void SetMemoryPolicy(const ManagedMemoryPolicy
& policy
) override
{}
78 void CopyCallback(bool* called
, scoped_ptr
<CopyOutputResult
> result
) {
82 // Check that frame is damaged and swapped only under correct conditions.
83 TEST_F(DisplayTest
, DisplayDamaged
) {
84 TestDisplayClient client
;
85 RendererSettings settings
;
86 settings
.partial_swap_enabled
= true;
87 Display
display(&client
, &manager_
, shared_bitmap_manager_
.get(), nullptr,
90 display
.Initialize(output_surface_
.Pass());
92 SurfaceId
surface_id(7u);
93 EXPECT_FALSE(client
.damaged
);
94 display
.SetSurfaceId(surface_id
, 1.f
);
95 EXPECT_TRUE(client
.damaged
);
97 client
.damaged
= false;
98 display
.Resize(gfx::Size(100, 100));
99 EXPECT_TRUE(client
.damaged
);
101 factory_
.Create(surface_id
);
103 // First draw from surface should have full damage.
104 RenderPassList pass_list
;
105 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
106 pass
->output_rect
= gfx::Rect(0, 0, 100, 100);
107 pass
->damage_rect
= gfx::Rect(10, 10, 1, 1);
108 pass
->id
= RenderPassId(1, 1);
109 pass_list
.push_back(pass
.Pass());
111 client
.damaged
= false;
112 SubmitFrame(&pass_list
, surface_id
);
113 EXPECT_TRUE(client
.damaged
);
115 EXPECT_FALSE(client
.swapped
);
116 EXPECT_EQ(0u, output_surface_ptr_
->num_sent_frames());
118 EXPECT_TRUE(client
.swapped
);
119 EXPECT_EQ(1u, output_surface_ptr_
->num_sent_frames());
120 SoftwareFrameData
* software_data
=
121 output_surface_ptr_
->last_sent_frame().software_frame_data
.get();
122 ASSERT_NE(nullptr, software_data
);
123 EXPECT_EQ(gfx::Size(100, 100).ToString(), software_data
->size
.ToString());
124 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
125 software_data
->damage_rect
.ToString());
128 // Only damaged portion should be swapped.
129 pass
= RenderPass::Create();
130 pass
->output_rect
= gfx::Rect(0, 0, 100, 100);
131 pass
->damage_rect
= gfx::Rect(10, 10, 1, 1);
132 pass
->id
= RenderPassId(1, 1);
134 pass_list
.push_back(pass
.Pass());
135 client
.damaged
= false;
136 SubmitFrame(&pass_list
, surface_id
);
137 EXPECT_TRUE(client
.damaged
);
139 client
.swapped
= false;
141 EXPECT_TRUE(client
.swapped
);
142 EXPECT_EQ(2u, output_surface_ptr_
->num_sent_frames());
144 output_surface_ptr_
->last_sent_frame().software_frame_data
.get();
145 ASSERT_NE(nullptr, software_data
);
146 EXPECT_EQ(gfx::Size(100, 100).ToString(), software_data
->size
.ToString());
147 EXPECT_EQ(gfx::Rect(10, 10, 1, 1).ToString(),
148 software_data
->damage_rect
.ToString());
152 // Pass has no damage so shouldn't be swapped.
153 pass
= RenderPass::Create();
154 pass
->output_rect
= gfx::Rect(0, 0, 100, 100);
155 pass
->damage_rect
= gfx::Rect(10, 10, 0, 0);
156 pass
->id
= RenderPassId(1, 1);
158 pass_list
.push_back(pass
.Pass());
159 client
.damaged
= false;
160 SubmitFrame(&pass_list
, surface_id
);
161 EXPECT_TRUE(client
.damaged
);
163 client
.swapped
= false;
165 EXPECT_TRUE(client
.swapped
);
166 EXPECT_EQ(2u, output_surface_ptr_
->num_sent_frames());
170 // Pass is wrong size so shouldn't be swapped.
171 pass
= RenderPass::Create();
172 pass
->output_rect
= gfx::Rect(0, 0, 99, 99);
173 pass
->damage_rect
= gfx::Rect(10, 10, 10, 10);
174 pass
->id
= RenderPassId(1, 1);
176 pass_list
.push_back(pass
.Pass());
177 client
.damaged
= false;
178 SubmitFrame(&pass_list
, surface_id
);
179 EXPECT_TRUE(client
.damaged
);
181 client
.swapped
= false;
183 EXPECT_TRUE(client
.swapped
);
184 EXPECT_EQ(2u, output_surface_ptr_
->num_sent_frames());
188 // Pass has copy output request so should be swapped.
189 pass
= RenderPass::Create();
190 pass
->output_rect
= gfx::Rect(0, 0, 100, 100);
191 pass
->damage_rect
= gfx::Rect(10, 10, 0, 0);
192 bool copy_called
= false;
193 pass
->copy_requests
.push_back(CopyOutputRequest::CreateRequest(
194 base::Bind(&CopyCallback
, ©_called
)));
195 pass
->id
= RenderPassId(1, 1);
197 pass_list
.push_back(pass
.Pass());
198 client
.damaged
= false;
199 SubmitFrame(&pass_list
, surface_id
);
200 EXPECT_TRUE(client
.damaged
);
202 client
.swapped
= false;
204 EXPECT_TRUE(client
.swapped
);
205 EXPECT_EQ(3u, output_surface_ptr_
->num_sent_frames());
206 EXPECT_TRUE(copy_called
);
209 // Pass has latency info so should be swapped.
211 pass
= RenderPass::Create();
212 pass
->output_rect
= gfx::Rect(0, 0, 100, 100);
213 pass
->damage_rect
= gfx::Rect(10, 10, 0, 0);
214 pass
->id
= RenderPassId(1, 1);
216 pass_list
.push_back(pass
.Pass());
217 client
.damaged
= false;
218 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
219 pass_list
.swap(frame_data
->render_pass_list
);
221 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
222 frame
->delegated_frame_data
= frame_data
.Pass();
223 frame
->metadata
.latency_info
.push_back(ui::LatencyInfo());
225 factory_
.SubmitFrame(surface_id
, frame
.Pass(),
226 SurfaceFactory::DrawCallback());
227 EXPECT_TRUE(client
.damaged
);
229 client
.swapped
= false;
231 EXPECT_TRUE(client
.swapped
);
232 EXPECT_EQ(4u, output_surface_ptr_
->num_sent_frames());
235 factory_
.Destroy(surface_id
);