// Go down shadow layer tree and apply transformations for scrollable layers. static void TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader, nsIFrame* aFrame, Layer* aLayer, const ViewTransform& aTransform) { ShadowLayer* shadow = aLayer->AsShadowLayer(); shadow->SetShadowClipRect(aLayer->GetClipRect()); shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion()); const FrameMetrics* metrics = GetFrameMetrics(aLayer); gfx3DMatrix shadowTransform; ViewTransform layerTransform = aTransform; if (metrics && metrics->IsScrollable()) { const ViewID scrollId = metrics->mScrollId; const nsContentView* view = aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree"); const gfx3DMatrix& currentTransform = aLayer->GetTransform(); ViewTransform viewTransform = ComputeShadowTreeTransform( aFrame, aFrameLoader, metrics, view->GetViewConfig(), 1 / (GetXScale(currentTransform)*layerTransform.mXScale), 1 / (GetYScale(currentTransform)*layerTransform.mYScale) ); // Apply the layer's own transform *before* the view transform shadowTransform = gfx3DMatrix(viewTransform) * currentTransform; if (metrics->IsRootScrollable()) { layerTransform.mTranslation = viewTransform.mTranslation; // Apply the root frame translation *before* we do the rest of the transforms. nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder); shadowTransform = shadowTransform * gfx3DMatrix::Translation(float(rootFrameOffset.x), float(rootFrameOffset.y), 0.0); layerTransform.mXScale *= GetXScale(currentTransform); layerTransform.mYScale *= GetYScale(currentTransform); } } else { shadowTransform = aLayer->GetTransform(); } if (aLayer->GetIsFixedPosition() && !aLayer->GetParent()->GetIsFixedPosition()) { ReverseTranslate(shadowTransform, layerTransform); const nsIntRect* clipRect = shadow->GetShadowClipRect(); if (clipRect) { nsIntRect transformedClipRect(*clipRect); transformedClipRect.MoveBy(shadowTransform._41, shadowTransform._42); shadow->SetShadowClipRect(&transformedClipRect); } } shadow->SetShadowTransform(shadowTransform); for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { TransformShadowTree(aBuilder, aFrameLoader, aFrame, child, layerTransform); } }
// Use shadow layer tree to build display list for the browser's frame. static void BuildListForLayer(Layer* aLayer, nsFrameLoader* aRootFrameLoader, const gfx3DMatrix& aTransform, nsDisplayListBuilder* aBuilder, nsDisplayList& aShadowTree, nsIFrame* aSubdocFrame) { const FrameMetrics* metrics = GetFrameMetrics(aLayer); gfx3DMatrix transform; if (metrics && metrics->IsScrollable()) { const ViewID scrollId = metrics->mScrollId; // We need to figure out the bounds of the scrollable region using the // shadow layer tree from the remote process. The metrics viewport is // defined based on all the transformations of its parent layers and // the scale of the current layer. // Calculate transform for this layer. nsContentView* view = aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); // XXX why don't we include aLayer->GetTransform() in the inverse-scale here? // This seems wrong, but it doesn't seem to cause bugs! gfx3DMatrix applyTransform = ComputeShadowTreeTransform( aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(), 1 / GetXScale(aTransform), 1 / GetYScale(aTransform)); transform = applyTransform * aLayer->GetTransform() * aTransform; // As mentioned above, bounds calculation also depends on the scale // of this layer. gfx3DMatrix tmpTransform = aTransform; Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform)); // Calculate rect for this layer based on aTransform. nsRect bounds; { nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel(); bounds = metrics->mViewport.ToAppUnits(auPerDevPixel); ApplyTransform(bounds, tmpTransform, auPerDevPixel); } aShadowTree.AppendToTop( new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId)); } else { transform = aLayer->GetTransform() * aTransform; } for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { BuildListForLayer(child, aRootFrameLoader, transform, aBuilder, aShadowTree, aSubdocFrame); } }