SkPMFloat.h revision 4b65059e6eea7d90ff3547e4656f7659d3815dc4
1#ifndef SkPM_DEFINED
2#define SkPM_DEFINED
3
4#include "SkTypes.h"
5#include "SkColor.h"
6#include "SkColorPriv.h"
7#include "Sk4x.h"
8
9#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
10    #include <immintrin.h>
11#elif defined(SK_ARM_HAS_NEON)
12    #include <arm_neon.h>
13#endif
14
15// A pre-multiplied color storing each component in the same order as SkPMColor,
16// but as a float in the range [0, 255].
17class SK_STRUCT_ALIGN(16) SkPMFloat {
18public:
19    static SkPMFloat FromPMColor(SkPMColor c) { return SkPMFloat(c); }
20    static SkPMFloat FromARGB(float a, float r, float g, float b) { return SkPMFloat(a,r,g,b); }
21
22    // May be more efficient than one at a time.  No special alignment assumed for SkPMColors.
23    static void From4PMColors(SkPMFloat[4], const SkPMColor[4]);
24
25    explicit SkPMFloat(SkPMColor);
26    SkPMFloat(float a, float r, float g, float b) {
27        // TODO: faster when specialized?
28        fColor[SK_A32_SHIFT / 8] = a;
29        fColor[SK_R32_SHIFT / 8] = r;
30        fColor[SK_G32_SHIFT / 8] = g;
31        fColor[SK_B32_SHIFT / 8] = b;
32    }
33
34    // Uninitialized.
35    SkPMFloat() {}
36
37    SkPMFloat(const SkPMFloat& that) { *this = that; }
38    SkPMFloat& operator=(const SkPMFloat& that);
39
40    // Freely autoconvert between SkPMFloat and Sk4f.  They're always byte-for-byte identical.
41    /*implicit*/ SkPMFloat(const Sk4f& fs) { fs.storeAligned(fColor); }
42    /*implicit*/ operator Sk4f() const { return Sk4f::LoadAligned(fColor); }
43
44    float a() const { return fColor[SK_A32_SHIFT / 8]; }
45    float r() const { return fColor[SK_R32_SHIFT / 8]; }
46    float g() const { return fColor[SK_G32_SHIFT / 8]; }
47    float b() const { return fColor[SK_B32_SHIFT / 8]; }
48
49    // get() and clamped() round component values to the nearest integer.
50    SkPMColor     get() const;  // May SkASSERT(this->isValid()).  Some implementations may clamp.
51    SkPMColor clamped() const;  // Will clamp all values to [0, 255].  Then may assert isValid().
52
53    // 4-at-a-time versions of get() and clamped().  Like From4PMColors(), no alignment assumed.
54    static void To4PMColors(SkPMColor[4], const SkPMFloat[4]);
55    static void ClampTo4PMColors(SkPMColor[4], const SkPMFloat[4]);
56
57    bool isValid() const {
58        return this->a() >= 0 && this->a() <= 255
59            && this->r() >= 0 && this->r() <= this->a()
60            && this->g() >= 0 && this->g() <= this->a()
61            && this->b() >= 0 && this->b() <= this->a();
62    }
63
64private:
65    union {
66        float fColor[4];
67#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
68        __m128 fColors;
69#elif defined(SK_ARM_HAS_NEON)
70        float32x4_t fColors;
71#endif
72    };
73};
74
75#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
76    #include "../opts/SkPMFloat_SSSE3.h"
77#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
78    #include "../opts/SkPMFloat_SSE2.h"
79#elif defined(SK_ARM_HAS_NEON)
80    #include "../opts/SkPMFloat_neon.h"
81#else
82    #include "../opts/SkPMFloat_none.h"
83#endif
84
85#endif//SkPM_DEFINED
86