1 /*
2 * Copyright 2023 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
8 #include "include/core/SkTypes.h"
9
10 #ifndef SK_USE_DRAWING_MIPMAP_DOWNSAMPLER
11
12 #include "include/private/SkColorData.h"
13 #include "src/base/SkHalf.h"
14 #include "src/base/SkVx.h"
15 #include "src/core/SkMipmap.h"
16
17 namespace {
18
19 struct ColorTypeFilter_8888 {
20 typedef uint32_t Type;
Expand__anon33863e050111::ColorTypeFilter_888821 static skvx::Vec<4, uint16_t> Expand(uint32_t x) {
22 return skvx::cast<uint16_t>(skvx::byte4::Load(&x));
23 }
Compact__anon33863e050111::ColorTypeFilter_888824 static uint32_t Compact(const skvx::Vec<4, uint16_t>& x) {
25 uint32_t r;
26 skvx::cast<uint8_t>(x).store(&r);
27 return r;
28 }
29 };
30
31 struct ColorTypeFilter_565 {
32 typedef uint16_t Type;
Expand__anon33863e050111::ColorTypeFilter_56533 static uint32_t Expand(uint16_t x) {
34 return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16);
35 }
Compact__anon33863e050111::ColorTypeFilter_56536 static uint16_t Compact(uint32_t x) {
37 return ((x & ~SK_G16_MASK_IN_PLACE) & 0xFFFF) | ((x >> 16) & SK_G16_MASK_IN_PLACE);
38 }
39 };
40
41 struct ColorTypeFilter_4444 {
42 typedef uint16_t Type;
Expand__anon33863e050111::ColorTypeFilter_444443 static uint32_t Expand(uint16_t x) {
44 return (x & 0xF0F) | ((x & ~0xF0F) << 12);
45 }
Compact__anon33863e050111::ColorTypeFilter_444446 static uint16_t Compact(uint32_t x) {
47 return (x & 0xF0F) | ((x >> 12) & ~0xF0F);
48 }
49 };
50
51 struct ColorTypeFilter_8 {
52 typedef uint8_t Type;
Expand__anon33863e050111::ColorTypeFilter_853 static unsigned Expand(unsigned x) {
54 return x;
55 }
Compact__anon33863e050111::ColorTypeFilter_856 static uint8_t Compact(unsigned x) {
57 return (uint8_t)x;
58 }
59 };
60
61 struct ColorTypeFilter_Alpha_F16 {
62 typedef uint16_t Type;
Expand__anon33863e050111::ColorTypeFilter_Alpha_F1663 static skvx::float4 Expand(uint16_t x) {
64 uint64_t x4 = (uint64_t)x; // add 0s out to four lanes (0,0,0,x)
65 return from_half(skvx::half4::Load(&x4));
66 }
Compact__anon33863e050111::ColorTypeFilter_Alpha_F1667 static uint16_t Compact(const skvx::float4& x) {
68 uint64_t r;
69 to_half(x).store(&r);
70 return r & 0xFFFF; // but ignore the extra 3 here
71 }
72 };
73
74 struct ColorTypeFilter_RGBA_F16 {
75 typedef uint64_t Type; // SkHalf x4
Expand__anon33863e050111::ColorTypeFilter_RGBA_F1676 static skvx::float4 Expand(uint64_t x) {
77 return from_half(skvx::half4::Load(&x));
78 }
Compact__anon33863e050111::ColorTypeFilter_RGBA_F1679 static uint64_t Compact(const skvx::float4& x) {
80 uint64_t r;
81 to_half(x).store(&r);
82 return r;
83 }
84 };
85
86 struct ColorTypeFilter_88 {
87 typedef uint16_t Type;
Expand__anon33863e050111::ColorTypeFilter_8888 static uint32_t Expand(uint16_t x) {
89 return (x & 0xFF) | ((x & ~0xFF) << 8);
90 }
Compact__anon33863e050111::ColorTypeFilter_8891 static uint16_t Compact(uint32_t x) {
92 return (x & 0xFF) | ((x >> 8) & ~0xFF);
93 }
94 };
95
96 struct ColorTypeFilter_1616 {
97 typedef uint32_t Type;
Expand__anon33863e050111::ColorTypeFilter_161698 static uint64_t Expand(uint32_t x) {
99 return (x & 0xFFFF) | ((x & ~0xFFFF) << 16);
100 }
Compact__anon33863e050111::ColorTypeFilter_1616101 static uint16_t Compact(uint64_t x) {
102 return (x & 0xFFFF) | ((x >> 16) & ~0xFFFF);
103 }
104 };
105
106 struct ColorTypeFilter_F16F16 {
107 typedef uint32_t Type;
Expand__anon33863e050111::ColorTypeFilter_F16F16108 static skvx::float4 Expand(uint32_t x) {
109 uint64_t x4 = (uint64_t)x; // // add 0s out to four lanes (0,0,x,x)
110 return from_half(skvx::half4::Load(&x4));
111 }
Compact__anon33863e050111::ColorTypeFilter_F16F16112 static uint32_t Compact(const skvx::float4& x) {
113 uint64_t r;
114 to_half(x).store(&r);
115 return (uint32_t) (r & 0xFFFFFFFF); // but ignore the extra 2 here
116 }
117 };
118
119 struct ColorTypeFilter_16161616 {
120 typedef uint64_t Type;
Expand__anon33863e050111::ColorTypeFilter_16161616121 static skvx::Vec<4, uint32_t> Expand(uint64_t x) {
122 return skvx::cast<uint32_t>(skvx::Vec<4, uint16_t>::Load(&x));
123 }
Compact__anon33863e050111::ColorTypeFilter_16161616124 static uint64_t Compact(const skvx::Vec<4, uint32_t>& x) {
125 uint64_t r;
126 skvx::cast<uint16_t>(x).store(&r);
127 return r;
128 }
129 };
130
131 struct ColorTypeFilter_16 {
132 typedef uint16_t Type;
Expand__anon33863e050111::ColorTypeFilter_16133 static uint32_t Expand(uint16_t x) {
134 return x;
135 }
Compact__anon33863e050111::ColorTypeFilter_16136 static uint16_t Compact(uint32_t x) {
137 return (uint16_t) x;
138 }
139 };
140
141 struct ColorTypeFilter_1010102 {
142 typedef uint32_t Type;
Expand__anon33863e050111::ColorTypeFilter_1010102143 static uint64_t Expand(uint64_t x) {
144 return (((x ) & 0x3ff) ) |
145 (((x >> 10) & 0x3ff) << 20) |
146 (((x >> 20) & 0x3ff) << 40) |
147 (((x >> 30) & 0x3 ) << 60);
148 }
Compact__anon33863e050111::ColorTypeFilter_1010102149 static uint32_t Compact(uint64_t x) {
150 return (((x ) & 0x3ff) ) |
151 (((x >> 20) & 0x3ff) << 10) |
152 (((x >> 40) & 0x3ff) << 20) |
153 (((x >> 60) & 0x3 ) << 30);
154 }
155 };
156
add_121(const T & a,const T & b,const T & c)157 template <typename T> T add_121(const T& a, const T& b, const T& c) {
158 return a + b + b + c;
159 }
160
shift_right(const T & x,int bits)161 template <typename T> T shift_right(const T& x, int bits) {
162 return x >> bits;
163 }
164
shift_right(const skvx::float4 & x,int bits)165 skvx::float4 shift_right(const skvx::float4& x, int bits) {
166 return x * (1.0f / (1 << bits));
167 }
168
shift_left(const T & x,int bits)169 template <typename T> T shift_left(const T& x, int bits) {
170 return x << bits;
171 }
172
shift_left(const skvx::float4 & x,int bits)173 skvx::float4 shift_left(const skvx::float4& x, int bits) {
174 return x * (1 << bits);
175 }
176
177 //
178 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50,50)
179 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50)
180 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings,
181 // else for even cases, we just use a 2x box filter.
182 //
183 // This produces 4 possible isotropic filters: 2x2 2x3 3x2 3x3 where WxH indicates the number of
184 // src pixels we need to sample in each dimension to produce 1 dst pixel.
185 //
186 // OpenGL expects a full mipmap stack to contain anisotropic space as well.
187 // This means a 100x1 image would continue down to a 50x1 image, 25x1 image...
188 // Because of this, we need 4 more anisotropic filters: 1x2, 1x3, 2x1, 3x1.
189
downsample_1_2(void * dst,const void * src,size_t srcRB,int count)190 template <typename F> void downsample_1_2(void* dst, const void* src, size_t srcRB, int count) {
191 SkASSERT(count > 0);
192 auto p0 = static_cast<const typename F::Type*>(src);
193 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
194 auto d = static_cast<typename F::Type*>(dst);
195
196 for (int i = 0; i < count; ++i) {
197 auto c00 = F::Expand(p0[0]);
198 auto c10 = F::Expand(p1[0]);
199
200 auto c = c00 + c10;
201 d[i] = F::Compact(shift_right(c, 1));
202 p0 += 2;
203 p1 += 2;
204 }
205 }
206
downsample_1_3(void * dst,const void * src,size_t srcRB,int count)207 template <typename F> void downsample_1_3(void* dst, const void* src, size_t srcRB, int count) {
208 SkASSERT(count > 0);
209 auto p0 = static_cast<const typename F::Type*>(src);
210 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
211 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
212 auto d = static_cast<typename F::Type*>(dst);
213
214 for (int i = 0; i < count; ++i) {
215 auto c00 = F::Expand(p0[0]);
216 auto c10 = F::Expand(p1[0]);
217 auto c20 = F::Expand(p2[0]);
218
219 auto c = add_121(c00, c10, c20);
220 d[i] = F::Compact(shift_right(c, 2));
221 p0 += 2;
222 p1 += 2;
223 p2 += 2;
224 }
225 }
226
downsample_2_1(void * dst,const void * src,size_t srcRB,int count)227 template <typename F> void downsample_2_1(void* dst, const void* src, size_t srcRB, int count) {
228 SkASSERT(count > 0);
229 auto p0 = static_cast<const typename F::Type*>(src);
230 auto d = static_cast<typename F::Type*>(dst);
231
232 for (int i = 0; i < count; ++i) {
233 auto c00 = F::Expand(p0[0]);
234 auto c01 = F::Expand(p0[1]);
235
236 auto c = c00 + c01;
237 d[i] = F::Compact(shift_right(c, 1));
238 p0 += 2;
239 }
240 }
241
downsample_2_2(void * dst,const void * src,size_t srcRB,int count)242 template <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB, int count) {
243 SkASSERT(count > 0);
244 auto p0 = static_cast<const typename F::Type*>(src);
245 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
246 auto d = static_cast<typename F::Type*>(dst);
247
248 for (int i = 0; i < count; ++i) {
249 auto c00 = F::Expand(p0[0]);
250 auto c01 = F::Expand(p0[1]);
251 auto c10 = F::Expand(p1[0]);
252 auto c11 = F::Expand(p1[1]);
253
254 auto c = c00 + c10 + c01 + c11;
255 d[i] = F::Compact(shift_right(c, 2));
256 p0 += 2;
257 p1 += 2;
258 }
259 }
260
downsample_2_3(void * dst,const void * src,size_t srcRB,int count)261 template <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB, int count) {
262 SkASSERT(count > 0);
263 auto p0 = static_cast<const typename F::Type*>(src);
264 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
265 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
266 auto d = static_cast<typename F::Type*>(dst);
267
268 for (int i = 0; i < count; ++i) {
269 auto c00 = F::Expand(p0[0]);
270 auto c01 = F::Expand(p0[1]);
271 auto c10 = F::Expand(p1[0]);
272 auto c11 = F::Expand(p1[1]);
273 auto c20 = F::Expand(p2[0]);
274 auto c21 = F::Expand(p2[1]);
275
276 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21);
277 d[i] = F::Compact(shift_right(c, 3));
278 p0 += 2;
279 p1 += 2;
280 p2 += 2;
281 }
282 }
283
downsample_3_1(void * dst,const void * src,size_t srcRB,int count)284 template <typename F> void downsample_3_1(void* dst, const void* src, size_t srcRB, int count) {
285 SkASSERT(count > 0);
286 auto p0 = static_cast<const typename F::Type*>(src);
287 auto d = static_cast<typename F::Type*>(dst);
288
289 auto c02 = F::Expand(p0[0]);
290 for (int i = 0; i < count; ++i) {
291 auto c00 = c02;
292 auto c01 = F::Expand(p0[1]);
293 c02 = F::Expand(p0[2]);
294
295 auto c = add_121(c00, c01, c02);
296 d[i] = F::Compact(shift_right(c, 2));
297 p0 += 2;
298 }
299 }
300
downsample_3_2(void * dst,const void * src,size_t srcRB,int count)301 template <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB, int count) {
302 SkASSERT(count > 0);
303 auto p0 = static_cast<const typename F::Type*>(src);
304 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
305 auto d = static_cast<typename F::Type*>(dst);
306
307 // Given pixels:
308 // a0 b0 c0 d0 e0 ...
309 // a1 b1 c1 d1 e1 ...
310 // We want:
311 // (a0 + 2*b0 + c0 + a1 + 2*b1 + c1) / 8
312 // (c0 + 2*d0 + e0 + c1 + 2*d1 + e1) / 8
313 // ...
314
315 auto c0 = F::Expand(p0[0]);
316 auto c1 = F::Expand(p1[0]);
317 auto c = c0 + c1;
318 for (int i = 0; i < count; ++i) {
319 auto a = c;
320
321 auto b0 = F::Expand(p0[1]);
322 auto b1 = F::Expand(p1[1]);
323 auto b = b0 + b0 + b1 + b1;
324
325 c0 = F::Expand(p0[2]);
326 c1 = F::Expand(p1[2]);
327 c = c0 + c1;
328
329 auto sum = a + b + c;
330 d[i] = F::Compact(shift_right(sum, 3));
331 p0 += 2;
332 p1 += 2;
333 }
334 }
335
downsample_3_3(void * dst,const void * src,size_t srcRB,int count)336 template <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB, int count) {
337 SkASSERT(count > 0);
338 auto p0 = static_cast<const typename F::Type*>(src);
339 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB);
340 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB);
341 auto d = static_cast<typename F::Type*>(dst);
342
343 // Given pixels:
344 // a0 b0 c0 d0 e0 ...
345 // a1 b1 c1 d1 e1 ...
346 // a2 b2 c2 d2 e2 ...
347 // We want:
348 // (a0 + 2*b0 + c0 + 2*a1 + 4*b1 + 2*c1 + a2 + 2*b2 + c2) / 16
349 // (c0 + 2*d0 + e0 + 2*c1 + 4*d1 + 2*e1 + c2 + 2*d2 + e2) / 16
350 // ...
351
352 auto c0 = F::Expand(p0[0]);
353 auto c1 = F::Expand(p1[0]);
354 auto c2 = F::Expand(p2[0]);
355 auto c = add_121(c0, c1, c2);
356 for (int i = 0; i < count; ++i) {
357 auto a = c;
358
359 auto b0 = F::Expand(p0[1]);
360 auto b1 = F::Expand(p1[1]);
361 auto b2 = F::Expand(p2[1]);
362 auto b = shift_left(add_121(b0, b1, b2), 1);
363
364 c0 = F::Expand(p0[2]);
365 c1 = F::Expand(p1[2]);
366 c2 = F::Expand(p2[2]);
367 c = add_121(c0, c1, c2);
368
369 auto sum = a + b + c;
370 d[i] = F::Compact(shift_right(sum, 4));
371 p0 += 2;
372 p1 += 2;
373 p2 += 2;
374 }
375 }
376
377
378 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
379
380 struct HQDownSampler : SkMipmapDownSampler {
381 FilterProc* proc_1_2 = nullptr;
382 FilterProc* proc_1_3 = nullptr;
383 FilterProc* proc_2_1 = nullptr;
384 FilterProc* proc_2_2 = nullptr;
385 FilterProc* proc_2_3 = nullptr;
386 FilterProc* proc_3_1 = nullptr;
387 FilterProc* proc_3_2 = nullptr;
388 FilterProc* proc_3_3 = nullptr;
389
390 void buildLevel(const SkPixmap& dst, const SkPixmap& src) override;
391 };
392
buildLevel(const SkPixmap & dst,const SkPixmap & src)393 void HQDownSampler::buildLevel(const SkPixmap& dst, const SkPixmap& src) {
394 const int width = src.width();
395 const int height = src.height();
396
397 FilterProc* proc;
398 if (height & 1) {
399 if (height == 1) { // src-height is 1
400 if (width & 1) { // src-width is 3
401 proc = proc_3_1;
402 } else { // src-width is 2
403 proc = proc_2_1;
404 }
405 } else { // src-height is 3
406 if (width & 1) {
407 if (width == 1) { // src-width is 1
408 proc = proc_1_3;
409 } else { // src-width is 3
410 proc = proc_3_3;
411 }
412 } else { // src-width is 2
413 proc = proc_2_3;
414 }
415 }
416 } else { // src-height is 2
417 if (width & 1) {
418 if (width == 1) { // src-width is 1
419 proc = proc_1_2;
420 } else { // src-width is 3
421 proc = proc_3_2;
422 }
423 } else { // src-width is 2
424 proc = proc_2_2;
425 }
426 }
427
428 const void* srcBasePtr = src.addr();
429 const size_t srcRB = src.rowBytes();
430 void* dstBasePtr = dst.writable_addr();
431
432 for (int y = 0; y < dst.height(); y++) {
433 proc(dstBasePtr, srcBasePtr, srcRB, dst.width());
434 srcBasePtr = (const char*)srcBasePtr + srcRB * 2; // jump two rows
435 dstBasePtr = ( char*)dstBasePtr + dst.rowBytes();
436 }
437 }
438
439 } // namespace
440
MakeDownSampler(const SkPixmap & root)441 std::unique_ptr<SkMipmapDownSampler> SkMipmap::MakeDownSampler(const SkPixmap& root) {
442 FilterProc* proc_1_2 = nullptr;
443 FilterProc* proc_1_3 = nullptr;
444 FilterProc* proc_2_1 = nullptr;
445 FilterProc* proc_2_2 = nullptr;
446 FilterProc* proc_2_3 = nullptr;
447 FilterProc* proc_3_1 = nullptr;
448 FilterProc* proc_3_2 = nullptr;
449 FilterProc* proc_3_3 = nullptr;
450
451 switch (root.colorType()) {
452 case kRGBA_8888_SkColorType:
453 case kBGRA_8888_SkColorType:
454 proc_1_2 = downsample_1_2<ColorTypeFilter_8888>;
455 proc_1_3 = downsample_1_3<ColorTypeFilter_8888>;
456 proc_2_1 = downsample_2_1<ColorTypeFilter_8888>;
457 proc_2_2 = downsample_2_2<ColorTypeFilter_8888>;
458 proc_2_3 = downsample_2_3<ColorTypeFilter_8888>;
459 proc_3_1 = downsample_3_1<ColorTypeFilter_8888>;
460 proc_3_2 = downsample_3_2<ColorTypeFilter_8888>;
461 proc_3_3 = downsample_3_3<ColorTypeFilter_8888>;
462 break;
463 case kRGB_565_SkColorType:
464 proc_1_2 = downsample_1_2<ColorTypeFilter_565>;
465 proc_1_3 = downsample_1_3<ColorTypeFilter_565>;
466 proc_2_1 = downsample_2_1<ColorTypeFilter_565>;
467 proc_2_2 = downsample_2_2<ColorTypeFilter_565>;
468 proc_2_3 = downsample_2_3<ColorTypeFilter_565>;
469 proc_3_1 = downsample_3_1<ColorTypeFilter_565>;
470 proc_3_2 = downsample_3_2<ColorTypeFilter_565>;
471 proc_3_3 = downsample_3_3<ColorTypeFilter_565>;
472 break;
473 case kARGB_4444_SkColorType:
474 proc_1_2 = downsample_1_2<ColorTypeFilter_4444>;
475 proc_1_3 = downsample_1_3<ColorTypeFilter_4444>;
476 proc_2_1 = downsample_2_1<ColorTypeFilter_4444>;
477 proc_2_2 = downsample_2_2<ColorTypeFilter_4444>;
478 proc_2_3 = downsample_2_3<ColorTypeFilter_4444>;
479 proc_3_1 = downsample_3_1<ColorTypeFilter_4444>;
480 proc_3_2 = downsample_3_2<ColorTypeFilter_4444>;
481 proc_3_3 = downsample_3_3<ColorTypeFilter_4444>;
482 break;
483 case kAlpha_8_SkColorType:
484 case kGray_8_SkColorType:
485 case kR8_unorm_SkColorType:
486 proc_1_2 = downsample_1_2<ColorTypeFilter_8>;
487 proc_1_3 = downsample_1_3<ColorTypeFilter_8>;
488 proc_2_1 = downsample_2_1<ColorTypeFilter_8>;
489 proc_2_2 = downsample_2_2<ColorTypeFilter_8>;
490 proc_2_3 = downsample_2_3<ColorTypeFilter_8>;
491 proc_3_1 = downsample_3_1<ColorTypeFilter_8>;
492 proc_3_2 = downsample_3_2<ColorTypeFilter_8>;
493 proc_3_3 = downsample_3_3<ColorTypeFilter_8>;
494 break;
495 case kRGBA_F16Norm_SkColorType:
496 case kRGBA_F16_SkColorType:
497 proc_1_2 = downsample_1_2<ColorTypeFilter_RGBA_F16>;
498 proc_1_3 = downsample_1_3<ColorTypeFilter_RGBA_F16>;
499 proc_2_1 = downsample_2_1<ColorTypeFilter_RGBA_F16>;
500 proc_2_2 = downsample_2_2<ColorTypeFilter_RGBA_F16>;
501 proc_2_3 = downsample_2_3<ColorTypeFilter_RGBA_F16>;
502 proc_3_1 = downsample_3_1<ColorTypeFilter_RGBA_F16>;
503 proc_3_2 = downsample_3_2<ColorTypeFilter_RGBA_F16>;
504 proc_3_3 = downsample_3_3<ColorTypeFilter_RGBA_F16>;
505 break;
506 case kR8G8_unorm_SkColorType:
507 proc_1_2 = downsample_1_2<ColorTypeFilter_88>;
508 proc_1_3 = downsample_1_3<ColorTypeFilter_88>;
509 proc_2_1 = downsample_2_1<ColorTypeFilter_88>;
510 proc_2_2 = downsample_2_2<ColorTypeFilter_88>;
511 proc_2_3 = downsample_2_3<ColorTypeFilter_88>;
512 proc_3_1 = downsample_3_1<ColorTypeFilter_88>;
513 proc_3_2 = downsample_3_2<ColorTypeFilter_88>;
514 proc_3_3 = downsample_3_3<ColorTypeFilter_88>;
515 break;
516 case kR16G16_unorm_SkColorType:
517 proc_1_2 = downsample_1_2<ColorTypeFilter_1616>;
518 proc_1_3 = downsample_1_3<ColorTypeFilter_1616>;
519 proc_2_1 = downsample_2_1<ColorTypeFilter_1616>;
520 proc_2_2 = downsample_2_2<ColorTypeFilter_1616>;
521 proc_2_3 = downsample_2_3<ColorTypeFilter_1616>;
522 proc_3_1 = downsample_3_1<ColorTypeFilter_1616>;
523 proc_3_2 = downsample_3_2<ColorTypeFilter_1616>;
524 proc_3_3 = downsample_3_3<ColorTypeFilter_1616>;
525 break;
526 case kA16_unorm_SkColorType:
527 proc_1_2 = downsample_1_2<ColorTypeFilter_16>;
528 proc_1_3 = downsample_1_3<ColorTypeFilter_16>;
529 proc_2_1 = downsample_2_1<ColorTypeFilter_16>;
530 proc_2_2 = downsample_2_2<ColorTypeFilter_16>;
531 proc_2_3 = downsample_2_3<ColorTypeFilter_16>;
532 proc_3_1 = downsample_3_1<ColorTypeFilter_16>;
533 proc_3_2 = downsample_3_2<ColorTypeFilter_16>;
534 proc_3_3 = downsample_3_3<ColorTypeFilter_16>;
535 break;
536 case kRGBA_1010102_SkColorType:
537 case kBGRA_1010102_SkColorType:
538 proc_1_2 = downsample_1_2<ColorTypeFilter_1010102>;
539 proc_1_3 = downsample_1_3<ColorTypeFilter_1010102>;
540 proc_2_1 = downsample_2_1<ColorTypeFilter_1010102>;
541 proc_2_2 = downsample_2_2<ColorTypeFilter_1010102>;
542 proc_2_3 = downsample_2_3<ColorTypeFilter_1010102>;
543 proc_3_1 = downsample_3_1<ColorTypeFilter_1010102>;
544 proc_3_2 = downsample_3_2<ColorTypeFilter_1010102>;
545 proc_3_3 = downsample_3_3<ColorTypeFilter_1010102>;
546 break;
547 case kA16_float_SkColorType:
548 proc_1_2 = downsample_1_2<ColorTypeFilter_Alpha_F16>;
549 proc_1_3 = downsample_1_3<ColorTypeFilter_Alpha_F16>;
550 proc_2_1 = downsample_2_1<ColorTypeFilter_Alpha_F16>;
551 proc_2_2 = downsample_2_2<ColorTypeFilter_Alpha_F16>;
552 proc_2_3 = downsample_2_3<ColorTypeFilter_Alpha_F16>;
553 proc_3_1 = downsample_3_1<ColorTypeFilter_Alpha_F16>;
554 proc_3_2 = downsample_3_2<ColorTypeFilter_Alpha_F16>;
555 proc_3_3 = downsample_3_3<ColorTypeFilter_Alpha_F16>;
556 break;
557 case kR16G16_float_SkColorType:
558 proc_1_2 = downsample_1_2<ColorTypeFilter_F16F16>;
559 proc_1_3 = downsample_1_3<ColorTypeFilter_F16F16>;
560 proc_2_1 = downsample_2_1<ColorTypeFilter_F16F16>;
561 proc_2_2 = downsample_2_2<ColorTypeFilter_F16F16>;
562 proc_2_3 = downsample_2_3<ColorTypeFilter_F16F16>;
563 proc_3_1 = downsample_3_1<ColorTypeFilter_F16F16>;
564 proc_3_2 = downsample_3_2<ColorTypeFilter_F16F16>;
565 proc_3_3 = downsample_3_3<ColorTypeFilter_F16F16>;
566 break;
567 case kR16G16B16A16_unorm_SkColorType:
568 proc_1_2 = downsample_1_2<ColorTypeFilter_16161616>;
569 proc_1_3 = downsample_1_3<ColorTypeFilter_16161616>;
570 proc_2_1 = downsample_2_1<ColorTypeFilter_16161616>;
571 proc_2_2 = downsample_2_2<ColorTypeFilter_16161616>;
572 proc_2_3 = downsample_2_3<ColorTypeFilter_16161616>;
573 proc_3_1 = downsample_3_1<ColorTypeFilter_16161616>;
574 proc_3_2 = downsample_3_2<ColorTypeFilter_16161616>;
575 proc_3_3 = downsample_3_3<ColorTypeFilter_16161616>;
576 break;
577
578 case kUnknown_SkColorType:
579 case kRGB_888x_SkColorType: // TODO: use 8888?
580 case kRGB_101010x_SkColorType: // TODO: use 1010102?
581 case kBGR_101010x_SkColorType: // TODO: use 1010102?
582 case kBGR_101010x_XR_SkColorType: // TODO: use 1010102?
583 case kRGB_F16F16F16x_SkColorType: // TODO: use F16?
584 case kBGRA_10101010_XR_SkColorType:
585 case kRGBA_10x6_SkColorType:
586 case kRGBA_F32_SkColorType:
587 return nullptr;
588
589 case kSRGBA_8888_SkColorType: // TODO: needs careful handling
590 return nullptr;
591 }
592
593 auto sampler = std::make_unique<HQDownSampler>();
594 sampler->proc_1_2 = proc_1_2;
595 sampler->proc_1_3 = proc_1_3;
596 sampler->proc_2_1 = proc_2_1;
597 sampler->proc_2_2 = proc_2_2;
598 sampler->proc_2_3 = proc_2_3;
599 sampler->proc_3_1 = proc_3_1;
600 sampler->proc_3_2 = proc_3_2;
601 sampler->proc_3_3 = proc_3_3;
602 return sampler;
603 }
604
605 #endif
606