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 |