Index: src/core/SkMipMap.cpp |
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp |
index d766dfa8a56378debe58255589087ca7790423fa..685659aba7b1a1bedb23ec21bb1d8ebe3cc50dbf 100644 |
--- a/src/core/SkMipMap.cpp |
+++ b/src/core/SkMipMap.cpp |
@@ -8,6 +8,7 @@ |
#include "SkMipMap.h" |
#include "SkBitmap.h" |
#include "SkColorPriv.h" |
+#include "SkHalf.h" |
#include "SkMath.h" |
#include "SkNx.h" |
#include "SkTypes.h" |
@@ -70,10 +71,36 @@ struct ColorTypeFilter_8 { |
} |
}; |
+struct ColorTypeFilter_F16 { |
+ typedef SkHalf Type; |
mtklein
2016/04/05 21:05:15
Are you sure this code works correctly?
The other
|
+ static float Expand(SkHalf x) { |
+ return SkHalfToFloat(x); |
+ } |
+ static SkHalf Compact(float x) { |
+ return SkFloatToHalf(x); |
+ } |
+}; |
+ |
template <typename T> T add_121(const T& a, const T& b, const T& c) { |
return a + b + b + c; |
} |
+template <typename T> T shift_right_or_divide(const T& x, int bits) { |
f(malita)
2016/04/05 20:42:00
I think the shift mostly gets in the way at this p
mtklein
2016/04/05 20:58:36
Hrm, sadly, no. This would work but for the Sk4b/
f(malita)
2016/04/05 21:18:08
Ack.
|
+ return x >> bits; |
+} |
+ |
+template <> float shift_right_or_divide<float>(const float& x, int bits) { |
mtklein
2016/04/05 20:58:36
This is fine, but you can also just write
stat
|
+ return x / (1 << bits); |
mtklein
2016/04/05 20:58:36
Probably best to write x * (1.0f / (1<<bits)), whi
|
+} |
+ |
+template <typename T> T shift_left_or_multiply(const T& x, int bits) { |
+ return x << bits; |
+} |
+ |
+template <> float shift_left_or_multiply<float>(const float& x, int bits) { |
+ return x * (1 << bits); |
+} |
+ |
// |
// To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50,50) |
// If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) |
@@ -98,7 +125,7 @@ template <typename F> void downsample_1_2(void* dst, const void* src, size_t src |
auto c10 = F::Expand(p1[0]); |
auto c = c00 + c10; |
- d[i] = F::Compact(c >> 1); |
+ d[i] = F::Compact(shift_right_or_divide(c, 1)); |
mtklein
2016/04/05 20:58:36
Given that these shift_right_or_divide() and shift
|
p0 += 2; |
p1 += 2; |
} |
@@ -117,7 +144,7 @@ template <typename F> void downsample_1_3(void* dst, const void* src, size_t src |
auto c20 = F::Expand(p2[0]); |
auto c = add_121(c00, c10, c20); |
- d[i] = F::Compact(c >> 2); |
+ d[i] = F::Compact(shift_right_or_divide(c, 2)); |
p0 += 2; |
p1 += 2; |
p2 += 2; |
@@ -134,7 +161,7 @@ template <typename F> void downsample_2_1(void* dst, const void* src, size_t src |
auto c01 = F::Expand(p0[1]); |
auto c = c00 + c01; |
- d[i] = F::Compact(c >> 1); |
+ d[i] = F::Compact(shift_right_or_divide(c, 1)); |
p0 += 2; |
} |
} |
@@ -152,7 +179,7 @@ template <typename F> void downsample_2_2(void* dst, const void* src, size_t src |
auto c11 = F::Expand(p1[1]); |
auto c = c00 + c10 + c01 + c11; |
- d[i] = F::Compact(c >> 2); |
+ d[i] = F::Compact(shift_right_or_divide(c, 2)); |
p0 += 2; |
p1 += 2; |
} |
@@ -174,7 +201,7 @@ template <typename F> void downsample_2_3(void* dst, const void* src, size_t src |
auto c21 = F::Expand(p2[1]); |
auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); |
- d[i] = F::Compact(c >> 3); |
+ d[i] = F::Compact(shift_right_or_divide(c, 3)); |
p0 += 2; |
p1 += 2; |
p2 += 2; |
@@ -193,7 +220,7 @@ template <typename F> void downsample_3_1(void* dst, const void* src, size_t src |
c02 = F::Expand(p0[2]); |
auto c = add_121(c00, c01, c02); |
- d[i] = F::Compact(c >> 2); |
+ d[i] = F::Compact(shift_right_or_divide(c, 2)); |
p0 += 2; |
} |
} |
@@ -215,7 +242,7 @@ template <typename F> void downsample_3_2(void* dst, const void* src, size_t src |
c12 = F::Expand(p1[2]); |
auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); |
- d[i] = F::Compact(c >> 3); |
+ d[i] = F::Compact(shift_right_or_divide(c, 3)); |
p0 += 2; |
p1 += 2; |
} |
@@ -242,8 +269,11 @@ template <typename F> void downsample_3_3(void* dst, const void* src, size_t src |
auto c21 = F::Expand(p2[1]); |
c22 = F::Expand(p2[2]); |
- auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_121(c20, c21, c22); |
- d[i] = F::Compact(c >> 4); |
+ auto c = |
+ add_121(c00, c01, c02) + |
+ shift_left_or_multiply(add_121(c10, c11, c12), 1) + |
+ add_121(c20, c21, c22); |
+ d[i] = F::Compact(shift_right_or_divide(c, 4)); |
p0 += 2; |
p1 += 2; |
p2 += 2; |
@@ -320,6 +350,16 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { |
proc_3_2 = downsample_3_2<ColorTypeFilter_8>; |
proc_3_3 = downsample_3_3<ColorTypeFilter_8>; |
break; |
+ case kRGBA_F16_SkColorType: |
+ proc_1_2 = downsample_1_2<ColorTypeFilter_F16>; |
+ proc_1_3 = downsample_1_3<ColorTypeFilter_F16>; |
+ proc_2_1 = downsample_2_1<ColorTypeFilter_F16>; |
+ proc_2_2 = downsample_2_2<ColorTypeFilter_F16>; |
+ proc_2_3 = downsample_2_3<ColorTypeFilter_F16>; |
+ proc_3_1 = downsample_3_1<ColorTypeFilter_F16>; |
+ proc_3_2 = downsample_3_2<ColorTypeFilter_F16>; |
+ proc_3_3 = downsample_3_3<ColorTypeFilter_F16>; |
+ break; |
default: |
// TODO: We could build miplevels for kIndex8 if the levels were in 8888. |
// Means using more ram, but the quality would be fine. |