| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2015 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 |  | 
| mtklein | f94fa71 | 2015-03-18 09:51:23 -0700 | [diff] [blame] | 8 | inline SkPMFloat& SkPMFloat::operator=(const SkPMFloat& that) { | 
 | 9 |     fColors = that.fColors; | 
 | 10 |     return *this; | 
 | 11 | } | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 12 |  | 
| mtklein | 4e644f5 | 2015-03-04 11:25:27 -0800 | [diff] [blame] | 13 | // For SkPMFloat(SkPMColor), we widen our 8 bit components (fix8) to 8-bit components in 16 bits | 
 | 14 | // (fix8_16), then widen those to 8-bit-in-32-bits (fix8_32), and finally convert those to floats. | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 15 |  | 
| mtklein | 60d2a32 | 2015-03-03 07:46:15 -0800 | [diff] [blame] | 16 | // get() and clamped() do the opposite, working from floats to 8-bit-in-32-bit, | 
 | 17 | // to 8-bit-in-16-bit, back down to 8-bit components. | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 18 | // _mm_packus_epi16() gives us clamping for free while narrowing. | 
 | 19 |  | 
| mtklein | 4e644f5 | 2015-03-04 11:25:27 -0800 | [diff] [blame] | 20 | inline SkPMFloat::SkPMFloat(SkPMColor c) { | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 21 |     SkPMColorAssert(c); | 
 | 22 |     __m128i fix8    = _mm_set_epi32(0,0,0,c), | 
 | 23 |             fix8_16 = _mm_unpacklo_epi8 (fix8,    _mm_setzero_si128()), | 
 | 24 |             fix8_32 = _mm_unpacklo_epi16(fix8_16, _mm_setzero_si128()); | 
| mtklein | f94fa71 | 2015-03-18 09:51:23 -0700 | [diff] [blame] | 25 |     fColors = _mm_cvtepi32_ps(fix8_32); | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 26 |     SkASSERT(this->isValid()); | 
 | 27 | } | 
 | 28 |  | 
 | 29 | inline SkPMColor SkPMFloat::get() const { | 
 | 30 |     SkASSERT(this->isValid()); | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 31 |     return this->clamped();  // Haven't beaten this yet. | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 32 | } | 
 | 33 |  | 
 | 34 | inline SkPMColor SkPMFloat::clamped() const { | 
| mtklein | 92d04da | 2015-03-23 12:01:45 -0700 | [diff] [blame] | 35 |     // We don't use _mm_cvtps_epi32, because we want precise control over how 0.5 rounds (up). | 
 | 36 |     __m128i fix8_32 = _mm_cvttps_epi32(_mm_add_ps(_mm_set1_ps(0.5f), fColors)), | 
| mtklein | a2f4be7 | 2015-02-23 10:04:34 -0800 | [diff] [blame] | 37 |             fix8_16 = _mm_packus_epi16(fix8_32, fix8_32), | 
 | 38 |             fix8    = _mm_packus_epi16(fix8_16, fix8_16); | 
 | 39 |     SkPMColor c = _mm_cvtsi128_si32(fix8); | 
 | 40 |     SkPMColorAssert(c); | 
 | 41 |     return c; | 
 | 42 | } | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 43 |  | 
| mtklein | 3d4c4a5 | 2015-03-26 12:32:29 -0700 | [diff] [blame] | 44 | inline SkPMColor SkPMFloat::trunc() const { | 
 | 45 |     // Basically, same as clamped(), but no rounding. | 
 | 46 |     __m128i fix8_32 = _mm_cvttps_epi32(fColors), | 
 | 47 |             fix8_16 = _mm_packus_epi16(fix8_32, fix8_32), | 
 | 48 |             fix8    = _mm_packus_epi16(fix8_16, fix8_16); | 
 | 49 |     SkPMColor c = _mm_cvtsi128_si32(fix8); | 
 | 50 |     SkPMColorAssert(c); | 
 | 51 |     return c; | 
 | 52 | } | 
 | 53 |  | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 54 | inline void SkPMFloat::From4PMColors(const SkPMColor colors[4], | 
 | 55 |                                      SkPMFloat* a, SkPMFloat* b, SkPMFloat* c, SkPMFloat* d) { | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 56 |     // Haven't beaten this yet. | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 57 |     *a = FromPMColor(colors[0]); | 
 | 58 |     *b = FromPMColor(colors[1]); | 
 | 59 |     *c = FromPMColor(colors[2]); | 
 | 60 |     *d = FromPMColor(colors[3]); | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 61 | } | 
 | 62 |  | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 63 | inline void SkPMFloat::To4PMColors( | 
 | 64 |         const SkPMFloat& a, const SkPMFloat& b, const SkPMFloat&c, const SkPMFloat& d, | 
 | 65 |         SkPMColor colors[4]) { | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 66 |     // Haven't beaten this yet. | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 67 |     ClampTo4PMColors(a,b,c,d, colors); | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 68 | } | 
 | 69 |  | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 70 | inline void SkPMFloat::ClampTo4PMColors( | 
 | 71 |         const SkPMFloat& a, const SkPMFloat& b, const SkPMFloat&c, const SkPMFloat& d, | 
 | 72 |         SkPMColor colors[4]) { | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 73 |     // Same as _SSSE3.h's.  We use 3 _mm_packus_epi16() where the naive loop uses 8. | 
| mtklein | 92d04da | 2015-03-23 12:01:45 -0700 | [diff] [blame] | 74 |     // We don't use _mm_cvtps_epi32, because we want precise control over how 0.5 rounds (up). | 
| mtklein | 15391ee | 2015-03-25 13:43:34 -0700 | [diff] [blame] | 75 |     __m128i c0 = _mm_cvttps_epi32(_mm_add_ps(_mm_set1_ps(0.5f), a.fColors)), | 
 | 76 |             c1 = _mm_cvttps_epi32(_mm_add_ps(_mm_set1_ps(0.5f), b.fColors)), | 
 | 77 |             c2 = _mm_cvttps_epi32(_mm_add_ps(_mm_set1_ps(0.5f), c.fColors)), | 
 | 78 |             c3 = _mm_cvttps_epi32(_mm_add_ps(_mm_set1_ps(0.5f), d.fColors)); | 
| mtklein | 91fd737 | 2015-03-06 06:15:44 -0800 | [diff] [blame] | 79 |     __m128i c3210 = _mm_packus_epi16(_mm_packus_epi16(c0, c1), | 
 | 80 |                                      _mm_packus_epi16(c2, c3)); | 
 | 81 |     _mm_storeu_si128((__m128i*)colors, c3210); | 
 | 82 |     SkPMColorAssert(colors[0]); | 
 | 83 |     SkPMColorAssert(colors[1]); | 
 | 84 |     SkPMColorAssert(colors[2]); | 
 | 85 |     SkPMColorAssert(colors[3]); | 
 | 86 | } |