APZCTreeManagerTester.h (8704B)
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 "APZTestAccess.h" 16 #include "APZTestCommon.h" 17 #include "gfxPlatform.h" 18 #include "MockHitTester.h" 19 #include "apz/src/WRHitTester.h" 20 21 #include "mozilla/layers/APZSampler.h" 22 #include "mozilla/layers/APZUpdater.h" 23 #include "mozilla/layers/WebRenderScrollDataWrapper.h" 24 25 class APZCTreeManagerTester : public APZCTesterBase { 26 protected: 27 APZCTreeManagerTester() : mHitTester(MakeUnique<WRHitTester>()) {} 28 29 virtual void SetUp() { 30 APZCTesterBase::SetUp(); 31 32 APZThreadUtils::SetThreadAssertionsEnabled(false); 33 APZThreadUtils::SetControllerThread(NS_GetCurrentThread()); 34 35 manager = new TestAPZCTreeManager(mcc, std::move(mHitTester)); 36 updater = new APZUpdater(manager, false); 37 sampler = new APZSampler(manager, false); 38 } 39 40 virtual void TearDown() { 41 while (mcc->RunThroughDelayedTasks()); 42 manager->ClearTree(); 43 manager->ClearContentController(); 44 45 APZCTesterBase::TearDown(); 46 } 47 48 /** 49 * Sample animations once for all APZCs, 1 ms later than the last sample and 50 * return whether there is still any active animations or not. 51 */ 52 bool SampleAnimationsOnce() { 53 const TimeDuration increment = TimeDuration::FromMilliseconds(1); 54 ParentLayerPoint pointOut; 55 AsyncTransform viewTransformOut; 56 mcc->AdvanceBy(increment); 57 58 bool activeAnimations = false; 59 60 for (size_t i = 0; i < layers.GetLayerCount(); ++i) { 61 if (TestAsyncPanZoomController* apzc = ApzcOf(layers[i])) { 62 activeAnimations |= 63 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); 64 } 65 } 66 67 return activeAnimations; 68 } 69 70 // A convenience function for letting a test modify the frame metrics 71 // stored on a particular layer. 72 template <typename Callback> 73 void ModifyFrameMetrics(WebRenderLayerScrollData* aLayer, 74 Callback aCallback) { 75 MOZ_ASSERT(aLayer->GetScrollMetadataCount() == 1); 76 ScrollMetadata& metadataRef = 77 APZTestAccess::GetScrollMetadataMut(*aLayer, layers, 0); 78 aCallback(metadataRef, metadataRef.GetMetrics()); 79 } 80 81 // A convenience wrapper for manager->UpdateHitTestingTree(). 82 void UpdateHitTestingTree(uint32_t aPaintSequenceNumber = 0) { 83 manager->UpdateHitTestingTree(WebRenderScrollDataWrapper{*updater, &layers}, 84 LayersId{0}, aPaintSequenceNumber); 85 } 86 87 void CreateScrollData(const char* aTreeShape, 88 const LayerIntRect* aVisibleRects = nullptr, 89 const gfx::Matrix4x4* aTransforms = nullptr) { 90 layers = TestWRScrollData::Create(aTreeShape, *updater, aVisibleRects, 91 aTransforms); 92 root = layers[0]; 93 } 94 95 void CreateMockHitTester() { 96 mHitTester = MakeUnique<MockHitTester>(); 97 // Save a pointer in a separate variable, because SetUp() will 98 // move the value out of mHitTester. 99 mMockHitTester = static_cast<MockHitTester*>(mHitTester.get()); 100 } 101 void QueueMockHitResult(ScrollableLayerGuid::ViewID aScrollId, 102 gfx::CompositorHitTestInfo aHitInfo = 103 gfx::CompositorHitTestFlags::eVisibleToHitTest) { 104 QueueMockHitResult(ScrollableLayerGuid(LayersId{0}, 0, aScrollId), 105 aHitInfo); 106 } 107 108 // This overload allows customizing the LayersId as well. 109 void QueueMockHitResult(ScrollableLayerGuid aGuid, 110 gfx::CompositorHitTestInfo aHitInfo = 111 gfx::CompositorHitTestFlags::eVisibleToHitTest) { 112 MOZ_ASSERT(mMockHitTester); 113 mMockHitTester->QueueHitResult(aGuid, aHitInfo); 114 } 115 116 RefPtr<TestAPZCTreeManager> manager; 117 RefPtr<APZSampler> sampler; 118 RefPtr<APZUpdater> updater; 119 TestWRScrollData layers; 120 WebRenderLayerScrollData* root = nullptr; 121 122 UniquePtr<IAPZHitTester> mHitTester; 123 MockHitTester* mMockHitTester = nullptr; 124 125 protected: 126 static ScrollMetadata BuildScrollMetadata( 127 ScrollableLayerGuid::ViewID aScrollId, const CSSRect& aScrollableRect, 128 const ParentLayerRect& aCompositionBounds) { 129 ScrollMetadata metadata; 130 FrameMetrics& metrics = metadata.GetMetrics(); 131 metrics.SetScrollId(aScrollId); 132 // By convention in this test file, START_SCROLL_ID is the root, so mark it 133 // as such. 134 if (aScrollId == ScrollableLayerGuid::START_SCROLL_ID) { 135 metadata.SetIsLayersIdRoot(true); 136 } 137 metrics.SetCompositionBounds(aCompositionBounds); 138 metrics.SetScrollableRect(aScrollableRect); 139 metrics.SetLayoutScrollOffset(CSSPoint(0, 0)); 140 metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100)); 141 metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10)); 142 return metadata; 143 } 144 145 void SetScrollMetadata(WebRenderLayerScrollData* aLayer, 146 const ScrollMetadata& aMetadata) { 147 MOZ_ASSERT(aLayer->GetScrollMetadataCount() <= 1, 148 "This function does not support multiple ScrollMetadata on a " 149 "single layer"); 150 if (aLayer->GetScrollMetadataCount() == 0) { 151 // Add new metrics 152 aLayer->AppendScrollMetadata(layers, aMetadata); 153 } else { 154 // Overwrite existing metrics 155 ModifyFrameMetrics( 156 aLayer, [&](ScrollMetadata& aSm, FrameMetrics&) { aSm = aMetadata; }); 157 } 158 } 159 160 void SetScrollMetadata(WebRenderLayerScrollData* aLayer, 161 const nsTArray<ScrollMetadata>& aMetadata) { 162 // The reason for this restriction is that WebRenderLayerScrollData does not 163 // have an API to *remove* previous metadata. 164 MOZ_ASSERT(aLayer->GetScrollMetadataCount() == 0, 165 "This function can only be used on layers which do not yet have " 166 "scroll metadata"); 167 for (const ScrollMetadata& metadata : aMetadata) { 168 aLayer->AppendScrollMetadata(layers, metadata); 169 } 170 } 171 172 void SetScrollableFrameMetrics(WebRenderLayerScrollData* aLayer, 173 ScrollableLayerGuid::ViewID aScrollId, 174 CSSRect aScrollableRect = CSSRect(-1, -1, -1, 175 -1)) { 176 auto localTransform = aLayer->GetTransformTyped() * AsyncTransformMatrix(); 177 ParentLayerIntRect compositionBounds = RoundedToInt( 178 localTransform.TransformBounds(LayerRect(aLayer->GetVisibleRect()))); 179 ScrollMetadata metadata = BuildScrollMetadata( 180 aScrollId, aScrollableRect, ParentLayerRect(compositionBounds)); 181 SetScrollMetadata(aLayer, metadata); 182 } 183 184 bool HasScrollableFrameMetrics(const WebRenderLayerScrollData* aLayer) const { 185 for (uint32_t i = 0; i < aLayer->GetScrollMetadataCount(); i++) { 186 if (aLayer->GetScrollMetadata(layers, i).GetMetrics().IsScrollable()) { 187 return true; 188 } 189 } 190 return false; 191 } 192 193 void SetScrollHandoff(WebRenderLayerScrollData* aChild, 194 WebRenderLayerScrollData* aParent) { 195 ModifyFrameMetrics(aChild, [&](ScrollMetadata& aSm, FrameMetrics&) { 196 aSm.SetScrollParentId( 197 aParent->GetScrollMetadata(layers, 0).GetMetrics().GetScrollId()); 198 }); 199 } 200 201 TestAsyncPanZoomController* ApzcOf(WebRenderLayerScrollData* aLayer) { 202 EXPECT_EQ(1u, aLayer->GetScrollMetadataCount()); 203 return ApzcOf(aLayer, 0); 204 } 205 206 TestAsyncPanZoomController* ApzcOf(WebRenderLayerScrollData* aLayer, 207 uint32_t aIndex) { 208 EXPECT_LT(aIndex, aLayer->GetScrollMetadataCount()); 209 // Unlike Layer, WebRenderLayerScrollData does not store the associated 210 // APZCs, so look it up using the tree manager instead. 211 RefPtr<AsyncPanZoomController> apzc = manager->GetTargetAPZC( 212 LayersId{0}, 213 aLayer->GetScrollMetadata(layers, aIndex).GetMetrics().GetScrollId()); 214 return (TestAsyncPanZoomController*)apzc.get(); 215 } 216 217 void CreateSimpleScrollingLayer() { 218 const char* treeShape = "x"; 219 LayerIntRect layerVisibleRect[] = { 220 LayerIntRect(0, 0, 200, 200), 221 }; 222 CreateScrollData(treeShape, layerVisibleRect); 223 SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID, 224 CSSRect(0, 0, 500, 500)); 225 } 226 }; 227 228 #endif // mozilla_layers_APZCTreeManagerTester_h