xref: /aosp_15_r20/external/skia/src/gpu/DitherUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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 "src/gpu/DitherUtils.h"
9 
10 #ifndef SK_IGNORE_GPU_DITHER
11 
12 #include "include/core/SkBitmap.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkImageInfo.h"
15 
16 #include <cstdint>
17 
18 namespace skgpu {
19 
DitherRangeForConfig(SkColorType dstColorType)20 float DitherRangeForConfig(SkColorType dstColorType) {
21     SkASSERT(dstColorType != kUnknown_SkColorType);
22 
23     // We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values
24     switch (dstColorType) {
25         // 4 bit
26         case kARGB_4444_SkColorType:
27             return 1 / 15.f;
28 
29         // 6 bit
30         case kRGB_565_SkColorType:
31             return 1 / 63.f;
32 
33         // 8 bit
34         case kAlpha_8_SkColorType:
35         case kGray_8_SkColorType:
36         case kR8_unorm_SkColorType:
37         case kR8G8_unorm_SkColorType:
38         case kRGB_888x_SkColorType:
39         case kRGBA_8888_SkColorType:
40         case kSRGBA_8888_SkColorType:
41         case kBGRA_8888_SkColorType:
42             return 1 / 255.f;
43 
44         // 10 bit
45         case kRGBA_1010102_SkColorType:
46         case kBGRA_1010102_SkColorType:
47         case kRGB_101010x_SkColorType:
48         case kBGR_101010x_SkColorType:
49         case kBGR_101010x_XR_SkColorType:
50         case kBGRA_10101010_XR_SkColorType:
51         case kRGBA_10x6_SkColorType:
52             return 1 / 1023.f;
53 
54         // 16 bit
55         case kA16_unorm_SkColorType:
56         case kR16G16_unorm_SkColorType:
57         case kR16G16B16A16_unorm_SkColorType:
58             return 1 / 32767.f;
59 
60         // Unknown
61         case kUnknown_SkColorType:
62         // Half
63         case kA16_float_SkColorType:
64         case kR16G16_float_SkColorType:
65         case kRGBA_F16_SkColorType:
66         case kRGB_F16F16F16x_SkColorType:
67         case kRGBA_F16Norm_SkColorType:
68         // Float
69         case kRGBA_F32_SkColorType:
70             return 0.f; // no dithering
71     }
72     SkUNREACHABLE;
73 }
74 
MakeDitherLUT()75 SkBitmap MakeDitherLUT() {
76     static constexpr struct DitherTable {
77         constexpr DitherTable() : data() {
78             constexpr int kImgSize = 8; // if changed, also change value in sk_dither_shader
79 
80             for (int x = 0; x < kImgSize; ++x) {
81                 for (int y = 0; y < kImgSize; ++y) {
82                     // The computation of 'm' and 'value' is lifted from CPU backend.
83                     unsigned int m = (y & 1) << 5 | (x & 1) << 4 |
84                                      (y & 2) << 2 | (x & 2) << 1 |
85                                      (y & 4) >> 1 | (x & 4) >> 2;
86                     float value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
87                     // Bias by 0.5 to be in 0..1, mul by 255 and round to nearest int to make byte.
88                     data[y * 8 + x] = (uint8_t)((value + 0.5) * 255.f + 0.5f);
89                 }
90             }
91         }
92         uint8_t data[64];
93     } gTable;
94 
95     SkBitmap bmp;
96     bmp.setInfo(SkImageInfo::MakeA8(8, 8));
97     bmp.setPixels(const_cast<uint8_t*>(gTable.data));
98     bmp.setImmutable();
99     return bmp;
100 }
101 
102 }  // namespace skgpu
103 
104 #endif // SK_IGNORE_GPU_DITHER
105