gfx/2d/FilterProcessingScalar.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #define FILTER_PROCESSING_SCALAR
     8 #include "FilterProcessingSIMD-inl.h"
    10 namespace mozilla {
    11 namespace gfx {
    13 void
    14 FilterProcessing::ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride)
    15 {
    16   for (int32_t y = 0; y < size.height; y++) {
    17     for (int32_t x = 0; x < size.width; x++) {
    18       int32_t sourceIndex = y * sourceStride + 4 * x;
    19       int32_t targetIndex = y * alphaStride + x;
    20       alphaData[targetIndex] = sourceData[sourceIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
    21     }
    22   }
    23 }
    25 TemporaryRef<DataSourceSurface>
    26 FilterProcessing::ConvertToB8G8R8A8_Scalar(SourceSurface* aSurface)
    27 {
    28   return ConvertToB8G8R8A8_SIMD<simd::Scalaru8x16_t>(aSurface);
    29 }
    31 template<BlendMode aBlendMode>
    32 static TemporaryRef<DataSourceSurface>
    33 ApplyBlending_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2)
    34 {
    35   IntSize size = aInput1->GetSize();
    36   RefPtr<DataSourceSurface> target =
    37     Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
    38   if (!target) {
    39     return nullptr;
    40   }
    42   uint8_t* source1Data = aInput1->GetData();
    43   uint8_t* source2Data = aInput2->GetData();
    44   uint8_t* targetData = target->GetData();
    45   uint32_t targetStride = target->Stride();
    46   uint32_t source1Stride = aInput1->Stride();
    47   uint32_t source2Stride = aInput2->Stride();
    49   for (int32_t y = 0; y < size.height; y++) {
    50     for (int32_t x = 0; x < size.width; x++) {
    51       uint32_t targetIndex = y * targetStride + 4 * x;
    52       uint32_t source1Index = y * source1Stride + 4 * x;
    53       uint32_t source2Index = y * source2Stride + 4 * x;
    54       uint32_t qa = source1Data[source1Index + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
    55       uint32_t qb = source2Data[source2Index + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
    56       for (int32_t i = std::min(B8G8R8A8_COMPONENT_BYTEOFFSET_B, B8G8R8A8_COMPONENT_BYTEOFFSET_R);
    57            i <= std::max(B8G8R8A8_COMPONENT_BYTEOFFSET_B, B8G8R8A8_COMPONENT_BYTEOFFSET_R); i++) {
    58         uint32_t ca = source1Data[source1Index + i];
    59         uint32_t cb = source2Data[source2Index + i];
    60         uint32_t val;
    61         switch (aBlendMode) {
    62           case BLEND_MODE_MULTIPLY:
    63             val = ((255 - qa) * cb + (255 - qb + cb) * ca);
    64             break;
    65           case BLEND_MODE_SCREEN:
    66             val = 255 * (cb + ca) - ca * cb;
    67             break;
    68           case BLEND_MODE_DARKEN:
    69             val = umin((255 - qa) * cb + 255 * ca,
    70                        (255 - qb) * ca + 255 * cb);
    71             break;
    72           case BLEND_MODE_LIGHTEN:
    73             val = umax((255 - qa) * cb + 255 * ca,
    74                        (255 - qb) * ca + 255 * cb);
    75             break;
    76           default:
    77             MOZ_CRASH();
    78         }
    79         val = umin(FilterProcessing::FastDivideBy255<unsigned>(val), 255U);
    80         targetData[targetIndex + i] = static_cast<uint8_t>(val);
    81       }
    82       uint32_t alpha = 255 * 255 - (255 - qa) * (255 - qb);
    83       targetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] =
    84         FilterProcessing::FastDivideBy255<uint8_t>(alpha);
    85     }
    86   }
    88   return target;
    89 }
    91 TemporaryRef<DataSourceSurface>
    92 FilterProcessing::ApplyBlending_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2,
    93                                        BlendMode aBlendMode)
    94 {
    95   switch (aBlendMode) {
    96     case BLEND_MODE_MULTIPLY:
    97       return gfx::ApplyBlending_Scalar<BLEND_MODE_MULTIPLY>(aInput1, aInput2);
    98     case BLEND_MODE_SCREEN:
    99       return gfx::ApplyBlending_Scalar<BLEND_MODE_SCREEN>(aInput1, aInput2);
   100     case BLEND_MODE_DARKEN:
   101       return gfx::ApplyBlending_Scalar<BLEND_MODE_DARKEN>(aInput1, aInput2);
   102     case BLEND_MODE_LIGHTEN:
   103       return gfx::ApplyBlending_Scalar<BLEND_MODE_LIGHTEN>(aInput1, aInput2);
   104     default:
   105       return nullptr;
   106   }
   107 }
   109 template<MorphologyOperator Operator>
   110 static void
   111 ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
   112                                  uint8_t* aDestData, int32_t aDestStride,
   113                                  const IntRect& aDestRect, int32_t aRadius)
   114 {
   115   static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE ||
   116                 Operator == MORPHOLOGY_OPERATOR_DILATE,
   117                 "unexpected morphology operator");
   119   for (int32_t y = aDestRect.y; y < aDestRect.YMost(); y++) {
   120     int32_t startX = aDestRect.x - aRadius;
   121     int32_t endX = aDestRect.x + aRadius;
   122     for (int32_t x = aDestRect.x; x < aDestRect.XMost(); x++, startX++, endX++) {
   123       int32_t sourceIndex = y * aSourceStride + 4 * startX;
   124       uint8_t u[4];
   125       for (size_t i = 0; i < 4; i++) {
   126         u[i] = aSourceData[sourceIndex + i];
   127       }
   128       sourceIndex += 4;
   129       for (int32_t ix = startX + 1; ix <= endX; ix++, sourceIndex += 4) {
   130         for (size_t i = 0; i < 4; i++) {
   131           if (Operator == MORPHOLOGY_OPERATOR_ERODE) {
   132             u[i] = umin(u[i], aSourceData[sourceIndex + i]);
   133           } else {
   134             u[i] = umax(u[i], aSourceData[sourceIndex + i]);
   135           }
   136         }
   137       }
   139       int32_t destIndex = y * aDestStride + 4 * x;
   140       for (size_t i = 0; i < 4; i++) {
   141         aDestData[destIndex+i] = u[i];
   142       }
   143     }
   144   }
   145 }
   147 void
   148 FilterProcessing::ApplyMorphologyHorizontal_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
   149                                                    uint8_t* aDestData, int32_t aDestStride,
   150                                                    const IntRect& aDestRect, int32_t aRadius,
   151                                                    MorphologyOperator aOp)
   152 {
   153   if (aOp == MORPHOLOGY_OPERATOR_ERODE) {
   154     gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_ERODE>(
   155       aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
   156   } else {
   157     gfx::ApplyMorphologyHorizontal_Scalar<MORPHOLOGY_OPERATOR_DILATE>(
   158       aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
   159   }
   160 }
   162 template<MorphologyOperator Operator>
   163 static void ApplyMorphologyVertical_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
   164                                            uint8_t* aDestData, int32_t aDestStride,
   165                                            const IntRect& aDestRect, int32_t aRadius)
   166 {
   167   static_assert(Operator == MORPHOLOGY_OPERATOR_ERODE ||
   168                 Operator == MORPHOLOGY_OPERATOR_DILATE,
   169                 "unexpected morphology operator");
   171   int32_t startY = aDestRect.y - aRadius;
   172   int32_t endY = aDestRect.y + aRadius;
   173   for (int32_t y = aDestRect.y; y < aDestRect.YMost(); y++, startY++, endY++) {
   174     for (int32_t x = aDestRect.x; x < aDestRect.XMost(); x++) {
   175       int32_t sourceIndex = startY * aSourceStride + 4 * x;
   176       uint8_t u[4];
   177       for (size_t i = 0; i < 4; i++) {
   178         u[i] = aSourceData[sourceIndex + i];
   179       }
   180       sourceIndex += aSourceStride;
   181       for (int32_t iy = startY + 1; iy <= endY; iy++, sourceIndex += aSourceStride) {
   182         for (size_t i = 0; i < 4; i++) {
   183           if (Operator == MORPHOLOGY_OPERATOR_ERODE) {
   184             u[i] = umin(u[i], aSourceData[sourceIndex + i]);
   185           } else {
   186             u[i] = umax(u[i], aSourceData[sourceIndex + i]);
   187           }
   188         }
   189       }
   191       int32_t destIndex = y * aDestStride + 4 * x;
   192       for (size_t i = 0; i < 4; i++) {
   193         aDestData[destIndex+i] = u[i];
   194       }
   195     }
   196   }
   197 }
   199 void
   200 FilterProcessing::ApplyMorphologyVertical_Scalar(uint8_t* aSourceData, int32_t aSourceStride,
   201                                                    uint8_t* aDestData, int32_t aDestStride,
   202                                                    const IntRect& aDestRect, int32_t aRadius,
   203                                                    MorphologyOperator aOp)
   204 {
   205   if (aOp == MORPHOLOGY_OPERATOR_ERODE) {
   206     gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_ERODE>(
   207       aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
   208   } else {
   209     gfx::ApplyMorphologyVertical_Scalar<MORPHOLOGY_OPERATOR_DILATE>(
   210       aSourceData, aSourceStride, aDestData, aDestStride, aDestRect, aRadius);
   211   }
   212 }
   214 TemporaryRef<DataSourceSurface>
   215 FilterProcessing::ApplyColorMatrix_Scalar(DataSourceSurface* aInput, const Matrix5x4 &aMatrix)
   216 {
   217   return ApplyColorMatrix_SIMD<simd::Scalari32x4_t,simd::Scalari16x8_t,simd::Scalaru8x16_t>(aInput, aMatrix);
   218 }
   220 void
   221 FilterProcessing::ApplyComposition_Scalar(DataSourceSurface* aSource, DataSourceSurface* aDest,
   222                                           CompositeOperator aOperator)
   223 {
   224   return ApplyComposition_SIMD<simd::Scalari32x4_t,simd::Scalaru16x8_t,simd::Scalaru8x16_t>(aSource, aDest, aOperator);
   225 }
   227 void
   228 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)
   229 {
   230   for (int32_t y = 0; y < size.height; y++) {
   231     for (int32_t x = 0; x < size.width; x++) {
   232       int32_t sourceIndex = y * sourceStride + 4 * x;
   233       int32_t targetIndex = y * channelStride + x;
   234       channel0Data[targetIndex] = sourceData[sourceIndex];
   235       channel1Data[targetIndex] = sourceData[sourceIndex+1];
   236       channel2Data[targetIndex] = sourceData[sourceIndex+2];
   237       channel3Data[targetIndex] = sourceData[sourceIndex+3];
   238     }
   239   }
   240 }
   242 void
   243 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)
   244 {
   245   for (int32_t y = 0; y < size.height; y++) {
   246     for (int32_t x = 0; x < size.width; x++) {
   247       int32_t resultIndex = y * resultStride + 4 * x;
   248       int32_t channelIndex = y * channelStride + x;
   249       resultData[resultIndex] = channel0Data[channelIndex];
   250       resultData[resultIndex+1] = channel1Data[channelIndex];
   251       resultData[resultIndex+2] = channel2Data[channelIndex];
   252       resultData[resultIndex+3] = channel3Data[channelIndex];
   253     }
   254   }
   255 }
   257 void
   258 FilterProcessing::DoPremultiplicationCalculation_Scalar(const IntSize& aSize,
   259                                      uint8_t* aTargetData, int32_t aTargetStride,
   260                                      uint8_t* aSourceData, int32_t aSourceStride)
   261 {
   262   for (int32_t y = 0; y < aSize.height; y++) {
   263     for (int32_t x = 0; x < aSize.width; x++) {
   264       int32_t inputIndex = y * aSourceStride + 4 * x;
   265       int32_t targetIndex = y * aTargetStride + 4 * x;
   266       uint8_t alpha = aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
   267       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
   268         FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alpha);
   269       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
   270         FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alpha);
   271       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
   272         FastDivideBy255<uint8_t>(aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alpha);
   273       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = alpha;
   274     }
   275   }
   276 }
   278 void
   279 FilterProcessing::DoUnpremultiplicationCalculation_Scalar(
   280                                  const IntSize& aSize,
   281                                  uint8_t* aTargetData, int32_t aTargetStride,
   282                                  uint8_t* aSourceData, int32_t aSourceStride)
   283 {
   284   for (int32_t y = 0; y < aSize.height; y++) {
   285     for (int32_t x = 0; x < aSize.width; x++) {
   286       int32_t inputIndex = y * aSourceStride + 4 * x;
   287       int32_t targetIndex = y * aTargetStride + 4 * x;
   288       uint8_t alpha = aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A];
   289       uint16_t alphaFactor = sAlphaFactors[alpha];
   290       // inputColor * alphaFactor + 128 is guaranteed to fit into uint16_t
   291       // because the input is premultiplied and thus inputColor <= inputAlpha.
   292       // The maximum value this can attain is 65520 (which is less than 65535)
   293       // for color == alpha == 244:
   294       // 244 * sAlphaFactors[244] + 128 == 244 * 268 + 128 == 65520
   295       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
   296         (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alphaFactor + 128) >> 8;
   297       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
   298         (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alphaFactor + 128) >> 8;
   299       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
   300         (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alphaFactor + 128) >> 8;
   301       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = alpha;
   302     }
   303   }
   304 }
   306 TemporaryRef<DataSourceSurface>
   307 FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
   308                                           int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
   309 {
   310    return RenderTurbulence_SIMD<simd::Scalarf32x4_t,simd::Scalari32x4_t,simd::Scalaru8x16_t>(
   311      aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect);
   312 }
   314 TemporaryRef<DataSourceSurface>
   315 FilterProcessing::ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4)
   316 {
   317   return ApplyArithmeticCombine_SIMD<simd::Scalari32x4_t,simd::Scalari16x8_t,simd::Scalaru8x16_t>(aInput1, aInput2, aK1, aK2, aK3, aK4);
   318 }
   320 } // namespace mozilla
   321 } // namespace gfx

mercurial