Restore FilterNodeSoftware intermediate surface caching (bug 1436723, r=mstange)

This is a just a back out of changeset 6882857e1bb5.

MozReview-Commit-ID: 9Z6iEHl3eAy

--HG--
extra : rebase_source : 3d091c72a6e589e702d90ffe6800e131b009604b
This commit is contained in:
Ryan Hunt 2018-02-08 15:21:06 -06:00
Родитель 5468b5b6a3
Коммит bdc27969fe
2 изменённых файлов: 321 добавлений и 2 удалений

Просмотреть файл

@ -613,7 +613,53 @@ FilterNodeSoftware::GetOutput(const IntRect &aRect)
return nullptr;
}
return Render(aRect);
if (!mCachedRect.Contains(aRect)) {
RequestRect(aRect);
mCachedOutput = Render(mRequestedRect);
if (!mCachedOutput) {
mCachedRect = IntRect();
mRequestedRect = IntRect();
return nullptr;
}
mCachedRect = mRequestedRect;
mRequestedRect = IntRect();
} else {
MOZ_ASSERT(mCachedOutput, "cached rect but no cached output?");
}
return GetDataSurfaceInRect(mCachedOutput, mCachedRect, aRect, EDGE_MODE_NONE);
}
void
FilterNodeSoftware::RequestRect(const IntRect &aRect)
{
if (mRequestedRect.Contains(aRect)) {
// Bail out now. Otherwise pathological filters can spend time exponential
// in the number of primitives, e.g. if each primitive takes the
// previous primitive as its two inputs.
return;
}
mRequestedRect = mRequestedRect.Union(aRect);
RequestFromInputsForRect(aRect);
}
void
FilterNodeSoftware::RequestInputRect(uint32_t aInputEnumIndex, const IntRect &aRect)
{
if (aRect.Overflows()) {
return;
}
int32_t inputIndex = InputIndex(aInputEnumIndex);
if (inputIndex < 0 || (uint32_t)inputIndex >= NumberOfSetInputs()) {
gfxDevCrash(LogReason::FilterInputError) << "Invalid input " << inputIndex << " vs. " << NumberOfSetInputs();
return;
}
if (mInputSurfaces[inputIndex]) {
return;
}
RefPtr<FilterNodeSoftware> filter = mInputFilters[inputIndex];
MOZ_ASSERT(filter, "missing input");
filter->RequestRect(filter->GetOutputRectInRect(aRect));
}
SurfaceFormat
@ -772,8 +818,50 @@ FilterNodeSoftware::NumberOfSetInputs()
return std::max(mInputSurfaces.size(), mInputFilters.size());
}
void
FilterNodeSoftware::AddInvalidationListener(FilterInvalidationListener* aListener)
{
MOZ_ASSERT(aListener, "null listener");
mInvalidationListeners.push_back(aListener);
}
void
FilterNodeSoftware::RemoveInvalidationListener(FilterInvalidationListener* aListener)
{
MOZ_ASSERT(aListener, "null listener");
std::vector<FilterInvalidationListener*>::iterator it =
std::find(mInvalidationListeners.begin(), mInvalidationListeners.end(), aListener);
mInvalidationListeners.erase(it);
}
void
FilterNodeSoftware::FilterInvalidated(FilterNodeSoftware* aFilter)
{
Invalidate();
}
void
FilterNodeSoftware::Invalidate()
{
mCachedOutput = nullptr;
mCachedRect = IntRect();
for (std::vector<FilterInvalidationListener*>::iterator it = mInvalidationListeners.begin();
it != mInvalidationListeners.end(); it++) {
(*it)->FilterInvalidated(this);
}
}
FilterNodeSoftware::~FilterNodeSoftware()
{
MOZ_ASSERT(!mInvalidationListeners.size(),
"All invalidation listeners should have unsubscribed themselves by now!");
for (std::vector<RefPtr<FilterNodeSoftware> >::iterator it = mInputFilters.begin();
it != mInputFilters.end(); it++) {
if (*it) {
(*it)->RemoveInvalidationListener(this);
}
}
}
void
@ -807,11 +895,18 @@ FilterNodeSoftware::SetInput(uint32_t aInputEnumIndex,
mInputFilters.resize(inputIndex + 1);
}
mInputSurfaces[inputIndex] = aSurface;
if (mInputFilters[inputIndex]) {
mInputFilters[inputIndex]->RemoveInvalidationListener(this);
}
if (aFilter) {
aFilter->AddInvalidationListener(this);
}
mInputFilters[inputIndex] = aFilter;
if (!aSurface && !aFilter && (size_t)inputIndex == NumberOfSetInputs()) {
mInputSurfaces.resize(inputIndex);
mInputFilters.resize(inputIndex);
}
Invalidate();
}
FilterNodeBlendSoftware::FilterNodeBlendSoftware()
@ -833,6 +928,7 @@ FilterNodeBlendSoftware::SetAttribute(uint32_t aIndex, uint32_t aBlendMode)
{
MOZ_ASSERT(aIndex == ATT_BLEND_BLENDMODE);
mBlendMode = static_cast<BlendMode>(aBlendMode);
Invalidate();
}
static CompositionOp ToBlendOp(BlendMode aOp)
@ -936,6 +1032,13 @@ FilterNodeBlendSoftware::Render(const IntRect& aRect)
return target.forget();
}
void
FilterNodeBlendSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_BLEND_IN, aRect);
RequestInputRect(IN_BLEND_IN2, aRect);
}
IntRect
FilterNodeBlendSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -961,6 +1064,7 @@ FilterNodeTransformSoftware::SetAttribute(uint32_t aIndex, uint32_t aFilter)
{
MOZ_ASSERT(aIndex == ATT_TRANSFORM_FILTER);
mSamplingFilter = static_cast<SamplingFilter>(aFilter);
Invalidate();
}
void
@ -968,6 +1072,7 @@ FilterNodeTransformSoftware::SetAttribute(uint32_t aIndex, const Matrix &aMatrix
{
MOZ_ASSERT(aIndex == ATT_TRANSFORM_MATRIX);
mMatrix = aMatrix;
Invalidate();
}
IntRect
@ -1042,6 +1147,12 @@ FilterNodeTransformSoftware::Render(const IntRect& aRect)
return surf.forget();
}
void
FilterNodeTransformSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_TRANSFORM_IN, SourceRectForOutputRect(aRect));
}
IntRect
FilterNodeTransformSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -1079,6 +1190,7 @@ FilterNodeMorphologySoftware::SetAttribute(uint32_t aIndex,
MOZ_ASSERT(aIndex == ATT_MORPHOLOGY_RADII);
mRadii.width = std::min(std::max(aRadii.width, 0), 100000);
mRadii.height = std::min(std::max(aRadii.height, 0), 100000);
Invalidate();
}
void
@ -1087,6 +1199,7 @@ FilterNodeMorphologySoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_MORPHOLOGY_OPERATOR);
mOperator = static_cast<MorphologyOperator>(aOperator);
Invalidate();
}
static already_AddRefed<DataSourceSurface>
@ -1175,6 +1288,14 @@ FilterNodeMorphologySoftware::Render(const IntRect& aRect)
return ApplyMorphology(srcRect, input, aRect, rx, ry, mOperator);
}
void
FilterNodeMorphologySoftware::RequestFromInputsForRect(const IntRect &aRect)
{
IntRect srcRect = aRect;
srcRect.Inflate(mRadii);
RequestInputRect(IN_MORPHOLOGY_IN, srcRect);
}
IntRect
FilterNodeMorphologySoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -1204,6 +1325,7 @@ FilterNodeColorMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_COLOR_MATRIX_MATRIX);
mMatrix = aMatrix;
Invalidate();
}
void
@ -1212,6 +1334,7 @@ FilterNodeColorMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_COLOR_MATRIX_ALPHA_MODE);
mAlphaMode = (AlphaMode)aAlphaMode;
Invalidate();
}
static already_AddRefed<DataSourceSurface>
@ -1301,6 +1424,12 @@ FilterNodeColorMatrixSoftware::Render(const IntRect& aRect)
return result.forget();
}
void
FilterNodeColorMatrixSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_COLOR_MATRIX_IN, aRect);
}
IntRect
FilterNodeColorMatrixSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -1315,6 +1444,7 @@ FilterNodeFloodSoftware::SetAttribute(uint32_t aIndex, const Color &aColor)
{
MOZ_ASSERT(aIndex == ATT_FLOOD_COLOR);
mColor = aColor;
Invalidate();
}
static uint32_t
@ -1417,6 +1547,7 @@ FilterNodeTileSoftware::SetAttribute(uint32_t aIndex,
MOZ_ASSERT(aIndex == ATT_TILE_SOURCE_RECT);
mSourceRect.SetRect(int32_t(aSourceRect.X()), int32_t(aSourceRect.Y()),
int32_t(aSourceRect.Width()), int32_t(aSourceRect.Height()));
Invalidate();
}
namespace {
@ -1505,6 +1636,15 @@ FilterNodeTileSoftware::Render(const IntRect& aRect)
return target.forget();
}
void
FilterNodeTileSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
// Do not request anything.
// Source rects for the tile filter can be discontinuous with large gaps
// between them. Requesting those from our input filter might cause it to
// render the whole bounding box of all of them, which would be wasteful.
}
IntRect
FilterNodeTileSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -1538,6 +1678,7 @@ FilterNodeComponentTransferSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeComponentTransferSoftware::SetAttribute");
}
Invalidate();
}
void
@ -1664,6 +1805,12 @@ FilterNodeComponentTransferSoftware::Render(const IntRect& aRect)
return target.forget();
}
void
FilterNodeComponentTransferSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_TRANSFER_IN, aRect);
}
IntRect
FilterNodeComponentTransferSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -1704,6 +1851,7 @@ FilterNodeTableTransferSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeTableTransferSoftware::SetAttribute");
}
Invalidate();
}
void
@ -1772,6 +1920,7 @@ FilterNodeDiscreteTransferSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeDiscreteTransferSoftware::SetAttribute");
}
Invalidate();
}
void
@ -1860,6 +2009,7 @@ FilterNodeLinearTransferSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeLinearTransferSoftware::SetAttribute");
}
Invalidate();
}
void
@ -1953,6 +2103,7 @@ FilterNodeGammaTransferSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeGammaTransferSoftware::SetAttribute");
}
Invalidate();
}
void
@ -2014,6 +2165,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_KERNEL_SIZE);
mKernelSize = aKernelSize;
Invalidate();
}
void
@ -2023,6 +2175,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_KERNEL_MATRIX);
mKernelMatrix = std::vector<Float>(aMatrix, aMatrix + aSize);
Invalidate();
}
void
@ -2038,6 +2191,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex, Float aValue)
default:
MOZ_CRASH("GFX: FilterNodeConvolveMatrixSoftware::SetAttribute");
}
Invalidate();
}
void
@ -2050,6 +2204,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex, const Size &aKer
default:
MOZ_CRASH("GFX: FilterNodeConvolveMatrixSoftware::SetAttribute");
}
Invalidate();
}
void
@ -2058,6 +2213,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_TARGET);
mTarget = aTarget;
Invalidate();
}
void
@ -2066,6 +2222,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_SOURCE_RECT);
mSourceRect = aSourceRect;
Invalidate();
}
void
@ -2074,6 +2231,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_EDGE_MODE);
mEdgeMode = static_cast<ConvolveMatrixEdgeMode>(aEdgeMode);
Invalidate();
}
void
@ -2082,6 +2240,7 @@ FilterNodeConvolveMatrixSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_CONVOLVE_MATRIX_PRESERVE_ALPHA);
mPreserveAlpha = aPreserveAlpha;
Invalidate();
}
#ifdef DEBUG
@ -2328,6 +2487,12 @@ FilterNodeConvolveMatrixSoftware::DoRender(const IntRect& aRect,
return target.forget();
}
void
FilterNodeConvolveMatrixSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_CONVOLVE_MATRIX_IN, InflatedSourceRect(aRect));
}
IntRect
FilterNodeConvolveMatrixSoftware::InflatedSourceRect(const IntRect &aDestRect)
{
@ -2394,6 +2559,7 @@ FilterNodeDisplacementMapSoftware::SetAttribute(uint32_t aIndex,
{
MOZ_ASSERT(aIndex == ATT_DISPLACEMENT_MAP_SCALE);
mScale = aScale;
Invalidate();
}
void
@ -2409,6 +2575,7 @@ FilterNodeDisplacementMapSoftware::SetAttribute(uint32_t aIndex, uint32_t aValue
default:
MOZ_CRASH("GFX: FilterNodeDisplacementMapSoftware::SetAttribute");
}
Invalidate();
}
already_AddRefed<DataSourceSurface>
@ -2473,6 +2640,13 @@ FilterNodeDisplacementMapSoftware::Render(const IntRect& aRect)
return target.forget();
}
void
FilterNodeDisplacementMapSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_DISPLACEMENT_MAP_IN, InflatedSourceOrDestRect(aRect));
RequestInputRect(IN_DISPLACEMENT_MAP_IN2, aRect);
}
IntRect
FilterNodeDisplacementMapSoftware::InflatedSourceOrDestRect(const IntRect &aDestOrSourceRect)
{
@ -2513,6 +2687,7 @@ FilterNodeTurbulenceSoftware::SetAttribute(uint32_t aIndex, const Size &aBaseFre
MOZ_CRASH("GFX: FilterNodeTurbulenceSoftware::SetAttribute");
break;
}
Invalidate();
}
void
@ -2526,6 +2701,7 @@ FilterNodeTurbulenceSoftware::SetAttribute(uint32_t aIndex, const IntRect &aRect
MOZ_CRASH("GFX: FilterNodeTurbulenceSoftware::SetAttribute");
break;
}
Invalidate();
}
void
@ -2533,6 +2709,7 @@ FilterNodeTurbulenceSoftware::SetAttribute(uint32_t aIndex, bool aStitchable)
{
MOZ_ASSERT(aIndex == ATT_TURBULENCE_STITCHABLE);
mStitchable = aStitchable;
Invalidate();
}
void
@ -2552,6 +2729,7 @@ FilterNodeTurbulenceSoftware::SetAttribute(uint32_t aIndex, uint32_t aValue)
MOZ_CRASH("GFX: FilterNodeTurbulenceSoftware::SetAttribute");
break;
}
Invalidate();
}
already_AddRefed<DataSourceSurface>
@ -2595,6 +2773,8 @@ FilterNodeArithmeticCombineSoftware::SetAttribute(uint32_t aIndex,
mK2 = aFloat[1];
mK3 = aFloat[2];
mK4 = aFloat[3];
Invalidate();
}
already_AddRefed<DataSourceSurface>
@ -2625,6 +2805,13 @@ FilterNodeArithmeticCombineSoftware::Render(const IntRect& aRect)
return FilterProcessing::ApplyArithmeticCombine(input1, input2, k1, k2, k3, k4);
}
void
FilterNodeArithmeticCombineSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_ARITHMETIC_COMBINE_IN, aRect);
RequestInputRect(IN_ARITHMETIC_COMBINE_IN2, aRect);
}
IntRect
FilterNodeArithmeticCombineSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -2661,6 +2848,7 @@ FilterNodeCompositeSoftware::SetAttribute(uint32_t aIndex, uint32_t aCompositeOp
{
MOZ_ASSERT(aIndex == ATT_COMPOSITE_OPERATOR);
mOperator = static_cast<CompositeOperator>(aCompositeOperator);
Invalidate();
}
already_AddRefed<DataSourceSurface>
@ -2707,6 +2895,14 @@ FilterNodeCompositeSoftware::Render(const IntRect& aRect)
return dest.forget();
}
void
FilterNodeCompositeSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
for (size_t inputIndex = 0; inputIndex < NumberOfSetInputs(); inputIndex++) {
RequestInputRect(IN_COMPOSITE_IN_START + inputIndex, aRect);
}
}
IntRect
FilterNodeCompositeSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -2792,6 +2988,12 @@ FilterNodeBlurXYSoftware::Render(const IntRect& aRect)
return GetDataSurfaceInRect(target, srcRect, aRect, EDGE_MODE_NONE);
}
void
FilterNodeBlurXYSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_GAUSSIAN_BLUR_IN, InflatedSourceOrDestRect(aRect));
}
IntRect
FilterNodeBlurXYSoftware::InflatedSourceOrDestRect(const IntRect &aDestRect)
{
@ -2832,6 +3034,7 @@ FilterNodeGaussianBlurSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeGaussianBlurSoftware::SetAttribute");
}
Invalidate();
}
Size
@ -2855,6 +3058,7 @@ FilterNodeDirectionalBlurSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeDirectionalBlurSoftware::SetAttribute");
}
Invalidate();
}
void
@ -2868,6 +3072,7 @@ FilterNodeDirectionalBlurSoftware::SetAttribute(uint32_t aIndex,
default:
MOZ_CRASH("GFX: FilterNodeDirectionalBlurSoftware::SetAttribute");
}
Invalidate();
}
Size
@ -2897,6 +3102,7 @@ FilterNodeCropSoftware::SetAttribute(uint32_t aIndex,
if (!srcRect.ToIntRect(&mCropRect)) {
mCropRect = IntRect();
}
Invalidate();
}
already_AddRefed<DataSourceSurface>
@ -2905,6 +3111,12 @@ FilterNodeCropSoftware::Render(const IntRect& aRect)
return GetInputDataSourceSurface(IN_CROP_IN, aRect.Intersect(mCropRect));
}
void
FilterNodeCropSoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_CROP_IN, aRect.Intersect(mCropRect));
}
IntRect
FilterNodeCropSoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -2928,6 +3140,12 @@ FilterNodePremultiplySoftware::Render(const IntRect& aRect)
return input ? Premultiply(input) : nullptr;
}
void
FilterNodePremultiplySoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_PREMULTIPLY_IN, aRect);
}
IntRect
FilterNodePremultiplySoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -2951,6 +3169,12 @@ FilterNodeUnpremultiplySoftware::Render(const IntRect& aRect)
return input ? Unpremultiply(input) : nullptr;
}
void
FilterNodeUnpremultiplySoftware::RequestFromInputsForRect(const IntRect &aRect)
{
RequestInputRect(IN_UNPREMULTIPLY_IN, aRect);
}
IntRect
FilterNodeUnpremultiplySoftware::GetOutputRectInRect(const IntRect& aRect)
{
@ -3061,6 +3285,7 @@ void
FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(uint32_t aIndex, const Point3D &aPoint)
{
if (mLight.SetAttribute(aIndex, aPoint)) {
Invalidate();
return;
}
MOZ_CRASH("GFX: FilterNodeLightingSoftware::SetAttribute point");
@ -3072,6 +3297,7 @@ FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(uint32_t aInde
{
if (mLight.SetAttribute(aIndex, aValue) ||
mLighting.SetAttribute(aIndex, aValue)) {
Invalidate();
return;
}
switch (aIndex) {
@ -3081,6 +3307,7 @@ FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(uint32_t aInde
default:
MOZ_CRASH("GFX: FilterNodeLightingSoftware::SetAttribute float");
}
Invalidate();
}
template<typename LightType, typename LightingType>
@ -3094,6 +3321,7 @@ FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(uint32_t aInde
default:
MOZ_CRASH("GFX: FilterNodeLightingSoftware::SetAttribute size");
}
Invalidate();
}
template<typename LightType, typename LightingType>
@ -3102,6 +3330,7 @@ FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(uint32_t aInde
{
MOZ_ASSERT(aIndex == ATT_LIGHTING_COLOR);
mColor = aColor;
Invalidate();
}
template<typename LightType, typename LightingType>
@ -3232,6 +3461,16 @@ FilterNodeLightingSoftware<LightType, LightingType>::Render(const IntRect& aRect
return DoRender(aRect, mKernelUnitLength.width, mKernelUnitLength.height);
}
template<typename LightType, typename LightingType>
void
FilterNodeLightingSoftware<LightType, LightingType>::RequestFromInputsForRect(const IntRect &aRect)
{
IntRect srcRect = aRect;
srcRect.Inflate(ceil(mKernelUnitLength.width),
ceil(mKernelUnitLength.height));
RequestInputRect(IN_LIGHTING_IN, srcRect);
}
template<typename LightType, typename LightingType> template<typename CoordType>
already_AddRefed<DataSourceSurface>
FilterNodeLightingSoftware<LightType, LightingType>::DoRender(const IntRect& aRect,

Просмотреть файл

@ -19,12 +19,25 @@ class DrawTarget;
struct DrawOptions;
class FilterNodeSoftware;
/**
* Can be attached to FilterNodeSoftware instances using
* AddInvalidationListener. FilterInvalidated is called whenever the output of
* the observed filter may have changed; that is, whenever cached GetOutput()
* results (and results derived from them) need to discarded.
*/
class FilterInvalidationListener
{
public:
virtual void FilterInvalidated(FilterNodeSoftware* aFilter) = 0;
};
/**
* This is the base class for the software (i.e. pure CPU, non-accelerated)
* FilterNode implementation. The software implementation is backend-agnostic,
* so it can be used as a fallback for all DrawTarget implementations.
*/
class FilterNodeSoftware : public FilterNode
class FilterNodeSoftware : public FilterNode,
public FilterInvalidationListener
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeSoftware, override)
@ -43,6 +56,12 @@ public:
virtual const char* GetName() { return "Unknown"; }
virtual void AddInvalidationListener(FilterInvalidationListener* aListener);
virtual void RemoveInvalidationListener(FilterInvalidationListener* aListener);
// FilterInvalidationListener implementation
virtual void FilterInvalidated(FilterNodeSoftware* aFilter) override;
protected:
// The following methods are intended to be overriden by subclasses.
@ -75,6 +94,13 @@ protected:
*/
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) = 0;
/**
* Call RequestRect (see below) on any input filters with the desired input
* rect, so that the input filter knows what to cache the next time it
* renders.
*/
virtual void RequestFromInputsForRect(const IntRect &aRect) {}
/**
* This method provides a caching default implementation but can be overriden
* by subclasses that don't want to cache their output. Those classes should
@ -127,12 +153,31 @@ protected:
*/
IntRect GetInputRectInRect(uint32_t aInputEnumIndex, const IntRect& aInRect);
/**
* Calls RequestRect on the specified input, if it's a filter.
*/
void RequestInputRect(uint32_t aInputEnumIndex, const IntRect& aRect);
/**
* Returns the number of set input filters or surfaces. Needed for filters
* which can have an arbitrary number of inputs.
*/
size_t NumberOfSetInputs();
/**
* Discard the cached surface that was stored in the GetOutput default
* implementation. Needs to be called whenever attributes or inputs are set
* that might change the result of a Render() call.
*/
void Invalidate();
/**
* Called in order to let this filter know what to cache during the next
* GetOutput call. Expected to call RequestRect on this filter's input
* filters.
*/
void RequestRect(const IntRect &aRect);
/**
* Set input filter and clear input surface for this input index, or set
* input surface and clear input filter. One of aSurface and aFilter should
@ -148,6 +193,26 @@ protected:
*/
std::vector<RefPtr<SourceSurface> > mInputSurfaces;
std::vector<RefPtr<FilterNodeSoftware> > mInputFilters;
/**
* Weak pointers to our invalidation listeners, i.e. to those filters who
* have this filter as an input. Invalidation listeners are required to
* unsubscribe themselves from us when they let go of their reference to us.
* This ensures that the pointers in this array are never stale.
*/
std::vector<FilterInvalidationListener*> mInvalidationListeners;
/**
* Stores the rect which we want to render and cache on the next call to
* GetOutput.
*/
IntRect mRequestedRect;
/**
* Stores our cached output.
*/
IntRect mCachedRect;
RefPtr<DataSourceSurface> mCachedOutput;
};
// Subclasses for specific filters.
@ -166,6 +231,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
IntRect SourceRectForOutputRect(const IntRect &aRect);
private:
@ -186,6 +252,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
BlendMode mBlendMode;
@ -205,6 +272,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
IntSize mRadii;
@ -224,6 +292,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
Matrix5x4 mMatrix;
@ -259,6 +328,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
IntRect mSourceRect;
@ -280,6 +350,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
virtual void GenerateLookupTable(ptrdiff_t aComponent, uint8_t aTables[4][256],
bool aDisabled);
virtual void FillLookupTable(ptrdiff_t aComponent, uint8_t aTable[256]) = 0;
@ -404,6 +475,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
template<typename CoordType>
@ -439,6 +511,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
IntRect InflatedSourceOrDestRect(const IntRect &aDestOrSourceRect);
@ -487,6 +560,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
Float mK1;
@ -508,6 +582,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
CompositeOperator mOperator;
@ -524,6 +599,7 @@ protected:
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
IntRect InflatedSourceOrDestRect(const IntRect &aDestRect);
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
// Implemented by subclasses.
virtual Size StdDeviationXY() = 0;
@ -575,6 +651,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
IntRect mCropRect;
@ -589,6 +666,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
};
class FilterNodeUnpremultiplySoftware : public FilterNodeSoftware
@ -600,6 +678,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
};
template<typename LightType, typename LightingType>
@ -623,6 +702,7 @@ protected:
virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
virtual void RequestFromInputsForRect(const IntRect &aRect) override;
private:
template<typename CoordType>