1 /* Copyright (c) 2020-2022 Hans-Kristian Arntzen
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22 const ivec2 etc1_color_modifier_table[8] = ivec2[](
23 ivec2(2, 8),
24 ivec2(5, 17),
25 ivec2(9, 29),
26 ivec2(13, 42),
27 ivec2(18, 60),
28 ivec2(24, 80),
29 ivec2(33, 106),
30 ivec2(47, 183));
31
32 const ivec4 etc2_alpha_modifier_table[16] = ivec4[](
33 ivec4(2, 5, 8, 14),
34 ivec4(2, 6, 9, 12),
35 ivec4(1, 4, 7, 12),
36 ivec4(1, 3, 5, 12),
37 ivec4(2, 5, 7, 11),
38 ivec4(2, 6, 8, 10),
39 ivec4(3, 6, 7, 10),
40 ivec4(2, 4, 7, 10),
41 ivec4(1, 5, 7, 9),
42 ivec4(1, 4, 7, 9),
43 ivec4(1, 3, 7, 9),
44 ivec4(1, 4, 6, 9),
45 ivec4(2, 3, 6, 9),
46 ivec4(0, 1, 2, 9),
47 ivec4(3, 5, 7, 8),
48 ivec4(2, 4, 6, 8)
49 );
50
51 const int etc2_distance_table[8] = int[](3, 6, 11, 16, 23, 32, 41, 64);
52
decode_etc2_alpha(uvec2 payload,int linear_pixel)53 int decode_etc2_alpha(uvec2 payload, int linear_pixel)
54 {
55 int bit_offset = 45 - 3 * linear_pixel;
56 #if R11
57 int base = isSigned !=0 ? bitfieldExtract(int(payload.y), 24, 8) : int(bitfieldExtract(payload.y, 24, 8));
58 #else
59 int base = int(bitfieldExtract(payload.y, 24, 8));
60 #endif
61 int multiplier = int(bitfieldExtract(payload.y, 20, 4));
62 int table = int(bitfieldExtract(payload.y, 16, 4));
63
64 int lsb_index = int(bitfieldExtract(payload[bit_offset >> 5], bit_offset & 31, 2));
65 bit_offset += 2;
66 int msb = int((payload[bit_offset >> 5] >> (bit_offset & 31)) & 1u);
67 int mod = etc2_alpha_modifier_table[table][lsb_index] ^ (msb - 1);
68 #if R11
69 int a = base * 8 + 4;
70 a += multiplier != 0 ? mod * multiplier * 8 : mod;
71 int minValue = isSigned !=0 ? -1023: 0;
72 int maxValue = isSigned !=0 ? 1023 : 2047;
73 a = clamp(a, minValue, maxValue);
74 float scale = isSigned !=0 ? 127.0f : 255.0f;
75 return int(a/float(maxValue) * scale + 0.5f);
76 #else
77 int a = base + mod * multiplier;
78 return clamp(a, 0, 0xff);
79 #endif
80 }
81
DecodeRGB(ivec2 pixel_coord,uvec2 color_payload,int linear_pixel,inout bool punchthrough)82 ivec4 DecodeRGB(ivec2 pixel_coord, uvec2 color_payload, int linear_pixel, inout bool punchthrough) {
83 int alpha_result = 0xff;
84 ivec3 rgb_result;
85 ivec3 base_rgb;
86 uint flip = color_payload.y & 1u;
87 uint subblock = uint((pixel_coord[flip] & 2) >> 1);
88 bool etc1_compat = false;
89
90 if (alphaBits != 1 && (color_payload.y & 2u) == 0u)
91 {
92 // Individual mode (ETC1)
93 etc1_compat = true;
94 base_rgb = ivec3(color_payload.yyy >> (uvec3(28, 20, 12) - 4u * subblock));
95 base_rgb &= 0xf;
96 base_rgb *= 0x11;
97 }
98 else
99 {
100 int r = int(bitfieldExtract(color_payload.y, 27, 5));
101 int rd = bitfieldExtract(int(color_payload.y), 24, 3);
102 int g = int(bitfieldExtract(color_payload.y, 19, 5));
103 int gd = bitfieldExtract(int(color_payload.y), 16, 3);
104 int b = int(bitfieldExtract(color_payload.y, 11, 5));
105 int bd = bitfieldExtract(int(color_payload.y), 8, 3);
106
107 int r1 = r + rd;
108 int g1 = g + gd;
109 int b1 = b + bd;
110
111 if (uint(r1) > 31u) // T mode
112 {
113 int r1 = int(bitfieldExtract(color_payload.y, 56 - 32, 2)) |
114 (int(bitfieldExtract(color_payload.y, 59 - 32, 2)) << 2);
115 int g1 = int(bitfieldExtract(color_payload.y, 52 - 32, 4));
116 int b1 = int(bitfieldExtract(color_payload.y, 48 - 32, 4));
117 int r2 = int(bitfieldExtract(color_payload.y, 44 - 32, 4));
118 int g2 = int(bitfieldExtract(color_payload.y, 40 - 32, 4));
119 int b2 = int(bitfieldExtract(color_payload.y, 36 - 32, 4));
120 uint da = (bitfieldExtract(color_payload.y, 34 - 32, 2) << 1) |
121 (color_payload.y & 1u);
122 int dist = etc2_distance_table[da];
123
124 int msb = int((color_payload.x >> (15 + linear_pixel)) & 2u);
125 int lsb = int((color_payload.x >> linear_pixel) & 1u);
126 int index = msb | lsb;
127
128 if (punchthrough)
129 punchthrough = index == 2;
130
131 if (index == 0)
132 {
133 rgb_result = ivec3(r1, g1, b1);
134 rgb_result *= 0x11;
135 }
136 else
137 {
138 int mod = 2 - index;
139 ivec3 rgb = ivec3(r2, g2, b2) * 0x11 + mod * dist;
140 rgb_result = ivec3(clamp(rgb, ivec3(0), ivec3(255)));
141 }
142 }
143 else if (uint(g1) > 31u) // H mode
144 {
145 int r1 = int(bitfieldExtract(color_payload.y, 59 - 32, 4));
146 int g1 = (int(bitfieldExtract(color_payload.y, 56 - 32, 3)) << 1) |
147 int((color_payload.y >> 20u) & 1u);
148 int b1 = int(bitfieldExtract(color_payload.y, 47 - 32, 3)) |
149 int((color_payload.y >> 16u) & 8u);
150 int r2 = int(bitfieldExtract(color_payload.y, 43 - 32, 4));
151 int g2 = int(bitfieldExtract(color_payload.y, 39 - 32, 4));
152 int b2 = int(bitfieldExtract(color_payload.y, 35 - 32, 4));
153 uint da = color_payload.y & 4u;
154 uint db = color_payload.y & 1u;
155 uint d = da + 2u * db;
156 d += uint((r1 * 0x10000 + g1 * 0x100 + b1) >= (r2 * 0x10000 + g2 * 0x100 + b2));
157 int dist = etc2_distance_table[d];
158 int msb = int((color_payload.x >> (15 + linear_pixel)) & 2u);
159 int lsb = int((color_payload.x >> linear_pixel) & 1u);
160
161 if (punchthrough)
162 punchthrough = (msb + lsb) == 2;
163
164 ivec3 base = msb != 0 ? ivec3(r2, g2, b2) : ivec3(r1, g1, b1);
165 base *= 0x11;
166 int mod = 1 - 2 * lsb;
167 base += mod * dist;
168 rgb_result = ivec3(clamp(base, ivec3(0), ivec3(0xff)));
169 }
170 else if (uint(b1) > 31u) // plane mode
171 {
172 // Planar mode
173 int r = int(bitfieldExtract(color_payload.y, 57 - 32, 6));
174 int g = int(bitfieldExtract(color_payload.y, 49 - 32, 6)) |
175 (int(color_payload.y >> 18) & 0x40);
176 int b = int(bitfieldExtract(color_payload.y, 39 - 32, 3)) |
177 (int(bitfieldExtract(color_payload.y, 43 - 32, 2)) << 3) |
178 (int(color_payload.y >> 11) & 0x20);
179 int rh = int(color_payload.y & 1u) |
180 (int(bitfieldExtract(color_payload.y, 2, 5)) << 1);
181 int rv = int(bitfieldExtract(color_payload.x, 13, 6));
182 int gh = int(bitfieldExtract(color_payload.x, 25, 7));
183 int gv = int(bitfieldExtract(color_payload.x, 6, 7));
184 int bh = int(bitfieldExtract(color_payload.x, 19, 6));
185 int bv = int(bitfieldExtract(color_payload.x, 0, 6));
186
187 r = (r << 2) | (r >> 4);
188 rh = (rh << 2) | (rh >> 4);
189 rv = (rv << 2) | (rv >> 4);
190 g = (g << 1) | (g >> 6);
191 gh = (gh << 1) | (gh >> 6);
192 gv = (gv << 1) | (gv >> 6);
193 b = (b << 2) | (b >> 4);
194 bh = (bh << 2) | (bh >> 4);
195 bv = (bv << 2) | (bv >> 4);
196
197 ivec3 rgb = ivec3(r, g, b);
198 ivec3 dx = ivec3(rh, gh, bh) - rgb;
199 ivec3 dy = ivec3(rv, gv, bv) - rgb;
200 dx *= int(pixel_coord.x);
201 dy *= int(pixel_coord.y);
202 rgb = rgb + ((dx + dy + 2) >> 2);
203 rgb = clamp(rgb, ivec3(0), ivec3(255));
204 rgb_result = ivec3(rgb);
205
206 punchthrough = false;
207
208 }
209 else // diff mode
210 {
211 // Differential mode (ETC1)
212 etc1_compat = true;
213 base_rgb = ivec3(r, g, b) + int(subblock) * ivec3(rd, gd, bd);
214 base_rgb = (base_rgb << 3) | (base_rgb >> 2);
215 }
216 }
217
218 if (etc1_compat)
219 {
220 uint etc1_table_index = bitfieldExtract(color_payload.y, 5 - 3 * int(subblock != 0u), 3);
221 int msb = int((color_payload.x >> (15 + linear_pixel)) & 2u);
222 int lsb = int((color_payload.x >> linear_pixel) & 1u);
223 int sgn = 1 - msb;
224
225 if (punchthrough)
226 {
227 sgn *= lsb;
228 punchthrough = (msb + lsb) == 2;
229 }
230
231 int offset = etc1_color_modifier_table[etc1_table_index][lsb] * sgn;
232 base_rgb = clamp(base_rgb + offset, ivec3(0), ivec3(255));
233 rgb_result = ivec3(base_rgb);
234 }
235
236 if (alphaBits == 1 && punchthrough)
237 {
238 rgb_result = ivec3(0);
239 alpha_result = 0;
240 }
241
242 return ivec4(rgb_result.r, rgb_result.g, rgb_result.b, alpha_result);
243 }