diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 6676c9ee96ea..b12c3cd14c88 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -894,11 +894,6 @@ public: * normally return the same SourceSurface object. */ virtual already_AddRefed Snapshot() = 0; - - // Snapshots the contents and returns an alpha mask - // based on the RGB values. - virtual already_AddRefed IntoLuminanceSource(LuminanceType aLuminanceType, - float aOpacity); virtual IntSize GetSize() = 0; /** diff --git a/gfx/2d/DrawTarget.cpp b/gfx/2d/DrawTarget.cpp index 388097d9320b..4f89d05e8b64 100644 --- a/gfx/2d/DrawTarget.cpp +++ b/gfx/2d/DrawTarget.cpp @@ -9,172 +9,9 @@ #include "DrawTargetCapture.h" -#ifdef BUILD_ARM_NEON -#include "mozilla/arm.h" -#include "LuminanceNEON.h" -#endif - namespace mozilla { namespace gfx { -/** - * Byte offsets of channels in a native packed gfxColor or cairo image surface. - */ -#ifdef IS_BIG_ENDIAN -#define GFX_ARGB32_OFFSET_A 0 -#define GFX_ARGB32_OFFSET_R 1 -#define GFX_ARGB32_OFFSET_G 2 -#define GFX_ARGB32_OFFSET_B 3 -#else -#define GFX_ARGB32_OFFSET_A 3 -#define GFX_ARGB32_OFFSET_R 2 -#define GFX_ARGB32_OFFSET_G 1 -#define GFX_ARGB32_OFFSET_B 0 -#endif - -// c = n / 255 -// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5 -static const uint8_t gsRGBToLinearRGBMap[256] = { - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 8, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 12, 12, 12, 13, - 13, 13, 14, 14, 15, 15, 16, 16, - 17, 17, 17, 18, 18, 19, 19, 20, - 20, 21, 22, 22, 23, 23, 24, 24, - 25, 25, 26, 27, 27, 28, 29, 29, - 30, 30, 31, 32, 32, 33, 34, 35, - 35, 36, 37, 37, 38, 39, 40, 41, - 41, 42, 43, 44, 45, 45, 46, 47, - 48, 49, 50, 51, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 76, 77, 78, 79, - 80, 81, 82, 84, 85, 86, 87, 88, - 90, 91, 92, 93, 95, 96, 97, 99, -100, 101, 103, 104, 105, 107, 108, 109, -111, 112, 114, 115, 116, 118, 119, 121, -122, 124, 125, 127, 128, 130, 131, 133, -134, 136, 138, 139, 141, 142, 144, 146, -147, 149, 151, 152, 154, 156, 157, 159, -161, 163, 164, 166, 168, 170, 171, 173, -175, 177, 179, 181, 183, 184, 186, 188, -190, 192, 194, 196, 198, 200, 202, 204, -206, 208, 210, 212, 214, 216, 218, 220, -222, 224, 226, 229, 231, 233, 235, 237, -239, 242, 244, 246, 248, 250, 253, 255 -}; - -static void -ComputesRGBLuminanceMask(const uint8_t *aSourceData, - int32_t aSourceStride, - uint8_t *aDestData, - int32_t aDestStride, - const IntSize &aSize, - float aOpacity) -{ -#ifdef BUILD_ARM_NEON - if (mozilla::supports_neon()) { - ComputesRGBLuminanceMask_NEON(aSourceData, aSourceStride, - aDestData, aDestStride, - aSize, aOpacity); - return; - } -#endif - - int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity - int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity - int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721 - int32_t sourceOffset = aSourceStride - 4 * aSize.width; - const uint8_t *sourcePixel = aSourceData; - int32_t destOffset = aDestStride - aSize.width; - uint8_t *destPixel = aDestData; - - for (int32_t y = 0; y < aSize.height; y++) { - for (int32_t x = 0; x < aSize.width; x++) { - uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A]; - - if (a) { - *destPixel = (redFactor * sourcePixel[GFX_ARGB32_OFFSET_R] + - greenFactor * sourcePixel[GFX_ARGB32_OFFSET_G] + - blueFactor * sourcePixel[GFX_ARGB32_OFFSET_B]) >> 8; - } else { - *destPixel = 0; - } - sourcePixel += 4; - destPixel++; - } - sourcePixel += sourceOffset; - destPixel += destOffset; - } -} - -static void -ComputeLinearRGBLuminanceMask(const uint8_t *aSourceData, - int32_t aSourceStride, - uint8_t *aDestData, - int32_t aDestStride, - const IntSize &aSize, - float aOpacity) -{ - int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity - int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity - int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721 - int32_t sourceOffset = aSourceStride - 4 * aSize.width; - const uint8_t *sourcePixel = aSourceData; - int32_t destOffset = aDestStride - aSize.width; - uint8_t *destPixel = aDestData; - - for (int32_t y = 0; y < aSize.height; y++) { - for (int32_t x = 0; x < aSize.width; x++) { - uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A]; - - // unpremultiply - if (a) { - if (a == 255) { - /* sRGB -> linearRGB -> intensity */ - *destPixel = - static_cast - ((gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_R]] * - redFactor + - gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_G]] * - greenFactor + - gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_B]] * - blueFactor) >> 8); - } else { - uint8_t tempPixel[4]; - tempPixel[GFX_ARGB32_OFFSET_B] = - (255 * sourcePixel[GFX_ARGB32_OFFSET_B]) / a; - tempPixel[GFX_ARGB32_OFFSET_G] = - (255 * sourcePixel[GFX_ARGB32_OFFSET_G]) / a; - tempPixel[GFX_ARGB32_OFFSET_R] = - (255 * sourcePixel[GFX_ARGB32_OFFSET_R]) / a; - - /* sRGB -> linearRGB -> intensity */ - *destPixel = - static_cast - (((gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_R]] * - redFactor + - gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_G]] * - greenFactor + - gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_B]] * - blueFactor) >> 8) * (a / 255.0f)); - } - } else { - *destPixel = 0; - } - sourcePixel += 4; - destPixel++; - } - sourcePixel += sourceOffset; - destPixel += destOffset; - } -} - already_AddRefed DrawTarget::CreateCaptureDT(const IntSize& aSize) { @@ -227,51 +64,6 @@ DrawTarget::StrokeGlyphs(ScaledFont* aFont, Stroke(path, aPattern, aStrokeOptions, aOptions); } -already_AddRefed -DrawTarget::IntoLuminanceSource(LuminanceType aMaskType, float aOpacity) -{ - RefPtr surface = Snapshot(); - IntSize size = surface->GetSize(); - - RefPtr maskSurface = surface->GetDataSurface(); - DataSourceSurface::MappedSurface map; - if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) { - return nullptr; - } - - // Create alpha channel mask for output - RefPtr destMaskSurface = - Factory::CreateDataSourceSurface(size, SurfaceFormat::A8); - if (!destMaskSurface) { - return nullptr; - } - DataSourceSurface::MappedSurface destMap; - if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) { - return nullptr; - } - - switch (aMaskType) { - case LuminanceType::LUMINANCE: - { - ComputesRGBLuminanceMask(map.mData, map.mStride, - destMap.mData, destMap.mStride, - size, aOpacity); - break; - } - case LuminanceType::LINEARRGB: - { - ComputeLinearRGBLuminanceMask(map.mData, map.mStride, - destMap.mData, destMap.mStride, - size, aOpacity); - break; - } - } - - maskSurface->Unmap(); - destMaskSurface->Unmap(); - - return destMaskSurface.forget(); -} } // namespace gfx } // namespace mozilla diff --git a/gfx/2d/DrawTargetD2D1.cpp b/gfx/2d/DrawTargetD2D1.cpp index aedbe30b8f27..7d5971bf3a2d 100644 --- a/gfx/2d/DrawTargetD2D1.cpp +++ b/gfx/2d/DrawTargetD2D1.cpp @@ -99,37 +99,6 @@ DrawTargetD2D1::Snapshot() return snapshot.forget(); } -void -DrawTargetD2D1::EnsureLuminanceEffect() -{ - if (mLuminanceEffect.get()) { - return; - } - - HRESULT hr = mDC->CreateEffect(CLSID_D2D1LuminanceToAlpha, - getter_AddRefs(mLuminanceEffect)); - if (FAILED(hr)) { - gfxWarning() << "Failed to create luminance effect. Code: " << hexa(hr); - } -} - -already_AddRefed -DrawTargetD2D1::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity) -{ - if (aLuminanceType != LuminanceType::LUMINANCE) { - return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity); - } - - // Create the luminance effect - EnsureLuminanceEffect(); - mLuminanceEffect->SetInput(0, mBitmap); - - RefPtr luminanceOutput; - mLuminanceEffect->GetOutput(getter_AddRefs(luminanceOutput)); - - return MakeAndAddRef(luminanceOutput, mDC, SurfaceFormat::A8, mSize); -} - // Command lists are kept around by device contexts until EndDraw is called, // this can cause issues with memory usage (see bug 1238328). EndDraw/BeginDraw // are expensive though, especially relatively when little work is done, so @@ -851,27 +820,26 @@ DrawTargetD2D1::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask, options |= D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND; } - RefPtr mask; - Matrix maskTransform = aMaskTransform; - RefPtr clip; + RefPtr mask; + Matrix maskTransform = aMaskTransform; + + RefPtr clip; if (aMask) { - RefPtr image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP); mDC->SetTransform(D2D1::IdentityMatrix()); mTransformDirty = true; + RefPtr image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP); + // The mask is given in user space. Our layer will apply it in device space. maskTransform = maskTransform * mTransform; if (image) { - IntSize maskSize = aMask->GetSize(); - HRESULT hr = mDC->CreateImageBrush(image, - D2D1::ImageBrushProperties(D2D1::RectF(0, 0, maskSize.width, maskSize.height)), - D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), - getter_AddRefs(mask)); - if (FAILED(hr)) { - gfxWarning() <<"[D2D1.1] Failed to create a ImageBrush, code: " << hexa(hr); - } + RefPtr bitmap; + image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap)); + + mDC->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), getter_AddRefs(mask)); + MOZ_ASSERT(bitmap); // This should always be true since it was created for a surface. factory()->CreatePathGeometry(getter_AddRefs(clip)); RefPtr sink; @@ -1901,6 +1869,7 @@ DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTrans bool aUserSpace) { RefPtr image; + switch (aSurface->GetType()) { case SurfaceType::D2D1_1_IMAGE: { diff --git a/gfx/2d/DrawTargetD2D1.h b/gfx/2d/DrawTargetD2D1.h index 8154461213cd..68de9b332036 100644 --- a/gfx/2d/DrawTargetD2D1.h +++ b/gfx/2d/DrawTargetD2D1.h @@ -36,8 +36,6 @@ public: virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D1_1; } virtual already_AddRefed Snapshot() override; - virtual already_AddRefed IntoLuminanceSource(LuminanceType aLuminanceType, - float aOpacity) override; virtual IntSize GetSize() override { return mSize; } virtual void Flush() override; @@ -297,10 +295,6 @@ private: static IDWriteFactory *mDWriteFactory; // This value is uesed to verify if the DrawTarget is created by a stale device. uint32_t mDeviceSeq; - - // List of effects we use - void EnsureLuminanceEffect(); - RefPtr mLuminanceEffect; }; } diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h index 036c6ae13b67..28d203bb0562 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -278,12 +278,6 @@ enum class SamplingBounds : int8_t { BOUNDED }; -// Moz2d version for SVG mask types -enum class LuminanceType : int8_t { - LUMINANCE, - LINEARRGB, -}; - /* Color is stored in non-premultiplied form */ struct Color { diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 6cf2f65e4f6c..dd46590aa96e 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -220,11 +220,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: SOURCES += [ 'BlurNEON.cpp', - 'LuminanceNEON.cpp', 'SwizzleNEON.cpp', ] SOURCES['BlurNEON.cpp'].flags += CONFIG['NEON_FLAGS'] - SOURCES['LuminanceNEON.cpp'].flags += CONFIG['NEON_FLAGS'] SOURCES['SwizzleNEON.cpp'].flags += CONFIG['NEON_FLAGS'] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/layout/svg/moz.build b/layout/svg/moz.build index f64577dcdb66..60e0c2d0c94a 100644 --- a/layout/svg/moz.build +++ b/layout/svg/moz.build @@ -66,6 +66,10 @@ UNIFIED_SOURCES += [ 'SVGViewFrame.cpp', ] +if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: + SOURCES += ['nsSVGMaskFrameNEON.cpp'] + SOURCES['nsSVGMaskFrameNEON.cpp'].flags += CONFIG['NEON_FLAGS'] + FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '../../widget', diff --git a/layout/svg/nsSVGMaskFrame.cpp b/layout/svg/nsSVGMaskFrame.cpp index f39f07ddea0c..12f201b454be 100644 --- a/layout/svg/nsSVGMaskFrame.cpp +++ b/layout/svg/nsSVGMaskFrame.cpp @@ -14,12 +14,159 @@ #include "mozilla/RefPtr.h" #include "nsSVGEffects.h" #include "mozilla/dom/SVGMaskElement.h" +#ifdef BUILD_ARM_NEON +#include "mozilla/arm.h" +#include "nsSVGMaskFrameNEON.h" +#endif using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; using namespace mozilla::image; +// c = n / 255 +// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5 +static const uint8_t gsRGBToLinearRGBMap[256] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 12, 12, 12, 13, + 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 17, 18, 18, 19, 19, 20, + 20, 21, 22, 22, 23, 23, 24, 24, + 25, 25, 26, 27, 27, 28, 29, 29, + 30, 30, 31, 32, 32, 33, 34, 35, + 35, 36, 37, 37, 38, 39, 40, 41, + 41, 42, 43, 44, 45, 45, 46, 47, + 48, 49, 50, 51, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, + 80, 81, 82, 84, 85, 86, 87, 88, + 90, 91, 92, 93, 95, 96, 97, 99, +100, 101, 103, 104, 105, 107, 108, 109, +111, 112, 114, 115, 116, 118, 119, 121, +122, 124, 125, 127, 128, 130, 131, 133, +134, 136, 138, 139, 141, 142, 144, 146, +147, 149, 151, 152, 154, 156, 157, 159, +161, 163, 164, 166, 168, 170, 171, 173, +175, 177, 179, 181, 183, 184, 186, 188, +190, 192, 194, 196, 198, 200, 202, 204, +206, 208, 210, 212, 214, 216, 218, 220, +222, 224, 226, 229, 231, 233, 235, 237, +239, 242, 244, 246, 248, 250, 253, 255 +}; + +static void +ComputesRGBLuminanceMask(const uint8_t *aSourceData, + int32_t aSourceStride, + uint8_t *aDestData, + int32_t aDestStride, + const IntSize &aSize, + float aOpacity) +{ +#ifdef BUILD_ARM_NEON + if (mozilla::supports_neon()) { + ComputesRGBLuminanceMask_NEON(aSourceData, aSourceStride, + aDestData, aDestStride, + aSize, aOpacity); + return; + } +#endif + + int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity + int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity + int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721 + int32_t sourceOffset = aSourceStride - 4 * aSize.width; + const uint8_t *sourcePixel = aSourceData; + int32_t destOffset = aDestStride - aSize.width; + uint8_t *destPixel = aDestData; + + for (int32_t y = 0; y < aSize.height; y++) { + for (int32_t x = 0; x < aSize.width; x++) { + uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A]; + + if (a) { + *destPixel = (redFactor * sourcePixel[GFX_ARGB32_OFFSET_R] + + greenFactor * sourcePixel[GFX_ARGB32_OFFSET_G] + + blueFactor * sourcePixel[GFX_ARGB32_OFFSET_B]) >> 8; + } else { + *destPixel = 0; + } + sourcePixel += 4; + destPixel++; + } + sourcePixel += sourceOffset; + destPixel += destOffset; + } +} + +static void +ComputeLinearRGBLuminanceMask(const uint8_t *aSourceData, + int32_t aSourceStride, + uint8_t *aDestData, + int32_t aDestStride, + const IntSize &aSize, + float aOpacity) +{ + int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity + int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity + int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721 + int32_t sourceOffset = aSourceStride - 4 * aSize.width; + const uint8_t *sourcePixel = aSourceData; + int32_t destOffset = aDestStride - aSize.width; + uint8_t *destPixel = aDestData; + + for (int32_t y = 0; y < aSize.height; y++) { + for (int32_t x = 0; x < aSize.width; x++) { + uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A]; + + // unpremultiply + if (a) { + if (a == 255) { + /* sRGB -> linearRGB -> intensity */ + *destPixel = + static_cast + ((gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_R]] * + redFactor + + gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_G]] * + greenFactor + + gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_B]] * + blueFactor) >> 8); + } else { + uint8_t tempPixel[4]; + tempPixel[GFX_ARGB32_OFFSET_B] = + (255 * sourcePixel[GFX_ARGB32_OFFSET_B]) / a; + tempPixel[GFX_ARGB32_OFFSET_G] = + (255 * sourcePixel[GFX_ARGB32_OFFSET_G]) / a; + tempPixel[GFX_ARGB32_OFFSET_R] = + (255 * sourcePixel[GFX_ARGB32_OFFSET_R]) / a; + + /* sRGB -> linearRGB -> intensity */ + *destPixel = + static_cast + (((gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_R]] * + redFactor + + gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_G]] * + greenFactor + + gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_B]] * + blueFactor) >> 8) * (a / 255.0f)); + } + } else { + *destPixel = 0; + } + sourcePixel += 4; + destPixel++; + } + sourcePixel += sourceOffset; + destPixel += destOffset; + } +} + //---------------------------------------------------------------------- // Implementation @@ -31,22 +178,6 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame) -static LuminanceType -GetLuminanceType(uint8_t aNSMaskType) -{ - switch (aNSMaskType) { - case NS_STYLE_MASK_TYPE_LUMINANCE: - return LuminanceType::LUMINANCE; - case NS_STYLE_COLOR_INTERPOLATION_LINEARRGB: - return LuminanceType::LINEARRGB; - default: - { - NS_WARNING("Unknown SVG mask type, defaulting to luminance"); - return LuminanceType::LUMINANCE; - } - } -} - already_AddRefed nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams) { @@ -129,18 +260,42 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams) RefPtr surface; if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) { - if (StyleSVG()->mColorInterpolation == - NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) { - maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB; - } - - RefPtr maskSnapshot = - maskDT->IntoLuminanceSource(GetLuminanceType(maskType), aParams.opacity); + RefPtr maskSnapshot = maskDT->Snapshot(); if (!maskSnapshot) { return nullptr; } - surface = maskSnapshot.forget(); + RefPtr maskSurface = maskSnapshot->GetDataSurface(); + DataSourceSurface::MappedSurface map; + if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) { + return nullptr; + } + + // Create alpha channel mask for output + RefPtr destMaskSurface = + Factory::CreateDataSourceSurface(maskSurfaceSize, SurfaceFormat::A8); + if (!destMaskSurface) { + return nullptr; + } + DataSourceSurface::MappedSurface destMap; + if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) { + return nullptr; + } + + if (StyleSVG()->mColorInterpolation == + NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) { + ComputeLinearRGBLuminanceMask(map.mData, map.mStride, + destMap.mData, destMap.mStride, + maskSurfaceSize, aParams.opacity); + } else { + ComputesRGBLuminanceMask(map.mData, map.mStride, + destMap.mData, destMap.mStride, + maskSurfaceSize, aParams.opacity); + } + + maskSurface->Unmap(); + destMaskSurface->Unmap(); + surface = destMaskSurface.forget(); } else { maskDT->SetTransform(Matrix()); maskDT->FillRect(Rect(0, 0, maskSurfaceSize.width, maskSurfaceSize.height), ColorPattern(Color(1.0f, 1.0f, 1.0f, aParams.opacity)), DrawOptions(1, CompositionOp::OP_IN)); diff --git a/layout/svg/nsSVGMaskFrame.h b/layout/svg/nsSVGMaskFrame.h index bc937cb38633..b8ccfda754c2 100644 --- a/layout/svg/nsSVGMaskFrame.h +++ b/layout/svg/nsSVGMaskFrame.h @@ -16,6 +16,21 @@ class gfxContext; +/** + * Byte offsets of channels in a native packed gfxColor or cairo image surface. + */ +#ifdef IS_BIG_ENDIAN +#define GFX_ARGB32_OFFSET_A 0 +#define GFX_ARGB32_OFFSET_R 1 +#define GFX_ARGB32_OFFSET_G 2 +#define GFX_ARGB32_OFFSET_B 3 +#else +#define GFX_ARGB32_OFFSET_A 3 +#define GFX_ARGB32_OFFSET_R 2 +#define GFX_ARGB32_OFFSET_G 1 +#define GFX_ARGB32_OFFSET_B 0 +#endif + class nsSVGMaskFrame final : public nsSVGContainerFrame { friend nsIFrame* diff --git a/gfx/2d/LuminanceNEON.cpp b/layout/svg/nsSVGMaskFrameNEON.cpp similarity index 87% rename from gfx/2d/LuminanceNEON.cpp rename to layout/svg/nsSVGMaskFrameNEON.cpp index 07db921f3701..f690b8164dea 100644 --- a/gfx/2d/LuminanceNEON.cpp +++ b/layout/svg/nsSVGMaskFrameNEON.cpp @@ -3,27 +3,12 @@ * 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 "nsSVGMaskFrameNEON.h" +#include "nsSVGMaskFrame.h" #include -#include "LuminanceNEON.h" using namespace mozilla::gfx; -/** - * Byte offsets of channels in a native packed gfxColor or cairo image surface. - */ -#ifdef IS_BIG_ENDIAN -#define GFX_ARGB32_OFFSET_A 0 -#define GFX_ARGB32_OFFSET_R 1 -#define GFX_ARGB32_OFFSET_G 2 -#define GFX_ARGB32_OFFSET_B 3 -#else -#define GFX_ARGB32_OFFSET_A 3 -#define GFX_ARGB32_OFFSET_R 2 -#define GFX_ARGB32_OFFSET_G 1 -#define GFX_ARGB32_OFFSET_B 0 -#endif - - void ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData, int32_t aSourceStride, diff --git a/gfx/2d/LuminanceNEON.h b/layout/svg/nsSVGMaskFrameNEON.h similarity index 85% rename from gfx/2d/LuminanceNEON.h rename to layout/svg/nsSVGMaskFrameNEON.h index 95099600c841..1da901ba7f41 100644 --- a/gfx/2d/LuminanceNEON.h +++ b/layout/svg/nsSVGMaskFrameNEON.h @@ -3,8 +3,8 @@ * 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/. */ -#ifndef __LUMINANCENEON_H__ -#define __LUMINANCENEON_H__ +#ifndef __NS_SVGMASKFRAMENEON_H__ +#define __NS_SVGMASKFRAMENEON_H__ #include "mozilla/gfx/Point.h" @@ -16,4 +16,4 @@ ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData, const mozilla::gfx::IntSize &aSize, float aOpacity); -#endif /* __LUMINANCENEON_H__ */ +#endif /* __NS_SVGMASKFRAMENEON_H__ */