gecko-dev/gfx/2d/DrawTargetDual.cpp
Ryan Hunt 9c419c4c91 Bug 1478815 part 2 - Make DrawTargetDual aware of component alpha clearing. r=bas
This commit changes the behavior of DrawTargetDual::Clear to be aware that
it has on-white and on-black buffers, and perform clearing appropriately.

This is slightly against what the DrawTarget documentation says the method
should do, but it allows us to move another paint thread operation into
DrawTargetCapture and simplify our ContentClient implementations.

I haven't seen any obvious breakage with this, and reftests are green.

An alternative would be to add a separate Clear method with documented
difference here.

MozReview-Commit-ID: 65CzcxlRqv7

--HG--
extra : rebase_source : 299adbb02e79f66f7d6860c5fe86784bad8332f8
extra : source : 3dc47f17fa446bb7f2b5876753f8271a93c0e0c8
2018-08-01 12:45:35 -05:00

225 lines
6.8 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DrawTargetDual.h"
#include "Tools.h"
#include "Logging.h"
namespace mozilla {
namespace gfx {
class DualSurface
{
public:
inline explicit DualSurface(SourceSurface *aSurface)
{
if (!aSurface) {
mA = mB = nullptr;
return;
}
if (aSurface->GetType() != SurfaceType::DUAL_DT) {
mA = mB = aSurface;
return;
}
SourceSurfaceDual *ssDual =
static_cast<SourceSurfaceDual*>(aSurface);
mA = ssDual->mA;
mB = ssDual->mB;
}
SourceSurface *mA;
SourceSurface *mB;
};
/* This only needs to split patterns up for SurfacePatterns. Only in that
* case can we be dealing with a 'dual' source (SourceSurfaceDual) and do
* we need to pass separate patterns into our destination DrawTargets.
*/
class DualPattern
{
public:
inline explicit DualPattern(const Pattern &aPattern)
: mPatternsInitialized(false)
{
if (aPattern.GetType() != PatternType::SURFACE) {
mA = mB = &aPattern;
return;
}
const SurfacePattern *surfPat =
static_cast<const SurfacePattern*>(&aPattern);
if (surfPat->mSurface->GetType() != SurfaceType::DUAL_DT) {
mA = mB = &aPattern;
return;
}
const SourceSurfaceDual *ssDual =
static_cast<const SourceSurfaceDual*>(surfPat->mSurface.get());
mA = new (mSurfPatA.addr()) SurfacePattern(ssDual->mA, surfPat->mExtendMode,
surfPat->mMatrix,
surfPat->mSamplingFilter);
mB = new (mSurfPatB.addr()) SurfacePattern(ssDual->mB, surfPat->mExtendMode,
surfPat->mMatrix,
surfPat->mSamplingFilter);
mPatternsInitialized = true;
}
inline ~DualPattern()
{
if (mPatternsInitialized) {
mA->~Pattern();
mB->~Pattern();
}
}
ClassStorage<SurfacePattern> mSurfPatA;
ClassStorage<SurfacePattern> mSurfPatB;
const Pattern *mA;
const Pattern *mB;
bool mPatternsInitialized;
};
void
DrawTargetDual::DetachAllSnapshots()
{
mA->DetachAllSnapshots();
mB->DetachAllSnapshots();
}
void
DrawTargetDual::DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource,
const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions)
{
DualSurface surface(aSurface);
mA->DrawSurface(surface.mA, aDest, aSource, aSurfOptions, aOptions);
mB->DrawSurface(surface.mB, aDest, aSource, aSurfOptions, aOptions);
}
void
DrawTargetDual::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest,
const Color &aColor, const Point &aOffset,
Float aSigma, CompositionOp aOp)
{
DualSurface surface(aSurface);
mA->DrawSurfaceWithShadow(surface.mA, aDest, aColor, aOffset, aSigma, aOp);
mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp);
}
void
DrawTargetDual::MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions)
{
DualPattern source(aSource);
DualSurface mask(aMask);
mA->MaskSurface(*source.mA, mask.mA, aOffset, aOptions);
mB->MaskSurface(*source.mB, mask.mB, aOffset, aOptions);
}
void
DrawTargetDual::ClearRect(const Rect &aRect)
{
mA->FillRect(aRect, ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
mB->FillRect(aRect, ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
}
void
DrawTargetDual::CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect,
const IntPoint &aDestination)
{
DualSurface surface(aSurface);
mA->CopySurface(surface.mA, aSourceRect, aDestination);
mB->CopySurface(surface.mB, aSourceRect, aDestination);
}
void
DrawTargetDual::FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->FillRect(aRect, *pattern.mA, aOptions);
mB->FillRect(aRect, *pattern.mB, aOptions);
}
void
DrawTargetDual::StrokeRect(const Rect &aRect, const Pattern &aPattern,
const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->StrokeRect(aRect, *pattern.mA, aStrokeOptions, aOptions);
mB->StrokeRect(aRect, *pattern.mB, aStrokeOptions, aOptions);
}
void
DrawTargetDual::StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern,
const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->StrokeLine(aStart, aEnd, *pattern.mA, aStrokeOptions, aOptions);
mB->StrokeLine(aStart, aEnd, *pattern.mB, aStrokeOptions, aOptions);
}
void
DrawTargetDual::Stroke(const Path *aPath, const Pattern &aPattern,
const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->Stroke(aPath, *pattern.mA, aStrokeOptions, aOptions);
mB->Stroke(aPath, *pattern.mB, aStrokeOptions, aOptions);
}
void
DrawTargetDual::Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->Fill(aPath, *pattern.mA, aOptions);
mB->Fill(aPath, *pattern.mB, aOptions);
}
void
DrawTargetDual::FillGlyphs(ScaledFont *aScaledFont, const GlyphBuffer &aBuffer,
const Pattern &aPattern, const DrawOptions &aOptions)
{
DualPattern pattern(aPattern);
mA->FillGlyphs(aScaledFont, aBuffer, *pattern.mA, aOptions);
mB->FillGlyphs(aScaledFont, aBuffer, *pattern.mB, aOptions);
}
void
DrawTargetDual::Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions)
{
DualPattern source(aSource);
DualPattern mask(aMask);
mA->Mask(*source.mA, *mask.mA, aOptions);
mB->Mask(*source.mB, *mask.mB, aOptions);
}
void
DrawTargetDual::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
const Matrix& aMaskTransform, const IntRect& aBounds,
bool aCopyBackground)
{
DualSurface mask(aMask);
mA->PushLayer(aOpaque, aOpacity, mask.mA, aMaskTransform, aBounds, aCopyBackground);
mB->PushLayer(aOpaque, aOpacity, mask.mB, aMaskTransform, aBounds, aCopyBackground);
}
already_AddRefed<DrawTarget>
DrawTargetDual::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
{
/* Now that we have PushLayer there a very few cases where a user of DrawTargetDual
* wants to have a DualTarget when creating a similar one. */
return mA->CreateSimilarDrawTarget(aSize, aFormat);
}
} // namespace gfx
} // namespace mozilla