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/. */
8 #include "LuminanceNEON.h"
10 using namespace mozilla::gfx
;
13 * Byte offsets of channels in a native packed gfxColor or cairo image surface.
16 # define GFX_ARGB32_OFFSET_A 0
17 # define GFX_ARGB32_OFFSET_R 1
18 # define GFX_ARGB32_OFFSET_G 2
19 # define GFX_ARGB32_OFFSET_B 3
21 # define GFX_ARGB32_OFFSET_A 3
22 # define GFX_ARGB32_OFFSET_R 2
23 # define GFX_ARGB32_OFFSET_G 1
24 # define GFX_ARGB32_OFFSET_B 0
27 void ComputesRGBLuminanceMask_NEON(const uint8_t* aSourceData
,
28 int32_t aSourceStride
, uint8_t* aDestData
,
29 int32_t aDestStride
, const IntSize
& aSize
,
31 int32_t redFactor
= 55 * aOpacity
; // 255 * 0.2125 * opacity
32 int32_t greenFactor
= 183 * aOpacity
; // 255 * 0.7154 * opacity
33 int32_t blueFactor
= 18 * aOpacity
; // 255 * 0.0721
34 const uint8_t* sourcePixel
= aSourceData
;
35 int32_t sourceOffset
= aSourceStride
- 4 * aSize
.width
;
36 uint8_t* destPixel
= aDestData
;
37 int32_t destOffset
= aDestStride
- aSize
.width
;
39 sourcePixel
= aSourceData
;
40 int32_t remainderWidth
= aSize
.width
% 8;
41 int32_t roundedWidth
= aSize
.width
- remainderWidth
;
44 uint8x8_t redVector
= vdup_n_u8(redFactor
);
45 uint8x8_t greenVector
= vdup_n_u8(greenFactor
);
46 uint8x8_t blueVector
= vdup_n_u8(blueFactor
);
47 uint8x8_t fullBitVector
= vdup_n_u8(255);
48 uint8x8_t oneVector
= vdup_n_u8(1);
49 for (int32_t y
= 0; y
< aSize
.height
; y
++) {
50 // Calculate luminance by neon with 8 pixels per loop
51 for (int32_t x
= 0; x
< roundedWidth
; x
+= 8) {
52 uint8x8x4_t argb
= vld4_u8(sourcePixel
);
53 temp
= vmull_u8(argb
.val
[GFX_ARGB32_OFFSET_R
],
54 redVector
); // temp = red * redFactor
55 temp
= vmlal_u8(temp
, argb
.val
[GFX_ARGB32_OFFSET_G
],
56 greenVector
); // temp += green * greenFactor
57 temp
= vmlal_u8(temp
, argb
.val
[GFX_ARGB32_OFFSET_B
],
58 blueVector
); // temp += blue * blueFactor
59 gray
= vshrn_n_u16(temp
, 8); // gray = temp >> 8
62 uint8x8_t alphaVector
=
63 vtst_u8(argb
.val
[GFX_ARGB32_OFFSET_A
], fullBitVector
);
64 gray
= vmul_u8(gray
, vand_u8(alphaVector
, oneVector
));
66 // Put the result to the 8 pixels
67 vst1_u8(destPixel
, gray
);
72 // Calculate the rest pixels of the line by cpu
73 for (int32_t x
= 0; x
< remainderWidth
; x
++) {
74 if (sourcePixel
[GFX_ARGB32_OFFSET_A
] > 0) {
75 *destPixel
= (redFactor
* sourcePixel
[GFX_ARGB32_OFFSET_R
] +
76 greenFactor
* sourcePixel
[GFX_ARGB32_OFFSET_G
] +
77 blueFactor
* sourcePixel
[GFX_ARGB32_OFFSET_B
]) >>
85 sourcePixel
+= sourceOffset
;
86 destPixel
+= destOffset
;