diff --git a/gfx/2d/FilterNodeD2D1.cpp b/gfx/2d/FilterNodeD2D1.cpp index 937798ab892..33becd3249b 100644 --- a/gfx/2d/FilterNodeD2D1.cpp +++ b/gfx/2d/FilterNodeD2D1.cpp @@ -30,6 +30,22 @@ D2D1_COLORMATRIX_ALPHA_MODE D2DAlphaMode(uint32_t aMode) return D2D1_COLORMATRIX_ALPHA_MODE_PREMULTIPLIED; } +D2D1_2DAFFINETRANSFORM_INTERPOLATION_MODE D2DAffineTransformInterpolationMode(uint32_t aFilter) +{ + switch (aFilter) { + case FILTER_GOOD: + return D2D1_2DAFFINETRANSFORM_INTERPOLATION_MODE_LINEAR; + case FILTER_LINEAR: + return D2D1_2DAFFINETRANSFORM_INTERPOLATION_MODE_LINEAR; + case FILTER_POINT: + return D2D1_2DAFFINETRANSFORM_INTERPOLATION_MODE_NEAREST_NEIGHBOR; + default: + MOZ_CRASH("Unknown enum value!"); + } + + return D2D1_2DAFFINETRANSFORM_INTERPOLATION_MODE_LINEAR; +} + D2D1_BLEND_MODE D2DBlendMode(uint32_t aMode) { switch (aMode) { @@ -145,6 +161,11 @@ uint32_t ConvertValue(uint32_t aType, uint32_t aAttribute, uint32_t aValue) aValue = D2DAlphaMode(aValue); } break; + case FILTER_TRANSFORM: + if (aAttribute == ATT_TRANSFORM_FILTER) { + aValue = D2DAffineTransformInterpolationMode(aValue); + } + break; case FILTER_BLEND: if (aAttribute == ATT_BLEND_BLENDMODE) { aValue = D2DBlendMode(aValue); @@ -210,6 +231,11 @@ GetD2D1PropForAttribute(uint32_t aType, uint32_t aIndex) CONVERT_PROP(COLOR_MATRIX_ALPHA_MODE, COLORMATRIX_PROP_ALPHA_MODE); } break; + case FILTER_TRANSFORM: + switch (aIndex) { + CONVERT_PROP(TRANSFORM_MATRIX, 2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX); + CONVERT_PROP(TRANSFORM_FILTER, 2DAFFINETRANSFORM_PROP_INTERPOLATION_MODE); + } case FILTER_BLEND: switch (aIndex) { CONVERT_PROP(BLEND_BLENDMODE, BLEND_PROP_MODE); @@ -430,6 +456,8 @@ static inline REFCLSID GetCLDIDForFilterType(FilterType aType) switch (aType) { case FILTER_COLOR_MATRIX: return CLSID_D2D1ColorMatrix; + case FILTER_TRANSFORM: + return CLSID_D2D12DAffineTransform; case FILTER_BLEND: return CLSID_D2D1Blend; case FILTER_MORPHOLOGY: @@ -446,8 +474,6 @@ static inline REFCLSID GetCLDIDForFilterType(FilterType aType) return CLSID_D2D1DiscreteTransfer; case FILTER_GAMMA_TRANSFER: return CLSID_D2D1GammaTransfer; - case FILTER_OFFSET: - return CLSID_D2D12DAffineTransform; case FILTER_DISPLACEMENT_MAP: return CLSID_D2D1DisplacementMap; case FILTER_TURBULENCE: @@ -511,6 +537,18 @@ FilterNodeD2D1::Create(DrawTarget* aDT, ID2D1DeviceContext *aDC, FilterType aTyp } } +void +FilterNodeD2D1::InitUnmappedProperties() +{ + switch (mType) { + case FILTER_TRANSFORM: + mEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_BORDER_MODE, D2D1_BORDER_MODE_HARD); + break; + default: + break; + } +} + void FilterNodeD2D1::SetInput(uint32_t aIndex, SourceSurface *aSurface) { @@ -705,21 +743,21 @@ FilterNodeD2D1::SetAttribute(uint32_t aIndex, const Float *aValues, uint32_t aSi void FilterNodeD2D1::SetAttribute(uint32_t aIndex, const IntPoint &aValue) { - if (mType == FILTER_OFFSET) { - MOZ_ASSERT(aIndex == ATT_OFFSET_OFFSET); - - Matrix mat; - mat.Translate(Float(aValue.x), Float(aValue.y)); - mEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, D2DMatrix(mat)); - return; - } - UINT32 input = GetD2D1PropForAttribute(mType, aIndex); MOZ_ASSERT(input < mEffect->GetPropertyCount()); mEffect->SetValue(input, D2DPoint(aValue)); } +void +FilterNodeD2D1::SetAttribute(uint32_t aIndex, const Matrix &aMatrix) +{ + UINT32 input = GetD2D1PropForAttribute(mType, aIndex); + MOZ_ASSERT(input < mEffect->GetPropertyCount()); + + mEffect->SetValue(input, D2DMatrix(aMatrix)); +} + FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC) : FilterNodeD2D1(aDT, nullptr, FILTER_CONVOLVE_MATRIX) , mEdgeMode(EDGE_MODE_DUPLICATE) diff --git a/gfx/2d/FilterNodeD2D1.h b/gfx/2d/FilterNodeD2D1.h index f022182887d..4e7a9f8a43f 100644 --- a/gfx/2d/FilterNodeD2D1.h +++ b/gfx/2d/FilterNodeD2D1.h @@ -23,7 +23,9 @@ public: : mDT(aDT) , mEffect(aEffect) , mType(aType) - {} + { + InitUnmappedProperties(); + } virtual FilterBackend GetBackendType() { return FILTER_BACKEND_DIRECT2D1_1; } @@ -43,6 +45,7 @@ public: virtual void SetAttribute(uint32_t aIndex, bool aValue); virtual void SetAttribute(uint32_t aIndex, const Float *aValues, uint32_t aSize); virtual void SetAttribute(uint32_t aIndex, const IntPoint &aValue); + virtual void SetAttribute(uint32_t aIndex, const Matrix &aValue); protected: friend class DrawTargetD2D1; @@ -52,6 +55,8 @@ protected: virtual ID2D1Effect* InputEffect() { return mEffect.get(); } virtual ID2D1Effect* OutputEffect() { return mEffect.get(); } + void InitUnmappedProperties(); + RefPtr mDT; RefPtr mEffect; FilterType mType; diff --git a/gfx/2d/FilterNodeSoftware.cpp b/gfx/2d/FilterNodeSoftware.cpp index 4c92de62073..7157cdd881c 100644 --- a/gfx/2d/FilterNodeSoftware.cpp +++ b/gfx/2d/FilterNodeSoftware.cpp @@ -473,6 +473,9 @@ FilterNodeSoftware::Create(FilterType aType) case FILTER_BLEND: filter = new FilterNodeBlendSoftware(); break; + case FILTER_TRANSFORM: + filter = new FilterNodeTransformSoftware(); + break; case FILTER_MORPHOLOGY: filter = new FilterNodeMorphologySoftware(); break; @@ -500,9 +503,6 @@ FilterNodeSoftware::Create(FilterType aType) case FILTER_CONVOLVE_MATRIX: filter = new FilterNodeConvolveMatrixSoftware(); break; - case FILTER_OFFSET: - filter = new FilterNodeOffsetSoftware(); - break; case FILTER_DISPLACEMENT_MAP: filter = new FilterNodeDisplacementMapSoftware(); break; @@ -908,6 +908,96 @@ FilterNodeBlendSoftware::GetOutputRectInRect(const IntRect& aRect) GetInputRectInRect(IN_BLEND_IN2, aRect)).Intersect(aRect); } +FilterNodeTransformSoftware::FilterNodeTransformSoftware() + : mFilter(FILTER_GOOD) +{} + +int32_t +FilterNodeTransformSoftware::InputIndex(uint32_t aInputEnumIndex) +{ + switch (aInputEnumIndex) { + case IN_TRANSFORM_IN: return 0; + default: return -1; + } +} + +void +FilterNodeTransformSoftware::SetAttribute(uint32_t aIndex, uint32_t aFilter) +{ + MOZ_ASSERT(aIndex == ATT_TRANSFORM_FILTER); + mFilter = static_cast(aFilter); + Invalidate(); +} + +void +FilterNodeTransformSoftware::SetAttribute(uint32_t aIndex, const Matrix &aMatrix) +{ + MOZ_ASSERT(aIndex == ATT_TRANSFORM_MATRIX); + mMatrix = aMatrix; + Invalidate(); +} + +IntRect +FilterNodeTransformSoftware::SourceRectForOutputRect(const IntRect &aRect) +{ + Matrix inverted(mMatrix); + if (!inverted.Invert()) { + return IntRect(); + } + + Rect neededRect = inverted.TransformBounds(Rect(aRect)); + neededRect.RoundOut(); + return GetInputRectInRect(IN_TRANSFORM_IN, RoundedToInt(neededRect)); +} + +TemporaryRef +FilterNodeTransformSoftware::Render(const IntRect& aRect) +{ + IntRect srcRect = SourceRectForOutputRect(aRect); + + RefPtr input = + GetInputDataSourceSurface(IN_TRANSFORM_IN, srcRect, NEED_COLOR_CHANNELS); + + if (!input) { + return nullptr; + } + + Matrix transform = Matrix().Translate(srcRect.x, srcRect.y) * mMatrix * + Matrix().Translate(-aRect.x, -aRect.y); + if (transform.IsIdentity() && srcRect.Size() == aRect.Size()) { + return input; + } + + RefPtr dt = + Factory::CreateDrawTarget(BACKEND_CAIRO, aRect.Size(), input->GetFormat()); + if (!dt) { + return nullptr; + } + + Rect r(0, 0, srcRect.width, srcRect.height); + dt->SetTransform(transform); + dt->DrawSurface(input, r, r, DrawSurfaceOptions(mFilter)); + + RefPtr result = dt->Snapshot(); + RefPtr resultData = result->GetDataSurface(); + return resultData; +} + +void +FilterNodeTransformSoftware::RequestFromInputsForRect(const IntRect &aRect) +{ + RequestInputRect(IN_TRANSFORM_IN, SourceRectForOutputRect(aRect)); +} + +IntRect +FilterNodeTransformSoftware::GetOutputRectInRect(const IntRect& aRect) +{ + IntRect srcRect = SourceRectForOutputRect(aRect); + Rect outRect = mMatrix.TransformBounds(Rect(srcRect)); + outRect.RoundOut(); + return RoundedToInt(outRect).Intersect(aRect); +} + FilterNodeMorphologySoftware::FilterNodeMorphologySoftware() : mOperator(MORPHOLOGY_OPERATOR_ERODE) {} @@ -2187,49 +2277,6 @@ FilterNodeConvolveMatrixSoftware::GetOutputRectInRect(const IntRect& aRect) return InflatedDestRect(srcOutput).Intersect(aRect); } -int32_t -FilterNodeOffsetSoftware::InputIndex(uint32_t aInputEnumIndex) -{ - switch (aInputEnumIndex) { - case IN_OFFSET_IN: return 0; - default: return -1; - } -} - -void -FilterNodeOffsetSoftware::SetAttribute(uint32_t aIndex, - const IntPoint &aOffset) -{ - MOZ_ASSERT(aIndex == ATT_OFFSET_OFFSET); - mOffset = aOffset; - Invalidate(); -} - -TemporaryRef -FilterNodeOffsetSoftware::Render(const IntRect& aRect) -{ - return GetInputDataSourceSurface(IN_OFFSET_IN, aRect - mOffset); -} - -// Override GetOutput in order to disable caching. -TemporaryRef -FilterNodeOffsetSoftware::GetOutput(const IntRect& aRect) -{ - return Render(aRect); -} - -void -FilterNodeOffsetSoftware::RequestFromInputsForRect(const IntRect &aRect) -{ - RequestInputRect(IN_OFFSET_IN, aRect - mOffset); -} - -IntRect -FilterNodeOffsetSoftware::GetOutputRectInRect(const IntRect& aRect) -{ - return GetInputRectInRect(IN_OFFSET_IN, aRect - mOffset) + mOffset; -} - FilterNodeDisplacementMapSoftware::FilterNodeDisplacementMapSoftware() : mScale(0.0f) , mChannelX(COLOR_CHANNEL_R) diff --git a/gfx/2d/FilterNodeSoftware.h b/gfx/2d/FilterNodeSoftware.h index 981a2cc25b2..0ff34c0befd 100644 --- a/gfx/2d/FilterNodeSoftware.h +++ b/gfx/2d/FilterNodeSoftware.h @@ -212,6 +212,26 @@ protected: // Subclasses for specific filters. +class FilterNodeTransformSoftware : public FilterNodeSoftware +{ +public: + FilterNodeTransformSoftware(); + using FilterNodeSoftware::SetAttribute; + virtual void SetAttribute(uint32_t aIndex, uint32_t aGraphicsFilter) MOZ_OVERRIDE; + virtual void SetAttribute(uint32_t aIndex, const Matrix &aMatrix) MOZ_OVERRIDE; + +protected: + virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; + virtual IntRect GetOutputRectInRect(const IntRect& aRect) MOZ_OVERRIDE; + virtual int32_t InputIndex(uint32_t aInputEnumIndex) MOZ_OVERRIDE; + virtual void RequestFromInputsForRect(const IntRect &aRect) MOZ_OVERRIDE; + IntRect SourceRectForOutputRect(const IntRect &aRect); + +private: + Matrix mMatrix; + Filter mFilter; +}; + class FilterNodeBlendSoftware : public FilterNodeSoftware { public: @@ -449,23 +469,6 @@ private: bool mPreserveAlpha; }; -class FilterNodeOffsetSoftware : public FilterNodeSoftware -{ -public: - using FilterNodeSoftware::SetAttribute; - virtual void SetAttribute(uint32_t aIndex, const IntPoint &aOffset) MOZ_OVERRIDE; - -protected: - virtual TemporaryRef GetOutput(const IntRect &aRect) MOZ_OVERRIDE; - virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; - virtual IntRect GetOutputRectInRect(const IntRect& aRect) MOZ_OVERRIDE; - virtual int32_t InputIndex(uint32_t aInputEnumIndex) MOZ_OVERRIDE; - virtual void RequestFromInputsForRect(const IntRect &aRect) MOZ_OVERRIDE; - -private: - IntPoint mOffset; -}; - class FilterNodeDisplacementMapSoftware : public FilterNodeSoftware { public: diff --git a/gfx/2d/Filters.h b/gfx/2d/Filters.h index bd803f346e1..14df2b78d7a 100644 --- a/gfx/2d/Filters.h +++ b/gfx/2d/Filters.h @@ -23,6 +23,17 @@ enum FilterBackend { FILTER_BACKEND_DIRECT2D1_1 }; +enum TransformFilterAtts +{ + ATT_TRANSFORM_MATRIX = 0, // Matrix + ATT_TRANSFORM_FILTER // Filter +}; + +enum TransformFilterInputs +{ + IN_TRANSFORM_IN = 0 +}; + enum BlendFilterAtts { ATT_BLEND_BLENDMODE = 0 // uint32_t @@ -214,16 +225,6 @@ enum ConvolveMatrixInputs IN_CONVOLVE_MATRIX_IN = 0 }; -enum OffsetAtts -{ - ATT_OFFSET_OFFSET = 0 // IntPoint -}; - -enum OffsetInputs -{ - IN_OFFSET_IN = 0 -}; - enum DisplacementMapAtts { ATT_DISPLACEMENT_MAP_SCALE = 0, // Float @@ -480,6 +481,7 @@ public: virtual void SetAttribute(uint32_t aIndex, const Rect &) { MOZ_CRASH(); } virtual void SetAttribute(uint32_t aIndex, const IntRect &) { MOZ_CRASH(); } virtual void SetAttribute(uint32_t aIndex, const Point &) { MOZ_CRASH(); } + virtual void SetAttribute(uint32_t aIndex, const Matrix &) { MOZ_CRASH(); } virtual void SetAttribute(uint32_t aIndex, const Matrix5x4 &) { MOZ_CRASH(); } virtual void SetAttribute(uint32_t aIndex, const Point3D &) { MOZ_CRASH(); } virtual void SetAttribute(uint32_t aIndex, const Color &) { MOZ_CRASH(); } diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h index af7ea3247b4..f81461c6afc 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -46,6 +46,7 @@ enum SurfaceFormat enum FilterType { FILTER_BLEND = 0, + FILTER_TRANSFORM, FILTER_MORPHOLOGY, FILTER_COLOR_MATRIX, FILTER_FLOOD, @@ -55,7 +56,6 @@ enum FilterType FILTER_LINEAR_TRANSFER, FILTER_GAMMA_TRANSFER, FILTER_CONVOLVE_MATRIX, - FILTER_OFFSET, FILTER_DISPLACEMENT_MAP, FILTER_TURBULENCE, FILTER_ARITHMETIC_COMBINE,