FilterProcessingScalar.cpp (8632B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #define FILTER_PROCESSING_SCALAR 8 9 #include "FilterProcessingSIMD-inl.h" 10 #include "Logging.h" 11 12 namespace mozilla { 13 namespace gfx { 14 15 void FilterProcessing::ExtractAlpha_Scalar(const IntSize& size, 16 const uint8_t* sourceData, 17 int32_t sourceStride, 18 uint8_t* alphaData, 19 int32_t alphaStride) { 20 for (int32_t y = 0; y < size.height; y++) { 21 for (int32_t x = 0; x < size.width; x++) { 22 int32_t sourceIndex = y * sourceStride + 4 * x; 23 int32_t targetIndex = y * alphaStride + x; 24 alphaData[targetIndex] = 25 sourceData[sourceIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A]; 26 } 27 } 28 } 29 30 already_AddRefed<DataSourceSurface> FilterProcessing::ConvertToB8G8R8A8_Scalar( 31 SourceSurface* aSurface) { 32 return ConvertToB8G8R8A8_SIMD<simd::Scalaru8x16_t>(aSurface); 33 } 34 35 template <MorphologyOperator Operator> 36 static void ApplyMorphologyHorizontal_Scalar( 37 const uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, 38 int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius) { 39 static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE || 40 Operator == MORPHOLOGY_OPERATOR_DILATE, 41 "unexpected morphology operator"); 42 43 for (int32_t y = aDestRect.Y(); y < aDestRect.YMost(); y++) { 44 int32_t startX = aDestRect.X() - aRadius; 45 int32_t endX = aDestRect.X() + aRadius; 46 for (int32_t x = aDestRect.X(); x < aDestRect.XMost(); 47 x++, startX++, endX++) { 48 int32_t sourceIndex = y * aSourceStride + 4 * startX; 49 uint8_t u[4]; 50 for (int32_t i = 0; i < std::ssize(u); i++) { 51 u[i] = aSourceData[sourceIndex + i]; 52 } 53 sourceIndex += 4; 54 for (int32_t ix = startX + 1; ix <= endX; ix++, sourceIndex += 4) { 55 for (int32_t i = 0; i < std::ssize(u); i++) { 56 if (Operator == MORPHOLOGY_OPERATOR_ERODE) { 57 u[i] = umin(u[i], aSourceData[sourceIndex + i]); 58 } else { 59 u[i] = umax(u[i], aSourceData[sourceIndex + i]); 60 } 61 } 62 } 63 64 int32_t destIndex = y * aDestStride + 4 * x; 65 for (int32_t i = 0; i < std::ssize(u); i++) { 66 aDestData[destIndex + i] = u[i]; 67 } 68 } 69 } 70 } 71 72 void FilterProcessing::ApplyMorphologyHorizontal_Scalar( 73 const uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, 74 int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, 75 MorphologyOperator aOp) { 76 if (aOp == MORPHOLOGY_OPERATOR_ERODE) { 77 gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_ERODE>( 78 aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius); 79 } else { 80 gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_DILATE>( 81 aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius); 82 } 83 } 84 85 template <MorphologyOperator Operator> 86 static void ApplyMorphologyVertical_Scalar( 87 const uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, 88 int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius) { 89 static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE || 90 Operator == MORPHOLOGY_OPERATOR_DILATE, 91 "unexpected morphology operator"); 92 93 int32_t startY = aDestRect.Y() - aRadius; 94 int32_t endY = aDestRect.Y() + aRadius; 95 for (int32_t y = aDestRect.Y(); y < aDestRect.YMost(); 96 y++, startY++, endY++) { 97 for (int32_t x = aDestRect.X(); x < aDestRect.XMost(); x++) { 98 int32_t sourceIndex = startY * aSourceStride + 4 * x; 99 uint8_t u[4]; 100 for (int32_t i = 0; i < std::ssize(u); i++) { 101 u[i] = aSourceData[sourceIndex + i]; 102 } 103 sourceIndex += aSourceStride; 104 for (int32_t iy = startY + 1; iy <= endY; 105 iy++, sourceIndex += aSourceStride) { 106 for (int32_t i = 0; i < std::ssize(u); i++) { 107 if (Operator == MORPHOLOGY_OPERATOR_ERODE) { 108 u[i] = umin(u[i], aSourceData[sourceIndex + i]); 109 } else { 110 u[i] = umax(u[i], aSourceData[sourceIndex + i]); 111 } 112 } 113 } 114 115 int32_t destIndex = y * aDestStride + 4 * x; 116 for (int32_t i = 0; i < std::ssize(u); i++) { 117 aDestData[destIndex + i] = u[i]; 118 } 119 } 120 } 121 } 122 123 void FilterProcessing::ApplyMorphologyVertical_Scalar( 124 const uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData, 125 int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius, 126 MorphologyOperator aOp) { 127 if (aOp == MORPHOLOGY_OPERATOR_ERODE) { 128 gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_ERODE>( 129 aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius); 130 } else { 131 gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_DILATE>( 132 aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius); 133 } 134 } 135 136 already_AddRefed<DataSourceSurface> FilterProcessing::ApplyColorMatrix_Scalar( 137 DataSourceSurface* aInput, const Matrix5x4& aMatrix) { 138 return ApplyColorMatrix_SIMD<simd::Scalari32x4_t, simd::Scalari16x8_t, 139 simd::Scalaru8x16_t>(aInput, aMatrix); 140 } 141 142 void FilterProcessing::ApplyComposition_Scalar(DataSourceSurface* aSource, 143 DataSourceSurface* aDest, 144 CompositeOperator aOperator) { 145 return ApplyComposition_SIMD<simd::Scalari32x4_t, simd::Scalaru16x8_t, 146 simd::Scalaru8x16_t>(aSource, aDest, aOperator); 147 } 148 149 void FilterProcessing::DoOpacityCalculation_Scalar( 150 const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride, 151 const uint8_t* aSourceData, int32_t aSourceStride, Float aValue) { 152 uint8_t alpha = uint8_t(roundf(255.f * aValue)); 153 for (int32_t y = 0; y < aSize.height; y++) { 154 for (int32_t x = 0; x < aSize.width; x++) { 155 int32_t inputIndex = y * aSourceStride + 4 * x; 156 int32_t targetIndex = y * aTargetStride + 4 * x; 157 aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] = 158 (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alpha) >> 159 8; 160 aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] = 161 (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alpha) >> 162 8; 163 aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] = 164 (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alpha) >> 165 8; 166 aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = 167 (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] * alpha) >> 168 8; 169 } 170 } 171 } 172 173 void FilterProcessing::DoOpacityCalculationA8_Scalar( 174 const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride, 175 const uint8_t* aSourceData, int32_t aSourceStride, Float aValue) { 176 uint8_t alpha = uint8_t(255.f * aValue); 177 for (int32_t y = 0; y < aSize.height; y++) { 178 for (int32_t x = 0; x < aSize.width; x++) { 179 int32_t inputIndex = y * aSourceStride; 180 int32_t targetIndex = y * aTargetStride; 181 aTargetData[targetIndex] = 182 FastDivideBy255<uint8_t>(aSourceData[inputIndex] * alpha); 183 } 184 } 185 } 186 187 already_AddRefed<DataSourceSurface> FilterProcessing::RenderTurbulence_Scalar( 188 const IntSize& aSize, const Point& aOffset, const Size& aBaseFrequency, 189 int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, 190 const Rect& aTileRect) { 191 return RenderTurbulence_SIMD<simd::Scalarf32x4_t, simd::Scalari32x4_t, 192 simd::Scalaru8x16_t>( 193 aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, 194 aTileRect); 195 } 196 197 already_AddRefed<DataSourceSurface> 198 FilterProcessing::ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, 199 DataSourceSurface* aInput2, 200 Float aK1, Float aK2, Float aK3, 201 Float aK4) { 202 return ApplyArithmeticCombine_SIMD<simd::Scalari32x4_t, simd::Scalari16x8_t, 203 simd::Scalaru8x16_t>(aInput1, aInput2, aK1, 204 aK2, aK3, aK4); 205 } 206 207 } // namespace gfx 208 } // namespace mozilla