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 #include "FilterProcessing.h"
8 #include "Logging.h"
9 
10 namespace mozilla {
11 namespace gfx {
12 
ExtractAlpha(DataSourceSurface * aSource)13 already_AddRefed<DataSourceSurface> FilterProcessing::ExtractAlpha(
14     DataSourceSurface* aSource) {
15   IntSize size = aSource->GetSize();
16   RefPtr<DataSourceSurface> alpha =
17       Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
18   if (MOZ2D_WARN_IF(!alpha)) {
19     return nullptr;
20   }
21 
22   DataSourceSurface::ScopedMap sourceMap(aSource, DataSourceSurface::READ);
23   DataSourceSurface::ScopedMap alphaMap(alpha, DataSourceSurface::WRITE);
24   if (MOZ2D_WARN_IF(!sourceMap.IsMapped() || !alphaMap.IsMapped())) {
25     return nullptr;
26   }
27 
28   uint8_t* sourceData = sourceMap.GetData();
29   int32_t sourceStride = sourceMap.GetStride();
30   uint8_t* alphaData = alphaMap.GetData();
31   int32_t alphaStride = alphaMap.GetStride();
32 
33   if (Factory::HasSSE2()) {
34 #ifdef USE_SSE2
35     ExtractAlpha_SSE2(size, sourceData, sourceStride, alphaData, alphaStride);
36 #endif
37   } else {
38     ExtractAlpha_Scalar(size, sourceData, sourceStride, alphaData, alphaStride);
39   }
40 
41   return alpha.forget();
42 }
43 
ConvertToB8G8R8A8(SourceSurface * aSurface)44 already_AddRefed<DataSourceSurface> FilterProcessing::ConvertToB8G8R8A8(
45     SourceSurface* aSurface) {
46   if (Factory::HasSSE2()) {
47 #ifdef USE_SSE2
48     return ConvertToB8G8R8A8_SSE2(aSurface);
49 #endif
50   }
51   return ConvertToB8G8R8A8_Scalar(aSurface);
52 }
53 
ApplyBlending(DataSourceSurface * aInput1,DataSourceSurface * aInput2,BlendMode aBlendMode)54 already_AddRefed<DataSourceSurface> FilterProcessing::ApplyBlending(
55     DataSourceSurface* aInput1, DataSourceSurface* aInput2,
56     BlendMode aBlendMode) {
57   if (Factory::HasSSE2()) {
58 #ifdef USE_SSE2
59     return ApplyBlending_SSE2(aInput1, aInput2, aBlendMode);
60 #endif
61   }
62   return nullptr;
63 }
64 
ApplyMorphologyHorizontal(uint8_t * aSourceData,int32_t aSourceStride,uint8_t * aDestData,int32_t aDestStride,const IntRect & aDestRect,int32_t aRadius,MorphologyOperator aOp)65 void FilterProcessing::ApplyMorphologyHorizontal(
66     uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData,
67     int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius,
68     MorphologyOperator aOp) {
69   if (Factory::HasSSE2()) {
70 #ifdef USE_SSE2
71     ApplyMorphologyHorizontal_SSE2(aSourceData, aSourceStride, aDestData,
72                                    aDestStride, aDestRect, aRadius, aOp);
73 #endif
74   } else {
75     ApplyMorphologyHorizontal_Scalar(aSourceData, aSourceStride, aDestData,
76                                      aDestStride, aDestRect, aRadius, aOp);
77   }
78 }
79 
ApplyMorphologyVertical(uint8_t * aSourceData,int32_t aSourceStride,uint8_t * aDestData,int32_t aDestStride,const IntRect & aDestRect,int32_t aRadius,MorphologyOperator aOp)80 void FilterProcessing::ApplyMorphologyVertical(
81     uint8_t* aSourceData, int32_t aSourceStride, uint8_t* aDestData,
82     int32_t aDestStride, const IntRect& aDestRect, int32_t aRadius,
83     MorphologyOperator aOp) {
84   if (Factory::HasSSE2()) {
85 #ifdef USE_SSE2
86     ApplyMorphologyVertical_SSE2(aSourceData, aSourceStride, aDestData,
87                                  aDestStride, aDestRect, aRadius, aOp);
88 #endif
89   } else {
90     ApplyMorphologyVertical_Scalar(aSourceData, aSourceStride, aDestData,
91                                    aDestStride, aDestRect, aRadius, aOp);
92   }
93 }
94 
ApplyColorMatrix(DataSourceSurface * aInput,const Matrix5x4 & aMatrix)95 already_AddRefed<DataSourceSurface> FilterProcessing::ApplyColorMatrix(
96     DataSourceSurface* aInput, const Matrix5x4& aMatrix) {
97   if (Factory::HasSSE2()) {
98 #ifdef USE_SSE2
99     return ApplyColorMatrix_SSE2(aInput, aMatrix);
100 #endif
101   }
102   return ApplyColorMatrix_Scalar(aInput, aMatrix);
103 }
104 
ApplyComposition(DataSourceSurface * aSource,DataSourceSurface * aDest,CompositeOperator aOperator)105 void FilterProcessing::ApplyComposition(DataSourceSurface* aSource,
106                                         DataSourceSurface* aDest,
107                                         CompositeOperator aOperator) {
108   if (Factory::HasSSE2()) {
109 #ifdef USE_SSE2
110     ApplyComposition_SSE2(aSource, aDest, aOperator);
111 #endif
112   } else {
113     ApplyComposition_Scalar(aSource, aDest, aOperator);
114   }
115 }
116 
SeparateColorChannels(DataSourceSurface * aSource,RefPtr<DataSourceSurface> & aChannel0,RefPtr<DataSourceSurface> & aChannel1,RefPtr<DataSourceSurface> & aChannel2,RefPtr<DataSourceSurface> & aChannel3)117 void FilterProcessing::SeparateColorChannels(
118     DataSourceSurface* aSource, RefPtr<DataSourceSurface>& aChannel0,
119     RefPtr<DataSourceSurface>& aChannel1, RefPtr<DataSourceSurface>& aChannel2,
120     RefPtr<DataSourceSurface>& aChannel3) {
121   IntSize size = aSource->GetSize();
122   aChannel0 = Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
123   aChannel1 = Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
124   aChannel2 = Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
125   aChannel3 = Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
126   if (MOZ2D_WARN_IF(!(aChannel0 && aChannel1 && aChannel2 && aChannel3))) {
127     return;
128   }
129 
130   DataSourceSurface::ScopedMap sourceMap(aSource, DataSourceSurface::READ);
131   DataSourceSurface::ScopedMap channel0Map(aChannel0, DataSourceSurface::WRITE);
132   DataSourceSurface::ScopedMap channel1Map(aChannel1, DataSourceSurface::WRITE);
133   DataSourceSurface::ScopedMap channel2Map(aChannel2, DataSourceSurface::WRITE);
134   DataSourceSurface::ScopedMap channel3Map(aChannel3, DataSourceSurface::WRITE);
135   if (MOZ2D_WARN_IF(!(sourceMap.IsMapped() && channel0Map.IsMapped() &&
136                       channel1Map.IsMapped() && channel2Map.IsMapped() &&
137                       channel3Map.IsMapped()))) {
138     return;
139   }
140   uint8_t* sourceData = sourceMap.GetData();
141   int32_t sourceStride = sourceMap.GetStride();
142   uint8_t* channel0Data = channel0Map.GetData();
143   uint8_t* channel1Data = channel1Map.GetData();
144   uint8_t* channel2Data = channel2Map.GetData();
145   uint8_t* channel3Data = channel3Map.GetData();
146   int32_t channelStride = channel0Map.GetStride();
147 
148   if (Factory::HasSSE2()) {
149 #ifdef USE_SSE2
150     SeparateColorChannels_SSE2(size, sourceData, sourceStride, channel0Data,
151                                channel1Data, channel2Data, channel3Data,
152                                channelStride);
153 #endif
154   } else {
155     SeparateColorChannels_Scalar(size, sourceData, sourceStride, channel0Data,
156                                  channel1Data, channel2Data, channel3Data,
157                                  channelStride);
158   }
159 }
160 
CombineColorChannels(DataSourceSurface * aChannel0,DataSourceSurface * aChannel1,DataSourceSurface * aChannel2,DataSourceSurface * aChannel3)161 already_AddRefed<DataSourceSurface> FilterProcessing::CombineColorChannels(
162     DataSourceSurface* aChannel0, DataSourceSurface* aChannel1,
163     DataSourceSurface* aChannel2, DataSourceSurface* aChannel3) {
164   IntSize size = aChannel0->GetSize();
165   RefPtr<DataSourceSurface> result =
166       Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
167   if (MOZ2D_WARN_IF(!result)) {
168     return nullptr;
169   }
170   DataSourceSurface::ScopedMap resultMap(result, DataSourceSurface::WRITE);
171   DataSourceSurface::ScopedMap channel0Map(aChannel0, DataSourceSurface::READ);
172   DataSourceSurface::ScopedMap channel1Map(aChannel1, DataSourceSurface::READ);
173   DataSourceSurface::ScopedMap channel2Map(aChannel2, DataSourceSurface::READ);
174   DataSourceSurface::ScopedMap channel3Map(aChannel3, DataSourceSurface::READ);
175   if (MOZ2D_WARN_IF(!(resultMap.IsMapped() && channel0Map.IsMapped() &&
176                       channel1Map.IsMapped() && channel2Map.IsMapped() &&
177                       channel3Map.IsMapped()))) {
178     return nullptr;
179   }
180   int32_t resultStride = resultMap.GetStride();
181   uint8_t* resultData = resultMap.GetData();
182   int32_t channelStride = channel0Map.GetStride();
183   uint8_t* channel0Data = channel0Map.GetData();
184   uint8_t* channel1Data = channel1Map.GetData();
185   uint8_t* channel2Data = channel2Map.GetData();
186   uint8_t* channel3Data = channel3Map.GetData();
187 
188   if (Factory::HasSSE2()) {
189 #ifdef USE_SSE2
190     CombineColorChannels_SSE2(size, resultStride, resultData, channelStride,
191                               channel0Data, channel1Data, channel2Data,
192                               channel3Data);
193 #endif
194   } else {
195     CombineColorChannels_Scalar(size, resultStride, resultData, channelStride,
196                                 channel0Data, channel1Data, channel2Data,
197                                 channel3Data);
198   }
199 
200   return result.forget();
201 }
202 
DoPremultiplicationCalculation(const IntSize & aSize,uint8_t * aTargetData,int32_t aTargetStride,uint8_t * aSourceData,int32_t aSourceStride)203 void FilterProcessing::DoPremultiplicationCalculation(const IntSize& aSize,
204                                                       uint8_t* aTargetData,
205                                                       int32_t aTargetStride,
206                                                       uint8_t* aSourceData,
207                                                       int32_t aSourceStride) {
208   if (Factory::HasSSE2()) {
209 #ifdef USE_SSE2
210     DoPremultiplicationCalculation_SSE2(aSize, aTargetData, aTargetStride,
211                                         aSourceData, aSourceStride);
212 #endif
213   } else {
214     DoPremultiplicationCalculation_Scalar(aSize, aTargetData, aTargetStride,
215                                           aSourceData, aSourceStride);
216   }
217 }
218 
DoUnpremultiplicationCalculation(const IntSize & aSize,uint8_t * aTargetData,int32_t aTargetStride,uint8_t * aSourceData,int32_t aSourceStride)219 void FilterProcessing::DoUnpremultiplicationCalculation(const IntSize& aSize,
220                                                         uint8_t* aTargetData,
221                                                         int32_t aTargetStride,
222                                                         uint8_t* aSourceData,
223                                                         int32_t aSourceStride) {
224   if (Factory::HasSSE2()) {
225 #ifdef USE_SSE2
226     DoUnpremultiplicationCalculation_SSE2(aSize, aTargetData, aTargetStride,
227                                           aSourceData, aSourceStride);
228 #endif
229   } else {
230     DoUnpremultiplicationCalculation_Scalar(aSize, aTargetData, aTargetStride,
231                                             aSourceData, aSourceStride);
232   }
233 }
234 
DoOpacityCalculation(const IntSize & aSize,uint8_t * aTargetData,int32_t aTargetStride,uint8_t * aSourceData,int32_t aSourceStride,Float aValue)235 void FilterProcessing::DoOpacityCalculation(
236     const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride,
237     uint8_t* aSourceData, int32_t aSourceStride, Float aValue) {
238   if (Factory::HasSSE2()) {
239 #ifdef USE_SSE2
240     DoOpacityCalculation_SSE2(aSize, aTargetData, aTargetStride, aSourceData,
241                               aSourceStride, aValue);
242 #endif
243   } else {
244     DoOpacityCalculation_Scalar(aSize, aTargetData, aTargetStride, aSourceData,
245                                 aSourceStride, aValue);
246   }
247 }
248 
DoOpacityCalculationA8(const IntSize & aSize,uint8_t * aTargetData,int32_t aTargetStride,uint8_t * aSourceData,int32_t aSourceStride,Float aValue)249 void FilterProcessing::DoOpacityCalculationA8(
250     const IntSize& aSize, uint8_t* aTargetData, int32_t aTargetStride,
251     uint8_t* aSourceData, int32_t aSourceStride, Float aValue) {
252   DoOpacityCalculationA8_Scalar(aSize, aTargetData, aTargetStride, aSourceData,
253                                 aSourceStride, aValue);
254 }
255 
RenderTurbulence(const IntSize & aSize,const Point & aOffset,const Size & aBaseFrequency,int32_t aSeed,int aNumOctaves,TurbulenceType aType,bool aStitch,const Rect & aTileRect)256 already_AddRefed<DataSourceSurface> FilterProcessing::RenderTurbulence(
257     const IntSize& aSize, const Point& aOffset, const Size& aBaseFrequency,
258     int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch,
259     const Rect& aTileRect) {
260   if (Factory::HasSSE2()) {
261 #ifdef USE_SSE2
262     return RenderTurbulence_SSE2(aSize, aOffset, aBaseFrequency, aSeed,
263                                  aNumOctaves, aType, aStitch, aTileRect);
264 #endif
265   }
266   return RenderTurbulence_Scalar(aSize, aOffset, aBaseFrequency, aSeed,
267                                  aNumOctaves, aType, aStitch, aTileRect);
268 }
269 
ApplyArithmeticCombine(DataSourceSurface * aInput1,DataSourceSurface * aInput2,Float aK1,Float aK2,Float aK3,Float aK4)270 already_AddRefed<DataSourceSurface> FilterProcessing::ApplyArithmeticCombine(
271     DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1,
272     Float aK2, Float aK3, Float aK4) {
273   if (Factory::HasSSE2()) {
274 #ifdef USE_SSE2
275     return ApplyArithmeticCombine_SSE2(aInput1, aInput2, aK1, aK2, aK3, aK4);
276 #endif
277   }
278   return ApplyArithmeticCombine_Scalar(aInput1, aInput2, aK1, aK2, aK3, aK4);
279 }
280 
281 }  // namespace gfx
282 }  // namespace mozilla
283