Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: src/core/SkMipMap.cpp

Issue 1831353002: Add mipmap procs for F16 format. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address Mike's feedback Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkMipMap.h" 8 #include "SkMipMap.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkHalf.h"
11 #include "SkMath.h" 12 #include "SkMath.h"
12 #include "SkNx.h" 13 #include "SkNx.h"
13 #include "SkTypes.h" 14 #include "SkTypes.h"
14 15
15 // 16 //
16 // ColorTypeFilter is the "Type" we pass to some downsample template functions. 17 // ColorTypeFilter is the "Type" we pass to some downsample template functions.
17 // It controls how we expand a pixel into a large type, with space between each component, 18 // It controls how we expand a pixel into a large type, with space between each component,
18 // so we can then perform our simple filter (either box or triangle) and store t he intermediates 19 // so we can then perform our simple filter (either box or triangle) and store t he intermediates
19 // in the expanded type. 20 // in the expanded type.
20 // 21 //
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 struct ColorTypeFilter_8 { 64 struct ColorTypeFilter_8 {
64 typedef uint8_t Type; 65 typedef uint8_t Type;
65 static unsigned Expand(unsigned x) { 66 static unsigned Expand(unsigned x) {
66 return x; 67 return x;
67 } 68 }
68 static uint8_t Compact(unsigned x) { 69 static uint8_t Compact(unsigned x) {
69 return (uint8_t)x; 70 return (uint8_t)x;
70 } 71 }
71 }; 72 };
72 73
74 struct ColorTypeFilter_F16 {
75 typedef uint64_t Type; // SkHalf x4
76 static Sk4f Expand(uint64_t x) {
77 return SkHalfToFloat_01(x);
78 }
79 static uint64_t Compact(const Sk4f& x) {
80 return SkFloatToHalf_01(x);
81 }
82 };
83
73 template <typename T> T add_121(const T& a, const T& b, const T& c) { 84 template <typename T> T add_121(const T& a, const T& b, const T& c) {
74 return a + b + b + c; 85 return a + b + b + c;
75 } 86 }
76 87
88 template <typename T> T shift_right(const T& x, int bits) {
89 return x >> bits;
90 }
91
92 Sk4f shift_right(const Sk4f& x, int bits) {
93 return x * (1.0f / (1 << bits));
94 }
95
96 template <typename T> T shift_left(const T& x, int bits) {
97 return x << bits;
98 }
99
100 Sk4f shift_left(const Sk4f& x, int bits) {
101 return x * (1 << bits);
102 }
103
77 // 104 //
78 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50 ,50) 105 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50 ,50)
79 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) 106 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50)
80 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings, 107 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings,
81 // else for even cases, we just use a 2x box filter. 108 // else for even cases, we just use a 2x box filter.
82 // 109 //
83 // This produces 4 possible isotropic filters: 2x2 2x3 3x2 3x3 where WxH indica tes the number of 110 // This produces 4 possible isotropic filters: 2x2 2x3 3x2 3x3 where WxH indica tes the number of
84 // src pixels we need to sample in each dimension to produce 1 dst pixel. 111 // src pixels we need to sample in each dimension to produce 1 dst pixel.
85 // 112 //
86 // OpenGL expects a full mipmap stack to contain anisotropic space as well. 113 // OpenGL expects a full mipmap stack to contain anisotropic space as well.
87 // This means a 100x1 image would continue down to a 50x1 image, 25x1 image... 114 // This means a 100x1 image would continue down to a 50x1 image, 25x1 image...
88 // Because of this, we need 4 more anisotropic filters: 1x2, 1x3, 2x1, 3x1. 115 // Because of this, we need 4 more anisotropic filters: 1x2, 1x3, 2x1, 3x1.
89 116
90 template <typename F> void downsample_1_2(void* dst, const void* src, size_t src RB, int count) { 117 template <typename F> void downsample_1_2(void* dst, const void* src, size_t src RB, int count) {
91 SkASSERT(count > 0); 118 SkASSERT(count > 0);
92 auto p0 = static_cast<const typename F::Type*>(src); 119 auto p0 = static_cast<const typename F::Type*>(src);
93 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 120 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
94 auto d = static_cast<typename F::Type*>(dst); 121 auto d = static_cast<typename F::Type*>(dst);
95 122
96 for (int i = 0; i < count; ++i) { 123 for (int i = 0; i < count; ++i) {
97 auto c00 = F::Expand(p0[0]); 124 auto c00 = F::Expand(p0[0]);
98 auto c10 = F::Expand(p1[0]); 125 auto c10 = F::Expand(p1[0]);
99 126
100 auto c = c00 + c10; 127 auto c = c00 + c10;
101 d[i] = F::Compact(c >> 1); 128 d[i] = F::Compact(shift_right(c, 1));
102 p0 += 2; 129 p0 += 2;
103 p1 += 2; 130 p1 += 2;
104 } 131 }
105 } 132 }
106 133
107 template <typename F> void downsample_1_3(void* dst, const void* src, size_t src RB, int count) { 134 template <typename F> void downsample_1_3(void* dst, const void* src, size_t src RB, int count) {
108 SkASSERT(count > 0); 135 SkASSERT(count > 0);
109 auto p0 = static_cast<const typename F::Type*>(src); 136 auto p0 = static_cast<const typename F::Type*>(src);
110 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 137 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
111 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 138 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
112 auto d = static_cast<typename F::Type*>(dst); 139 auto d = static_cast<typename F::Type*>(dst);
113 140
114 for (int i = 0; i < count; ++i) { 141 for (int i = 0; i < count; ++i) {
115 auto c00 = F::Expand(p0[0]); 142 auto c00 = F::Expand(p0[0]);
116 auto c10 = F::Expand(p1[0]); 143 auto c10 = F::Expand(p1[0]);
117 auto c20 = F::Expand(p2[0]); 144 auto c20 = F::Expand(p2[0]);
118 145
119 auto c = add_121(c00, c10, c20); 146 auto c = add_121(c00, c10, c20);
120 d[i] = F::Compact(c >> 2); 147 d[i] = F::Compact(shift_right(c, 2));
121 p0 += 2; 148 p0 += 2;
122 p1 += 2; 149 p1 += 2;
123 p2 += 2; 150 p2 += 2;
124 } 151 }
125 } 152 }
126 153
127 template <typename F> void downsample_2_1(void* dst, const void* src, size_t src RB, int count) { 154 template <typename F> void downsample_2_1(void* dst, const void* src, size_t src RB, int count) {
128 SkASSERT(count > 0); 155 SkASSERT(count > 0);
129 auto p0 = static_cast<const typename F::Type*>(src); 156 auto p0 = static_cast<const typename F::Type*>(src);
130 auto d = static_cast<typename F::Type*>(dst); 157 auto d = static_cast<typename F::Type*>(dst);
131 158
132 for (int i = 0; i < count; ++i) { 159 for (int i = 0; i < count; ++i) {
133 auto c00 = F::Expand(p0[0]); 160 auto c00 = F::Expand(p0[0]);
134 auto c01 = F::Expand(p0[1]); 161 auto c01 = F::Expand(p0[1]);
135 162
136 auto c = c00 + c01; 163 auto c = c00 + c01;
137 d[i] = F::Compact(c >> 1); 164 d[i] = F::Compact(shift_right(c, 1));
138 p0 += 2; 165 p0 += 2;
139 } 166 }
140 } 167 }
141 168
142 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src RB, int count) { 169 template <typename F> void downsample_2_2(void* dst, const void* src, size_t src RB, int count) {
143 SkASSERT(count > 0); 170 SkASSERT(count > 0);
144 auto p0 = static_cast<const typename F::Type*>(src); 171 auto p0 = static_cast<const typename F::Type*>(src);
145 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 172 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
146 auto d = static_cast<typename F::Type*>(dst); 173 auto d = static_cast<typename F::Type*>(dst);
147 174
148 for (int i = 0; i < count; ++i) { 175 for (int i = 0; i < count; ++i) {
149 auto c00 = F::Expand(p0[0]); 176 auto c00 = F::Expand(p0[0]);
150 auto c01 = F::Expand(p0[1]); 177 auto c01 = F::Expand(p0[1]);
151 auto c10 = F::Expand(p1[0]); 178 auto c10 = F::Expand(p1[0]);
152 auto c11 = F::Expand(p1[1]); 179 auto c11 = F::Expand(p1[1]);
153 180
154 auto c = c00 + c10 + c01 + c11; 181 auto c = c00 + c10 + c01 + c11;
155 d[i] = F::Compact(c >> 2); 182 d[i] = F::Compact(shift_right(c, 2));
156 p0 += 2; 183 p0 += 2;
157 p1 += 2; 184 p1 += 2;
158 } 185 }
159 } 186 }
160 187
161 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src RB, int count) { 188 template <typename F> void downsample_2_3(void* dst, const void* src, size_t src RB, int count) {
162 SkASSERT(count > 0); 189 SkASSERT(count > 0);
163 auto p0 = static_cast<const typename F::Type*>(src); 190 auto p0 = static_cast<const typename F::Type*>(src);
164 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 191 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
165 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 192 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
166 auto d = static_cast<typename F::Type*>(dst); 193 auto d = static_cast<typename F::Type*>(dst);
167 194
168 for (int i = 0; i < count; ++i) { 195 for (int i = 0; i < count; ++i) {
169 auto c00 = F::Expand(p0[0]); 196 auto c00 = F::Expand(p0[0]);
170 auto c01 = F::Expand(p0[1]); 197 auto c01 = F::Expand(p0[1]);
171 auto c10 = F::Expand(p1[0]); 198 auto c10 = F::Expand(p1[0]);
172 auto c11 = F::Expand(p1[1]); 199 auto c11 = F::Expand(p1[1]);
173 auto c20 = F::Expand(p2[0]); 200 auto c20 = F::Expand(p2[0]);
174 auto c21 = F::Expand(p2[1]); 201 auto c21 = F::Expand(p2[1]);
175 202
176 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); 203 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
177 d[i] = F::Compact(c >> 3); 204 d[i] = F::Compact(shift_right(c, 3));
178 p0 += 2; 205 p0 += 2;
179 p1 += 2; 206 p1 += 2;
180 p2 += 2; 207 p2 += 2;
181 } 208 }
182 } 209 }
183 210
184 template <typename F> void downsample_3_1(void* dst, const void* src, size_t src RB, int count) { 211 template <typename F> void downsample_3_1(void* dst, const void* src, size_t src RB, int count) {
185 SkASSERT(count > 0); 212 SkASSERT(count > 0);
186 auto p0 = static_cast<const typename F::Type*>(src); 213 auto p0 = static_cast<const typename F::Type*>(src);
187 auto d = static_cast<typename F::Type*>(dst); 214 auto d = static_cast<typename F::Type*>(dst);
188 215
189 auto c02 = F::Expand(p0[0]); 216 auto c02 = F::Expand(p0[0]);
190 for (int i = 0; i < count; ++i) { 217 for (int i = 0; i < count; ++i) {
191 auto c00 = c02; 218 auto c00 = c02;
192 auto c01 = F::Expand(p0[1]); 219 auto c01 = F::Expand(p0[1]);
193 c02 = F::Expand(p0[2]); 220 c02 = F::Expand(p0[2]);
194 221
195 auto c = add_121(c00, c01, c02); 222 auto c = add_121(c00, c01, c02);
196 d[i] = F::Compact(c >> 2); 223 d[i] = F::Compact(shift_right(c, 2));
197 p0 += 2; 224 p0 += 2;
198 } 225 }
199 } 226 }
200 227
201 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src RB, int count) { 228 template <typename F> void downsample_3_2(void* dst, const void* src, size_t src RB, int count) {
202 SkASSERT(count > 0); 229 SkASSERT(count > 0);
203 auto p0 = static_cast<const typename F::Type*>(src); 230 auto p0 = static_cast<const typename F::Type*>(src);
204 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 231 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
205 auto d = static_cast<typename F::Type*>(dst); 232 auto d = static_cast<typename F::Type*>(dst);
206 233
207 auto c02 = F::Expand(p0[0]); 234 auto c02 = F::Expand(p0[0]);
208 auto c12 = F::Expand(p1[0]); 235 auto c12 = F::Expand(p1[0]);
209 for (int i = 0; i < count; ++i) { 236 for (int i = 0; i < count; ++i) {
210 auto c00 = c02; 237 auto c00 = c02;
211 auto c01 = F::Expand(p0[1]); 238 auto c01 = F::Expand(p0[1]);
212 c02 = F::Expand(p0[2]); 239 c02 = F::Expand(p0[2]);
213 auto c10 = c12; 240 auto c10 = c12;
214 auto c11 = F::Expand(p1[1]); 241 auto c11 = F::Expand(p1[1]);
215 c12 = F::Expand(p1[2]); 242 c12 = F::Expand(p1[2]);
216 243
217 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); 244 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12);
218 d[i] = F::Compact(c >> 3); 245 d[i] = F::Compact(shift_right(c, 3));
219 p0 += 2; 246 p0 += 2;
220 p1 += 2; 247 p1 += 2;
221 } 248 }
222 } 249 }
223 250
224 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src RB, int count) { 251 template <typename F> void downsample_3_3(void* dst, const void* src, size_t src RB, int count) {
225 SkASSERT(count > 0); 252 SkASSERT(count > 0);
226 auto p0 = static_cast<const typename F::Type*>(src); 253 auto p0 = static_cast<const typename F::Type*>(src);
227 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 254 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
228 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 255 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
229 auto d = static_cast<typename F::Type*>(dst); 256 auto d = static_cast<typename F::Type*>(dst);
230 257
231 auto c02 = F::Expand(p0[0]); 258 auto c02 = F::Expand(p0[0]);
232 auto c12 = F::Expand(p1[0]); 259 auto c12 = F::Expand(p1[0]);
233 auto c22 = F::Expand(p2[0]); 260 auto c22 = F::Expand(p2[0]);
234 for (int i = 0; i < count; ++i) { 261 for (int i = 0; i < count; ++i) {
235 auto c00 = c02; 262 auto c00 = c02;
236 auto c01 = F::Expand(p0[1]); 263 auto c01 = F::Expand(p0[1]);
237 c02 = F::Expand(p0[2]); 264 c02 = F::Expand(p0[2]);
238 auto c10 = c12; 265 auto c10 = c12;
239 auto c11 = F::Expand(p1[1]); 266 auto c11 = F::Expand(p1[1]);
240 c12 = F::Expand(p1[2]); 267 c12 = F::Expand(p1[2]);
241 auto c20 = c22; 268 auto c20 = c22;
242 auto c21 = F::Expand(p2[1]); 269 auto c21 = F::Expand(p2[1]);
243 c22 = F::Expand(p2[2]); 270 c22 = F::Expand(p2[2]);
244 271
245 auto c = add_121(c00, c01, c02) + (add_121(c10, c11, c12) << 1) + add_12 1(c20, c21, c22); 272 auto c =
246 d[i] = F::Compact(c >> 4); 273 add_121(c00, c01, c02) +
274 shift_left(add_121(c10, c11, c12), 1) +
275 add_121(c20, c21, c22);
276 d[i] = F::Compact(shift_right(c, 4));
247 p0 += 2; 277 p0 += 2;
248 p1 += 2; 278 p1 += 2;
249 p2 += 2; 279 p2 += 2;
250 } 280 }
251 } 281 }
252 282
253 //////////////////////////////////////////////////////////////////////////////// /////////////////// 283 //////////////////////////////////////////////////////////////////////////////// ///////////////////
254 284
255 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { 285 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) {
256 if (levelCount < 0) { 286 if (levelCount < 0) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 case kGray_8_SkColorType: 343 case kGray_8_SkColorType:
314 proc_1_2 = downsample_1_2<ColorTypeFilter_8>; 344 proc_1_2 = downsample_1_2<ColorTypeFilter_8>;
315 proc_1_3 = downsample_1_3<ColorTypeFilter_8>; 345 proc_1_3 = downsample_1_3<ColorTypeFilter_8>;
316 proc_2_1 = downsample_2_1<ColorTypeFilter_8>; 346 proc_2_1 = downsample_2_1<ColorTypeFilter_8>;
317 proc_2_2 = downsample_2_2<ColorTypeFilter_8>; 347 proc_2_2 = downsample_2_2<ColorTypeFilter_8>;
318 proc_2_3 = downsample_2_3<ColorTypeFilter_8>; 348 proc_2_3 = downsample_2_3<ColorTypeFilter_8>;
319 proc_3_1 = downsample_3_1<ColorTypeFilter_8>; 349 proc_3_1 = downsample_3_1<ColorTypeFilter_8>;
320 proc_3_2 = downsample_3_2<ColorTypeFilter_8>; 350 proc_3_2 = downsample_3_2<ColorTypeFilter_8>;
321 proc_3_3 = downsample_3_3<ColorTypeFilter_8>; 351 proc_3_3 = downsample_3_3<ColorTypeFilter_8>;
322 break; 352 break;
353 case kRGBA_F16_SkColorType:
354 proc_1_2 = downsample_1_2<ColorTypeFilter_F16>;
355 proc_1_3 = downsample_1_3<ColorTypeFilter_F16>;
356 proc_2_1 = downsample_2_1<ColorTypeFilter_F16>;
357 proc_2_2 = downsample_2_2<ColorTypeFilter_F16>;
358 proc_2_3 = downsample_2_3<ColorTypeFilter_F16>;
359 proc_3_1 = downsample_3_1<ColorTypeFilter_F16>;
360 proc_3_2 = downsample_3_2<ColorTypeFilter_F16>;
361 proc_3_3 = downsample_3_3<ColorTypeFilter_F16>;
362 break;
323 default: 363 default:
324 // TODO: We could build miplevels for kIndex8 if the levels were in 8888. 364 // TODO: We could build miplevels for kIndex8 if the levels were in 8888.
325 // Means using more ram, but the quality would be fine. 365 // Means using more ram, but the quality would be fine.
326 return nullptr; 366 return nullptr;
327 } 367 }
328 368
329 if (src.width() <= 1 && src.height() <= 1) { 369 if (src.width() <= 1 && src.height() <= 1) {
330 return nullptr; 370 return nullptr;
331 } 371 }
332 // whip through our loop to compute the exact size needed 372 // whip through our loop to compute the exact size needed
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 return false; 580 return false;
541 } 581 }
542 if (index > fCount - 1) { 582 if (index > fCount - 1) {
543 return false; 583 return false;
544 } 584 }
545 if (levelPtr) { 585 if (levelPtr) {
546 *levelPtr = fLevels[index]; 586 *levelPtr = fLevels[index];
547 } 587 }
548 return true; 588 return true;
549 } 589 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698