Backed out changeset e12fa325e112 (bug 1359527) for Win8 masking reftest failures

MozReview-Commit-ID: 5ecOfTu606d
This commit is contained in:
Phil Ringnalda 2017-05-28 15:45:42 -07:00
Родитель fe139bbf07
Коммит 16b90e808a
11 изменённых файлов: 215 добавлений и 314 удалений

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

@ -894,11 +894,6 @@ public:
* normally return the same SourceSurface object. * normally return the same SourceSurface object.
*/ */
virtual already_AddRefed<SourceSurface> Snapshot() = 0; 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; virtual IntSize GetSize() = 0;
/** /**

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

@ -9,172 +9,9 @@
#include "DrawTargetCapture.h" #include "DrawTargetCapture.h"
#ifdef BUILD_ARM_NEON
#include "mozilla/arm.h"
#include "LuminanceNEON.h"
#endif
namespace mozilla { namespace mozilla {
namespace gfx { 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> already_AddRefed<DrawTargetCapture>
DrawTarget::CreateCaptureDT(const IntSize& aSize) DrawTarget::CreateCaptureDT(const IntSize& aSize)
{ {
@ -227,51 +64,6 @@ DrawTarget::StrokeGlyphs(ScaledFont* aFont,
Stroke(path, aPattern, aStrokeOptions, aOptions); 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 gfx
} // namespace mozilla } // namespace mozilla

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

@ -99,37 +99,6 @@ DrawTargetD2D1::Snapshot()
return snapshot.forget(); 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)
{
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, // Command lists are kept around by device contexts until EndDraw is called,
// this can cause issues with memory usage (see bug 1238328). EndDraw/BeginDraw // this can cause issues with memory usage (see bug 1238328). EndDraw/BeginDraw
// are expensive though, especially relatively when little work is done, so // 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; options |= D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
} }
RefPtr<ID2D1ImageBrush> mask; RefPtr<ID2D1BitmapBrush> mask;
Matrix maskTransform = aMaskTransform;
RefPtr<ID2D1PathGeometry> clip;
Matrix maskTransform = aMaskTransform;
RefPtr<ID2D1PathGeometry> clip;
if (aMask) { if (aMask) {
RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
mDC->SetTransform(D2D1::IdentityMatrix()); mDC->SetTransform(D2D1::IdentityMatrix());
mTransformDirty = true; mTransformDirty = true;
RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
// The mask is given in user space. Our layer will apply it in device space. // The mask is given in user space. Our layer will apply it in device space.
maskTransform = maskTransform * mTransform; maskTransform = maskTransform * mTransform;
if (image) { if (image) {
IntSize maskSize = aMask->GetSize(); RefPtr<ID2D1Bitmap> bitmap;
HRESULT hr = mDC->CreateImageBrush(image, image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
D2D1::ImageBrushProperties(D2D1::RectF(0, 0, maskSize.width, maskSize.height)),
D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), mDC->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), getter_AddRefs(mask));
getter_AddRefs(mask)); MOZ_ASSERT(bitmap); // This should always be true since it was created for a surface.
if (FAILED(hr)) {
gfxWarning() <<"[D2D1.1] Failed to create a ImageBrush, code: " << hexa(hr);
}
factory()->CreatePathGeometry(getter_AddRefs(clip)); factory()->CreatePathGeometry(getter_AddRefs(clip));
RefPtr<ID2D1GeometrySink> sink; RefPtr<ID2D1GeometrySink> sink;
@ -1901,6 +1869,7 @@ DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTrans
bool aUserSpace) bool aUserSpace)
{ {
RefPtr<ID2D1Image> image; RefPtr<ID2D1Image> image;
switch (aSurface->GetType()) { switch (aSurface->GetType()) {
case SurfaceType::D2D1_1_IMAGE: case SurfaceType::D2D1_1_IMAGE:
{ {

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

@ -36,8 +36,6 @@ public:
virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; }
virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D1_1; } virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D1_1; }
virtual already_AddRefed<SourceSurface> Snapshot() override; virtual already_AddRefed<SourceSurface> Snapshot() override;
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(LuminanceType aLuminanceType,
float aOpacity) override;
virtual IntSize GetSize() override { return mSize; } virtual IntSize GetSize() override { return mSize; }
virtual void Flush() override; virtual void Flush() override;
@ -297,10 +295,6 @@ private:
static IDWriteFactory *mDWriteFactory; static IDWriteFactory *mDWriteFactory;
// This value is uesed to verify if the DrawTarget is created by a stale device. // This value is uesed to verify if the DrawTarget is created by a stale device.
uint32_t mDeviceSeq; uint32_t mDeviceSeq;
// List of effects we use
void EnsureLuminanceEffect();
RefPtr<ID2D1Effect> mLuminanceEffect;
}; };
} }

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

@ -278,12 +278,6 @@ enum class SamplingBounds : int8_t {
BOUNDED BOUNDED
}; };
// Moz2d version for SVG mask types
enum class LuminanceType : int8_t {
LUMINANCE,
LINEARRGB,
};
/* Color is stored in non-premultiplied form */ /* Color is stored in non-premultiplied form */
struct Color struct Color
{ {

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

@ -220,11 +220,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']: if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
SOURCES += [ SOURCES += [
'BlurNEON.cpp', 'BlurNEON.cpp',
'LuminanceNEON.cpp',
'SwizzleNEON.cpp', 'SwizzleNEON.cpp',
] ]
SOURCES['BlurNEON.cpp'].flags += CONFIG['NEON_FLAGS'] SOURCES['BlurNEON.cpp'].flags += CONFIG['NEON_FLAGS']
SOURCES['LuminanceNEON.cpp'].flags += CONFIG['NEON_FLAGS']
SOURCES['SwizzleNEON.cpp'].flags += CONFIG['NEON_FLAGS'] SOURCES['SwizzleNEON.cpp'].flags += CONFIG['NEON_FLAGS']
include('/ipc/chromium/chromium-config.mozbuild') include('/ipc/chromium/chromium-config.mozbuild')

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

@ -66,6 +66,10 @@ UNIFIED_SOURCES += [
'SVGViewFrame.cpp', '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' FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'../../widget', '../../widget',

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

@ -14,12 +14,159 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsSVGEffects.h" #include "nsSVGEffects.h"
#include "mozilla/dom/SVGMaskElement.h" #include "mozilla/dom/SVGMaskElement.h"
#ifdef BUILD_ARM_NEON
#include "mozilla/arm.h"
#include "nsSVGMaskFrameNEON.h"
#endif
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
using namespace mozilla::gfx; using namespace mozilla::gfx;
using namespace mozilla::image; 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<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 // Implementation
@ -31,22 +178,6 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame) 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<SourceSurface> already_AddRefed<SourceSurface>
nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams) nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
{ {
@ -129,18 +260,42 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
RefPtr<SourceSurface> surface; RefPtr<SourceSurface> surface;
if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) { if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
if (StyleSVG()->mColorInterpolation == RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
}
RefPtr<SourceSurface> maskSnapshot =
maskDT->IntoLuminanceSource(GetLuminanceType(maskType), aParams.opacity);
if (!maskSnapshot) { if (!maskSnapshot) {
return nullptr; 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 { } else {
maskDT->SetTransform(Matrix()); 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)); 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; 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 class nsSVGMaskFrame final : public nsSVGContainerFrame
{ {
friend nsIFrame* friend nsIFrame*

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

@ -3,27 +3,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsSVGMaskFrameNEON.h"
#include "nsSVGMaskFrame.h"
#include <arm_neon.h> #include <arm_neon.h>
#include "LuminanceNEON.h"
using namespace mozilla::gfx; 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 void
ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData, ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
int32_t aSourceStride, int32_t aSourceStride,

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

@ -3,8 +3,8 @@
* license, v. 2.0. if a copy of the mpl was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __LUMINANCENEON_H__ #ifndef __NS_SVGMASKFRAMENEON_H__
#define __LUMINANCENEON_H__ #define __NS_SVGMASKFRAMENEON_H__
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
@ -16,4 +16,4 @@ ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
const mozilla::gfx::IntSize &aSize, const mozilla::gfx::IntSize &aSize,
float aOpacity); float aOpacity);
#endif /* __LUMINANCENEON_H__ */ #endif /* __NS_SVGMASKFRAMENEON_H__ */