Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMipmapHQDownSampler.cpp
Go to the documentation of this file.
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
9
10#ifndef SK_USE_DRAWING_MIPMAP_DOWNSAMPLER
11
13#include "src/base/SkHalf.h"
14#include "src/base/SkVx.h"
15#include "src/core/SkMipmap.h"
16
17namespace {
18
19struct ColorTypeFilter_8888 {
20 typedef uint32_t Type;
21 static skvx::Vec<4, uint16_t> Expand(uint32_t x) {
22 return skvx::cast<uint16_t>(skvx::byte4::Load(&x));
23 }
24 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
31struct ColorTypeFilter_565 {
32 typedef uint16_t Type;
33 static uint32_t Expand(uint16_t x) {
34 return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16);
35 }
36 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
41struct ColorTypeFilter_4444 {
42 typedef uint16_t Type;
43 static uint32_t Expand(uint16_t x) {
44 return (x & 0xF0F) | ((x & ~0xF0F) << 12);
45 }
46 static uint16_t Compact(uint32_t x) {
47 return (x & 0xF0F) | ((x >> 12) & ~0xF0F);
48 }
49};
50
51struct ColorTypeFilter_8 {
52 typedef uint8_t Type;
53 static unsigned Expand(unsigned x) {
54 return x;
55 }
56 static uint8_t Compact(unsigned x) {
57 return (uint8_t)x;
58 }
59};
60
61struct ColorTypeFilter_Alpha_F16 {
62 typedef uint16_t Type;
63 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 }
67 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
74struct ColorTypeFilter_RGBA_F16 {
75 typedef uint64_t Type; // SkHalf x4
76 static skvx::float4 Expand(uint64_t x) {
78 }
79 static uint64_t Compact(const skvx::float4& x) {
80 uint64_t r;
81 to_half(x).store(&r);
82 return r;
83 }
84};
85
86struct ColorTypeFilter_88 {
87 typedef uint16_t Type;
88 static uint32_t Expand(uint16_t x) {
89 return (x & 0xFF) | ((x & ~0xFF) << 8);
90 }
91 static uint16_t Compact(uint32_t x) {
92 return (x & 0xFF) | ((x >> 8) & ~0xFF);
93 }
94};
95
96struct ColorTypeFilter_1616 {
97 typedef uint32_t Type;
98 static uint64_t Expand(uint32_t x) {
99 return (x & 0xFFFF) | ((x & ~0xFFFF) << 16);
100 }
101 static uint16_t Compact(uint64_t x) {
102 return (x & 0xFFFF) | ((x >> 16) & ~0xFFFF);
103 }
104};
105
106struct ColorTypeFilter_F16F16 {
107 typedef uint32_t Type;
108 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 }
112 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
119struct ColorTypeFilter_16161616 {
120 typedef uint64_t Type;
121 static skvx::Vec<4, uint32_t> Expand(uint64_t x) {
122 return skvx::cast<uint32_t>(skvx::Vec<4, uint16_t>::Load(&x));
123 }
124 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
131struct ColorTypeFilter_16 {
132 typedef uint16_t Type;
133 static uint32_t Expand(uint16_t x) {
134 return x;
135 }
136 static uint16_t Compact(uint32_t x) {
137 return (uint16_t) x;
138 }
139};
140
141struct ColorTypeFilter_1010102 {
142 typedef uint32_t Type;
143 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 }
149 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
157template <typename T> T add_121(const T& a, const T& b, const T& c) {
158 return a + b + b + c;
159}
160
161template <typename T> T shift_right(const T& x, int bits) {
162 return x >> bits;
163}
164
165skvx::float4 shift_right(const skvx::float4& x, int bits) {
166 return x * (1.0f / (1 << bits));
167}
168
169template <typename T> T shift_left(const T& x, int bits) {
170 return x << bits;
171}
172
173skvx::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
190template <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
207template <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
227template <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
242template <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
261template <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
284template <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
301template <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
336template <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
378typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
379
380struct 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
393void 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
441std::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()) {
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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
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?
586 return nullptr;
587
588 case kSRGBA_8888_SkColorType: // TODO: needs careful handling
589 return nullptr;
590 }
591
592 auto sampler = std::make_unique<HQDownSampler>();
593 sampler->proc_1_2 = proc_1_2;
594 sampler->proc_1_3 = proc_1_3;
595 sampler->proc_2_1 = proc_2_1;
596 sampler->proc_2_2 = proc_2_2;
597 sampler->proc_2_3 = proc_2_3;
598 sampler->proc_3_1 = proc_3_1;
599 sampler->proc_3_2 = proc_3_2;
600 sampler->proc_3_3 = proc_3_3;
601 return sampler;
602}
603
604#endif
int count
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SK_G16_MASK_IN_PLACE
@ kR16G16B16A16_unorm_SkColorType
pixel with a little endian uint16_t for red, green, blue
Definition SkColorType.h:50
@ kRGBA_10x6_SkColorType
pixel with 10 used bits (most significant) followed by 6 unused
Definition SkColorType.h:33
@ kR8_unorm_SkColorType
Definition SkColorType.h:54
@ kBGR_101010x_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word
Definition SkColorType.h:30
@ kARGB_4444_SkColorType
pixel with 4 bits for alpha, red, green, blue; in 16-bit word
Definition SkColorType.h:23
@ kR8G8_unorm_SkColorType
pixel with a uint8_t for red and green
Definition SkColorType.h:43
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kA16_unorm_SkColorType
pixel with a little endian uint16_t for alpha
Definition SkColorType.h:48
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition SkColorType.h:21
@ kRGB_101010x_SkColorType
pixel with 10 bits each for red, green, blue; in 32-bit word
Definition SkColorType.h:29
@ kSRGBA_8888_SkColorType
Definition SkColorType.h:53
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition SkColorType.h:22
@ kBGRA_10101010_XR_SkColorType
pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
Definition SkColorType.h:32
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition SkColorType.h:25
@ kBGRA_1010102_SkColorType
10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:28
@ kA16_float_SkColorType
pixel with a half float for alpha
Definition SkColorType.h:45
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition SkColorType.h:40
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:27
@ kBGR_101010x_XR_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
Definition SkColorType.h:31
@ kR16G16_unorm_SkColorType
pixel with a little endian uint16_t for red and green
Definition SkColorType.h:49
@ kRGBA_F16Norm_SkColorType
pixel with half floats in [0,1] for red, green, blue, alpha;
Definition SkColorType.h:36
@ kUnknown_SkColorType
uninitialized
Definition SkColorType.h:20
@ kR16G16_float_SkColorType
pixel with a half float for red and green
Definition SkColorType.h:46
static std::unique_ptr< SkMipmapDownSampler > MakeDownSampler(const SkPixmap &)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
struct MyStruct a[10]
double y
double x
dst
Definition cp.py:12
SIN Vec< N, float > from_half(const Vec< N, uint16_t > &x)
Definition SkVx.h:790
SIN Vec< N, uint16_t > to_half(const Vec< N, float > &x)
Definition SkVx.h:750
#define T
int32_t height
int32_t width
virtual void buildLevel(const SkPixmap &dst, const SkPixmap &src)=0
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition SkVx.h:109