Bug 1816775 - Handle OP_CLEAR in DrawTargetD2D1. r=aosmond

Depends on D172956

Differential Revision: https://phabricator.services.mozilla.com/D174142
This commit is contained in:
Lee Salzman 2023-03-31 07:51:00 +00:00
parent f5477ac188
commit 87bb7d04d6
3 changed files with 57 additions and 24 deletions

View file

@ -189,10 +189,23 @@ static const uint32_t kTransformedGlyphsBeforePurge = 1000;
void DrawTargetD2D1::Flush() { FlushInternal(); }
bool DrawTargetD2D1::MaybeClearRect(CompositionOp aOp, const Rect& aBounds) {
if (aOp == CompositionOp::OP_CLEAR) {
FillRect(aBounds, ColorPattern(DeviceColor(1.0f, 1.0f, 1.0f, 1.0f)),
DrawOptions(1.0f, aOp));
return true;
}
return false;
}
void DrawTargetD2D1::DrawSurface(SourceSurface* aSurface, const Rect& aDest,
const Rect& aSource,
const DrawSurfaceOptions& aSurfOptions,
const DrawOptions& aOptions) {
if (MaybeClearRect(aOptions.mCompositionOp, aDest)) {
return;
}
if (!PrepareForDrawing(aOptions.mCompositionOp,
ColorPattern(DeviceColor()))) {
return;
@ -270,6 +283,11 @@ void DrawTargetD2D1::DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
return;
}
if (MaybeClearRect(aOptions.mCompositionOp,
Rect(aDestPoint, aSourceRect.Size()))) {
return;
}
if (!PrepareForDrawing(aOptions.mCompositionOp,
ColorPattern(DeviceColor()))) {
return;
@ -310,6 +328,11 @@ void DrawTargetD2D1::DrawSurfaceWithShadow(SourceSurface* aSurface,
if (!EnsureInitialized()) {
return;
}
if (MaybeClearRect(aOperator, Rect(aDest, Size(aSurface->GetSize())))) {
return;
}
MarkChanged();
Matrix mat;
@ -474,7 +497,7 @@ void DrawTargetD2D1::MaskSurface(const Pattern& aSource, SourceSurface* aMask,
gfxWarning() << "FillOpacityMask only works with Bitmap source surfaces. "
"Falling back to push/pop layer";
RefPtr<ID2D1Brush> source = CreateBrushForPattern(aSource, aOptions.mAlpha);
RefPtr<ID2D1Brush> source = CreateBrushForPattern(aSource, aOptions);
RefPtr<ID2D1ImageBrush> maskBrush;
hr = mDC->CreateImageBrush(
image,
@ -513,7 +536,7 @@ void DrawTargetD2D1::MaskSurface(const Pattern& aSource, SourceSurface* aMask,
Rect maskRect = Rect(aMask->GetRect().x, aMask->GetRect().y,
Float(size.width), Float(size.height));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions);
mDC->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
D2DRect(dest), D2DRect(maskRect));
@ -602,7 +625,7 @@ void DrawTargetD2D1::FillRect(const Rect& aRect, const Pattern& aPattern,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
mDC->FillRectangle(D2DRect(aRect), brush);
FinalizeDrawing(aOptions.mCompositionOp, aPattern);
@ -621,7 +644,7 @@ void DrawTargetD2D1::FillRoundedRect(const RoundedRect& aRect,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
mDC->FillRoundedRectangle(D2DRoundedRect(aRect), brush);
FinalizeDrawing(aOptions.mCompositionOp, aPattern);
@ -636,7 +659,7 @@ void DrawTargetD2D1::StrokeRect(const Rect& aRect, const Pattern& aPattern,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
RefPtr<ID2D1StrokeStyle> strokeStyle =
CreateStrokeStyleForOptions(aStrokeOptions);
@ -656,7 +679,7 @@ void DrawTargetD2D1::StrokeLine(const Point& aStart, const Point& aEnd,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
RefPtr<ID2D1StrokeStyle> strokeStyle =
CreateStrokeStyleForOptions(aStrokeOptions);
@ -682,7 +705,7 @@ void DrawTargetD2D1::Stroke(const Path* aPath, const Pattern& aPattern,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
RefPtr<ID2D1StrokeStyle> strokeStyle =
CreateStrokeStyleForOptions(aStrokeOptions);
@ -707,7 +730,7 @@ void DrawTargetD2D1::Fill(const Path* aPath, const Pattern& aPattern,
mDC->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
mDC->FillGeometry(d2dPath->mGeometry, brush);
@ -777,7 +800,7 @@ void DrawTargetD2D1::FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
mTextRenderingParams = params;
}
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions);
AutoDWriteGlyphRun autoRun;
DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
@ -858,8 +881,8 @@ void DrawTargetD2D1::Mask(const Pattern& aSource, const Pattern& aMask,
return;
}
RefPtr<ID2D1Brush> source = CreateBrushForPattern(aSource, aOptions.mAlpha);
RefPtr<ID2D1Brush> mask = CreateBrushForPattern(aMask, 1.0f);
RefPtr<ID2D1Brush> source = CreateBrushForPattern(aSource, aOptions);
RefPtr<ID2D1Brush> mask = CreateBrushForPattern(aMask, DrawOptions());
mDC->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::IdentityMatrix(), 1.0f, mask),
@ -1501,7 +1524,7 @@ void DrawTargetD2D1::MarkChanged() {
bool DrawTargetD2D1::ShouldClipTemporarySurfaceDrawing(CompositionOp aOp,
const Pattern& aPattern,
bool aClipIsComplex) {
bool patternSupported = IsPatternSupportedByD2D(aPattern);
bool patternSupported = IsPatternSupportedByD2D(aPattern, aOp);
return patternSupported && !CurrentLayer().mIsOpaque &&
D2DSupportsCompositeMode(aOp) && IsOperatorBoundByMask(aOp) &&
aClipIsComplex;
@ -1517,7 +1540,7 @@ bool DrawTargetD2D1::PrepareForDrawing(CompositionOp aOp,
PushAllClips();
bool patternSupported = IsPatternSupportedByD2D(aPattern);
bool patternSupported = IsPatternSupportedByD2D(aPattern, aOp);
if (D2DSupportsPrimitiveBlendMode(aOp) && patternSupported) {
// It's important to do this before FlushTransformToDC! As this will cause
// the transform to become dirty.
@ -1559,7 +1582,7 @@ bool DrawTargetD2D1::PrepareForDrawing(CompositionOp aOp,
void DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp,
const Pattern& aPattern) {
bool patternSupported = IsPatternSupportedByD2D(aPattern);
bool patternSupported = IsPatternSupportedByD2D(aPattern, aOp);
if (D2DSupportsPrimitiveBlendMode(aOp) && patternSupported) {
if (aOp != CompositionOp::OP_OVER)
@ -2038,15 +2061,16 @@ already_AddRefed<ID2D1SolidColorBrush> DrawTargetD2D1::GetSolidColorBrush(
}
already_AddRefed<ID2D1Brush> DrawTargetD2D1::CreateBrushForPattern(
const Pattern& aPattern, Float aAlpha) {
if (!IsPatternSupportedByD2D(aPattern)) {
const Pattern& aPattern, const DrawOptions& aOptions) {
if (!IsPatternSupportedByD2D(aPattern) ||
aOptions.mCompositionOp == CompositionOp::OP_CLEAR) {
return GetSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f));
}
if (aPattern.GetType() == PatternType::COLOR) {
DeviceColor color = static_cast<const ColorPattern*>(&aPattern)->mColor;
return GetSolidColorBrush(
D2D1::ColorF(color.r, color.g, color.b, color.a * aAlpha));
D2D1::ColorF(color.r, color.g, color.b, color.a * aOptions.mAlpha));
}
if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
RefPtr<ID2D1LinearGradientBrush> gradBrush;
@ -2067,7 +2091,7 @@ already_AddRefed<ID2D1Brush> DrawTargetD2D1::CreateBrushForPattern(
mDC->CreateLinearGradientBrush(
D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
D2DPoint(pat->mEnd)),
D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
D2D1::BrushProperties(aOptions.mAlpha, D2DMatrix(pat->mMatrix)),
stops->mStopCollection, getter_AddRefs(gradBrush));
if (!gradBrush) {
@ -2098,7 +2122,7 @@ already_AddRefed<ID2D1Brush> DrawTargetD2D1::CreateBrushForPattern(
D2D1::RadialGradientBrushProperties(
D2DPoint(pat->mCenter2), D2DPoint(pat->mCenter1 - pat->mCenter2),
pat->mRadius2, pat->mRadius2),
D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
D2D1::BrushProperties(aOptions.mAlpha, D2DMatrix(pat->mMatrix)),
stops->mStopCollection, getter_AddRefs(gradBrush));
if (!gradBrush) {
@ -2180,7 +2204,7 @@ already_AddRefed<ID2D1Brush> DrawTargetD2D1::CreateBrushForPattern(
bitmap,
D2D1::BitmapBrushProperties(xRepeat, yRepeat,
D2DFilter(pat->mSamplingFilter)),
D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
D2D1::BrushProperties(aOptions.mAlpha, D2DMatrix(mat)),
getter_AddRefs(bitmapBrush));
if (!bitmapBrush) {
gfxWarning() << "Couldn't create bitmap brush!";
@ -2211,7 +2235,7 @@ already_AddRefed<ID2D1Brush> DrawTargetD2D1::CreateBrushForPattern(
image,
D2D1::ImageBrushProperties(samplingBounds, xRepeat, yRepeat,
D2DInterpolationMode(pat->mSamplingFilter)),
D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
D2D1::BrushProperties(aOptions.mAlpha, D2DMatrix(mat)),
getter_AddRefs(imageBrush));
if (!imageBrush) {

View file

@ -193,6 +193,7 @@ class DrawTargetD2D1 : public DrawTarget {
bool aClipIsComplex);
bool PrepareForDrawing(CompositionOp aOp, const Pattern& aPattern);
void FinalizeDrawing(CompositionOp aOp, const Pattern& aPattern);
bool MaybeClearRect(CompositionOp aOp, const Rect& aBounds);
void FlushTransformToDC() {
if (mTransformDirty) {
mDC->SetTransform(D2DMatrix(mTransform));
@ -233,8 +234,8 @@ class DrawTargetD2D1 : public DrawTarget {
already_AddRefed<ID2D1Brush> CreateTransparentBlackBrush();
already_AddRefed<ID2D1SolidColorBrush> GetSolidColorBrush(
const D2D_COLOR_F& aColor);
already_AddRefed<ID2D1Brush> CreateBrushForPattern(const Pattern& aPattern,
Float aAlpha = 1.0f);
already_AddRefed<ID2D1Brush> CreateBrushForPattern(
const Pattern& aPattern, const DrawOptions& aOptions);
void PushClipGeometry(ID2D1Geometry* aGeometry,
const D2D1_MATRIX_3X2_F& aTransform,

View file

@ -205,6 +205,7 @@ static inline bool D2DSupportsCompositeMode(CompositionOp aOp) {
case CompositionOp::OP_DEST_OVER:
case CompositionOp::OP_DEST_ATOP:
case CompositionOp::OP_XOR:
case CompositionOp::OP_CLEAR:
return true;
default:
return false;
@ -235,6 +236,8 @@ static inline D2D1_COMPOSITE_MODE D2DCompositionMode(CompositionOp aOp) {
return D2D1_COMPOSITE_MODE_DESTINATION_ATOP;
case CompositionOp::OP_XOR:
return D2D1_COMPOSITE_MODE_XOR;
case CompositionOp::OP_CLEAR:
return D2D1_COMPOSITE_MODE_DESTINATION_OUT;
default:
return D2D1_COMPOSITE_MODE_SOURCE_OVER;
}
@ -310,7 +313,12 @@ static inline D2D1_PRIMITIVE_BLEND D2DPrimitiveBlendMode(CompositionOp aOp) {
}
}
static inline bool IsPatternSupportedByD2D(const Pattern& aPattern) {
static inline bool IsPatternSupportedByD2D(
const Pattern& aPattern, CompositionOp aOp = CompositionOp::OP_OVER) {
if (aOp == CompositionOp::OP_CLEAR) {
return true;
}
if (aPattern.GetType() == PatternType::CONIC_GRADIENT) {
return false;
}