blob: fa920d75d6c0dc09e810895811dff7b1647d5117 [file] [log] [blame]
mtklein15391ee2015-03-25 13:43:34 -07001/*
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
mtkleinf94fa712015-03-18 09:51:23 -07008inline SkPMFloat& SkPMFloat::operator=(const SkPMFloat& that) {
9 fColors = that.fColors;
10 return *this;
11}
mtkleina2f4be72015-02-23 10:04:34 -080012
mtklein4e644f52015-03-04 11:25:27 -080013// 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.
mtkleina2f4be72015-02-23 10:04:34 -080015
mtklein60d2a322015-03-03 07:46:15 -080016// 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.
mtkleina2f4be72015-02-23 10:04:34 -080018// _mm_packus_epi16() gives us clamping for free while narrowing.
19
mtklein4e644f52015-03-04 11:25:27 -080020inline SkPMFloat::SkPMFloat(SkPMColor c) {
mtkleina2f4be72015-02-23 10:04:34 -080021 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());
mtkleinf94fa712015-03-18 09:51:23 -070025 fColors = _mm_cvtepi32_ps(fix8_32);
mtkleina2f4be72015-02-23 10:04:34 -080026 SkASSERT(this->isValid());
27}
28
29inline SkPMColor SkPMFloat::get() const {
30 SkASSERT(this->isValid());
mtklein91fd7372015-03-06 06:15:44 -080031 return this->clamped(); // Haven't beaten this yet.
mtkleina2f4be72015-02-23 10:04:34 -080032}
33
34inline SkPMColor SkPMFloat::clamped() const {
mtklein92d04da2015-03-23 12:01:45 -070035 // 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)),
mtkleina2f4be72015-02-23 10:04:34 -080037 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}
mtklein91fd7372015-03-06 06:15:44 -080043
mtklein3d4c4a52015-03-26 12:32:29 -070044inline 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
mtklein15391ee2015-03-25 13:43:34 -070054inline void SkPMFloat::From4PMColors(const SkPMColor colors[4],
55 SkPMFloat* a, SkPMFloat* b, SkPMFloat* c, SkPMFloat* d) {
mtklein91fd7372015-03-06 06:15:44 -080056 // Haven't beaten this yet.
mtklein15391ee2015-03-25 13:43:34 -070057 *a = FromPMColor(colors[0]);
58 *b = FromPMColor(colors[1]);
59 *c = FromPMColor(colors[2]);
60 *d = FromPMColor(colors[3]);
mtklein91fd7372015-03-06 06:15:44 -080061}
62
mtklein15391ee2015-03-25 13:43:34 -070063inline void SkPMFloat::To4PMColors(
64 const SkPMFloat& a, const SkPMFloat& b, const SkPMFloat&c, const SkPMFloat& d,
65 SkPMColor colors[4]) {
mtklein91fd7372015-03-06 06:15:44 -080066 // Haven't beaten this yet.
mtklein15391ee2015-03-25 13:43:34 -070067 ClampTo4PMColors(a,b,c,d, colors);
mtklein91fd7372015-03-06 06:15:44 -080068}
69
mtklein15391ee2015-03-25 13:43:34 -070070inline void SkPMFloat::ClampTo4PMColors(
71 const SkPMFloat& a, const SkPMFloat& b, const SkPMFloat&c, const SkPMFloat& d,
72 SkPMColor colors[4]) {
mtklein91fd7372015-03-06 06:15:44 -080073 // Same as _SSSE3.h's. We use 3 _mm_packus_epi16() where the naive loop uses 8.
mtklein92d04da2015-03-23 12:01:45 -070074 // We don't use _mm_cvtps_epi32, because we want precise control over how 0.5 rounds (up).
mtklein15391ee2015-03-25 13:43:34 -070075 __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));
mtklein91fd7372015-03-06 06:15:44 -080079 __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}