Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / 2d / FilterProcessing.cpp
blob4f26cd624959f893b39ed02b19358020f9099e4d
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/. */
7 #include "FilterProcessing.h"
8 #include "Logging.h"
10 namespace mozilla {
11 namespace gfx {
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;
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;
28 uint8_t* sourceData = sourceMap.GetData();
29 int32_t sourceStride = sourceMap.GetStride();
30 uint8_t* alphaData = alphaMap.GetData();
31 int32_t alphaStride = alphaMap.GetStride();
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);
41 return alpha.forget();
44 already_AddRefed<DataSourceSurface> FilterProcessing::ConvertToB8G8R8A8(
45 SourceSurface* aSurface) {
46 if (Factory::HasSSE2()) {
47 #ifdef USE_SSE2
48 return ConvertToB8G8R8A8_SSE2(aSurface);
49 #endif
51 return ConvertToB8G8R8A8_Scalar(aSurface);
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
62 return nullptr;
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);
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);
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
102 return ApplyColorMatrix_Scalar(aInput, aMatrix);
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);
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;
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;
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();
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);
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;
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;
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();
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);
200 return result.forget();
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);
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);
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);
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);
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
266 return RenderTurbulence_Scalar(aSize, aOffset, aBaseFrequency, aSeed,
267 aNumOctaves, aType, aStitch, aTileRect);
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
278 return ApplyArithmeticCombine_Scalar(aInput1, aInput2, aK1, aK2, aK3, aK4);
281 } // namespace gfx
282 } // namespace mozilla