зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset f09499d7310c (bug 1359527) for Android bustage while processing gfx/2d/moz.build. r=backout
This commit is contained in:
Родитель
1545d39a00
Коммит
ff1767bcb6
|
@ -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__ */
|
Загрузка…
Ссылка в новой задаче