OLD | NEW |
| (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/quads/texture_draw_quad.h" | |
12 #include "cc/resources/shared_bitmap_manager.h" | |
13 #include "cc/surfaces/surface.h" | |
14 #include "cc/surfaces/surface_aggregator.h" | |
15 #include "cc/surfaces/surface_aggregator_test_helpers.h" | |
16 #include "cc/surfaces/surface_factory.h" | |
17 #include "cc/surfaces/surface_factory_client.h" | |
18 #include "cc/surfaces/surface_id_allocator.h" | |
19 #include "cc/surfaces/surface_manager.h" | |
20 #include "cc/test/fake_output_surface.h" | |
21 #include "cc/test/fake_output_surface_client.h" | |
22 #include "cc/test/render_pass_test_common.h" | |
23 #include "cc/test/render_pass_test_utils.h" | |
24 #include "cc/test/test_shared_bitmap_manager.h" | |
25 #include "testing/gmock/include/gmock/gmock.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 #include "third_party/skia/include/core/SkColor.h" | |
28 | |
29 namespace cc { | |
30 namespace { | |
31 | |
32 SurfaceId InvalidSurfaceId() { | |
33 static SurfaceId invalid; | |
34 invalid.id = static_cast<uint64_t>(-1); | |
35 return invalid; | |
36 } | |
37 | |
38 gfx::Size SurfaceSize() { | |
39 static gfx::Size size(5, 5); | |
40 return size; | |
41 } | |
42 | |
43 class EmptySurfaceFactoryClient : public SurfaceFactoryClient { | |
44 public: | |
45 void ReturnResources(const ReturnedResourceArray& resources) override {} | |
46 }; | |
47 | |
48 class SurfaceAggregatorTest : public testing::Test { | |
49 public: | |
50 SurfaceAggregatorTest() | |
51 : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {} | |
52 | |
53 protected: | |
54 SurfaceManager manager_; | |
55 EmptySurfaceFactoryClient empty_client_; | |
56 SurfaceFactory factory_; | |
57 SurfaceAggregator aggregator_; | |
58 }; | |
59 | |
60 TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) { | |
61 SurfaceId one_id(7); | |
62 factory_.Create(one_id); | |
63 scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one_id); | |
64 EXPECT_FALSE(frame); | |
65 factory_.Destroy(one_id); | |
66 } | |
67 | |
68 class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { | |
69 public: | |
70 SurfaceAggregatorValidSurfaceTest() : allocator_(1u), child_allocator_(2u) {} | |
71 | |
72 void SetUp() override { | |
73 SurfaceAggregatorTest::SetUp(); | |
74 root_surface_id_ = allocator_.GenerateId(); | |
75 factory_.Create(root_surface_id_); | |
76 } | |
77 | |
78 void TearDown() override { | |
79 factory_.Destroy(root_surface_id_); | |
80 SurfaceAggregatorTest::TearDown(); | |
81 } | |
82 | |
83 void AggregateAndVerify(test::Pass* expected_passes, | |
84 size_t expected_pass_count, | |
85 SurfaceId* surface_ids, | |
86 size_t expected_surface_count) { | |
87 scoped_ptr<CompositorFrame> aggregated_frame = | |
88 aggregator_.Aggregate(root_surface_id_); | |
89 | |
90 ASSERT_TRUE(aggregated_frame); | |
91 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
92 | |
93 DelegatedFrameData* frame_data = | |
94 aggregated_frame->delegated_frame_data.get(); | |
95 | |
96 TestPassesMatchExpectations( | |
97 expected_passes, expected_pass_count, &frame_data->render_pass_list); | |
98 | |
99 // Ensure no duplicate pass ids output. | |
100 std::set<RenderPassId> used_passes; | |
101 for (auto* pass : frame_data->render_pass_list) { | |
102 EXPECT_TRUE(used_passes.insert(pass->id).second); | |
103 } | |
104 | |
105 EXPECT_EQ(expected_surface_count, | |
106 aggregator_.previous_contained_surfaces().size()); | |
107 for (size_t i = 0; i < expected_surface_count; i++) { | |
108 EXPECT_TRUE( | |
109 aggregator_.previous_contained_surfaces().find(surface_ids[i]) != | |
110 aggregator_.previous_contained_surfaces().end()); | |
111 } | |
112 } | |
113 | |
114 void SubmitFrame(test::Pass* passes, | |
115 size_t pass_count, | |
116 SurfaceId surface_id) { | |
117 RenderPassList pass_list; | |
118 AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count); | |
119 | |
120 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); | |
121 pass_list.swap(frame_data->render_pass_list); | |
122 | |
123 scoped_ptr<CompositorFrame> frame(new CompositorFrame); | |
124 frame->delegated_frame_data = frame_data.Pass(); | |
125 | |
126 factory_.SubmitFrame(surface_id, frame.Pass(), | |
127 SurfaceFactory::DrawCallback()); | |
128 } | |
129 | |
130 void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) { | |
131 scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData); | |
132 delegated_frame_data->render_pass_list.push_back(pass.Pass()); | |
133 | |
134 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); | |
135 child_frame->delegated_frame_data = delegated_frame_data.Pass(); | |
136 | |
137 factory_.SubmitFrame(surface_id, child_frame.Pass(), | |
138 SurfaceFactory::DrawCallback()); | |
139 } | |
140 | |
141 protected: | |
142 SurfaceId root_surface_id_; | |
143 SurfaceIdAllocator allocator_; | |
144 SurfaceIdAllocator child_allocator_; | |
145 }; | |
146 | |
147 // Tests that a very simple frame containing only two solid color quads makes it | |
148 // through the aggregator correctly. | |
149 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) { | |
150 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorRED), | |
151 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
152 test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; | |
153 | |
154 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
155 | |
156 SurfaceId ids[] = {root_surface_id_}; | |
157 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); | |
158 } | |
159 | |
160 TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { | |
161 SurfaceId embedded_surface_id = allocator_.GenerateId(); | |
162 factory_.Create(embedded_surface_id); | |
163 | |
164 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
165 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
166 test::Pass embedded_passes[] = { | |
167 test::Pass(embedded_quads, arraysize(embedded_quads))}; | |
168 | |
169 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id); | |
170 | |
171 test::Quad quads[] = {test::Quad::SurfaceQuad(embedded_surface_id, .5f)}; | |
172 test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; | |
173 | |
174 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
175 | |
176 scoped_ptr<CompositorFrame> aggregated_frame = | |
177 aggregator_.Aggregate(root_surface_id_); | |
178 | |
179 ASSERT_TRUE(aggregated_frame); | |
180 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
181 | |
182 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
183 | |
184 RenderPassList& render_pass_list(frame_data->render_pass_list); | |
185 ASSERT_EQ(2u, render_pass_list.size()); | |
186 SharedQuadStateList& shared_quad_state_list( | |
187 render_pass_list[0]->shared_quad_state_list); | |
188 ASSERT_EQ(2u, shared_quad_state_list.size()); | |
189 EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(0)->opacity); | |
190 EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(1)->opacity); | |
191 | |
192 SharedQuadStateList& shared_quad_state_list2( | |
193 render_pass_list[1]->shared_quad_state_list); | |
194 ASSERT_EQ(1u, shared_quad_state_list2.size()); | |
195 EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity); | |
196 | |
197 factory_.Destroy(embedded_surface_id); | |
198 } | |
199 | |
200 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) { | |
201 test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE), | |
202 test::Quad::SolidColorQuad(SK_ColorLTGRAY)}, | |
203 {test::Quad::SolidColorQuad(SK_ColorGRAY), | |
204 test::Quad::SolidColorQuad(SK_ColorDKGRAY)}}; | |
205 test::Pass passes[] = { | |
206 test::Pass(quads[0], arraysize(quads[0]), RenderPassId(1, 1)), | |
207 test::Pass(quads[1], arraysize(quads[1]), RenderPassId(1, 2))}; | |
208 | |
209 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
210 | |
211 SurfaceId ids[] = {root_surface_id_}; | |
212 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); | |
213 } | |
214 | |
215 // This tests very simple embedding. root_surface has a frame containing a few | |
216 // solid color quads and a surface quad referencing embedded_surface. | |
217 // embedded_surface has a frame containing only a solid color quad. The solid | |
218 // color quad should be aggregated into the final frame. | |
219 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { | |
220 SurfaceId embedded_surface_id = allocator_.GenerateId(); | |
221 factory_.Create(embedded_surface_id); | |
222 | |
223 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; | |
224 test::Pass embedded_passes[] = { | |
225 test::Pass(embedded_quads, arraysize(embedded_quads))}; | |
226 | |
227 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id); | |
228 | |
229 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), | |
230 test::Quad::SurfaceQuad(embedded_surface_id, 1.f), | |
231 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
232 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; | |
233 | |
234 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_); | |
235 | |
236 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), | |
237 test::Quad::SolidColorQuad(SK_ColorGREEN), | |
238 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
239 test::Pass expected_passes[] = { | |
240 test::Pass(expected_quads, arraysize(expected_quads))}; | |
241 SurfaceId ids[] = {root_surface_id_, embedded_surface_id}; | |
242 AggregateAndVerify( | |
243 expected_passes, arraysize(expected_passes), ids, arraysize(ids)); | |
244 | |
245 factory_.Destroy(embedded_surface_id); | |
246 } | |
247 | |
248 TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { | |
249 SurfaceId embedded_surface_id = allocator_.GenerateId(); | |
250 factory_.Create(embedded_surface_id); | |
251 | |
252 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; | |
253 test::Pass embedded_passes[] = { | |
254 test::Pass(embedded_quads, arraysize(embedded_quads))}; | |
255 | |
256 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id); | |
257 scoped_ptr<CopyOutputRequest> copy_request( | |
258 CopyOutputRequest::CreateEmptyRequest()); | |
259 CopyOutputRequest* copy_request_ptr = copy_request.get(); | |
260 factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass()); | |
261 | |
262 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), | |
263 test::Quad::SurfaceQuad(embedded_surface_id, 1.f), | |
264 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
265 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; | |
266 | |
267 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_); | |
268 | |
269 scoped_ptr<CompositorFrame> aggregated_frame = | |
270 aggregator_.Aggregate(root_surface_id_); | |
271 | |
272 ASSERT_TRUE(aggregated_frame); | |
273 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
274 | |
275 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
276 | |
277 test::Quad expected_quads[] = { | |
278 test::Quad::SolidColorQuad(SK_ColorWHITE), | |
279 test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id), | |
280 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
281 test::Pass expected_passes[] = { | |
282 test::Pass(embedded_quads, arraysize(embedded_quads)), | |
283 test::Pass(expected_quads, arraysize(expected_quads))}; | |
284 TestPassesMatchExpectations(expected_passes, | |
285 arraysize(expected_passes), | |
286 &frame_data->render_pass_list); | |
287 ASSERT_EQ(2u, frame_data->render_pass_list.size()); | |
288 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size()); | |
289 DCHECK_EQ(copy_request_ptr, | |
290 frame_data->render_pass_list[0]->copy_requests[0]); | |
291 | |
292 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id}; | |
293 EXPECT_EQ(arraysize(surface_ids), | |
294 aggregator_.previous_contained_surfaces().size()); | |
295 for (size_t i = 0; i < arraysize(surface_ids); i++) { | |
296 EXPECT_TRUE( | |
297 aggregator_.previous_contained_surfaces().find(surface_ids[i]) != | |
298 aggregator_.previous_contained_surfaces().end()); | |
299 } | |
300 | |
301 factory_.Destroy(embedded_surface_id); | |
302 } | |
303 | |
304 // Root surface may contain copy requests. | |
305 TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { | |
306 SurfaceId embedded_surface_id = allocator_.GenerateId(); | |
307 factory_.Create(embedded_surface_id); | |
308 | |
309 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; | |
310 test::Pass embedded_passes[] = { | |
311 test::Pass(embedded_quads, arraysize(embedded_quads))}; | |
312 | |
313 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id); | |
314 scoped_ptr<CopyOutputRequest> copy_request( | |
315 CopyOutputRequest::CreateEmptyRequest()); | |
316 CopyOutputRequest* copy_request_ptr = copy_request.get(); | |
317 scoped_ptr<CopyOutputRequest> copy_request2( | |
318 CopyOutputRequest::CreateEmptyRequest()); | |
319 CopyOutputRequest* copy_request2_ptr = copy_request2.get(); | |
320 | |
321 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), | |
322 test::Quad::SurfaceQuad(embedded_surface_id, 1.f), | |
323 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
324 test::Quad root_quads2[] = {test::Quad::SolidColorQuad(SK_ColorRED)}; | |
325 test::Pass root_passes[] = { | |
326 test::Pass(root_quads, arraysize(root_quads), RenderPassId(1, 1)), | |
327 test::Pass(root_quads2, arraysize(root_quads2), RenderPassId(1, 2))}; | |
328 { | |
329 RenderPassList pass_list; | |
330 AddPasses(&pass_list, | |
331 gfx::Rect(SurfaceSize()), | |
332 root_passes, | |
333 arraysize(root_passes)); | |
334 pass_list[0]->copy_requests.push_back(copy_request.Pass()); | |
335 pass_list[1]->copy_requests.push_back(copy_request2.Pass()); | |
336 | |
337 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); | |
338 pass_list.swap(frame_data->render_pass_list); | |
339 | |
340 scoped_ptr<CompositorFrame> frame(new CompositorFrame); | |
341 frame->delegated_frame_data = frame_data.Pass(); | |
342 | |
343 factory_.SubmitFrame(root_surface_id_, frame.Pass(), | |
344 SurfaceFactory::DrawCallback()); | |
345 } | |
346 | |
347 scoped_ptr<CompositorFrame> aggregated_frame = | |
348 aggregator_.Aggregate(root_surface_id_); | |
349 | |
350 ASSERT_TRUE(aggregated_frame); | |
351 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
352 | |
353 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
354 | |
355 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), | |
356 test::Quad::SolidColorQuad(SK_ColorGREEN), | |
357 test::Quad::SolidColorQuad(SK_ColorBLACK)}; | |
358 test::Pass expected_passes[] = { | |
359 test::Pass(expected_quads, arraysize(expected_quads)), | |
360 test::Pass(root_quads2, arraysize(root_quads2))}; | |
361 TestPassesMatchExpectations(expected_passes, | |
362 arraysize(expected_passes), | |
363 &frame_data->render_pass_list); | |
364 ASSERT_EQ(2u, frame_data->render_pass_list.size()); | |
365 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size()); | |
366 DCHECK_EQ(copy_request_ptr, | |
367 frame_data->render_pass_list[0]->copy_requests[0]); | |
368 ASSERT_EQ(1u, frame_data->render_pass_list[1]->copy_requests.size()); | |
369 DCHECK_EQ(copy_request2_ptr, | |
370 frame_data->render_pass_list[1]->copy_requests[0]); | |
371 | |
372 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id}; | |
373 EXPECT_EQ(arraysize(surface_ids), | |
374 aggregator_.previous_contained_surfaces().size()); | |
375 for (size_t i = 0; i < arraysize(surface_ids); i++) { | |
376 EXPECT_TRUE( | |
377 aggregator_.previous_contained_surfaces().find(surface_ids[i]) != | |
378 aggregator_.previous_contained_surfaces().end()); | |
379 } | |
380 | |
381 // Ensure copy requests have been removed from root surface. | |
382 const CompositorFrame* original_frame = | |
383 manager_.GetSurfaceForId(root_surface_id_)->GetEligibleFrame(); | |
384 RenderPassList& original_pass_list = | |
385 original_frame->delegated_frame_data->render_pass_list; | |
386 ASSERT_EQ(2u, original_pass_list.size()); | |
387 DCHECK(original_pass_list[0]->copy_requests.empty()); | |
388 DCHECK(original_pass_list[1]->copy_requests.empty()); | |
389 | |
390 factory_.Destroy(embedded_surface_id); | |
391 } | |
392 | |
393 // This tests referencing a surface that has multiple render passes. | |
394 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { | |
395 SurfaceId embedded_surface_id = child_allocator_.GenerateId(); | |
396 factory_.Create(embedded_surface_id); | |
397 | |
398 RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2), | |
399 RenderPassId(1, 3)}; | |
400 | |
401 test::Quad embedded_quads[][2] = { | |
402 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)}, | |
403 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])}, | |
404 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}}; | |
405 test::Pass embedded_passes[] = { | |
406 test::Pass(embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]), | |
407 test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]), | |
408 test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])}; | |
409 | |
410 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id); | |
411 | |
412 test::Quad root_quads[][2] = { | |
413 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)}, | |
414 {test::Quad::SurfaceQuad(embedded_surface_id, 1.f), | |
415 test::Quad::RenderPassQuad(pass_ids[0])}, | |
416 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}}; | |
417 test::Pass root_passes[] = { | |
418 test::Pass(root_quads[0], arraysize(root_quads[0]), pass_ids[0]), | |
419 test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]), | |
420 test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])}; | |
421 | |
422 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_); | |
423 | |
424 scoped_ptr<CompositorFrame> aggregated_frame = | |
425 aggregator_.Aggregate(root_surface_id_); | |
426 | |
427 ASSERT_TRUE(aggregated_frame); | |
428 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
429 | |
430 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
431 | |
432 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
433 | |
434 ASSERT_EQ(5u, aggregated_pass_list.size()); | |
435 RenderPassId actual_pass_ids[] = { | |
436 aggregated_pass_list[0]->id, aggregated_pass_list[1]->id, | |
437 aggregated_pass_list[2]->id, aggregated_pass_list[3]->id, | |
438 aggregated_pass_list[4]->id}; | |
439 for (size_t i = 0; i < 5; ++i) { | |
440 for (size_t j = 0; j < i; ++j) { | |
441 EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]); | |
442 } | |
443 } | |
444 | |
445 { | |
446 SCOPED_TRACE("First pass"); | |
447 // The first pass will just be the first pass from the root surfaces quad | |
448 // with no render pass quads to remap. | |
449 TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]); | |
450 } | |
451 | |
452 { | |
453 SCOPED_TRACE("Second pass"); | |
454 // The next two passes will be from the embedded surface since we have to | |
455 // draw those passes before they are referenced from the render pass draw | |
456 // quad embedded into the root surface's second pass. | |
457 // First, there's the first embedded pass which doesn't reference anything | |
458 // else. | |
459 TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]); | |
460 } | |
461 | |
462 { | |
463 SCOPED_TRACE("Third pass"); | |
464 const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list; | |
465 ASSERT_EQ(2u, third_pass_quad_list.size()); | |
466 TestQuadMatchesExpectations(embedded_quads[1][0], | |
467 third_pass_quad_list.ElementAt(0)); | |
468 | |
469 // This render pass pass quad will reference the first pass from the | |
470 // embedded surface, which is the second pass in the aggregated frame. | |
471 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
472 third_pass_quad_list.ElementAt(1)->material); | |
473 const RenderPassDrawQuad* third_pass_render_pass_draw_quad = | |
474 RenderPassDrawQuad::MaterialCast(third_pass_quad_list.ElementAt(1)); | |
475 EXPECT_EQ(actual_pass_ids[1], | |
476 third_pass_render_pass_draw_quad->render_pass_id); | |
477 } | |
478 | |
479 { | |
480 SCOPED_TRACE("Fourth pass"); | |
481 // The fourth pass will have aggregated quads from the root surface's second | |
482 // pass and the embedded surface's first pass. | |
483 const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list; | |
484 ASSERT_EQ(3u, fourth_pass_quad_list.size()); | |
485 | |
486 // The first quad will be the yellow quad from the embedded surface's last | |
487 // pass. | |
488 TestQuadMatchesExpectations(embedded_quads[2][0], | |
489 fourth_pass_quad_list.ElementAt(0)); | |
490 | |
491 // The next quad will be a render pass quad referencing the second pass from | |
492 // the embedded surface, which is the third pass in the aggregated frame. | |
493 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
494 fourth_pass_quad_list.ElementAt(1)->material); | |
495 const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad = | |
496 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(1)); | |
497 EXPECT_EQ(actual_pass_ids[2], | |
498 fourth_pass_first_render_pass_draw_quad->render_pass_id); | |
499 | |
500 // The last quad will be a render pass quad referencing the first pass from | |
501 // the root surface, which is the first pass overall. | |
502 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
503 fourth_pass_quad_list.ElementAt(2)->material); | |
504 const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad = | |
505 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(2)); | |
506 EXPECT_EQ(actual_pass_ids[0], | |
507 fourth_pass_second_render_pass_draw_quad->render_pass_id); | |
508 } | |
509 | |
510 { | |
511 SCOPED_TRACE("Fifth pass"); | |
512 const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list; | |
513 ASSERT_EQ(2u, fifth_pass_quad_list.size()); | |
514 | |
515 TestQuadMatchesExpectations(root_quads[2][0], | |
516 fifth_pass_quad_list.ElementAt(0)); | |
517 | |
518 // The last quad in the last pass will reference the second pass from the | |
519 // root surface, which after aggregating is the fourth pass in the overall | |
520 // list. | |
521 ASSERT_EQ(DrawQuad::RENDER_PASS, | |
522 fifth_pass_quad_list.ElementAt(1)->material); | |
523 const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad = | |
524 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.ElementAt(1)); | |
525 EXPECT_EQ(actual_pass_ids[3], | |
526 fifth_pass_render_pass_draw_quad->render_pass_id); | |
527 } | |
528 factory_.Destroy(embedded_surface_id); | |
529 } | |
530 | |
531 // Tests an invalid surface reference in a frame. The surface quad should just | |
532 // be dropped. | |
533 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) { | |
534 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
535 test::Quad::SurfaceQuad(InvalidSurfaceId(), 1.f), | |
536 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
537 test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; | |
538 | |
539 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
540 | |
541 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
542 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
543 test::Pass expected_passes[] = { | |
544 test::Pass(expected_quads, arraysize(expected_quads))}; | |
545 SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()}; | |
546 AggregateAndVerify( | |
547 expected_passes, arraysize(expected_passes), ids, arraysize(ids)); | |
548 } | |
549 | |
550 // Tests a reference to a valid surface with no submitted frame. This quad | |
551 // should also just be dropped. | |
552 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { | |
553 SurfaceId surface_with_no_frame_id = allocator_.GenerateId(); | |
554 factory_.Create(surface_with_no_frame_id); | |
555 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
556 test::Quad::SurfaceQuad(surface_with_no_frame_id, 1.f), | |
557 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
558 test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; | |
559 | |
560 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
561 | |
562 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
563 test::Quad::SolidColorQuad(SK_ColorBLUE)}; | |
564 test::Pass expected_passes[] = { | |
565 test::Pass(expected_quads, arraysize(expected_quads))}; | |
566 SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id}; | |
567 AggregateAndVerify( | |
568 expected_passes, arraysize(expected_passes), ids, arraysize(ids)); | |
569 factory_.Destroy(surface_with_no_frame_id); | |
570 } | |
571 | |
572 // Tests a surface quad referencing itself, generating a trivial cycle. | |
573 // The quad creating the cycle should be dropped from the final frame. | |
574 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) { | |
575 test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_, 1.f), | |
576 test::Quad::SolidColorQuad(SK_ColorYELLOW)}; | |
577 test::Pass passes[] = {test::Pass(quads, arraysize(quads))}; | |
578 | |
579 SubmitFrame(passes, arraysize(passes), root_surface_id_); | |
580 | |
581 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)}; | |
582 test::Pass expected_passes[] = { | |
583 test::Pass(expected_quads, arraysize(expected_quads))}; | |
584 SurfaceId ids[] = {root_surface_id_}; | |
585 AggregateAndVerify( | |
586 expected_passes, arraysize(expected_passes), ids, arraysize(ids)); | |
587 } | |
588 | |
589 // Tests a more complex cycle with one intermediate surface. | |
590 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { | |
591 SurfaceId child_surface_id = allocator_.GenerateId(); | |
592 factory_.Create(child_surface_id); | |
593 | |
594 test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE), | |
595 test::Quad::SurfaceQuad(child_surface_id, 1.f), | |
596 test::Quad::SolidColorQuad(SK_ColorCYAN)}; | |
597 test::Pass parent_passes[] = { | |
598 test::Pass(parent_quads, arraysize(parent_quads))}; | |
599 | |
600 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_); | |
601 | |
602 test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), | |
603 test::Quad::SurfaceQuad(root_surface_id_, 1.f), | |
604 test::Quad::SolidColorQuad(SK_ColorMAGENTA)}; | |
605 test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))}; | |
606 | |
607 SubmitFrame(child_passes, arraysize(child_passes), child_surface_id); | |
608 | |
609 // The child surface's reference to the root_surface_ will be dropped, so | |
610 // we'll end up with: | |
611 // SK_ColorBLUE from the parent | |
612 // SK_ColorGREEN from the child | |
613 // SK_ColorMAGENTA from the child | |
614 // SK_ColorCYAN from the parent | |
615 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE), | |
616 test::Quad::SolidColorQuad(SK_ColorGREEN), | |
617 test::Quad::SolidColorQuad(SK_ColorMAGENTA), | |
618 test::Quad::SolidColorQuad(SK_ColorCYAN)}; | |
619 test::Pass expected_passes[] = { | |
620 test::Pass(expected_quads, arraysize(expected_quads))}; | |
621 SurfaceId ids[] = {root_surface_id_, child_surface_id}; | |
622 AggregateAndVerify( | |
623 expected_passes, arraysize(expected_passes), ids, arraysize(ids)); | |
624 factory_.Destroy(child_surface_id); | |
625 } | |
626 | |
627 // Tests that we map render pass IDs from different surfaces into a unified | |
628 // namespace and update RenderPassDrawQuad's id references to match. | |
629 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { | |
630 SurfaceId child_surface_id = allocator_.GenerateId(); | |
631 factory_.Create(child_surface_id); | |
632 | |
633 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)}; | |
634 test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)}, | |
635 {test::Quad::RenderPassQuad(child_pass_id[0])}}; | |
636 test::Pass surface_passes[] = { | |
637 test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]), | |
638 test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])}; | |
639 | |
640 SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id); | |
641 | |
642 // Pass IDs from the parent surface may collide with ones from the child. | |
643 RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)}; | |
644 test::Quad parent_quad[][1] = { | |
645 {test::Quad::SurfaceQuad(child_surface_id, 1.f)}, | |
646 {test::Quad::RenderPassQuad(parent_pass_id[0])}}; | |
647 test::Pass parent_passes[] = { | |
648 test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]), | |
649 test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])}; | |
650 | |
651 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_); | |
652 scoped_ptr<CompositorFrame> aggregated_frame = | |
653 aggregator_.Aggregate(root_surface_id_); | |
654 | |
655 ASSERT_TRUE(aggregated_frame); | |
656 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
657 | |
658 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
659 | |
660 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
661 | |
662 ASSERT_EQ(3u, aggregated_pass_list.size()); | |
663 RenderPassId actual_pass_ids[] = {aggregated_pass_list[0]->id, | |
664 aggregated_pass_list[1]->id, | |
665 aggregated_pass_list[2]->id}; | |
666 // Make sure the aggregated frame's pass IDs are all unique. | |
667 for (size_t i = 0; i < 3; ++i) { | |
668 for (size_t j = 0; j < i; ++j) { | |
669 EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i | |
670 << " and " << j; | |
671 } | |
672 } | |
673 | |
674 // Make sure the render pass quads reference the remapped pass IDs. | |
675 DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list.front(), | |
676 aggregated_pass_list[2]->quad_list.front()}; | |
677 ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS); | |
678 EXPECT_EQ( | |
679 actual_pass_ids[0], | |
680 RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id); | |
681 | |
682 ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS); | |
683 EXPECT_EQ( | |
684 actual_pass_ids[1], | |
685 RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id); | |
686 factory_.Destroy(child_surface_id); | |
687 } | |
688 | |
689 void AddSolidColorQuadWithBlendMode(const gfx::Size& size, | |
690 RenderPass* pass, | |
691 const SkXfermode::Mode blend_mode) { | |
692 const gfx::Transform content_to_target_transform; | |
693 const gfx::Size content_bounds(size); | |
694 const gfx::Rect visible_content_rect(size); | |
695 const gfx::Rect clip_rect(size); | |
696 | |
697 bool is_clipped = false; | |
698 float opacity = 1.f; | |
699 | |
700 bool force_anti_aliasing_off = false; | |
701 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); | |
702 sqs->SetAll(content_to_target_transform, | |
703 content_bounds, | |
704 visible_content_rect, | |
705 clip_rect, | |
706 is_clipped, | |
707 opacity, | |
708 blend_mode, | |
709 0); | |
710 | |
711 SolidColorDrawQuad* color_quad = | |
712 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); | |
713 color_quad->SetNew(pass->shared_quad_state_list.back(), | |
714 visible_content_rect, | |
715 visible_content_rect, | |
716 SK_ColorGREEN, | |
717 force_anti_aliasing_off); | |
718 } | |
719 | |
720 // This tests that we update shared quad state pointers correctly within | |
721 // aggregated passes. The shared quad state list on the aggregated pass will | |
722 // include the shared quad states from each pass in one list so the quads will | |
723 // end up pointed to shared quad state objects at different offsets. This test | |
724 // uses the blend_mode value stored on the shared quad state to track the shared | |
725 // quad state, but anything saved on the shared quad state would work. | |
726 // | |
727 // This test has 4 surfaces in the following structure: | |
728 // root_surface -> quad with kClear_Mode, | |
729 // [child_one_surface], | |
730 // quad with kDstOver_Mode, | |
731 // [child_two_surface], | |
732 // quad with kDstIn_Mode | |
733 // child_one_surface -> quad with kSrc_Mode, | |
734 // [grandchild_surface], | |
735 // quad with kSrcOver_Mode | |
736 // child_two_surface -> quad with kSrcIn_Mode | |
737 // grandchild_surface -> quad with kDst_Mode | |
738 // | |
739 // Resulting in the following aggregated pass: | |
740 // quad_root_0 - blend_mode kClear_Mode | |
741 // quad_child_one_0 - blend_mode kSrc_Mode | |
742 // quad_grandchild_0 - blend_mode kDst_Mode | |
743 // quad_child_one_1 - blend_mode kSrcOver_Mode | |
744 // quad_root_1 - blend_mode kDstOver_Mode | |
745 // quad_child_two_0 - blend_mode kSrcIn_Mode | |
746 // quad_root_2 - blend_mode kDstIn_Mode | |
747 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { | |
748 const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode, // 0 | |
749 SkXfermode::kSrc_Mode, // 1 | |
750 SkXfermode::kDst_Mode, // 2 | |
751 SkXfermode::kSrcOver_Mode, // 3 | |
752 SkXfermode::kDstOver_Mode, // 4 | |
753 SkXfermode::kSrcIn_Mode, // 5 | |
754 SkXfermode::kDstIn_Mode, // 6 | |
755 }; | |
756 | |
757 RenderPassId pass_id(1, 1); | |
758 SurfaceId grandchild_surface_id = allocator_.GenerateId(); | |
759 factory_.Create(grandchild_surface_id); | |
760 scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create(); | |
761 gfx::Rect output_rect(SurfaceSize()); | |
762 gfx::Rect damage_rect(SurfaceSize()); | |
763 gfx::Transform transform_to_root_target; | |
764 grandchild_pass->SetNew( | |
765 pass_id, output_rect, damage_rect, transform_to_root_target); | |
766 AddSolidColorQuadWithBlendMode( | |
767 SurfaceSize(), grandchild_pass.get(), blend_modes[2]); | |
768 QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id); | |
769 | |
770 SurfaceId child_one_surface_id = allocator_.GenerateId(); | |
771 factory_.Create(child_one_surface_id); | |
772 | |
773 scoped_ptr<RenderPass> child_one_pass = RenderPass::Create(); | |
774 child_one_pass->SetNew( | |
775 pass_id, output_rect, damage_rect, transform_to_root_target); | |
776 AddSolidColorQuadWithBlendMode( | |
777 SurfaceSize(), child_one_pass.get(), blend_modes[1]); | |
778 SurfaceDrawQuad* grandchild_surface_quad = | |
779 child_one_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); | |
780 grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(), | |
781 gfx::Rect(SurfaceSize()), | |
782 gfx::Rect(SurfaceSize()), | |
783 grandchild_surface_id); | |
784 AddSolidColorQuadWithBlendMode( | |
785 SurfaceSize(), child_one_pass.get(), blend_modes[3]); | |
786 QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id); | |
787 | |
788 SurfaceId child_two_surface_id = allocator_.GenerateId(); | |
789 factory_.Create(child_two_surface_id); | |
790 | |
791 scoped_ptr<RenderPass> child_two_pass = RenderPass::Create(); | |
792 child_two_pass->SetNew( | |
793 pass_id, output_rect, damage_rect, transform_to_root_target); | |
794 AddSolidColorQuadWithBlendMode( | |
795 SurfaceSize(), child_two_pass.get(), blend_modes[5]); | |
796 QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id); | |
797 | |
798 scoped_ptr<RenderPass> root_pass = RenderPass::Create(); | |
799 root_pass->SetNew( | |
800 pass_id, output_rect, damage_rect, transform_to_root_target); | |
801 | |
802 AddSolidColorQuadWithBlendMode( | |
803 SurfaceSize(), root_pass.get(), blend_modes[0]); | |
804 SurfaceDrawQuad* child_one_surface_quad = | |
805 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); | |
806 child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(), | |
807 gfx::Rect(SurfaceSize()), | |
808 gfx::Rect(SurfaceSize()), | |
809 child_one_surface_id); | |
810 AddSolidColorQuadWithBlendMode( | |
811 SurfaceSize(), root_pass.get(), blend_modes[4]); | |
812 SurfaceDrawQuad* child_two_surface_quad = | |
813 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); | |
814 child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(), | |
815 gfx::Rect(SurfaceSize()), | |
816 gfx::Rect(SurfaceSize()), | |
817 child_two_surface_id); | |
818 AddSolidColorQuadWithBlendMode( | |
819 SurfaceSize(), root_pass.get(), blend_modes[6]); | |
820 | |
821 QueuePassAsFrame(root_pass.Pass(), root_surface_id_); | |
822 | |
823 scoped_ptr<CompositorFrame> aggregated_frame = | |
824 aggregator_.Aggregate(root_surface_id_); | |
825 | |
826 ASSERT_TRUE(aggregated_frame); | |
827 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
828 | |
829 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
830 | |
831 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
832 | |
833 ASSERT_EQ(1u, aggregated_pass_list.size()); | |
834 | |
835 const QuadList& aggregated_quad_list = aggregated_pass_list[0]->quad_list; | |
836 | |
837 ASSERT_EQ(7u, aggregated_quad_list.size()); | |
838 | |
839 for (auto iter = aggregated_quad_list.cbegin(); | |
840 iter != aggregated_quad_list.cend(); | |
841 ++iter) { | |
842 EXPECT_EQ(blend_modes[iter.index()], iter->shared_quad_state->blend_mode) | |
843 << iter.index(); | |
844 } | |
845 factory_.Destroy(child_one_surface_id); | |
846 factory_.Destroy(child_two_surface_id); | |
847 factory_.Destroy(grandchild_surface_id); | |
848 } | |
849 | |
850 // This tests that when aggregating a frame with multiple render passes that we | |
851 // map the transforms for the root pass but do not modify the transform on child | |
852 // passes. | |
853 // | |
854 // The root surface has one pass with a surface quad transformed by +10 in the y | |
855 // direction. | |
856 // | |
857 // The middle surface has one pass with a surface quad scaled by 2 in the x | |
858 // and 3 in the y directions. | |
859 // | |
860 // The child surface has two passes. The first pass has a quad with a transform | |
861 // of +5 in the x direction. The second pass has a reference to the first pass' | |
862 // pass id and a transform of +8 in the x direction. | |
863 // | |
864 // After aggregation, the child surface's root pass quad should have all | |
865 // transforms concatenated for a total transform of +23 x, +10 y. The | |
866 // contributing render pass' transform in the aggregate frame should not be | |
867 // affected. | |
868 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { | |
869 // Innermost child surface. | |
870 SurfaceId child_surface_id = allocator_.GenerateId(); | |
871 { | |
872 factory_.Create(child_surface_id); | |
873 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)}; | |
874 test::Quad child_quads[][1] = { | |
875 {test::Quad::SolidColorQuad(SK_ColorGREEN)}, | |
876 {test::Quad::RenderPassQuad(child_pass_id[0])}, | |
877 }; | |
878 test::Pass child_passes[] = { | |
879 test::Pass(child_quads[0], arraysize(child_quads[0]), child_pass_id[0]), | |
880 test::Pass(child_quads[1], arraysize(child_quads[1]), | |
881 child_pass_id[1])}; | |
882 | |
883 RenderPassList child_pass_list; | |
884 AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes, | |
885 arraysize(child_passes)); | |
886 | |
887 RenderPass* child_nonroot_pass = child_pass_list.at(0u); | |
888 child_nonroot_pass->transform_to_root_target.Translate(8, 0); | |
889 SharedQuadState* child_nonroot_pass_sqs = | |
890 child_nonroot_pass->shared_quad_state_list.front(); | |
891 child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0); | |
892 | |
893 RenderPass* child_root_pass = child_pass_list.at(1u); | |
894 SharedQuadState* child_root_pass_sqs = | |
895 child_root_pass->shared_quad_state_list.front(); | |
896 child_root_pass_sqs->content_to_target_transform.Translate(8, 0); | |
897 child_root_pass_sqs->is_clipped = true; | |
898 child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5); | |
899 | |
900 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData); | |
901 child_pass_list.swap(child_frame_data->render_pass_list); | |
902 | |
903 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); | |
904 child_frame->delegated_frame_data = child_frame_data.Pass(); | |
905 | |
906 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), | |
907 SurfaceFactory::DrawCallback()); | |
908 } | |
909 | |
910 // Middle child surface. | |
911 SurfaceId middle_surface_id = allocator_.GenerateId(); | |
912 { | |
913 factory_.Create(middle_surface_id); | |
914 test::Quad middle_quads[] = { | |
915 test::Quad::SurfaceQuad(child_surface_id, 1.f)}; | |
916 test::Pass middle_passes[] = { | |
917 test::Pass(middle_quads, arraysize(middle_quads)), | |
918 }; | |
919 | |
920 RenderPassList middle_pass_list; | |
921 AddPasses(&middle_pass_list, gfx::Rect(SurfaceSize()), middle_passes, | |
922 arraysize(middle_passes)); | |
923 | |
924 RenderPass* middle_root_pass = middle_pass_list.at(0u); | |
925 middle_root_pass->quad_list.ElementAt(0)->visible_rect = | |
926 gfx::Rect(0, 1, 100, 7); | |
927 SharedQuadState* middle_root_pass_sqs = | |
928 middle_root_pass->shared_quad_state_list.front(); | |
929 middle_root_pass_sqs->content_to_target_transform.Scale(2, 3); | |
930 | |
931 scoped_ptr<DelegatedFrameData> middle_frame_data(new DelegatedFrameData); | |
932 middle_pass_list.swap(middle_frame_data->render_pass_list); | |
933 | |
934 scoped_ptr<CompositorFrame> middle_frame(new CompositorFrame); | |
935 middle_frame->delegated_frame_data = middle_frame_data.Pass(); | |
936 | |
937 factory_.SubmitFrame(middle_surface_id, middle_frame.Pass(), | |
938 SurfaceFactory::DrawCallback()); | |
939 } | |
940 | |
941 // Root surface. | |
942 test::Quad secondary_quads[] = { | |
943 test::Quad::SolidColorQuad(1), | |
944 test::Quad::SurfaceQuad(middle_surface_id, 1.f)}; | |
945 test::Quad root_quads[] = {test::Quad::SolidColorQuad(1)}; | |
946 test::Pass root_passes[] = { | |
947 test::Pass(secondary_quads, arraysize(secondary_quads)), | |
948 test::Pass(root_quads, arraysize(root_quads))}; | |
949 | |
950 RenderPassList root_pass_list; | |
951 AddPasses(&root_pass_list, | |
952 gfx::Rect(SurfaceSize()), | |
953 root_passes, | |
954 arraysize(root_passes)); | |
955 | |
956 root_pass_list.at(0) | |
957 ->shared_quad_state_list.front() | |
958 ->content_to_target_transform.Translate(0, 7); | |
959 root_pass_list.at(0) | |
960 ->shared_quad_state_list.ElementAt(1) | |
961 ->content_to_target_transform.Translate(0, 10); | |
962 root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect = | |
963 gfx::Rect(0, 0, 8, 100); | |
964 | |
965 root_pass_list[0]->transform_to_root_target.Translate(10, 5); | |
966 | |
967 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); | |
968 root_pass_list.swap(root_frame_data->render_pass_list); | |
969 | |
970 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); | |
971 root_frame->delegated_frame_data = root_frame_data.Pass(); | |
972 | |
973 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), | |
974 SurfaceFactory::DrawCallback()); | |
975 | |
976 scoped_ptr<CompositorFrame> aggregated_frame = | |
977 aggregator_.Aggregate(root_surface_id_); | |
978 | |
979 ASSERT_TRUE(aggregated_frame); | |
980 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
981 | |
982 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
983 | |
984 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
985 | |
986 ASSERT_EQ(3u, aggregated_pass_list.size()); | |
987 | |
988 ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size()); | |
989 | |
990 // The first pass should have one shared quad state for the one solid color | |
991 // quad. | |
992 EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size()); | |
993 // The second pass should have just two shared quad states. We'll | |
994 // verify the properties through the quads. | |
995 EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size()); | |
996 | |
997 EXPECT_EQ(1u, aggregated_pass_list[2]->shared_quad_state_list.size()); | |
998 | |
999 SharedQuadState* aggregated_first_pass_sqs = | |
1000 aggregated_pass_list[0]->shared_quad_state_list.front(); | |
1001 | |
1002 // The first pass's transform should be unaffected by the embedding and still | |
1003 // be a translation by +5 in the x direction. | |
1004 gfx::Transform expected_aggregated_first_pass_sqs_transform; | |
1005 expected_aggregated_first_pass_sqs_transform.Translate(5, 0); | |
1006 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(), | |
1007 aggregated_first_pass_sqs->content_to_target_transform.ToString()); | |
1008 | |
1009 // The first pass's transform to the root target should include the aggregated | |
1010 // transform, including the transform from the child pass to the root. | |
1011 gfx::Transform expected_first_pass_transform_to_root_target; | |
1012 expected_first_pass_transform_to_root_target.Translate(10, 5); | |
1013 expected_first_pass_transform_to_root_target.Translate(0, 10); | |
1014 expected_first_pass_transform_to_root_target.Scale(2, 3); | |
1015 expected_first_pass_transform_to_root_target.Translate(8, 0); | |
1016 EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(), | |
1017 aggregated_pass_list[0]->transform_to_root_target.ToString()); | |
1018 | |
1019 ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size()); | |
1020 | |
1021 gfx::Transform expected_root_pass_quad_transforms[2]; | |
1022 // The first quad in the root pass is the solid color quad from the original | |
1023 // root surface. Its transform should be unaffected by the aggregation and | |
1024 // still be +7 in the y direction. | |
1025 expected_root_pass_quad_transforms[0].Translate(0, 7); | |
1026 // The second quad in the root pass is aggregated from the child surface so | |
1027 // its transform should be the combination of its original translation | |
1028 // (0, 10), the middle surface draw quad's scale of (2, 3), and the | |
1029 // child surface draw quad's translation (8, 0). | |
1030 expected_root_pass_quad_transforms[1].Translate(0, 10); | |
1031 expected_root_pass_quad_transforms[1].Scale(2, 3); | |
1032 expected_root_pass_quad_transforms[1].Translate(8, 0); | |
1033 | |
1034 for (auto iter = aggregated_pass_list[1]->quad_list.cbegin(); | |
1035 iter != aggregated_pass_list[1]->quad_list.cend(); | |
1036 ++iter) { | |
1037 EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(), | |
1038 iter->quadTransform().ToString()) | |
1039 << iter.index(); | |
1040 } | |
1041 | |
1042 EXPECT_TRUE( | |
1043 aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped); | |
1044 | |
1045 // The second quad in the root pass is aggregated from the child, so its | |
1046 // clip rect must be transformed by the child's translation/scale and | |
1047 // clipped be the visible_rects for both children. | |
1048 EXPECT_EQ(gfx::Rect(0, 13, 8, 12).ToString(), | |
1049 aggregated_pass_list[1] | |
1050 ->shared_quad_state_list.ElementAt(1) | |
1051 ->clip_rect.ToString()); | |
1052 | |
1053 factory_.Destroy(middle_surface_id); | |
1054 factory_.Destroy(child_surface_id); | |
1055 } | |
1056 | |
1057 // Tests that damage rects are aggregated correctly when surfaces change. | |
1058 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { | |
1059 SurfaceId child_surface_id = allocator_.GenerateId(); | |
1060 factory_.Create(child_surface_id); | |
1061 RenderPassId child_pass_id = RenderPassId(1, 1); | |
1062 test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)}; | |
1063 test::Pass child_passes[] = { | |
1064 test::Pass(child_quads, arraysize(child_quads), child_pass_id)}; | |
1065 | |
1066 RenderPassList child_pass_list; | |
1067 AddPasses(&child_pass_list, | |
1068 gfx::Rect(SurfaceSize()), | |
1069 child_passes, | |
1070 arraysize(child_passes)); | |
1071 | |
1072 RenderPass* child_root_pass = child_pass_list.at(0u); | |
1073 SharedQuadState* child_root_pass_sqs = | |
1074 child_root_pass->shared_quad_state_list.front(); | |
1075 child_root_pass_sqs->content_to_target_transform.Translate(8, 0); | |
1076 | |
1077 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData); | |
1078 child_pass_list.swap(child_frame_data->render_pass_list); | |
1079 | |
1080 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); | |
1081 child_frame->delegated_frame_data = child_frame_data.Pass(); | |
1082 | |
1083 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), | |
1084 SurfaceFactory::DrawCallback()); | |
1085 | |
1086 RenderPassId pass_id(5, 10); | |
1087 test::Quad first_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)}; | |
1088 test::Quad root_quads[] = {test::Quad::RenderPassQuad(pass_id)}; | |
1089 | |
1090 test::Pass root_passes[] = { | |
1091 test::Pass(first_quads, arraysize(first_quads), pass_id), | |
1092 test::Pass(root_quads, arraysize(root_quads))}; | |
1093 | |
1094 RenderPassList root_pass_list; | |
1095 AddPasses(&root_pass_list, | |
1096 gfx::Rect(SurfaceSize()), | |
1097 root_passes, | |
1098 arraysize(root_passes)); | |
1099 | |
1100 root_pass_list.at(0) | |
1101 ->shared_quad_state_list.front() | |
1102 ->content_to_target_transform.Translate(0, 10); | |
1103 root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10); | |
1104 root_pass_list.at(1)->damage_rect = gfx::Rect(5, 5, 100, 100); | |
1105 | |
1106 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); | |
1107 root_pass_list.swap(root_frame_data->render_pass_list); | |
1108 | |
1109 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); | |
1110 root_frame->delegated_frame_data = root_frame_data.Pass(); | |
1111 | |
1112 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), | |
1113 SurfaceFactory::DrawCallback()); | |
1114 | |
1115 scoped_ptr<CompositorFrame> aggregated_frame = | |
1116 aggregator_.Aggregate(root_surface_id_); | |
1117 | |
1118 ASSERT_TRUE(aggregated_frame); | |
1119 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
1120 | |
1121 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); | |
1122 | |
1123 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
1124 | |
1125 ASSERT_EQ(2u, aggregated_pass_list.size()); | |
1126 | |
1127 // Damage rect for first aggregation should contain entire root surface. | |
1128 EXPECT_TRUE( | |
1129 aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize()))); | |
1130 | |
1131 { | |
1132 AddPasses(&child_pass_list, | |
1133 gfx::Rect(SurfaceSize()), | |
1134 child_passes, | |
1135 arraysize(child_passes)); | |
1136 | |
1137 RenderPass* child_root_pass = child_pass_list.at(0u); | |
1138 SharedQuadState* child_root_pass_sqs = | |
1139 child_root_pass->shared_quad_state_list.front(); | |
1140 child_root_pass_sqs->content_to_target_transform.Translate(8, 0); | |
1141 child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10); | |
1142 | |
1143 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData); | |
1144 child_pass_list.swap(child_frame_data->render_pass_list); | |
1145 | |
1146 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); | |
1147 child_frame->delegated_frame_data = child_frame_data.Pass(); | |
1148 | |
1149 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), | |
1150 SurfaceFactory::DrawCallback()); | |
1151 | |
1152 scoped_ptr<CompositorFrame> aggregated_frame = | |
1153 aggregator_.Aggregate(root_surface_id_); | |
1154 | |
1155 ASSERT_TRUE(aggregated_frame); | |
1156 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
1157 | |
1158 DelegatedFrameData* frame_data = | |
1159 aggregated_frame->delegated_frame_data.get(); | |
1160 | |
1161 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
1162 | |
1163 ASSERT_EQ(2u, aggregated_pass_list.size()); | |
1164 | |
1165 // Outer surface didn't change, so transformed inner damage rect should be | |
1166 // used. | |
1167 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(), | |
1168 aggregated_pass_list[1]->damage_rect.ToString()); | |
1169 } | |
1170 | |
1171 { | |
1172 RenderPassList root_pass_list; | |
1173 AddPasses(&root_pass_list, | |
1174 gfx::Rect(SurfaceSize()), | |
1175 root_passes, | |
1176 arraysize(root_passes)); | |
1177 | |
1178 root_pass_list.at(0) | |
1179 ->shared_quad_state_list.front() | |
1180 ->content_to_target_transform.Translate(0, 10); | |
1181 root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1); | |
1182 | |
1183 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); | |
1184 root_pass_list.swap(root_frame_data->render_pass_list); | |
1185 | |
1186 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); | |
1187 root_frame->delegated_frame_data = root_frame_data.Pass(); | |
1188 | |
1189 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), | |
1190 SurfaceFactory::DrawCallback()); | |
1191 } | |
1192 | |
1193 { | |
1194 RenderPassList root_pass_list; | |
1195 AddPasses(&root_pass_list, | |
1196 gfx::Rect(SurfaceSize()), | |
1197 root_passes, | |
1198 arraysize(root_passes)); | |
1199 | |
1200 root_pass_list.at(0) | |
1201 ->shared_quad_state_list.front() | |
1202 ->content_to_target_transform.Translate(0, 10); | |
1203 root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1); | |
1204 | |
1205 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); | |
1206 root_pass_list.swap(root_frame_data->render_pass_list); | |
1207 | |
1208 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); | |
1209 root_frame->delegated_frame_data = root_frame_data.Pass(); | |
1210 | |
1211 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), | |
1212 SurfaceFactory::DrawCallback()); | |
1213 | |
1214 scoped_ptr<CompositorFrame> aggregated_frame = | |
1215 aggregator_.Aggregate(root_surface_id_); | |
1216 | |
1217 ASSERT_TRUE(aggregated_frame); | |
1218 ASSERT_TRUE(aggregated_frame->delegated_frame_data); | |
1219 | |
1220 DelegatedFrameData* frame_data = | |
1221 aggregated_frame->delegated_frame_data.get(); | |
1222 | |
1223 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; | |
1224 | |
1225 ASSERT_EQ(2u, aggregated_pass_list.size()); | |
1226 | |
1227 // The root surface was enqueued without being aggregated once, so it should | |
1228 // be treated as completely damaged. | |
1229 EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.Contains( | |
1230 gfx::Rect(SurfaceSize()))); | |
1231 } | |
1232 | |
1233 factory_.Destroy(child_surface_id); | |
1234 } | |
1235 | |
1236 class SurfaceAggregatorWithResourcesTest : public testing::Test { | |
1237 public: | |
1238 void SetUp() override { | |
1239 output_surface_ = FakeOutputSurface::CreateSoftware( | |
1240 make_scoped_ptr(new SoftwareOutputDevice)); | |
1241 output_surface_->BindToClient(&output_surface_client_); | |
1242 shared_bitmap_manager_.reset(new TestSharedBitmapManager); | |
1243 | |
1244 resource_provider_ = ResourceProvider::Create(output_surface_.get(), | |
1245 shared_bitmap_manager_.get(), | |
1246 NULL, | |
1247 NULL, | |
1248 0, | |
1249 false, | |
1250 1); | |
1251 | |
1252 aggregator_.reset( | |
1253 new SurfaceAggregator(&manager_, resource_provider_.get())); | |
1254 } | |
1255 | |
1256 protected: | |
1257 SurfaceManager manager_; | |
1258 FakeOutputSurfaceClient output_surface_client_; | |
1259 scoped_ptr<OutputSurface> output_surface_; | |
1260 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; | |
1261 scoped_ptr<ResourceProvider> resource_provider_; | |
1262 scoped_ptr<SurfaceAggregator> aggregator_; | |
1263 }; | |
1264 | |
1265 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient { | |
1266 public: | |
1267 ResourceTrackingSurfaceFactoryClient() {} | |
1268 ~ResourceTrackingSurfaceFactoryClient() override {} | |
1269 | |
1270 void ReturnResources(const ReturnedResourceArray& resources) override { | |
1271 returned_resources_ = resources; | |
1272 } | |
1273 | |
1274 ReturnedResourceArray returned_resources() const { | |
1275 return returned_resources_; | |
1276 } | |
1277 | |
1278 private: | |
1279 ReturnedResourceArray returned_resources_; | |
1280 | |
1281 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient); | |
1282 }; | |
1283 | |
1284 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids, | |
1285 size_t num_resource_ids, | |
1286 SurfaceFactory* factory, | |
1287 SurfaceId surface_id) { | |
1288 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); | |
1289 scoped_ptr<RenderPass> pass = RenderPass::Create(); | |
1290 pass->id = RenderPassId(1, 1); | |
1291 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); | |
1292 for (size_t i = 0u; i < num_resource_ids; ++i) { | |
1293 TransferableResource resource; | |
1294 resource.id = resource_ids[i]; | |
1295 resource.is_software = true; | |
1296 frame_data->resource_list.push_back(resource); | |
1297 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
1298 const gfx::Rect rect; | |
1299 const gfx::Rect opaque_rect; | |
1300 const gfx::Rect visible_rect; | |
1301 bool needs_blending = false; | |
1302 bool premultiplied_alpha = false; | |
1303 const gfx::PointF uv_top_left; | |
1304 const gfx::PointF uv_bottom_right; | |
1305 SkColor background_color = SK_ColorGREEN; | |
1306 const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f}; | |
1307 bool flipped = false; | |
1308 bool nearest_neighbor = false; | |
1309 quad->SetAll(sqs, | |
1310 rect, | |
1311 opaque_rect, | |
1312 visible_rect, | |
1313 needs_blending, | |
1314 resource_ids[i], | |
1315 premultiplied_alpha, | |
1316 uv_top_left, | |
1317 uv_bottom_right, | |
1318 background_color, | |
1319 vertex_opacity, | |
1320 flipped, | |
1321 nearest_neighbor); | |
1322 | |
1323 quad->shared_quad_state = sqs; | |
1324 } | |
1325 frame_data->render_pass_list.push_back(pass.Pass()); | |
1326 scoped_ptr<CompositorFrame> frame(new CompositorFrame); | |
1327 frame->delegated_frame_data = frame_data.Pass(); | |
1328 factory->SubmitFrame(surface_id, frame.Pass(), | |
1329 SurfaceFactory::DrawCallback()); | |
1330 } | |
1331 | |
1332 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { | |
1333 ResourceTrackingSurfaceFactoryClient client; | |
1334 SurfaceFactory factory(&manager_, &client); | |
1335 SurfaceId surface_id(7u); | |
1336 factory.Create(surface_id); | |
1337 | |
1338 ResourceProvider::ResourceId ids[] = {11, 12, 13}; | |
1339 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id); | |
1340 | |
1341 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id); | |
1342 | |
1343 // Nothing should be available to be returned yet. | |
1344 EXPECT_TRUE(client.returned_resources().empty()); | |
1345 | |
1346 SubmitFrameWithResources(NULL, 0u, &factory, surface_id); | |
1347 | |
1348 frame = aggregator_->Aggregate(surface_id); | |
1349 | |
1350 ASSERT_EQ(3u, client.returned_resources().size()); | |
1351 ResourceProvider::ResourceId returned_ids[3]; | |
1352 for (size_t i = 0; i < 3; ++i) { | |
1353 returned_ids[i] = client.returned_resources()[i].id; | |
1354 } | |
1355 EXPECT_THAT(returned_ids, | |
1356 testing::WhenSorted(testing::ElementsAreArray(ids))); | |
1357 factory.Destroy(surface_id); | |
1358 } | |
1359 | |
1360 TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { | |
1361 ResourceTrackingSurfaceFactoryClient client; | |
1362 SurfaceFactory factory(&manager_, &client); | |
1363 SurfaceId surface_id(7u); | |
1364 factory.Create(surface_id); | |
1365 | |
1366 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); | |
1367 scoped_ptr<RenderPass> pass = RenderPass::Create(); | |
1368 pass->id = RenderPassId(1, 1); | |
1369 TransferableResource resource; | |
1370 resource.id = 11; | |
1371 // ResourceProvider is software but resource is not, so it should be | |
1372 // ignored. | |
1373 resource.is_software = false; | |
1374 frame_data->resource_list.push_back(resource); | |
1375 frame_data->render_pass_list.push_back(pass.Pass()); | |
1376 scoped_ptr<CompositorFrame> frame(new CompositorFrame); | |
1377 frame->delegated_frame_data = frame_data.Pass(); | |
1378 factory.SubmitFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback()); | |
1379 | |
1380 scoped_ptr<CompositorFrame> returned_frame = | |
1381 aggregator_->Aggregate(surface_id); | |
1382 | |
1383 // Nothing should be available to be returned yet. | |
1384 EXPECT_TRUE(client.returned_resources().empty()); | |
1385 | |
1386 SubmitFrameWithResources(NULL, 0u, &factory, surface_id); | |
1387 ASSERT_EQ(1u, client.returned_resources().size()); | |
1388 EXPECT_EQ(11u, client.returned_resources()[0].id); | |
1389 | |
1390 factory.Destroy(surface_id); | |
1391 } | |
1392 | |
1393 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { | |
1394 ResourceTrackingSurfaceFactoryClient client; | |
1395 SurfaceFactory factory(&manager_, &client); | |
1396 SurfaceId surface_id(7u); | |
1397 factory.Create(surface_id); | |
1398 SurfaceId surface_id2(8u); | |
1399 factory.Create(surface_id2); | |
1400 | |
1401 ResourceProvider::ResourceId ids[] = {11, 12, 13}; | |
1402 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id); | |
1403 ResourceProvider::ResourceId ids2[] = {14, 15, 16}; | |
1404 SubmitFrameWithResources(ids2, arraysize(ids2), &factory, surface_id2); | |
1405 | |
1406 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id); | |
1407 | |
1408 SubmitFrameWithResources(NULL, 0, &factory, surface_id); | |
1409 | |
1410 // Nothing should be available to be returned yet. | |
1411 EXPECT_TRUE(client.returned_resources().empty()); | |
1412 | |
1413 frame = aggregator_->Aggregate(surface_id2); | |
1414 | |
1415 // surface_id wasn't referenced, so its resources should be returned. | |
1416 ASSERT_EQ(3u, client.returned_resources().size()); | |
1417 ResourceProvider::ResourceId returned_ids[3]; | |
1418 for (size_t i = 0; i < 3; ++i) { | |
1419 returned_ids[i] = client.returned_resources()[i].id; | |
1420 } | |
1421 EXPECT_THAT(returned_ids, | |
1422 testing::WhenSorted(testing::ElementsAreArray(ids))); | |
1423 EXPECT_EQ(3u, resource_provider_->num_resources()); | |
1424 factory.Destroy(surface_id); | |
1425 factory.Destroy(surface_id2); | |
1426 } | |
1427 | |
1428 } // namespace | |
1429 } // namespace cc | |
1430 | |
OLD | NEW |