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