1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_layers_APZCTreeManagerTester_h
8 #define mozilla_layers_APZCTreeManagerTester_h
9 
10 /**
11  * Defines a test fixture used for testing multiple APZCs interacting in
12  * an APZCTreeManager.
13  */
14 
15 #include "APZTestCommon.h"
16 #include "gfxPlatform.h"
17 
18 #include "mozilla/layers/APZSampler.h"
19 #include "mozilla/layers/APZUpdater.h"
20 
21 class APZCTreeManagerTester : public APZCTesterBase {
22  protected:
APZCTreeManagerTester()23   APZCTreeManagerTester() : mLayersOnly(false) {}
24 
SetUp()25   virtual void SetUp() {
26     APZCTesterBase::SetUp();
27     if (mLayersOnly) {
28       SCOPED_GFX_VAR_MAYBE_EMPLACE(mVarWebRender, UseWebRender, false);
29       SCOPED_GFX_VAR_MAYBE_EMPLACE(mVarSoftwareWebRender, UseSoftwareWebRender,
30                                    false);
31     }
32 
33     APZThreadUtils::SetThreadAssertionsEnabled(false);
34     APZThreadUtils::SetControllerThread(NS_GetCurrentThread());
35 
36     manager = new TestAPZCTreeManager(mcc);
37     updater = new APZUpdater(manager, false);
38     sampler = new APZSampler(manager, false);
39   }
40 
TearDown()41   virtual void TearDown() {
42     while (mcc->RunThroughDelayedTasks())
43       ;
44     manager->ClearTree();
45     manager->ClearContentController();
46     mVarWebRender.reset();
47     mVarSoftwareWebRender.reset();
48   }
49 
50   /**
51    * Sample animations once for all APZCs, 1 ms later than the last sample and
52    * return whether there is still any active animations or not.
53    */
SampleAnimationsOnce()54   bool SampleAnimationsOnce() {
55     const TimeDuration increment = TimeDuration::FromMilliseconds(1);
56     ParentLayerPoint pointOut;
57     AsyncTransform viewTransformOut;
58     mcc->AdvanceBy(increment);
59 
60     bool activeAnimations = false;
61 
62     for (const RefPtr<Layer>& layer : layers) {
63       if (TestAsyncPanZoomController* apzc = ApzcOf(layer)) {
64         activeAnimations |=
65             apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
66       }
67     }
68 
69     return activeAnimations;
70   }
71 
72   // A convenience function for letting a test modify the frame metrics
73   // stored on a particular layer. The layer doesn't let us modify it in-place,
74   // so we take care of the copying in this function.
75   template <typename Callback>
ModifyFrameMetrics(Layer * aLayer,Callback aCallback)76   void ModifyFrameMetrics(Layer* aLayer, Callback aCallback) {
77     ScrollMetadata metadata = aLayer->GetScrollMetadata(0);
78     aCallback(metadata, metadata.GetMetrics());
79     aLayer->SetScrollMetadata(metadata);
80   }
81 
82   // A convenience wrapper for manager->UpdateHitTestingTree().
83   void UpdateHitTestingTree(uint32_t aPaintSequenceNumber = 0) {
84     manager->UpdateHitTestingTree(root, /* is first paint = */ false,
85                                   LayersId{0}, aPaintSequenceNumber);
86   }
87 
88   nsTArray<RefPtr<Layer> > layers;
89   RefPtr<LayerManager> lm;
90   RefPtr<Layer> root;
91 
92   RefPtr<TestAPZCTreeManager> manager;
93   RefPtr<APZSampler> sampler;
94   RefPtr<APZUpdater> updater;
95 
96   SCOPED_GFX_VAR_MAYBE_TYPE(bool) mVarWebRender;
97   SCOPED_GFX_VAR_MAYBE_TYPE(bool) mVarSoftwareWebRender;
98   bool mLayersOnly;
99 
100  protected:
BuildScrollMetadata(ScrollableLayerGuid::ViewID aScrollId,const CSSRect & aScrollableRect,const ParentLayerRect & aCompositionBounds)101   static ScrollMetadata BuildScrollMetadata(
102       ScrollableLayerGuid::ViewID aScrollId, const CSSRect& aScrollableRect,
103       const ParentLayerRect& aCompositionBounds) {
104     ScrollMetadata metadata;
105     FrameMetrics& metrics = metadata.GetMetrics();
106     metrics.SetScrollId(aScrollId);
107     // By convention in this test file, START_SCROLL_ID is the root, so mark it
108     // as such.
109     if (aScrollId == ScrollableLayerGuid::START_SCROLL_ID) {
110       metadata.SetIsLayersIdRoot(true);
111     }
112     metrics.SetCompositionBounds(aCompositionBounds);
113     metrics.SetScrollableRect(aScrollableRect);
114     metrics.SetLayoutScrollOffset(CSSPoint(0, 0));
115     metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
116     metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
117     return metadata;
118   }
119 
SetEventRegionsBasedOnBottommostMetrics(Layer * aLayer)120   static void SetEventRegionsBasedOnBottommostMetrics(Layer* aLayer) {
121     const FrameMetrics& metrics = aLayer->GetScrollMetadata(0).GetMetrics();
122     CSSRect scrollableRect = metrics.GetScrollableRect();
123     if (!scrollableRect.IsEqualEdges(CSSRect(-1, -1, -1, -1))) {
124       // The purpose of this is to roughly mimic what layout would do in the
125       // case of a scrollable frame with the event regions and clip. This lets
126       // us exercise the hit-testing code in APZCTreeManager
127       EventRegions er = aLayer->GetEventRegions();
128       IntRect scrollRect =
129           RoundedToInt(scrollableRect * metrics.LayersPixelsPerCSSPixel())
130               .ToUnknownRect();
131       er.mHitRegion = nsIntRegion(IntRect(
132           RoundedToInt(
133               metrics.GetCompositionBounds().TopLeft().ToUnknownPoint()),
134           scrollRect.Size()));
135       aLayer->SetEventRegions(er);
136     }
137   }
138 
139   static void SetScrollableFrameMetrics(
140       Layer* aLayer, ScrollableLayerGuid::ViewID aScrollId,
141       CSSRect aScrollableRect = CSSRect(-1, -1, -1, -1)) {
142     ParentLayerIntRect compositionBounds =
143         RoundedToInt(aLayer->GetLocalTransformTyped().TransformBounds(
144             LayerRect(aLayer->GetVisibleRegion().GetBounds())));
145     ScrollMetadata metadata = BuildScrollMetadata(
146         aScrollId, aScrollableRect, ParentLayerRect(compositionBounds));
147     aLayer->SetScrollMetadata(metadata);
148     aLayer->SetClipRect(Some(compositionBounds));
149     SetEventRegionsBasedOnBottommostMetrics(aLayer);
150   }
151 
SetScrollHandoff(Layer * aChild,Layer * aParent)152   void SetScrollHandoff(Layer* aChild, Layer* aParent) {
153     ScrollMetadata metadata = aChild->GetScrollMetadata(0);
154     metadata.SetScrollParentId(aParent->GetFrameMetrics(0).GetScrollId());
155     aChild->SetScrollMetadata(metadata);
156   }
157 
ApzcOf(Layer * aLayer)158   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer) {
159     EXPECT_EQ(1u, aLayer->GetScrollMetadataCount());
160     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(0);
161   }
162 
ApzcOf(Layer * aLayer,uint32_t aIndex)163   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer, uint32_t aIndex) {
164     EXPECT_LT(aIndex, aLayer->GetScrollMetadataCount());
165     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(
166         aIndex);
167   }
168 
CreateSimpleScrollingLayer()169   void CreateSimpleScrollingLayer() {
170     const char* layerTreeSyntax = "t";
171     nsIntRegion layerVisibleRegion[] = {
172         nsIntRegion(IntRect(0, 0, 200, 200)),
173     };
174     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
175                            layers);
176     SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
177                               CSSRect(0, 0, 500, 500));
178   }
179 };
180 
181 #endif  // mozilla_layers_APZCTreeManagerTester_h
182