Files
palemoon27/gfx/2d/FilterProcessingScalar.cpp
T
roytam1 8f529f64f5 import changes from rmottola/Arctic-Fox:
- Bug 932865 - Add ThreadHangStats for collecting background hang telemetry; r=vladan (2f08a076b)
- Bug 932865 - Add way for telemetry to iterate over active threads; r=froydnj (535615d3d)
- Bug 1128768: Part 3 - Update BHR to allow for hang annotations; r=vladan (0b880a667)
- Bug 935092 - Add ThreadStackHelper to get a thread's pesudo-stack; r=BenWa (1422cfe4d)
- Bug 942488 - Don't report pseudo-stacks without SPS profiler. r=nchen (e160a7a08)
- Bug 946817 - Don't assert mPseudoStack on B2G. r=BenWa (9f846df3b)
- Bug 951431 - Don't get stacks during profiler runs on Linux; r=BenWa (15036e907)
- Bug 978262 - Ignore duplicate frames when getting BHR stack. r=froydnj (964721b1b)
- Bug 985155 - Add signal trampoline on ARM Linux to work around kernel bug. r=snorp (cb8a7846c)
- Bug 995730 - Convert xpcom/threads/ to Gecko style. r=froydnj (fe150404e)
- Bug 1013326 - Distinguish chrome and content scripts in pseudostack; r=snorp (81273c977)
- Bug 1023461 - Remove temporary stack buffer in ThreadStackHelper; r=snorp (cf5a717c2)
- Bug 1023461 - Record filename and line number for chrome JS entries; r=snorp (10c89808f)
- Bug 1022456 - Fix modelines in xpcom/{base,glue,io,string,threads}/. (48dbc0416)
- Bug 1016441 - Switch to using real-time signal in ThreadStackHelper; (2c5f818be)
- Bug 1016629 - b. Use RAII class to assign mStackToFill; r=snorp (769eae130)
- Bug 1016629 - c. Add define for ThreadStackHelper pseudostack support; r=snorp (67def0d2f)
- Bug 1016629 - d. Add and implement GetNativeStack method in ThreadStackHelper; r=snorp r=jseward (46c52f2be)
- Bug 1016629 - e. Implement platform-specific code for filling in context; r=snorp r=jseward (e6a66858b)
- Bug 1016629 - g. Avoid ASan flag when copying stack; r=snorp (0159628b5)
- Bug 1045176 - Unbreak build on non-SPS platforms after bug 1016629. (f1d60d838)
- Bug 1047123 - ThreadStackHelper should use UniquePtr<uint8_t[]>, not ScopedDeleteArray. r=jchen (0e4af313c)
- Bug 1049161 - Fix ThreadStackHelper thread handle permissions on Windows; r=snorp (c05172b1c)
- Bug 1050185 - Make ThreadStackHelper::FillThreadContext Valgrind-friendly. r=nchen (368725774)
- Bug 1050440 - Remove repeated js::RunScript frames in ThreadStackHelper (2a79600b3)
- Bug 1046841 - Fix more style violations in previously touched .cpp files in xpcom/. r=froydnj (02afe2493)
- Bug 1069694 - Remove or move around functions in OldDebugAPI. r=shu (177197302)
- Bug 1069694 - Remove OldDebugAPI from the browser. r=shu (b8c917d42)
- Bug 1100911 - For MacOS builds running on Valgrind, make ThreadStackHelper::GetStack be a no-op. r=nchen. (d99c02e16)
- Bug 1091758 - Report full paths for most chrome scripts; r=snorp (2b72e7878)
- Bug 1109291 - Include better paths for hanging chrome scripts in profile extensions directory; r=snorp r=bsmedberg (1997b9532)
- Bug 1113416 - Don't read stack labels inside hang monitor sighandler; r=nfroyd r=snorp (9688f6069)
- bug 1146027 - more final r=froydnj (7b0f295e5)
- Bug 1164090 - Check for Windows path separator in BHR file name; r=snorp (f014b4d78)
- Bug 1169034 - include <cstdlib> in ThreadStackHelper.cpp to declare correct overload for std::abs; r=jseward (874d4447e)
- Bug 1182996 - Fix and add missing namespace comments. rs=ehsan (054fc00b2)
- Bug 932865 - Collect thread hang stats in BackgroundHangMonitor; (ac80c8e9f)
- minor anticipated fixes to get it compiling (2bd701d15)
2020-02-01 08:07:15 +08:00

245 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 20; 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/. */
#define FILTER_PROCESSING_SCALAR
#include "FilterProcessingSIMD-inl.h"
#include "Logging.h"
namespace mozilla {
namespace gfx {
void
FilterProcessing::ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride)
{
for (int32_t y = 0; y < size.height; y++) {
for (int32_t x = 0; x < size.width; x++) {
int32_t sourceIndex = y * sourceStride + 4 * x;
int32_t targetIndex = y * alphaStride + x;
alphaData[targetIndex] = sourceData[sourceIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
}
}
}
already_AddRefed<DataSourceSurface>
FilterProcessing::ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface)
{
return ConvertToB8G8R8A8_SIMD<simd::Scalaru8x16_t>(aSurface);
}
template<MorphologyOperator Operator>
static void
ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
uint8_t* aDestData, int32_t aDestStride,
const IntRect& aDestRect, int32_t aRadius)
{
static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE ||
Operator == MORPHOLOGY_OPERATOR_DILATE,
"unexpected morphology operator");
for (int32_t y = aDestRect.y; y < aDestRect.YMost(); y++) {
int32_t startX = aDestRect.x - aRadius;
int32_t endX = aDestRect.x + aRadius;
for (int32_t x = aDestRect.x; x < aDestRect.XMost(); x++, startX++, endX++) {
int32_t sourceIndex = y * aSourceStride + 4 * startX;
uint8_t u[4];
for (size_t i = 0; i < 4; i++) {
u[i] = aSourceData[sourceIndex + i];
}
sourceIndex += 4;
for (int32_t ix = startX + 1; ix <= endX; ix++, sourceIndex += 4) {
for (size_t i = 0; i < 4; i++) {
if (Operator == MORPHOLOGY_OPERATOR_ERODE) {
u[i] = umin(u[i], aSourceData[sourceIndex + i]);
} else {
u[i] = umax(u[i], aSourceData[sourceIndex + i]);
}
}
}
int32_t destIndex = y * aDestStride + 4 * x;
for (size_t i = 0; i < 4; i++) {
aDestData[destIndex+i] = u[i];
}
}
}
}
void
FilterProcessing::ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
uint8_t* aDestData, int32_t aDestStride,
const IntRect& aDestRect, int32_t aRadius,
MorphologyOperator aOp)
{
if (aOp == MORPHOLOGY_OPERATOR_ERODE) {
gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_ERODE>(
aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
} else {
gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_DILATE>(
aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
}
}
template<MorphologyOperator Operator>
static void ApplyMorphologyVertical_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
uint8_t* aDestData, int32_t aDestStride,
const IntRect& aDestRect, int32_t aRadius)
{
static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE ||
Operator == MORPHOLOGY_OPERATOR_DILATE,
"unexpected morphology operator");
int32_t startY = aDestRect.y - aRadius;
int32_t endY = aDestRect.y + aRadius;
for (int32_t y = aDestRect.y; y < aDestRect.YMost(); y++, startY++, endY++) {
for (int32_t x = aDestRect.x; x < aDestRect.XMost(); x++) {
int32_t sourceIndex = startY * aSourceStride + 4 * x;
uint8_t u[4];
for (size_t i = 0; i < 4; i++) {
u[i] = aSourceData[sourceIndex + i];
}
sourceIndex += aSourceStride;
for (int32_t iy = startY + 1; iy <= endY; iy++, sourceIndex += aSourceStride) {
for (size_t i = 0; i < 4; i++) {
if (Operator == MORPHOLOGY_OPERATOR_ERODE) {
u[i] = umin(u[i], aSourceData[sourceIndex + i]);
} else {
u[i] = umax(u[i], aSourceData[sourceIndex + i]);
}
}
}
int32_t destIndex = y * aDestStride + 4 * x;
for (size_t i = 0; i < 4; i++) {
aDestData[destIndex+i] = u[i];
}
}
}
}
void
FilterProcessing::ApplyMorphologyVertical_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
uint8_t* aDestData, int32_t aDestStride,
const IntRect& aDestRect, int32_t aRadius,
MorphologyOperator aOp)
{
if (aOp == MORPHOLOGY_OPERATOR_ERODE) {
gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_ERODE>(
aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
} else {
gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_DILATE>(
aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
}
}
already_AddRefed<DataSourceSurface>
FilterProcessing::ApplyColorMatrix_Scalar(DataSourceSurface* aInput, const Matrix5x4 &aMatrix)
{
return ApplyColorMatrix_SIMD<simd::Scalari32x4_t,simd::Scalari16x8_t,simd::Scalaru8x16_t>(aInput, aMatrix);
}
void
FilterProcessing::ApplyComposition_Scalar(DataSourceSurface* aSource, DataSourceSurface* aDest,
CompositeOperator aOperator)
{
return ApplyComposition_SIMD<simd::Scalari32x4_t,simd::Scalaru16x8_t,simd::Scalaru8x16_t>(aSource, aDest, aOperator);
}
void
FilterProcessing::SeparateColorChannels_Scalar(const IntSize &size, uint8_t* sourceData, int32_t sourceStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data, int32_t channelStride)
{
for (int32_t y = 0; y < size.height; y++) {
for (int32_t x = 0; x < size.width; x++) {
int32_t sourceIndex = y * sourceStride + 4 * x;
int32_t targetIndex = y * channelStride + x;
channel0Data[targetIndex] = sourceData[sourceIndex];
channel1Data[targetIndex] = sourceData[sourceIndex+1];
channel2Data[targetIndex] = sourceData[sourceIndex+2];
channel3Data[targetIndex] = sourceData[sourceIndex+3];
}
}
}
void
FilterProcessing::CombineColorChannels_Scalar(const IntSize &size, int32_t resultStride, uint8_t* resultData, int32_t channelStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data)
{
for (int32_t y = 0; y < size.height; y++) {
for (int32_t x = 0; x < size.width; x++) {
int32_t resultIndex = y * resultStride + 4 * x;
int32_t channelIndex = y * channelStride + x;
resultData[resultIndex] = channel0Data[channelIndex];
resultData[resultIndex+1] = channel1Data[channelIndex];
resultData[resultIndex+2] = channel2Data[channelIndex];
resultData[resultIndex+3] = channel3Data[channelIndex];
}
}
}
void
FilterProcessing::DoPremultiplicationCalculation_Scalar(const IntSize& aSize,
uint8_t* aTargetData, int32_t aTargetStride,
uint8_t* aSourceData, int32_t aSourceStride)
{
for (int32_t y = 0; y < aSize.height; y++) {
for (int32_t x = 0; x < aSize.width; x++) {
int32_t inputIndex = y * aSourceStride + 4 * x;
int32_t targetIndex = y * aTargetStride + 4 * x;
uint8_t alpha = aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alpha);
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alpha);
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alpha);
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = alpha;
}
}
}
void
FilterProcessing::DoUnpremultiplicationCalculation_Scalar(
const IntSize& aSize,
uint8_t* aTargetData, int32_t aTargetStride,
uint8_t* aSourceData, int32_t aSourceStride)
{
for (int32_t y = 0; y < aSize.height; y++) {
for (int32_t x = 0; x < aSize.width; x++) {
int32_t inputIndex = y * aSourceStride + 4 * x;
int32_t targetIndex = y * aTargetStride + 4 * x;
uint8_t alpha = aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
uint16_t alphaFactor = sAlphaFactors[alpha];
// inputColor * alphaFactor + 128 is guaranteed to fit into uint16_t
// because the input is premultiplied and thus inputColor <= inputAlpha.
// The maximum value this can attain is 65520 (which is less than 65535)
// for color == alpha == 244:
// 244 * sAlphaFactors[244] + 128 == 244 * 268 + 128 == 65520
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alphaFactor + 128) >> 8;
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alphaFactor + 128) >> 8;
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alphaFactor + 128) >> 8;
aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = alpha;
}
}
}
already_AddRefed<DataSourceSurface>
FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
{
return RenderTurbulence_SIMD<simd::Scalarf32x4_t,simd::Scalari32x4_t,simd::Scalaru8x16_t>(
aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect);
}
already_AddRefed<DataSourceSurface>
FilterProcessing::ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4)
{
return ApplyArithmeticCombine_SIMD<simd::Scalari32x4_t,simd::Scalari16x8_t,simd::Scalaru8x16_t>(aInput1, aInput2, aK1, aK2, aK3, aK4);
}
} // namespace gfx
} // namespace mozilla