--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -310,16 +310,17 @@ struct DIGroup
nsPoint mAnimatedGeometryRootOrigin;
nsPoint mLastAnimatedGeometryRootOrigin;
IntRect mInvalidRect;
nsRect mGroupBounds;
int32_t mAppUnitsPerDevPixel;
gfx::Size mScale;
FrameMetrics::ViewID mScrollId;
+ LayerPoint mResidualOffset;
LayerIntRect mLayerBounds;
Maybe<wr::ImageKey> mKey;
std::vector<RefPtr<SourceSurface>> mExternalSurfaces;
DIGroup()
: mAppUnitsPerDevPixel(0)
, mScrollId(FrameMetrics::NULL_SCROLL_ID)
{
@@ -564,19 +565,19 @@ struct DIGroup
delete data;
} else {
data->mUsed = false;
}
}
// Round the bounds out to leave space for unsnapped content
LayoutDeviceToLayerScale2D scale(mScale.width, mScale.height);
- LayerIntRect layerBounds = LayerIntRect::FromUnknownRect(mGroupBounds.ScaleToOutsidePixels(mScale.width, mScale.height, aGrouper->mAppUnitsPerDevPixel));
+ LayerIntRect layerBounds = mLayerBounds;
IntSize dtSize = layerBounds.Size().ToUnknownSize();
- LayoutDeviceRect bounds = layerBounds / scale;
+ LayoutDeviceRect bounds = (LayerRect(layerBounds) - mResidualOffset) / scale;
if (mInvalidRect.IsEmpty()) {
GP("Not repainting group because it's empty\n");
GP("End EndGroup\n");
if (mKey) {
PushImage(aBuilder, bounds);
}
return;
@@ -960,16 +961,17 @@ Grouper::ConstructGroups(WebRenderComman
aCommandBuilder->mManager->AddImageKeyForDiscard(groupData->mFollowingGroup.mKey.value());
groupData->mFollowingGroup.mKey = Nothing();
}
}
groupData->mFollowingGroup.mGroupBounds = currentGroup->mGroupBounds;
groupData->mFollowingGroup.mAppUnitsPerDevPixel = currentGroup->mAppUnitsPerDevPixel;
groupData->mFollowingGroup.mLayerBounds = currentGroup->mLayerBounds;
groupData->mFollowingGroup.mScale = currentGroup->mScale;
+ groupData->mFollowingGroup.mResidualOffset = currentGroup->mResidualOffset;
currentGroup = &groupData->mFollowingGroup;
startOfCurrentGroup = item->GetAbove();
} else { // inactive item
if (item->GetType() == DisplayItemType::TYPE_TRANSFORM) {
nsDisplayTransform* transformItem = static_cast<nsDisplayTransform*>(item);
@@ -1041,16 +1043,34 @@ Grouper::ConstructGroupInsideInactive(We
BlobItemData* data = GetBlobItemDataForGroup(item, currentGroup);
currentGroup->ComputeGeometryChange(item, data, mTransform, mDisplayListBuilder); // we compute the geometry change here because we have the transform around still
item = item->GetAbove();
}
}
+/* This is just a copy of nsRect::ScaleToOutsidePixels with an offset added in.
+ * The offset is applied just before the rounding. It's in the scaled space. */
+static mozilla::gfx::IntRect
+ScaleToOutsidePixelsOffset(nsRect aRect, float aXScale, float aYScale,
+ nscoord aAppUnitsPerPixel, LayerPoint aOffset)
+{
+ mozilla::gfx::IntRect rect;
+ rect.SetNonEmptyBox(NSToIntFloor(NSAppUnitsToFloatPixels(aRect.x,
+ float(aAppUnitsPerPixel)) * aXScale + aOffset.x),
+ NSToIntFloor(NSAppUnitsToFloatPixels(aRect.y,
+ float(aAppUnitsPerPixel)) * aYScale + aOffset.y),
+ NSToIntCeil(NSAppUnitsToFloatPixels(aRect.XMost(),
+ float(aAppUnitsPerPixel)) * aXScale + aOffset.x),
+ NSToIntCeil(NSAppUnitsToFloatPixels(aRect.YMost(),
+ float(aAppUnitsPerPixel)) * aYScale + aOffset.y));
+ return rect;
+}
+
void
WebRenderCommandBuilder::DoGroupingForDisplayList(nsDisplayList* aList,
nsDisplayItem* aWrappingItem,
nsDisplayListBuilder* aDisplayListBuilder,
const StackingContextHelper& aSc,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources)
{
@@ -1066,21 +1086,26 @@ WebRenderCommandBuilder::DoGroupingForDi
g.mDisplayListBuilder = aDisplayListBuilder;
RefPtr<WebRenderGroupData> groupData = CreateOrRecycleWebRenderUserData<WebRenderGroupData>(aWrappingItem);
bool snapped;
nsRect groupBounds = aWrappingItem->GetBounds(aDisplayListBuilder, &snapped);
DIGroup& group = groupData->mSubGroup;
auto p = group.mGroupBounds;
auto q = groupBounds;
gfx::Size scale = aSc.GetInheritedScale();
+ auto trans = ViewAs<LayerPixel>(aSc.GetSnappingSurfaceTransform().GetTranslation());
+ auto snappedTrans = LayerIntPoint::Floor(trans);
+ LayerPoint residualOffset = trans - snappedTrans;
+
GP("Inherrited scale %f %f\n", scale.width, scale.height);
GP("Bounds: %d %d %d %d vs %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x, q.y, q.width, q.height);
if (!group.mGroupBounds.IsEqualEdges(groupBounds) ||
group.mAppUnitsPerDevPixel != appUnitsPerDevPixel ||
- group.mScale != scale) {
+ group.mScale != scale ||
+ group.mResidualOffset != residualOffset) {
if (group.mAppUnitsPerDevPixel != appUnitsPerDevPixel) {
GP("app unit %d %d\n", group.mAppUnitsPerDevPixel, appUnitsPerDevPixel);
}
// The bounds have changed so we need to discard the old image and add all
// the commands again.
auto p = group.mGroupBounds;
auto q = groupBounds;
GP("Bounds change: %d %d %d %d vs %d %d %d %d\n", p.x, p.y, p.width, p.height, q.x, q.y, q.width, q.height);
@@ -1094,22 +1119,28 @@ WebRenderCommandBuilder::DoGroupingForDi
}
FrameMetrics::ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
if (const ActiveScrolledRoot* asr = aWrappingItem->GetActiveScrolledRoot()) {
scrollId = asr->GetViewId();
}
g.mAppUnitsPerDevPixel = appUnitsPerDevPixel;
- g.mTransform = Matrix::Scaling(scale.width, scale.height);
+ group.mResidualOffset = residualOffset;
+ group.mGroupBounds = groupBounds;
group.mAppUnitsPerDevPixel = appUnitsPerDevPixel;
- group.mGroupBounds = groupBounds;
+ group.mLayerBounds = LayerIntRect::FromUnknownRect(ScaleToOutsidePixelsOffset(group.mGroupBounds,
+ scale.width,
+ scale.height,
+ group.mAppUnitsPerDevPixel,
+ residualOffset));
+ g.mTransform = Matrix::Scaling(scale.width, scale.height)
+ .PostTranslate(residualOffset.x, residualOffset.y);
group.mScale = scale;
group.mScrollId = scrollId;
- group.mLayerBounds = LayerIntRect::FromUnknownRect(group.mGroupBounds.ScaleToOutsidePixels(scale.width, scale.height, group.mAppUnitsPerDevPixel));
group.mAnimatedGeometryRootOrigin = group.mGroupBounds.TopLeft();
g.ConstructGroups(this, aBuilder, aResources, &group, aList, aSc);
mClipManager.EndList(aSc);
}
void
WebRenderCommandBuilder::Destroy()
{