From 81db073a18f202dac946ca93924709ba4190f39f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 15 Jul 2019 15:24:54 +0000 Subject: [PATCH] Bug 1565904. Move the blob metadata from image space to an absolute space. r=nical This is a follow up to bug 1564655. It removes the offset from ToDeviceSpace and thus moves item rects into absolute space which is now the same coordinate space as the recordings are in. We also adjust item bounds for fallback blobs. Some additional changes that need happen to: 1. In Moz2DImageRenderer we can reunify the origin because the recording and the recording metadata return to using the same coordinate space. 2. The calls to PushLayer can return to using the item bounds which are now in the same coordinate space. 3. This dirty rect which remains in images space is adjusted during merging. Differential Revision: https://phabricator.services.mozilla.com/D38015 --HG-- extra : moz-landing-system : lando --- gfx/layers/wr/WebRenderCommandBuilder.cpp | 104 ++++++++---------- gfx/webrender_bindings/Moz2DImageRenderer.cpp | 16 +-- gfx/webrender_bindings/src/moz2d_renderer.rs | 7 +- 3 files changed, 60 insertions(+), 67 deletions(-) diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp index 7952ec1ea07f..5f69b210e68c 100644 --- a/gfx/layers/wr/WebRenderCommandBuilder.cpp +++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -305,8 +305,7 @@ struct DIGroup { ScrollableLayerGuid::ViewID mScrollId; LayerPoint mResidualOffset; LayerIntRect mLayerBounds; - // The current bounds of the blob image, relative to - // the top-left of the mLayerBounds. + // The current bounds of the blob image IntRect mImageBounds; // mImageBounds clipped to the container/parent of the // current item being processed. @@ -348,16 +347,14 @@ struct DIGroup { } static IntRect ToDeviceSpace(nsRect aBounds, Matrix& aMatrix, - int32_t aAppUnitsPerDevPixel, - LayerIntPoint aOffset) { + int32_t aAppUnitsPerDevPixel) { // RoundedOut can convert empty rectangles to non-empty ones // so special case them here if (aBounds.IsEmpty()) { return IntRect(); } - return RoundedOut(aMatrix.TransformBounds(ToRect( - nsLayoutUtils::RectToGfxRect(aBounds, aAppUnitsPerDevPixel)))) - - aOffset.ToUnknownPoint(); + return RoundedOut(aMatrix.TransformBounds( + ToRect(nsLayoutUtils::RectToGfxRect(aBounds, aAppUnitsPerDevPixel)))); } void ComputeGeometryChange(nsDisplayItem* aItem, BlobItemData* aData, @@ -372,14 +369,12 @@ struct DIGroup { int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel(); MOZ_RELEASE_ASSERT(mAppUnitsPerDevPixel == appUnitsPerDevPixel); - LayoutDeviceRect bounds = - LayoutDeviceRect::FromAppUnits(mGroupBounds, appUnitsPerDevPixel); - LayoutDeviceIntPoint offset = RoundedToInt(bounds.TopLeft()); GP("\n"); - GP("CGC offset %d %d\n", offset.x, offset.y); GP("clippedImageRect %d %d %d %d\n", mClippedImageBounds.x, mClippedImageBounds.y, mClippedImageBounds.width, mClippedImageBounds.height); + LayerIntSize size = mLayerBounds.Size(); + GP("imageSize: %d %d\n", size.width, size.height); /*if (aItem->IsReused() && aData->mGeometry) { return; }*/ @@ -397,12 +392,12 @@ struct DIGroup { geometry->ComputeInvalidationRegion()); aData->mGeometry = std::move(geometry); - IntRect transformedRect = ToDeviceSpace( - clippedBounds, aMatrix, appUnitsPerDevPixel, mLayerBounds.TopLeft()); + IntRect transformedRect = + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); aData->mRect = transformedRect.Intersect(mClippedImageBounds); GP("CGC %s %d %d %d %d\n", aItem->Name(), clippedBounds.x, clippedBounds.y, clippedBounds.width, clippedBounds.height); - GP("%d %d, %f %f\n", mLayerBounds.TopLeft().x, mLayerBounds.TopLeft().y, + GP("%d %d, %f %f\n", mPaintRect.TopLeft().x, mPaintRect.TopLeft().y, aMatrix._11, aMatrix._22); GP("mRect %d %d %d %d\n", aData->mRect.x, aData->mRect.y, aData->mRect.width, aData->mRect.height); @@ -411,7 +406,6 @@ struct DIGroup { } else if (aData->mInvalid || /* XXX: handle image load invalidation */ ( aItem->IsInvalid(invalid) && invalid.IsEmpty())) { - MOZ_RELEASE_ASSERT(mLayerBounds.TopLeft() == aData->mGroupOffset); UniquePtr geometry( aItem->AllocateGeometry(aBuilder)); nsRect clippedBounds = clip.ApplyNonRoundedIntersection( @@ -427,15 +421,14 @@ struct DIGroup { // matrix? // XXX: TransformBounds is expensive. We should avoid doing it if we have // no transform - IntRect transformedRect = ToDeviceSpace( - clippedBounds, aMatrix, appUnitsPerDevPixel, mLayerBounds.TopLeft()); + IntRect transformedRect = + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); aData->mRect = transformedRect.Intersect(mClippedImageBounds); InvalidateRect(aData->mRect); GP("new rect: %d %d %d %d\n", aData->mRect.x, aData->mRect.y, aData->mRect.width, aData->mRect.height); aData->mInvalid = true; } else { - MOZ_RELEASE_ASSERT(mLayerBounds.TopLeft() == aData->mGroupOffset); GP("else invalidate: %s\n", aItem->Name()); nsRegion combined; // this includes situations like reflow changing the position @@ -456,8 +449,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( aData->mGeometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); aData->mRect = transformedRect.Intersect(mClippedImageBounds); InvalidateRect(aData->mRect); @@ -487,8 +479,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( aData->mGeometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); InvalidateRect(aData->mRect.Intersect(mImageBounds)); aData->mRect = transformedRect.Intersect(mClippedImageBounds); InvalidateRect(aData->mRect); @@ -517,8 +508,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( aData->mGeometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); InvalidateRect(aData->mRect.Intersect(mImageBounds)); aData->mRect = transformedRect.Intersect(mClippedImageBounds); InvalidateRect(aData->mRect); @@ -536,8 +526,7 @@ struct DIGroup { geometry->ComputeInvalidationRegion()); aData->mGeometry = std::move(geometry); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); InvalidateRect(aData->mRect.Intersect(mImageBounds)); aData->mRect = transformedRect.Intersect(mClippedImageBounds); InvalidateRect(aData->mRect); @@ -547,8 +536,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( geometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); // The invalid rect should contain the old rect and the new rect // but may not because the parent may have been removed. InvalidateRect(aData->mRect); @@ -560,8 +548,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( geometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); auto rect = transformedRect.Intersect(mClippedImageBounds); GP("Layer NoChange: %s %d %d %d %d\n", aItem->Name(), aData->mRect.x, aData->mRect.y, aData->mRect.XMost(), @@ -575,8 +562,7 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( geometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); // The invalid rect should contain the old rect and the new rect // but may not because the parent may have been removed. InvalidateRect(aData->mRect); @@ -590,18 +576,17 @@ struct DIGroup { nsRect clippedBounds = clip.ApplyNonRoundedIntersection( geometry->ComputeInvalidationRegion()); IntRect transformedRect = - ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel, - mLayerBounds.TopLeft()); + ToDeviceSpace(clippedBounds, aMatrix, appUnitsPerDevPixel); auto rect = transformedRect.Intersect(mClippedImageBounds); - GP("NoChange: %s %d %d %d %d\n", aItem->Name(), aData->mRect.x, - aData->mRect.y, aData->mRect.XMost(), aData->mRect.YMost()); + GP("NoChange: %s %d %d %d %d vs %d %d %d %d\n", aItem->Name(), rect.x, + rect.y, rect.XMost(), rect.YMost(), aData->mRect.x, aData->mRect.y, + aData->mRect.XMost(), aData->mRect.YMost()); MOZ_RELEASE_ASSERT(rect.IsEqualEdges(aData->mRect)); } } } aData->mClip = clip; aData->mMatrix = aMatrix; - aData->mGroupOffset = mLayerBounds.TopLeft(); aData->mImageRect = mClippedImageBounds; GP("post mInvalidRect: %d %d %d %d\n", mInvalidRect.x, mInvalidRect.y, mInvalidRect.width, mInvalidRect.height); @@ -630,22 +615,25 @@ struct DIGroup { } } + IntSize dtSize = mLayerBounds.Size().ToUnknownSize(); + // The actual display item's size shouldn't have the scale factored in // Round the bounds out to leave space for unsnapped content LayoutDeviceToLayerScale2D scale(mScale.width, mScale.height); - LayerIntRect layerBounds = mLayerBounds; - IntSize dtSize = layerBounds.Size().ToUnknownSize(); - LayoutDeviceRect bounds = - (LayerRect(layerBounds) - mResidualOffset) / scale; + LayoutDeviceRect itemBounds = + (LayerRect(mLayerBounds) - mResidualOffset) / scale; if (mInvalidRect.IsEmpty()) { GP("Not repainting group because it's empty\n"); GP("End EndGroup\n"); if (mKey) { + // Although the contents haven't changed, the visible area *may* have, + // so request it be updated unconditionally (wr should be able to easily + // detect if this is a no-op on its side, if that matters) aResources.SetBlobImageVisibleArea( mKey.value().second(), ViewAs(mPaintRect, PixelCastJustification::LayerIsImage)); - PushImage(aBuilder, bounds); + PushImage(aBuilder, itemBounds); } return; } @@ -681,7 +669,9 @@ struct DIGroup { recorder, dummyDt, mLayerBounds.ToUnknownRect()); // Setup the gfxContext RefPtr context = gfxContext::CreateOrNull(dt); - context->SetMatrix(Matrix::Scaling(mScale.width, mScale.height).PostTranslate(mResidualOffset.x, mResidualOffset.y)); + context->SetMatrix( + Matrix::Scaling(mScale.width, mScale.height) + .PostTranslate(mResidualOffset.x, mResidualOffset.y)); GP("mInvalidRect: %d %d %d %d\n", mInvalidRect.x, mInvalidRect.y, mInvalidRect.width, mInvalidRect.height); @@ -728,7 +718,13 @@ struct DIGroup { mKey = Some(MakePair(aBuilder.GetRenderRoot(), key)); } else { wr::ImageDescriptor descriptor(dtSize, 0, dt->GetFormat(), opacity); - auto bottomRight = mInvalidRect.BottomRight(); + + // Convert mInvalidRect to image space by subtracting the corner of the + // image bounds + auto dirtyRect = ViewAs( + mInvalidRect - mLayerBounds.ToUnknownRect().TopLeft()); + + auto bottomRight = dirtyRect.BottomRight(); GP("check invalid %d %d - %d %d\n", bottomRight.x, bottomRight.y, dtSize.width, dtSize.height); MOZ_RELEASE_ASSERT(bottomRight.x <= dtSize.width && @@ -739,7 +735,7 @@ struct DIGroup { mKey.value().second(), descriptor, bytes, ViewAs(mPaintRect, PixelCastJustification::LayerIsImage), - ViewAs(mInvalidRect))) { + dirtyRect)) { return; } } @@ -748,7 +744,7 @@ struct DIGroup { aResources.SetBlobImageVisibleArea( mKey.value().second(), ViewAs(mPaintRect, PixelCastJustification::LayerIsImage)); - PushImage(aBuilder, bounds); + PushImage(aBuilder, itemBounds); GP("End EndGroup\n\n"); } @@ -965,7 +961,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, aContext->GetDrawTarget()->PushLayer(false, opacityItem->GetOpacity(), nullptr, mozilla::gfx::Matrix(), - aItemBounds + aGroup->mLayerBounds.ToUnknownRect().TopLeft()); + aItemBounds); GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey()); aContext->GetDrawTarget()->FlushItem(aItemBounds); @@ -981,7 +977,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, auto blendItem = static_cast(aItem); auto blendMode = blendItem->BlendMode(); aContext->GetDrawTarget()->PushLayerWithBlend( - false, 1.0, nullptr, mozilla::gfx::Matrix(), aItemBounds + aGroup->mLayerBounds.ToUnknownRect().TopLeft(), false, + false, 1.0, nullptr, mozilla::gfx::Matrix(), aItemBounds, false, blendMode); GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey()); @@ -996,7 +992,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, } case DisplayItemType::TYPE_BLEND_CONTAINER: { aContext->GetDrawTarget()->PushLayer(false, 1.0, nullptr, - mozilla::gfx::Matrix(), aItemBounds + aGroup->mLayerBounds.ToUnknownRect().TopLeft()); + mozilla::gfx::Matrix(), aItemBounds); GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(), aItem->GetPerFrameKey()); aContext->GetDrawTarget()->FlushItem(aItemBounds); @@ -1518,8 +1514,7 @@ void WebRenderCommandBuilder::DoGroupingForDisplayList( group.mLayerBounds = LayerIntRect::FromUnknownRect( ScaleToOutsidePixelsOffset(group.mGroupBounds, scale.width, scale.height, group.mAppUnitsPerDevPixel, residualOffset)); - group.mImageBounds = - IntRect(0, 0, group.mLayerBounds.width, group.mLayerBounds.height); + group.mImageBounds = group.mLayerBounds.ToUnknownRect(); group.mClippedImageBounds = group.mImageBounds; const nsRect& untransformedPaintRect = @@ -1530,10 +1525,7 @@ void WebRenderCommandBuilder::DoGroupingForDisplayList( untransformedPaintRect, scale.width, scale.height, group.mAppUnitsPerDevPixel, residualOffset)) .Intersect(group.mLayerBounds); - // XXX: Make the paint rect relative to the layer bounds. After we include - // mLayerBounds.TopLeft() in the blob image we want to stop doing this - // adjustment. - group.mPaintRect = group.mPaintRect - group.mLayerBounds.TopLeft(); + g.mTransform = Matrix::Scaling(scale.width, scale.height) .PostTranslate(residualOffset.x, residualOffset.y); group.mScale = scale; @@ -2292,7 +2284,7 @@ WebRenderCommandBuilder::GenerateFallbackData( isInvalidated = true; } } - recorder->FlushItem(IntRect({0, 0}, dtSize.ToUnknownSize())); + recorder->FlushItem(dtRect.ToUnknownRect()); recorder->Finish(); if (!validFonts) { diff --git a/gfx/webrender_bindings/Moz2DImageRenderer.cpp b/gfx/webrender_bindings/Moz2DImageRenderer.cpp index 60d0d9d8ef00..ba26f3fa7399 100644 --- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp +++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp @@ -369,10 +369,9 @@ static bool Moz2DRenderCallback(const Range aBlob, // them because of CompositorHitTestInfo and merging. size_t footerSize = sizeof(size_t) + sizeof(IntPoint); MOZ_RELEASE_ASSERT(aBlob.length() >= footerSize); - size_t indexOffset = - ConvertFromBytes(aBlob.end().get() - footerSize); - IntPoint recordingOrigin = - ConvertFromBytes(aBlob.end().get() - footerSize + sizeof(size_t)); + size_t indexOffset = ConvertFromBytes(aBlob.end().get() - footerSize); + IntPoint origin = ConvertFromBytes(aBlob.end().get() - footerSize + + sizeof(size_t)); // Apply the visibleRect's offset to make (0, 0) in the DT correspond to (0, // 0) in the texture @@ -380,20 +379,17 @@ static bool Moz2DRenderCallback(const Range aBlob, Reader reader(aBlob.begin().get() + indexOffset, aBlob.length() - footerSize - indexOffset); - IntPoint origin; if (aTileOffset) { origin += gfx::IntPoint(aTileOffset->x * *aTileSize, aTileOffset->y * *aTileSize); } - dt = gfx::Factory::CreateOffsetDrawTarget(dt, recordingOrigin + origin); + dt = gfx::Factory::CreateOffsetDrawTarget(dt, origin); auto bounds = gfx::IntRect(origin, aSize); if (aDirtyRect) { - Rect dirty(aDirtyRect->origin.x + recordingOrigin.x, - aDirtyRect->origin.y + recordingOrigin.y, - aDirtyRect->size.width, - aDirtyRect->size.height); + Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y, + aDirtyRect->size.width, aDirtyRect->size.height); dt->PushClipRect(dirty); bounds = bounds.Intersect( IntRect(aDirtyRect->origin.x, aDirtyRect->origin.y, diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs index 5aa067ffb739..a431bfc8f3b6 100644 --- a/gfx/webrender_bindings/src/moz2d_renderer.rs +++ b/gfx/webrender_bindings/src/moz2d_renderer.rs @@ -380,7 +380,7 @@ impl<'a> CachedReader<'a> { /// the first not-yet-copied item with those bounds in the old list and copy that. /// Any items found in the old list but not the new one can be safely assumed to /// have been deleted. -fn merge_blob_images(old_buf: &[u8], new_buf: &[u8], dirty_rect: Box2d) -> Vec { +fn merge_blob_images(old_buf: &[u8], new_buf: &[u8], mut dirty_rect: Box2d) -> Vec { let mut result = BlobWriter::new(); dlog!("dirty rect: {:?}", dirty_rect); @@ -395,6 +395,11 @@ fn merge_blob_images(old_buf: &[u8], new_buf: &[u8], dirty_rect: Box2d) -> Vec