Changeset 249440 in webkit
- Timestamp:
- Sep 3, 2019 12:55:11 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r249439 r249440 83 83 (WebCore::IOSApplication::isSafariViewService): 84 84 Adds a way to detect SafariViewService. 85 86 2019-09-03 Simon Fraser <simon.fraser@apple.com> 87 88 Cache "compositingAncestor" during the compositing updateBackingAndHierarchy() tree walk 89 https://bugs.webkit.org/show_bug.cgi?id=201403 90 91 Reviewed by Antti Koivisto. 92 93 Finding a layer's compositingAncestor requires an ancestor tree walk. We can avoid this during 94 compositing updates, since we're already in the middle of a paint-order tree walk, and can just 95 keep track of the current compositingAncestor on the way down. 96 97 Shaves a few % off time in updateCompositingLayers(). 98 99 * rendering/RenderLayerBacking.cpp: 100 (WebCore::RenderLayerBacking::updateConfiguration): 101 (WebCore::ComputedOffsets::ComputedOffsets): 102 (WebCore::ComputedOffsets::fromAncestorGraphicsLayer): 103 (WebCore::RenderLayerBacking::computePrimaryGraphicsLayerRect const): 104 (WebCore::RenderLayerBacking::updateGeometry): 105 * rendering/RenderLayerBacking.h: 106 * rendering/RenderLayerCompositor.cpp: 107 (WebCore::RenderLayerCompositor::UpdateBackingTraversalState::UpdateBackingTraversalState): 108 (WebCore::RenderLayerCompositor::UpdateBackingTraversalState::stateForDescendants const): 109 (WebCore::RenderLayerCompositor::updateCompositingLayers): 110 (WebCore::RenderLayerCompositor::computeCompositingRequirements): 111 (WebCore::RenderLayerCompositor::updateBackingAndHierarchy): 112 (WebCore::RenderLayerCompositor::updateLayerCompositingState): 113 (WebCore::RenderLayerCompositor::computeCoordinatedPositioningForLayer const): 114 (WebCore::RenderLayerCompositor::coordinatedScrollingRolesForLayer const): 115 (WebCore::RenderLayerCompositor::updateScrollCoordinationForLayer): 116 (WebCore::RenderLayerCompositor::updateScrollingNodeForPositioningRole): 117 * rendering/RenderLayerCompositor.h: 85 118 86 119 2019-09-03 Simon Fraser <simon.fraser@apple.com> -
trunk/Source/WebCore/rendering/RenderLayerBacking.cpp
r248879 r249440 832 832 } 833 833 834 bool RenderLayerBacking::updateConfiguration( )834 bool RenderLayerBacking::updateConfiguration(const RenderLayer* compositingAncestor) 835 835 { 836 836 ASSERT(!m_owningLayer.normalFlowListDirty()); … … 866 866 layerConfigChanged = true; 867 867 868 auto* compositingAncestor = m_owningLayer.ancestorCompositingLayer();868 ASSERT(compositingAncestor == m_owningLayer.ancestorCompositingLayer()); 869 869 if (updateAncestorClipping(compositor.clippedByAncestor(m_owningLayer, compositingAncestor), compositingAncestor)) 870 870 layerConfigChanged = true; … … 1027 1027 class ComputedOffsets { 1028 1028 public: 1029 ComputedOffsets(const RenderLayer& renderLayer, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect)1029 ComputedOffsets(const RenderLayer& renderLayer, const RenderLayer* compositingAncestor, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect) 1030 1030 : m_renderLayer(renderLayer) 1031 , m_compositingAncestor(compositingAncestor) 1031 1032 , m_location(localRect.location()) 1032 1033 , m_parentGraphicsLayerOffset(toLayoutSize(parentGraphicsLayerRect.location())) … … 1054 1055 { 1055 1056 if (!m_fromAncestorGraphicsLayer) { 1056 auto* compositedAncestor = m_renderLayer.ancestorCompositingLayer(); 1057 LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(compositedAncestor, m_location, RenderLayer::AdjustForColumns); 1058 m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor); 1057 LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(m_compositingAncestor, m_location, RenderLayer::AdjustForColumns); 1058 m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(m_compositingAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor); 1059 1059 } 1060 1060 return m_fromAncestorGraphicsLayer.value(); … … 1066 1066 1067 1067 const RenderLayer& m_renderLayer; 1068 const RenderLayer* m_compositingAncestor; 1068 1069 // Location is relative to the renderer. 1069 1070 const LayoutPoint m_location; … … 1073 1074 }; 1074 1075 1075 LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const1076 { 1077 ComputedOffsets compositedBoundsOffset(m_owningLayer, composited Bounds(), parentGraphicsLayerRect, { });1076 LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const RenderLayer* compositedAncestor, const LayoutRect& parentGraphicsLayerRect) const 1077 { 1078 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedAncestor, compositedBounds(), parentGraphicsLayerRect, { }); 1078 1079 return LayoutRect(encloseRectToDevicePixels(LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), 1079 1080 deviceScaleFactor())); … … 1113 1114 } 1114 1115 1115 void RenderLayerBacking::updateGeometry( )1116 void RenderLayerBacking::updateGeometry(const RenderLayer* compositedAncestor) 1116 1117 { 1117 1118 ASSERT(!m_owningLayer.normalFlowListDirty()); … … 1139 1140 #endif 1140 1141 1141 auto* compositedAncestor = m_owningLayer.ancestorCompositingLayer();1142 ASSERT(compositedAncestor == m_owningLayer.ancestorCompositingLayer()); 1142 1143 LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor); 1143 1144 … … 1169 1170 } 1170 1171 1171 LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect( parentGraphicsLayerRect);1172 1173 ComputedOffsets compositedBoundsOffset(m_owningLayer, composited Bounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect);1174 ComputedOffsets rendererOffset(m_owningLayer, { }, parentGraphicsLayerRect, primaryGraphicsLayerRect);1172 LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect(compositedAncestor, parentGraphicsLayerRect); 1173 1174 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedAncestor, compositedBounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect); 1175 ComputedOffsets rendererOffset(m_owningLayer, compositedAncestor, { }, parentGraphicsLayerRect, primaryGraphicsLayerRect); 1175 1176 1176 1177 m_compositedBoundsOffsetFromGraphicsLayer = compositedBoundsOffset.fromPrimaryGraphicsLayer(); … … 1282 1283 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) { 1283 1284 auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing(); 1284 reflectionBacking->updateGeometry( );1285 reflectionBacking->updateGeometry(&m_owningLayer); 1285 1286 1286 1287 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(), -
trunk/Source/WebCore/rendering/RenderLayerBacking.h
r247540 r249440 82 82 83 83 // Returns true if layer configuration changed. 84 bool updateConfiguration( );84 bool updateConfiguration(const RenderLayer* compositingAncestor); 85 85 86 86 // Update graphics layer position and bounds. 87 void updateGeometry( );87 void updateGeometry(const RenderLayer* compositingAncestor); 88 88 89 89 // Update state the requires that descendant layers have been updated. … … 386 386 bool canIssueSetNeedsDisplay() const { return !paintsIntoWindow() && !paintsIntoCompositedAncestor(); } 387 387 LayoutRect computeParentGraphicsLayerRect(const RenderLayer* compositedAncestor) const; 388 LayoutRect computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const;388 LayoutRect computePrimaryGraphicsLayerRect(const RenderLayer* compositedAncestor, const LayoutRect& parentGraphicsLayerRect) const; 389 389 390 390 RenderLayer& m_owningLayer; -
trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp
r249434 r249440 200 200 }; 201 201 202 struct RenderLayerCompositor::UpdateBackingTraversalState { 203 204 UpdateBackingTraversalState(RenderLayer* compAncestor = nullptr) 205 : compositingAncestor(compAncestor) 206 { 207 } 208 209 UpdateBackingTraversalState stateForDescendants() const 210 { 211 UpdateBackingTraversalState state(compositingAncestor); 212 #if !LOG_DISABLED 213 state.depth = depth + 1; 214 #endif 215 return state; 216 } 217 218 RenderLayer* compositingAncestor; 219 #if !LOG_DISABLED 220 unsigned depth { 0 }; 221 #endif 222 }; 223 202 224 class RenderLayerCompositor::BackingSharingState { 203 225 WTF_MAKE_NONCOPYABLE(BackingSharingState); … … 792 814 scrollingTreeState.parentNodeID = frameHostingNodeForFrame(m_renderView.frame()); 793 815 816 UpdateBackingTraversalState traversalState; 794 817 Vector<Ref<GraphicsLayer>> childList; 795 updateBackingAndHierarchy(*updateRoot, childList, scrollingTreeState);818 updateBackingAndHierarchy(*updateRoot, childList, traversalState, scrollingTreeState); 796 819 797 820 // Host the document layer in the RenderView's root layer. … … 1053 1076 1054 1077 // Update layer state bits. 1055 if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), queryData, CompositingChangeRepaintNow))1078 if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), &layer, queryData, CompositingChangeRepaintNow)) 1056 1079 layer.setNeedsCompositingLayerConnection(); 1057 1080 … … 1176 1199 } 1177 1200 1178 void RenderLayerCompositor::updateBackingAndHierarchy(RenderLayer& layer, Vector<Ref<GraphicsLayer>>& childLayersOfEnclosingLayer, ScrollingTreeState& scrollingTreeState, OptionSet<UpdateLevel> updateLevel, int depth)1201 void RenderLayerCompositor::updateBackingAndHierarchy(RenderLayer& layer, Vector<Ref<GraphicsLayer>>& childLayersOfEnclosingLayer, UpdateBackingTraversalState& traversalState, ScrollingTreeState& scrollingTreeState, OptionSet<UpdateLevel> updateLevel) 1179 1202 { 1180 1203 layer.updateDescendantDependentFlags(); … … 1185 1208 updateLevel.add(UpdateLevel::AllDescendants); 1186 1209 1187 ScrollingTreeState stateForDescendants = scrollingTreeState; 1210 ScrollingTreeState scrollingStateForDescendants = scrollingTreeState; 1211 UpdateBackingTraversalState traversalStateForDescendants = traversalState.stateForDescendants(); 1188 1212 1189 1213 auto* layerBacking = layer.backing(); … … 1200 1224 1201 1225 if (layerNeedsUpdate || layer.needsCompositingConfigurationUpdate()) { 1202 if (layerBacking->updateConfiguration( )) {1226 if (layerBacking->updateConfiguration(traversalState.compositingAncestor)) { 1203 1227 layerNeedsUpdate = true; // We also need to update geometry. 1204 1228 layer.setNeedsCompositingLayerConnection(); … … 1210 1234 OptionSet<ScrollingNodeChangeFlags> scrollingNodeChanges = { ScrollingNodeChangeFlags::Layer }; 1211 1235 if (layerNeedsUpdate || layer.needsCompositingGeometryUpdate()) { 1212 layerBacking->updateGeometry( );1236 layerBacking->updateGeometry(traversalState.compositingAncestor); 1213 1237 scrollingNodeChanges.add(ScrollingNodeChangeFlags::LayerGeometry); 1214 1238 } else if (layer.needsScrollingTreeUpdate()) … … 1223 1247 if (auto* reflectionBacking = reflection->backing()) { 1224 1248 reflectionBacking->updateCompositedBounds(); 1225 reflectionBacking->updateGeometry( );1249 reflectionBacking->updateGeometry(&layer); 1226 1250 reflectionBacking->updateAfterDescendants(); 1227 1251 } … … 1233 1257 // FIXME: do based on dirty flags. Need to do this for changes of geometry, configuration and hierarchy. 1234 1258 // Need to be careful to do the right thing when a scroll-coordinated layer loses a scroll-coordinated ancestor. 1235 stateForDescendants.parentNodeID = updateScrollCoordinationForLayer(layer, scrollingTreeState, scrollingNodeChanges); 1236 stateForDescendants.nextChildIndex = 0; 1259 scrollingStateForDescendants.parentNodeID = updateScrollCoordinationForLayer(layer, traversalState.compositingAncestor, scrollingTreeState, scrollingNodeChanges); 1260 scrollingStateForDescendants.nextChildIndex = 0; 1261 1262 traversalStateForDescendants.compositingAncestor = &layer; 1237 1263 1238 1264 #if !LOG_DISABLED 1239 logLayerInfo(layer, "updateBackingAndHierarchy", depth); 1240 #else 1241 UNUSED_PARAM(depth); 1265 logLayerInfo(layer, "updateBackingAndHierarchy", traversalState.depth); 1242 1266 #endif 1243 1267 } … … 1270 1294 if (requireDescendantTraversal) { 1271 1295 for (auto* renderLayer : layer.negativeZOrderLayers()) 1272 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);1296 updateBackingAndHierarchy(*renderLayer, childList, traversalStateForDescendants, scrollingStateForDescendants, updateLevel); 1273 1297 1274 1298 appendForegroundLayerIfNecessary(); 1275 1299 1276 1300 for (auto* renderLayer : layer.normalFlowLayers()) 1277 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);1301 updateBackingAndHierarchy(*renderLayer, childList, traversalStateForDescendants, scrollingStateForDescendants, updateLevel); 1278 1302 1279 1303 for (auto* renderLayer : layer.positiveZOrderLayers()) 1280 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);1304 updateBackingAndHierarchy(*renderLayer, childList, traversalStateForDescendants, scrollingStateForDescendants, updateLevel); 1281 1305 } else if (requiresChildRebuild) 1282 1306 appendForegroundLayerIfNecessary(); … … 1690 1714 } 1691 1715 1692 bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer& layer, RequiresCompositingData& queryData, CompositingChangeRepaint shouldRepaint)1716 bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer& layer, const RenderLayer* compositingAncestor, RequiresCompositingData& queryData, CompositingChangeRepaint shouldRepaint) 1693 1717 { 1694 1718 bool layerChanged = updateBacking(layer, queryData, shouldRepaint); … … 1696 1720 // See if we need content or clipping layers. Methods called here should assume 1697 1721 // that the compositing state of descendant layers has not been updated yet. 1698 if (layer.backing() && layer.backing()->updateConfiguration( ))1722 if (layer.backing() && layer.backing()->updateConfiguration(compositingAncestor)) 1699 1723 layerChanged = true; 1700 1724 … … 3242 3266 } 3243 3267 3244 ScrollPositioningBehavior RenderLayerCompositor::computeCoordinatedPositioningForLayer(const RenderLayer& layer ) const3268 ScrollPositioningBehavior RenderLayerCompositor::computeCoordinatedPositioningForLayer(const RenderLayer& layer, const RenderLayer* compositedAncestor) const 3245 3269 { 3246 3270 if (layer.isRenderViewLayer()) … … 3257 3281 return ScrollPositioningBehavior::None; 3258 3282 3259 auto* compositedAncestor = layer.ancestorCompositingLayer();3260 3283 if (!compositedAncestor) { 3261 3284 ASSERT_NOT_REACHED(); … … 4307 4330 } 4308 4331 4309 OptionSet<ScrollCoordinationRole> RenderLayerCompositor::coordinatedScrollingRolesForLayer(const RenderLayer& layer ) const4332 OptionSet<ScrollCoordinationRole> RenderLayerCompositor::coordinatedScrollingRolesForLayer(const RenderLayer& layer, const RenderLayer* compositingAncestor) const 4310 4333 { 4311 4334 OptionSet<ScrollCoordinationRole> coordinationRoles; … … 4316 4339 coordinationRoles.add(ScrollCoordinationRole::Scrolling); 4317 4340 4318 auto coordinatedPositioning = computeCoordinatedPositioningForLayer(layer );4341 auto coordinatedPositioning = computeCoordinatedPositioningForLayer(layer, compositingAncestor); 4319 4342 switch (coordinatedPositioning) { 4320 4343 case ScrollPositioningBehavior::Moves: … … 4334 4357 } 4335 4358 4336 ScrollingNodeID RenderLayerCompositor::updateScrollCoordinationForLayer(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes)4337 { 4338 auto roles = coordinatedScrollingRolesForLayer(layer );4359 ScrollingNodeID RenderLayerCompositor::updateScrollCoordinationForLayer(RenderLayer& layer, const RenderLayer* compositingAncestor, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes) 4360 { 4361 auto roles = coordinatedScrollingRolesForLayer(layer, compositingAncestor); 4339 4362 4340 4363 #if PLATFORM(IOS_FAMILY) … … 4359 4382 // If there's a positioning node, it's the parent scrolling node for fixed/sticky/scrolling/frame hosting. 4360 4383 if (roles.contains(ScrollCoordinationRole::Positioning)) { 4361 newNodeID = updateScrollingNodeForPositioningRole(layer, *currentTreeState, changes);4384 newNodeID = updateScrollingNodeForPositioningRole(layer, compositingAncestor, *currentTreeState, changes); 4362 4385 childTreeState.parentNodeID = newNodeID; 4363 4386 currentTreeState = &childTreeState; … … 4585 4608 } 4586 4609 4587 ScrollingNodeID RenderLayerCompositor::updateScrollingNodeForPositioningRole(RenderLayer& layer, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes)4610 ScrollingNodeID RenderLayerCompositor::updateScrollingNodeForPositioningRole(RenderLayer& layer, const RenderLayer* compositingAncestor, ScrollingTreeState& treeState, OptionSet<ScrollingNodeChangeFlags> changes) 4588 4611 { 4589 4612 auto* scrollingCoordinator = this->scrollingCoordinator(); … … 4602 4625 if (changes & ScrollingNodeChangeFlags::LayerGeometry && treeState.parentNodeID) { 4603 4626 // Would be nice to avoid calling computeCoordinatedPositioningForLayer() again. 4604 auto positioningBehavior = computeCoordinatedPositioningForLayer(layer );4627 auto positioningBehavior = computeCoordinatedPositioningForLayer(layer, compositingAncestor); 4605 4628 auto relatedNodeIDs = collectRelatedCoordinatedScrollingNodes(layer, positioningBehavior); 4606 4629 scrollingCoordinator->setRelatedOverflowScrollingNodes(newNodeID, WTFMove(relatedNodeIDs)); -
trunk/Source/WebCore/rendering/RenderLayerCompositor.h
r249434 r249440 209 209 }; 210 210 211 bool updateLayerCompositingState(RenderLayer&, RequiresCompositingData&, CompositingChangeRepaint = CompositingChangeRepaintNow);211 bool updateLayerCompositingState(RenderLayer&, const RenderLayer* compositingAncestor, RequiresCompositingData&, CompositingChangeRepaint = CompositingChangeRepaintNow); 212 212 213 213 // Whether layer's backing needs a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow). … … 348 348 bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer&) const; 349 349 bool useCoordinatedScrollingForLayer(const RenderLayer&) const; 350 ScrollPositioningBehavior computeCoordinatedPositioningForLayer(const RenderLayer& ) const;350 ScrollPositioningBehavior computeCoordinatedPositioningForLayer(const RenderLayer&, const RenderLayer* compositingAncestor) const; 351 351 bool isLayerForIFrameWithScrollCoordinatedContents(const RenderLayer&) const; 352 352 … … 391 391 struct CompositingState; 392 392 struct OverlapExtent; 393 struct UpdateBackingTraversalState; 393 394 394 395 // Returns true if the policy changed. … … 441 442 }; 442 443 // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer. 443 void updateBackingAndHierarchy(RenderLayer&, Vector<Ref<GraphicsLayer>>& childGraphicsLayersOfEnclosingLayer, struct ScrollingTreeState&, OptionSet<UpdateLevel> = { }, int depth = 0);444 void updateBackingAndHierarchy(RenderLayer&, Vector<Ref<GraphicsLayer>>& childGraphicsLayersOfEnclosingLayer, struct UpdateBackingTraversalState&, struct ScrollingTreeState&, OptionSet<UpdateLevel> = { }); 444 445 445 446 bool layerHas3DContent(const RenderLayer&) const; … … 513 514 ScrollingNodeID registerScrollingNodeID(ScrollingCoordinator&, ScrollingNodeID, ScrollingNodeType, struct ScrollingTreeState&); 514 515 515 OptionSet<ScrollCoordinationRole> coordinatedScrollingRolesForLayer(const RenderLayer& ) const;516 OptionSet<ScrollCoordinationRole> coordinatedScrollingRolesForLayer(const RenderLayer&, const RenderLayer* compositingAncestor) const; 516 517 517 518 // Returns the ScrollingNodeID which acts as the parent for children. 518 ScrollingNodeID updateScrollCoordinationForLayer(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>);519 ScrollingNodeID updateScrollCoordinationForLayer(RenderLayer&, const RenderLayer* compositingAncestor, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>); 519 520 520 521 // These return the ScrollingNodeID which acts as the parent for children. … … 523 524 ScrollingNodeID updateScrollingNodeForScrollingProxyRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>); 524 525 ScrollingNodeID updateScrollingNodeForFrameHostingRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>); 525 ScrollingNodeID updateScrollingNodeForPositioningRole(RenderLayer&, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>);526 ScrollingNodeID updateScrollingNodeForPositioningRole(RenderLayer&, const RenderLayer* compositingAncestor, struct ScrollingTreeState&, OptionSet<ScrollingNodeChangeFlags>); 526 527 527 528 void updateScrollingNodeLayers(ScrollingNodeID, RenderLayer&, ScrollingCoordinator&);
Note: See TracChangeset
for help on using the changeset viewer.