1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2015 Philip Taylor <[email protected]>
3*61046927SAndroid Build Coastguard Worker * Copyright 2018 Advanced Micro Devices, Inc.
4*61046927SAndroid Build Coastguard Worker *
5*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*61046927SAndroid Build Coastguard Worker *
12*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
13*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
14*61046927SAndroid Build Coastguard Worker * Software.
15*61046927SAndroid Build Coastguard Worker *
16*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22*61046927SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
23*61046927SAndroid Build Coastguard Worker */
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker /**
26*61046927SAndroid Build Coastguard Worker * \file texcompress_astc.c
27*61046927SAndroid Build Coastguard Worker *
28*61046927SAndroid Build Coastguard Worker * Decompression code for GL_KHR_texture_compression_astc_ldr, which is just
29*61046927SAndroid Build Coastguard Worker * ASTC 2D LDR.
30*61046927SAndroid Build Coastguard Worker *
31*61046927SAndroid Build Coastguard Worker * The ASTC 2D LDR decoder (without the sRGB part) was copied from the OASTC
32*61046927SAndroid Build Coastguard Worker * library written by Philip Taylor. I added sRGB support and adjusted it for
33*61046927SAndroid Build Coastguard Worker * Mesa. - Marek
34*61046927SAndroid Build Coastguard Worker */
35*61046927SAndroid Build Coastguard Worker
36*61046927SAndroid Build Coastguard Worker #include "texcompress_astc.h"
37*61046927SAndroid Build Coastguard Worker #include "macros.h"
38*61046927SAndroid Build Coastguard Worker #include "util/half_float.h"
39*61046927SAndroid Build Coastguard Worker #include <stdio.h>
40*61046927SAndroid Build Coastguard Worker #include <cstdlib> // for abort() on windows
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker static bool VERBOSE_DECODE = false;
43*61046927SAndroid Build Coastguard Worker static bool VERBOSE_WRITE = false;
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker class decode_error
46*61046927SAndroid Build Coastguard Worker {
47*61046927SAndroid Build Coastguard Worker public:
48*61046927SAndroid Build Coastguard Worker enum type {
49*61046927SAndroid Build Coastguard Worker ok,
50*61046927SAndroid Build Coastguard Worker unsupported_hdr_void_extent,
51*61046927SAndroid Build Coastguard Worker reserved_block_mode_1,
52*61046927SAndroid Build Coastguard Worker reserved_block_mode_2,
53*61046927SAndroid Build Coastguard Worker dual_plane_and_too_many_partitions,
54*61046927SAndroid Build Coastguard Worker invalid_range_in_void_extent,
55*61046927SAndroid Build Coastguard Worker weight_grid_exceeds_block_size,
56*61046927SAndroid Build Coastguard Worker invalid_colour_endpoints_size,
57*61046927SAndroid Build Coastguard Worker invalid_colour_endpoints_count,
58*61046927SAndroid Build Coastguard Worker invalid_weight_bits,
59*61046927SAndroid Build Coastguard Worker invalid_num_weights,
60*61046927SAndroid Build Coastguard Worker };
61*61046927SAndroid Build Coastguard Worker };
62*61046927SAndroid Build Coastguard Worker
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker struct cem_range {
65*61046927SAndroid Build Coastguard Worker uint8_t max;
66*61046927SAndroid Build Coastguard Worker uint8_t t, q, b;
67*61046927SAndroid Build Coastguard Worker };
68*61046927SAndroid Build Coastguard Worker
69*61046927SAndroid Build Coastguard Worker /* Based on the Color Unquantization Parameters table,
70*61046927SAndroid Build Coastguard Worker * plus the bit-only representations, sorted by increasing size
71*61046927SAndroid Build Coastguard Worker */
72*61046927SAndroid Build Coastguard Worker static cem_range cem_ranges[] = {
73*61046927SAndroid Build Coastguard Worker { 5, 1, 0, 1 },
74*61046927SAndroid Build Coastguard Worker { 7, 0, 0, 3 },
75*61046927SAndroid Build Coastguard Worker { 9, 0, 1, 1 },
76*61046927SAndroid Build Coastguard Worker { 11, 1, 0, 2 },
77*61046927SAndroid Build Coastguard Worker { 15, 0, 0, 4 },
78*61046927SAndroid Build Coastguard Worker { 19, 0, 1, 2 },
79*61046927SAndroid Build Coastguard Worker { 23, 1, 0, 3 },
80*61046927SAndroid Build Coastguard Worker { 31, 0, 0, 5 },
81*61046927SAndroid Build Coastguard Worker { 39, 0, 1, 3 },
82*61046927SAndroid Build Coastguard Worker { 47, 1, 0, 4 },
83*61046927SAndroid Build Coastguard Worker { 63, 0, 0, 6 },
84*61046927SAndroid Build Coastguard Worker { 79, 0, 1, 4 },
85*61046927SAndroid Build Coastguard Worker { 95, 1, 0, 5 },
86*61046927SAndroid Build Coastguard Worker { 127, 0, 0, 7 },
87*61046927SAndroid Build Coastguard Worker { 159, 0, 1, 5 },
88*61046927SAndroid Build Coastguard Worker { 191, 1, 0, 6 },
89*61046927SAndroid Build Coastguard Worker { 255, 0, 0, 8 },
90*61046927SAndroid Build Coastguard Worker };
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker #define CAT_BITS_2(a, b) ( ((a) << 1) | (b) )
93*61046927SAndroid Build Coastguard Worker #define CAT_BITS_3(a, b, c) ( ((a) << 2) | ((b) << 1) | (c) )
94*61046927SAndroid Build Coastguard Worker #define CAT_BITS_4(a, b, c, d) ( ((a) << 3) | ((b) << 2) | ((c) << 1) | (d) )
95*61046927SAndroid Build Coastguard Worker #define CAT_BITS_5(a, b, c, d, e) ( ((a) << 4) | ((b) << 3) | ((c) << 2) | ((d) << 1) | (e) )
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker /**
98*61046927SAndroid Build Coastguard Worker * Unpack 5n+8 bits from 'in' into 5 output values.
99*61046927SAndroid Build Coastguard Worker * If n <= 4 then T should be uint32_t, else it must be uint64_t.
100*61046927SAndroid Build Coastguard Worker */
101*61046927SAndroid Build Coastguard Worker template <typename T>
unpack_trit_block(int n,T in,uint8_t * out)102*61046927SAndroid Build Coastguard Worker static void unpack_trit_block(int n, T in, uint8_t *out)
103*61046927SAndroid Build Coastguard Worker {
104*61046927SAndroid Build Coastguard Worker assert(n <= 6); /* else output will overflow uint8_t */
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker uint8_t T0 = (in >> (n)) & 0x1;
107*61046927SAndroid Build Coastguard Worker uint8_t T1 = (in >> (n+1)) & 0x1;
108*61046927SAndroid Build Coastguard Worker uint8_t T2 = (in >> (2*n+2)) & 0x1;
109*61046927SAndroid Build Coastguard Worker uint8_t T3 = (in >> (2*n+3)) & 0x1;
110*61046927SAndroid Build Coastguard Worker uint8_t T4 = (in >> (3*n+4)) & 0x1;
111*61046927SAndroid Build Coastguard Worker uint8_t T5 = (in >> (4*n+5)) & 0x1;
112*61046927SAndroid Build Coastguard Worker uint8_t T6 = (in >> (4*n+6)) & 0x1;
113*61046927SAndroid Build Coastguard Worker uint8_t T7 = (in >> (5*n+7)) & 0x1;
114*61046927SAndroid Build Coastguard Worker uint8_t mmask = (1 << n) - 1;
115*61046927SAndroid Build Coastguard Worker uint8_t m0 = (in >> (0)) & mmask;
116*61046927SAndroid Build Coastguard Worker uint8_t m1 = (in >> (n+2)) & mmask;
117*61046927SAndroid Build Coastguard Worker uint8_t m2 = (in >> (2*n+4)) & mmask;
118*61046927SAndroid Build Coastguard Worker uint8_t m3 = (in >> (3*n+5)) & mmask;
119*61046927SAndroid Build Coastguard Worker uint8_t m4 = (in >> (4*n+7)) & mmask;
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker uint8_t C;
122*61046927SAndroid Build Coastguard Worker uint8_t t4, t3, t2, t1, t0;
123*61046927SAndroid Build Coastguard Worker if (CAT_BITS_3(T4, T3, T2) == 0x7) {
124*61046927SAndroid Build Coastguard Worker C = CAT_BITS_5(T7, T6, T5, T1, T0);
125*61046927SAndroid Build Coastguard Worker t4 = t3 = 2;
126*61046927SAndroid Build Coastguard Worker } else {
127*61046927SAndroid Build Coastguard Worker C = CAT_BITS_5(T4, T3, T2, T1, T0);
128*61046927SAndroid Build Coastguard Worker if (CAT_BITS_2(T6, T5) == 0x3) {
129*61046927SAndroid Build Coastguard Worker t4 = 2;
130*61046927SAndroid Build Coastguard Worker t3 = T7;
131*61046927SAndroid Build Coastguard Worker } else {
132*61046927SAndroid Build Coastguard Worker t4 = T7;
133*61046927SAndroid Build Coastguard Worker t3 = CAT_BITS_2(T6, T5);
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker if ((C & 0x3) == 0x3) {
138*61046927SAndroid Build Coastguard Worker t2 = 2;
139*61046927SAndroid Build Coastguard Worker t1 = (C >> 4) & 0x1;
140*61046927SAndroid Build Coastguard Worker uint8_t C3 = (C >> 3) & 0x1;
141*61046927SAndroid Build Coastguard Worker uint8_t C2 = (C >> 2) & 0x1;
142*61046927SAndroid Build Coastguard Worker t0 = (C3 << 1) | (C2 & ~C3);
143*61046927SAndroid Build Coastguard Worker } else if (((C >> 2) & 0x3) == 0x3) {
144*61046927SAndroid Build Coastguard Worker t2 = 2;
145*61046927SAndroid Build Coastguard Worker t1 = 2;
146*61046927SAndroid Build Coastguard Worker t0 = C & 0x3;
147*61046927SAndroid Build Coastguard Worker } else {
148*61046927SAndroid Build Coastguard Worker t2 = (C >> 4) & 0x1;
149*61046927SAndroid Build Coastguard Worker t1 = (C >> 2) & 0x3;
150*61046927SAndroid Build Coastguard Worker uint8_t C1 = (C >> 1) & 0x1;
151*61046927SAndroid Build Coastguard Worker uint8_t C0 = (C >> 0) & 0x1;
152*61046927SAndroid Build Coastguard Worker t0 = (C1 << 1) | (C0 & ~C1);
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker out[0] = (t0 << n) | m0;
156*61046927SAndroid Build Coastguard Worker out[1] = (t1 << n) | m1;
157*61046927SAndroid Build Coastguard Worker out[2] = (t2 << n) | m2;
158*61046927SAndroid Build Coastguard Worker out[3] = (t3 << n) | m3;
159*61046927SAndroid Build Coastguard Worker out[4] = (t4 << n) | m4;
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker /**
163*61046927SAndroid Build Coastguard Worker * Unpack 3n+7 bits from 'in' into 3 output values
164*61046927SAndroid Build Coastguard Worker */
unpack_quint_block(int n,uint32_t in,uint8_t * out)165*61046927SAndroid Build Coastguard Worker static void unpack_quint_block(int n, uint32_t in, uint8_t *out)
166*61046927SAndroid Build Coastguard Worker {
167*61046927SAndroid Build Coastguard Worker assert(n <= 5); /* else output will overflow uint8_t */
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker uint8_t Q0 = (in >> (n)) & 0x1;
170*61046927SAndroid Build Coastguard Worker uint8_t Q1 = (in >> (n+1)) & 0x1;
171*61046927SAndroid Build Coastguard Worker uint8_t Q2 = (in >> (n+2)) & 0x1;
172*61046927SAndroid Build Coastguard Worker uint8_t Q3 = (in >> (2*n+3)) & 0x1;
173*61046927SAndroid Build Coastguard Worker uint8_t Q4 = (in >> (2*n+4)) & 0x1;
174*61046927SAndroid Build Coastguard Worker uint8_t Q5 = (in >> (3*n+5)) & 0x1;
175*61046927SAndroid Build Coastguard Worker uint8_t Q6 = (in >> (3*n+6)) & 0x1;
176*61046927SAndroid Build Coastguard Worker uint8_t mmask = (1 << n) - 1;
177*61046927SAndroid Build Coastguard Worker uint8_t m0 = (in >> (0)) & mmask;
178*61046927SAndroid Build Coastguard Worker uint8_t m1 = (in >> (n+3)) & mmask;
179*61046927SAndroid Build Coastguard Worker uint8_t m2 = (in >> (2*n+5)) & mmask;
180*61046927SAndroid Build Coastguard Worker
181*61046927SAndroid Build Coastguard Worker uint8_t C;
182*61046927SAndroid Build Coastguard Worker uint8_t q2, q1, q0;
183*61046927SAndroid Build Coastguard Worker if (CAT_BITS_4(Q6, Q5, Q2, Q1) == 0x3) {
184*61046927SAndroid Build Coastguard Worker q2 = CAT_BITS_3(Q0, Q4 & ~Q0, Q3 & ~Q0);
185*61046927SAndroid Build Coastguard Worker q1 = 4;
186*61046927SAndroid Build Coastguard Worker q0 = 4;
187*61046927SAndroid Build Coastguard Worker } else {
188*61046927SAndroid Build Coastguard Worker if (CAT_BITS_2(Q2, Q1) == 0x3) {
189*61046927SAndroid Build Coastguard Worker q2 = 4;
190*61046927SAndroid Build Coastguard Worker C = CAT_BITS_5(Q4, Q3, 0x1 & ~Q6, 0x1 & ~Q5, Q0);
191*61046927SAndroid Build Coastguard Worker } else {
192*61046927SAndroid Build Coastguard Worker q2 = CAT_BITS_2(Q6, Q5);
193*61046927SAndroid Build Coastguard Worker C = CAT_BITS_5(Q4, Q3, Q2, Q1, Q0);
194*61046927SAndroid Build Coastguard Worker }
195*61046927SAndroid Build Coastguard Worker if ((C & 0x7) == 0x5) {
196*61046927SAndroid Build Coastguard Worker q1 = 4;
197*61046927SAndroid Build Coastguard Worker q0 = (C >> 3) & 0x3;
198*61046927SAndroid Build Coastguard Worker } else {
199*61046927SAndroid Build Coastguard Worker q1 = (C >> 3) & 0x3;
200*61046927SAndroid Build Coastguard Worker q0 = C & 0x7;
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker }
203*61046927SAndroid Build Coastguard Worker out[0] = (q0 << n) | m0;
204*61046927SAndroid Build Coastguard Worker out[1] = (q1 << n) | m1;
205*61046927SAndroid Build Coastguard Worker out[2] = (q2 << n) | m2;
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker struct uint8x4_t
210*61046927SAndroid Build Coastguard Worker {
211*61046927SAndroid Build Coastguard Worker uint8_t v[4];
212*61046927SAndroid Build Coastguard Worker
uint8x4_tuint8x4_t213*61046927SAndroid Build Coastguard Worker uint8x4_t() { }
214*61046927SAndroid Build Coastguard Worker
uint8x4_tuint8x4_t215*61046927SAndroid Build Coastguard Worker uint8x4_t(int a, int b, int c, int d)
216*61046927SAndroid Build Coastguard Worker {
217*61046927SAndroid Build Coastguard Worker assert(0 <= a && a <= 255);
218*61046927SAndroid Build Coastguard Worker assert(0 <= b && b <= 255);
219*61046927SAndroid Build Coastguard Worker assert(0 <= c && c <= 255);
220*61046927SAndroid Build Coastguard Worker assert(0 <= d && d <= 255);
221*61046927SAndroid Build Coastguard Worker v[0] = a;
222*61046927SAndroid Build Coastguard Worker v[1] = b;
223*61046927SAndroid Build Coastguard Worker v[2] = c;
224*61046927SAndroid Build Coastguard Worker v[3] = d;
225*61046927SAndroid Build Coastguard Worker }
226*61046927SAndroid Build Coastguard Worker
clampeduint8x4_t227*61046927SAndroid Build Coastguard Worker static uint8x4_t clamped(int a, int b, int c, int d)
228*61046927SAndroid Build Coastguard Worker {
229*61046927SAndroid Build Coastguard Worker uint8x4_t r;
230*61046927SAndroid Build Coastguard Worker r.v[0] = MAX2(0, MIN2(255, a));
231*61046927SAndroid Build Coastguard Worker r.v[1] = MAX2(0, MIN2(255, b));
232*61046927SAndroid Build Coastguard Worker r.v[2] = MAX2(0, MIN2(255, c));
233*61046927SAndroid Build Coastguard Worker r.v[3] = MAX2(0, MIN2(255, d));
234*61046927SAndroid Build Coastguard Worker return r;
235*61046927SAndroid Build Coastguard Worker }
236*61046927SAndroid Build Coastguard Worker };
237*61046927SAndroid Build Coastguard Worker
blue_contract(int r,int g,int b,int a)238*61046927SAndroid Build Coastguard Worker static uint8x4_t blue_contract(int r, int g, int b, int a)
239*61046927SAndroid Build Coastguard Worker {
240*61046927SAndroid Build Coastguard Worker return uint8x4_t((r+b) >> 1, (g+b) >> 1, b, a);
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker
blue_contract_clamped(int r,int g,int b,int a)243*61046927SAndroid Build Coastguard Worker static uint8x4_t blue_contract_clamped(int r, int g, int b, int a)
244*61046927SAndroid Build Coastguard Worker {
245*61046927SAndroid Build Coastguard Worker return uint8x4_t::clamped((r+b) >> 1, (g+b) >> 1, b, a);
246*61046927SAndroid Build Coastguard Worker }
247*61046927SAndroid Build Coastguard Worker
bit_transfer_signed(int & a,int & b)248*61046927SAndroid Build Coastguard Worker static void bit_transfer_signed(int &a, int &b)
249*61046927SAndroid Build Coastguard Worker {
250*61046927SAndroid Build Coastguard Worker b >>= 1;
251*61046927SAndroid Build Coastguard Worker b |= a & 0x80;
252*61046927SAndroid Build Coastguard Worker a >>= 1;
253*61046927SAndroid Build Coastguard Worker a &= 0x3f;
254*61046927SAndroid Build Coastguard Worker if (a & 0x20)
255*61046927SAndroid Build Coastguard Worker a -= 0x40;
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker
hash52(uint32_t p)258*61046927SAndroid Build Coastguard Worker static uint32_t hash52(uint32_t p)
259*61046927SAndroid Build Coastguard Worker {
260*61046927SAndroid Build Coastguard Worker p ^= p >> 15;
261*61046927SAndroid Build Coastguard Worker p -= p << 17;
262*61046927SAndroid Build Coastguard Worker p += p << 7;
263*61046927SAndroid Build Coastguard Worker p += p << 4;
264*61046927SAndroid Build Coastguard Worker p ^= p >> 5;
265*61046927SAndroid Build Coastguard Worker p += p << 16;
266*61046927SAndroid Build Coastguard Worker p ^= p >> 7;
267*61046927SAndroid Build Coastguard Worker p ^= p >> 3;
268*61046927SAndroid Build Coastguard Worker p ^= p << 6;
269*61046927SAndroid Build Coastguard Worker p ^= p >> 17;
270*61046927SAndroid Build Coastguard Worker return p;
271*61046927SAndroid Build Coastguard Worker }
272*61046927SAndroid Build Coastguard Worker
select_partition(int seed,int x,int y,int z,int partitioncount,int small_block)273*61046927SAndroid Build Coastguard Worker static int select_partition(int seed, int x, int y, int z, int partitioncount,
274*61046927SAndroid Build Coastguard Worker int small_block)
275*61046927SAndroid Build Coastguard Worker {
276*61046927SAndroid Build Coastguard Worker if (small_block) {
277*61046927SAndroid Build Coastguard Worker x <<= 1;
278*61046927SAndroid Build Coastguard Worker y <<= 1;
279*61046927SAndroid Build Coastguard Worker z <<= 1;
280*61046927SAndroid Build Coastguard Worker }
281*61046927SAndroid Build Coastguard Worker seed += (partitioncount - 1) * 1024;
282*61046927SAndroid Build Coastguard Worker uint32_t rnum = hash52(seed);
283*61046927SAndroid Build Coastguard Worker uint8_t seed1 = rnum & 0xF;
284*61046927SAndroid Build Coastguard Worker uint8_t seed2 = (rnum >> 4) & 0xF;
285*61046927SAndroid Build Coastguard Worker uint8_t seed3 = (rnum >> 8) & 0xF;
286*61046927SAndroid Build Coastguard Worker uint8_t seed4 = (rnum >> 12) & 0xF;
287*61046927SAndroid Build Coastguard Worker uint8_t seed5 = (rnum >> 16) & 0xF;
288*61046927SAndroid Build Coastguard Worker uint8_t seed6 = (rnum >> 20) & 0xF;
289*61046927SAndroid Build Coastguard Worker uint8_t seed7 = (rnum >> 24) & 0xF;
290*61046927SAndroid Build Coastguard Worker uint8_t seed8 = (rnum >> 28) & 0xF;
291*61046927SAndroid Build Coastguard Worker uint8_t seed9 = (rnum >> 18) & 0xF;
292*61046927SAndroid Build Coastguard Worker uint8_t seed10 = (rnum >> 22) & 0xF;
293*61046927SAndroid Build Coastguard Worker uint8_t seed11 = (rnum >> 26) & 0xF;
294*61046927SAndroid Build Coastguard Worker uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF;
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker seed1 *= seed1;
297*61046927SAndroid Build Coastguard Worker seed2 *= seed2;
298*61046927SAndroid Build Coastguard Worker seed3 *= seed3;
299*61046927SAndroid Build Coastguard Worker seed4 *= seed4;
300*61046927SAndroid Build Coastguard Worker seed5 *= seed5;
301*61046927SAndroid Build Coastguard Worker seed6 *= seed6;
302*61046927SAndroid Build Coastguard Worker seed7 *= seed7;
303*61046927SAndroid Build Coastguard Worker seed8 *= seed8;
304*61046927SAndroid Build Coastguard Worker seed9 *= seed9;
305*61046927SAndroid Build Coastguard Worker seed10 *= seed10;
306*61046927SAndroid Build Coastguard Worker seed11 *= seed11;
307*61046927SAndroid Build Coastguard Worker seed12 *= seed12;
308*61046927SAndroid Build Coastguard Worker
309*61046927SAndroid Build Coastguard Worker int sh1, sh2, sh3;
310*61046927SAndroid Build Coastguard Worker if (seed & 1) {
311*61046927SAndroid Build Coastguard Worker sh1 = (seed & 2 ? 4 : 5);
312*61046927SAndroid Build Coastguard Worker sh2 = (partitioncount == 3 ? 6 : 5);
313*61046927SAndroid Build Coastguard Worker } else {
314*61046927SAndroid Build Coastguard Worker sh1 = (partitioncount == 3 ? 6 : 5);
315*61046927SAndroid Build Coastguard Worker sh2 = (seed & 2 ? 4 : 5);
316*61046927SAndroid Build Coastguard Worker }
317*61046927SAndroid Build Coastguard Worker sh3 = (seed & 0x10) ? sh1 : sh2;
318*61046927SAndroid Build Coastguard Worker
319*61046927SAndroid Build Coastguard Worker seed1 >>= sh1;
320*61046927SAndroid Build Coastguard Worker seed2 >>= sh2;
321*61046927SAndroid Build Coastguard Worker seed3 >>= sh1;
322*61046927SAndroid Build Coastguard Worker seed4 >>= sh2;
323*61046927SAndroid Build Coastguard Worker seed5 >>= sh1;
324*61046927SAndroid Build Coastguard Worker seed6 >>= sh2;
325*61046927SAndroid Build Coastguard Worker seed7 >>= sh1;
326*61046927SAndroid Build Coastguard Worker seed8 >>= sh2;
327*61046927SAndroid Build Coastguard Worker seed9 >>= sh3;
328*61046927SAndroid Build Coastguard Worker seed10 >>= sh3;
329*61046927SAndroid Build Coastguard Worker seed11 >>= sh3;
330*61046927SAndroid Build Coastguard Worker seed12 >>= sh3;
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
333*61046927SAndroid Build Coastguard Worker int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
334*61046927SAndroid Build Coastguard Worker int c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
335*61046927SAndroid Build Coastguard Worker int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
336*61046927SAndroid Build Coastguard Worker
337*61046927SAndroid Build Coastguard Worker a &= 0x3F;
338*61046927SAndroid Build Coastguard Worker b &= 0x3F;
339*61046927SAndroid Build Coastguard Worker c &= 0x3F;
340*61046927SAndroid Build Coastguard Worker d &= 0x3F;
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Worker if (partitioncount < 4)
343*61046927SAndroid Build Coastguard Worker d = 0;
344*61046927SAndroid Build Coastguard Worker if (partitioncount < 3)
345*61046927SAndroid Build Coastguard Worker c = 0;
346*61046927SAndroid Build Coastguard Worker
347*61046927SAndroid Build Coastguard Worker if (a >= b && a >= c && a >= d)
348*61046927SAndroid Build Coastguard Worker return 0;
349*61046927SAndroid Build Coastguard Worker else if (b >= c && b >= d)
350*61046927SAndroid Build Coastguard Worker return 1;
351*61046927SAndroid Build Coastguard Worker else if (c >= d)
352*61046927SAndroid Build Coastguard Worker return 2;
353*61046927SAndroid Build Coastguard Worker else
354*61046927SAndroid Build Coastguard Worker return 3;
355*61046927SAndroid Build Coastguard Worker }
356*61046927SAndroid Build Coastguard Worker
357*61046927SAndroid Build Coastguard Worker
358*61046927SAndroid Build Coastguard Worker struct InputBitVector
359*61046927SAndroid Build Coastguard Worker {
360*61046927SAndroid Build Coastguard Worker uint32_t data[4];
361*61046927SAndroid Build Coastguard Worker
printf_bitsInputBitVector362*61046927SAndroid Build Coastguard Worker void printf_bits(int offset, int count, const char *fmt = "", ...)
363*61046927SAndroid Build Coastguard Worker {
364*61046927SAndroid Build Coastguard Worker char out[129];
365*61046927SAndroid Build Coastguard Worker memset(out, '.', 128);
366*61046927SAndroid Build Coastguard Worker out[128] = '\0';
367*61046927SAndroid Build Coastguard Worker int idx = offset;
368*61046927SAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
369*61046927SAndroid Build Coastguard Worker out[127 - idx] = ((data[idx >> 5] >> (idx & 31)) & 1) ? '1' : '0';
370*61046927SAndroid Build Coastguard Worker ++idx;
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker printf("%s ", out);
373*61046927SAndroid Build Coastguard Worker va_list ap;
374*61046927SAndroid Build Coastguard Worker va_start(ap, fmt);
375*61046927SAndroid Build Coastguard Worker vprintf(fmt, ap);
376*61046927SAndroid Build Coastguard Worker va_end(ap);
377*61046927SAndroid Build Coastguard Worker printf("\n");
378*61046927SAndroid Build Coastguard Worker }
379*61046927SAndroid Build Coastguard Worker
get_bitsInputBitVector380*61046927SAndroid Build Coastguard Worker uint32_t get_bits(int offset, int count)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker assert(count >= 0 && count < 32);
383*61046927SAndroid Build Coastguard Worker
384*61046927SAndroid Build Coastguard Worker uint32_t out = 0;
385*61046927SAndroid Build Coastguard Worker if (offset < 32)
386*61046927SAndroid Build Coastguard Worker out |= data[0] >> offset;
387*61046927SAndroid Build Coastguard Worker
388*61046927SAndroid Build Coastguard Worker if (0 < offset && offset <= 32)
389*61046927SAndroid Build Coastguard Worker out |= data[1] << (32 - offset);
390*61046927SAndroid Build Coastguard Worker if (32 < offset && offset < 64)
391*61046927SAndroid Build Coastguard Worker out |= data[1] >> (offset - 32);
392*61046927SAndroid Build Coastguard Worker
393*61046927SAndroid Build Coastguard Worker if (32 < offset && offset <= 64)
394*61046927SAndroid Build Coastguard Worker out |= data[2] << (64 - offset);
395*61046927SAndroid Build Coastguard Worker if (64 < offset && offset < 96)
396*61046927SAndroid Build Coastguard Worker out |= data[2] >> (offset - 64);
397*61046927SAndroid Build Coastguard Worker
398*61046927SAndroid Build Coastguard Worker if (64 < offset && offset <= 96)
399*61046927SAndroid Build Coastguard Worker out |= data[3] << (96 - offset);
400*61046927SAndroid Build Coastguard Worker if (96 < offset && offset < 128)
401*61046927SAndroid Build Coastguard Worker out |= data[3] >> (offset - 96);
402*61046927SAndroid Build Coastguard Worker
403*61046927SAndroid Build Coastguard Worker out &= (1 << count) - 1;
404*61046927SAndroid Build Coastguard Worker return out;
405*61046927SAndroid Build Coastguard Worker }
406*61046927SAndroid Build Coastguard Worker
get_bits64InputBitVector407*61046927SAndroid Build Coastguard Worker uint64_t get_bits64(int offset, int count)
408*61046927SAndroid Build Coastguard Worker {
409*61046927SAndroid Build Coastguard Worker assert(count >= 0 && count < 64);
410*61046927SAndroid Build Coastguard Worker
411*61046927SAndroid Build Coastguard Worker uint64_t out = 0;
412*61046927SAndroid Build Coastguard Worker if (offset < 32)
413*61046927SAndroid Build Coastguard Worker out |= data[0] >> offset;
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker if (offset <= 32)
416*61046927SAndroid Build Coastguard Worker out |= (uint64_t)data[1] << (32 - offset);
417*61046927SAndroid Build Coastguard Worker if (32 < offset && offset < 64)
418*61046927SAndroid Build Coastguard Worker out |= data[1] >> (offset - 32);
419*61046927SAndroid Build Coastguard Worker
420*61046927SAndroid Build Coastguard Worker if (0 < offset && offset <= 64)
421*61046927SAndroid Build Coastguard Worker out |= (uint64_t)data[2] << (64 - offset);
422*61046927SAndroid Build Coastguard Worker if (64 < offset && offset < 96)
423*61046927SAndroid Build Coastguard Worker out |= data[2] >> (offset - 64);
424*61046927SAndroid Build Coastguard Worker
425*61046927SAndroid Build Coastguard Worker if (32 < offset && offset <= 96)
426*61046927SAndroid Build Coastguard Worker out |= (uint64_t)data[3] << (96 - offset);
427*61046927SAndroid Build Coastguard Worker if (96 < offset && offset < 128)
428*61046927SAndroid Build Coastguard Worker out |= data[3] >> (offset - 96);
429*61046927SAndroid Build Coastguard Worker
430*61046927SAndroid Build Coastguard Worker out &= ((uint64_t)1 << count) - 1;
431*61046927SAndroid Build Coastguard Worker return out;
432*61046927SAndroid Build Coastguard Worker }
433*61046927SAndroid Build Coastguard Worker
get_bits_revInputBitVector434*61046927SAndroid Build Coastguard Worker uint32_t get_bits_rev(int offset, int count)
435*61046927SAndroid Build Coastguard Worker {
436*61046927SAndroid Build Coastguard Worker assert(offset >= count);
437*61046927SAndroid Build Coastguard Worker uint32_t tmp = get_bits(offset - count, count);
438*61046927SAndroid Build Coastguard Worker uint32_t out = 0;
439*61046927SAndroid Build Coastguard Worker for (int i = 0; i < count; ++i)
440*61046927SAndroid Build Coastguard Worker out |= ((tmp >> i) & 1) << (count - 1 - i);
441*61046927SAndroid Build Coastguard Worker return out;
442*61046927SAndroid Build Coastguard Worker }
443*61046927SAndroid Build Coastguard Worker };
444*61046927SAndroid Build Coastguard Worker
445*61046927SAndroid Build Coastguard Worker struct OutputBitVector
446*61046927SAndroid Build Coastguard Worker {
447*61046927SAndroid Build Coastguard Worker uint32_t data[4];
448*61046927SAndroid Build Coastguard Worker int offset;
449*61046927SAndroid Build Coastguard Worker
OutputBitVectorOutputBitVector450*61046927SAndroid Build Coastguard Worker OutputBitVector()
451*61046927SAndroid Build Coastguard Worker : offset(0)
452*61046927SAndroid Build Coastguard Worker {
453*61046927SAndroid Build Coastguard Worker memset(data, 0, sizeof(data));
454*61046927SAndroid Build Coastguard Worker }
455*61046927SAndroid Build Coastguard Worker
appendOutputBitVector456*61046927SAndroid Build Coastguard Worker void append(uint32_t value, int size)
457*61046927SAndroid Build Coastguard Worker {
458*61046927SAndroid Build Coastguard Worker if (VERBOSE_WRITE)
459*61046927SAndroid Build Coastguard Worker printf("append offset=%d size=%d values=0x%x\n", offset, size, value);
460*61046927SAndroid Build Coastguard Worker
461*61046927SAndroid Build Coastguard Worker assert(offset + size <= 128);
462*61046927SAndroid Build Coastguard Worker
463*61046927SAndroid Build Coastguard Worker assert(size <= 32);
464*61046927SAndroid Build Coastguard Worker if (size < 32)
465*61046927SAndroid Build Coastguard Worker assert((value >> size) == 0);
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker while (size) {
468*61046927SAndroid Build Coastguard Worker int c = MIN2(size, 32 - (offset & 31));
469*61046927SAndroid Build Coastguard Worker data[offset >> 5] |= (value << (offset & 31));
470*61046927SAndroid Build Coastguard Worker offset += c;
471*61046927SAndroid Build Coastguard Worker size -= c;
472*61046927SAndroid Build Coastguard Worker value >>= c;
473*61046927SAndroid Build Coastguard Worker }
474*61046927SAndroid Build Coastguard Worker }
475*61046927SAndroid Build Coastguard Worker
append64OutputBitVector476*61046927SAndroid Build Coastguard Worker void append64(uint64_t value, int size)
477*61046927SAndroid Build Coastguard Worker {
478*61046927SAndroid Build Coastguard Worker if (VERBOSE_WRITE)
479*61046927SAndroid Build Coastguard Worker printf("append offset=%d size=%d values=0x%llx\n", offset, size, (unsigned long long)value);
480*61046927SAndroid Build Coastguard Worker
481*61046927SAndroid Build Coastguard Worker assert(offset + size <= 128);
482*61046927SAndroid Build Coastguard Worker
483*61046927SAndroid Build Coastguard Worker assert(size <= 64);
484*61046927SAndroid Build Coastguard Worker if (size < 64)
485*61046927SAndroid Build Coastguard Worker assert((value >> size) == 0);
486*61046927SAndroid Build Coastguard Worker
487*61046927SAndroid Build Coastguard Worker while (size) {
488*61046927SAndroid Build Coastguard Worker int c = MIN2(size, 32 - (offset & 31));
489*61046927SAndroid Build Coastguard Worker data[offset >> 5] |= (value << (offset & 31));
490*61046927SAndroid Build Coastguard Worker offset += c;
491*61046927SAndroid Build Coastguard Worker size -= c;
492*61046927SAndroid Build Coastguard Worker value >>= c;
493*61046927SAndroid Build Coastguard Worker }
494*61046927SAndroid Build Coastguard Worker }
495*61046927SAndroid Build Coastguard Worker
appendOutputBitVector496*61046927SAndroid Build Coastguard Worker void append(OutputBitVector &v, int size)
497*61046927SAndroid Build Coastguard Worker {
498*61046927SAndroid Build Coastguard Worker if (VERBOSE_WRITE)
499*61046927SAndroid Build Coastguard Worker printf("append vector offset=%d size=%d\n", offset, size);
500*61046927SAndroid Build Coastguard Worker
501*61046927SAndroid Build Coastguard Worker assert(offset + size <= 128);
502*61046927SAndroid Build Coastguard Worker int i = 0;
503*61046927SAndroid Build Coastguard Worker while (size >= 32) {
504*61046927SAndroid Build Coastguard Worker append(v.data[i++], 32);
505*61046927SAndroid Build Coastguard Worker size -= 32;
506*61046927SAndroid Build Coastguard Worker }
507*61046927SAndroid Build Coastguard Worker if (size > 0)
508*61046927SAndroid Build Coastguard Worker append(v.data[i] & ((1 << size) - 1), size);
509*61046927SAndroid Build Coastguard Worker }
510*61046927SAndroid Build Coastguard Worker
append_endOutputBitVector511*61046927SAndroid Build Coastguard Worker void append_end(OutputBitVector &v, int size)
512*61046927SAndroid Build Coastguard Worker {
513*61046927SAndroid Build Coastguard Worker for (int i = 0; i < size; ++i)
514*61046927SAndroid Build Coastguard Worker data[(127 - i) >> 5] |= ((v.data[i >> 5] >> (i & 31)) & 1) << ((127 - i) & 31);
515*61046927SAndroid Build Coastguard Worker }
516*61046927SAndroid Build Coastguard Worker
517*61046927SAndroid Build Coastguard Worker /* Insert the given number of '1' bits. (We could use 0s instead, but 1s are
518*61046927SAndroid Build Coastguard Worker * more likely to flush out bugs where we accidentally read undefined bits.)
519*61046927SAndroid Build Coastguard Worker */
skipOutputBitVector520*61046927SAndroid Build Coastguard Worker void skip(int size)
521*61046927SAndroid Build Coastguard Worker {
522*61046927SAndroid Build Coastguard Worker if (VERBOSE_WRITE)
523*61046927SAndroid Build Coastguard Worker printf("skip offset=%d size=%d\n", offset, size);
524*61046927SAndroid Build Coastguard Worker
525*61046927SAndroid Build Coastguard Worker assert(offset + size <= 128);
526*61046927SAndroid Build Coastguard Worker while (size >= 32) {
527*61046927SAndroid Build Coastguard Worker append(0xffffffff, 32);
528*61046927SAndroid Build Coastguard Worker size -= 32;
529*61046927SAndroid Build Coastguard Worker }
530*61046927SAndroid Build Coastguard Worker if (size > 0)
531*61046927SAndroid Build Coastguard Worker append(0xffffffff >> (32 - size), size);
532*61046927SAndroid Build Coastguard Worker }
533*61046927SAndroid Build Coastguard Worker };
534*61046927SAndroid Build Coastguard Worker
535*61046927SAndroid Build Coastguard Worker
536*61046927SAndroid Build Coastguard Worker class Decoder
537*61046927SAndroid Build Coastguard Worker {
538*61046927SAndroid Build Coastguard Worker public:
Decoder(int block_w,int block_h,int block_d,bool srgb,bool output_unorm8)539*61046927SAndroid Build Coastguard Worker Decoder(int block_w, int block_h, int block_d, bool srgb, bool output_unorm8)
540*61046927SAndroid Build Coastguard Worker : block_w(block_w), block_h(block_h), block_d(block_d), srgb(srgb),
541*61046927SAndroid Build Coastguard Worker output_unorm8(output_unorm8) {}
542*61046927SAndroid Build Coastguard Worker
543*61046927SAndroid Build Coastguard Worker decode_error::type decode(const uint8_t *in, uint16_t *output) const;
544*61046927SAndroid Build Coastguard Worker
545*61046927SAndroid Build Coastguard Worker int block_w, block_h, block_d;
546*61046927SAndroid Build Coastguard Worker bool srgb, output_unorm8;
547*61046927SAndroid Build Coastguard Worker };
548*61046927SAndroid Build Coastguard Worker
549*61046927SAndroid Build Coastguard Worker struct Block
550*61046927SAndroid Build Coastguard Worker {
551*61046927SAndroid Build Coastguard Worker bool is_error;
552*61046927SAndroid Build Coastguard Worker bool bogus_colour_endpoints;
553*61046927SAndroid Build Coastguard Worker bool bogus_weights;
554*61046927SAndroid Build Coastguard Worker
555*61046927SAndroid Build Coastguard Worker int high_prec;
556*61046927SAndroid Build Coastguard Worker int dual_plane;
557*61046927SAndroid Build Coastguard Worker int colour_component_selector;
558*61046927SAndroid Build Coastguard Worker int wt_range;
559*61046927SAndroid Build Coastguard Worker int wt_w, wt_h, wt_d;
560*61046927SAndroid Build Coastguard Worker int num_parts;
561*61046927SAndroid Build Coastguard Worker int partition_index;
562*61046927SAndroid Build Coastguard Worker
563*61046927SAndroid Build Coastguard Worker bool is_void_extent;
564*61046927SAndroid Build Coastguard Worker int void_extent_d;
565*61046927SAndroid Build Coastguard Worker int void_extent_min_s;
566*61046927SAndroid Build Coastguard Worker int void_extent_max_s;
567*61046927SAndroid Build Coastguard Worker int void_extent_min_t;
568*61046927SAndroid Build Coastguard Worker int void_extent_max_t;
569*61046927SAndroid Build Coastguard Worker uint16_t void_extent_colour_r;
570*61046927SAndroid Build Coastguard Worker uint16_t void_extent_colour_g;
571*61046927SAndroid Build Coastguard Worker uint16_t void_extent_colour_b;
572*61046927SAndroid Build Coastguard Worker uint16_t void_extent_colour_a;
573*61046927SAndroid Build Coastguard Worker
574*61046927SAndroid Build Coastguard Worker bool is_multi_cem;
575*61046927SAndroid Build Coastguard Worker int num_extra_cem_bits;
576*61046927SAndroid Build Coastguard Worker int colour_endpoint_data_offset;
577*61046927SAndroid Build Coastguard Worker int extra_cem_bits;
578*61046927SAndroid Build Coastguard Worker int cem_base_class;
579*61046927SAndroid Build Coastguard Worker int cems[4];
580*61046927SAndroid Build Coastguard Worker
581*61046927SAndroid Build Coastguard Worker int num_cem_values;
582*61046927SAndroid Build Coastguard Worker
583*61046927SAndroid Build Coastguard Worker /* Calculated by unpack_weights(): */
584*61046927SAndroid Build Coastguard Worker uint8_t weights_quant[64 + 4]; /* max 64 values, plus padding for overflows in trit parsing */
585*61046927SAndroid Build Coastguard Worker
586*61046927SAndroid Build Coastguard Worker /* Calculated by unquantise_weights(): */
587*61046927SAndroid Build Coastguard Worker uint8_t weights[64 + 18]; /* max 64 values, plus padding for the infill interpolation */
588*61046927SAndroid Build Coastguard Worker
589*61046927SAndroid Build Coastguard Worker /* Calculated by unpack_colour_endpoints(): */
590*61046927SAndroid Build Coastguard Worker uint8_t colour_endpoints_quant[18 + 4]; /* max 18 values, plus padding for overflows in trit parsing */
591*61046927SAndroid Build Coastguard Worker
592*61046927SAndroid Build Coastguard Worker /* Calculated by unquantise_colour_endpoints(): */
593*61046927SAndroid Build Coastguard Worker uint8_t colour_endpoints[18];
594*61046927SAndroid Build Coastguard Worker
595*61046927SAndroid Build Coastguard Worker /* Calculated by calculate_from_weights(): */
596*61046927SAndroid Build Coastguard Worker int wt_trits;
597*61046927SAndroid Build Coastguard Worker int wt_quints;
598*61046927SAndroid Build Coastguard Worker int wt_bits;
599*61046927SAndroid Build Coastguard Worker int wt_max;
600*61046927SAndroid Build Coastguard Worker int num_weights;
601*61046927SAndroid Build Coastguard Worker int weight_bits;
602*61046927SAndroid Build Coastguard Worker
603*61046927SAndroid Build Coastguard Worker /* Calculated by calculate_remaining_bits(): */
604*61046927SAndroid Build Coastguard Worker int remaining_bits;
605*61046927SAndroid Build Coastguard Worker
606*61046927SAndroid Build Coastguard Worker /* Calculated by calculate_colour_endpoints_size(): */
607*61046927SAndroid Build Coastguard Worker int colour_endpoint_bits;
608*61046927SAndroid Build Coastguard Worker int ce_max;
609*61046927SAndroid Build Coastguard Worker int ce_trits;
610*61046927SAndroid Build Coastguard Worker int ce_quints;
611*61046927SAndroid Build Coastguard Worker int ce_bits;
612*61046927SAndroid Build Coastguard Worker
613*61046927SAndroid Build Coastguard Worker /* Calculated by compute_infill_weights(); */
614*61046927SAndroid Build Coastguard Worker uint8_t infill_weights[2][216]; /* large enough for 6x6x6 */
615*61046927SAndroid Build Coastguard Worker
616*61046927SAndroid Build Coastguard Worker /* Calculated by decode_colour_endpoints(); */
617*61046927SAndroid Build Coastguard Worker uint8x4_t endpoints_decoded[2][4];
618*61046927SAndroid Build Coastguard Worker
619*61046927SAndroid Build Coastguard Worker void calculate_from_weights();
620*61046927SAndroid Build Coastguard Worker void calculate_remaining_bits();
621*61046927SAndroid Build Coastguard Worker decode_error::type calculate_colour_endpoints_size();
622*61046927SAndroid Build Coastguard Worker
623*61046927SAndroid Build Coastguard Worker void unquantise_weights();
624*61046927SAndroid Build Coastguard Worker void unquantise_colour_endpoints();
625*61046927SAndroid Build Coastguard Worker
626*61046927SAndroid Build Coastguard Worker decode_error::type decode(const Decoder &decoder, InputBitVector in);
627*61046927SAndroid Build Coastguard Worker
628*61046927SAndroid Build Coastguard Worker decode_error::type decode_block_mode(InputBitVector in);
629*61046927SAndroid Build Coastguard Worker decode_error::type decode_void_extent(InputBitVector in);
630*61046927SAndroid Build Coastguard Worker void decode_cem(InputBitVector in);
631*61046927SAndroid Build Coastguard Worker void unpack_colour_endpoints(InputBitVector in);
632*61046927SAndroid Build Coastguard Worker void decode_colour_endpoints();
633*61046927SAndroid Build Coastguard Worker void unpack_weights(InputBitVector in);
634*61046927SAndroid Build Coastguard Worker void compute_infill_weights(int block_w, int block_h, int block_d);
635*61046927SAndroid Build Coastguard Worker
636*61046927SAndroid Build Coastguard Worker void write_decoded(const Decoder &decoder, uint16_t *output);
637*61046927SAndroid Build Coastguard Worker };
638*61046927SAndroid Build Coastguard Worker
639*61046927SAndroid Build Coastguard Worker
decode(const uint8_t * in,uint16_t * output) const640*61046927SAndroid Build Coastguard Worker decode_error::type Decoder::decode(const uint8_t *in, uint16_t *output) const
641*61046927SAndroid Build Coastguard Worker {
642*61046927SAndroid Build Coastguard Worker Block blk;
643*61046927SAndroid Build Coastguard Worker InputBitVector in_vec;
644*61046927SAndroid Build Coastguard Worker memcpy(&in_vec.data, in, 16);
645*61046927SAndroid Build Coastguard Worker decode_error::type err = blk.decode(*this, in_vec);
646*61046927SAndroid Build Coastguard Worker if (err == decode_error::ok) {
647*61046927SAndroid Build Coastguard Worker blk.write_decoded(*this, output);
648*61046927SAndroid Build Coastguard Worker } else {
649*61046927SAndroid Build Coastguard Worker /* Fill output with the error colour */
650*61046927SAndroid Build Coastguard Worker for (int i = 0; i < block_w * block_h * block_d; ++i) {
651*61046927SAndroid Build Coastguard Worker if (output_unorm8) {
652*61046927SAndroid Build Coastguard Worker output[i*4+0] = 0xff;
653*61046927SAndroid Build Coastguard Worker output[i*4+1] = 0;
654*61046927SAndroid Build Coastguard Worker output[i*4+2] = 0xff;
655*61046927SAndroid Build Coastguard Worker output[i*4+3] = 0xff;
656*61046927SAndroid Build Coastguard Worker } else {
657*61046927SAndroid Build Coastguard Worker assert(!srgb); /* srgb must use unorm8 */
658*61046927SAndroid Build Coastguard Worker
659*61046927SAndroid Build Coastguard Worker output[i*4+0] = FP16_ONE;
660*61046927SAndroid Build Coastguard Worker output[i*4+1] = FP16_ZERO;
661*61046927SAndroid Build Coastguard Worker output[i*4+2] = FP16_ONE;
662*61046927SAndroid Build Coastguard Worker output[i*4+3] = FP16_ONE;
663*61046927SAndroid Build Coastguard Worker }
664*61046927SAndroid Build Coastguard Worker }
665*61046927SAndroid Build Coastguard Worker }
666*61046927SAndroid Build Coastguard Worker return err;
667*61046927SAndroid Build Coastguard Worker }
668*61046927SAndroid Build Coastguard Worker
669*61046927SAndroid Build Coastguard Worker
decode_void_extent(InputBitVector block)670*61046927SAndroid Build Coastguard Worker decode_error::type Block::decode_void_extent(InputBitVector block)
671*61046927SAndroid Build Coastguard Worker {
672*61046927SAndroid Build Coastguard Worker /* TODO: 3D */
673*61046927SAndroid Build Coastguard Worker
674*61046927SAndroid Build Coastguard Worker is_void_extent = true;
675*61046927SAndroid Build Coastguard Worker void_extent_d = block.get_bits(9, 1);
676*61046927SAndroid Build Coastguard Worker void_extent_min_s = block.get_bits(12, 13);
677*61046927SAndroid Build Coastguard Worker void_extent_max_s = block.get_bits(25, 13);
678*61046927SAndroid Build Coastguard Worker void_extent_min_t = block.get_bits(38, 13);
679*61046927SAndroid Build Coastguard Worker void_extent_max_t = block.get_bits(51, 13);
680*61046927SAndroid Build Coastguard Worker void_extent_colour_r = block.get_bits(64, 16);
681*61046927SAndroid Build Coastguard Worker void_extent_colour_g = block.get_bits(80, 16);
682*61046927SAndroid Build Coastguard Worker void_extent_colour_b = block.get_bits(96, 16);
683*61046927SAndroid Build Coastguard Worker void_extent_colour_a = block.get_bits(112, 16);
684*61046927SAndroid Build Coastguard Worker
685*61046927SAndroid Build Coastguard Worker /* TODO: maybe we should do something useful with the extent coordinates? */
686*61046927SAndroid Build Coastguard Worker
687*61046927SAndroid Build Coastguard Worker if (void_extent_d) {
688*61046927SAndroid Build Coastguard Worker return decode_error::unsupported_hdr_void_extent;
689*61046927SAndroid Build Coastguard Worker }
690*61046927SAndroid Build Coastguard Worker
691*61046927SAndroid Build Coastguard Worker if (void_extent_min_s == 0x1fff && void_extent_max_s == 0x1fff
692*61046927SAndroid Build Coastguard Worker && void_extent_min_t == 0x1fff && void_extent_max_t == 0x1fff) {
693*61046927SAndroid Build Coastguard Worker
694*61046927SAndroid Build Coastguard Worker /* No extents */
695*61046927SAndroid Build Coastguard Worker
696*61046927SAndroid Build Coastguard Worker } else {
697*61046927SAndroid Build Coastguard Worker
698*61046927SAndroid Build Coastguard Worker /* Check for illegal encoding */
699*61046927SAndroid Build Coastguard Worker if (void_extent_min_s >= void_extent_max_s || void_extent_min_t >= void_extent_max_t) {
700*61046927SAndroid Build Coastguard Worker return decode_error::invalid_range_in_void_extent;
701*61046927SAndroid Build Coastguard Worker }
702*61046927SAndroid Build Coastguard Worker }
703*61046927SAndroid Build Coastguard Worker
704*61046927SAndroid Build Coastguard Worker return decode_error::ok;
705*61046927SAndroid Build Coastguard Worker }
706*61046927SAndroid Build Coastguard Worker
decode_block_mode(InputBitVector in)707*61046927SAndroid Build Coastguard Worker decode_error::type Block::decode_block_mode(InputBitVector in)
708*61046927SAndroid Build Coastguard Worker {
709*61046927SAndroid Build Coastguard Worker dual_plane = in.get_bits(10, 1);
710*61046927SAndroid Build Coastguard Worker high_prec = in.get_bits(9, 1);
711*61046927SAndroid Build Coastguard Worker
712*61046927SAndroid Build Coastguard Worker if (in.get_bits(0, 2) != 0x0) {
713*61046927SAndroid Build Coastguard Worker wt_range = (in.get_bits(0, 2) << 1) | in.get_bits(4, 1);
714*61046927SAndroid Build Coastguard Worker int a = in.get_bits(5, 2);
715*61046927SAndroid Build Coastguard Worker int b = in.get_bits(7, 2);
716*61046927SAndroid Build Coastguard Worker switch (in.get_bits(2, 2)) {
717*61046927SAndroid Build Coastguard Worker case 0x0:
718*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
719*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DHBBAAR00RR");
720*61046927SAndroid Build Coastguard Worker wt_w = b + 4;
721*61046927SAndroid Build Coastguard Worker wt_h = a + 2;
722*61046927SAndroid Build Coastguard Worker break;
723*61046927SAndroid Build Coastguard Worker case 0x1:
724*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
725*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DHBBAAR01RR");
726*61046927SAndroid Build Coastguard Worker wt_w = b + 8;
727*61046927SAndroid Build Coastguard Worker wt_h = a + 2;
728*61046927SAndroid Build Coastguard Worker break;
729*61046927SAndroid Build Coastguard Worker case 0x2:
730*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
731*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DHBBAAR10RR");
732*61046927SAndroid Build Coastguard Worker wt_w = a + 2;
733*61046927SAndroid Build Coastguard Worker wt_h = b + 8;
734*61046927SAndroid Build Coastguard Worker break;
735*61046927SAndroid Build Coastguard Worker case 0x3:
736*61046927SAndroid Build Coastguard Worker if ((b & 0x2) == 0) {
737*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
738*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH0BAAR11RR");
739*61046927SAndroid Build Coastguard Worker wt_w = a + 2;
740*61046927SAndroid Build Coastguard Worker wt_h = b + 6;
741*61046927SAndroid Build Coastguard Worker } else {
742*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
743*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH1BAAR11RR");
744*61046927SAndroid Build Coastguard Worker wt_w = (b & 0x1) + 2;
745*61046927SAndroid Build Coastguard Worker wt_h = a + 2;
746*61046927SAndroid Build Coastguard Worker }
747*61046927SAndroid Build Coastguard Worker break;
748*61046927SAndroid Build Coastguard Worker }
749*61046927SAndroid Build Coastguard Worker } else {
750*61046927SAndroid Build Coastguard Worker if (in.get_bits(6, 3) == 0x7) {
751*61046927SAndroid Build Coastguard Worker if (in.get_bits(0, 9) == 0x1fc) {
752*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
753*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "xx111111100 (void extent)");
754*61046927SAndroid Build Coastguard Worker return decode_void_extent(in);
755*61046927SAndroid Build Coastguard Worker } else {
756*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
757*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "xx111xxxx00");
758*61046927SAndroid Build Coastguard Worker return decode_error::reserved_block_mode_1;
759*61046927SAndroid Build Coastguard Worker }
760*61046927SAndroid Build Coastguard Worker }
761*61046927SAndroid Build Coastguard Worker if (in.get_bits(0, 4) == 0x0) {
762*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
763*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "xxxxxxx0000");
764*61046927SAndroid Build Coastguard Worker return decode_error::reserved_block_mode_2;
765*61046927SAndroid Build Coastguard Worker }
766*61046927SAndroid Build Coastguard Worker
767*61046927SAndroid Build Coastguard Worker wt_range = in.get_bits(1, 3) | in.get_bits(4, 1);
768*61046927SAndroid Build Coastguard Worker int a = in.get_bits(5, 2);
769*61046927SAndroid Build Coastguard Worker int b;
770*61046927SAndroid Build Coastguard Worker
771*61046927SAndroid Build Coastguard Worker switch (in.get_bits(7, 2)) {
772*61046927SAndroid Build Coastguard Worker case 0x0:
773*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
774*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH00AARRR00");
775*61046927SAndroid Build Coastguard Worker wt_w = 12;
776*61046927SAndroid Build Coastguard Worker wt_h = a + 2;
777*61046927SAndroid Build Coastguard Worker break;
778*61046927SAndroid Build Coastguard Worker case 0x1:
779*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
780*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH01AARRR00");
781*61046927SAndroid Build Coastguard Worker wt_w = a + 2;
782*61046927SAndroid Build Coastguard Worker wt_h = 12;
783*61046927SAndroid Build Coastguard Worker break;
784*61046927SAndroid Build Coastguard Worker case 0x3:
785*61046927SAndroid Build Coastguard Worker if (in.get_bits(5, 1) == 0) {
786*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
787*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH1100RRR00");
788*61046927SAndroid Build Coastguard Worker wt_w = 6;
789*61046927SAndroid Build Coastguard Worker wt_h = 10;
790*61046927SAndroid Build Coastguard Worker } else {
791*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
792*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "DH1101RRR00");
793*61046927SAndroid Build Coastguard Worker wt_w = 10;
794*61046927SAndroid Build Coastguard Worker wt_h = 6;
795*61046927SAndroid Build Coastguard Worker }
796*61046927SAndroid Build Coastguard Worker break;
797*61046927SAndroid Build Coastguard Worker case 0x2:
798*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
799*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 11, "BB10AARRR00");
800*61046927SAndroid Build Coastguard Worker b = in.get_bits(9, 2);
801*61046927SAndroid Build Coastguard Worker wt_w = a + 6;
802*61046927SAndroid Build Coastguard Worker wt_h = b + 6;
803*61046927SAndroid Build Coastguard Worker dual_plane = 0;
804*61046927SAndroid Build Coastguard Worker high_prec = 0;
805*61046927SAndroid Build Coastguard Worker break;
806*61046927SAndroid Build Coastguard Worker }
807*61046927SAndroid Build Coastguard Worker }
808*61046927SAndroid Build Coastguard Worker return decode_error::ok;
809*61046927SAndroid Build Coastguard Worker }
810*61046927SAndroid Build Coastguard Worker
decode_cem(InputBitVector in)811*61046927SAndroid Build Coastguard Worker void Block::decode_cem(InputBitVector in)
812*61046927SAndroid Build Coastguard Worker {
813*61046927SAndroid Build Coastguard Worker cems[0] = cems[1] = cems[2] = cems[3] = -1;
814*61046927SAndroid Build Coastguard Worker
815*61046927SAndroid Build Coastguard Worker num_extra_cem_bits = 0;
816*61046927SAndroid Build Coastguard Worker extra_cem_bits = 0;
817*61046927SAndroid Build Coastguard Worker
818*61046927SAndroid Build Coastguard Worker if (num_parts > 1) {
819*61046927SAndroid Build Coastguard Worker
820*61046927SAndroid Build Coastguard Worker partition_index = in.get_bits(13, 10);
821*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
822*61046927SAndroid Build Coastguard Worker in.printf_bits(13, 10, "partition ID (%d)", partition_index);
823*61046927SAndroid Build Coastguard Worker
824*61046927SAndroid Build Coastguard Worker uint32_t cem = in.get_bits(23, 6);
825*61046927SAndroid Build Coastguard Worker
826*61046927SAndroid Build Coastguard Worker if ((cem & 0x3) == 0x0) {
827*61046927SAndroid Build Coastguard Worker cem >>= 2;
828*61046927SAndroid Build Coastguard Worker cem_base_class = cem >> 2;
829*61046927SAndroid Build Coastguard Worker is_multi_cem = false;
830*61046927SAndroid Build Coastguard Worker
831*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_parts; ++i)
832*61046927SAndroid Build Coastguard Worker cems[i] = cem;
833*61046927SAndroid Build Coastguard Worker
834*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
835*61046927SAndroid Build Coastguard Worker in.printf_bits(23, 6, "CEM (single, %d)", cem);
836*61046927SAndroid Build Coastguard Worker } else {
837*61046927SAndroid Build Coastguard Worker
838*61046927SAndroid Build Coastguard Worker cem_base_class = (cem & 0x3) - 1;
839*61046927SAndroid Build Coastguard Worker is_multi_cem = true;
840*61046927SAndroid Build Coastguard Worker
841*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
842*61046927SAndroid Build Coastguard Worker in.printf_bits(23, 6, "CEM (multi, base class %d)", cem_base_class);
843*61046927SAndroid Build Coastguard Worker
844*61046927SAndroid Build Coastguard Worker int offset = 128 - weight_bits;
845*61046927SAndroid Build Coastguard Worker
846*61046927SAndroid Build Coastguard Worker if (num_parts == 2) {
847*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
848*61046927SAndroid Build Coastguard Worker in.printf_bits(25, 4, "M0M0 C1 C0");
849*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - 2, 2, "M1M1");
850*61046927SAndroid Build Coastguard Worker }
851*61046927SAndroid Build Coastguard Worker
852*61046927SAndroid Build Coastguard Worker uint32_t c0 = in.get_bits(25, 1);
853*61046927SAndroid Build Coastguard Worker uint32_t c1 = in.get_bits(26, 1);
854*61046927SAndroid Build Coastguard Worker
855*61046927SAndroid Build Coastguard Worker extra_cem_bits = c0 + c1;
856*61046927SAndroid Build Coastguard Worker
857*61046927SAndroid Build Coastguard Worker num_extra_cem_bits = 2;
858*61046927SAndroid Build Coastguard Worker
859*61046927SAndroid Build Coastguard Worker uint32_t m0 = in.get_bits(27, 2);
860*61046927SAndroid Build Coastguard Worker uint32_t m1 = in.get_bits(offset - 2, 2);
861*61046927SAndroid Build Coastguard Worker
862*61046927SAndroid Build Coastguard Worker cems[0] = ((cem_base_class + c0) << 2) | m0;
863*61046927SAndroid Build Coastguard Worker cems[1] = ((cem_base_class + c1) << 2) | m1;
864*61046927SAndroid Build Coastguard Worker
865*61046927SAndroid Build Coastguard Worker } else if (num_parts == 3) {
866*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
867*61046927SAndroid Build Coastguard Worker in.printf_bits(25, 4, "M0 C2 C1 C0");
868*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - 5, 5, "M2M2 M1M1 M0");
869*61046927SAndroid Build Coastguard Worker }
870*61046927SAndroid Build Coastguard Worker
871*61046927SAndroid Build Coastguard Worker uint32_t c0 = in.get_bits(25, 1);
872*61046927SAndroid Build Coastguard Worker uint32_t c1 = in.get_bits(26, 1);
873*61046927SAndroid Build Coastguard Worker uint32_t c2 = in.get_bits(27, 1);
874*61046927SAndroid Build Coastguard Worker
875*61046927SAndroid Build Coastguard Worker extra_cem_bits = c0 + c1 + c2;
876*61046927SAndroid Build Coastguard Worker
877*61046927SAndroid Build Coastguard Worker num_extra_cem_bits = 5;
878*61046927SAndroid Build Coastguard Worker
879*61046927SAndroid Build Coastguard Worker uint32_t m0 = in.get_bits(28, 1) | (in.get_bits(128 - weight_bits - 5, 1) << 1);
880*61046927SAndroid Build Coastguard Worker uint32_t m1 = in.get_bits(offset - 4, 2);
881*61046927SAndroid Build Coastguard Worker uint32_t m2 = in.get_bits(offset - 2, 2);
882*61046927SAndroid Build Coastguard Worker
883*61046927SAndroid Build Coastguard Worker cems[0] = ((cem_base_class + c0) << 2) | m0;
884*61046927SAndroid Build Coastguard Worker cems[1] = ((cem_base_class + c1) << 2) | m1;
885*61046927SAndroid Build Coastguard Worker cems[2] = ((cem_base_class + c2) << 2) | m2;
886*61046927SAndroid Build Coastguard Worker
887*61046927SAndroid Build Coastguard Worker } else if (num_parts == 4) {
888*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
889*61046927SAndroid Build Coastguard Worker in.printf_bits(25, 4, "C3 C2 C1 C0");
890*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - 8, 8, "M3M3 M2M2 M1M1 M0M0");
891*61046927SAndroid Build Coastguard Worker }
892*61046927SAndroid Build Coastguard Worker
893*61046927SAndroid Build Coastguard Worker uint32_t c0 = in.get_bits(25, 1);
894*61046927SAndroid Build Coastguard Worker uint32_t c1 = in.get_bits(26, 1);
895*61046927SAndroid Build Coastguard Worker uint32_t c2 = in.get_bits(27, 1);
896*61046927SAndroid Build Coastguard Worker uint32_t c3 = in.get_bits(28, 1);
897*61046927SAndroid Build Coastguard Worker
898*61046927SAndroid Build Coastguard Worker extra_cem_bits = c0 + c1 + c2 + c3;
899*61046927SAndroid Build Coastguard Worker
900*61046927SAndroid Build Coastguard Worker num_extra_cem_bits = 8;
901*61046927SAndroid Build Coastguard Worker
902*61046927SAndroid Build Coastguard Worker uint32_t m0 = in.get_bits(offset - 8, 2);
903*61046927SAndroid Build Coastguard Worker uint32_t m1 = in.get_bits(offset - 6, 2);
904*61046927SAndroid Build Coastguard Worker uint32_t m2 = in.get_bits(offset - 4, 2);
905*61046927SAndroid Build Coastguard Worker uint32_t m3 = in.get_bits(offset - 2, 2);
906*61046927SAndroid Build Coastguard Worker
907*61046927SAndroid Build Coastguard Worker cems[0] = ((cem_base_class + c0) << 2) | m0;
908*61046927SAndroid Build Coastguard Worker cems[1] = ((cem_base_class + c1) << 2) | m1;
909*61046927SAndroid Build Coastguard Worker cems[2] = ((cem_base_class + c2) << 2) | m2;
910*61046927SAndroid Build Coastguard Worker cems[3] = ((cem_base_class + c3) << 2) | m3;
911*61046927SAndroid Build Coastguard Worker } else {
912*61046927SAndroid Build Coastguard Worker unreachable("");
913*61046927SAndroid Build Coastguard Worker }
914*61046927SAndroid Build Coastguard Worker }
915*61046927SAndroid Build Coastguard Worker
916*61046927SAndroid Build Coastguard Worker colour_endpoint_data_offset = 29;
917*61046927SAndroid Build Coastguard Worker
918*61046927SAndroid Build Coastguard Worker } else {
919*61046927SAndroid Build Coastguard Worker uint32_t cem = in.get_bits(13, 4);
920*61046927SAndroid Build Coastguard Worker
921*61046927SAndroid Build Coastguard Worker cem_base_class = cem >> 2;
922*61046927SAndroid Build Coastguard Worker is_multi_cem = false;
923*61046927SAndroid Build Coastguard Worker
924*61046927SAndroid Build Coastguard Worker cems[0] = cem;
925*61046927SAndroid Build Coastguard Worker
926*61046927SAndroid Build Coastguard Worker partition_index = -1;
927*61046927SAndroid Build Coastguard Worker
928*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
929*61046927SAndroid Build Coastguard Worker in.printf_bits(13, 4, "CEM = %d (class %d)", cem, cem_base_class);
930*61046927SAndroid Build Coastguard Worker
931*61046927SAndroid Build Coastguard Worker colour_endpoint_data_offset = 17;
932*61046927SAndroid Build Coastguard Worker }
933*61046927SAndroid Build Coastguard Worker }
934*61046927SAndroid Build Coastguard Worker
unpack_colour_endpoints(InputBitVector in)935*61046927SAndroid Build Coastguard Worker void Block::unpack_colour_endpoints(InputBitVector in)
936*61046927SAndroid Build Coastguard Worker {
937*61046927SAndroid Build Coastguard Worker if (ce_trits) {
938*61046927SAndroid Build Coastguard Worker int offset = colour_endpoint_data_offset;
939*61046927SAndroid Build Coastguard Worker int bits_left = colour_endpoint_bits;
940*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; i += 5) {
941*61046927SAndroid Build Coastguard Worker int bits_to_read = MIN2(bits_left, 8 + ce_bits * 5);
942*61046927SAndroid Build Coastguard Worker /* If ce_trits then ce_bits <= 6, so bits_to_read <= 38 and we have to use uint64_t */
943*61046927SAndroid Build Coastguard Worker uint64_t raw = in.get_bits64(offset, bits_to_read);
944*61046927SAndroid Build Coastguard Worker unpack_trit_block(ce_bits, raw, &colour_endpoints_quant[i]);
945*61046927SAndroid Build Coastguard Worker
946*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
947*61046927SAndroid Build Coastguard Worker in.printf_bits(offset, bits_to_read,
948*61046927SAndroid Build Coastguard Worker "trits [%d,%d,%d,%d,%d]",
949*61046927SAndroid Build Coastguard Worker colour_endpoints_quant[i+0], colour_endpoints_quant[i+1],
950*61046927SAndroid Build Coastguard Worker colour_endpoints_quant[i+2], colour_endpoints_quant[i+3],
951*61046927SAndroid Build Coastguard Worker colour_endpoints_quant[i+4]);
952*61046927SAndroid Build Coastguard Worker
953*61046927SAndroid Build Coastguard Worker offset += 8 + ce_bits * 5;
954*61046927SAndroid Build Coastguard Worker bits_left -= 8 + ce_bits * 5;
955*61046927SAndroid Build Coastguard Worker }
956*61046927SAndroid Build Coastguard Worker } else if (ce_quints) {
957*61046927SAndroid Build Coastguard Worker int offset = colour_endpoint_data_offset;
958*61046927SAndroid Build Coastguard Worker int bits_left = colour_endpoint_bits;
959*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; i += 3) {
960*61046927SAndroid Build Coastguard Worker int bits_to_read = MIN2(bits_left, 7 + ce_bits * 3);
961*61046927SAndroid Build Coastguard Worker /* If ce_quints then ce_bits <= 5, so bits_to_read <= 22 and we can use uint32_t */
962*61046927SAndroid Build Coastguard Worker uint32_t raw = in.get_bits(offset, bits_to_read);
963*61046927SAndroid Build Coastguard Worker unpack_quint_block(ce_bits, raw, &colour_endpoints_quant[i]);
964*61046927SAndroid Build Coastguard Worker
965*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
966*61046927SAndroid Build Coastguard Worker in.printf_bits(offset, bits_to_read,
967*61046927SAndroid Build Coastguard Worker "quints [%d,%d,%d]",
968*61046927SAndroid Build Coastguard Worker colour_endpoints_quant[i], colour_endpoints_quant[i+1], colour_endpoints_quant[i+2]);
969*61046927SAndroid Build Coastguard Worker
970*61046927SAndroid Build Coastguard Worker offset += 7 + ce_bits * 3;
971*61046927SAndroid Build Coastguard Worker bits_left -= 7 + ce_bits * 3;
972*61046927SAndroid Build Coastguard Worker }
973*61046927SAndroid Build Coastguard Worker } else {
974*61046927SAndroid Build Coastguard Worker assert((colour_endpoint_bits % ce_bits) == 0);
975*61046927SAndroid Build Coastguard Worker int offset = colour_endpoint_data_offset;
976*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; i++) {
977*61046927SAndroid Build Coastguard Worker colour_endpoints_quant[i] = in.get_bits(offset, ce_bits);
978*61046927SAndroid Build Coastguard Worker
979*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
980*61046927SAndroid Build Coastguard Worker in.printf_bits(offset, ce_bits, "bits [%d]", colour_endpoints_quant[i]);
981*61046927SAndroid Build Coastguard Worker
982*61046927SAndroid Build Coastguard Worker offset += ce_bits;
983*61046927SAndroid Build Coastguard Worker }
984*61046927SAndroid Build Coastguard Worker }
985*61046927SAndroid Build Coastguard Worker }
986*61046927SAndroid Build Coastguard Worker
decode_colour_endpoints()987*61046927SAndroid Build Coastguard Worker void Block::decode_colour_endpoints()
988*61046927SAndroid Build Coastguard Worker {
989*61046927SAndroid Build Coastguard Worker int cem_values_idx = 0;
990*61046927SAndroid Build Coastguard Worker for (int part = 0; part < num_parts; ++part) {
991*61046927SAndroid Build Coastguard Worker uint8_t *v = &colour_endpoints[cem_values_idx];
992*61046927SAndroid Build Coastguard Worker int v0 = v[0];
993*61046927SAndroid Build Coastguard Worker int v1 = v[1];
994*61046927SAndroid Build Coastguard Worker int v2 = v[2];
995*61046927SAndroid Build Coastguard Worker int v3 = v[3];
996*61046927SAndroid Build Coastguard Worker int v4 = v[4];
997*61046927SAndroid Build Coastguard Worker int v5 = v[5];
998*61046927SAndroid Build Coastguard Worker int v6 = v[6];
999*61046927SAndroid Build Coastguard Worker int v7 = v[7];
1000*61046927SAndroid Build Coastguard Worker cem_values_idx += ((cems[part] >> 2) + 1) * 2;
1001*61046927SAndroid Build Coastguard Worker
1002*61046927SAndroid Build Coastguard Worker uint8x4_t e0, e1;
1003*61046927SAndroid Build Coastguard Worker int s0, s1, L0, L1;
1004*61046927SAndroid Build Coastguard Worker
1005*61046927SAndroid Build Coastguard Worker switch (cems[part])
1006*61046927SAndroid Build Coastguard Worker {
1007*61046927SAndroid Build Coastguard Worker case 0:
1008*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v0, v0, 0xff);
1009*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v1, v1, v1, 0xff);
1010*61046927SAndroid Build Coastguard Worker break;
1011*61046927SAndroid Build Coastguard Worker case 1:
1012*61046927SAndroid Build Coastguard Worker L0 = (v0 >> 2) | (v1 & 0xc0);
1013*61046927SAndroid Build Coastguard Worker L1 = L0 + (v1 & 0x3f);
1014*61046927SAndroid Build Coastguard Worker if (L1 > 0xff)
1015*61046927SAndroid Build Coastguard Worker L1 = 0xff;
1016*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(L0, L0, L0, 0xff);
1017*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(L1, L1, L1, 0xff);
1018*61046927SAndroid Build Coastguard Worker break;
1019*61046927SAndroid Build Coastguard Worker case 4:
1020*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v0, v0, v2);
1021*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v1, v1, v1, v3);
1022*61046927SAndroid Build Coastguard Worker break;
1023*61046927SAndroid Build Coastguard Worker case 5:
1024*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0);
1025*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2);
1026*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v0, v0, v2);
1027*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t::clamped(v0+v1, v0+v1, v0+v1, v2+v3);
1028*61046927SAndroid Build Coastguard Worker break;
1029*61046927SAndroid Build Coastguard Worker case 6:
1030*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0*v3 >> 8, v1*v3 >> 8, v2*v3 >> 8, 0xff);
1031*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v0, v1, v2, 0xff);
1032*61046927SAndroid Build Coastguard Worker break;
1033*61046927SAndroid Build Coastguard Worker case 8:
1034*61046927SAndroid Build Coastguard Worker s0 = v0 + v2 + v4;
1035*61046927SAndroid Build Coastguard Worker s1 = v1 + v3 + v5;
1036*61046927SAndroid Build Coastguard Worker if (s1 >= s0) {
1037*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v2, v4, 0xff);
1038*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v1, v3, v5, 0xff);
1039*61046927SAndroid Build Coastguard Worker } else {
1040*61046927SAndroid Build Coastguard Worker e0 = blue_contract(v1, v3, v5, 0xff);
1041*61046927SAndroid Build Coastguard Worker e1 = blue_contract(v0, v2, v4, 0xff);
1042*61046927SAndroid Build Coastguard Worker }
1043*61046927SAndroid Build Coastguard Worker break;
1044*61046927SAndroid Build Coastguard Worker case 9:
1045*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0);
1046*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2);
1047*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v5, v4);
1048*61046927SAndroid Build Coastguard Worker if (v1 + v3 + v5 >= 0) {
1049*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v2, v4, 0xff);
1050*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t::clamped(v0+v1, v2+v3, v4+v5, 0xff);
1051*61046927SAndroid Build Coastguard Worker } else {
1052*61046927SAndroid Build Coastguard Worker e0 = blue_contract_clamped(v0+v1, v2+v3, v4+v5, 0xff);
1053*61046927SAndroid Build Coastguard Worker e1 = blue_contract(v0, v2, v4, 0xff);
1054*61046927SAndroid Build Coastguard Worker }
1055*61046927SAndroid Build Coastguard Worker break;
1056*61046927SAndroid Build Coastguard Worker case 10:
1057*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0*v3 >> 8, v1*v3 >> 8, v2*v3 >> 8, v4);
1058*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v0, v1, v2, v5);
1059*61046927SAndroid Build Coastguard Worker break;
1060*61046927SAndroid Build Coastguard Worker case 12:
1061*61046927SAndroid Build Coastguard Worker s0 = v0 + v2 + v4;
1062*61046927SAndroid Build Coastguard Worker s1 = v1 + v3 + v5;
1063*61046927SAndroid Build Coastguard Worker if (s1 >= s0) {
1064*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v2, v4, v6);
1065*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(v1, v3, v5, v7);
1066*61046927SAndroid Build Coastguard Worker } else {
1067*61046927SAndroid Build Coastguard Worker e0 = blue_contract(v1, v3, v5, v7);
1068*61046927SAndroid Build Coastguard Worker e1 = blue_contract(v0, v2, v4, v6);
1069*61046927SAndroid Build Coastguard Worker }
1070*61046927SAndroid Build Coastguard Worker break;
1071*61046927SAndroid Build Coastguard Worker case 13:
1072*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v1, v0);
1073*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v3, v2);
1074*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v5, v4);
1075*61046927SAndroid Build Coastguard Worker bit_transfer_signed(v7, v6);
1076*61046927SAndroid Build Coastguard Worker if (v1 + v3 + v5 >= 0) {
1077*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(v0, v2, v4, v6);
1078*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t::clamped(v0+v1, v2+v3, v4+v5, v6+v7);
1079*61046927SAndroid Build Coastguard Worker } else {
1080*61046927SAndroid Build Coastguard Worker e0 = blue_contract_clamped(v0+v1, v2+v3, v4+v5, v6+v7);
1081*61046927SAndroid Build Coastguard Worker e1 = blue_contract(v0, v2, v4, v6);
1082*61046927SAndroid Build Coastguard Worker }
1083*61046927SAndroid Build Coastguard Worker break;
1084*61046927SAndroid Build Coastguard Worker default:
1085*61046927SAndroid Build Coastguard Worker /* HDR endpoints not supported; return error colour */
1086*61046927SAndroid Build Coastguard Worker e0 = uint8x4_t(255, 0, 255, 255);
1087*61046927SAndroid Build Coastguard Worker e1 = uint8x4_t(255, 0, 255, 255);
1088*61046927SAndroid Build Coastguard Worker break;
1089*61046927SAndroid Build Coastguard Worker }
1090*61046927SAndroid Build Coastguard Worker
1091*61046927SAndroid Build Coastguard Worker endpoints_decoded[0][part] = e0;
1092*61046927SAndroid Build Coastguard Worker endpoints_decoded[1][part] = e1;
1093*61046927SAndroid Build Coastguard Worker
1094*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
1095*61046927SAndroid Build Coastguard Worker printf("cems[%d]=%d v=[", part, cems[part]);
1096*61046927SAndroid Build Coastguard Worker for (int i = 0; i < (cems[part] >> 2) + 1; ++i) {
1097*61046927SAndroid Build Coastguard Worker if (i)
1098*61046927SAndroid Build Coastguard Worker printf(", ");
1099*61046927SAndroid Build Coastguard Worker printf("%3d", v[i]);
1100*61046927SAndroid Build Coastguard Worker }
1101*61046927SAndroid Build Coastguard Worker printf("] e0=[%3d,%4d,%4d,%4d] e1=[%3d,%4d,%4d,%4d]\n",
1102*61046927SAndroid Build Coastguard Worker e0.v[0], e0.v[1], e0.v[2], e0.v[3],
1103*61046927SAndroid Build Coastguard Worker e1.v[0], e1.v[1], e1.v[2], e1.v[3]);
1104*61046927SAndroid Build Coastguard Worker }
1105*61046927SAndroid Build Coastguard Worker }
1106*61046927SAndroid Build Coastguard Worker }
1107*61046927SAndroid Build Coastguard Worker
unpack_weights(InputBitVector in)1108*61046927SAndroid Build Coastguard Worker void Block::unpack_weights(InputBitVector in)
1109*61046927SAndroid Build Coastguard Worker {
1110*61046927SAndroid Build Coastguard Worker if (wt_trits) {
1111*61046927SAndroid Build Coastguard Worker int offset = 128;
1112*61046927SAndroid Build Coastguard Worker int bits_left = weight_bits;
1113*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_weights; i += 5) {
1114*61046927SAndroid Build Coastguard Worker int bits_to_read = MIN2(bits_left, 8 + 5*wt_bits);
1115*61046927SAndroid Build Coastguard Worker /* If wt_trits then wt_bits <= 3, so bits_to_read <= 23 and we can use uint32_t */
1116*61046927SAndroid Build Coastguard Worker uint32_t raw = in.get_bits_rev(offset, bits_to_read);
1117*61046927SAndroid Build Coastguard Worker unpack_trit_block(wt_bits, raw, &weights_quant[i]);
1118*61046927SAndroid Build Coastguard Worker
1119*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1120*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - bits_to_read, bits_to_read, "weight trits [%d,%d,%d,%d,%d]",
1121*61046927SAndroid Build Coastguard Worker weights_quant[i+0], weights_quant[i+1],
1122*61046927SAndroid Build Coastguard Worker weights_quant[i+2], weights_quant[i+3],
1123*61046927SAndroid Build Coastguard Worker weights_quant[i+4]);
1124*61046927SAndroid Build Coastguard Worker
1125*61046927SAndroid Build Coastguard Worker offset -= 8 + wt_bits * 5;
1126*61046927SAndroid Build Coastguard Worker bits_left -= 8 + wt_bits * 5;
1127*61046927SAndroid Build Coastguard Worker }
1128*61046927SAndroid Build Coastguard Worker
1129*61046927SAndroid Build Coastguard Worker } else if (wt_quints) {
1130*61046927SAndroid Build Coastguard Worker
1131*61046927SAndroid Build Coastguard Worker int offset = 128;
1132*61046927SAndroid Build Coastguard Worker int bits_left = weight_bits;
1133*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_weights; i += 3) {
1134*61046927SAndroid Build Coastguard Worker int bits_to_read = MIN2(bits_left, 7 + 3*wt_bits);
1135*61046927SAndroid Build Coastguard Worker /* If wt_quints then wt_bits <= 2, so bits_to_read <= 13 and we can use uint32_t */
1136*61046927SAndroid Build Coastguard Worker uint32_t raw = in.get_bits_rev(offset, bits_to_read);
1137*61046927SAndroid Build Coastguard Worker unpack_quint_block(wt_bits, raw, &weights_quant[i]);
1138*61046927SAndroid Build Coastguard Worker
1139*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1140*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - bits_to_read, bits_to_read, "weight quints [%d,%d,%d]",
1141*61046927SAndroid Build Coastguard Worker weights_quant[i], weights_quant[i+1], weights_quant[i+2]);
1142*61046927SAndroid Build Coastguard Worker
1143*61046927SAndroid Build Coastguard Worker offset -= 7 + wt_bits * 3;
1144*61046927SAndroid Build Coastguard Worker bits_left -= 7 + wt_bits * 3;
1145*61046927SAndroid Build Coastguard Worker }
1146*61046927SAndroid Build Coastguard Worker
1147*61046927SAndroid Build Coastguard Worker } else {
1148*61046927SAndroid Build Coastguard Worker int offset = 128;
1149*61046927SAndroid Build Coastguard Worker assert((weight_bits % wt_bits) == 0);
1150*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_weights; ++i) {
1151*61046927SAndroid Build Coastguard Worker weights_quant[i] = in.get_bits_rev(offset, wt_bits);
1152*61046927SAndroid Build Coastguard Worker
1153*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1154*61046927SAndroid Build Coastguard Worker in.printf_bits(offset - wt_bits, wt_bits, "weight bits [%d]", weights_quant[i]);
1155*61046927SAndroid Build Coastguard Worker
1156*61046927SAndroid Build Coastguard Worker offset -= wt_bits;
1157*61046927SAndroid Build Coastguard Worker }
1158*61046927SAndroid Build Coastguard Worker }
1159*61046927SAndroid Build Coastguard Worker }
1160*61046927SAndroid Build Coastguard Worker
unquantise_weights()1161*61046927SAndroid Build Coastguard Worker void Block::unquantise_weights()
1162*61046927SAndroid Build Coastguard Worker {
1163*61046927SAndroid Build Coastguard Worker assert(num_weights <= (int)ARRAY_SIZE(weights_quant));
1164*61046927SAndroid Build Coastguard Worker assert(num_weights <= (int)ARRAY_SIZE(weights));
1165*61046927SAndroid Build Coastguard Worker
1166*61046927SAndroid Build Coastguard Worker memset(weights, 0, sizeof(weights));
1167*61046927SAndroid Build Coastguard Worker
1168*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_weights; ++i) {
1169*61046927SAndroid Build Coastguard Worker
1170*61046927SAndroid Build Coastguard Worker uint8_t v = weights_quant[i];
1171*61046927SAndroid Build Coastguard Worker uint8_t w;
1172*61046927SAndroid Build Coastguard Worker
1173*61046927SAndroid Build Coastguard Worker if (wt_trits) {
1174*61046927SAndroid Build Coastguard Worker
1175*61046927SAndroid Build Coastguard Worker if (wt_bits == 0) {
1176*61046927SAndroid Build Coastguard Worker w = v * 32;
1177*61046927SAndroid Build Coastguard Worker } else {
1178*61046927SAndroid Build Coastguard Worker uint8_t A, B, C, D;
1179*61046927SAndroid Build Coastguard Worker A = (v & 0x1) ? 0x7F : 0x00;
1180*61046927SAndroid Build Coastguard Worker switch (wt_bits) {
1181*61046927SAndroid Build Coastguard Worker case 1:
1182*61046927SAndroid Build Coastguard Worker B = 0;
1183*61046927SAndroid Build Coastguard Worker C = 50;
1184*61046927SAndroid Build Coastguard Worker D = v >> 1;
1185*61046927SAndroid Build Coastguard Worker break;
1186*61046927SAndroid Build Coastguard Worker case 2:
1187*61046927SAndroid Build Coastguard Worker B = (v & 0x2) ? 0x45 : 0x00;
1188*61046927SAndroid Build Coastguard Worker C = 23;
1189*61046927SAndroid Build Coastguard Worker D = v >> 2;
1190*61046927SAndroid Build Coastguard Worker break;
1191*61046927SAndroid Build Coastguard Worker case 3:
1192*61046927SAndroid Build Coastguard Worker B = ((v & 0x6) >> 1) | ((v & 0x6) << 4);
1193*61046927SAndroid Build Coastguard Worker C = 11;
1194*61046927SAndroid Build Coastguard Worker D = v >> 3;
1195*61046927SAndroid Build Coastguard Worker break;
1196*61046927SAndroid Build Coastguard Worker default:
1197*61046927SAndroid Build Coastguard Worker unreachable("");
1198*61046927SAndroid Build Coastguard Worker }
1199*61046927SAndroid Build Coastguard Worker uint16_t T = D * C + B;
1200*61046927SAndroid Build Coastguard Worker T = T ^ A;
1201*61046927SAndroid Build Coastguard Worker T = (A & 0x20) | (T >> 2);
1202*61046927SAndroid Build Coastguard Worker assert(T < 64);
1203*61046927SAndroid Build Coastguard Worker if (T > 32)
1204*61046927SAndroid Build Coastguard Worker T++;
1205*61046927SAndroid Build Coastguard Worker w = T;
1206*61046927SAndroid Build Coastguard Worker }
1207*61046927SAndroid Build Coastguard Worker
1208*61046927SAndroid Build Coastguard Worker } else if (wt_quints) {
1209*61046927SAndroid Build Coastguard Worker
1210*61046927SAndroid Build Coastguard Worker if (wt_bits == 0) {
1211*61046927SAndroid Build Coastguard Worker w = v * 16;
1212*61046927SAndroid Build Coastguard Worker } else {
1213*61046927SAndroid Build Coastguard Worker uint8_t A, B, C, D;
1214*61046927SAndroid Build Coastguard Worker A = (v & 0x1) ? 0x7F : 0x00;
1215*61046927SAndroid Build Coastguard Worker switch (wt_bits) {
1216*61046927SAndroid Build Coastguard Worker case 1:
1217*61046927SAndroid Build Coastguard Worker B = 0;
1218*61046927SAndroid Build Coastguard Worker C = 28;
1219*61046927SAndroid Build Coastguard Worker D = v >> 1;
1220*61046927SAndroid Build Coastguard Worker break;
1221*61046927SAndroid Build Coastguard Worker case 2:
1222*61046927SAndroid Build Coastguard Worker B = (v & 0x2) ? 0x42 : 0x00;
1223*61046927SAndroid Build Coastguard Worker C = 13;
1224*61046927SAndroid Build Coastguard Worker D = v >> 2;
1225*61046927SAndroid Build Coastguard Worker break;
1226*61046927SAndroid Build Coastguard Worker default:
1227*61046927SAndroid Build Coastguard Worker unreachable("");
1228*61046927SAndroid Build Coastguard Worker }
1229*61046927SAndroid Build Coastguard Worker uint16_t T = D * C + B;
1230*61046927SAndroid Build Coastguard Worker T = T ^ A;
1231*61046927SAndroid Build Coastguard Worker T = (A & 0x20) | (T >> 2);
1232*61046927SAndroid Build Coastguard Worker assert(T < 64);
1233*61046927SAndroid Build Coastguard Worker if (T > 32)
1234*61046927SAndroid Build Coastguard Worker T++;
1235*61046927SAndroid Build Coastguard Worker w = T;
1236*61046927SAndroid Build Coastguard Worker }
1237*61046927SAndroid Build Coastguard Worker weights[i] = w;
1238*61046927SAndroid Build Coastguard Worker
1239*61046927SAndroid Build Coastguard Worker } else {
1240*61046927SAndroid Build Coastguard Worker
1241*61046927SAndroid Build Coastguard Worker switch (wt_bits) {
1242*61046927SAndroid Build Coastguard Worker case 1: w = v ? 0x3F : 0x00; break;
1243*61046927SAndroid Build Coastguard Worker case 2: w = v | (v << 2) | (v << 4); break;
1244*61046927SAndroid Build Coastguard Worker case 3: w = v | (v << 3); break;
1245*61046927SAndroid Build Coastguard Worker case 4: w = (v >> 2) | (v << 2); break;
1246*61046927SAndroid Build Coastguard Worker case 5: w = (v >> 4) | (v << 1); break;
1247*61046927SAndroid Build Coastguard Worker default: unreachable("");
1248*61046927SAndroid Build Coastguard Worker }
1249*61046927SAndroid Build Coastguard Worker assert(w < 64);
1250*61046927SAndroid Build Coastguard Worker if (w > 32)
1251*61046927SAndroid Build Coastguard Worker w++;
1252*61046927SAndroid Build Coastguard Worker }
1253*61046927SAndroid Build Coastguard Worker weights[i] = w;
1254*61046927SAndroid Build Coastguard Worker }
1255*61046927SAndroid Build Coastguard Worker }
1256*61046927SAndroid Build Coastguard Worker
compute_infill_weights(int block_w,int block_h,int block_d)1257*61046927SAndroid Build Coastguard Worker void Block::compute_infill_weights(int block_w, int block_h, int block_d)
1258*61046927SAndroid Build Coastguard Worker {
1259*61046927SAndroid Build Coastguard Worker int Ds = block_w <= 1 ? 0 : (1024 + block_w / 2) / (block_w - 1);
1260*61046927SAndroid Build Coastguard Worker int Dt = block_h <= 1 ? 0 : (1024 + block_h / 2) / (block_h - 1);
1261*61046927SAndroid Build Coastguard Worker int Dr = block_d <= 1 ? 0 : (1024 + block_d / 2) / (block_d - 1);
1262*61046927SAndroid Build Coastguard Worker for (int r = 0; r < block_d; ++r) {
1263*61046927SAndroid Build Coastguard Worker for (int t = 0; t < block_h; ++t) {
1264*61046927SAndroid Build Coastguard Worker for (int s = 0; s < block_w; ++s) {
1265*61046927SAndroid Build Coastguard Worker int cs = Ds * s;
1266*61046927SAndroid Build Coastguard Worker int ct = Dt * t;
1267*61046927SAndroid Build Coastguard Worker int cr = Dr * r;
1268*61046927SAndroid Build Coastguard Worker int gs = (cs * (wt_w - 1) + 32) >> 6;
1269*61046927SAndroid Build Coastguard Worker int gt = (ct * (wt_h - 1) + 32) >> 6;
1270*61046927SAndroid Build Coastguard Worker int gr = (cr * (wt_d - 1) + 32) >> 6;
1271*61046927SAndroid Build Coastguard Worker assert(gs >= 0 && gs <= 176);
1272*61046927SAndroid Build Coastguard Worker assert(gt >= 0 && gt <= 176);
1273*61046927SAndroid Build Coastguard Worker assert(gr >= 0 && gr <= 176);
1274*61046927SAndroid Build Coastguard Worker int js = gs >> 4;
1275*61046927SAndroid Build Coastguard Worker int fs = gs & 0xf;
1276*61046927SAndroid Build Coastguard Worker int jt = gt >> 4;
1277*61046927SAndroid Build Coastguard Worker int ft = gt & 0xf;
1278*61046927SAndroid Build Coastguard Worker int jr = gr >> 4;
1279*61046927SAndroid Build Coastguard Worker int fr = gr & 0xf;
1280*61046927SAndroid Build Coastguard Worker
1281*61046927SAndroid Build Coastguard Worker /* TODO: 3D */
1282*61046927SAndroid Build Coastguard Worker (void)jr;
1283*61046927SAndroid Build Coastguard Worker (void)fr;
1284*61046927SAndroid Build Coastguard Worker
1285*61046927SAndroid Build Coastguard Worker int w11 = (fs * ft + 8) >> 4;
1286*61046927SAndroid Build Coastguard Worker int w10 = ft - w11;
1287*61046927SAndroid Build Coastguard Worker int w01 = fs - w11;
1288*61046927SAndroid Build Coastguard Worker int w00 = 16 - fs - ft + w11;
1289*61046927SAndroid Build Coastguard Worker
1290*61046927SAndroid Build Coastguard Worker if (dual_plane) {
1291*61046927SAndroid Build Coastguard Worker int p00, p01, p10, p11, i0, i1;
1292*61046927SAndroid Build Coastguard Worker int v0 = js + jt * wt_w;
1293*61046927SAndroid Build Coastguard Worker p00 = weights[(v0) * 2];
1294*61046927SAndroid Build Coastguard Worker p01 = weights[(v0 + 1) * 2];
1295*61046927SAndroid Build Coastguard Worker p10 = weights[(v0 + wt_w) * 2];
1296*61046927SAndroid Build Coastguard Worker p11 = weights[(v0 + wt_w + 1) * 2];
1297*61046927SAndroid Build Coastguard Worker i0 = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4;
1298*61046927SAndroid Build Coastguard Worker p00 = weights[(v0) * 2 + 1];
1299*61046927SAndroid Build Coastguard Worker p01 = weights[(v0 + 1) * 2 + 1];
1300*61046927SAndroid Build Coastguard Worker p10 = weights[(v0 + wt_w) * 2 + 1];
1301*61046927SAndroid Build Coastguard Worker p11 = weights[(v0 + wt_w + 1) * 2 + 1];
1302*61046927SAndroid Build Coastguard Worker assert((v0 + wt_w + 1) * 2 + 1 < (int)ARRAY_SIZE(weights));
1303*61046927SAndroid Build Coastguard Worker i1 = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4;
1304*61046927SAndroid Build Coastguard Worker assert(0 <= i0 && i0 <= 64);
1305*61046927SAndroid Build Coastguard Worker infill_weights[0][s + t*block_w + r*block_w*block_h] = i0;
1306*61046927SAndroid Build Coastguard Worker infill_weights[1][s + t*block_w + r*block_w*block_h] = i1;
1307*61046927SAndroid Build Coastguard Worker } else {
1308*61046927SAndroid Build Coastguard Worker int p00, p01, p10, p11, i;
1309*61046927SAndroid Build Coastguard Worker int v0 = js + jt * wt_w;
1310*61046927SAndroid Build Coastguard Worker p00 = weights[v0];
1311*61046927SAndroid Build Coastguard Worker p01 = weights[v0 + 1];
1312*61046927SAndroid Build Coastguard Worker p10 = weights[v0 + wt_w];
1313*61046927SAndroid Build Coastguard Worker p11 = weights[v0 + wt_w + 1];
1314*61046927SAndroid Build Coastguard Worker assert(v0 + wt_w + 1 < (int)ARRAY_SIZE(weights));
1315*61046927SAndroid Build Coastguard Worker i = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4;
1316*61046927SAndroid Build Coastguard Worker assert(0 <= i && i <= 64);
1317*61046927SAndroid Build Coastguard Worker infill_weights[0][s + t*block_w + r*block_w*block_h] = i;
1318*61046927SAndroid Build Coastguard Worker }
1319*61046927SAndroid Build Coastguard Worker }
1320*61046927SAndroid Build Coastguard Worker }
1321*61046927SAndroid Build Coastguard Worker }
1322*61046927SAndroid Build Coastguard Worker }
1323*61046927SAndroid Build Coastguard Worker
unquantise_colour_endpoints()1324*61046927SAndroid Build Coastguard Worker void Block::unquantise_colour_endpoints()
1325*61046927SAndroid Build Coastguard Worker {
1326*61046927SAndroid Build Coastguard Worker assert(num_cem_values <= (int)ARRAY_SIZE(colour_endpoints_quant));
1327*61046927SAndroid Build Coastguard Worker assert(num_cem_values <= (int)ARRAY_SIZE(colour_endpoints));
1328*61046927SAndroid Build Coastguard Worker
1329*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; ++i) {
1330*61046927SAndroid Build Coastguard Worker uint8_t v = colour_endpoints_quant[i];
1331*61046927SAndroid Build Coastguard Worker
1332*61046927SAndroid Build Coastguard Worker if (ce_trits) {
1333*61046927SAndroid Build Coastguard Worker uint16_t A, B, C, D;
1334*61046927SAndroid Build Coastguard Worker uint16_t t;
1335*61046927SAndroid Build Coastguard Worker A = (v & 0x1) ? 0x1FF : 0x000;
1336*61046927SAndroid Build Coastguard Worker switch (ce_bits) {
1337*61046927SAndroid Build Coastguard Worker case 1:
1338*61046927SAndroid Build Coastguard Worker B = 0;
1339*61046927SAndroid Build Coastguard Worker C = 204;
1340*61046927SAndroid Build Coastguard Worker D = v >> 1;
1341*61046927SAndroid Build Coastguard Worker break;
1342*61046927SAndroid Build Coastguard Worker case 2:
1343*61046927SAndroid Build Coastguard Worker B = (v & 0x2) ? 0x116 : 0x000;
1344*61046927SAndroid Build Coastguard Worker C = 93;
1345*61046927SAndroid Build Coastguard Worker D = v >> 2;
1346*61046927SAndroid Build Coastguard Worker break;
1347*61046927SAndroid Build Coastguard Worker case 3:
1348*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0x3);
1349*61046927SAndroid Build Coastguard Worker B = t | (t << 2) | (t << 7);
1350*61046927SAndroid Build Coastguard Worker C = 44;
1351*61046927SAndroid Build Coastguard Worker D = v >> 3;
1352*61046927SAndroid Build Coastguard Worker break;
1353*61046927SAndroid Build Coastguard Worker case 4:
1354*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0x7);
1355*61046927SAndroid Build Coastguard Worker B = t | (t << 6);
1356*61046927SAndroid Build Coastguard Worker C = 22;
1357*61046927SAndroid Build Coastguard Worker D = v >> 4;
1358*61046927SAndroid Build Coastguard Worker break;
1359*61046927SAndroid Build Coastguard Worker case 5:
1360*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0xF);
1361*61046927SAndroid Build Coastguard Worker B = (t >> 2) | (t << 5);
1362*61046927SAndroid Build Coastguard Worker C = 11;
1363*61046927SAndroid Build Coastguard Worker D = v >> 5;
1364*61046927SAndroid Build Coastguard Worker break;
1365*61046927SAndroid Build Coastguard Worker case 6:
1366*61046927SAndroid Build Coastguard Worker B = ((v & 0x3E) << 3) | ((v >> 5) & 0x1);
1367*61046927SAndroid Build Coastguard Worker C = 5;
1368*61046927SAndroid Build Coastguard Worker D = v >> 6;
1369*61046927SAndroid Build Coastguard Worker break;
1370*61046927SAndroid Build Coastguard Worker default:
1371*61046927SAndroid Build Coastguard Worker unreachable("");
1372*61046927SAndroid Build Coastguard Worker }
1373*61046927SAndroid Build Coastguard Worker uint16_t T = D * C + B;
1374*61046927SAndroid Build Coastguard Worker T = T ^ A;
1375*61046927SAndroid Build Coastguard Worker T = (A & 0x80) | (T >> 2);
1376*61046927SAndroid Build Coastguard Worker assert(T < 256);
1377*61046927SAndroid Build Coastguard Worker colour_endpoints[i] = T;
1378*61046927SAndroid Build Coastguard Worker } else if (ce_quints) {
1379*61046927SAndroid Build Coastguard Worker uint16_t A, B, C, D;
1380*61046927SAndroid Build Coastguard Worker uint16_t t;
1381*61046927SAndroid Build Coastguard Worker A = (v & 0x1) ? 0x1FF : 0x000;
1382*61046927SAndroid Build Coastguard Worker switch (ce_bits) {
1383*61046927SAndroid Build Coastguard Worker case 1:
1384*61046927SAndroid Build Coastguard Worker B = 0;
1385*61046927SAndroid Build Coastguard Worker C = 113;
1386*61046927SAndroid Build Coastguard Worker D = v >> 1;
1387*61046927SAndroid Build Coastguard Worker break;
1388*61046927SAndroid Build Coastguard Worker case 2:
1389*61046927SAndroid Build Coastguard Worker B = (v & 0x2) ? 0x10C : 0x000;
1390*61046927SAndroid Build Coastguard Worker C = 54;
1391*61046927SAndroid Build Coastguard Worker D = v >> 2;
1392*61046927SAndroid Build Coastguard Worker break;
1393*61046927SAndroid Build Coastguard Worker case 3:
1394*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0x3);
1395*61046927SAndroid Build Coastguard Worker B = (t >> 1) | (t << 1) | (t << 7);
1396*61046927SAndroid Build Coastguard Worker C = 26;
1397*61046927SAndroid Build Coastguard Worker D = v >> 3;
1398*61046927SAndroid Build Coastguard Worker break;
1399*61046927SAndroid Build Coastguard Worker case 4:
1400*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0x7);
1401*61046927SAndroid Build Coastguard Worker B = (t >> 1) | (t << 6);
1402*61046927SAndroid Build Coastguard Worker C = 13;
1403*61046927SAndroid Build Coastguard Worker D = v >> 4;
1404*61046927SAndroid Build Coastguard Worker break;
1405*61046927SAndroid Build Coastguard Worker case 5:
1406*61046927SAndroid Build Coastguard Worker t = ((v >> 1) & 0xF);
1407*61046927SAndroid Build Coastguard Worker B = (t >> 4) | (t << 5);
1408*61046927SAndroid Build Coastguard Worker C = 6;
1409*61046927SAndroid Build Coastguard Worker D = v >> 5;
1410*61046927SAndroid Build Coastguard Worker break;
1411*61046927SAndroid Build Coastguard Worker default:
1412*61046927SAndroid Build Coastguard Worker unreachable("");
1413*61046927SAndroid Build Coastguard Worker }
1414*61046927SAndroid Build Coastguard Worker uint16_t T = D * C + B;
1415*61046927SAndroid Build Coastguard Worker T = T ^ A;
1416*61046927SAndroid Build Coastguard Worker T = (A & 0x80) | (T >> 2);
1417*61046927SAndroid Build Coastguard Worker assert(T < 256);
1418*61046927SAndroid Build Coastguard Worker colour_endpoints[i] = T;
1419*61046927SAndroid Build Coastguard Worker } else {
1420*61046927SAndroid Build Coastguard Worker switch (ce_bits) {
1421*61046927SAndroid Build Coastguard Worker case 1: v = v ? 0xFF : 0x00; break;
1422*61046927SAndroid Build Coastguard Worker case 2: v = (v << 6) | (v << 4) | (v << 2) | v; break;
1423*61046927SAndroid Build Coastguard Worker case 3: v = (v << 5) | (v << 2) | (v >> 1); break;
1424*61046927SAndroid Build Coastguard Worker case 4: v = (v << 4) | v; break;
1425*61046927SAndroid Build Coastguard Worker case 5: v = (v << 3) | (v >> 2); break;
1426*61046927SAndroid Build Coastguard Worker case 6: v = (v << 2) | (v >> 4); break;
1427*61046927SAndroid Build Coastguard Worker case 7: v = (v << 1) | (v >> 6); break;
1428*61046927SAndroid Build Coastguard Worker case 8: break;
1429*61046927SAndroid Build Coastguard Worker default: unreachable("");
1430*61046927SAndroid Build Coastguard Worker }
1431*61046927SAndroid Build Coastguard Worker colour_endpoints[i] = v;
1432*61046927SAndroid Build Coastguard Worker }
1433*61046927SAndroid Build Coastguard Worker }
1434*61046927SAndroid Build Coastguard Worker }
1435*61046927SAndroid Build Coastguard Worker
decode(const Decoder & decoder,InputBitVector in)1436*61046927SAndroid Build Coastguard Worker decode_error::type Block::decode(const Decoder &decoder, InputBitVector in)
1437*61046927SAndroid Build Coastguard Worker {
1438*61046927SAndroid Build Coastguard Worker decode_error::type err;
1439*61046927SAndroid Build Coastguard Worker
1440*61046927SAndroid Build Coastguard Worker is_error = false;
1441*61046927SAndroid Build Coastguard Worker bogus_colour_endpoints = false;
1442*61046927SAndroid Build Coastguard Worker bogus_weights = false;
1443*61046927SAndroid Build Coastguard Worker is_void_extent = false;
1444*61046927SAndroid Build Coastguard Worker
1445*61046927SAndroid Build Coastguard Worker wt_d = 1;
1446*61046927SAndroid Build Coastguard Worker /* TODO: 3D */
1447*61046927SAndroid Build Coastguard Worker
1448*61046927SAndroid Build Coastguard Worker /* TODO: test for all the illegal encodings */
1449*61046927SAndroid Build Coastguard Worker
1450*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1451*61046927SAndroid Build Coastguard Worker in.printf_bits(0, 128);
1452*61046927SAndroid Build Coastguard Worker
1453*61046927SAndroid Build Coastguard Worker err = decode_block_mode(in);
1454*61046927SAndroid Build Coastguard Worker if (err != decode_error::ok)
1455*61046927SAndroid Build Coastguard Worker return err;
1456*61046927SAndroid Build Coastguard Worker
1457*61046927SAndroid Build Coastguard Worker if (is_void_extent)
1458*61046927SAndroid Build Coastguard Worker return decode_error::ok;
1459*61046927SAndroid Build Coastguard Worker
1460*61046927SAndroid Build Coastguard Worker /* TODO: 3D */
1461*61046927SAndroid Build Coastguard Worker
1462*61046927SAndroid Build Coastguard Worker calculate_from_weights();
1463*61046927SAndroid Build Coastguard Worker
1464*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1465*61046927SAndroid Build Coastguard Worker printf("weights_grid=%dx%dx%d dual_plane=%d num_weights=%d high_prec=%d r=%d range=0..%d (%dt %dq %db) weight_bits=%d\n",
1466*61046927SAndroid Build Coastguard Worker wt_w, wt_h, wt_d, dual_plane, num_weights, high_prec, wt_range, wt_max, wt_trits, wt_quints, wt_bits, weight_bits);
1467*61046927SAndroid Build Coastguard Worker
1468*61046927SAndroid Build Coastguard Worker if (wt_w > decoder.block_w || wt_h > decoder.block_h || wt_d > decoder.block_d)
1469*61046927SAndroid Build Coastguard Worker return decode_error::weight_grid_exceeds_block_size;
1470*61046927SAndroid Build Coastguard Worker
1471*61046927SAndroid Build Coastguard Worker num_parts = in.get_bits(11, 2) + 1;
1472*61046927SAndroid Build Coastguard Worker
1473*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1474*61046927SAndroid Build Coastguard Worker in.printf_bits(11, 2, "partitions = %d", num_parts);
1475*61046927SAndroid Build Coastguard Worker
1476*61046927SAndroid Build Coastguard Worker if (dual_plane && num_parts > 3)
1477*61046927SAndroid Build Coastguard Worker return decode_error::dual_plane_and_too_many_partitions;
1478*61046927SAndroid Build Coastguard Worker
1479*61046927SAndroid Build Coastguard Worker decode_cem(in);
1480*61046927SAndroid Build Coastguard Worker
1481*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1482*61046927SAndroid Build Coastguard Worker printf("cem=[%d,%d,%d,%d] base_cem_class=%d\n", cems[0], cems[1], cems[2], cems[3], cem_base_class);
1483*61046927SAndroid Build Coastguard Worker
1484*61046927SAndroid Build Coastguard Worker int num_cem_pairs = (cem_base_class + 1) * num_parts + extra_cem_bits;
1485*61046927SAndroid Build Coastguard Worker num_cem_values = num_cem_pairs * 2;
1486*61046927SAndroid Build Coastguard Worker
1487*61046927SAndroid Build Coastguard Worker calculate_remaining_bits();
1488*61046927SAndroid Build Coastguard Worker err = calculate_colour_endpoints_size();
1489*61046927SAndroid Build Coastguard Worker if (err != decode_error::ok)
1490*61046927SAndroid Build Coastguard Worker return err;
1491*61046927SAndroid Build Coastguard Worker
1492*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1493*61046927SAndroid Build Coastguard Worker in.printf_bits(colour_endpoint_data_offset, colour_endpoint_bits,
1494*61046927SAndroid Build Coastguard Worker "endpoint data (%d bits, %d vals, %dt %dq %db)",
1495*61046927SAndroid Build Coastguard Worker colour_endpoint_bits, num_cem_values, ce_trits, ce_quints, ce_bits);
1496*61046927SAndroid Build Coastguard Worker
1497*61046927SAndroid Build Coastguard Worker unpack_colour_endpoints(in);
1498*61046927SAndroid Build Coastguard Worker
1499*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
1500*61046927SAndroid Build Coastguard Worker printf("cem values raw =[");
1501*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; i++) {
1502*61046927SAndroid Build Coastguard Worker if (i)
1503*61046927SAndroid Build Coastguard Worker printf(", ");
1504*61046927SAndroid Build Coastguard Worker printf("%3d", colour_endpoints_quant[i]);
1505*61046927SAndroid Build Coastguard Worker }
1506*61046927SAndroid Build Coastguard Worker printf("]\n");
1507*61046927SAndroid Build Coastguard Worker }
1508*61046927SAndroid Build Coastguard Worker
1509*61046927SAndroid Build Coastguard Worker if (num_cem_values > 18)
1510*61046927SAndroid Build Coastguard Worker return decode_error::invalid_colour_endpoints_count;
1511*61046927SAndroid Build Coastguard Worker
1512*61046927SAndroid Build Coastguard Worker unquantise_colour_endpoints();
1513*61046927SAndroid Build Coastguard Worker
1514*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
1515*61046927SAndroid Build Coastguard Worker printf("cem values norm=[");
1516*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_cem_values; i++) {
1517*61046927SAndroid Build Coastguard Worker if (i)
1518*61046927SAndroid Build Coastguard Worker printf(", ");
1519*61046927SAndroid Build Coastguard Worker printf("%3d", colour_endpoints[i]);
1520*61046927SAndroid Build Coastguard Worker }
1521*61046927SAndroid Build Coastguard Worker printf("]\n");
1522*61046927SAndroid Build Coastguard Worker }
1523*61046927SAndroid Build Coastguard Worker
1524*61046927SAndroid Build Coastguard Worker decode_colour_endpoints();
1525*61046927SAndroid Build Coastguard Worker
1526*61046927SAndroid Build Coastguard Worker if (dual_plane) {
1527*61046927SAndroid Build Coastguard Worker int ccs_offset = 128 - weight_bits - num_extra_cem_bits - 2;
1528*61046927SAndroid Build Coastguard Worker colour_component_selector = in.get_bits(ccs_offset, 2);
1529*61046927SAndroid Build Coastguard Worker
1530*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1531*61046927SAndroid Build Coastguard Worker in.printf_bits(ccs_offset, 2, "colour component selector = %d", colour_component_selector);
1532*61046927SAndroid Build Coastguard Worker } else {
1533*61046927SAndroid Build Coastguard Worker colour_component_selector = 0;
1534*61046927SAndroid Build Coastguard Worker }
1535*61046927SAndroid Build Coastguard Worker
1536*61046927SAndroid Build Coastguard Worker
1537*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1538*61046927SAndroid Build Coastguard Worker in.printf_bits(128 - weight_bits, weight_bits, "weights (%d bits)", weight_bits);
1539*61046927SAndroid Build Coastguard Worker
1540*61046927SAndroid Build Coastguard Worker if (num_weights > 64)
1541*61046927SAndroid Build Coastguard Worker return decode_error::invalid_num_weights;
1542*61046927SAndroid Build Coastguard Worker
1543*61046927SAndroid Build Coastguard Worker if (weight_bits < 24 || weight_bits > 96)
1544*61046927SAndroid Build Coastguard Worker return decode_error::invalid_weight_bits;
1545*61046927SAndroid Build Coastguard Worker
1546*61046927SAndroid Build Coastguard Worker unpack_weights(in);
1547*61046927SAndroid Build Coastguard Worker
1548*61046927SAndroid Build Coastguard Worker unquantise_weights();
1549*61046927SAndroid Build Coastguard Worker
1550*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
1551*61046927SAndroid Build Coastguard Worker printf("weights=[");
1552*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_weights; ++i) {
1553*61046927SAndroid Build Coastguard Worker if (i)
1554*61046927SAndroid Build Coastguard Worker printf(", ");
1555*61046927SAndroid Build Coastguard Worker printf("%d", weights[i]);
1556*61046927SAndroid Build Coastguard Worker }
1557*61046927SAndroid Build Coastguard Worker printf("]\n");
1558*61046927SAndroid Build Coastguard Worker
1559*61046927SAndroid Build Coastguard Worker for (int plane = 0; plane <= dual_plane; ++plane) {
1560*61046927SAndroid Build Coastguard Worker printf("weights (plane %d):\n", plane);
1561*61046927SAndroid Build Coastguard Worker int i = 0;
1562*61046927SAndroid Build Coastguard Worker (void)i;
1563*61046927SAndroid Build Coastguard Worker
1564*61046927SAndroid Build Coastguard Worker for (int r = 0; r < wt_d; ++r) {
1565*61046927SAndroid Build Coastguard Worker for (int t = 0; t < wt_h; ++t) {
1566*61046927SAndroid Build Coastguard Worker for (int s = 0; s < wt_w; ++s) {
1567*61046927SAndroid Build Coastguard Worker printf("%3d", weights[i++ * (1 + dual_plane) + plane]);
1568*61046927SAndroid Build Coastguard Worker }
1569*61046927SAndroid Build Coastguard Worker printf("\n");
1570*61046927SAndroid Build Coastguard Worker }
1571*61046927SAndroid Build Coastguard Worker if (r < wt_d - 1)
1572*61046927SAndroid Build Coastguard Worker printf("\n");
1573*61046927SAndroid Build Coastguard Worker }
1574*61046927SAndroid Build Coastguard Worker }
1575*61046927SAndroid Build Coastguard Worker }
1576*61046927SAndroid Build Coastguard Worker
1577*61046927SAndroid Build Coastguard Worker compute_infill_weights(decoder.block_w, decoder.block_h, decoder.block_d);
1578*61046927SAndroid Build Coastguard Worker
1579*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE) {
1580*61046927SAndroid Build Coastguard Worker for (int plane = 0; plane <= dual_plane; ++plane) {
1581*61046927SAndroid Build Coastguard Worker printf("infilled weights (plane %d):\n", plane);
1582*61046927SAndroid Build Coastguard Worker int i = 0;
1583*61046927SAndroid Build Coastguard Worker (void)i;
1584*61046927SAndroid Build Coastguard Worker
1585*61046927SAndroid Build Coastguard Worker for (int r = 0; r < decoder.block_d; ++r) {
1586*61046927SAndroid Build Coastguard Worker for (int t = 0; t < decoder.block_h; ++t) {
1587*61046927SAndroid Build Coastguard Worker for (int s = 0; s < decoder.block_w; ++s) {
1588*61046927SAndroid Build Coastguard Worker printf("%3d", infill_weights[plane][i++]);
1589*61046927SAndroid Build Coastguard Worker }
1590*61046927SAndroid Build Coastguard Worker printf("\n");
1591*61046927SAndroid Build Coastguard Worker }
1592*61046927SAndroid Build Coastguard Worker if (r < decoder.block_d - 1)
1593*61046927SAndroid Build Coastguard Worker printf("\n");
1594*61046927SAndroid Build Coastguard Worker }
1595*61046927SAndroid Build Coastguard Worker }
1596*61046927SAndroid Build Coastguard Worker }
1597*61046927SAndroid Build Coastguard Worker if (VERBOSE_DECODE)
1598*61046927SAndroid Build Coastguard Worker printf("\n");
1599*61046927SAndroid Build Coastguard Worker
1600*61046927SAndroid Build Coastguard Worker return decode_error::ok;
1601*61046927SAndroid Build Coastguard Worker }
1602*61046927SAndroid Build Coastguard Worker
write_decoded(const Decoder & decoder,uint16_t * output)1603*61046927SAndroid Build Coastguard Worker void Block::write_decoded(const Decoder &decoder, uint16_t *output)
1604*61046927SAndroid Build Coastguard Worker {
1605*61046927SAndroid Build Coastguard Worker /* sRGB can only be stored as unorm8. */
1606*61046927SAndroid Build Coastguard Worker assert(!decoder.srgb || decoder.output_unorm8);
1607*61046927SAndroid Build Coastguard Worker
1608*61046927SAndroid Build Coastguard Worker if (is_void_extent) {
1609*61046927SAndroid Build Coastguard Worker for (int idx = 0; idx < decoder.block_w*decoder.block_h*decoder.block_d; ++idx) {
1610*61046927SAndroid Build Coastguard Worker if (decoder.output_unorm8) {
1611*61046927SAndroid Build Coastguard Worker output[idx*4+0] = void_extent_colour_r >> 8;
1612*61046927SAndroid Build Coastguard Worker output[idx*4+1] = void_extent_colour_g >> 8;
1613*61046927SAndroid Build Coastguard Worker output[idx*4+2] = void_extent_colour_b >> 8;
1614*61046927SAndroid Build Coastguard Worker output[idx*4+3] = void_extent_colour_a >> 8;
1615*61046927SAndroid Build Coastguard Worker } else {
1616*61046927SAndroid Build Coastguard Worker /* Store the color as FP16. */
1617*61046927SAndroid Build Coastguard Worker output[idx*4+0] = _mesa_uint16_div_64k_to_half(void_extent_colour_r);
1618*61046927SAndroid Build Coastguard Worker output[idx*4+1] = _mesa_uint16_div_64k_to_half(void_extent_colour_g);
1619*61046927SAndroid Build Coastguard Worker output[idx*4+2] = _mesa_uint16_div_64k_to_half(void_extent_colour_b);
1620*61046927SAndroid Build Coastguard Worker output[idx*4+3] = _mesa_uint16_div_64k_to_half(void_extent_colour_a);
1621*61046927SAndroid Build Coastguard Worker }
1622*61046927SAndroid Build Coastguard Worker }
1623*61046927SAndroid Build Coastguard Worker return;
1624*61046927SAndroid Build Coastguard Worker }
1625*61046927SAndroid Build Coastguard Worker
1626*61046927SAndroid Build Coastguard Worker int small_block = (decoder.block_w * decoder.block_h * decoder.block_d) < 31;
1627*61046927SAndroid Build Coastguard Worker
1628*61046927SAndroid Build Coastguard Worker int idx = 0;
1629*61046927SAndroid Build Coastguard Worker for (int z = 0; z < decoder.block_d; ++z) {
1630*61046927SAndroid Build Coastguard Worker for (int y = 0; y < decoder.block_h; ++y) {
1631*61046927SAndroid Build Coastguard Worker for (int x = 0; x < decoder.block_w; ++x) {
1632*61046927SAndroid Build Coastguard Worker
1633*61046927SAndroid Build Coastguard Worker int partition;
1634*61046927SAndroid Build Coastguard Worker if (num_parts > 1) {
1635*61046927SAndroid Build Coastguard Worker partition = select_partition(partition_index, x, y, z, num_parts, small_block);
1636*61046927SAndroid Build Coastguard Worker assert(partition < num_parts);
1637*61046927SAndroid Build Coastguard Worker } else {
1638*61046927SAndroid Build Coastguard Worker partition = 0;
1639*61046927SAndroid Build Coastguard Worker }
1640*61046927SAndroid Build Coastguard Worker
1641*61046927SAndroid Build Coastguard Worker /* TODO: HDR */
1642*61046927SAndroid Build Coastguard Worker
1643*61046927SAndroid Build Coastguard Worker uint8x4_t e0 = endpoints_decoded[0][partition];
1644*61046927SAndroid Build Coastguard Worker uint8x4_t e1 = endpoints_decoded[1][partition];
1645*61046927SAndroid Build Coastguard Worker uint16_t c0[4], c1[4];
1646*61046927SAndroid Build Coastguard Worker
1647*61046927SAndroid Build Coastguard Worker /* Expand to 16 bits. */
1648*61046927SAndroid Build Coastguard Worker if (decoder.srgb) {
1649*61046927SAndroid Build Coastguard Worker c0[0] = (uint16_t)((e0.v[0] << 8) | 0x80);
1650*61046927SAndroid Build Coastguard Worker c0[1] = (uint16_t)((e0.v[1] << 8) | 0x80);
1651*61046927SAndroid Build Coastguard Worker c0[2] = (uint16_t)((e0.v[2] << 8) | 0x80);
1652*61046927SAndroid Build Coastguard Worker c0[3] = (uint16_t)((e0.v[3] << 8) | 0x80);
1653*61046927SAndroid Build Coastguard Worker
1654*61046927SAndroid Build Coastguard Worker c1[0] = (uint16_t)((e1.v[0] << 8) | 0x80);
1655*61046927SAndroid Build Coastguard Worker c1[1] = (uint16_t)((e1.v[1] << 8) | 0x80);
1656*61046927SAndroid Build Coastguard Worker c1[2] = (uint16_t)((e1.v[2] << 8) | 0x80);
1657*61046927SAndroid Build Coastguard Worker c1[3] = (uint16_t)((e1.v[3] << 8) | 0x80);
1658*61046927SAndroid Build Coastguard Worker } else {
1659*61046927SAndroid Build Coastguard Worker c0[0] = (uint16_t)((e0.v[0] << 8) | e0.v[0]);
1660*61046927SAndroid Build Coastguard Worker c0[1] = (uint16_t)((e0.v[1] << 8) | e0.v[1]);
1661*61046927SAndroid Build Coastguard Worker c0[2] = (uint16_t)((e0.v[2] << 8) | e0.v[2]);
1662*61046927SAndroid Build Coastguard Worker c0[3] = (uint16_t)((e0.v[3] << 8) | e0.v[3]);
1663*61046927SAndroid Build Coastguard Worker
1664*61046927SAndroid Build Coastguard Worker c1[0] = (uint16_t)((e1.v[0] << 8) | e1.v[0]);
1665*61046927SAndroid Build Coastguard Worker c1[1] = (uint16_t)((e1.v[1] << 8) | e1.v[1]);
1666*61046927SAndroid Build Coastguard Worker c1[2] = (uint16_t)((e1.v[2] << 8) | e1.v[2]);
1667*61046927SAndroid Build Coastguard Worker c1[3] = (uint16_t)((e1.v[3] << 8) | e1.v[3]);
1668*61046927SAndroid Build Coastguard Worker }
1669*61046927SAndroid Build Coastguard Worker
1670*61046927SAndroid Build Coastguard Worker int w[4];
1671*61046927SAndroid Build Coastguard Worker if (dual_plane) {
1672*61046927SAndroid Build Coastguard Worker int w0 = infill_weights[0][idx];
1673*61046927SAndroid Build Coastguard Worker int w1 = infill_weights[1][idx];
1674*61046927SAndroid Build Coastguard Worker w[0] = w[1] = w[2] = w[3] = w0;
1675*61046927SAndroid Build Coastguard Worker w[colour_component_selector] = w1;
1676*61046927SAndroid Build Coastguard Worker } else {
1677*61046927SAndroid Build Coastguard Worker int w0 = infill_weights[0][idx];
1678*61046927SAndroid Build Coastguard Worker w[0] = w[1] = w[2] = w[3] = w0;
1679*61046927SAndroid Build Coastguard Worker }
1680*61046927SAndroid Build Coastguard Worker
1681*61046927SAndroid Build Coastguard Worker /* Interpolate to produce UNORM16, applying weights. */
1682*61046927SAndroid Build Coastguard Worker uint16_t c[4] = {
1683*61046927SAndroid Build Coastguard Worker (uint16_t)((c0[0] * (64 - w[0]) + c1[0] * w[0] + 32) >> 6),
1684*61046927SAndroid Build Coastguard Worker (uint16_t)((c0[1] * (64 - w[1]) + c1[1] * w[1] + 32) >> 6),
1685*61046927SAndroid Build Coastguard Worker (uint16_t)((c0[2] * (64 - w[2]) + c1[2] * w[2] + 32) >> 6),
1686*61046927SAndroid Build Coastguard Worker (uint16_t)((c0[3] * (64 - w[3]) + c1[3] * w[3] + 32) >> 6),
1687*61046927SAndroid Build Coastguard Worker };
1688*61046927SAndroid Build Coastguard Worker
1689*61046927SAndroid Build Coastguard Worker if (decoder.output_unorm8) {
1690*61046927SAndroid Build Coastguard Worker output[idx*4+0] = c[0] >> 8;
1691*61046927SAndroid Build Coastguard Worker output[idx*4+1] = c[1] >> 8;
1692*61046927SAndroid Build Coastguard Worker output[idx*4+2] = c[2] >> 8;
1693*61046927SAndroid Build Coastguard Worker output[idx*4+3] = c[3] >> 8;
1694*61046927SAndroid Build Coastguard Worker } else {
1695*61046927SAndroid Build Coastguard Worker /* Store the color as FP16. */
1696*61046927SAndroid Build Coastguard Worker output[idx*4+0] = c[0] == 65535 ? FP16_ONE : _mesa_uint16_div_64k_to_half(c[0]);
1697*61046927SAndroid Build Coastguard Worker output[idx*4+1] = c[1] == 65535 ? FP16_ONE : _mesa_uint16_div_64k_to_half(c[1]);
1698*61046927SAndroid Build Coastguard Worker output[idx*4+2] = c[2] == 65535 ? FP16_ONE : _mesa_uint16_div_64k_to_half(c[2]);
1699*61046927SAndroid Build Coastguard Worker output[idx*4+3] = c[3] == 65535 ? FP16_ONE : _mesa_uint16_div_64k_to_half(c[3]);
1700*61046927SAndroid Build Coastguard Worker }
1701*61046927SAndroid Build Coastguard Worker
1702*61046927SAndroid Build Coastguard Worker idx++;
1703*61046927SAndroid Build Coastguard Worker }
1704*61046927SAndroid Build Coastguard Worker }
1705*61046927SAndroid Build Coastguard Worker }
1706*61046927SAndroid Build Coastguard Worker }
1707*61046927SAndroid Build Coastguard Worker
calculate_from_weights()1708*61046927SAndroid Build Coastguard Worker void Block::calculate_from_weights()
1709*61046927SAndroid Build Coastguard Worker {
1710*61046927SAndroid Build Coastguard Worker wt_trits = 0;
1711*61046927SAndroid Build Coastguard Worker wt_quints = 0;
1712*61046927SAndroid Build Coastguard Worker wt_bits = 0;
1713*61046927SAndroid Build Coastguard Worker switch (high_prec) {
1714*61046927SAndroid Build Coastguard Worker case 0:
1715*61046927SAndroid Build Coastguard Worker switch (wt_range) {
1716*61046927SAndroid Build Coastguard Worker case 0x2: wt_max = 1; wt_bits = 1; break;
1717*61046927SAndroid Build Coastguard Worker case 0x3: wt_max = 2; wt_trits = 1; break;
1718*61046927SAndroid Build Coastguard Worker case 0x4: wt_max = 3; wt_bits = 2; break;
1719*61046927SAndroid Build Coastguard Worker case 0x5: wt_max = 4; wt_quints = 1; break;
1720*61046927SAndroid Build Coastguard Worker case 0x6: wt_max = 5; wt_trits = 1; wt_bits = 1; break;
1721*61046927SAndroid Build Coastguard Worker case 0x7: wt_max = 7; wt_bits = 3; break;
1722*61046927SAndroid Build Coastguard Worker default: abort();
1723*61046927SAndroid Build Coastguard Worker }
1724*61046927SAndroid Build Coastguard Worker break;
1725*61046927SAndroid Build Coastguard Worker case 1:
1726*61046927SAndroid Build Coastguard Worker switch (wt_range) {
1727*61046927SAndroid Build Coastguard Worker case 0x2: wt_max = 9; wt_quints = 1; wt_bits = 1; break;
1728*61046927SAndroid Build Coastguard Worker case 0x3: wt_max = 11; wt_trits = 1; wt_bits = 2; break;
1729*61046927SAndroid Build Coastguard Worker case 0x4: wt_max = 15; wt_bits = 4; break;
1730*61046927SAndroid Build Coastguard Worker case 0x5: wt_max = 19; wt_quints = 1; wt_bits = 2; break;
1731*61046927SAndroid Build Coastguard Worker case 0x6: wt_max = 23; wt_trits = 1; wt_bits = 3; break;
1732*61046927SAndroid Build Coastguard Worker case 0x7: wt_max = 31; wt_bits = 5; break;
1733*61046927SAndroid Build Coastguard Worker default: abort();
1734*61046927SAndroid Build Coastguard Worker }
1735*61046927SAndroid Build Coastguard Worker break;
1736*61046927SAndroid Build Coastguard Worker }
1737*61046927SAndroid Build Coastguard Worker
1738*61046927SAndroid Build Coastguard Worker assert(wt_trits || wt_quints || wt_bits);
1739*61046927SAndroid Build Coastguard Worker
1740*61046927SAndroid Build Coastguard Worker num_weights = wt_w * wt_h * wt_d;
1741*61046927SAndroid Build Coastguard Worker
1742*61046927SAndroid Build Coastguard Worker if (dual_plane)
1743*61046927SAndroid Build Coastguard Worker num_weights *= 2;
1744*61046927SAndroid Build Coastguard Worker
1745*61046927SAndroid Build Coastguard Worker weight_bits =
1746*61046927SAndroid Build Coastguard Worker (num_weights * 8 * wt_trits + 4) / 5
1747*61046927SAndroid Build Coastguard Worker + (num_weights * 7 * wt_quints + 2) / 3
1748*61046927SAndroid Build Coastguard Worker + num_weights * wt_bits;
1749*61046927SAndroid Build Coastguard Worker }
1750*61046927SAndroid Build Coastguard Worker
calculate_remaining_bits()1751*61046927SAndroid Build Coastguard Worker void Block::calculate_remaining_bits()
1752*61046927SAndroid Build Coastguard Worker {
1753*61046927SAndroid Build Coastguard Worker int config_bits;
1754*61046927SAndroid Build Coastguard Worker if (num_parts > 1) {
1755*61046927SAndroid Build Coastguard Worker if (!is_multi_cem)
1756*61046927SAndroid Build Coastguard Worker config_bits = 29;
1757*61046927SAndroid Build Coastguard Worker else
1758*61046927SAndroid Build Coastguard Worker config_bits = 25 + 3 * num_parts;
1759*61046927SAndroid Build Coastguard Worker } else {
1760*61046927SAndroid Build Coastguard Worker config_bits = 17;
1761*61046927SAndroid Build Coastguard Worker }
1762*61046927SAndroid Build Coastguard Worker
1763*61046927SAndroid Build Coastguard Worker if (dual_plane)
1764*61046927SAndroid Build Coastguard Worker config_bits += 2;
1765*61046927SAndroid Build Coastguard Worker
1766*61046927SAndroid Build Coastguard Worker remaining_bits = 128 - config_bits - weight_bits;
1767*61046927SAndroid Build Coastguard Worker }
1768*61046927SAndroid Build Coastguard Worker
calculate_colour_endpoints_size()1769*61046927SAndroid Build Coastguard Worker decode_error::type Block::calculate_colour_endpoints_size()
1770*61046927SAndroid Build Coastguard Worker {
1771*61046927SAndroid Build Coastguard Worker /* Specified as illegal */
1772*61046927SAndroid Build Coastguard Worker if (remaining_bits < (13 * num_cem_values + 4) / 5) {
1773*61046927SAndroid Build Coastguard Worker colour_endpoint_bits = ce_max = ce_trits = ce_quints = ce_bits = 0;
1774*61046927SAndroid Build Coastguard Worker return decode_error::invalid_colour_endpoints_size;
1775*61046927SAndroid Build Coastguard Worker }
1776*61046927SAndroid Build Coastguard Worker
1777*61046927SAndroid Build Coastguard Worker /* Find the largest cem_ranges that fits within remaining_bits */
1778*61046927SAndroid Build Coastguard Worker for (int i = ARRAY_SIZE(cem_ranges)-1; i >= 0; --i) {
1779*61046927SAndroid Build Coastguard Worker int cem_bits;
1780*61046927SAndroid Build Coastguard Worker cem_bits = (num_cem_values * 8 * cem_ranges[i].t + 4) / 5
1781*61046927SAndroid Build Coastguard Worker + (num_cem_values * 7 * cem_ranges[i].q + 2) / 3
1782*61046927SAndroid Build Coastguard Worker + num_cem_values * cem_ranges[i].b;
1783*61046927SAndroid Build Coastguard Worker
1784*61046927SAndroid Build Coastguard Worker if (cem_bits <= remaining_bits)
1785*61046927SAndroid Build Coastguard Worker {
1786*61046927SAndroid Build Coastguard Worker colour_endpoint_bits = cem_bits;
1787*61046927SAndroid Build Coastguard Worker ce_max = cem_ranges[i].max;
1788*61046927SAndroid Build Coastguard Worker ce_trits = cem_ranges[i].t;
1789*61046927SAndroid Build Coastguard Worker ce_quints = cem_ranges[i].q;
1790*61046927SAndroid Build Coastguard Worker ce_bits = cem_ranges[i].b;
1791*61046927SAndroid Build Coastguard Worker return decode_error::ok;
1792*61046927SAndroid Build Coastguard Worker }
1793*61046927SAndroid Build Coastguard Worker }
1794*61046927SAndroid Build Coastguard Worker
1795*61046927SAndroid Build Coastguard Worker assert(0);
1796*61046927SAndroid Build Coastguard Worker return decode_error::invalid_colour_endpoints_size;
1797*61046927SAndroid Build Coastguard Worker }
1798*61046927SAndroid Build Coastguard Worker
1799*61046927SAndroid Build Coastguard Worker /**
1800*61046927SAndroid Build Coastguard Worker * Decode ASTC 2D LDR texture data.
1801*61046927SAndroid Build Coastguard Worker *
1802*61046927SAndroid Build Coastguard Worker * \param src_width in pixels
1803*61046927SAndroid Build Coastguard Worker * \param src_height in pixels
1804*61046927SAndroid Build Coastguard Worker * \param dst_stride in bytes
1805*61046927SAndroid Build Coastguard Worker */
1806*61046927SAndroid Build Coastguard Worker extern "C" void
_mesa_unpack_astc_2d_ldr(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned src_width,unsigned src_height,mesa_format format)1807*61046927SAndroid Build Coastguard Worker _mesa_unpack_astc_2d_ldr(uint8_t *dst_row,
1808*61046927SAndroid Build Coastguard Worker unsigned dst_stride,
1809*61046927SAndroid Build Coastguard Worker const uint8_t *src_row,
1810*61046927SAndroid Build Coastguard Worker unsigned src_stride,
1811*61046927SAndroid Build Coastguard Worker unsigned src_width,
1812*61046927SAndroid Build Coastguard Worker unsigned src_height,
1813*61046927SAndroid Build Coastguard Worker mesa_format format)
1814*61046927SAndroid Build Coastguard Worker {
1815*61046927SAndroid Build Coastguard Worker assert(_mesa_is_format_astc_2d(format));
1816*61046927SAndroid Build Coastguard Worker bool srgb = _mesa_is_format_srgb(format);
1817*61046927SAndroid Build Coastguard Worker
1818*61046927SAndroid Build Coastguard Worker unsigned blk_w, blk_h;
1819*61046927SAndroid Build Coastguard Worker _mesa_get_format_block_size(format, &blk_w, &blk_h);
1820*61046927SAndroid Build Coastguard Worker
1821*61046927SAndroid Build Coastguard Worker const unsigned block_size = 16;
1822*61046927SAndroid Build Coastguard Worker unsigned x_blocks = (src_width + blk_w - 1) / blk_w;
1823*61046927SAndroid Build Coastguard Worker unsigned y_blocks = (src_height + blk_h - 1) / blk_h;
1824*61046927SAndroid Build Coastguard Worker
1825*61046927SAndroid Build Coastguard Worker Decoder dec(blk_w, blk_h, 1, srgb, true);
1826*61046927SAndroid Build Coastguard Worker
1827*61046927SAndroid Build Coastguard Worker for (unsigned y = 0; y < y_blocks; ++y) {
1828*61046927SAndroid Build Coastguard Worker for (unsigned x = 0; x < x_blocks; ++x) {
1829*61046927SAndroid Build Coastguard Worker /* Same size as the largest block. */
1830*61046927SAndroid Build Coastguard Worker uint16_t block_out[12 * 12 * 4];
1831*61046927SAndroid Build Coastguard Worker
1832*61046927SAndroid Build Coastguard Worker dec.decode(src_row + x * block_size, block_out);
1833*61046927SAndroid Build Coastguard Worker
1834*61046927SAndroid Build Coastguard Worker /* This can be smaller with NPOT dimensions. */
1835*61046927SAndroid Build Coastguard Worker unsigned dst_blk_w = MIN2(blk_w, src_width - x*blk_w);
1836*61046927SAndroid Build Coastguard Worker unsigned dst_blk_h = MIN2(blk_h, src_height - y*blk_h);
1837*61046927SAndroid Build Coastguard Worker
1838*61046927SAndroid Build Coastguard Worker for (unsigned sub_y = 0; sub_y < dst_blk_h; ++sub_y) {
1839*61046927SAndroid Build Coastguard Worker for (unsigned sub_x = 0; sub_x < dst_blk_w; ++sub_x) {
1840*61046927SAndroid Build Coastguard Worker uint8_t *dst = dst_row + sub_y * dst_stride +
1841*61046927SAndroid Build Coastguard Worker (x * blk_w + sub_x) * 4;
1842*61046927SAndroid Build Coastguard Worker const uint16_t *src = &block_out[(sub_y * blk_w + sub_x) * 4];
1843*61046927SAndroid Build Coastguard Worker
1844*61046927SAndroid Build Coastguard Worker dst[0] = src[0];
1845*61046927SAndroid Build Coastguard Worker dst[1] = src[1];
1846*61046927SAndroid Build Coastguard Worker dst[2] = src[2];
1847*61046927SAndroid Build Coastguard Worker dst[3] = src[3];
1848*61046927SAndroid Build Coastguard Worker }
1849*61046927SAndroid Build Coastguard Worker }
1850*61046927SAndroid Build Coastguard Worker }
1851*61046927SAndroid Build Coastguard Worker src_row += src_stride;
1852*61046927SAndroid Build Coastguard Worker dst_row += dst_stride * blk_h;
1853*61046927SAndroid Build Coastguard Worker }
1854*61046927SAndroid Build Coastguard Worker }
1855