• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkColorPriv_DEFINED
9 #define SkColorPriv_DEFINED
10 
11 // turn this own for extra debug checking when blending onto 565
12 #ifdef SK_DEBUG
13     #define CHECK_FOR_565_OVERFLOW
14 #endif
15 
16 #include "SkColor.h"
17 #include "SkMath.h"
18 
19 //////////////////////////////////////////////////////////////////////////////
20 
21 #define SkASSERT_IS_BYTE(x)     SkASSERT(0 == ((x) & ~0xFF))
22 
23 /*
24  *  Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
25  *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
26  *
27  *  For easier compatibility with Skia's GPU backend, we further restrict these
28  *  to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
29  *  not directly correspond to the same shift-order, since we have to take endianess
30  *  into account.
31  *
32  *  Here we enforce this constraint.
33  */
34 
35 #ifdef SK_CPU_BENDIAN
36     #define SK_RGBA_R32_SHIFT   24
37     #define SK_RGBA_G32_SHIFT   16
38     #define SK_RGBA_B32_SHIFT   8
39     #define SK_RGBA_A32_SHIFT   0
40 
41     #define SK_BGRA_B32_SHIFT   24
42     #define SK_BGRA_G32_SHIFT   16
43     #define SK_BGRA_R32_SHIFT   8
44     #define SK_BGRA_A32_SHIFT   0
45 #else
46     #define SK_RGBA_R32_SHIFT   0
47     #define SK_RGBA_G32_SHIFT   8
48     #define SK_RGBA_B32_SHIFT   16
49     #define SK_RGBA_A32_SHIFT   24
50 
51     #define SK_BGRA_B32_SHIFT   0
52     #define SK_BGRA_G32_SHIFT   8
53     #define SK_BGRA_R32_SHIFT   16
54     #define SK_BGRA_A32_SHIFT   24
55 #endif
56 
57 #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
58     #error "can't define PMCOLOR to be RGBA and BGRA"
59 #endif
60 
61 #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA  \
62     (SK_A32_SHIFT == SK_RGBA_A32_SHIFT &&    \
63      SK_R32_SHIFT == SK_RGBA_R32_SHIFT &&    \
64      SK_G32_SHIFT == SK_RGBA_G32_SHIFT &&    \
65      SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
66 
67 #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA  \
68     (SK_A32_SHIFT == SK_BGRA_A32_SHIFT &&    \
69      SK_R32_SHIFT == SK_BGRA_R32_SHIFT &&    \
70      SK_G32_SHIFT == SK_BGRA_G32_SHIFT &&    \
71      SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
72 
73 
74 #define SK_A_INDEX  (SK_A32_SHIFT/8)
75 #define SK_R_INDEX  (SK_R32_SHIFT/8)
76 #define SK_G_INDEX  (SK_G32_SHIFT/8)
77 #define SK_B_INDEX  (SK_B32_SHIFT/8)
78 
79 #if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
80     #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values"
81 #endif
82 
83 #if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
84     #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values"
85 #endif
86 
87 #if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_BGRA)
88     // deduce which to define from the _SHIFT defines
89 
90     #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
91         #define SK_PMCOLOR_IS_RGBA
92     #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
93         #define SK_PMCOLOR_IS_BGRA
94     #else
95         #error "need 32bit packing to be either RGBA or BGRA"
96     #endif
97 #endif
98 
99 // hide these now that we're done
100 #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
101 #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
102 
103 //////////////////////////////////////////////////////////////////////////////
104 
105 // Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the
106 // pair of them are in the same 2 slots in both RGBA and BGRA, thus there is
107 // no need to pass in the colortype to this function.
SkSwizzle_RB(uint32_t c)108 static inline uint32_t SkSwizzle_RB(uint32_t c) {
109     static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT);
110 
111     unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF;
112     unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF;
113     return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT);
114 }
115 
SkPackARGB_as_RGBA(U8CPU a,U8CPU r,U8CPU g,U8CPU b)116 static inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
117     SkASSERT_IS_BYTE(a);
118     SkASSERT_IS_BYTE(r);
119     SkASSERT_IS_BYTE(g);
120     SkASSERT_IS_BYTE(b);
121     return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) |
122            (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT);
123 }
124 
SkPackARGB_as_BGRA(U8CPU a,U8CPU r,U8CPU g,U8CPU b)125 static inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
126     SkASSERT_IS_BYTE(a);
127     SkASSERT_IS_BYTE(r);
128     SkASSERT_IS_BYTE(g);
129     SkASSERT_IS_BYTE(b);
130     return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) |
131            (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT);
132 }
133 
SkSwizzle_RGBA_to_PMColor(uint32_t c)134 static inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) {
135 #ifdef SK_PMCOLOR_IS_RGBA
136     return c;
137 #else
138     return SkSwizzle_RB(c);
139 #endif
140 }
141 
SkSwizzle_BGRA_to_PMColor(uint32_t c)142 static inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) {
143 #ifdef SK_PMCOLOR_IS_BGRA
144     return c;
145 #else
146     return SkSwizzle_RB(c);
147 #endif
148 }
149 
150 //////////////////////////////////////////////////////////////////////////////
151 
152 ///@{
153 /** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/
154 #define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
155 #define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
156 #define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
157 ///@}
158 
159 ///@{
160 /** A float value which specifies this channel's contribution to luminance. */
161 #define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
162 #define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
163 #define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
164 ///@}
165 
166 /** Computes the luminance from the given r, g, and b in accordance with
167     SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space.
168 */
SkComputeLuminance(U8CPU r,U8CPU g,U8CPU b)169 static inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
170     //The following is
171     //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
172     //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
173     return (r * 54 + g * 183 + b * 19) >> 8;
174 }
175 
176 /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
177     byte into a scale value, so that we can say scale * value >> 8 instead of
178     alpha * value / 255.
179 
180     In debugging, asserts that alpha is 0..255
181 */
SkAlpha255To256(U8CPU alpha)182 static inline unsigned SkAlpha255To256(U8CPU alpha) {
183     SkASSERT(SkToU8(alpha) == alpha);
184     // this one assues that blending on top of an opaque dst keeps it that way
185     // even though it is less accurate than a+(a>>7) for non-opaque dsts
186     return alpha + 1;
187 }
188 
189 /**
190  *  Turn a 0..255 value into a 0..256 value, rounding up if the value is >= 0x80.
191  *  This is slightly more accurate than SkAlpha255To256.
192  */
Sk255To256(U8CPU value)193 static inline unsigned Sk255To256(U8CPU value) {
194     SkASSERT(SkToU8(value) == value);
195     return value + (value >> 7);
196 }
197 
198 /** Multiplify value by 0..256, and shift the result down 8
199     (i.e. return (value * alpha256) >> 8)
200  */
201 #define SkAlphaMul(value, alpha256)     (((value) * (alpha256)) >> 8)
202 
203 /** Calculates 256 - (value * alpha256) / 255 in range [0,256],
204  *  for [0,255] value and [0,256] alpha256.
205  */
SkAlphaMulInv256(U16CPU value,U16CPU alpha256)206 static inline U16CPU SkAlphaMulInv256(U16CPU value, U16CPU alpha256) {
207     unsigned prod = 0xFFFF - value * alpha256;
208     return (prod + (prod >> 8)) >> 8;
209 }
210 
211 //  The caller may want negative values, so keep all params signed (int)
212 //  so we don't accidentally slip into unsigned math and lose the sign
213 //  extension when we shift (in SkAlphaMul)
SkAlphaBlend(int src,int dst,int scale256)214 static inline int SkAlphaBlend(int src, int dst, int scale256) {
215     SkASSERT((unsigned)scale256 <= 256);
216     return dst + SkAlphaMul(src - dst, scale256);
217 }
218 
219 /**
220  *  Returns (src * alpha + dst * (255 - alpha)) / 255
221  *
222  *  This is more accurate than SkAlphaBlend, but slightly slower
223  */
SkAlphaBlend255(S16CPU src,S16CPU dst,U8CPU alpha)224 static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
225     SkASSERT((int16_t)src == src);
226     SkASSERT((int16_t)dst == dst);
227     SkASSERT((uint8_t)alpha == alpha);
228 
229     int prod = (src - dst) * alpha + 128;
230     prod = (prod + (prod >> 8)) >> 8;
231     return dst + prod;
232 }
233 
SkUnitScalarClampToByte(SkScalar x)234 static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
235     return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);
236 }
237 
238 #define SK_R16_BITS     5
239 #define SK_G16_BITS     6
240 #define SK_B16_BITS     5
241 
242 #define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
243 #define SK_G16_SHIFT    (SK_B16_BITS)
244 #define SK_B16_SHIFT    0
245 
246 #define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
247 #define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
248 #define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
249 
250 #define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
251 #define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
252 #define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
253 
254 #define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
255 #define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
256 #define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
257 
SkPackRGB16(unsigned r,unsigned g,unsigned b)258 static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
259     SkASSERT(r <= SK_R16_MASK);
260     SkASSERT(g <= SK_G16_MASK);
261     SkASSERT(b <= SK_B16_MASK);
262 
263     return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
264 }
265 
266 #define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
267 #define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
268 #define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
269 
270 /** Expand the 16bit color into a 32bit value that can be scaled all at once
271     by a value up to 32. Used in conjunction with SkCompact_rgb_16.
272 */
SkExpand_rgb_16(U16CPU c)273 static inline uint32_t SkExpand_rgb_16(U16CPU c) {
274     SkASSERT(c == (uint16_t)c);
275 
276     return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
277 }
278 
279 /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
280     color value. The computation yields only 16bits of valid data, but we claim
281     to return 32bits, so that the compiler won't generate extra instructions to
282     "clean" the top 16bits. However, the top 16 can contain garbage, so it is
283     up to the caller to safely ignore them.
284 */
SkCompact_rgb_16(uint32_t c)285 static inline U16CPU SkCompact_rgb_16(uint32_t c) {
286     return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
287 }
288 
289 /** Scale the 16bit color value by the 0..256 scale parameter.
290     The computation yields only 16bits of valid data, but we claim
291     to return 32bits, so that the compiler won't generate extra instructions to
292     "clean" the top 16bits.
293 */
SkAlphaMulRGB16(U16CPU c,unsigned scale)294 static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
295     return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
296 }
297 
298 // this helper explicitly returns a clean 16bit value (but slower)
299 #define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
300 
301 /** Blend pre-expanded RGB32 with 16bit color value by the 0..32 scale parameter.
302     The computation yields only 16bits of valid data, but we claim to return
303     32bits, so that the compiler won't generate extra instructions to "clean"
304     the top 16bits.
305 */
SkBlend32_RGB16(uint32_t src_expand,uint16_t dst,unsigned scale)306 static inline U16CPU SkBlend32_RGB16(uint32_t src_expand, uint16_t dst, unsigned scale) {
307     uint32_t dst_expand = SkExpand_rgb_16(dst) * scale;
308     return SkCompact_rgb_16((src_expand + dst_expand) >> 5);
309 }
310 
311 /** Blend src and dst 16bit colors by the 0..256 scale parameter.
312     The computation yields only 16bits of valid data, but we claim
313     to return 32bits, so that the compiler won't generate extra instructions to
314     "clean" the top 16bits.
315 */
SkBlendRGB16(U16CPU src,U16CPU dst,int srcScale)316 static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
317     SkASSERT((unsigned)srcScale <= 256);
318 
319     srcScale >>= 3;
320 
321     uint32_t src32 = SkExpand_rgb_16(src);
322     uint32_t dst32 = SkExpand_rgb_16(dst);
323     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
324 }
325 
SkBlendRGB16(const uint16_t src[],uint16_t dst[],int srcScale,int count)326 static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
327                                 int srcScale, int count) {
328     SkASSERT(count > 0);
329     SkASSERT((unsigned)srcScale <= 256);
330 
331     srcScale >>= 3;
332 
333     do {
334         uint32_t src32 = SkExpand_rgb_16(*src++);
335         uint32_t dst32 = SkExpand_rgb_16(*dst);
336         *dst++ = static_cast<uint16_t>(
337             SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)));
338     } while (--count > 0);
339 }
340 
341 #ifdef SK_DEBUG
SkRGB16Add(U16CPU a,U16CPU b)342     static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
343         SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
344         SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
345         SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
346 
347         return a + b;
348     }
349 #else
350     #define SkRGB16Add(a, b)  ((a) + (b))
351 #endif
352 
353 ///////////////////////////////////////////////////////////////////////////////
354 
355 #define SK_A32_BITS     8
356 #define SK_R32_BITS     8
357 #define SK_G32_BITS     8
358 #define SK_B32_BITS     8
359 
360 #define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
361 #define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
362 #define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
363 #define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
364 
365 #define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
366 #define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
367 #define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
368 #define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
369 
370 #define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
371 #define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
372 #define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
373 #define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
374 
375 #ifdef SK_DEBUG
376     #define SkPMColorAssert(color_value)                                    \
377         do {                                                                \
378             SkPMColor pm_color_value = (color_value);                       \
379             uint32_t alpha_color_value = SkGetPackedA32(pm_color_value);    \
380             SkA32Assert(alpha_color_value);                                 \
381             SkASSERT(SkGetPackedR32(pm_color_value) <= alpha_color_value);  \
382             SkASSERT(SkGetPackedG32(pm_color_value) <= alpha_color_value);  \
383             SkASSERT(SkGetPackedB32(pm_color_value) <= alpha_color_value);  \
384         } while (false)
385 #else
386     #define SkPMColorAssert(c)
387 #endif
388 
SkPMColorValid(SkPMColor c)389 static inline bool SkPMColorValid(SkPMColor c) {
390     auto a = SkGetPackedA32(c);
391     bool valid = a <= SK_A32_MASK
392               && SkGetPackedR32(c) <= a
393               && SkGetPackedG32(c) <= a
394               && SkGetPackedB32(c) <= a;
395     if (valid) {
396         SkPMColorAssert(c);  // Make sure we're consistent when it counts.
397     }
398     return valid;
399 }
400 
401 /**
402  *  Pack the components into a SkPMColor, checking (in the debug version) that
403  *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
404  */
SkPackARGB32(U8CPU a,U8CPU r,U8CPU g,U8CPU b)405 static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
406     SkA32Assert(a);
407     SkASSERT(r <= a);
408     SkASSERT(g <= a);
409     SkASSERT(b <= a);
410 
411     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
412            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
413 }
414 
SkPackPMColor_as_RGBA(SkPMColor c)415 static inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) {
416     return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c),
417                               SkGetPackedG32(c), SkGetPackedB32(c));
418 }
419 
SkPackPMColor_as_BGRA(SkPMColor c)420 static inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) {
421     return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c),
422                               SkGetPackedG32(c), SkGetPackedB32(c));
423 }
424 
425 /**
426  * Abstract 4-byte interpolation, implemented on top of SkPMColor
427  * utility functions. Third parameter controls blending of the first two:
428  *   (src, dst, 0) returns dst
429  *   (src, dst, 0xFF) returns src
430  *   srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255]
431  */
SkFourByteInterp256(SkPMColor src,SkPMColor dst,unsigned scale)432 static inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
433                                          unsigned scale) {
434     unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
435     unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
436     unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
437     unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
438 
439     return SkPackARGB32(a, r, g, b);
440 }
441 
442 /**
443  * Abstract 4-byte interpolation, implemented on top of SkPMColor
444  * utility functions. Third parameter controls blending of the first two:
445  *   (src, dst, 0) returns dst
446  *   (src, dst, 0xFF) returns src
447  */
SkFourByteInterp(SkPMColor src,SkPMColor dst,U8CPU srcWeight)448 static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
449                                          U8CPU srcWeight) {
450     unsigned scale = SkAlpha255To256(srcWeight);
451     return SkFourByteInterp256(src, dst, scale);
452 }
453 
454 /**
455  * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB
456  */
SkSplay(uint32_t color,uint32_t * ag,uint32_t * rb)457 static inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) {
458     const uint32_t mask = 0x00FF00FF;
459     *ag = (color >> 8) & mask;
460     *rb = color & mask;
461 }
462 
463 /**
464  * 0xAARRGGBB -> 0x00AA00GG00RR00BB
465  * (note, ARGB -> AGRB)
466  */
SkSplay(uint32_t color)467 static inline uint64_t SkSplay(uint32_t color) {
468     const uint32_t mask = 0x00FF00FF;
469     uint64_t agrb = (color >> 8) & mask;  // 0x0000000000AA00GG
470     agrb <<= 32;                          // 0x00AA00GG00000000
471     agrb |= color & mask;                 // 0x00AA00GG00RR00BB
472     return agrb;
473 }
474 
475 /**
476  * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB
477  */
SkUnsplay(uint32_t ag,uint32_t rb)478 static inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) {
479     const uint32_t mask = 0xFF00FF00;
480     return (ag & mask) | ((rb & mask) >> 8);
481 }
482 
483 /**
484  * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB
485  * (note, AGRB -> ARGB)
486  */
SkUnsplay(uint64_t agrb)487 static inline uint32_t SkUnsplay(uint64_t agrb) {
488     const uint32_t mask = 0xFF00FF00;
489     return SkPMColor(
490         ((agrb & mask) >> 8) |   // 0x00RR00BB
491         ((agrb >> 32) & mask));  // 0xAARRGGBB
492 }
493 
SkFastFourByteInterp256_32(SkPMColor src,SkPMColor dst,unsigned scale)494 static inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) {
495     SkASSERT(scale <= 256);
496 
497     // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide.
498     uint32_t src_ag, src_rb, dst_ag, dst_rb;
499     SkSplay(src, &src_ag, &src_rb);
500     SkSplay(dst, &dst_ag, &dst_rb);
501 
502     const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
503     const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
504 
505     return SkUnsplay(ret_ag, ret_rb);
506 }
507 
SkFastFourByteInterp256_64(SkPMColor src,SkPMColor dst,unsigned scale)508 static inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) {
509     SkASSERT(scale <= 256);
510     // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide.
511     return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst));
512 }
513 
514 // TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere.
515 
516 /**
517  * Same as SkFourByteInterp256, but faster.
518  */
SkFastFourByteInterp256(SkPMColor src,SkPMColor dst,unsigned scale)519 static inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) {
520     // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine.
521     if (sizeof(void*) == 4) {
522         return SkFastFourByteInterp256_32(src, dst, scale);
523     } else {
524         return SkFastFourByteInterp256_64(src, dst, scale);
525     }
526 }
527 
528 /**
529  * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better
530  * srcWeight scaling to [0, 256].
531  */
SkFastFourByteInterp(SkPMColor src,SkPMColor dst,U8CPU srcWeight)532 static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
533                                              SkPMColor dst,
534                                              U8CPU srcWeight) {
535     SkASSERT(srcWeight <= 255);
536     // scale = srcWeight + (srcWeight >> 7) is more accurate than
537     // scale = srcWeight + 1, but 7% slower
538     return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
539 }
540 
541 /**
542  *  Same as SkPackARGB32, but this version guarantees to not check that the
543  *  values are premultiplied in the debug version.
544  */
SkPackARGB32NoCheck(U8CPU a,U8CPU r,U8CPU g,U8CPU b)545 static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
546     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
547            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
548 }
549 
550 static inline
SkPremultiplyARGBInline(U8CPU a,U8CPU r,U8CPU g,U8CPU b)551 SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
552     SkA32Assert(a);
553     SkR32Assert(r);
554     SkG32Assert(g);
555     SkB32Assert(b);
556 
557     if (a != 255) {
558         r = SkMulDiv255Round(r, a);
559         g = SkMulDiv255Round(g, a);
560         b = SkMulDiv255Round(b, a);
561     }
562     return SkPackARGB32(a, r, g, b);
563 }
564 
565 // When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
566 // inlined; forcing inlining significantly improves performance.
SkAlphaMulQ(uint32_t c,unsigned scale)567 static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
568     uint32_t mask = 0xFF00FF;
569 
570     uint32_t rb = ((c & mask) * scale) >> 8;
571     uint32_t ag = ((c >> 8) & mask) * scale;
572     return (rb & mask) | (ag & ~mask);
573 }
574 
SkPMSrcOver(SkPMColor src,SkPMColor dst)575 static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
576     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
577 }
578 
579 /**
580  * Interpolates between colors src and dst using [0,256] scale.
581  */
SkPMLerp(SkPMColor src,SkPMColor dst,unsigned scale)582 static inline SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale) {
583     return SkFastFourByteInterp256(src, dst, scale);
584 }
585 
SkBlendARGB32(SkPMColor src,SkPMColor dst,U8CPU aa)586 static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
587     SkASSERT((unsigned)aa <= 255);
588 
589     unsigned src_scale = SkAlpha255To256(aa);
590     unsigned dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), src_scale);
591 
592     const uint32_t mask = 0xFF00FF;
593 
594     uint32_t src_rb = (src & mask) * src_scale;
595     uint32_t src_ag = ((src >> 8) & mask) * src_scale;
596 
597     uint32_t dst_rb = (dst & mask) * dst_scale;
598     uint32_t dst_ag = ((dst >> 8) & mask) * dst_scale;
599 
600     return (((src_rb + dst_rb) >> 8) & mask) | ((src_ag + dst_ag) & ~mask);
601 }
602 
603 ////////////////////////////////////////////////////////////////////////////////////////////
604 // Convert a 32bit pixel to a 16bit pixel (no dither)
605 
606 #define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
607 #define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
608 #define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
609 
610 #ifdef SK_DEBUG
SkR32ToR16(unsigned r)611     static inline unsigned SkR32ToR16(unsigned r) {
612         SkR32Assert(r);
613         return SkR32ToR16_MACRO(r);
614     }
SkG32ToG16(unsigned g)615     static inline unsigned SkG32ToG16(unsigned g) {
616         SkG32Assert(g);
617         return SkG32ToG16_MACRO(g);
618     }
SkB32ToB16(unsigned b)619     static inline unsigned SkB32ToB16(unsigned b) {
620         SkB32Assert(b);
621         return SkB32ToB16_MACRO(b);
622     }
623 #else
624     #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
625     #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
626     #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
627 #endif
628 
629 #define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
630 #define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
631 #define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
632 
SkPixel32ToPixel16(SkPMColor c)633 static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
634     unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
635     unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
636     unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
637     return r | g | b;
638 }
639 
SkPack888ToRGB16(U8CPU r,U8CPU g,U8CPU b)640 static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
641     return  (SkR32ToR16(r) << SK_R16_SHIFT) |
642             (SkG32ToG16(g) << SK_G16_SHIFT) |
643             (SkB32ToB16(b) << SK_B16_SHIFT);
644 }
645 
646 #define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
647 
648 /////////////////////////////////////////////////////////////////////////////////////////
649 // Fast dither from 32->16
650 
651 #define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
652 
SkDitherPack888ToRGB16(U8CPU r,U8CPU g,U8CPU b)653 static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
654     r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
655     g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
656     b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
657 
658     return SkPackRGB16(r, g, b);
659 }
660 
SkDitherPixel32ToPixel16(SkPMColor c)661 static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
662     return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
663 }
664 
665 /*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
666     It is now suitable for combining with a scaled expanded_rgb_16 color
667     as in SkSrcOver32To16().
668     We must do this 565 high-bit replication, in order for the subsequent add
669     to saturate properly (and not overflow). If we take the 8 bits as is, it is
670     possible to overflow.
671 */
SkPMColorToExpanded16x5(SkPMColor c)672 static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
673     unsigned sr = SkPacked32ToR16(c);
674     unsigned sg = SkPacked32ToG16(c);
675     unsigned sb = SkPacked32ToB16(c);
676 
677     sr = (sr << 5) | sr;
678     sg = (sg << 5) | (sg >> 1);
679     sb = (sb << 5) | sb;
680     return (sr << 11) | (sg << 21) | (sb << 0);
681 }
682 
683 /*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
684     (with dirt in the high 16bits, so caller beware).
685 */
SkSrcOver32To16(SkPMColor src,uint16_t dst)686 static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
687     unsigned sr = SkGetPackedR32(src);
688     unsigned sg = SkGetPackedG32(src);
689     unsigned sb = SkGetPackedB32(src);
690 
691     unsigned dr = SkGetPackedR16(dst);
692     unsigned dg = SkGetPackedG16(dst);
693     unsigned db = SkGetPackedB16(dst);
694 
695     unsigned isa = 255 - SkGetPackedA32(src);
696 
697     dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
698     dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
699     db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
700 
701     return SkPackRGB16(dr, dg, db);
702 }
703 
704 ////////////////////////////////////////////////////////////////////////////////////////////
705 // Convert a 16bit pixel to a 32bit pixel
706 
SkR16ToR32(unsigned r)707 static inline unsigned SkR16ToR32(unsigned r) {
708     return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
709 }
710 
SkG16ToG32(unsigned g)711 static inline unsigned SkG16ToG32(unsigned g) {
712     return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
713 }
714 
SkB16ToB32(unsigned b)715 static inline unsigned SkB16ToB32(unsigned b) {
716     return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
717 }
718 
719 #define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
720 #define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
721 #define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
722 
SkPixel16ToPixel32(U16CPU src)723 static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
724     SkASSERT(src == SkToU16(src));
725 
726     unsigned    r = SkPacked16ToR32(src);
727     unsigned    g = SkPacked16ToG32(src);
728     unsigned    b = SkPacked16ToB32(src);
729 
730     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
731     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
732     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
733 
734     return SkPackARGB32(0xFF, r, g, b);
735 }
736 
737 // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
SkPixel16ToColor(U16CPU src)738 static inline SkColor SkPixel16ToColor(U16CPU src) {
739     SkASSERT(src == SkToU16(src));
740 
741     unsigned    r = SkPacked16ToR32(src);
742     unsigned    g = SkPacked16ToG32(src);
743     unsigned    b = SkPacked16ToB32(src);
744 
745     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
746     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
747     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
748 
749     return SkColorSetRGB(r, g, b);
750 }
751 
752 ///////////////////////////////////////////////////////////////////////////////
753 
754 typedef uint16_t SkPMColor16;
755 
756 // Put in OpenGL order (r g b a)
757 #define SK_A4444_SHIFT    0
758 #define SK_R4444_SHIFT    12
759 #define SK_G4444_SHIFT    8
760 #define SK_B4444_SHIFT    4
761 
762 #define SkA32To4444(a)  ((unsigned)(a) >> 4)
763 #define SkR32To4444(r)  ((unsigned)(r) >> 4)
764 #define SkG32To4444(g)  ((unsigned)(g) >> 4)
765 #define SkB32To4444(b)  ((unsigned)(b) >> 4)
766 
SkReplicateNibble(unsigned nib)767 static inline U8CPU SkReplicateNibble(unsigned nib) {
768     SkASSERT(nib <= 0xF);
769     return (nib << 4) | nib;
770 }
771 
772 #define SkA4444ToA32(a)     SkReplicateNibble(a)
773 #define SkR4444ToR32(r)     SkReplicateNibble(r)
774 #define SkG4444ToG32(g)     SkReplicateNibble(g)
775 #define SkB4444ToB32(b)     SkReplicateNibble(b)
776 
777 #define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
778 #define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
779 #define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
780 #define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
781 
782 #define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
783 #define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
784 #define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
785 #define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
786 
787 #ifdef SK_DEBUG
SkPMColor16Assert(U16CPU c)788 static inline void SkPMColor16Assert(U16CPU c) {
789     unsigned a = SkGetPackedA4444(c);
790     unsigned r = SkGetPackedR4444(c);
791     unsigned g = SkGetPackedG4444(c);
792     unsigned b = SkGetPackedB4444(c);
793 
794     SkASSERT(a <= 0xF);
795     SkASSERT(r <= a);
796     SkASSERT(g <= a);
797     SkASSERT(b <= a);
798 }
799 #else
800 #define SkPMColor16Assert(c)
801 #endif
802 
SkAlpha15To16(unsigned a)803 static inline unsigned SkAlpha15To16(unsigned a) {
804     SkASSERT(a <= 0xF);
805     return a + (a >> 3);
806 }
807 
808 #ifdef SK_DEBUG
SkAlphaMul4(int value,int scale)809     static inline int SkAlphaMul4(int value, int scale) {
810         SkASSERT((unsigned)scale <= 0x10);
811         return value * scale >> 4;
812     }
813 #else
814     #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
815 #endif
816 
SkR4444ToR565(unsigned r)817 static inline unsigned SkR4444ToR565(unsigned r) {
818     SkASSERT(r <= 0xF);
819     return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
820 }
821 
SkG4444ToG565(unsigned g)822 static inline unsigned SkG4444ToG565(unsigned g) {
823     SkASSERT(g <= 0xF);
824     return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
825 }
826 
SkB4444ToB565(unsigned b)827 static inline unsigned SkB4444ToB565(unsigned b) {
828     SkASSERT(b <= 0xF);
829     return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
830 }
831 
SkPackARGB4444(unsigned a,unsigned r,unsigned g,unsigned b)832 static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
833                                          unsigned g, unsigned b) {
834     SkASSERT(a <= 0xF);
835     SkASSERT(r <= a);
836     SkASSERT(g <= a);
837     SkASSERT(b <= a);
838 
839     return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
840                          (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
841 }
842 
SkAlphaMulQ4(SkPMColor16 c,int scale)843 static inline SkPMColor16 SkAlphaMulQ4(SkPMColor16 c, int scale) {
844     SkASSERT(scale <= 16);
845 
846     const unsigned mask = 0xF0F;    //gMask_0F0F;
847 
848 #if 0
849     unsigned rb = ((c & mask) * scale) >> 4;
850     unsigned ag = ((c >> 4) & mask) * scale;
851     return (rb & mask) | (ag & ~mask);
852 #else
853     unsigned expanded_c = (c & mask) | ((c & (mask << 4)) << 12);
854     unsigned scaled_c = (expanded_c * scale) >> 4;
855     return (scaled_c & mask) | ((scaled_c >> 12) & (mask << 4));
856 #endif
857 }
858 
859 /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
860     once by a value up to 16.
861 */
SkExpand_4444(U16CPU c)862 static inline uint32_t SkExpand_4444(U16CPU c) {
863     SkASSERT(c == (uint16_t)c);
864 
865     const unsigned mask = 0xF0F;    //gMask_0F0F;
866     return (c & mask) | ((c & ~mask) << 12);
867 }
868 
SkSrcOver4444To16(SkPMColor16 s,uint16_t d)869 static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
870     unsigned sa = SkGetPackedA4444(s);
871     unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
872     unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
873     unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
874 
875     // To avoid overflow, we have to clear the low bit of the synthetic sg
876     // if the src alpha is <= 7.
877     // to see why, try blending 0x4444 on top of 565-white and watch green
878     // overflow (sum == 64)
879     sg &= ~(~(sa >> 3) & 1);
880 
881     unsigned scale = SkAlpha15To16(15 - sa);
882     unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
883     unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
884     unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
885 
886 #if 0
887     if (sg + dg > 63) {
888         SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
889     }
890 #endif
891     return SkPackRGB16(sr + dr, sg + dg, sb + db);
892 }
893 
SkBlend4444To16(SkPMColor16 src,uint16_t dst,int scale16)894 static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
895     SkASSERT((unsigned)scale16 <= 16);
896 
897     return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
898 }
899 
SkPixel4444ToPixel32(U16CPU c)900 static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
901     uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
902                  (SkGetPackedR4444(c) << SK_R32_SHIFT) |
903                  (SkGetPackedG4444(c) << SK_G32_SHIFT) |
904                  (SkGetPackedB4444(c) << SK_B32_SHIFT);
905     return d | (d << 4);
906 }
907 
SkPixel32ToPixel4444(SkPMColor c)908 static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
909     return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
910     (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
911     (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
912     (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
913 }
914 
915 // cheap 2x2 dither
SkDitherARGB32To4444(U8CPU a,U8CPU r,U8CPU g,U8CPU b)916 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
917                                                U8CPU g, U8CPU b) {
918     // to ensure that we stay a legal premultiplied color, we take the max()
919     // of the truncated and dithered alpha values. If we didn't, cases like
920     // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
921     // which is not legal premultiplied, since a < color
922     unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
923     a = SkMax32(a >> 4, dithered_a);
924     // these we just dither in place
925     r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
926     g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
927     b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
928 
929     return SkPackARGB4444(a, r, g, b);
930 }
931 
SkDitherPixel32To4444(SkPMColor c)932 static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
933     return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
934                                 SkGetPackedG32(c), SkGetPackedB32(c));
935 }
936 
937 /*  Assumes 16bit is in standard RGBA order.
938     Transforms a normal ARGB_8888 into the same byte order as
939     expanded ARGB_4444, but keeps each component 8bits
940 */
SkExpand_8888(SkPMColor c)941 static inline uint32_t SkExpand_8888(SkPMColor c) {
942     return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
943             (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
944             (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
945             (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
946 }
947 
948 /*  Undo the operation of SkExpand_8888, turning the argument back into
949     a SkPMColor.
950 */
SkCompact_8888(uint32_t c)951 static inline SkPMColor SkCompact_8888(uint32_t c) {
952     return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
953             (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
954             (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
955             (((c >>  0) & 0xFF) << SK_A32_SHIFT);
956 }
957 
958 /*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
959     but this routine just keeps the high 4bits of each component in the low
960     4bits of the result (just like a newly expanded PMColor16).
961 */
SkExpand32_4444(SkPMColor c)962 static inline uint32_t SkExpand32_4444(SkPMColor c) {
963     return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
964             (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
965             (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
966             (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
967 }
968 
969 // takes two values and alternamtes them as part of a memset16
970 // used for cheap 2x2 dithering when the colors are opaque
971 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
972 
973 ///////////////////////////////////////////////////////////////////////////////
974 
SkUpscale31To32(int value)975 static inline int SkUpscale31To32(int value) {
976     SkASSERT((unsigned)value <= 31);
977     return value + (value >> 4);
978 }
979 
SkBlend32(int src,int dst,int scale)980 static inline int SkBlend32(int src, int dst, int scale) {
981     SkASSERT((unsigned)src <= 0xFF);
982     SkASSERT((unsigned)dst <= 0xFF);
983     SkASSERT((unsigned)scale <= 32);
984     return dst + ((src - dst) * scale >> 5);
985 }
986 
SkBlendLCD16(int srcA,int srcR,int srcG,int srcB,SkPMColor dst,uint16_t mask)987 static inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
988                                      SkPMColor dst, uint16_t mask) {
989     if (mask == 0) {
990         return dst;
991     }
992 
993     /*  We want all of these in 5bits, hence the shifts in case one of them
994      *  (green) is 6bits.
995      */
996     int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
997     int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
998     int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
999 
1000     // Now upscale them to 0..32, so we can use blend32
1001     maskR = SkUpscale31To32(maskR);
1002     maskG = SkUpscale31To32(maskG);
1003     maskB = SkUpscale31To32(maskB);
1004 
1005     // srcA has been upscaled to 256 before passed into this function
1006     maskR = maskR * srcA >> 8;
1007     maskG = maskG * srcA >> 8;
1008     maskB = maskB * srcA >> 8;
1009 
1010     int dstR = SkGetPackedR32(dst);
1011     int dstG = SkGetPackedG32(dst);
1012     int dstB = SkGetPackedB32(dst);
1013 
1014     // LCD blitting is only supported if the dst is known/required
1015     // to be opaque
1016     return SkPackARGB32(0xFF,
1017                         SkBlend32(srcR, dstR, maskR),
1018                         SkBlend32(srcG, dstG, maskG),
1019                         SkBlend32(srcB, dstB, maskB));
1020 }
1021 
SkBlendLCD16Opaque(int srcR,int srcG,int srcB,SkPMColor dst,uint16_t mask,SkPMColor opaqueDst)1022 static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
1023                                            SkPMColor dst, uint16_t mask,
1024                                            SkPMColor opaqueDst) {
1025     if (mask == 0) {
1026         return dst;
1027     }
1028 
1029     if (0xFFFF == mask) {
1030         return opaqueDst;
1031     }
1032 
1033     /*  We want all of these in 5bits, hence the shifts in case one of them
1034      *  (green) is 6bits.
1035      */
1036     int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
1037     int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
1038     int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
1039 
1040     // Now upscale them to 0..32, so we can use blend32
1041     maskR = SkUpscale31To32(maskR);
1042     maskG = SkUpscale31To32(maskG);
1043     maskB = SkUpscale31To32(maskB);
1044 
1045     int dstR = SkGetPackedR32(dst);
1046     int dstG = SkGetPackedG32(dst);
1047     int dstB = SkGetPackedB32(dst);
1048 
1049     // LCD blitting is only supported if the dst is known/required
1050     // to be opaque
1051     return SkPackARGB32(0xFF,
1052                         SkBlend32(srcR, dstR, maskR),
1053                         SkBlend32(srcG, dstG, maskG),
1054                         SkBlend32(srcB, dstB, maskB));
1055 }
1056 
SkBlitLCD16Row(SkPMColor dst[],const uint16_t mask[],SkColor src,int width,SkPMColor)1057 static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
1058                                   SkColor src, int width, SkPMColor) {
1059     int srcA = SkColorGetA(src);
1060     int srcR = SkColorGetR(src);
1061     int srcG = SkColorGetG(src);
1062     int srcB = SkColorGetB(src);
1063 
1064     srcA = SkAlpha255To256(srcA);
1065 
1066     for (int i = 0; i < width; i++) {
1067         dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
1068     }
1069 }
1070 
SkBlitLCD16OpaqueRow(SkPMColor dst[],const uint16_t mask[],SkColor src,int width,SkPMColor opaqueDst)1071 static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
1072                                         SkColor src, int width,
1073                                         SkPMColor opaqueDst) {
1074     int srcR = SkColorGetR(src);
1075     int srcG = SkColorGetG(src);
1076     int srcB = SkColorGetB(src);
1077 
1078     for (int i = 0; i < width; i++) {
1079         dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
1080                                     opaqueDst);
1081     }
1082 }
1083 
1084 #endif
1085