зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1500575 - Map inset clip paths to WR complex clip regions. r=kats
Differential Revision: https://phabricator.services.mozilla.com/D9412 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ba7599486e
Коммит
d62a793992
|
@ -503,6 +503,31 @@ static inline wr::BorderRadius ToBorderRadius(const mozilla::LayoutDeviceSize& t
|
|||
return br;
|
||||
}
|
||||
|
||||
static inline wr::ComplexClipRegion ToComplexClipRegion(
|
||||
const nsRect& aRect,
|
||||
const nscoord* aRadii,
|
||||
int32_t aAppUnitsPerDevPixel)
|
||||
{
|
||||
wr::ComplexClipRegion ret;
|
||||
ret.rect = ToRoundedLayoutRect(
|
||||
LayoutDeviceRect::FromAppUnits(aRect, aAppUnitsPerDevPixel));
|
||||
ret.radii = ToBorderRadius(
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(aRadii[eCornerTopLeftX], aRadii[eCornerTopLeftY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(aRadii[eCornerTopRightX], aRadii[eCornerTopRightY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(aRadii[eCornerBottomLeftX], aRadii[eCornerBottomLeftY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(aRadii[eCornerBottomRightX], aRadii[eCornerBottomRightY]),
|
||||
aAppUnitsPerDevPixel));
|
||||
ret.mode = ClipMode::Clip;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline wr::LayoutSideOffsets ToBorderWidths(float top, float right, float bottom, float left)
|
||||
{
|
||||
wr::LayoutSideOffsets bw;
|
||||
|
|
|
@ -3185,7 +3185,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
* output even if the element being filtered wouldn't otherwise do so.
|
||||
*/
|
||||
if (usingSVGEffects) {
|
||||
MOZ_ASSERT(usingFilter ||usingMask,
|
||||
MOZ_ASSERT(usingFilter || usingMask,
|
||||
"Beside filter & mask/clip-path, what else effect do we have?");
|
||||
|
||||
if (clipCapturedBy == ContainerItemType::eFilter) {
|
||||
|
@ -3209,7 +3209,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
// an item always needs to have finite bounds with respect to its ASR.
|
||||
// If we weren't able to compute a clip for the mask, we fall back to
|
||||
// using containerItemASR, which is the lowest common ancestor clip of
|
||||
// the mask's contents. That's not entirely crrect, but it satisfies
|
||||
// the mask's contents. That's not entirely correct, but it satisfies
|
||||
// the base requirement of the ASR system (that items have finite bounds
|
||||
// wrt. their ASR).
|
||||
const ActiveScrolledRoot* maskASR = clipForMask.isSome()
|
||||
|
|
|
@ -587,25 +587,9 @@ DisplayItemClip::ToComplexClipRegions(
|
|||
const layers::StackingContextHelper& aSc,
|
||||
nsTArray<wr::ComplexClipRegion>& aOutArray) const
|
||||
{
|
||||
for (uint32_t i = 0; i < mRoundedClipRects.Length(); i++) {
|
||||
wr::ComplexClipRegion* region = aOutArray.AppendElement();
|
||||
region->rect = wr::ToRoundedLayoutRect(LayoutDeviceRect::FromAppUnits(
|
||||
mRoundedClipRects[i].mRect, aAppUnitsPerDevPixel));
|
||||
const nscoord* radii = mRoundedClipRects[i].mRadii;
|
||||
region->radii = wr::ToBorderRadius(
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(radii[eCornerTopLeftX], radii[eCornerTopLeftY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(radii[eCornerTopRightX], radii[eCornerTopRightY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(radii[eCornerBottomLeftX], radii[eCornerBottomLeftY]),
|
||||
aAppUnitsPerDevPixel),
|
||||
LayoutDeviceSize::FromAppUnits(
|
||||
nsSize(radii[eCornerBottomRightX], radii[eCornerBottomRightY]),
|
||||
aAppUnitsPerDevPixel));
|
||||
region->mode = wr::ClipMode::Clip;
|
||||
for (const auto& clipRect : mRoundedClipRects) {
|
||||
aOutArray.AppendElement(wr::ToComplexClipRegion(
|
||||
clipRect.mRect, clipRect.mRadii, aAppUnitsPerDevPixel));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/layers/PLayerTransaction.h"
|
||||
#include "mozilla/ShapeUtils.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsCSSRenderingGradients.h"
|
||||
#include "nsISelectionController.h"
|
||||
|
@ -9963,6 +9964,84 @@ nsDisplayMasksAndClipPaths::PaintWithContentsPaintCallback(
|
|||
nsDisplayMasksAndClipPathsGeometry::UpdateDrawResult(this, imgParams.result);
|
||||
}
|
||||
|
||||
static Maybe<wr::WrClipId>
|
||||
CreateSimpleClipRegion(const nsDisplayMasksAndClipPaths& aDisplayItem,
|
||||
wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
nsIFrame* frame = aDisplayItem.Frame();
|
||||
auto* style = frame->StyleSVGReset();
|
||||
MOZ_ASSERT(style->HasClipPath() || style->HasMask());
|
||||
if (style->HasMask()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// TODO(emilio): We should be able to still generate a clip and pass the
|
||||
// opacity down to StackingContextHelper instead.
|
||||
if (frame->StyleEffects()->mOpacity != 1.0) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
auto& clipPath = style->mClipPath;
|
||||
if (clipPath.GetType() != StyleShapeSourceType::Shape) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// TODO(emilio): We should be able to also simplify most of the circle() and
|
||||
// ellipse() shapes.
|
||||
auto& shape = clipPath.GetBasicShape();
|
||||
if (shape->GetShapeType() != StyleBasicShapeType::Inset) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const nsRect refBox =
|
||||
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.GetReferenceBox());
|
||||
|
||||
const nsRect insetRect =
|
||||
ShapeUtils::ComputeInsetRect(shape, refBox) + aDisplayItem.ToReferenceFrame();
|
||||
|
||||
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
nscoord radii[8] = { 0 };
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clipRegions;
|
||||
if (ShapeUtils::ComputeInsetRadii(shape, insetRect, refBox, radii)) {
|
||||
clipRegions.AppendElement(wr::ToComplexClipRegion(
|
||||
insetRect, radii, appUnitsPerDevPixel));
|
||||
}
|
||||
|
||||
auto rect = wr::ToRoundedLayoutRect(
|
||||
LayoutDeviceRect::FromAppUnits(insetRect, appUnitsPerDevPixel));
|
||||
wr::WrClipId clipId =
|
||||
aBuilder.DefineClip(Nothing(), rect, &clipRegions, nullptr);
|
||||
return Some(clipId);
|
||||
}
|
||||
|
||||
static Maybe<wr::WrClipId>
|
||||
CreateWRClipPathAndMasks(nsDisplayMasksAndClipPaths* aDisplayItem,
|
||||
const LayoutDeviceRect& aBounds,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
const StackingContextHelper& aSc,
|
||||
layers::WebRenderLayerManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
if (auto clip = CreateSimpleClipRegion(*aDisplayItem, aBuilder)) {
|
||||
return clip;
|
||||
}
|
||||
|
||||
Maybe<wr::WrImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(
|
||||
aDisplayItem, aBuilder, aResources, aSc, aDisplayListBuilder, aBounds);
|
||||
if (!mask) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
wr::WrClipId clipId =
|
||||
aBuilder.DefineClip(Nothing(),
|
||||
wr::ToRoundedLayoutRect(aBounds),
|
||||
nullptr,
|
||||
mask.ptr());
|
||||
|
||||
return Some(clipId);
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
|
||||
|
@ -9973,20 +10052,18 @@ nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
|
|||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
bool snap;
|
||||
float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
auto appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
nsRect displayBounds = GetBounds(aDisplayListBuilder, &snap);
|
||||
LayoutDeviceRect bounds =
|
||||
LayoutDeviceRect::FromAppUnits(displayBounds, appUnitsPerDevPixel);
|
||||
|
||||
Maybe<wr::WrImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(
|
||||
this, aBuilder, aResources, aSc, aDisplayListBuilder, bounds);
|
||||
Maybe<wr::WrClipId> clip =
|
||||
CreateWRClipPathAndMasks(
|
||||
this, bounds, aResources, aBuilder, aSc, aManager, aDisplayListBuilder);
|
||||
|
||||
Maybe<StackingContextHelper> layer;
|
||||
const StackingContextHelper* sc = &aSc;
|
||||
if (mask) {
|
||||
auto layoutBounds = wr::ToRoundedLayoutRect(bounds);
|
||||
wr::WrClipId clipId =
|
||||
aBuilder.DefineClip(Nothing(), layoutBounds, nullptr, mask.ptr());
|
||||
|
||||
if (clip) {
|
||||
// Create a new stacking context to attach the mask to, ensuring the mask is
|
||||
// applied to the aggregate, and not the individual elements.
|
||||
|
||||
|
@ -10006,7 +10083,7 @@ nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
|
|||
/*aBackfaceVisible: */ true,
|
||||
/*aIsPreserve3D: */ false,
|
||||
/*aTransformForScrollData: */ Nothing(),
|
||||
/*aClipNodeId: */ &clipId);
|
||||
/*aClipNodeId: */ clip.ptr());
|
||||
sc = layer.ptr();
|
||||
// The whole stacking context will be clipped by us, so no need to have any
|
||||
// parent for the children context's clip.
|
||||
|
@ -10017,7 +10094,7 @@ nsDisplayMasksAndClipPaths::CreateWebRenderCommands(
|
|||
nsDisplayEffectsBase::CreateWebRenderCommands(
|
||||
aBuilder, aResources, *sc, aManager, aDisplayListBuilder);
|
||||
|
||||
if (mask) {
|
||||
if (clip) {
|
||||
aManager->CommandBuilder().PopOverrideForASR(GetActiveScrolledRoot());
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@ fuzzy-if(webrender,64-64,1106-1106) == clip-path-ellipse-008.html clip-path-elli
|
|||
== clip-path-inset-001b.html clip-path-inset-001-ref.html
|
||||
== clip-path-inset-001c.html clip-path-inset-001-ref.html
|
||||
# Anti-aliasing behavior for masking and borders is different
|
||||
fuzzy(0-64,0-146) fuzzy-if(webrender,90-90,132-132) == clip-path-inset-002a.html clip-path-inset-002-ref.html
|
||||
fuzzy(0-64,0-146) fuzzy-if(webrender,90-90,132-132) == clip-path-inset-002b.html clip-path-inset-002-ref.html
|
||||
fuzzy(0-64,0-146) fuzzy-if(webrender,90-90,132-132) == clip-path-inset-002c.html clip-path-inset-002-ref.html
|
||||
fuzzy-if(!webrender,0-64,0-146) == clip-path-inset-002a.html clip-path-inset-002-ref.html
|
||||
fuzzy-if(!webrender,0-64,0-146) == clip-path-inset-002b.html clip-path-inset-002-ref.html
|
||||
fuzzy-if(!webrender,0-64,0-146) == clip-path-inset-002c.html clip-path-inset-002-ref.html
|
||||
fuzzy(0-64,0-340) fuzzy-if(webrender,104-104,311-311) == clip-path-inset-003.html clip-path-inset-003-ref.html
|
||||
|
||||
== clip-path-stroke-001.html clip-path-stroke-001-ref.html
|
||||
|
|
|
@ -181,7 +181,7 @@ nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame)
|
|||
bool
|
||||
nsSVGIntegrationUtils::UsingMaskOrClipPathForFrame(const nsIFrame* aFrame)
|
||||
{
|
||||
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
|
||||
const nsStyleSVGReset* style = aFrame->StyleSVGReset();
|
||||
return style->HasClipPath() || style->HasMask();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче