SkFixed15.h 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Copyright 2016 Google Inc.
  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. #ifndef SkFixed15_DEFINED
  8. #define SkFixed15_DEFINED
  9. #include "include/core/SkTypes.h"
  10. // SkFixed15 is a fixed point value that represents values in [0,1] as [0x0000, 0x8000].
  11. // This mapping allows us to implement most operations in tightly packed 16-bit SIMD,
  12. // most notably multiplying using Q15 multiplication instructions (and a little fixup).
  13. class SkFixed15 {
  14. public:
  15. SkFixed15() = default;
  16. SkFixed15(float val) : fVal(val * 32768) { SkASSERT(0.0f <= val && val <= 1.0f); }
  17. explicit operator float() const { return fVal * (1/32768.0f); }
  18. static SkFixed15 Load(uint16_t val) {
  19. SkASSERT(val <= 32768);
  20. return val;
  21. }
  22. uint16_t store() const { return fVal; }
  23. static SkFixed15 FromU8(uint8_t val) {
  24. return val*128 + (val>>1) // 32768/255 == 128.50196..., which is very close to 128 + 0.5.
  25. + ((val+1)>>8); // All val but 255 are correct. +1 if val == 255 to get 32768.
  26. }
  27. uint8_t to_u8() const {
  28. // FromU8() and to_u8() roundtrip all bytes.
  29. // There is still much room to tweak this towards the ideal, a rounding scale by 255/32768.
  30. return (fVal - (fVal>>8))>>7;
  31. }
  32. SkFixed15 operator +(SkFixed15 o) const { return fVal + o.fVal; }
  33. SkFixed15 operator -(SkFixed15 o) const { return fVal - o.fVal; }
  34. SkFixed15 operator *(SkFixed15 o) const { return (fVal * o.fVal + (1<<14)) >> 15; }
  35. SkFixed15 operator<<(int bits) const { return fVal << bits; }
  36. SkFixed15 operator>>(int bits) const { return fVal >> bits; }
  37. SkFixed15& operator +=(SkFixed15 o) { return (*this = *this + o); }
  38. SkFixed15& operator -=(SkFixed15 o) { return (*this = *this - o); }
  39. SkFixed15& operator *=(SkFixed15 o) { return (*this = *this * o); }
  40. SkFixed15& operator<<=(int bits) { return (*this = *this << bits); }
  41. SkFixed15& operator>>=(int bits) { return (*this = *this >> bits); }
  42. bool operator==(SkFixed15 o) const { return fVal == o.fVal; }
  43. bool operator!=(SkFixed15 o) const { return fVal != o.fVal; }
  44. bool operator<=(SkFixed15 o) const { return fVal <= o.fVal; }
  45. bool operator>=(SkFixed15 o) const { return fVal >= o.fVal; }
  46. bool operator< (SkFixed15 o) const { return fVal < o.fVal; }
  47. bool operator> (SkFixed15 o) const { return fVal > o.fVal; }
  48. private:
  49. SkFixed15(int val) : fVal(val) {}
  50. uint16_t fVal;
  51. };
  52. // Notes
  53. // - SSSE3+ multiply is _mm_abs_epi16(_mm_mulhrs_epi16(x, y));
  54. // - NEON multipy is vsraq_n_u16(vabsq_s16(vqrdmulhq_s16(x,y)),
  55. // vandq_s16(x,y), 15);
  56. // - Conversion to and from float can be done manually with bit masks and float add/subtract,
  57. // rather than the naive version here involving int<->float conversion and float multiply.
  58. // - On x86, conversion to float is _mm_sub_ps(_mm_unpacklo_epi16(x, _mm_set1_epi16(0x4380)),
  59. // _mm_set1_ps(256.0f)). // 0x43800000
  60. // - On ARM, we can use the vcvtq_n_f32_u32(vmovl_u16(x), 15) to convert to float,
  61. // and vcvtq_n_u32_f32(..., 15) for the other way around.
  62. #endif//SkFixed15_DEFINED