tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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