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

Side by Side Diff: cc/surfaces/surface_aggregator_unittest.cc

Issue 139763003: Initial surface aggregator implementation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « cc/surfaces/surface_aggregator_test_helpers.cc ('k') | cc/surfaces/surface_unittest.cc » ('j') | 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 2014 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 "cc/output/compositor_frame.h"
6 #include "cc/output/delegated_frame_data.h"
7 #include "cc/quads/render_pass.h"
8 #include "cc/quads/render_pass_draw_quad.h"
9 #include "cc/quads/solid_color_draw_quad.h"
10 #include "cc/quads/surface_draw_quad.h"
11 #include "cc/surfaces/surface.h"
12 #include "cc/surfaces/surface_aggregator.h"
13 #include "cc/surfaces/surface_aggregator_test_helpers.h"
14 #include "cc/surfaces/surface_manager.h"
15 #include "cc/test/render_pass_test_common.h"
16 #include "cc/test/render_pass_test_utils.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/skia/include/core/SkColor.h"
19
20 namespace cc {
21 namespace {
22 const int kInvalidSurfaceId = -1;
23
24 class SurfaceAggregatorTest : public testing::Test {
25 public:
26 SurfaceAggregatorTest() : aggregator_(&manager_) {}
27
28 protected:
29 SurfaceManager manager_;
30 SurfaceAggregator aggregator_;
31 };
32
33 TEST_F(SurfaceAggregatorTest, InvalidSurfaceId) {
34 scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(kInvalidSurfaceId);
35 EXPECT_FALSE(frame);
36 }
37
38 TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
39 Surface one(&manager_, NULL, gfx::Size(5, 5));
40 scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one.surface_id());
41 EXPECT_FALSE(frame);
42 }
43
44 class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
45 public:
46 SurfaceAggregatorValidSurfaceTest()
47 : root_surface_(&manager_, NULL, gfx::Size(5, 5)) {}
48
49 void AggregateAndVerify(test::Pass* expected_passes,
50 size_t expected_pass_count) {
51 scoped_ptr<CompositorFrame> aggregated_frame =
52 aggregator_.Aggregate(root_surface_.surface_id());
53
54 ASSERT_TRUE(aggregated_frame);
55 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
56
57 DelegatedFrameData* frame_data =
58 aggregated_frame->delegated_frame_data.get();
59
60 TestPassesMatchExpectations(
61 expected_passes, expected_pass_count, &frame_data->render_pass_list);
62 }
63
64 protected:
65 Surface root_surface_;
66 };
67
68 // Tests that a very simple frame containing only two solid color quads makes it
69 // through the aggregator correctly.
70 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
71 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorRED),
72 test::Quad::SolidColorQuad(SK_ColorBLUE)};
73 test::Pass passes[] = {{quads, arraysize(quads)}};
jamesr 2014/01/28 18:40:43 annoying! gcc doesn't like this form of initialize
74
75 SubmitFrame(passes, arraysize(passes), &root_surface_);
76
77 AggregateAndVerify(passes, arraysize(passes));
78 }
79
80 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
81 test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
82 test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
83 {test::Quad::SolidColorQuad(SK_ColorGRAY),
84 test::Quad::SolidColorQuad(SK_ColorDKGRAY)}};
85 test::Pass passes[] = {{quads[0], arraysize(quads[0])},
86 {quads[1], arraysize(quads[1])}};
87
88 SubmitFrame(passes, arraysize(passes), &root_surface_);
89
90 AggregateAndVerify(passes, arraysize(passes));
91 }
92
93 // This tests very simple embedding. root_surface has a frame containing a few
94 // solid color quads and a surface quad referencing embedded_surface.
95 // embedded_surface has a frame containing only a solid color quad. The solid
96 // color quad should be aggregated into the final frame.
97 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
98 gfx::Size surface_size(5, 5);
99
100 Surface embedded_surface(&manager_, NULL, surface_size);
101
102 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
103 test::Pass embedded_passes[] = {{embedded_quads, arraysize(embedded_quads)}};
104
105 SubmitFrame(embedded_passes, arraysize(embedded_passes), &embedded_surface);
106
107 test::Quad root_quads[] = {
108 test::Quad::SolidColorQuad(SK_ColorWHITE),
109 test::Quad::SurfaceQuad(embedded_surface.surface_id()),
110 test::Quad::SolidColorQuad(SK_ColorBLACK)};
111 test::Pass root_passes[] = {{root_quads, arraysize(root_quads)}};
112
113 SubmitFrame(root_passes, arraysize(root_passes), &root_surface_);
114
115 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
116 test::Quad::SolidColorQuad(SK_ColorGREEN),
117 test::Quad::SolidColorQuad(SK_ColorBLACK)};
118 test::Pass expected_passes[] = {{expected_quads, arraysize(expected_quads)}};
119 AggregateAndVerify(expected_passes, arraysize(expected_passes));
120 }
121
122 // This tests referencing a surface that has multiple render passes.
123 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
124 gfx::Size surface_size(5, 5);
125
126 Surface embedded_surface(&manager_, NULL, surface_size);
127
128 RenderPass::Id pass_ids[] = {RenderPass::Id(1, 1), RenderPass::Id(1, 2),
129 RenderPass::Id(1, 3)};
130
131 test::Quad embedded_quads[][2] = {
132 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
133 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])},
134 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}};
135 test::Pass embedded_passes[] = {
136 {embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]},
137 {embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]},
138 {embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2]}};
139
140 SubmitFrame(embedded_passes, arraysize(embedded_passes), &embedded_surface);
141
142 test::Quad root_quads[][2] = {
143 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
144 {test::Quad::SurfaceQuad(embedded_surface.surface_id()),
145 test::Quad::RenderPassQuad(pass_ids[0])},
146 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
147 test::Pass root_passes[] = {
148 {root_quads[0], arraysize(root_quads[0]), pass_ids[0]},
149 {root_quads[1], arraysize(root_quads[1]), pass_ids[1]},
150 {root_quads[2], arraysize(root_quads[2]), pass_ids[2]}};
151
152 SubmitFrame(root_passes, arraysize(root_passes), &root_surface_);
153
154 scoped_ptr<CompositorFrame> aggregated_frame =
155 aggregator_.Aggregate(root_surface_.surface_id());
156
157 ASSERT_TRUE(aggregated_frame);
158 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
159
160 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
161
162 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
163
164 ASSERT_EQ(5u, aggregated_pass_list.size());
165 RenderPass::Id actual_pass_ids[] = {
166 aggregated_pass_list[0]->id, aggregated_pass_list[1]->id,
167 aggregated_pass_list[2]->id, aggregated_pass_list[3]->id,
168 aggregated_pass_list[4]->id};
169 for (size_t i = 0; i < 5; ++i) {
170 for (size_t j = 0; j < i; ++j) {
171 EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]);
172 }
173 }
174
175 {
176 SCOPED_TRACE("First pass");
177 // The first pass will just be the first pass from the root surfaces quad
178 // with no render pass quads to remap.
179 TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]);
180 }
181
182 {
183 SCOPED_TRACE("Second pass");
184 // The next two passes will be from the embedded surface since we have to
185 // draw those passes before they are referenced from the render pass draw
186 // quad embedded into the root surface's second pass.
187 // First, there's the first embedded pass which doesn't reference anything
188 // else.
189 TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]);
190 }
191
192 {
193 SCOPED_TRACE("Third pass");
194 const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list;
195 ASSERT_EQ(2u, third_pass_quad_list.size());
196 TestQuadMatchesExpectations(embedded_quads[1][0],
197 third_pass_quad_list.at(0u));
198
199 // This render pass pass quad will reference the first pass from the
200 // embedded surface, which is the second pass in the aggregated frame.
201 ASSERT_EQ(DrawQuad::RENDER_PASS, third_pass_quad_list.at(1u)->material);
202 const RenderPassDrawQuad* third_pass_render_pass_draw_quad =
203 RenderPassDrawQuad::MaterialCast(third_pass_quad_list.at(1u));
204 EXPECT_EQ(actual_pass_ids[1],
205 third_pass_render_pass_draw_quad->render_pass_id);
206 }
207
208 {
209 SCOPED_TRACE("Fourth pass");
210 // The fourth pass will have aggregated quads from the root surface's second
211 // pass and the embedded surface's first pass.
212 const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list;
213 ASSERT_EQ(3u, fourth_pass_quad_list.size());
214
215 // The first quad will be the yellow quad from the embedded surface's last
216 // pass.
217 TestQuadMatchesExpectations(embedded_quads[2][0],
218 fourth_pass_quad_list.at(0u));
219
220 // The next quad will be a render pass quad referencing the second pass from
221 // the embedded surface, which is the third pass in the aggregated frame.
222 ASSERT_EQ(DrawQuad::RENDER_PASS, fourth_pass_quad_list.at(1u)->material);
223 const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad =
224 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.at(1u));
225 EXPECT_EQ(actual_pass_ids[2],
226 fourth_pass_first_render_pass_draw_quad->render_pass_id);
227
228 // The last quad will be a render pass quad referencing the first pass from
229 // the root surface, which is the first pass overall.
230 ASSERT_EQ(DrawQuad::RENDER_PASS, fourth_pass_quad_list.at(2u)->material);
231 const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad =
232 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.at(2u));
233 EXPECT_EQ(actual_pass_ids[0],
234 fourth_pass_second_render_pass_draw_quad->render_pass_id);
235 }
236
237 {
238 SCOPED_TRACE("Fifth pass");
239 const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list;
240 ASSERT_EQ(2u, fifth_pass_quad_list.size());
241
242 TestQuadMatchesExpectations(root_quads[2][0], fifth_pass_quad_list.at(0));
243
244 // The last quad in the last pass will reference the second pass from the
245 // root surface, which after aggregating is the fourth pass in the overall
246 // list.
247 ASSERT_EQ(DrawQuad::RENDER_PASS, fifth_pass_quad_list.at(1u)->material);
248 const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad =
249 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.at(1u));
250 EXPECT_EQ(actual_pass_ids[3],
251 fifth_pass_render_pass_draw_quad->render_pass_id);
252 }
253 }
254
255 // Tests an invalid surface reference in a frame. The surface quad should just
256 // be dropped.
257 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
258 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
259 test::Quad::SurfaceQuad(kInvalidSurfaceId),
260 test::Quad::SolidColorQuad(SK_ColorBLUE)};
261 test::Pass passes[] = {{quads, arraysize(quads)}};
262
263 SubmitFrame(passes, arraysize(passes), &root_surface_);
264
265 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
266 test::Quad::SolidColorQuad(SK_ColorBLUE)};
267 test::Pass expected_passes[] = {{expected_quads, arraysize(expected_quads)}};
268 AggregateAndVerify(expected_passes, arraysize(expected_passes));
269 }
270
271 // Tests a reference to a valid surface with no submitted frame. This quad
272 // should also just be dropped.
273 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
274 Surface surface_with_no_frame(&manager_, NULL, gfx::Size(5, 5));
275 test::Quad quads[] = {
276 test::Quad::SolidColorQuad(SK_ColorGREEN),
277 test::Quad::SurfaceQuad(surface_with_no_frame.surface_id()),
278 test::Quad::SolidColorQuad(SK_ColorBLUE)};
279 test::Pass passes[] = {{quads, arraysize(quads)}};
280
281 SubmitFrame(passes, arraysize(passes), &root_surface_);
282
283 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
284 test::Quad::SolidColorQuad(SK_ColorBLUE)};
285 test::Pass expected_passes[] = {{expected_quads, arraysize(expected_quads)}};
286 AggregateAndVerify(expected_passes, arraysize(expected_passes));
287 }
288
289 // Tests a surface quad referencing itself, generating a trivial cycle.
290 // The quad creating the cycle should be dropped from the final frame.
291 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
292 test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_.surface_id()),
293 test::Quad::SolidColorQuad(SK_ColorYELLOW)};
294 test::Pass passes[] = {{quads, arraysize(quads)}};
295
296 SubmitFrame(passes, arraysize(passes), &root_surface_);
297
298 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
299 test::Pass expected_passes[] = {{expected_quads, arraysize(expected_quads)}};
300 AggregateAndVerify(expected_passes, arraysize(expected_passes));
301 }
302
303 // Tests a more complex cycle with one intermediate surface.
304 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
305 gfx::Size surface_size(5, 5);
306
307 Surface child_surface(&manager_, NULL, surface_size);
308
309 test::Quad parent_quads[] = {
310 test::Quad::SolidColorQuad(SK_ColorBLUE),
311 test::Quad::SurfaceQuad(child_surface.surface_id()),
312 test::Quad::SolidColorQuad(SK_ColorCYAN)};
313 test::Pass parent_passes[] = {{parent_quads, arraysize(parent_quads)}};
314
315 SubmitFrame(parent_passes, arraysize(parent_passes), &root_surface_);
316
317 test::Quad child_quads[] = {
318 test::Quad::SolidColorQuad(SK_ColorGREEN),
319 test::Quad::SurfaceQuad(root_surface_.surface_id()),
320 test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
321 test::Pass child_passes[] = {{child_quads, arraysize(child_quads)}};
322
323 SubmitFrame(child_passes, arraysize(child_passes), &child_surface);
324
325 // The child surface's reference to the root_surface_ will be dropped, so
326 // we'll end up with:
327 // SK_ColorBLUE from the parent
328 // SK_ColorGREEN from the child
329 // SK_ColorMAGENTA from the child
330 // SK_ColorCYAN from the parent
331 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
332 test::Quad::SolidColorQuad(SK_ColorGREEN),
333 test::Quad::SolidColorQuad(SK_ColorMAGENTA),
334 test::Quad::SolidColorQuad(SK_ColorCYAN)};
335 test::Pass expected_passes[] = {{expected_quads, arraysize(expected_quads)}};
336 AggregateAndVerify(expected_passes, arraysize(expected_passes));
337 }
338
339 // Tests that we map render pass IDs from different surfaces into a unified
340 // namespace and update RenderPassDrawQuad's id references to match.
341 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
342 gfx::Size surface_size(5, 5);
343
344 Surface child_surface(&manager_, NULL, surface_size);
345
346 RenderPass::Id child_pass_id[] = {RenderPass::Id(1, 1), RenderPass::Id(1, 2)};
347 test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
348 {test::Quad::RenderPassQuad(child_pass_id[0])}};
349 test::Pass surface_passes[] = {
350 {child_quad[0], arraysize(child_quad[0]), child_pass_id[0]},
351 {child_quad[1], arraysize(child_quad[1]), child_pass_id[1]}};
352
353 SubmitFrame(surface_passes, arraysize(surface_passes), &child_surface);
354
355 // Pass IDs from the parent surface may collide with ones from the child.
356 RenderPass::Id parent_pass_id[] = {RenderPass::Id(2, 1),
357 RenderPass::Id(1, 2)};
358 test::Quad parent_quad[][1] = {
359 {test::Quad::SurfaceQuad(child_surface.surface_id())},
360 {test::Quad::RenderPassQuad(parent_pass_id[0])}};
361 test::Pass parent_passes[] = {
362 {parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]},
363 {parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1]}};
364
365 SubmitFrame(parent_passes, arraysize(parent_passes), &root_surface_);
366 scoped_ptr<CompositorFrame> aggregated_frame =
367 aggregator_.Aggregate(root_surface_.surface_id());
368
369 ASSERT_TRUE(aggregated_frame);
370 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
371
372 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
373
374 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
375
376 ASSERT_EQ(3u, aggregated_pass_list.size());
377 RenderPass::Id actual_pass_ids[] = {aggregated_pass_list[0]->id,
378 aggregated_pass_list[1]->id,
379 aggregated_pass_list[2]->id};
380 // Make sure the aggregated frame's pass IDs are all unique.
381 for (size_t i = 0; i < 3; ++i) {
382 for (size_t j = 0; j < i; ++j) {
383 EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i
384 << " and " << j;
385 }
386 }
387
388 // Make sure the render pass quads reference the remapped pass IDs.
389 DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list[0],
390 aggregated_pass_list[2]->quad_list[0]};
391 ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS);
392 EXPECT_EQ(
393 actual_pass_ids[0],
394 RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id);
395
396 ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS);
397 EXPECT_EQ(
398 actual_pass_ids[1],
399 RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
400 }
401
402 } // namespace
403 } // namespace cc
OLDNEW
« no previous file with comments | « cc/surfaces/surface_aggregator_test_helpers.cc ('k') | cc/surfaces/surface_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698