Backed out changeset f09499d7310c (bug 1359527) for Android bustage while processing gfx/2d/moz.build. r=backout

This commit is contained in:
Sebastian Hengst 2017-06-06 18:40:32 +02:00
Родитель 1545d39a00
Коммит ff1767bcb6
11 изменённых файлов: 300 добавлений и 317 удалений

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

@ -894,11 +894,6 @@ public:
* normally return the same SourceSurface object.
*/
virtual already_AddRefed<SourceSurface> Snapshot() = 0;
// Snapshots the contents and returns an alpha mask
// based on the RGB values.
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(LuminanceType aLuminanceType,
float aOpacity);
virtual IntSize GetSize() = 0;
/**

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

@ -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<uint8_t>
((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<uint8_t>
(((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<DrawTargetCapture>
DrawTarget::CreateCaptureDT(const IntSize& aSize)
{
@ -227,51 +64,6 @@ DrawTarget::StrokeGlyphs(ScaledFont* aFont,
Stroke(path, aPattern, aStrokeOptions, aOptions);
}
already_AddRefed<SourceSurface>
DrawTarget::IntoLuminanceSource(LuminanceType aMaskType, float aOpacity)
{
RefPtr<SourceSurface> surface = Snapshot();
IntSize size = surface->GetSize();
RefPtr<DataSourceSurface> maskSurface = surface->GetDataSurface();
DataSourceSurface::MappedSurface map;
if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
return nullptr;
}
// Create alpha channel mask for output
RefPtr<DataSourceSurface> 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

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

@ -99,38 +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<SourceSurface>
DrawTargetD2D1::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity)
{
//return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity);
if (aLuminanceType != LuminanceType::LUMINANCE) {
return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity);
}
// Create the luminance effect
EnsureLuminanceEffect();
mLuminanceEffect->SetInput(0, mBitmap);
RefPtr<ID2D1Image> luminanceOutput;
mLuminanceEffect->GetOutput(getter_AddRefs(luminanceOutput));
return MakeAndAddRef<SourceSurfaceD2D1>(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
@ -380,48 +348,20 @@ DrawTargetD2D1::MaskSurface(const Pattern &aSource,
PrepareForDrawing(aOptions.mCompositionOp, aSource);
IntSize size = IntSize::Truncate(aMask->GetSize().width, aMask->GetSize().height);
Rect dest = Rect(aOffset.x, aOffset.y, Float(size.width), Float(size.height));
HRESULT hr = image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
if (!bitmap || FAILED(hr)) {
// D2D says if we have an actual ID2D1Image and not a bitmap underlying the object,
// we can't query for a bitmap. Instead, Push/PopLayer
gfxWarning() << "FillOpacityMask only works with Bitmap source surfaces. Falling back to push/pop layer";
RefPtr<ID2D1Brush> source = CreateBrushForPattern(aSource, aOptions.mAlpha);
RefPtr<ID2D1ImageBrush> maskBrush;
hr = mDC->CreateImageBrush(image,
D2D1::ImageBrushProperties(D2D1::RectF(0, 0, size.width, size.height)),
D2D1::BrushProperties(1.0f, D2D1::IdentityMatrix()),
getter_AddRefs(maskBrush));
MOZ_ASSERT(SUCCEEDED(hr));
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::IdentityMatrix(),
1.0f, maskBrush, D2D1_LAYER_OPTIONS1_NONE),
nullptr);
mDC->FillRectangle(D2DRect(dest), source);
mDC->PopLayer();
FinalizeDrawing(aOptions.mCompositionOp, aSource);
return;
} else {
// If this is a data source surface, we might have created a partial bitmap
// for this surface and only uploaded part of the mask. In that case,
// we have to fixup our sizes here.
size.width = bitmap->GetSize().width;
size.height = bitmap->GetSize().height;
dest.width = size.width;
dest.height = size.height;
}
// FillOpacityMask only works if the antialias mode is MODE_ALIASED
mDC->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
if (!bitmap) {
gfxWarning() << "FillOpacityMask only works with Bitmap source surfaces.";
return;
}
IntSize size = IntSize::Truncate(bitmap->GetSize().width, bitmap->GetSize().height);
Rect maskRect = Rect(0.f, 0.f, Float(size.width), Float(size.height));
Rect dest = Rect(aOffset.x, aOffset.y, Float(size.width), Float(size.height));
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions.mAlpha);
mDC->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect));
@ -1931,6 +1871,7 @@ DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTrans
bool aUserSpace)
{
RefPtr<ID2D1Image> image;
switch (aSurface->GetType()) {
case SurfaceType::D2D1_1_IMAGE:
{

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

@ -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<SourceSurface> Snapshot() override;
virtual already_AddRefed<SourceSurface> 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<ID2D1Effect> mLuminanceEffect;
};
}

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

@ -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
{

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

@ -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')

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

@ -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',

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

@ -14,28 +14,162 @@
#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;
static LuminanceType
GetLuminanceType(uint8_t aNSMaskType)
// 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)
{
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;
#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<uint8_t>
((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<uint8_t>
(((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
nsIFrame*
NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
@ -124,20 +258,44 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);
}
if (StyleSVG()->mColorInterpolation ==
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
}
RefPtr<SourceSurface> surface;
if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
RefPtr<SourceSurface> maskSnapshot =
maskDT->IntoLuminanceSource(GetLuminanceType(maskType),
aParams.opacity);
RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
if (!maskSnapshot) {
return nullptr;
}
surface = maskSnapshot.forget();
RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
DataSourceSurface::MappedSurface map;
if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
return nullptr;
}
// Create alpha channel mask for output
RefPtr<DataSourceSurface> 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));

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

@ -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*

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsSVGMaskFrameNEON.h"
#include "nsSVGMaskFrame.h"
#include <arm_neon.h>
using namespace mozilla::gfx;
void
ComputesRGBLuminanceMask_NEON(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
const uint8_t *sourcePixel = aSourceData;
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
uint8_t *destPixel = aDestData;
int32_t destOffset = aDestStride - aSize.width;
sourcePixel = aSourceData;
int32_t remainderWidth = aSize.width % 8;
int32_t roundedWidth = aSize.width - remainderWidth;
uint16x8_t temp;
uint8x8_t gray;
uint8x8_t redVector = vdup_n_u8(redFactor);
uint8x8_t greenVector = vdup_n_u8(greenFactor);
uint8x8_t blueVector = vdup_n_u8(blueFactor);
uint8x8_t fullBitVector = vdup_n_u8(255);
uint8x8_t oneVector = vdup_n_u8(1);
for (int32_t y = 0; y < aSize.height; y++) {
// Calculate luminance by neon with 8 pixels per loop
for (int32_t x = 0; x < roundedWidth; x += 8) {
uint8x8x4_t argb = vld4_u8(sourcePixel);
temp = vmull_u8(argb.val[GFX_ARGB32_OFFSET_R], redVector); // temp = red * redFactor
temp = vmlal_u8(temp, argb.val[GFX_ARGB32_OFFSET_G], greenVector); // temp += green * greenFactor
temp = vmlal_u8(temp, argb.val[GFX_ARGB32_OFFSET_B], blueVector); // temp += blue * blueFactor
gray = vshrn_n_u16(temp, 8); // gray = temp >> 8
// Check alpha value
uint8x8_t alphaVector = vtst_u8(argb.val[GFX_ARGB32_OFFSET_A], fullBitVector);
gray = vmul_u8(gray, vand_u8(alphaVector, oneVector));
// Put the result to the 8 pixels
vst1_u8(destPixel, gray);
sourcePixel += 8 * 4;
destPixel += 8;
}
// Calculate the rest pixels of the line by cpu
for (int32_t x = 0; x < remainderWidth; x++) {
if (sourcePixel[GFX_ARGB32_OFFSET_A] > 0) {
*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;
}
}

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

@ -0,0 +1,19 @@
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef __NS_SVGMASKFRAMENEON_H__
#define __NS_SVGMASKFRAMENEON_H__
#include "mozilla/gfx/Point.h"
void
ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
int32_t aSourceStride,
uint8_t *aDestData,
int32_t aDestStride,
const mozilla::gfx::IntSize &aSize,
float aOpacity);
#endif /* __NS_SVGMASKFRAMENEON_H__ */