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 <map> 6 #include <memory> 7 #include <queue> 8 #include <utility> 9 10 #include "android_webview/browser/gfx/browser_view_renderer.h" 11 #include "android_webview/browser/gfx/child_frame.h" 12 #include "android_webview/browser/gfx/compositor_frame_consumer.h" 13 #include "android_webview/browser/gfx/render_thread_manager.h" 14 #include "android_webview/browser/gfx/test/rendering_test.h" 15 #include "base/bind.h" 16 #include "base/location.h" 17 #include "base/single_thread_task_runner.h" 18 #include "base/stl_util.h" 19 #include "base/threading/thread_task_runner_handle.h" 20 #include "components/viz/common/quads/compositor_frame.h" 21 #include "components/viz/common/surfaces/frame_sink_id.h" 22 #include "content/public/common/use_zoom_for_dsf_policy.h" 23 #include "content/public/test/test_synchronous_compositor_android.h" 24 25 namespace android_webview { 26 27 class SmokeTest : public RenderingTest { StartTest()28 void StartTest() override { 29 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 30 } 31 DidDrawOnRT()32 void DidDrawOnRT() override { EndTest(); } 33 }; 34 35 RENDERING_TEST_F(SmokeTest); 36 37 // Test the case where SynchronousCompositor is constructed after the RVH that 38 // owns it is switched to be active. 39 class ActiveCompositorSwitchBeforeConstructionTest : public RenderingTest { 40 public: ActiveCompositorSwitchBeforeConstructionTest()41 ActiveCompositorSwitchBeforeConstructionTest() 42 : on_draw_count_(0), new_compositor_(nullptr) {} StartTest()43 void StartTest() override { 44 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 45 } 46 DidOnDraw(bool success)47 void DidOnDraw(bool success) override { 48 on_draw_count_++; 49 switch (on_draw_count_) { 50 case 1: 51 EXPECT_TRUE(success); 52 // Change compositor here. And do another ondraw. 53 // The previous active compositor id is 0, 0, now change it to 0, 1. 54 browser_view_renderer_->SetActiveFrameSinkId(viz::FrameSinkId(0, 1)); 55 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 56 break; 57 case 2: 58 // The 2nd ondraw is skipped because there is no active compositor at 59 // the moment. 60 EXPECT_FALSE(success); 61 new_compositor_.reset( 62 new content::TestSynchronousCompositor(viz::FrameSinkId(0, 1))); 63 new_compositor_->SetClient(browser_view_renderer_.get()); 64 EXPECT_EQ(ActiveCompositor(), new_compositor_.get()); 65 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 66 break; 67 case 3: 68 EXPECT_TRUE(success); 69 compositor_ = std::move(new_compositor_); 70 71 EXPECT_EQ(ActiveCompositor(), compositor_.get()); 72 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 73 break; 74 case 4: 75 EXPECT_TRUE(success); 76 EndTest(); 77 } 78 } 79 80 private: 81 int on_draw_count_; 82 std::unique_ptr<content::TestSynchronousCompositor> new_compositor_; 83 }; 84 85 RENDERING_TEST_F(ActiveCompositorSwitchBeforeConstructionTest); 86 87 // Test the case where SynchronousCompositor is constructed before the RVH that 88 // owns it is switched to be active. 89 class ActiveCompositorSwitchAfterConstructionTest : public RenderingTest { 90 public: ActiveCompositorSwitchAfterConstructionTest()91 ActiveCompositorSwitchAfterConstructionTest() 92 : on_draw_count_(0), new_compositor_(nullptr) {} StartTest()93 void StartTest() override { 94 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 95 } 96 DidOnDraw(bool success)97 void DidOnDraw(bool success) override { 98 on_draw_count_++; 99 switch (on_draw_count_) { 100 case 1: 101 EXPECT_TRUE(success); 102 // Create a new compositor here. And switch it to be active. And then 103 // do another ondraw. 104 new_compositor_.reset( 105 new content::TestSynchronousCompositor(viz::FrameSinkId(0, 1))); 106 new_compositor_->SetClient(browser_view_renderer_.get()); 107 browser_view_renderer_->SetActiveFrameSinkId(viz::FrameSinkId(0, 1)); 108 109 EXPECT_EQ(ActiveCompositor(), new_compositor_.get()); 110 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 111 break; 112 case 2: 113 EXPECT_TRUE(success); 114 compositor_ = std::move(new_compositor_); 115 116 EXPECT_EQ(ActiveCompositor(), compositor_.get()); 117 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 118 break; 119 case 3: 120 EXPECT_TRUE(success); 121 EndTest(); 122 } 123 } 124 125 private: 126 int on_draw_count_; 127 std::unique_ptr<content::TestSynchronousCompositor> new_compositor_; 128 }; 129 130 RENDERING_TEST_F(ActiveCompositorSwitchAfterConstructionTest); 131 132 class ClearViewTest : public RenderingTest { 133 public: ClearViewTest()134 ClearViewTest() : on_draw_count_(0) {} 135 StartTest()136 void StartTest() override { 137 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 138 browser_view_renderer_->ClearView(); 139 } 140 DidOnDraw(bool success)141 void DidOnDraw(bool success) override { 142 on_draw_count_++; 143 if (on_draw_count_ == 1) { 144 // First OnDraw should be skipped due to ClearView. 145 EXPECT_FALSE(success); 146 browser_view_renderer_->DidUpdateContent( 147 ActiveCompositor()); // Unset ClearView. 148 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 149 } else { 150 // Following OnDraws should succeed. 151 EXPECT_TRUE(success); 152 } 153 } 154 DidDrawOnRT()155 void DidDrawOnRT() override { EndTest(); } 156 157 private: 158 int on_draw_count_; 159 }; 160 161 RENDERING_TEST_F(ClearViewTest); 162 163 class TestAnimateInAndOutOfScreen : public RenderingTest { 164 public: TestAnimateInAndOutOfScreen()165 TestAnimateInAndOutOfScreen() : on_draw_count_(0), draw_gl_count_on_rt_(0) {} 166 StartTest()167 void StartTest() override { 168 initial_constraints_ = ParentCompositorDrawConstraints( 169 window_->surface_size(), gfx::Transform()); 170 new_constraints_ = ParentCompositorDrawConstraints(window_->surface_size(), 171 gfx::Transform()); 172 new_constraints_.transform.Scale(2.0, 2.0); 173 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 174 } 175 WillOnDraw()176 void WillOnDraw() override { 177 RenderingTest::WillOnDraw(); 178 // Step 0: A single onDraw on screen. The parent draw constraints 179 // of the BVR will updated to be the initial constraints. 180 // Step 1: A single onDrraw off screen. The parent draw constraints of the 181 // BVR will be updated to the new constraints. 182 // Step 2: This onDraw is to introduce the DrawGL that animates the 183 // webview onto the screen on render thread. End the test when the parent 184 // draw constraints of BVR is updated to initial constraints. 185 if (on_draw_count_ == 1 || on_draw_count_ == 2) 186 browser_view_renderer_->PrepareToDraw(gfx::Vector2d(), gfx::Rect()); 187 } 188 DidOnDraw(bool success)189 void DidOnDraw(bool success) override { 190 EXPECT_TRUE(success); 191 on_draw_count_++; 192 } 193 WillDrawOnRT(HardwareRendererDrawParams * params)194 bool WillDrawOnRT(HardwareRendererDrawParams* params) override { 195 if (draw_gl_count_on_rt_ == 1) { 196 draw_gl_count_on_rt_++; 197 ui_task_runner_->PostTask(FROM_HERE, 198 base::BindOnce(&RenderingTest::PostInvalidate, 199 base::Unretained(this))); 200 return false; 201 } 202 203 params->width = window_->surface_size().width(); 204 params->height = window_->surface_size().height(); 205 206 gfx::Transform transform; 207 if (draw_gl_count_on_rt_ == 0) 208 transform = new_constraints_.transform; 209 210 transform.matrix().asColMajorf(params->transform); 211 return true; 212 } 213 DidDrawOnRT()214 void DidDrawOnRT() override { draw_gl_count_on_rt_++; } 215 DrawConstraintsEquals(const ParentCompositorDrawConstraints & constraints1,const ParentCompositorDrawConstraints & constraints2)216 bool DrawConstraintsEquals( 217 const ParentCompositorDrawConstraints& constraints1, 218 const ParentCompositorDrawConstraints& constraints2) { 219 return constraints1 == constraints2; 220 } 221 OnParentDrawDataUpdated()222 void OnParentDrawDataUpdated() override { 223 ParentCompositorDrawConstraints constraints; 224 viz::FrameSinkId frame_sink_id; 225 viz::FrameTimingDetailsMap timing_details; 226 uint32_t frame_token = 0u; 227 GetCompositorFrameConsumer()->TakeParentDrawDataOnUI( 228 &constraints, &frame_sink_id, &timing_details, &frame_token); 229 switch (on_draw_count_) { 230 case 0u: 231 // This OnParentDrawDataUpdated is generated by 232 // connecting the compositor frame consumer to the producer. 233 break; 234 case 1u: 235 EXPECT_TRUE(DrawConstraintsEquals(constraints, new_constraints_)); 236 break; 237 case 3u: 238 EXPECT_TRUE(DrawConstraintsEquals(constraints, initial_constraints_)); 239 EndTest(); 240 break; 241 // There will be a following 4th onDraw. But the hardware renderer won't 242 // post back the draw constraints in DrawGL because the constraints 243 // don't change. 244 default: 245 FAIL(); 246 } 247 } 248 249 private: 250 int on_draw_count_; 251 int draw_gl_count_on_rt_; 252 ParentCompositorDrawConstraints initial_constraints_; 253 ParentCompositorDrawConstraints new_constraints_; 254 }; 255 256 RENDERING_TEST_F(TestAnimateInAndOutOfScreen); 257 258 class TestAnimateOnScreenWithoutOnDraw : public RenderingTest { 259 public: StartTest()260 void StartTest() override { 261 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 262 } 263 WillOnDraw()264 void WillOnDraw() override { 265 RenderingTest::WillOnDraw(); 266 // Set empty tile viewport on first frame. 267 browser_view_renderer_->PrepareToDraw(gfx::Vector2d(), gfx::Rect()); 268 } 269 DidOnDraw(bool success)270 void DidOnDraw(bool success) override { 271 EXPECT_TRUE(success); 272 on_draw_count_++; 273 } 274 WillDrawOnRT(HardwareRendererDrawParams * params)275 bool WillDrawOnRT(HardwareRendererDrawParams* params) override { 276 will_draw_on_rt_count_++; 277 // What happens in practice is draw functor is skipped initially since 278 // it is offscreen so entirely clipped. Then later, the webview is moved 279 // onscreen without another OnDrawon UI thread, and draw functor is called 280 // with non-empty clip. Here in the test we pretend this second draw happens 281 // immediately. 282 bool result = RenderingTest::WillDrawOnRT(params); 283 assertNonEmptyClip(params); 284 return result; 285 } 286 OnParentDrawDataUpdated()287 void OnParentDrawDataUpdated() override { 288 switch (on_draw_count_) { 289 case 0: 290 // This OnParentDrawDataUpdated is generated by 291 // connecting the compositor frame consumer to the producer. 292 break; 293 case 1: 294 // DrawOnRT skipped for frame 1 so this should not happen. 295 EXPECT_TRUE(window_->on_draw_hardware_pending()); 296 EndTest(); 297 break; 298 case 2: 299 // Might happen due to invalidate on_draw_hardware_pending from 300 // previous frame. 301 break; 302 default: 303 FAIL(); 304 break; 305 } 306 } 307 308 private: assertNonEmptyClip(HardwareRendererDrawParams * params)309 void assertNonEmptyClip(HardwareRendererDrawParams* params) { 310 gfx::Rect clip(params->clip_left, params->clip_top, 311 params->clip_right - params->clip_left, 312 params->clip_bottom - params->clip_top); 313 ASSERT_FALSE(clip.IsEmpty()); 314 } 315 316 int on_draw_count_ = 0; 317 int will_draw_on_rt_count_ = 0; 318 }; 319 320 RENDERING_TEST_F(TestAnimateOnScreenWithoutOnDraw); 321 322 class CompositorNoFrameTest : public RenderingTest { 323 public: CompositorNoFrameTest()324 CompositorNoFrameTest() : on_draw_count_(0) {} 325 StartTest()326 void StartTest() override { 327 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 328 } 329 WillOnDraw()330 void WillOnDraw() override { 331 if (0 == on_draw_count_) { 332 // No frame from compositor. 333 } else if (1 == on_draw_count_) { 334 compositor_->SetHardwareFrame(0u, ConstructEmptyFrame()); 335 } else if (2 == on_draw_count_) { 336 // No frame from compositor. 337 } 338 // There may be trailing invalidates. 339 } 340 DidOnDraw(bool success)341 void DidOnDraw(bool success) override { 342 // OnDraw should succeed even when there are no frames from compositor. 343 EXPECT_TRUE(success); 344 if (0 == on_draw_count_) { 345 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 346 } else if (1 == on_draw_count_) { 347 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 348 } else if (2 == on_draw_count_) { 349 EndTest(); 350 } 351 on_draw_count_++; 352 } 353 354 private: 355 int on_draw_count_; 356 }; 357 358 RENDERING_TEST_F(CompositorNoFrameTest); 359 360 class ClientIsVisibleOnConstructionTest : public RenderingTest { SetUpTestHarness()361 void SetUpTestHarness() override { 362 browser_view_renderer_.reset( 363 new BrowserViewRenderer(this, base::ThreadTaskRunnerHandle::Get())); 364 } 365 StartTest()366 void StartTest() override { 367 EXPECT_FALSE(browser_view_renderer_->attached_to_window()); 368 EXPECT_FALSE(browser_view_renderer_->window_visible_for_tests()); 369 EXPECT_TRUE(browser_view_renderer_->IsClientVisible()); 370 EndTest(); 371 } 372 }; 373 374 RENDERING_TEST_F(ClientIsVisibleOnConstructionTest); 375 376 class ClientIsVisibleAfterAttachTest : public RenderingTest { StartTest()377 void StartTest() override { 378 EXPECT_TRUE(browser_view_renderer_->attached_to_window()); 379 EXPECT_TRUE(browser_view_renderer_->window_visible_for_tests()); 380 381 EXPECT_TRUE(browser_view_renderer_->IsClientVisible()); 382 EndTest(); 383 } 384 }; 385 386 RENDERING_TEST_F(ClientIsVisibleAfterAttachTest); 387 388 class ClientIsInvisibleAfterWindowGoneTest : public RenderingTest { StartTest()389 void StartTest() override { 390 browser_view_renderer_->SetWindowVisibility(false); 391 EXPECT_FALSE(browser_view_renderer_->IsClientVisible()); 392 EndTest(); 393 } 394 }; 395 396 RENDERING_TEST_F(ClientIsInvisibleAfterWindowGoneTest); 397 398 class ClientIsInvisibleAfterDetachTest : public RenderingTest { StartTest()399 void StartTest() override { 400 browser_view_renderer_->OnDetachedFromWindow(); 401 EXPECT_FALSE(browser_view_renderer_->IsClientVisible()); 402 EndTest(); 403 } 404 }; 405 406 RENDERING_TEST_F(ClientIsInvisibleAfterDetachTest); 407 408 class ResourceRenderingTest : public RenderingTest { 409 public: 410 using ResourceCountMap = std::map<viz::ResourceId, int>; 411 using LayerTreeFrameSinkResourceCountMap = 412 std::map<uint32_t, ResourceCountMap>; 413 414 virtual std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame( 415 int frame_number) = 0; 416 StartTest()417 void StartTest() override { 418 frame_number_ = 0; 419 AdvanceFrame(); 420 } 421 WillOnDraw()422 void WillOnDraw() override { 423 if (next_frame_) { 424 compositor_->SetHardwareFrame(next_frame_->layer_tree_frame_sink_id, 425 std::move(next_frame_->frame)); 426 } 427 } 428 DidOnDraw(bool success)429 void DidOnDraw(bool success) override { 430 EXPECT_EQ(next_frame_ != nullptr, success); 431 if (!AdvanceFrame()) { 432 ui_task_runner_->PostTask( 433 FROM_HERE, base::BindOnce(&ResourceRenderingTest::CheckResults, 434 base::Unretained(this))); 435 } 436 } 437 GetReturnedResourceCounts()438 LayerTreeFrameSinkResourceCountMap GetReturnedResourceCounts() { 439 LayerTreeFrameSinkResourceCountMap counts; 440 content::TestSynchronousCompositor::FrameAckArray returned_resources_array; 441 compositor_->SwapReturnedResources(&returned_resources_array); 442 for (const auto& resources : returned_resources_array) { 443 for (const auto& returned_resource : resources.resources) { 444 counts[resources.layer_tree_frame_sink_id][returned_resource.id] += 445 returned_resource.count; 446 } 447 } 448 return counts; 449 } 450 451 virtual void CheckResults() = 0; 452 453 private: AdvanceFrame()454 bool AdvanceFrame() { 455 next_frame_ = GetFrame(frame_number_++); 456 if (next_frame_) { 457 browser_view_renderer_->PostInvalidate(ActiveCompositor()); 458 return true; 459 } 460 return false; 461 } 462 463 std::unique_ptr<content::SynchronousCompositor::Frame> next_frame_; 464 int frame_number_; 465 }; 466 467 class SwitchLayerTreeFrameSinkIdTest : public ResourceRenderingTest { 468 struct FrameInfo { 469 uint32_t layer_tree_frame_sink_id; 470 viz::ResourceId resource_id; // Each frame contains a single resource. 471 }; 472 GetFrame(int frame_number)473 std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame( 474 int frame_number) override { 475 static const FrameInfo infos[] = { 476 // First output surface. 477 {0u, 1u}, {0u, 1u}, {0u, 2u}, {0u, 2u}, {0u, 3u}, {0u, 3u}, {0u, 4u}, 478 // Second output surface. 479 {1u, 1u}, {1u, 1u}, {1u, 2u}, {1u, 2u}, {1u, 3u}, {1u, 3u}, {1u, 4u}, 480 }; 481 if (frame_number >= static_cast<int>(base::size(infos))) { 482 return nullptr; 483 } 484 485 std::unique_ptr<content::SynchronousCompositor::Frame> frame( 486 new content::SynchronousCompositor::Frame); 487 frame->layer_tree_frame_sink_id = 488 infos[frame_number].layer_tree_frame_sink_id; 489 frame->frame = ConstructFrame(infos[frame_number].resource_id); 490 491 if (last_layer_tree_frame_sink_id_ != 492 infos[frame_number].layer_tree_frame_sink_id) { 493 expected_return_count_.clear(); 494 last_layer_tree_frame_sink_id_ = 495 infos[frame_number].layer_tree_frame_sink_id; 496 } 497 ++expected_return_count_[infos[frame_number].resource_id]; 498 return frame; 499 } 500 StartTest()501 void StartTest() override { 502 last_layer_tree_frame_sink_id_ = -1U; 503 ResourceRenderingTest::StartTest(); 504 } 505 CheckResults()506 void CheckResults() override { 507 window_->Detach(); 508 functor_->ReleaseOnUIWithInvoke(); 509 ui_task_runner_->PostTask( 510 FROM_HERE, 511 base::BindOnce(&SwitchLayerTreeFrameSinkIdTest::PostedCheckResults, 512 base::Unretained(this))); 513 } 514 PostedCheckResults()515 void PostedCheckResults() { 516 // Make sure resources for the last output surface are returned. 517 EXPECT_EQ(expected_return_count_, 518 GetReturnedResourceCounts()[last_layer_tree_frame_sink_id_]); 519 EndTest(); 520 } 521 522 private: 523 uint32_t last_layer_tree_frame_sink_id_; 524 ResourceCountMap expected_return_count_; 525 }; 526 527 RENDERING_TEST_F(SwitchLayerTreeFrameSinkIdTest); 528 529 class RenderThreadManagerDeletionTest : public ResourceRenderingTest { GetFrame(int frame_number)530 std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame( 531 int frame_number) override { 532 if (frame_number > 0) { 533 return nullptr; 534 } 535 536 const uint32_t layer_tree_frame_sink_id = 0u; 537 const viz::ResourceId resource_id = 538 static_cast<viz::ResourceId>(frame_number); 539 540 std::unique_ptr<content::SynchronousCompositor::Frame> frame( 541 new content::SynchronousCompositor::Frame); 542 frame->layer_tree_frame_sink_id = layer_tree_frame_sink_id; 543 frame->frame = ConstructFrame(resource_id); 544 ++expected_return_count_[layer_tree_frame_sink_id][resource_id]; 545 return frame; 546 } 547 CheckResults()548 void CheckResults() override { 549 functor_.reset(); 550 ui_task_runner_->PostTask( 551 FROM_HERE, 552 base::BindOnce(&RenderThreadManagerDeletionTest::PostedCheckResults, 553 base::Unretained(this))); 554 } 555 PostedCheckResults()556 void PostedCheckResults() { 557 // Make sure resources for the last frame are returned. 558 EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts()); 559 EndTest(); 560 } 561 562 private: 563 LayerTreeFrameSinkResourceCountMap expected_return_count_; 564 }; 565 566 RENDERING_TEST_F(RenderThreadManagerDeletionTest); 567 568 class RenderThreadManagerDeletionOnRTTest : public ResourceRenderingTest { GetFrame(int frame_number)569 std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame( 570 int frame_number) override { 571 if (frame_number > 0) { 572 return nullptr; 573 } 574 575 const uint32_t layer_tree_frame_sink_id = 0u; 576 const viz::ResourceId resource_id = 577 static_cast<viz::ResourceId>(frame_number); 578 579 std::unique_ptr<content::SynchronousCompositor::Frame> frame( 580 new content::SynchronousCompositor::Frame); 581 frame->layer_tree_frame_sink_id = layer_tree_frame_sink_id; 582 frame->frame = ConstructFrame(resource_id); 583 ++expected_return_count_[layer_tree_frame_sink_id][resource_id]; 584 return frame; 585 } 586 CheckResults()587 void CheckResults() override { 588 functor_->ReleaseOnUIWithoutInvoke( 589 base::BindOnce(&RenderThreadManagerDeletionOnRTTest::PostedCheckResults, 590 base::Unretained(this))); 591 } 592 PostedCheckResults()593 void PostedCheckResults() { 594 // Make sure resources for the last frame are returned. 595 EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts()); 596 EndTest(); 597 } 598 599 private: 600 LayerTreeFrameSinkResourceCountMap expected_return_count_; 601 }; 602 603 RENDERING_TEST_F(RenderThreadManagerDeletionOnRTTest); 604 605 class RenderThreadManagerSwitchTest : public ResourceRenderingTest { GetFrame(int frame_number)606 std::unique_ptr<content::SynchronousCompositor::Frame> GetFrame( 607 int frame_number) override { 608 switch (frame_number) { 609 case 0: { 610 // Draw a frame with initial RTM. 611 break; 612 } 613 case 1: { 614 // Switch to new RTM. 615 std::unique_ptr<FakeFunctor> functor(new FakeFunctor); 616 functor->Init(window_.get(), std::make_unique<RenderThreadManager>( 617 base::ThreadTaskRunnerHandle::Get())); 618 browser_view_renderer_->SetCurrentCompositorFrameConsumer( 619 functor->GetCompositorFrameConsumer()); 620 saved_functor_ = std::move(functor_); 621 functor_ = std::move(functor); 622 break; 623 } 624 case 2: { 625 // Draw a frame with the new RTM, but also redraw the initial RTM. 626 window_->RequestDrawGL(saved_functor_.get()); 627 break; 628 } 629 case 3: { 630 // Switch back to the initial RTM, allowing the new RTM to be destroyed. 631 functor_ = std::move(saved_functor_); 632 browser_view_renderer_->SetCurrentCompositorFrameConsumer( 633 functor_->GetCompositorFrameConsumer()); 634 break; 635 } 636 default: 637 return nullptr; 638 } 639 640 const uint32_t layer_tree_frame_sink_id = 0u; 641 const viz::ResourceId resource_id = 642 static_cast<viz::ResourceId>(frame_number); 643 644 std::unique_ptr<content::SynchronousCompositor::Frame> frame( 645 new content::SynchronousCompositor::Frame); 646 frame->layer_tree_frame_sink_id = layer_tree_frame_sink_id; 647 frame->frame = ConstructFrame(resource_id); 648 ++expected_return_count_[layer_tree_frame_sink_id][resource_id]; 649 return frame; 650 } 651 CheckResults()652 void CheckResults() override { 653 functor_.reset(); 654 ui_task_runner_->PostTask( 655 FROM_HERE, 656 base::BindOnce(&RenderThreadManagerSwitchTest::PostedCheckResults, 657 base::Unretained(this))); 658 } 659 PostedCheckResults()660 void PostedCheckResults() { 661 // Make sure resources for all frames are returned. 662 EXPECT_EQ(expected_return_count_, GetReturnedResourceCounts()); 663 EndTest(); 664 } 665 666 private: 667 std::unique_ptr<FakeFunctor> saved_functor_; 668 LayerTreeFrameSinkResourceCountMap expected_return_count_; 669 }; 670 671 RENDERING_TEST_F(RenderThreadManagerSwitchTest); 672 673 // Test for https://crbug.com/881458, this test is to make sure we will reach 674 // the maximal scroll offset. 675 class DidReachMaximalScrollOffsetTest : public RenderingTest { 676 public: StartTest()677 void StartTest() override { 678 browser_view_renderer_->SetDipScale(kDipScale); 679 gfx::Vector2dF total_scroll_offset = kTotalScrollOffset; 680 gfx::Vector2dF total_max_scroll_offset = kTotalMaxScrollOffset; 681 gfx::SizeF scrollable_size = kScrollableSize; 682 // When --use-zoom-for-dsf is enabled, these values are in physical pixels. 683 if (content::IsUseZoomForDSFEnabled()) { 684 total_scroll_offset.Scale(kDipScale); 685 total_max_scroll_offset.Scale(kDipScale); 686 scrollable_size.Scale(kDipScale); 687 } 688 // |UpdateRootLayerState()| will call |SetTotalRootLayerScrollOffset()|. 689 browser_view_renderer_->UpdateRootLayerState( 690 ActiveCompositor(), total_scroll_offset, total_max_scroll_offset, 691 scrollable_size, kPageScaleFactor, kMinPageScaleFactor, 692 kMaxPageScaleFactor); 693 } 694 ScrollContainerViewTo(const gfx::Vector2d & new_value)695 void ScrollContainerViewTo(const gfx::Vector2d& new_value) override { 696 EXPECT_EQ(kExpectedScrollOffset.ToString(), new_value.ToString()); 697 EndTest(); 698 } 699 700 private: 701 static constexpr float kDipScale = 2.625f; 702 static const gfx::Vector2dF kTotalScrollOffset; 703 static const gfx::Vector2dF kTotalMaxScrollOffset; 704 static const gfx::SizeF kScrollableSize; 705 static constexpr float kPageScaleFactor = 1.f; 706 // These two are not used in this test. 707 static constexpr float kMinPageScaleFactor = 1.f; 708 static constexpr float kMaxPageScaleFactor = 5.f; 709 710 static const gfx::Vector2d kExpectedScrollOffset; 711 }; 712 713 // The current scroll offset in logical pixel, which is at the end. 714 const gfx::Vector2dF DidReachMaximalScrollOffsetTest::kTotalScrollOffset = 715 gfx::Vector2dF(0.f, 6132.f); 716 // The maximum possible scroll offset in logical pixel. 717 const gfx::Vector2dF DidReachMaximalScrollOffsetTest::kTotalMaxScrollOffset = 718 gfx::Vector2dF(0.f, 6132.f); 719 // This is what passed to CTS test, not used for this test. 720 const gfx::SizeF DidReachMaximalScrollOffsetTest::kScrollableSize = 721 gfx::SizeF(412.f, 6712.f); 722 // In max_scroll_offset() we are using ceiling rounding for scaled scroll 723 // offset. Therefore ceiling(2.625 * 6132 = 16096.5) = 16097. 724 const gfx::Vector2d DidReachMaximalScrollOffsetTest::kExpectedScrollOffset = 725 gfx::Vector2d(0, 16097); 726 727 RENDERING_TEST_F(DidReachMaximalScrollOffsetTest); 728 729 } // namespace android_webview 730