xref: /aosp_15_r20/external/deqp/framework/common/tcuAstcUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Tester Core
3*35238bceSAndroid Build Coastguard Worker  * ----------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2016 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief ASTC Utilities.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "tcuAstcUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deFloat16.h"
26*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deMeta.hpp"
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker #include <algorithm>
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker namespace tcu
32*35238bceSAndroid Build Coastguard Worker {
33*35238bceSAndroid Build Coastguard Worker namespace astc
34*35238bceSAndroid Build Coastguard Worker {
35*35238bceSAndroid Build Coastguard Worker 
36*35238bceSAndroid Build Coastguard Worker using std::vector;
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker namespace
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker // Common utilities
42*35238bceSAndroid Build Coastguard Worker 
43*35238bceSAndroid Build Coastguard Worker enum
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker     MAX_BLOCK_WIDTH  = 12,
46*35238bceSAndroid Build Coastguard Worker     MAX_BLOCK_HEIGHT = 12
47*35238bceSAndroid Build Coastguard Worker };
48*35238bceSAndroid Build Coastguard Worker 
getBit(uint32_t src,int ndx)49*35238bceSAndroid Build Coastguard Worker inline uint32_t getBit(uint32_t src, int ndx)
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inBounds(ndx, 0, 32));
52*35238bceSAndroid Build Coastguard Worker     return (src >> ndx) & 1;
53*35238bceSAndroid Build Coastguard Worker }
54*35238bceSAndroid Build Coastguard Worker 
getBits(uint32_t src,int low,int high)55*35238bceSAndroid Build Coastguard Worker inline uint32_t getBits(uint32_t src, int low, int high)
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker     const int numBits = (high - low) + 1;
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numBits, 1, 32));
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     if (numBits < 32)
62*35238bceSAndroid Build Coastguard Worker         return (uint32_t)((src >> low) & ((1u << numBits) - 1));
63*35238bceSAndroid Build Coastguard Worker     else
64*35238bceSAndroid Build Coastguard Worker         return (uint32_t)((src >> low) & 0xFFFFFFFFu);
65*35238bceSAndroid Build Coastguard Worker }
66*35238bceSAndroid Build Coastguard Worker 
isBitSet(uint32_t src,int ndx)67*35238bceSAndroid Build Coastguard Worker inline bool isBitSet(uint32_t src, int ndx)
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker     return getBit(src, ndx) != 0;
70*35238bceSAndroid Build Coastguard Worker }
71*35238bceSAndroid Build Coastguard Worker 
reverseBits(uint32_t src,int numBits)72*35238bceSAndroid Build Coastguard Worker inline uint32_t reverseBits(uint32_t src, int numBits)
73*35238bceSAndroid Build Coastguard Worker {
74*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numBits, 0, 32));
75*35238bceSAndroid Build Coastguard Worker     uint32_t result = 0;
76*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < numBits; i++)
77*35238bceSAndroid Build Coastguard Worker         result |= ((src >> i) & 1) << (numBits - 1 - i);
78*35238bceSAndroid Build Coastguard Worker     return result;
79*35238bceSAndroid Build Coastguard Worker }
80*35238bceSAndroid Build Coastguard Worker 
bitReplicationScale(uint32_t src,int numSrcBits,int numDstBits)81*35238bceSAndroid Build Coastguard Worker inline uint32_t bitReplicationScale(uint32_t src, int numSrcBits, int numDstBits)
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numSrcBits <= numDstBits);
84*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((src & ((1 << numSrcBits) - 1)) == src);
85*35238bceSAndroid Build Coastguard Worker     uint32_t dst = 0;
86*35238bceSAndroid Build Coastguard Worker     for (int shift = numDstBits - numSrcBits; shift > -numSrcBits; shift -= numSrcBits)
87*35238bceSAndroid Build Coastguard Worker         dst |= shift >= 0 ? src << shift : src >> -shift;
88*35238bceSAndroid Build Coastguard Worker     return dst;
89*35238bceSAndroid Build Coastguard Worker }
90*35238bceSAndroid Build Coastguard Worker 
signExtend(int32_t src,int numSrcBits)91*35238bceSAndroid Build Coastguard Worker inline int32_t signExtend(int32_t src, int numSrcBits)
92*35238bceSAndroid Build Coastguard Worker {
93*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numSrcBits, 2, 31));
94*35238bceSAndroid Build Coastguard Worker     const bool negative = (src & (1 << (numSrcBits - 1))) != 0;
95*35238bceSAndroid Build Coastguard Worker     return src | (negative ? ~((1 << numSrcBits) - 1) : 0);
96*35238bceSAndroid Build Coastguard Worker }
97*35238bceSAndroid Build Coastguard Worker 
isFloat16InfOrNan(deFloat16 v)98*35238bceSAndroid Build Coastguard Worker inline bool isFloat16InfOrNan(deFloat16 v)
99*35238bceSAndroid Build Coastguard Worker {
100*35238bceSAndroid Build Coastguard Worker     return getBits(v, 10, 14) == 31;
101*35238bceSAndroid Build Coastguard Worker }
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker enum ISEMode
104*35238bceSAndroid Build Coastguard Worker {
105*35238bceSAndroid Build Coastguard Worker     ISEMODE_TRIT = 0,
106*35238bceSAndroid Build Coastguard Worker     ISEMODE_QUINT,
107*35238bceSAndroid Build Coastguard Worker     ISEMODE_PLAIN_BIT,
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker     ISEMODE_LAST
110*35238bceSAndroid Build Coastguard Worker };
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker struct ISEParams
113*35238bceSAndroid Build Coastguard Worker {
114*35238bceSAndroid Build Coastguard Worker     ISEMode mode;
115*35238bceSAndroid Build Coastguard Worker     int numBits;
116*35238bceSAndroid Build Coastguard Worker 
ISEParamstcu::astc::__anone0fc7f7b0111::ISEParams117*35238bceSAndroid Build Coastguard Worker     ISEParams(ISEMode mode_, int numBits_) : mode(mode_), numBits(numBits_)
118*35238bceSAndroid Build Coastguard Worker     {
119*35238bceSAndroid Build Coastguard Worker     }
120*35238bceSAndroid Build Coastguard Worker };
121*35238bceSAndroid Build Coastguard Worker 
computeNumRequiredBits(const ISEParams & iseParams,int numValues)122*35238bceSAndroid Build Coastguard Worker inline int computeNumRequiredBits(const ISEParams &iseParams, int numValues)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker     switch (iseParams.mode)
125*35238bceSAndroid Build Coastguard Worker     {
126*35238bceSAndroid Build Coastguard Worker     case ISEMODE_TRIT:
127*35238bceSAndroid Build Coastguard Worker         return deDivRoundUp32(numValues * 8, 5) + numValues * iseParams.numBits;
128*35238bceSAndroid Build Coastguard Worker     case ISEMODE_QUINT:
129*35238bceSAndroid Build Coastguard Worker         return deDivRoundUp32(numValues * 7, 3) + numValues * iseParams.numBits;
130*35238bceSAndroid Build Coastguard Worker     case ISEMODE_PLAIN_BIT:
131*35238bceSAndroid Build Coastguard Worker         return numValues * iseParams.numBits;
132*35238bceSAndroid Build Coastguard Worker     default:
133*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
134*35238bceSAndroid Build Coastguard Worker         return -1;
135*35238bceSAndroid Build Coastguard Worker     }
136*35238bceSAndroid Build Coastguard Worker }
137*35238bceSAndroid Build Coastguard Worker 
computeMaximumRangeISEParams(int numAvailableBits,int numValuesInSequence)138*35238bceSAndroid Build Coastguard Worker ISEParams computeMaximumRangeISEParams(int numAvailableBits, int numValuesInSequence)
139*35238bceSAndroid Build Coastguard Worker {
140*35238bceSAndroid Build Coastguard Worker     int curBitsForTritMode     = 6;
141*35238bceSAndroid Build Coastguard Worker     int curBitsForQuintMode    = 5;
142*35238bceSAndroid Build Coastguard Worker     int curBitsForPlainBitMode = 8;
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker     while (true)
145*35238bceSAndroid Build Coastguard Worker     {
146*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(curBitsForTritMode > 0 || curBitsForQuintMode > 0 || curBitsForPlainBitMode > 0);
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker         const int tritRange     = curBitsForTritMode > 0 ? (3 << curBitsForTritMode) - 1 : -1;
149*35238bceSAndroid Build Coastguard Worker         const int quintRange    = curBitsForQuintMode > 0 ? (5 << curBitsForQuintMode) - 1 : -1;
150*35238bceSAndroid Build Coastguard Worker         const int plainBitRange = curBitsForPlainBitMode > 0 ? (1 << curBitsForPlainBitMode) - 1 : -1;
151*35238bceSAndroid Build Coastguard Worker         const int maxRange      = de::max(de::max(tritRange, quintRange), plainBitRange);
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker         if (maxRange == tritRange)
154*35238bceSAndroid Build Coastguard Worker         {
155*35238bceSAndroid Build Coastguard Worker             const ISEParams params(ISEMODE_TRIT, curBitsForTritMode);
156*35238bceSAndroid Build Coastguard Worker             if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
157*35238bceSAndroid Build Coastguard Worker                 return ISEParams(ISEMODE_TRIT, curBitsForTritMode);
158*35238bceSAndroid Build Coastguard Worker             curBitsForTritMode--;
159*35238bceSAndroid Build Coastguard Worker         }
160*35238bceSAndroid Build Coastguard Worker         else if (maxRange == quintRange)
161*35238bceSAndroid Build Coastguard Worker         {
162*35238bceSAndroid Build Coastguard Worker             const ISEParams params(ISEMODE_QUINT, curBitsForQuintMode);
163*35238bceSAndroid Build Coastguard Worker             if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
164*35238bceSAndroid Build Coastguard Worker                 return ISEParams(ISEMODE_QUINT, curBitsForQuintMode);
165*35238bceSAndroid Build Coastguard Worker             curBitsForQuintMode--;
166*35238bceSAndroid Build Coastguard Worker         }
167*35238bceSAndroid Build Coastguard Worker         else
168*35238bceSAndroid Build Coastguard Worker         {
169*35238bceSAndroid Build Coastguard Worker             const ISEParams params(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
170*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(maxRange == plainBitRange);
171*35238bceSAndroid Build Coastguard Worker             if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
172*35238bceSAndroid Build Coastguard Worker                 return ISEParams(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
173*35238bceSAndroid Build Coastguard Worker             curBitsForPlainBitMode--;
174*35238bceSAndroid Build Coastguard Worker         }
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker }
177*35238bceSAndroid Build Coastguard Worker 
computeNumColorEndpointValues(uint32_t endpointMode)178*35238bceSAndroid Build Coastguard Worker inline int computeNumColorEndpointValues(uint32_t endpointMode)
179*35238bceSAndroid Build Coastguard Worker {
180*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(endpointMode < 16);
181*35238bceSAndroid Build Coastguard Worker     return (endpointMode / 4 + 1) * 2;
182*35238bceSAndroid Build Coastguard Worker }
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker // Decompression utilities
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker enum DecompressResult
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker     DECOMPRESS_RESULT_VALID_BLOCK = 0, //!< Decompressed valid block
189*35238bceSAndroid Build Coastguard Worker     DECOMPRESS_RESULT_ERROR,           //!< Encountered error while decompressing, error color written
190*35238bceSAndroid Build Coastguard Worker 
191*35238bceSAndroid Build Coastguard Worker     DECOMPRESS_RESULT_LAST
192*35238bceSAndroid Build Coastguard Worker };
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker // A helper for getting bits from a 128-bit block.
195*35238bceSAndroid Build Coastguard Worker class Block128
196*35238bceSAndroid Build Coastguard Worker {
197*35238bceSAndroid Build Coastguard Worker private:
198*35238bceSAndroid Build Coastguard Worker     typedef uint64_t Word;
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker     enum
201*35238bceSAndroid Build Coastguard Worker     {
202*35238bceSAndroid Build Coastguard Worker         WORD_BYTES = sizeof(Word),
203*35238bceSAndroid Build Coastguard Worker         WORD_BITS  = 8 * WORD_BYTES,
204*35238bceSAndroid Build Coastguard Worker         NUM_WORDS  = 128 / WORD_BITS
205*35238bceSAndroid Build Coastguard Worker     };
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(128 % WORD_BITS == 0);
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker public:
Block128(const uint8_t * src)210*35238bceSAndroid Build Coastguard Worker     Block128(const uint8_t *src)
211*35238bceSAndroid Build Coastguard Worker     {
212*35238bceSAndroid Build Coastguard Worker         for (int wordNdx = 0; wordNdx < NUM_WORDS; wordNdx++)
213*35238bceSAndroid Build Coastguard Worker         {
214*35238bceSAndroid Build Coastguard Worker             m_words[wordNdx] = 0;
215*35238bceSAndroid Build Coastguard Worker             for (int byteNdx = 0; byteNdx < WORD_BYTES; byteNdx++)
216*35238bceSAndroid Build Coastguard Worker                 m_words[wordNdx] |= (Word)src[wordNdx * WORD_BYTES + byteNdx] << (8 * byteNdx);
217*35238bceSAndroid Build Coastguard Worker         }
218*35238bceSAndroid Build Coastguard Worker     }
219*35238bceSAndroid Build Coastguard Worker 
getBit(int ndx) const220*35238bceSAndroid Build Coastguard Worker     uint32_t getBit(int ndx) const
221*35238bceSAndroid Build Coastguard Worker     {
222*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(ndx, 0, 128));
223*35238bceSAndroid Build Coastguard Worker         return (m_words[ndx / WORD_BITS] >> (ndx % WORD_BITS)) & 1;
224*35238bceSAndroid Build Coastguard Worker     }
225*35238bceSAndroid Build Coastguard Worker 
getBits(int low,int high) const226*35238bceSAndroid Build Coastguard Worker     uint32_t getBits(int low, int high) const
227*35238bceSAndroid Build Coastguard Worker     {
228*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(low, 0, 128));
229*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(high, 0, 128));
230*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inRange(high - low + 1, 0, 32));
231*35238bceSAndroid Build Coastguard Worker 
232*35238bceSAndroid Build Coastguard Worker         if (high - low + 1 == 0)
233*35238bceSAndroid Build Coastguard Worker             return 0;
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker         const int word0Ndx = low / WORD_BITS;
236*35238bceSAndroid Build Coastguard Worker         const int word1Ndx = high / WORD_BITS;
237*35238bceSAndroid Build Coastguard Worker 
238*35238bceSAndroid Build Coastguard Worker         // \note "foo << bar << 1" done instead of "foo << (bar+1)" to avoid overflow, i.e. shift amount being too big.
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker         if (word0Ndx == word1Ndx)
241*35238bceSAndroid Build Coastguard Worker             return (uint32_t)((m_words[word0Ndx] & ((((Word)1 << high % WORD_BITS << 1) - 1))) >>
242*35238bceSAndroid Build Coastguard Worker                               ((Word)low % WORD_BITS));
243*35238bceSAndroid Build Coastguard Worker         else
244*35238bceSAndroid Build Coastguard Worker         {
245*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(word1Ndx == word0Ndx + 1);
246*35238bceSAndroid Build Coastguard Worker 
247*35238bceSAndroid Build Coastguard Worker             return (uint32_t)(m_words[word0Ndx] >> (low % WORD_BITS)) |
248*35238bceSAndroid Build Coastguard Worker                    (uint32_t)((m_words[word1Ndx] & (((Word)1 << high % WORD_BITS << 1) - 1))
249*35238bceSAndroid Build Coastguard Worker                               << (high - low - high % WORD_BITS));
250*35238bceSAndroid Build Coastguard Worker         }
251*35238bceSAndroid Build Coastguard Worker     }
252*35238bceSAndroid Build Coastguard Worker 
isBitSet(int ndx) const253*35238bceSAndroid Build Coastguard Worker     bool isBitSet(int ndx) const
254*35238bceSAndroid Build Coastguard Worker     {
255*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(ndx, 0, 128));
256*35238bceSAndroid Build Coastguard Worker         return getBit(ndx) != 0;
257*35238bceSAndroid Build Coastguard Worker     }
258*35238bceSAndroid Build Coastguard Worker 
259*35238bceSAndroid Build Coastguard Worker private:
260*35238bceSAndroid Build Coastguard Worker     Word m_words[NUM_WORDS];
261*35238bceSAndroid Build Coastguard Worker };
262*35238bceSAndroid Build Coastguard Worker 
263*35238bceSAndroid Build Coastguard Worker // A helper for sequential access into a Block128.
264*35238bceSAndroid Build Coastguard Worker class BitAccessStream
265*35238bceSAndroid Build Coastguard Worker {
266*35238bceSAndroid Build Coastguard Worker public:
BitAccessStream(const Block128 & src,int startNdxInSrc,int length,bool forward)267*35238bceSAndroid Build Coastguard Worker     BitAccessStream(const Block128 &src, int startNdxInSrc, int length, bool forward)
268*35238bceSAndroid Build Coastguard Worker         : m_src(src)
269*35238bceSAndroid Build Coastguard Worker         , m_startNdxInSrc(startNdxInSrc)
270*35238bceSAndroid Build Coastguard Worker         , m_length(length)
271*35238bceSAndroid Build Coastguard Worker         , m_forward(forward)
272*35238bceSAndroid Build Coastguard Worker         , m_ndx(0)
273*35238bceSAndroid Build Coastguard Worker     {
274*35238bceSAndroid Build Coastguard Worker     }
275*35238bceSAndroid Build Coastguard Worker 
276*35238bceSAndroid Build Coastguard Worker     // Get the next num bits. Bits at positions greater than or equal to m_length are zeros.
getNext(int num)277*35238bceSAndroid Build Coastguard Worker     uint32_t getNext(int num)
278*35238bceSAndroid Build Coastguard Worker     {
279*35238bceSAndroid Build Coastguard Worker         if (num == 0 || m_ndx >= m_length)
280*35238bceSAndroid Build Coastguard Worker             return 0;
281*35238bceSAndroid Build Coastguard Worker 
282*35238bceSAndroid Build Coastguard Worker         const int end            = m_ndx + num;
283*35238bceSAndroid Build Coastguard Worker         const int numBitsFromSrc = de::max(0, de::min(m_length, end) - m_ndx);
284*35238bceSAndroid Build Coastguard Worker         const int low            = m_ndx;
285*35238bceSAndroid Build Coastguard Worker         const int high           = m_ndx + numBitsFromSrc - 1;
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker         m_ndx += num;
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker         return m_forward ? m_src.getBits(m_startNdxInSrc + low, m_startNdxInSrc + high) :
290*35238bceSAndroid Build Coastguard Worker                            reverseBits(m_src.getBits(m_startNdxInSrc - high, m_startNdxInSrc - low), numBitsFromSrc);
291*35238bceSAndroid Build Coastguard Worker     }
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker private:
294*35238bceSAndroid Build Coastguard Worker     const Block128 &m_src;
295*35238bceSAndroid Build Coastguard Worker     const int m_startNdxInSrc;
296*35238bceSAndroid Build Coastguard Worker     const int m_length;
297*35238bceSAndroid Build Coastguard Worker     const bool m_forward;
298*35238bceSAndroid Build Coastguard Worker 
299*35238bceSAndroid Build Coastguard Worker     int m_ndx;
300*35238bceSAndroid Build Coastguard Worker };
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker struct ISEDecodedResult
303*35238bceSAndroid Build Coastguard Worker {
304*35238bceSAndroid Build Coastguard Worker     uint32_t m;
305*35238bceSAndroid Build Coastguard Worker     uint32_t tq; //!< Trit or quint value, depending on ISE mode.
306*35238bceSAndroid Build Coastguard Worker     uint32_t v;
307*35238bceSAndroid Build Coastguard Worker };
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker // Data from an ASTC block's "block mode" part (i.e. bits [0,10]).
310*35238bceSAndroid Build Coastguard Worker struct ASTCBlockMode
311*35238bceSAndroid Build Coastguard Worker {
312*35238bceSAndroid Build Coastguard Worker     bool isError;
313*35238bceSAndroid Build Coastguard Worker     // \note Following fields only relevant if !isError.
314*35238bceSAndroid Build Coastguard Worker     bool isVoidExtent;
315*35238bceSAndroid Build Coastguard Worker     // \note Following fields only relevant if !isVoidExtent.
316*35238bceSAndroid Build Coastguard Worker     bool isDualPlane;
317*35238bceSAndroid Build Coastguard Worker     int weightGridWidth;
318*35238bceSAndroid Build Coastguard Worker     int weightGridHeight;
319*35238bceSAndroid Build Coastguard Worker     ISEParams weightISEParams;
320*35238bceSAndroid Build Coastguard Worker 
ASTCBlockModetcu::astc::__anone0fc7f7b0111::ASTCBlockMode321*35238bceSAndroid Build Coastguard Worker     ASTCBlockMode(void)
322*35238bceSAndroid Build Coastguard Worker         : isError(true)
323*35238bceSAndroid Build Coastguard Worker         , isVoidExtent(true)
324*35238bceSAndroid Build Coastguard Worker         , isDualPlane(true)
325*35238bceSAndroid Build Coastguard Worker         , weightGridWidth(-1)
326*35238bceSAndroid Build Coastguard Worker         , weightGridHeight(-1)
327*35238bceSAndroid Build Coastguard Worker         , weightISEParams(ISEMODE_LAST, -1)
328*35238bceSAndroid Build Coastguard Worker     {
329*35238bceSAndroid Build Coastguard Worker     }
330*35238bceSAndroid Build Coastguard Worker };
331*35238bceSAndroid Build Coastguard Worker 
computeNumWeights(const ASTCBlockMode & mode)332*35238bceSAndroid Build Coastguard Worker inline int computeNumWeights(const ASTCBlockMode &mode)
333*35238bceSAndroid Build Coastguard Worker {
334*35238bceSAndroid Build Coastguard Worker     return mode.weightGridWidth * mode.weightGridHeight * (mode.isDualPlane ? 2 : 1);
335*35238bceSAndroid Build Coastguard Worker }
336*35238bceSAndroid Build Coastguard Worker 
337*35238bceSAndroid Build Coastguard Worker struct ColorEndpointPair
338*35238bceSAndroid Build Coastguard Worker {
339*35238bceSAndroid Build Coastguard Worker     UVec4 e0;
340*35238bceSAndroid Build Coastguard Worker     UVec4 e1;
341*35238bceSAndroid Build Coastguard Worker };
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker struct TexelWeightPair
344*35238bceSAndroid Build Coastguard Worker {
345*35238bceSAndroid Build Coastguard Worker     uint32_t w[2];
346*35238bceSAndroid Build Coastguard Worker };
347*35238bceSAndroid Build Coastguard Worker 
getASTCBlockMode(uint32_t blockModeData)348*35238bceSAndroid Build Coastguard Worker ASTCBlockMode getASTCBlockMode(uint32_t blockModeData)
349*35238bceSAndroid Build Coastguard Worker {
350*35238bceSAndroid Build Coastguard Worker     ASTCBlockMode blockMode;
351*35238bceSAndroid Build Coastguard Worker     blockMode.isError = true; // \note Set to false later, if not error.
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker     blockMode.isVoidExtent = getBits(blockModeData, 0, 8) == 0x1fc;
354*35238bceSAndroid Build Coastguard Worker 
355*35238bceSAndroid Build Coastguard Worker     if (!blockMode.isVoidExtent)
356*35238bceSAndroid Build Coastguard Worker     {
357*35238bceSAndroid Build Coastguard Worker         if ((getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 6, 8) == 7) ||
358*35238bceSAndroid Build Coastguard Worker             getBits(blockModeData, 0, 3) == 0)
359*35238bceSAndroid Build Coastguard Worker             return blockMode; // Invalid ("reserved").
360*35238bceSAndroid Build Coastguard Worker 
361*35238bceSAndroid Build Coastguard Worker         uint32_t r = (uint32_t)-1; // \note Set in the following branches.
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker         if (getBits(blockModeData, 0, 1) == 0)
364*35238bceSAndroid Build Coastguard Worker         {
365*35238bceSAndroid Build Coastguard Worker             const uint32_t r0  = getBit(blockModeData, 4);
366*35238bceSAndroid Build Coastguard Worker             const uint32_t r1  = getBit(blockModeData, 2);
367*35238bceSAndroid Build Coastguard Worker             const uint32_t r2  = getBit(blockModeData, 3);
368*35238bceSAndroid Build Coastguard Worker             const uint32_t i78 = getBits(blockModeData, 7, 8);
369*35238bceSAndroid Build Coastguard Worker 
370*35238bceSAndroid Build Coastguard Worker             r = (r2 << 2) | (r1 << 1) | (r0 << 0);
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker             if (i78 == 3)
373*35238bceSAndroid Build Coastguard Worker             {
374*35238bceSAndroid Build Coastguard Worker                 const bool i5              = isBitSet(blockModeData, 5);
375*35238bceSAndroid Build Coastguard Worker                 blockMode.weightGridWidth  = i5 ? 10 : 6;
376*35238bceSAndroid Build Coastguard Worker                 blockMode.weightGridHeight = i5 ? 6 : 10;
377*35238bceSAndroid Build Coastguard Worker             }
378*35238bceSAndroid Build Coastguard Worker             else
379*35238bceSAndroid Build Coastguard Worker             {
380*35238bceSAndroid Build Coastguard Worker                 const uint32_t a = getBits(blockModeData, 5, 6);
381*35238bceSAndroid Build Coastguard Worker                 switch (i78)
382*35238bceSAndroid Build Coastguard Worker                 {
383*35238bceSAndroid Build Coastguard Worker                 case 0:
384*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = 12;
385*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = a + 2;
386*35238bceSAndroid Build Coastguard Worker                     break;
387*35238bceSAndroid Build Coastguard Worker                 case 1:
388*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = a + 2;
389*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = 12;
390*35238bceSAndroid Build Coastguard Worker                     break;
391*35238bceSAndroid Build Coastguard Worker                 case 2:
392*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = a + 6;
393*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = getBits(blockModeData, 9, 10) + 6;
394*35238bceSAndroid Build Coastguard Worker                     break;
395*35238bceSAndroid Build Coastguard Worker                 default:
396*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
397*35238bceSAndroid Build Coastguard Worker                 }
398*35238bceSAndroid Build Coastguard Worker             }
399*35238bceSAndroid Build Coastguard Worker         }
400*35238bceSAndroid Build Coastguard Worker         else
401*35238bceSAndroid Build Coastguard Worker         {
402*35238bceSAndroid Build Coastguard Worker             const uint32_t r0  = getBit(blockModeData, 4);
403*35238bceSAndroid Build Coastguard Worker             const uint32_t r1  = getBit(blockModeData, 0);
404*35238bceSAndroid Build Coastguard Worker             const uint32_t r2  = getBit(blockModeData, 1);
405*35238bceSAndroid Build Coastguard Worker             const uint32_t i23 = getBits(blockModeData, 2, 3);
406*35238bceSAndroid Build Coastguard Worker             const uint32_t a   = getBits(blockModeData, 5, 6);
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker             r = (r2 << 2) | (r1 << 1) | (r0 << 0);
409*35238bceSAndroid Build Coastguard Worker 
410*35238bceSAndroid Build Coastguard Worker             if (i23 == 3)
411*35238bceSAndroid Build Coastguard Worker             {
412*35238bceSAndroid Build Coastguard Worker                 const uint32_t b           = getBit(blockModeData, 7);
413*35238bceSAndroid Build Coastguard Worker                 const bool i8              = isBitSet(blockModeData, 8);
414*35238bceSAndroid Build Coastguard Worker                 blockMode.weightGridWidth  = i8 ? b + 2 : a + 2;
415*35238bceSAndroid Build Coastguard Worker                 blockMode.weightGridHeight = i8 ? a + 2 : b + 6;
416*35238bceSAndroid Build Coastguard Worker             }
417*35238bceSAndroid Build Coastguard Worker             else
418*35238bceSAndroid Build Coastguard Worker             {
419*35238bceSAndroid Build Coastguard Worker                 const uint32_t b = getBits(blockModeData, 7, 8);
420*35238bceSAndroid Build Coastguard Worker 
421*35238bceSAndroid Build Coastguard Worker                 switch (i23)
422*35238bceSAndroid Build Coastguard Worker                 {
423*35238bceSAndroid Build Coastguard Worker                 case 0:
424*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = b + 4;
425*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = a + 2;
426*35238bceSAndroid Build Coastguard Worker                     break;
427*35238bceSAndroid Build Coastguard Worker                 case 1:
428*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = b + 8;
429*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = a + 2;
430*35238bceSAndroid Build Coastguard Worker                     break;
431*35238bceSAndroid Build Coastguard Worker                 case 2:
432*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridWidth  = a + 2;
433*35238bceSAndroid Build Coastguard Worker                     blockMode.weightGridHeight = b + 8;
434*35238bceSAndroid Build Coastguard Worker                     break;
435*35238bceSAndroid Build Coastguard Worker                 default:
436*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
437*35238bceSAndroid Build Coastguard Worker                 }
438*35238bceSAndroid Build Coastguard Worker             }
439*35238bceSAndroid Build Coastguard Worker         }
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker         const bool zeroDH     = getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 7, 8) == 2;
442*35238bceSAndroid Build Coastguard Worker         const bool h          = zeroDH ? 0 : isBitSet(blockModeData, 9);
443*35238bceSAndroid Build Coastguard Worker         blockMode.isDualPlane = zeroDH ? 0 : isBitSet(blockModeData, 10);
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker         {
446*35238bceSAndroid Build Coastguard Worker             ISEMode &m = blockMode.weightISEParams.mode;
447*35238bceSAndroid Build Coastguard Worker             int &b     = blockMode.weightISEParams.numBits;
448*35238bceSAndroid Build Coastguard Worker             m          = ISEMODE_PLAIN_BIT;
449*35238bceSAndroid Build Coastguard Worker             b          = 0;
450*35238bceSAndroid Build Coastguard Worker 
451*35238bceSAndroid Build Coastguard Worker             if (h)
452*35238bceSAndroid Build Coastguard Worker             {
453*35238bceSAndroid Build Coastguard Worker                 switch (r)
454*35238bceSAndroid Build Coastguard Worker                 {
455*35238bceSAndroid Build Coastguard Worker                 case 2:
456*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_QUINT;
457*35238bceSAndroid Build Coastguard Worker                     b = 1;
458*35238bceSAndroid Build Coastguard Worker                     break;
459*35238bceSAndroid Build Coastguard Worker                 case 3:
460*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_TRIT;
461*35238bceSAndroid Build Coastguard Worker                     b = 2;
462*35238bceSAndroid Build Coastguard Worker                     break;
463*35238bceSAndroid Build Coastguard Worker                 case 4:
464*35238bceSAndroid Build Coastguard Worker                     b = 4;
465*35238bceSAndroid Build Coastguard Worker                     break;
466*35238bceSAndroid Build Coastguard Worker                 case 5:
467*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_QUINT;
468*35238bceSAndroid Build Coastguard Worker                     b = 2;
469*35238bceSAndroid Build Coastguard Worker                     break;
470*35238bceSAndroid Build Coastguard Worker                 case 6:
471*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_TRIT;
472*35238bceSAndroid Build Coastguard Worker                     b = 3;
473*35238bceSAndroid Build Coastguard Worker                     break;
474*35238bceSAndroid Build Coastguard Worker                 case 7:
475*35238bceSAndroid Build Coastguard Worker                     b = 5;
476*35238bceSAndroid Build Coastguard Worker                     break;
477*35238bceSAndroid Build Coastguard Worker                 default:
478*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
479*35238bceSAndroid Build Coastguard Worker                 }
480*35238bceSAndroid Build Coastguard Worker             }
481*35238bceSAndroid Build Coastguard Worker             else
482*35238bceSAndroid Build Coastguard Worker             {
483*35238bceSAndroid Build Coastguard Worker                 switch (r)
484*35238bceSAndroid Build Coastguard Worker                 {
485*35238bceSAndroid Build Coastguard Worker                 case 2:
486*35238bceSAndroid Build Coastguard Worker                     b = 1;
487*35238bceSAndroid Build Coastguard Worker                     break;
488*35238bceSAndroid Build Coastguard Worker                 case 3:
489*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_TRIT;
490*35238bceSAndroid Build Coastguard Worker                     break;
491*35238bceSAndroid Build Coastguard Worker                 case 4:
492*35238bceSAndroid Build Coastguard Worker                     b = 2;
493*35238bceSAndroid Build Coastguard Worker                     break;
494*35238bceSAndroid Build Coastguard Worker                 case 5:
495*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_QUINT;
496*35238bceSAndroid Build Coastguard Worker                     break;
497*35238bceSAndroid Build Coastguard Worker                 case 6:
498*35238bceSAndroid Build Coastguard Worker                     m = ISEMODE_TRIT;
499*35238bceSAndroid Build Coastguard Worker                     b = 1;
500*35238bceSAndroid Build Coastguard Worker                     break;
501*35238bceSAndroid Build Coastguard Worker                 case 7:
502*35238bceSAndroid Build Coastguard Worker                     b = 3;
503*35238bceSAndroid Build Coastguard Worker                     break;
504*35238bceSAndroid Build Coastguard Worker                 default:
505*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
506*35238bceSAndroid Build Coastguard Worker                 }
507*35238bceSAndroid Build Coastguard Worker             }
508*35238bceSAndroid Build Coastguard Worker         }
509*35238bceSAndroid Build Coastguard Worker     }
510*35238bceSAndroid Build Coastguard Worker 
511*35238bceSAndroid Build Coastguard Worker     blockMode.isError = false;
512*35238bceSAndroid Build Coastguard Worker     return blockMode;
513*35238bceSAndroid Build Coastguard Worker }
514*35238bceSAndroid Build Coastguard Worker 
setASTCErrorColorBlock(void * dst,int blockWidth,int blockHeight,bool isSRGB)515*35238bceSAndroid Build Coastguard Worker inline void setASTCErrorColorBlock(void *dst, int blockWidth, int blockHeight, bool isSRGB)
516*35238bceSAndroid Build Coastguard Worker {
517*35238bceSAndroid Build Coastguard Worker     if (isSRGB)
518*35238bceSAndroid Build Coastguard Worker     {
519*35238bceSAndroid Build Coastguard Worker         uint8_t *const dstU = (uint8_t *)dst;
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < blockWidth * blockHeight; i++)
522*35238bceSAndroid Build Coastguard Worker         {
523*35238bceSAndroid Build Coastguard Worker             dstU[4 * i + 0] = 0xff;
524*35238bceSAndroid Build Coastguard Worker             dstU[4 * i + 1] = 0;
525*35238bceSAndroid Build Coastguard Worker             dstU[4 * i + 2] = 0xff;
526*35238bceSAndroid Build Coastguard Worker             dstU[4 * i + 3] = 0xff;
527*35238bceSAndroid Build Coastguard Worker         }
528*35238bceSAndroid Build Coastguard Worker     }
529*35238bceSAndroid Build Coastguard Worker     else
530*35238bceSAndroid Build Coastguard Worker     {
531*35238bceSAndroid Build Coastguard Worker         float *const dstF = (float *)dst;
532*35238bceSAndroid Build Coastguard Worker 
533*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < blockWidth * blockHeight; i++)
534*35238bceSAndroid Build Coastguard Worker         {
535*35238bceSAndroid Build Coastguard Worker             dstF[4 * i + 0] = 1.0f;
536*35238bceSAndroid Build Coastguard Worker             dstF[4 * i + 1] = 0.0f;
537*35238bceSAndroid Build Coastguard Worker             dstF[4 * i + 2] = 1.0f;
538*35238bceSAndroid Build Coastguard Worker             dstF[4 * i + 3] = 1.0f;
539*35238bceSAndroid Build Coastguard Worker         }
540*35238bceSAndroid Build Coastguard Worker     }
541*35238bceSAndroid Build Coastguard Worker }
542*35238bceSAndroid Build Coastguard Worker 
decodeVoidExtentBlock(void * dst,const Block128 & blockData,int blockWidth,int blockHeight,bool isSRGB,bool isLDRMode)543*35238bceSAndroid Build Coastguard Worker DecompressResult decodeVoidExtentBlock(void *dst, const Block128 &blockData, int blockWidth, int blockHeight,
544*35238bceSAndroid Build Coastguard Worker                                        bool isSRGB, bool isLDRMode)
545*35238bceSAndroid Build Coastguard Worker {
546*35238bceSAndroid Build Coastguard Worker     const uint32_t minSExtent = blockData.getBits(12, 24);
547*35238bceSAndroid Build Coastguard Worker     const uint32_t maxSExtent = blockData.getBits(25, 37);
548*35238bceSAndroid Build Coastguard Worker     const uint32_t minTExtent = blockData.getBits(38, 50);
549*35238bceSAndroid Build Coastguard Worker     const uint32_t maxTExtent = blockData.getBits(51, 63);
550*35238bceSAndroid Build Coastguard Worker     const bool allExtentsAllOnes =
551*35238bceSAndroid Build Coastguard Worker         minSExtent == 0x1fff && maxSExtent == 0x1fff && minTExtent == 0x1fff && maxTExtent == 0x1fff;
552*35238bceSAndroid Build Coastguard Worker     const bool isHDRBlock = blockData.isBitSet(9);
553*35238bceSAndroid Build Coastguard Worker 
554*35238bceSAndroid Build Coastguard Worker     if ((isLDRMode && isHDRBlock) || (!allExtentsAllOnes && (minSExtent >= maxSExtent || minTExtent >= maxTExtent)))
555*35238bceSAndroid Build Coastguard Worker     {
556*35238bceSAndroid Build Coastguard Worker         setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
557*35238bceSAndroid Build Coastguard Worker         return DECOMPRESS_RESULT_ERROR;
558*35238bceSAndroid Build Coastguard Worker     }
559*35238bceSAndroid Build Coastguard Worker 
560*35238bceSAndroid Build Coastguard Worker     const uint32_t rgba[4] = {blockData.getBits(64, 79), blockData.getBits(80, 95), blockData.getBits(96, 111),
561*35238bceSAndroid Build Coastguard Worker                               blockData.getBits(112, 127)};
562*35238bceSAndroid Build Coastguard Worker 
563*35238bceSAndroid Build Coastguard Worker     if (isSRGB)
564*35238bceSAndroid Build Coastguard Worker     {
565*35238bceSAndroid Build Coastguard Worker         uint8_t *const dstU = (uint8_t *)dst;
566*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < blockWidth * blockHeight; i++)
567*35238bceSAndroid Build Coastguard Worker             for (int c = 0; c < 4; c++)
568*35238bceSAndroid Build Coastguard Worker                 dstU[i * 4 + c] = (uint8_t)((rgba[c] & 0xff00) >> 8);
569*35238bceSAndroid Build Coastguard Worker     }
570*35238bceSAndroid Build Coastguard Worker     else
571*35238bceSAndroid Build Coastguard Worker     {
572*35238bceSAndroid Build Coastguard Worker         float *const dstF = (float *)dst;
573*35238bceSAndroid Build Coastguard Worker 
574*35238bceSAndroid Build Coastguard Worker         if (isHDRBlock)
575*35238bceSAndroid Build Coastguard Worker         {
576*35238bceSAndroid Build Coastguard Worker             for (int c = 0; c < 4; c++)
577*35238bceSAndroid Build Coastguard Worker             {
578*35238bceSAndroid Build Coastguard Worker                 if (isFloat16InfOrNan((deFloat16)rgba[c]))
579*35238bceSAndroid Build Coastguard Worker                     throw InternalError("Infinity or NaN color component in HDR void extent block in ASTC texture "
580*35238bceSAndroid Build Coastguard Worker                                         "(behavior undefined by ASTC specification)");
581*35238bceSAndroid Build Coastguard Worker             }
582*35238bceSAndroid Build Coastguard Worker 
583*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < blockWidth * blockHeight; i++)
584*35238bceSAndroid Build Coastguard Worker                 for (int c = 0; c < 4; c++)
585*35238bceSAndroid Build Coastguard Worker                     dstF[i * 4 + c] = deFloat16To32((deFloat16)rgba[c]);
586*35238bceSAndroid Build Coastguard Worker         }
587*35238bceSAndroid Build Coastguard Worker         else
588*35238bceSAndroid Build Coastguard Worker         {
589*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < blockWidth * blockHeight; i++)
590*35238bceSAndroid Build Coastguard Worker                 for (int c = 0; c < 4; c++)
591*35238bceSAndroid Build Coastguard Worker                     dstF[i * 4 + c] = rgba[c] == 65535 ? 1.0f : (float)rgba[c] / 65536.0f;
592*35238bceSAndroid Build Coastguard Worker         }
593*35238bceSAndroid Build Coastguard Worker     }
594*35238bceSAndroid Build Coastguard Worker 
595*35238bceSAndroid Build Coastguard Worker     return DECOMPRESS_RESULT_VALID_BLOCK;
596*35238bceSAndroid Build Coastguard Worker }
597*35238bceSAndroid Build Coastguard Worker 
decodeColorEndpointModes(uint32_t * endpointModesDst,const Block128 & blockData,int numPartitions,int extraCemBitsStart)598*35238bceSAndroid Build Coastguard Worker void decodeColorEndpointModes(uint32_t *endpointModesDst, const Block128 &blockData, int numPartitions,
599*35238bceSAndroid Build Coastguard Worker                               int extraCemBitsStart)
600*35238bceSAndroid Build Coastguard Worker {
601*35238bceSAndroid Build Coastguard Worker     if (numPartitions == 1)
602*35238bceSAndroid Build Coastguard Worker         endpointModesDst[0] = blockData.getBits(13, 16);
603*35238bceSAndroid Build Coastguard Worker     else
604*35238bceSAndroid Build Coastguard Worker     {
605*35238bceSAndroid Build Coastguard Worker         const uint32_t highLevelSelector = blockData.getBits(23, 24);
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker         if (highLevelSelector == 0)
608*35238bceSAndroid Build Coastguard Worker         {
609*35238bceSAndroid Build Coastguard Worker             const uint32_t mode = blockData.getBits(25, 28);
610*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < numPartitions; i++)
611*35238bceSAndroid Build Coastguard Worker                 endpointModesDst[i] = mode;
612*35238bceSAndroid Build Coastguard Worker         }
613*35238bceSAndroid Build Coastguard Worker         else
614*35238bceSAndroid Build Coastguard Worker         {
615*35238bceSAndroid Build Coastguard Worker             for (int partNdx = 0; partNdx < numPartitions; partNdx++)
616*35238bceSAndroid Build Coastguard Worker             {
617*35238bceSAndroid Build Coastguard Worker                 const uint32_t cemClass   = highLevelSelector - (blockData.isBitSet(25 + partNdx) ? 0 : 1);
618*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowBit0Ndx = numPartitions + 2 * partNdx;
619*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowBit1Ndx = numPartitions + 2 * partNdx + 1;
620*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowBit0 =
621*35238bceSAndroid Build Coastguard Worker                     blockData.getBit(lowBit0Ndx < 4 ? 25 + lowBit0Ndx : extraCemBitsStart + lowBit0Ndx - 4);
622*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowBit1 =
623*35238bceSAndroid Build Coastguard Worker                     blockData.getBit(lowBit1Ndx < 4 ? 25 + lowBit1Ndx : extraCemBitsStart + lowBit1Ndx - 4);
624*35238bceSAndroid Build Coastguard Worker 
625*35238bceSAndroid Build Coastguard Worker                 endpointModesDst[partNdx] = (cemClass << 2) | (lowBit1 << 1) | lowBit0;
626*35238bceSAndroid Build Coastguard Worker             }
627*35238bceSAndroid Build Coastguard Worker         }
628*35238bceSAndroid Build Coastguard Worker     }
629*35238bceSAndroid Build Coastguard Worker }
630*35238bceSAndroid Build Coastguard Worker 
computeNumColorEndpointValues(const uint32_t * endpointModes,int numPartitions)631*35238bceSAndroid Build Coastguard Worker int computeNumColorEndpointValues(const uint32_t *endpointModes, int numPartitions)
632*35238bceSAndroid Build Coastguard Worker {
633*35238bceSAndroid Build Coastguard Worker     int result = 0;
634*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < numPartitions; i++)
635*35238bceSAndroid Build Coastguard Worker         result += computeNumColorEndpointValues(endpointModes[i]);
636*35238bceSAndroid Build Coastguard Worker     return result;
637*35238bceSAndroid Build Coastguard Worker }
638*35238bceSAndroid Build Coastguard Worker 
decodeISETritBlock(ISEDecodedResult * dst,int numValues,BitAccessStream & data,int numBits)639*35238bceSAndroid Build Coastguard Worker void decodeISETritBlock(ISEDecodedResult *dst, int numValues, BitAccessStream &data, int numBits)
640*35238bceSAndroid Build Coastguard Worker {
641*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numValues, 1, 5));
642*35238bceSAndroid Build Coastguard Worker 
643*35238bceSAndroid Build Coastguard Worker     uint32_t m[5];
644*35238bceSAndroid Build Coastguard Worker 
645*35238bceSAndroid Build Coastguard Worker     m[0]         = data.getNext(numBits);
646*35238bceSAndroid Build Coastguard Worker     uint32_t T01 = data.getNext(2);
647*35238bceSAndroid Build Coastguard Worker     m[1]         = data.getNext(numBits);
648*35238bceSAndroid Build Coastguard Worker     uint32_t T23 = data.getNext(2);
649*35238bceSAndroid Build Coastguard Worker     m[2]         = data.getNext(numBits);
650*35238bceSAndroid Build Coastguard Worker     uint32_t T4  = data.getNext(1);
651*35238bceSAndroid Build Coastguard Worker     m[3]         = data.getNext(numBits);
652*35238bceSAndroid Build Coastguard Worker     uint32_t T56 = data.getNext(2);
653*35238bceSAndroid Build Coastguard Worker     m[4]         = data.getNext(numBits);
654*35238bceSAndroid Build Coastguard Worker     uint32_t T7  = data.getNext(1);
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker     switch (numValues)
657*35238bceSAndroid Build Coastguard Worker     {
658*35238bceSAndroid Build Coastguard Worker     case 1:
659*35238bceSAndroid Build Coastguard Worker         T23 = 0;
660*35238bceSAndroid Build Coastguard Worker     // Fallthrough
661*35238bceSAndroid Build Coastguard Worker     case 2:
662*35238bceSAndroid Build Coastguard Worker         T4 = 0;
663*35238bceSAndroid Build Coastguard Worker     // Fallthrough
664*35238bceSAndroid Build Coastguard Worker     case 3:
665*35238bceSAndroid Build Coastguard Worker         T56 = 0;
666*35238bceSAndroid Build Coastguard Worker     // Fallthrough
667*35238bceSAndroid Build Coastguard Worker     case 4:
668*35238bceSAndroid Build Coastguard Worker         T7 = 0;
669*35238bceSAndroid Build Coastguard Worker     // Fallthrough
670*35238bceSAndroid Build Coastguard Worker     case 5:
671*35238bceSAndroid Build Coastguard Worker         break;
672*35238bceSAndroid Build Coastguard Worker     default:
673*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
674*35238bceSAndroid Build Coastguard Worker     }
675*35238bceSAndroid Build Coastguard Worker 
676*35238bceSAndroid Build Coastguard Worker     const uint32_t T = (T7 << 7) | (T56 << 5) | (T4 << 4) | (T23 << 2) | (T01 << 0);
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker     static const uint32_t tritsFromT[256][5] = {
679*35238bceSAndroid Build Coastguard Worker         {0, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, {2, 0, 0, 0, 0}, {0, 0, 2, 0, 0}, {0, 1, 0, 0, 0}, {1, 1, 0, 0, 0},
680*35238bceSAndroid Build Coastguard Worker         {2, 1, 0, 0, 0}, {1, 0, 2, 0, 0}, {0, 2, 0, 0, 0}, {1, 2, 0, 0, 0}, {2, 2, 0, 0, 0}, {2, 0, 2, 0, 0},
681*35238bceSAndroid Build Coastguard Worker         {0, 2, 2, 0, 0}, {1, 2, 2, 0, 0}, {2, 2, 2, 0, 0}, {2, 0, 2, 0, 0}, {0, 0, 1, 0, 0}, {1, 0, 1, 0, 0},
682*35238bceSAndroid Build Coastguard Worker         {2, 0, 1, 0, 0}, {0, 1, 2, 0, 0}, {0, 1, 1, 0, 0}, {1, 1, 1, 0, 0}, {2, 1, 1, 0, 0}, {1, 1, 2, 0, 0},
683*35238bceSAndroid Build Coastguard Worker         {0, 2, 1, 0, 0}, {1, 2, 1, 0, 0}, {2, 2, 1, 0, 0}, {2, 1, 2, 0, 0}, {0, 0, 0, 2, 2}, {1, 0, 0, 2, 2},
684*35238bceSAndroid Build Coastguard Worker         {2, 0, 0, 2, 2}, {0, 0, 2, 2, 2}, {0, 0, 0, 1, 0}, {1, 0, 0, 1, 0}, {2, 0, 0, 1, 0}, {0, 0, 2, 1, 0},
685*35238bceSAndroid Build Coastguard Worker         {0, 1, 0, 1, 0}, {1, 1, 0, 1, 0}, {2, 1, 0, 1, 0}, {1, 0, 2, 1, 0}, {0, 2, 0, 1, 0}, {1, 2, 0, 1, 0},
686*35238bceSAndroid Build Coastguard Worker         {2, 2, 0, 1, 0}, {2, 0, 2, 1, 0}, {0, 2, 2, 1, 0}, {1, 2, 2, 1, 0}, {2, 2, 2, 1, 0}, {2, 0, 2, 1, 0},
687*35238bceSAndroid Build Coastguard Worker         {0, 0, 1, 1, 0}, {1, 0, 1, 1, 0}, {2, 0, 1, 1, 0}, {0, 1, 2, 1, 0}, {0, 1, 1, 1, 0}, {1, 1, 1, 1, 0},
688*35238bceSAndroid Build Coastguard Worker         {2, 1, 1, 1, 0}, {1, 1, 2, 1, 0}, {0, 2, 1, 1, 0}, {1, 2, 1, 1, 0}, {2, 2, 1, 1, 0}, {2, 1, 2, 1, 0},
689*35238bceSAndroid Build Coastguard Worker         {0, 1, 0, 2, 2}, {1, 1, 0, 2, 2}, {2, 1, 0, 2, 2}, {1, 0, 2, 2, 2}, {0, 0, 0, 2, 0}, {1, 0, 0, 2, 0},
690*35238bceSAndroid Build Coastguard Worker         {2, 0, 0, 2, 0}, {0, 0, 2, 2, 0}, {0, 1, 0, 2, 0}, {1, 1, 0, 2, 0}, {2, 1, 0, 2, 0}, {1, 0, 2, 2, 0},
691*35238bceSAndroid Build Coastguard Worker         {0, 2, 0, 2, 0}, {1, 2, 0, 2, 0}, {2, 2, 0, 2, 0}, {2, 0, 2, 2, 0}, {0, 2, 2, 2, 0}, {1, 2, 2, 2, 0},
692*35238bceSAndroid Build Coastguard Worker         {2, 2, 2, 2, 0}, {2, 0, 2, 2, 0}, {0, 0, 1, 2, 0}, {1, 0, 1, 2, 0}, {2, 0, 1, 2, 0}, {0, 1, 2, 2, 0},
693*35238bceSAndroid Build Coastguard Worker         {0, 1, 1, 2, 0}, {1, 1, 1, 2, 0}, {2, 1, 1, 2, 0}, {1, 1, 2, 2, 0}, {0, 2, 1, 2, 0}, {1, 2, 1, 2, 0},
694*35238bceSAndroid Build Coastguard Worker         {2, 2, 1, 2, 0}, {2, 1, 2, 2, 0}, {0, 2, 0, 2, 2}, {1, 2, 0, 2, 2}, {2, 2, 0, 2, 2}, {2, 0, 2, 2, 2},
695*35238bceSAndroid Build Coastguard Worker         {0, 0, 0, 0, 2}, {1, 0, 0, 0, 2}, {2, 0, 0, 0, 2}, {0, 0, 2, 0, 2}, {0, 1, 0, 0, 2}, {1, 1, 0, 0, 2},
696*35238bceSAndroid Build Coastguard Worker         {2, 1, 0, 0, 2}, {1, 0, 2, 0, 2}, {0, 2, 0, 0, 2}, {1, 2, 0, 0, 2}, {2, 2, 0, 0, 2}, {2, 0, 2, 0, 2},
697*35238bceSAndroid Build Coastguard Worker         {0, 2, 2, 0, 2}, {1, 2, 2, 0, 2}, {2, 2, 2, 0, 2}, {2, 0, 2, 0, 2}, {0, 0, 1, 0, 2}, {1, 0, 1, 0, 2},
698*35238bceSAndroid Build Coastguard Worker         {2, 0, 1, 0, 2}, {0, 1, 2, 0, 2}, {0, 1, 1, 0, 2}, {1, 1, 1, 0, 2}, {2, 1, 1, 0, 2}, {1, 1, 2, 0, 2},
699*35238bceSAndroid Build Coastguard Worker         {0, 2, 1, 0, 2}, {1, 2, 1, 0, 2}, {2, 2, 1, 0, 2}, {2, 1, 2, 0, 2}, {0, 2, 2, 2, 2}, {1, 2, 2, 2, 2},
700*35238bceSAndroid Build Coastguard Worker         {2, 2, 2, 2, 2}, {2, 0, 2, 2, 2}, {0, 0, 0, 0, 1}, {1, 0, 0, 0, 1}, {2, 0, 0, 0, 1}, {0, 0, 2, 0, 1},
701*35238bceSAndroid Build Coastguard Worker         {0, 1, 0, 0, 1}, {1, 1, 0, 0, 1}, {2, 1, 0, 0, 1}, {1, 0, 2, 0, 1}, {0, 2, 0, 0, 1}, {1, 2, 0, 0, 1},
702*35238bceSAndroid Build Coastguard Worker         {2, 2, 0, 0, 1}, {2, 0, 2, 0, 1}, {0, 2, 2, 0, 1}, {1, 2, 2, 0, 1}, {2, 2, 2, 0, 1}, {2, 0, 2, 0, 1},
703*35238bceSAndroid Build Coastguard Worker         {0, 0, 1, 0, 1}, {1, 0, 1, 0, 1}, {2, 0, 1, 0, 1}, {0, 1, 2, 0, 1}, {0, 1, 1, 0, 1}, {1, 1, 1, 0, 1},
704*35238bceSAndroid Build Coastguard Worker         {2, 1, 1, 0, 1}, {1, 1, 2, 0, 1}, {0, 2, 1, 0, 1}, {1, 2, 1, 0, 1}, {2, 2, 1, 0, 1}, {2, 1, 2, 0, 1},
705*35238bceSAndroid Build Coastguard Worker         {0, 0, 1, 2, 2}, {1, 0, 1, 2, 2}, {2, 0, 1, 2, 2}, {0, 1, 2, 2, 2}, {0, 0, 0, 1, 1}, {1, 0, 0, 1, 1},
706*35238bceSAndroid Build Coastguard Worker         {2, 0, 0, 1, 1}, {0, 0, 2, 1, 1}, {0, 1, 0, 1, 1}, {1, 1, 0, 1, 1}, {2, 1, 0, 1, 1}, {1, 0, 2, 1, 1},
707*35238bceSAndroid Build Coastguard Worker         {0, 2, 0, 1, 1}, {1, 2, 0, 1, 1}, {2, 2, 0, 1, 1}, {2, 0, 2, 1, 1}, {0, 2, 2, 1, 1}, {1, 2, 2, 1, 1},
708*35238bceSAndroid Build Coastguard Worker         {2, 2, 2, 1, 1}, {2, 0, 2, 1, 1}, {0, 0, 1, 1, 1}, {1, 0, 1, 1, 1}, {2, 0, 1, 1, 1}, {0, 1, 2, 1, 1},
709*35238bceSAndroid Build Coastguard Worker         {0, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {2, 1, 1, 1, 1}, {1, 1, 2, 1, 1}, {0, 2, 1, 1, 1}, {1, 2, 1, 1, 1},
710*35238bceSAndroid Build Coastguard Worker         {2, 2, 1, 1, 1}, {2, 1, 2, 1, 1}, {0, 1, 1, 2, 2}, {1, 1, 1, 2, 2}, {2, 1, 1, 2, 2}, {1, 1, 2, 2, 2},
711*35238bceSAndroid Build Coastguard Worker         {0, 0, 0, 2, 1}, {1, 0, 0, 2, 1}, {2, 0, 0, 2, 1}, {0, 0, 2, 2, 1}, {0, 1, 0, 2, 1}, {1, 1, 0, 2, 1},
712*35238bceSAndroid Build Coastguard Worker         {2, 1, 0, 2, 1}, {1, 0, 2, 2, 1}, {0, 2, 0, 2, 1}, {1, 2, 0, 2, 1}, {2, 2, 0, 2, 1}, {2, 0, 2, 2, 1},
713*35238bceSAndroid Build Coastguard Worker         {0, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {2, 2, 2, 2, 1}, {2, 0, 2, 2, 1}, {0, 0, 1, 2, 1}, {1, 0, 1, 2, 1},
714*35238bceSAndroid Build Coastguard Worker         {2, 0, 1, 2, 1}, {0, 1, 2, 2, 1}, {0, 1, 1, 2, 1}, {1, 1, 1, 2, 1}, {2, 1, 1, 2, 1}, {1, 1, 2, 2, 1},
715*35238bceSAndroid Build Coastguard Worker         {0, 2, 1, 2, 1}, {1, 2, 1, 2, 1}, {2, 2, 1, 2, 1}, {2, 1, 2, 2, 1}, {0, 2, 1, 2, 2}, {1, 2, 1, 2, 2},
716*35238bceSAndroid Build Coastguard Worker         {2, 2, 1, 2, 2}, {2, 1, 2, 2, 2}, {0, 0, 0, 1, 2}, {1, 0, 0, 1, 2}, {2, 0, 0, 1, 2}, {0, 0, 2, 1, 2},
717*35238bceSAndroid Build Coastguard Worker         {0, 1, 0, 1, 2}, {1, 1, 0, 1, 2}, {2, 1, 0, 1, 2}, {1, 0, 2, 1, 2}, {0, 2, 0, 1, 2}, {1, 2, 0, 1, 2},
718*35238bceSAndroid Build Coastguard Worker         {2, 2, 0, 1, 2}, {2, 0, 2, 1, 2}, {0, 2, 2, 1, 2}, {1, 2, 2, 1, 2}, {2, 2, 2, 1, 2}, {2, 0, 2, 1, 2},
719*35238bceSAndroid Build Coastguard Worker         {0, 0, 1, 1, 2}, {1, 0, 1, 1, 2}, {2, 0, 1, 1, 2}, {0, 1, 2, 1, 2}, {0, 1, 1, 1, 2}, {1, 1, 1, 1, 2},
720*35238bceSAndroid Build Coastguard Worker         {2, 1, 1, 1, 2}, {1, 1, 2, 1, 2}, {0, 2, 1, 1, 2}, {1, 2, 1, 1, 2}, {2, 2, 1, 1, 2}, {2, 1, 2, 1, 2},
721*35238bceSAndroid Build Coastguard Worker         {0, 2, 2, 2, 2}, {1, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 1, 2, 2, 2}};
722*35238bceSAndroid Build Coastguard Worker 
723*35238bceSAndroid Build Coastguard Worker     const uint32_t(&trits)[5] = tritsFromT[T];
724*35238bceSAndroid Build Coastguard Worker 
725*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < numValues; i++)
726*35238bceSAndroid Build Coastguard Worker     {
727*35238bceSAndroid Build Coastguard Worker         dst[i].m  = m[i];
728*35238bceSAndroid Build Coastguard Worker         dst[i].tq = trits[i];
729*35238bceSAndroid Build Coastguard Worker         dst[i].v  = (trits[i] << numBits) + m[i];
730*35238bceSAndroid Build Coastguard Worker     }
731*35238bceSAndroid Build Coastguard Worker }
732*35238bceSAndroid Build Coastguard Worker 
decodeISEQuintBlock(ISEDecodedResult * dst,int numValues,BitAccessStream & data,int numBits)733*35238bceSAndroid Build Coastguard Worker void decodeISEQuintBlock(ISEDecodedResult *dst, int numValues, BitAccessStream &data, int numBits)
734*35238bceSAndroid Build Coastguard Worker {
735*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numValues, 1, 3));
736*35238bceSAndroid Build Coastguard Worker 
737*35238bceSAndroid Build Coastguard Worker     uint32_t m[3];
738*35238bceSAndroid Build Coastguard Worker 
739*35238bceSAndroid Build Coastguard Worker     m[0]          = data.getNext(numBits);
740*35238bceSAndroid Build Coastguard Worker     uint32_t Q012 = data.getNext(3);
741*35238bceSAndroid Build Coastguard Worker     m[1]          = data.getNext(numBits);
742*35238bceSAndroid Build Coastguard Worker     uint32_t Q34  = data.getNext(2);
743*35238bceSAndroid Build Coastguard Worker     m[2]          = data.getNext(numBits);
744*35238bceSAndroid Build Coastguard Worker     uint32_t Q56  = data.getNext(2);
745*35238bceSAndroid Build Coastguard Worker 
746*35238bceSAndroid Build Coastguard Worker     switch (numValues)
747*35238bceSAndroid Build Coastguard Worker     {
748*35238bceSAndroid Build Coastguard Worker     case 1:
749*35238bceSAndroid Build Coastguard Worker         Q34 = 0;
750*35238bceSAndroid Build Coastguard Worker     // Fallthrough
751*35238bceSAndroid Build Coastguard Worker     case 2:
752*35238bceSAndroid Build Coastguard Worker         Q56 = 0;
753*35238bceSAndroid Build Coastguard Worker     // Fallthrough
754*35238bceSAndroid Build Coastguard Worker     case 3:
755*35238bceSAndroid Build Coastguard Worker         break;
756*35238bceSAndroid Build Coastguard Worker     default:
757*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
758*35238bceSAndroid Build Coastguard Worker     }
759*35238bceSAndroid Build Coastguard Worker 
760*35238bceSAndroid Build Coastguard Worker     const uint32_t Q = (Q56 << 5) | (Q34 << 3) | (Q012 << 0);
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker     static const uint32_t quintsFromQ[256][3] = {
763*35238bceSAndroid Build Coastguard Worker         {0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4}, {0, 1, 0}, {1, 1, 0},
764*35238bceSAndroid Build Coastguard Worker         {2, 1, 0}, {3, 1, 0}, {4, 1, 0}, {1, 4, 0}, {4, 4, 1}, {4, 4, 4}, {0, 2, 0}, {1, 2, 0}, {2, 2, 0}, {3, 2, 0},
765*35238bceSAndroid Build Coastguard Worker         {4, 2, 0}, {2, 4, 0}, {4, 4, 2}, {4, 4, 4}, {0, 3, 0}, {1, 3, 0}, {2, 3, 0}, {3, 3, 0}, {4, 3, 0}, {3, 4, 0},
766*35238bceSAndroid Build Coastguard Worker         {4, 4, 3}, {4, 4, 4}, {0, 0, 1}, {1, 0, 1}, {2, 0, 1}, {3, 0, 1}, {4, 0, 1}, {0, 4, 1}, {4, 0, 4}, {0, 4, 4},
767*35238bceSAndroid Build Coastguard Worker         {0, 1, 1}, {1, 1, 1}, {2, 1, 1}, {3, 1, 1}, {4, 1, 1}, {1, 4, 1}, {4, 1, 4}, {1, 4, 4}, {0, 2, 1}, {1, 2, 1},
768*35238bceSAndroid Build Coastguard Worker         {2, 2, 1}, {3, 2, 1}, {4, 2, 1}, {2, 4, 1}, {4, 2, 4}, {2, 4, 4}, {0, 3, 1}, {1, 3, 1}, {2, 3, 1}, {3, 3, 1},
769*35238bceSAndroid Build Coastguard Worker         {4, 3, 1}, {3, 4, 1}, {4, 3, 4}, {3, 4, 4}, {0, 0, 2}, {1, 0, 2}, {2, 0, 2}, {3, 0, 2}, {4, 0, 2}, {0, 4, 2},
770*35238bceSAndroid Build Coastguard Worker         {2, 0, 4}, {3, 0, 4}, {0, 1, 2}, {1, 1, 2}, {2, 1, 2}, {3, 1, 2}, {4, 1, 2}, {1, 4, 2}, {2, 1, 4}, {3, 1, 4},
771*35238bceSAndroid Build Coastguard Worker         {0, 2, 2}, {1, 2, 2}, {2, 2, 2}, {3, 2, 2}, {4, 2, 2}, {2, 4, 2}, {2, 2, 4}, {3, 2, 4}, {0, 3, 2}, {1, 3, 2},
772*35238bceSAndroid Build Coastguard Worker         {2, 3, 2}, {3, 3, 2}, {4, 3, 2}, {3, 4, 2}, {2, 3, 4}, {3, 3, 4}, {0, 0, 3}, {1, 0, 3}, {2, 0, 3}, {3, 0, 3},
773*35238bceSAndroid Build Coastguard Worker         {4, 0, 3}, {0, 4, 3}, {0, 0, 4}, {1, 0, 4}, {0, 1, 3}, {1, 1, 3}, {2, 1, 3}, {3, 1, 3}, {4, 1, 3}, {1, 4, 3},
774*35238bceSAndroid Build Coastguard Worker         {0, 1, 4}, {1, 1, 4}, {0, 2, 3}, {1, 2, 3}, {2, 2, 3}, {3, 2, 3}, {4, 2, 3}, {2, 4, 3}, {0, 2, 4}, {1, 2, 4},
775*35238bceSAndroid Build Coastguard Worker         {0, 3, 3}, {1, 3, 3}, {2, 3, 3}, {3, 3, 3}, {4, 3, 3}, {3, 4, 3}, {0, 3, 4}, {1, 3, 4}};
776*35238bceSAndroid Build Coastguard Worker 
777*35238bceSAndroid Build Coastguard Worker     const uint32_t(&quints)[3] = quintsFromQ[Q];
778*35238bceSAndroid Build Coastguard Worker 
779*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < numValues; i++)
780*35238bceSAndroid Build Coastguard Worker     {
781*35238bceSAndroid Build Coastguard Worker         dst[i].m  = m[i];
782*35238bceSAndroid Build Coastguard Worker         dst[i].tq = quints[i];
783*35238bceSAndroid Build Coastguard Worker         dst[i].v  = (quints[i] << numBits) + m[i];
784*35238bceSAndroid Build Coastguard Worker     }
785*35238bceSAndroid Build Coastguard Worker }
786*35238bceSAndroid Build Coastguard Worker 
decodeISEBitBlock(ISEDecodedResult * dst,BitAccessStream & data,int numBits)787*35238bceSAndroid Build Coastguard Worker inline void decodeISEBitBlock(ISEDecodedResult *dst, BitAccessStream &data, int numBits)
788*35238bceSAndroid Build Coastguard Worker {
789*35238bceSAndroid Build Coastguard Worker     dst[0].m = data.getNext(numBits);
790*35238bceSAndroid Build Coastguard Worker     dst[0].v = dst[0].m;
791*35238bceSAndroid Build Coastguard Worker }
792*35238bceSAndroid Build Coastguard Worker 
decodeISE(ISEDecodedResult * dst,int numValues,BitAccessStream & data,const ISEParams & params)793*35238bceSAndroid Build Coastguard Worker void decodeISE(ISEDecodedResult *dst, int numValues, BitAccessStream &data, const ISEParams &params)
794*35238bceSAndroid Build Coastguard Worker {
795*35238bceSAndroid Build Coastguard Worker     if (params.mode == ISEMODE_TRIT)
796*35238bceSAndroid Build Coastguard Worker     {
797*35238bceSAndroid Build Coastguard Worker         const int numBlocks = deDivRoundUp32(numValues, 5);
798*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
799*35238bceSAndroid Build Coastguard Worker         {
800*35238bceSAndroid Build Coastguard Worker             const int numValuesInBlock = blockNdx == numBlocks - 1 ? numValues - 5 * (numBlocks - 1) : 5;
801*35238bceSAndroid Build Coastguard Worker             decodeISETritBlock(&dst[5 * blockNdx], numValuesInBlock, data, params.numBits);
802*35238bceSAndroid Build Coastguard Worker         }
803*35238bceSAndroid Build Coastguard Worker     }
804*35238bceSAndroid Build Coastguard Worker     else if (params.mode == ISEMODE_QUINT)
805*35238bceSAndroid Build Coastguard Worker     {
806*35238bceSAndroid Build Coastguard Worker         const int numBlocks = deDivRoundUp32(numValues, 3);
807*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
808*35238bceSAndroid Build Coastguard Worker         {
809*35238bceSAndroid Build Coastguard Worker             const int numValuesInBlock = blockNdx == numBlocks - 1 ? numValues - 3 * (numBlocks - 1) : 3;
810*35238bceSAndroid Build Coastguard Worker             decodeISEQuintBlock(&dst[3 * blockNdx], numValuesInBlock, data, params.numBits);
811*35238bceSAndroid Build Coastguard Worker         }
812*35238bceSAndroid Build Coastguard Worker     }
813*35238bceSAndroid Build Coastguard Worker     else
814*35238bceSAndroid Build Coastguard Worker     {
815*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(params.mode == ISEMODE_PLAIN_BIT);
816*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < numValues; i++)
817*35238bceSAndroid Build Coastguard Worker             decodeISEBitBlock(&dst[i], data, params.numBits);
818*35238bceSAndroid Build Coastguard Worker     }
819*35238bceSAndroid Build Coastguard Worker }
820*35238bceSAndroid Build Coastguard Worker 
unquantizeColorEndpoints(uint32_t * dst,const ISEDecodedResult * iseResults,int numEndpoints,const ISEParams & iseParams)821*35238bceSAndroid Build Coastguard Worker void unquantizeColorEndpoints(uint32_t *dst, const ISEDecodedResult *iseResults, int numEndpoints,
822*35238bceSAndroid Build Coastguard Worker                               const ISEParams &iseParams)
823*35238bceSAndroid Build Coastguard Worker {
824*35238bceSAndroid Build Coastguard Worker     if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
825*35238bceSAndroid Build Coastguard Worker     {
826*35238bceSAndroid Build Coastguard Worker         const int rangeCase = iseParams.numBits * 2 - (iseParams.mode == ISEMODE_TRIT ? 2 : 1);
827*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inRange(rangeCase, 0, 10));
828*35238bceSAndroid Build Coastguard Worker         static const uint32_t Ca[11] = {204, 113, 93, 54, 44, 26, 22, 13, 11, 6, 5};
829*35238bceSAndroid Build Coastguard Worker         const uint32_t C             = Ca[rangeCase];
830*35238bceSAndroid Build Coastguard Worker 
831*35238bceSAndroid Build Coastguard Worker         for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
832*35238bceSAndroid Build Coastguard Worker         {
833*35238bceSAndroid Build Coastguard Worker             const uint32_t a = getBit(iseResults[endpointNdx].m, 0);
834*35238bceSAndroid Build Coastguard Worker             const uint32_t b = getBit(iseResults[endpointNdx].m, 1);
835*35238bceSAndroid Build Coastguard Worker             const uint32_t c = getBit(iseResults[endpointNdx].m, 2);
836*35238bceSAndroid Build Coastguard Worker             const uint32_t d = getBit(iseResults[endpointNdx].m, 3);
837*35238bceSAndroid Build Coastguard Worker             const uint32_t e = getBit(iseResults[endpointNdx].m, 4);
838*35238bceSAndroid Build Coastguard Worker             const uint32_t f = getBit(iseResults[endpointNdx].m, 5);
839*35238bceSAndroid Build Coastguard Worker 
840*35238bceSAndroid Build Coastguard Worker             const uint32_t A = a == 0 ? 0 : (1 << 9) - 1;
841*35238bceSAndroid Build Coastguard Worker             const uint32_t B = rangeCase == 0  ? 0 :
842*35238bceSAndroid Build Coastguard Worker                                rangeCase == 1  ? 0 :
843*35238bceSAndroid Build Coastguard Worker                                rangeCase == 2  ? (b << 8) | (b << 4) | (b << 2) | (b << 1) :
844*35238bceSAndroid Build Coastguard Worker                                rangeCase == 3  ? (b << 8) | (b << 3) | (b << 2) :
845*35238bceSAndroid Build Coastguard Worker                                rangeCase == 4  ? (c << 8) | (b << 7) | (c << 3) | (b << 2) | (c << 1) | (b << 0) :
846*35238bceSAndroid Build Coastguard Worker                                rangeCase == 5  ? (c << 8) | (b << 7) | (c << 2) | (b << 1) | (c << 0) :
847*35238bceSAndroid Build Coastguard Worker                                rangeCase == 6  ? (d << 8) | (c << 7) | (b << 6) | (d << 2) | (c << 1) | (b << 0) :
848*35238bceSAndroid Build Coastguard Worker                                rangeCase == 7  ? (d << 8) | (c << 7) | (b << 6) | (d << 1) | (c << 0) :
849*35238bceSAndroid Build Coastguard Worker                                rangeCase == 8  ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 1) | (d << 0) :
850*35238bceSAndroid Build Coastguard Worker                                rangeCase == 9  ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 0) :
851*35238bceSAndroid Build Coastguard Worker                                rangeCase == 10 ? (f << 8) | (e << 7) | (d << 6) | (c << 5) | (b << 4) | (f << 0) :
852*35238bceSAndroid Build Coastguard Worker                                                  (uint32_t)-1;
853*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(B != (uint32_t)-1);
854*35238bceSAndroid Build Coastguard Worker 
855*35238bceSAndroid Build Coastguard Worker             dst[endpointNdx] = (((iseResults[endpointNdx].tq * C + B) ^ A) >> 2) | (A & 0x80);
856*35238bceSAndroid Build Coastguard Worker         }
857*35238bceSAndroid Build Coastguard Worker     }
858*35238bceSAndroid Build Coastguard Worker     else
859*35238bceSAndroid Build Coastguard Worker     {
860*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
861*35238bceSAndroid Build Coastguard Worker 
862*35238bceSAndroid Build Coastguard Worker         for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
863*35238bceSAndroid Build Coastguard Worker             dst[endpointNdx] = bitReplicationScale(iseResults[endpointNdx].v, iseParams.numBits, 8);
864*35238bceSAndroid Build Coastguard Worker     }
865*35238bceSAndroid Build Coastguard Worker }
866*35238bceSAndroid Build Coastguard Worker 
bitTransferSigned(int32_t & a,int32_t & b)867*35238bceSAndroid Build Coastguard Worker inline void bitTransferSigned(int32_t &a, int32_t &b)
868*35238bceSAndroid Build Coastguard Worker {
869*35238bceSAndroid Build Coastguard Worker     b >>= 1;
870*35238bceSAndroid Build Coastguard Worker     b |= a & 0x80;
871*35238bceSAndroid Build Coastguard Worker     a >>= 1;
872*35238bceSAndroid Build Coastguard Worker     a &= 0x3f;
873*35238bceSAndroid Build Coastguard Worker     if (isBitSet(a, 5))
874*35238bceSAndroid Build Coastguard Worker         a -= 0x40;
875*35238bceSAndroid Build Coastguard Worker }
876*35238bceSAndroid Build Coastguard Worker 
clampedRGBA(const IVec4 & rgba)877*35238bceSAndroid Build Coastguard Worker inline UVec4 clampedRGBA(const IVec4 &rgba)
878*35238bceSAndroid Build Coastguard Worker {
879*35238bceSAndroid Build Coastguard Worker     return UVec4(de::clamp(rgba.x(), 0, 0xff), de::clamp(rgba.y(), 0, 0xff), de::clamp(rgba.z(), 0, 0xff),
880*35238bceSAndroid Build Coastguard Worker                  de::clamp(rgba.w(), 0, 0xff));
881*35238bceSAndroid Build Coastguard Worker }
882*35238bceSAndroid Build Coastguard Worker 
blueContract(int r,int g,int b,int a)883*35238bceSAndroid Build Coastguard Worker inline IVec4 blueContract(int r, int g, int b, int a)
884*35238bceSAndroid Build Coastguard Worker {
885*35238bceSAndroid Build Coastguard Worker     return IVec4((r + b) >> 1, (g + b) >> 1, b, a);
886*35238bceSAndroid Build Coastguard Worker }
887*35238bceSAndroid Build Coastguard Worker 
isColorEndpointModeHDR(uint32_t mode)888*35238bceSAndroid Build Coastguard Worker inline bool isColorEndpointModeHDR(uint32_t mode)
889*35238bceSAndroid Build Coastguard Worker {
890*35238bceSAndroid Build Coastguard Worker     return mode == 2 || mode == 3 || mode == 7 || mode == 11 || mode == 14 || mode == 15;
891*35238bceSAndroid Build Coastguard Worker }
892*35238bceSAndroid Build Coastguard Worker 
decodeHDREndpointMode7(UVec4 & e0,UVec4 & e1,uint32_t v0,uint32_t v1,uint32_t v2,uint32_t v3)893*35238bceSAndroid Build Coastguard Worker void decodeHDREndpointMode7(UVec4 &e0, UVec4 &e1, uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
894*35238bceSAndroid Build Coastguard Worker {
895*35238bceSAndroid Build Coastguard Worker     const uint32_t m10     = getBit(v1, 7) | (getBit(v2, 7) << 1);
896*35238bceSAndroid Build Coastguard Worker     const uint32_t m23     = getBits(v0, 6, 7);
897*35238bceSAndroid Build Coastguard Worker     const uint32_t majComp = m10 != 3 ? m10 : m23 != 3 ? m23 : 0;
898*35238bceSAndroid Build Coastguard Worker     const uint32_t mode    = m10 != 3 ? m23 : m23 != 3 ? 4 : 5;
899*35238bceSAndroid Build Coastguard Worker 
900*35238bceSAndroid Build Coastguard Worker     int32_t red   = (int32_t)getBits(v0, 0, 5);
901*35238bceSAndroid Build Coastguard Worker     int32_t green = (int32_t)getBits(v1, 0, 4);
902*35238bceSAndroid Build Coastguard Worker     int32_t blue  = (int32_t)getBits(v2, 0, 4);
903*35238bceSAndroid Build Coastguard Worker     int32_t scale = (int32_t)getBits(v3, 0, 4);
904*35238bceSAndroid Build Coastguard Worker 
905*35238bceSAndroid Build Coastguard Worker     {
906*35238bceSAndroid Build Coastguard Worker #define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
907*35238bceSAndroid Build Coastguard Worker #define ASSIGN_X_BITS(V0, S0, V1, S1, V2, S2, V3, S3, V4, S4, V5, S5, V6, S6) \
908*35238bceSAndroid Build Coastguard Worker     do                                                                        \
909*35238bceSAndroid Build Coastguard Worker     {                                                                         \
910*35238bceSAndroid Build Coastguard Worker         SHOR(V0, S0, x0);                                                     \
911*35238bceSAndroid Build Coastguard Worker         SHOR(V1, S1, x1);                                                     \
912*35238bceSAndroid Build Coastguard Worker         SHOR(V2, S2, x2);                                                     \
913*35238bceSAndroid Build Coastguard Worker         SHOR(V3, S3, x3);                                                     \
914*35238bceSAndroid Build Coastguard Worker         SHOR(V4, S4, x4);                                                     \
915*35238bceSAndroid Build Coastguard Worker         SHOR(V5, S5, x5);                                                     \
916*35238bceSAndroid Build Coastguard Worker         SHOR(V6, S6, x6);                                                     \
917*35238bceSAndroid Build Coastguard Worker     } while (false)
918*35238bceSAndroid Build Coastguard Worker 
919*35238bceSAndroid Build Coastguard Worker         const uint32_t x0 = getBit(v1, 6);
920*35238bceSAndroid Build Coastguard Worker         const uint32_t x1 = getBit(v1, 5);
921*35238bceSAndroid Build Coastguard Worker         const uint32_t x2 = getBit(v2, 6);
922*35238bceSAndroid Build Coastguard Worker         const uint32_t x3 = getBit(v2, 5);
923*35238bceSAndroid Build Coastguard Worker         const uint32_t x4 = getBit(v3, 7);
924*35238bceSAndroid Build Coastguard Worker         const uint32_t x5 = getBit(v3, 6);
925*35238bceSAndroid Build Coastguard Worker         const uint32_t x6 = getBit(v3, 5);
926*35238bceSAndroid Build Coastguard Worker 
927*35238bceSAndroid Build Coastguard Worker         int32_t &R = red;
928*35238bceSAndroid Build Coastguard Worker         int32_t &G = green;
929*35238bceSAndroid Build Coastguard Worker         int32_t &B = blue;
930*35238bceSAndroid Build Coastguard Worker         int32_t &S = scale;
931*35238bceSAndroid Build Coastguard Worker 
932*35238bceSAndroid Build Coastguard Worker         switch (mode)
933*35238bceSAndroid Build Coastguard Worker         {
934*35238bceSAndroid Build Coastguard Worker         case 0:
935*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(R, 9, R, 8, R, 7, R, 10, R, 6, S, 6, S, 5);
936*35238bceSAndroid Build Coastguard Worker             break;
937*35238bceSAndroid Build Coastguard Worker         case 1:
938*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(R, 8, G, 5, R, 7, B, 5, R, 6, R, 10, R, 9);
939*35238bceSAndroid Build Coastguard Worker             break;
940*35238bceSAndroid Build Coastguard Worker         case 2:
941*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(R, 9, R, 8, R, 7, R, 6, S, 7, S, 6, S, 5);
942*35238bceSAndroid Build Coastguard Worker             break;
943*35238bceSAndroid Build Coastguard Worker         case 3:
944*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(R, 8, G, 5, R, 7, B, 5, R, 6, S, 6, S, 5);
945*35238bceSAndroid Build Coastguard Worker             break;
946*35238bceSAndroid Build Coastguard Worker         case 4:
947*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(G, 6, G, 5, B, 6, B, 5, R, 6, R, 7, S, 5);
948*35238bceSAndroid Build Coastguard Worker             break;
949*35238bceSAndroid Build Coastguard Worker         case 5:
950*35238bceSAndroid Build Coastguard Worker             ASSIGN_X_BITS(G, 6, G, 5, B, 6, B, 5, R, 6, S, 6, S, 5);
951*35238bceSAndroid Build Coastguard Worker             break;
952*35238bceSAndroid Build Coastguard Worker         default:
953*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
954*35238bceSAndroid Build Coastguard Worker         }
955*35238bceSAndroid Build Coastguard Worker 
956*35238bceSAndroid Build Coastguard Worker #undef ASSIGN_X_BITS
957*35238bceSAndroid Build Coastguard Worker #undef SHOR
958*35238bceSAndroid Build Coastguard Worker     }
959*35238bceSAndroid Build Coastguard Worker 
960*35238bceSAndroid Build Coastguard Worker     static const int shiftAmounts[] = {1, 1, 2, 3, 4, 5};
961*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(shiftAmounts));
962*35238bceSAndroid Build Coastguard Worker 
963*35238bceSAndroid Build Coastguard Worker     red <<= shiftAmounts[mode];
964*35238bceSAndroid Build Coastguard Worker     green <<= shiftAmounts[mode];
965*35238bceSAndroid Build Coastguard Worker     blue <<= shiftAmounts[mode];
966*35238bceSAndroid Build Coastguard Worker     scale <<= shiftAmounts[mode];
967*35238bceSAndroid Build Coastguard Worker 
968*35238bceSAndroid Build Coastguard Worker     if (mode != 5)
969*35238bceSAndroid Build Coastguard Worker     {
970*35238bceSAndroid Build Coastguard Worker         green = red - green;
971*35238bceSAndroid Build Coastguard Worker         blue  = red - blue;
972*35238bceSAndroid Build Coastguard Worker     }
973*35238bceSAndroid Build Coastguard Worker 
974*35238bceSAndroid Build Coastguard Worker     if (majComp == 1)
975*35238bceSAndroid Build Coastguard Worker         std::swap(red, green);
976*35238bceSAndroid Build Coastguard Worker     else if (majComp == 2)
977*35238bceSAndroid Build Coastguard Worker         std::swap(red, blue);
978*35238bceSAndroid Build Coastguard Worker 
979*35238bceSAndroid Build Coastguard Worker     e0 = UVec4(de::clamp(red - scale, 0, 0xfff), de::clamp(green - scale, 0, 0xfff), de::clamp(blue - scale, 0, 0xfff),
980*35238bceSAndroid Build Coastguard Worker                0x780);
981*35238bceSAndroid Build Coastguard Worker 
982*35238bceSAndroid Build Coastguard Worker     e1 = UVec4(de::clamp(red, 0, 0xfff), de::clamp(green, 0, 0xfff), de::clamp(blue, 0, 0xfff), 0x780);
983*35238bceSAndroid Build Coastguard Worker }
984*35238bceSAndroid Build Coastguard Worker 
decodeHDREndpointMode11(UVec4 & e0,UVec4 & e1,uint32_t v0,uint32_t v1,uint32_t v2,uint32_t v3,uint32_t v4,uint32_t v5)985*35238bceSAndroid Build Coastguard Worker void decodeHDREndpointMode11(UVec4 &e0, UVec4 &e1, uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3, uint32_t v4,
986*35238bceSAndroid Build Coastguard Worker                              uint32_t v5)
987*35238bceSAndroid Build Coastguard Worker {
988*35238bceSAndroid Build Coastguard Worker     const uint32_t major = (getBit(v5, 7) << 1) | getBit(v4, 7);
989*35238bceSAndroid Build Coastguard Worker 
990*35238bceSAndroid Build Coastguard Worker     if (major == 3)
991*35238bceSAndroid Build Coastguard Worker     {
992*35238bceSAndroid Build Coastguard Worker         e0 = UVec4(v0 << 4, v2 << 4, getBits(v4, 0, 6) << 5, 0x780);
993*35238bceSAndroid Build Coastguard Worker         e1 = UVec4(v1 << 4, v3 << 4, getBits(v5, 0, 6) << 5, 0x780);
994*35238bceSAndroid Build Coastguard Worker     }
995*35238bceSAndroid Build Coastguard Worker     else
996*35238bceSAndroid Build Coastguard Worker     {
997*35238bceSAndroid Build Coastguard Worker         const uint32_t mode = (getBit(v3, 7) << 2) | (getBit(v2, 7) << 1) | getBit(v1, 7);
998*35238bceSAndroid Build Coastguard Worker 
999*35238bceSAndroid Build Coastguard Worker         int32_t a  = (int32_t)((getBit(v1, 6) << 8) | v0);
1000*35238bceSAndroid Build Coastguard Worker         int32_t c  = (int32_t)(getBits(v1, 0, 5));
1001*35238bceSAndroid Build Coastguard Worker         int32_t b0 = (int32_t)(getBits(v2, 0, 5));
1002*35238bceSAndroid Build Coastguard Worker         int32_t b1 = (int32_t)(getBits(v3, 0, 5));
1003*35238bceSAndroid Build Coastguard Worker         int32_t d0 = (int32_t)(getBits(v4, 0, 4));
1004*35238bceSAndroid Build Coastguard Worker         int32_t d1 = (int32_t)(getBits(v5, 0, 4));
1005*35238bceSAndroid Build Coastguard Worker 
1006*35238bceSAndroid Build Coastguard Worker         {
1007*35238bceSAndroid Build Coastguard Worker #define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
1008*35238bceSAndroid Build Coastguard Worker #define ASSIGN_X_BITS(V0, S0, V1, S1, V2, S2, V3, S3, V4, S4, V5, S5) \
1009*35238bceSAndroid Build Coastguard Worker     do                                                                \
1010*35238bceSAndroid Build Coastguard Worker     {                                                                 \
1011*35238bceSAndroid Build Coastguard Worker         SHOR(V0, S0, x0);                                             \
1012*35238bceSAndroid Build Coastguard Worker         SHOR(V1, S1, x1);                                             \
1013*35238bceSAndroid Build Coastguard Worker         SHOR(V2, S2, x2);                                             \
1014*35238bceSAndroid Build Coastguard Worker         SHOR(V3, S3, x3);                                             \
1015*35238bceSAndroid Build Coastguard Worker         SHOR(V4, S4, x4);                                             \
1016*35238bceSAndroid Build Coastguard Worker         SHOR(V5, S5, x5);                                             \
1017*35238bceSAndroid Build Coastguard Worker     } while (false)
1018*35238bceSAndroid Build Coastguard Worker 
1019*35238bceSAndroid Build Coastguard Worker             const uint32_t x0 = getBit(v2, 6);
1020*35238bceSAndroid Build Coastguard Worker             const uint32_t x1 = getBit(v3, 6);
1021*35238bceSAndroid Build Coastguard Worker             const uint32_t x2 = getBit(v4, 6);
1022*35238bceSAndroid Build Coastguard Worker             const uint32_t x3 = getBit(v5, 6);
1023*35238bceSAndroid Build Coastguard Worker             const uint32_t x4 = getBit(v4, 5);
1024*35238bceSAndroid Build Coastguard Worker             const uint32_t x5 = getBit(v5, 5);
1025*35238bceSAndroid Build Coastguard Worker 
1026*35238bceSAndroid Build Coastguard Worker             switch (mode)
1027*35238bceSAndroid Build Coastguard Worker             {
1028*35238bceSAndroid Build Coastguard Worker             case 0:
1029*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(b0, 6, b1, 6, d0, 6, d1, 6, d0, 5, d1, 5);
1030*35238bceSAndroid Build Coastguard Worker                 break;
1031*35238bceSAndroid Build Coastguard Worker             case 1:
1032*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(b0, 6, b1, 6, b0, 7, b1, 7, d0, 5, d1, 5);
1033*35238bceSAndroid Build Coastguard Worker                 break;
1034*35238bceSAndroid Build Coastguard Worker             case 2:
1035*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(a, 9, c, 6, d0, 6, d1, 6, d0, 5, d1, 5);
1036*35238bceSAndroid Build Coastguard Worker                 break;
1037*35238bceSAndroid Build Coastguard Worker             case 3:
1038*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(b0, 6, b1, 6, a, 9, c, 6, d0, 5, d1, 5);
1039*35238bceSAndroid Build Coastguard Worker                 break;
1040*35238bceSAndroid Build Coastguard Worker             case 4:
1041*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(b0, 6, b1, 6, b0, 7, b1, 7, a, 9, a, 10);
1042*35238bceSAndroid Build Coastguard Worker                 break;
1043*35238bceSAndroid Build Coastguard Worker             case 5:
1044*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(a, 9, a, 10, c, 7, c, 6, d0, 5, d1, 5);
1045*35238bceSAndroid Build Coastguard Worker                 break;
1046*35238bceSAndroid Build Coastguard Worker             case 6:
1047*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(b0, 6, b1, 6, a, 11, c, 6, a, 9, a, 10);
1048*35238bceSAndroid Build Coastguard Worker                 break;
1049*35238bceSAndroid Build Coastguard Worker             case 7:
1050*35238bceSAndroid Build Coastguard Worker                 ASSIGN_X_BITS(a, 9, a, 10, a, 11, c, 6, d0, 5, d1, 5);
1051*35238bceSAndroid Build Coastguard Worker                 break;
1052*35238bceSAndroid Build Coastguard Worker             default:
1053*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1054*35238bceSAndroid Build Coastguard Worker             }
1055*35238bceSAndroid Build Coastguard Worker 
1056*35238bceSAndroid Build Coastguard Worker #undef ASSIGN_X_BITS
1057*35238bceSAndroid Build Coastguard Worker #undef SHOR
1058*35238bceSAndroid Build Coastguard Worker         }
1059*35238bceSAndroid Build Coastguard Worker 
1060*35238bceSAndroid Build Coastguard Worker         static const int numDBits[] = {7, 6, 7, 6, 5, 6, 5, 6};
1061*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(numDBits));
1062*35238bceSAndroid Build Coastguard Worker 
1063*35238bceSAndroid Build Coastguard Worker         d0 = signExtend(d0, numDBits[mode]);
1064*35238bceSAndroid Build Coastguard Worker         d1 = signExtend(d1, numDBits[mode]);
1065*35238bceSAndroid Build Coastguard Worker 
1066*35238bceSAndroid Build Coastguard Worker         const int shiftAmount = (mode >> 1) ^ 3;
1067*35238bceSAndroid Build Coastguard Worker         a <<= shiftAmount;
1068*35238bceSAndroid Build Coastguard Worker         c <<= shiftAmount;
1069*35238bceSAndroid Build Coastguard Worker         b0 <<= shiftAmount;
1070*35238bceSAndroid Build Coastguard Worker         b1 <<= shiftAmount;
1071*35238bceSAndroid Build Coastguard Worker         d0 <<= shiftAmount;
1072*35238bceSAndroid Build Coastguard Worker         d1 <<= shiftAmount;
1073*35238bceSAndroid Build Coastguard Worker 
1074*35238bceSAndroid Build Coastguard Worker         e0 = UVec4(de::clamp(a - c, 0, 0xfff), de::clamp(a - b0 - c - d0, 0, 0xfff),
1075*35238bceSAndroid Build Coastguard Worker                    de::clamp(a - b1 - c - d1, 0, 0xfff), 0x780);
1076*35238bceSAndroid Build Coastguard Worker 
1077*35238bceSAndroid Build Coastguard Worker         e1 = UVec4(de::clamp(a, 0, 0xfff), de::clamp(a - b0, 0, 0xfff), de::clamp(a - b1, 0, 0xfff), 0x780);
1078*35238bceSAndroid Build Coastguard Worker 
1079*35238bceSAndroid Build Coastguard Worker         if (major == 1)
1080*35238bceSAndroid Build Coastguard Worker         {
1081*35238bceSAndroid Build Coastguard Worker             std::swap(e0.x(), e0.y());
1082*35238bceSAndroid Build Coastguard Worker             std::swap(e1.x(), e1.y());
1083*35238bceSAndroid Build Coastguard Worker         }
1084*35238bceSAndroid Build Coastguard Worker         else if (major == 2)
1085*35238bceSAndroid Build Coastguard Worker         {
1086*35238bceSAndroid Build Coastguard Worker             std::swap(e0.x(), e0.z());
1087*35238bceSAndroid Build Coastguard Worker             std::swap(e1.x(), e1.z());
1088*35238bceSAndroid Build Coastguard Worker         }
1089*35238bceSAndroid Build Coastguard Worker     }
1090*35238bceSAndroid Build Coastguard Worker }
1091*35238bceSAndroid Build Coastguard Worker 
decodeHDREndpointMode15(UVec4 & e0,UVec4 & e1,uint32_t v0,uint32_t v1,uint32_t v2,uint32_t v3,uint32_t v4,uint32_t v5,uint32_t v6In,uint32_t v7In)1092*35238bceSAndroid Build Coastguard Worker void decodeHDREndpointMode15(UVec4 &e0, UVec4 &e1, uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3, uint32_t v4,
1093*35238bceSAndroid Build Coastguard Worker                              uint32_t v5, uint32_t v6In, uint32_t v7In)
1094*35238bceSAndroid Build Coastguard Worker {
1095*35238bceSAndroid Build Coastguard Worker     decodeHDREndpointMode11(e0, e1, v0, v1, v2, v3, v4, v5);
1096*35238bceSAndroid Build Coastguard Worker 
1097*35238bceSAndroid Build Coastguard Worker     const uint32_t mode = (getBit(v7In, 7) << 1) | getBit(v6In, 7);
1098*35238bceSAndroid Build Coastguard Worker     int32_t v6          = (int32_t)getBits(v6In, 0, 6);
1099*35238bceSAndroid Build Coastguard Worker     int32_t v7          = (int32_t)getBits(v7In, 0, 6);
1100*35238bceSAndroid Build Coastguard Worker 
1101*35238bceSAndroid Build Coastguard Worker     if (mode == 3)
1102*35238bceSAndroid Build Coastguard Worker     {
1103*35238bceSAndroid Build Coastguard Worker         e0.w() = v6 << 5;
1104*35238bceSAndroid Build Coastguard Worker         e1.w() = v7 << 5;
1105*35238bceSAndroid Build Coastguard Worker     }
1106*35238bceSAndroid Build Coastguard Worker     else
1107*35238bceSAndroid Build Coastguard Worker     {
1108*35238bceSAndroid Build Coastguard Worker         v6 |= (v7 << (mode + 1)) & 0x780;
1109*35238bceSAndroid Build Coastguard Worker         v7 &= (0x3f >> mode);
1110*35238bceSAndroid Build Coastguard Worker         v7 ^= 0x20 >> mode;
1111*35238bceSAndroid Build Coastguard Worker         v7 -= 0x20 >> mode;
1112*35238bceSAndroid Build Coastguard Worker         v6 <<= 4 - mode;
1113*35238bceSAndroid Build Coastguard Worker         v7 <<= 4 - mode;
1114*35238bceSAndroid Build Coastguard Worker 
1115*35238bceSAndroid Build Coastguard Worker         v7 += v6;
1116*35238bceSAndroid Build Coastguard Worker         v7     = de::clamp(v7, 0, 0xfff);
1117*35238bceSAndroid Build Coastguard Worker         e0.w() = v6;
1118*35238bceSAndroid Build Coastguard Worker         e1.w() = v7;
1119*35238bceSAndroid Build Coastguard Worker     }
1120*35238bceSAndroid Build Coastguard Worker }
1121*35238bceSAndroid Build Coastguard Worker 
decodeColorEndpoints(ColorEndpointPair * dst,const uint32_t * unquantizedEndpoints,const uint32_t * endpointModes,int numPartitions)1122*35238bceSAndroid Build Coastguard Worker void decodeColorEndpoints(ColorEndpointPair *dst, const uint32_t *unquantizedEndpoints, const uint32_t *endpointModes,
1123*35238bceSAndroid Build Coastguard Worker                           int numPartitions)
1124*35238bceSAndroid Build Coastguard Worker {
1125*35238bceSAndroid Build Coastguard Worker     int unquantizedNdx = 0;
1126*35238bceSAndroid Build Coastguard Worker 
1127*35238bceSAndroid Build Coastguard Worker     for (int partitionNdx = 0; partitionNdx < numPartitions; partitionNdx++)
1128*35238bceSAndroid Build Coastguard Worker     {
1129*35238bceSAndroid Build Coastguard Worker         const uint32_t endpointMode = endpointModes[partitionNdx];
1130*35238bceSAndroid Build Coastguard Worker         const uint32_t *v           = &unquantizedEndpoints[unquantizedNdx];
1131*35238bceSAndroid Build Coastguard Worker         UVec4 &e0                   = dst[partitionNdx].e0;
1132*35238bceSAndroid Build Coastguard Worker         UVec4 &e1                   = dst[partitionNdx].e1;
1133*35238bceSAndroid Build Coastguard Worker 
1134*35238bceSAndroid Build Coastguard Worker         unquantizedNdx += computeNumColorEndpointValues(endpointMode);
1135*35238bceSAndroid Build Coastguard Worker 
1136*35238bceSAndroid Build Coastguard Worker         switch (endpointMode)
1137*35238bceSAndroid Build Coastguard Worker         {
1138*35238bceSAndroid Build Coastguard Worker         case 0:
1139*35238bceSAndroid Build Coastguard Worker             e0 = UVec4(v[0], v[0], v[0], 0xff);
1140*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(v[1], v[1], v[1], 0xff);
1141*35238bceSAndroid Build Coastguard Worker             break;
1142*35238bceSAndroid Build Coastguard Worker 
1143*35238bceSAndroid Build Coastguard Worker         case 1:
1144*35238bceSAndroid Build Coastguard Worker         {
1145*35238bceSAndroid Build Coastguard Worker             const uint32_t L0 = (v[0] >> 2) | (getBits(v[1], 6, 7) << 6);
1146*35238bceSAndroid Build Coastguard Worker             const uint32_t L1 = de::min(0xffu, L0 + getBits(v[1], 0, 5));
1147*35238bceSAndroid Build Coastguard Worker             e0                = UVec4(L0, L0, L0, 0xff);
1148*35238bceSAndroid Build Coastguard Worker             e1                = UVec4(L1, L1, L1, 0xff);
1149*35238bceSAndroid Build Coastguard Worker             break;
1150*35238bceSAndroid Build Coastguard Worker         }
1151*35238bceSAndroid Build Coastguard Worker 
1152*35238bceSAndroid Build Coastguard Worker         case 2:
1153*35238bceSAndroid Build Coastguard Worker         {
1154*35238bceSAndroid Build Coastguard Worker             const uint32_t v1Gr = v[1] >= v[0];
1155*35238bceSAndroid Build Coastguard Worker             const uint32_t y0   = v1Gr ? v[0] << 4 : (v[1] << 4) + 8;
1156*35238bceSAndroid Build Coastguard Worker             const uint32_t y1   = v1Gr ? v[1] << 4 : (v[0] << 4) - 8;
1157*35238bceSAndroid Build Coastguard Worker 
1158*35238bceSAndroid Build Coastguard Worker             e0 = UVec4(y0, y0, y0, 0x780);
1159*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(y1, y1, y1, 0x780);
1160*35238bceSAndroid Build Coastguard Worker             break;
1161*35238bceSAndroid Build Coastguard Worker         }
1162*35238bceSAndroid Build Coastguard Worker 
1163*35238bceSAndroid Build Coastguard Worker         case 3:
1164*35238bceSAndroid Build Coastguard Worker         {
1165*35238bceSAndroid Build Coastguard Worker             const bool m      = isBitSet(v[0], 7);
1166*35238bceSAndroid Build Coastguard Worker             const uint32_t y0 = m ? (getBits(v[1], 5, 7) << 9) | (getBits(v[0], 0, 6) << 2) :
1167*35238bceSAndroid Build Coastguard Worker                                     (getBits(v[1], 4, 7) << 8) | (getBits(v[0], 0, 6) << 1);
1168*35238bceSAndroid Build Coastguard Worker             const uint32_t d  = m ? getBits(v[1], 0, 4) << 2 : getBits(v[1], 0, 3) << 1;
1169*35238bceSAndroid Build Coastguard Worker             const uint32_t y1 = de::min(0xfffu, y0 + d);
1170*35238bceSAndroid Build Coastguard Worker 
1171*35238bceSAndroid Build Coastguard Worker             e0 = UVec4(y0, y0, y0, 0x780);
1172*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(y1, y1, y1, 0x780);
1173*35238bceSAndroid Build Coastguard Worker             break;
1174*35238bceSAndroid Build Coastguard Worker         }
1175*35238bceSAndroid Build Coastguard Worker 
1176*35238bceSAndroid Build Coastguard Worker         case 4:
1177*35238bceSAndroid Build Coastguard Worker             e0 = UVec4(v[0], v[0], v[0], v[2]);
1178*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(v[1], v[1], v[1], v[3]);
1179*35238bceSAndroid Build Coastguard Worker             break;
1180*35238bceSAndroid Build Coastguard Worker 
1181*35238bceSAndroid Build Coastguard Worker         case 5:
1182*35238bceSAndroid Build Coastguard Worker         {
1183*35238bceSAndroid Build Coastguard Worker             int32_t v0 = (int32_t)v[0];
1184*35238bceSAndroid Build Coastguard Worker             int32_t v1 = (int32_t)v[1];
1185*35238bceSAndroid Build Coastguard Worker             int32_t v2 = (int32_t)v[2];
1186*35238bceSAndroid Build Coastguard Worker             int32_t v3 = (int32_t)v[3];
1187*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v1, v0);
1188*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v3, v2);
1189*35238bceSAndroid Build Coastguard Worker 
1190*35238bceSAndroid Build Coastguard Worker             e0 = clampedRGBA(IVec4(v0, v0, v0, v2));
1191*35238bceSAndroid Build Coastguard Worker             e1 = clampedRGBA(IVec4(v0 + v1, v0 + v1, v0 + v1, v2 + v3));
1192*35238bceSAndroid Build Coastguard Worker             break;
1193*35238bceSAndroid Build Coastguard Worker         }
1194*35238bceSAndroid Build Coastguard Worker 
1195*35238bceSAndroid Build Coastguard Worker         case 6:
1196*35238bceSAndroid Build Coastguard Worker             e0 = UVec4((v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8, 0xff);
1197*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(v[0], v[1], v[2], 0xff);
1198*35238bceSAndroid Build Coastguard Worker             break;
1199*35238bceSAndroid Build Coastguard Worker 
1200*35238bceSAndroid Build Coastguard Worker         case 7:
1201*35238bceSAndroid Build Coastguard Worker             decodeHDREndpointMode7(e0, e1, v[0], v[1], v[2], v[3]);
1202*35238bceSAndroid Build Coastguard Worker             break;
1203*35238bceSAndroid Build Coastguard Worker 
1204*35238bceSAndroid Build Coastguard Worker         case 8:
1205*35238bceSAndroid Build Coastguard Worker             if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4])
1206*35238bceSAndroid Build Coastguard Worker             {
1207*35238bceSAndroid Build Coastguard Worker                 e0 = UVec4(v[0], v[2], v[4], 0xff);
1208*35238bceSAndroid Build Coastguard Worker                 e1 = UVec4(v[1], v[3], v[5], 0xff);
1209*35238bceSAndroid Build Coastguard Worker             }
1210*35238bceSAndroid Build Coastguard Worker             else
1211*35238bceSAndroid Build Coastguard Worker             {
1212*35238bceSAndroid Build Coastguard Worker                 e0 = blueContract(v[1], v[3], v[5], 0xff).asUint();
1213*35238bceSAndroid Build Coastguard Worker                 e1 = blueContract(v[0], v[2], v[4], 0xff).asUint();
1214*35238bceSAndroid Build Coastguard Worker             }
1215*35238bceSAndroid Build Coastguard Worker             break;
1216*35238bceSAndroid Build Coastguard Worker 
1217*35238bceSAndroid Build Coastguard Worker         case 9:
1218*35238bceSAndroid Build Coastguard Worker         {
1219*35238bceSAndroid Build Coastguard Worker             int32_t v0 = (int32_t)v[0];
1220*35238bceSAndroid Build Coastguard Worker             int32_t v1 = (int32_t)v[1];
1221*35238bceSAndroid Build Coastguard Worker             int32_t v2 = (int32_t)v[2];
1222*35238bceSAndroid Build Coastguard Worker             int32_t v3 = (int32_t)v[3];
1223*35238bceSAndroid Build Coastguard Worker             int32_t v4 = (int32_t)v[4];
1224*35238bceSAndroid Build Coastguard Worker             int32_t v5 = (int32_t)v[5];
1225*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v1, v0);
1226*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v3, v2);
1227*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v5, v4);
1228*35238bceSAndroid Build Coastguard Worker 
1229*35238bceSAndroid Build Coastguard Worker             if (v1 + v3 + v5 >= 0)
1230*35238bceSAndroid Build Coastguard Worker             {
1231*35238bceSAndroid Build Coastguard Worker                 e0 = clampedRGBA(IVec4(v0, v2, v4, 0xff));
1232*35238bceSAndroid Build Coastguard Worker                 e1 = clampedRGBA(IVec4(v0 + v1, v2 + v3, v4 + v5, 0xff));
1233*35238bceSAndroid Build Coastguard Worker             }
1234*35238bceSAndroid Build Coastguard Worker             else
1235*35238bceSAndroid Build Coastguard Worker             {
1236*35238bceSAndroid Build Coastguard Worker                 e0 = clampedRGBA(blueContract(v0 + v1, v2 + v3, v4 + v5, 0xff));
1237*35238bceSAndroid Build Coastguard Worker                 e1 = clampedRGBA(blueContract(v0, v2, v4, 0xff));
1238*35238bceSAndroid Build Coastguard Worker             }
1239*35238bceSAndroid Build Coastguard Worker             break;
1240*35238bceSAndroid Build Coastguard Worker         }
1241*35238bceSAndroid Build Coastguard Worker 
1242*35238bceSAndroid Build Coastguard Worker         case 10:
1243*35238bceSAndroid Build Coastguard Worker             e0 = UVec4((v[0] * v[3]) >> 8, (v[1] * v[3]) >> 8, (v[2] * v[3]) >> 8, v[4]);
1244*35238bceSAndroid Build Coastguard Worker             e1 = UVec4(v[0], v[1], v[2], v[5]);
1245*35238bceSAndroid Build Coastguard Worker             break;
1246*35238bceSAndroid Build Coastguard Worker 
1247*35238bceSAndroid Build Coastguard Worker         case 11:
1248*35238bceSAndroid Build Coastguard Worker             decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
1249*35238bceSAndroid Build Coastguard Worker             break;
1250*35238bceSAndroid Build Coastguard Worker 
1251*35238bceSAndroid Build Coastguard Worker         case 12:
1252*35238bceSAndroid Build Coastguard Worker             if (v[1] + v[3] + v[5] >= v[0] + v[2] + v[4])
1253*35238bceSAndroid Build Coastguard Worker             {
1254*35238bceSAndroid Build Coastguard Worker                 e0 = UVec4(v[0], v[2], v[4], v[6]);
1255*35238bceSAndroid Build Coastguard Worker                 e1 = UVec4(v[1], v[3], v[5], v[7]);
1256*35238bceSAndroid Build Coastguard Worker             }
1257*35238bceSAndroid Build Coastguard Worker             else
1258*35238bceSAndroid Build Coastguard Worker             {
1259*35238bceSAndroid Build Coastguard Worker                 e0 = clampedRGBA(blueContract(v[1], v[3], v[5], v[7]));
1260*35238bceSAndroid Build Coastguard Worker                 e1 = clampedRGBA(blueContract(v[0], v[2], v[4], v[6]));
1261*35238bceSAndroid Build Coastguard Worker             }
1262*35238bceSAndroid Build Coastguard Worker             break;
1263*35238bceSAndroid Build Coastguard Worker 
1264*35238bceSAndroid Build Coastguard Worker         case 13:
1265*35238bceSAndroid Build Coastguard Worker         {
1266*35238bceSAndroid Build Coastguard Worker             int32_t v0 = (int32_t)v[0];
1267*35238bceSAndroid Build Coastguard Worker             int32_t v1 = (int32_t)v[1];
1268*35238bceSAndroid Build Coastguard Worker             int32_t v2 = (int32_t)v[2];
1269*35238bceSAndroid Build Coastguard Worker             int32_t v3 = (int32_t)v[3];
1270*35238bceSAndroid Build Coastguard Worker             int32_t v4 = (int32_t)v[4];
1271*35238bceSAndroid Build Coastguard Worker             int32_t v5 = (int32_t)v[5];
1272*35238bceSAndroid Build Coastguard Worker             int32_t v6 = (int32_t)v[6];
1273*35238bceSAndroid Build Coastguard Worker             int32_t v7 = (int32_t)v[7];
1274*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v1, v0);
1275*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v3, v2);
1276*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v5, v4);
1277*35238bceSAndroid Build Coastguard Worker             bitTransferSigned(v7, v6);
1278*35238bceSAndroid Build Coastguard Worker 
1279*35238bceSAndroid Build Coastguard Worker             if (v1 + v3 + v5 >= 0)
1280*35238bceSAndroid Build Coastguard Worker             {
1281*35238bceSAndroid Build Coastguard Worker                 e0 = clampedRGBA(IVec4(v0, v2, v4, v6));
1282*35238bceSAndroid Build Coastguard Worker                 e1 = clampedRGBA(IVec4(v0 + v1, v2 + v3, v4 + v5, v6 + v7));
1283*35238bceSAndroid Build Coastguard Worker             }
1284*35238bceSAndroid Build Coastguard Worker             else
1285*35238bceSAndroid Build Coastguard Worker             {
1286*35238bceSAndroid Build Coastguard Worker                 e0 = clampedRGBA(blueContract(v0 + v1, v2 + v3, v4 + v5, v6 + v7));
1287*35238bceSAndroid Build Coastguard Worker                 e1 = clampedRGBA(blueContract(v0, v2, v4, v6));
1288*35238bceSAndroid Build Coastguard Worker             }
1289*35238bceSAndroid Build Coastguard Worker 
1290*35238bceSAndroid Build Coastguard Worker             break;
1291*35238bceSAndroid Build Coastguard Worker         }
1292*35238bceSAndroid Build Coastguard Worker 
1293*35238bceSAndroid Build Coastguard Worker         case 14:
1294*35238bceSAndroid Build Coastguard Worker             decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
1295*35238bceSAndroid Build Coastguard Worker             e0.w() = v[6];
1296*35238bceSAndroid Build Coastguard Worker             e1.w() = v[7];
1297*35238bceSAndroid Build Coastguard Worker             break;
1298*35238bceSAndroid Build Coastguard Worker 
1299*35238bceSAndroid Build Coastguard Worker         case 15:
1300*35238bceSAndroid Build Coastguard Worker             decodeHDREndpointMode15(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
1301*35238bceSAndroid Build Coastguard Worker             break;
1302*35238bceSAndroid Build Coastguard Worker 
1303*35238bceSAndroid Build Coastguard Worker         default:
1304*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1305*35238bceSAndroid Build Coastguard Worker         }
1306*35238bceSAndroid Build Coastguard Worker     }
1307*35238bceSAndroid Build Coastguard Worker }
1308*35238bceSAndroid Build Coastguard Worker 
computeColorEndpoints(ColorEndpointPair * dst,const Block128 & blockData,const uint32_t * endpointModes,int numPartitions,int numColorEndpointValues,const ISEParams & iseParams,int numBitsAvailable)1309*35238bceSAndroid Build Coastguard Worker void computeColorEndpoints(ColorEndpointPair *dst, const Block128 &blockData, const uint32_t *endpointModes,
1310*35238bceSAndroid Build Coastguard Worker                            int numPartitions, int numColorEndpointValues, const ISEParams &iseParams,
1311*35238bceSAndroid Build Coastguard Worker                            int numBitsAvailable)
1312*35238bceSAndroid Build Coastguard Worker {
1313*35238bceSAndroid Build Coastguard Worker     const int colorEndpointDataStart = numPartitions == 1 ? 17 : 29;
1314*35238bceSAndroid Build Coastguard Worker     ISEDecodedResult colorEndpointData[18];
1315*35238bceSAndroid Build Coastguard Worker 
1316*35238bceSAndroid Build Coastguard Worker     {
1317*35238bceSAndroid Build Coastguard Worker         BitAccessStream dataStream(blockData, colorEndpointDataStart, numBitsAvailable, true);
1318*35238bceSAndroid Build Coastguard Worker         decodeISE(&colorEndpointData[0], numColorEndpointValues, dataStream, iseParams);
1319*35238bceSAndroid Build Coastguard Worker     }
1320*35238bceSAndroid Build Coastguard Worker 
1321*35238bceSAndroid Build Coastguard Worker     {
1322*35238bceSAndroid Build Coastguard Worker         uint32_t unquantizedEndpoints[18];
1323*35238bceSAndroid Build Coastguard Worker         unquantizeColorEndpoints(&unquantizedEndpoints[0], &colorEndpointData[0], numColorEndpointValues, iseParams);
1324*35238bceSAndroid Build Coastguard Worker         decodeColorEndpoints(dst, &unquantizedEndpoints[0], &endpointModes[0], numPartitions);
1325*35238bceSAndroid Build Coastguard Worker     }
1326*35238bceSAndroid Build Coastguard Worker }
1327*35238bceSAndroid Build Coastguard Worker 
unquantizeWeights(uint32_t dst[64],const ISEDecodedResult * weightGrid,const ASTCBlockMode & blockMode)1328*35238bceSAndroid Build Coastguard Worker void unquantizeWeights(uint32_t dst[64], const ISEDecodedResult *weightGrid, const ASTCBlockMode &blockMode)
1329*35238bceSAndroid Build Coastguard Worker {
1330*35238bceSAndroid Build Coastguard Worker     const int numWeights       = computeNumWeights(blockMode);
1331*35238bceSAndroid Build Coastguard Worker     const ISEParams &iseParams = blockMode.weightISEParams;
1332*35238bceSAndroid Build Coastguard Worker 
1333*35238bceSAndroid Build Coastguard Worker     if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
1334*35238bceSAndroid Build Coastguard Worker     {
1335*35238bceSAndroid Build Coastguard Worker         const int rangeCase = iseParams.numBits * 2 + (iseParams.mode == ISEMODE_QUINT ? 1 : 0);
1336*35238bceSAndroid Build Coastguard Worker 
1337*35238bceSAndroid Build Coastguard Worker         if (rangeCase == 0 || rangeCase == 1)
1338*35238bceSAndroid Build Coastguard Worker         {
1339*35238bceSAndroid Build Coastguard Worker             static const uint32_t map0[3] = {0, 32, 63};
1340*35238bceSAndroid Build Coastguard Worker             static const uint32_t map1[5] = {0, 16, 32, 47, 63};
1341*35238bceSAndroid Build Coastguard Worker             const uint32_t *const map     = rangeCase == 0 ? &map0[0] : &map1[0];
1342*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < numWeights; i++)
1343*35238bceSAndroid Build Coastguard Worker             {
1344*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(weightGrid[i].v < (rangeCase == 0 ? 3u : 5u));
1345*35238bceSAndroid Build Coastguard Worker                 dst[i] = map[weightGrid[i].v];
1346*35238bceSAndroid Build Coastguard Worker             }
1347*35238bceSAndroid Build Coastguard Worker         }
1348*35238bceSAndroid Build Coastguard Worker         else
1349*35238bceSAndroid Build Coastguard Worker         {
1350*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(rangeCase <= 6);
1351*35238bceSAndroid Build Coastguard Worker             static const uint32_t Ca[5] = {50, 28, 23, 13, 11};
1352*35238bceSAndroid Build Coastguard Worker             const uint32_t C            = Ca[rangeCase - 2];
1353*35238bceSAndroid Build Coastguard Worker 
1354*35238bceSAndroid Build Coastguard Worker             for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
1355*35238bceSAndroid Build Coastguard Worker             {
1356*35238bceSAndroid Build Coastguard Worker                 const uint32_t a = getBit(weightGrid[weightNdx].m, 0);
1357*35238bceSAndroid Build Coastguard Worker                 const uint32_t b = getBit(weightGrid[weightNdx].m, 1);
1358*35238bceSAndroid Build Coastguard Worker                 const uint32_t c = getBit(weightGrid[weightNdx].m, 2);
1359*35238bceSAndroid Build Coastguard Worker 
1360*35238bceSAndroid Build Coastguard Worker                 const uint32_t A = a == 0 ? 0 : (1 << 7) - 1;
1361*35238bceSAndroid Build Coastguard Worker                 const uint32_t B = rangeCase == 2 ? 0 :
1362*35238bceSAndroid Build Coastguard Worker                                    rangeCase == 3 ? 0 :
1363*35238bceSAndroid Build Coastguard Worker                                    rangeCase == 4 ? (b << 6) | (b << 2) | (b << 0) :
1364*35238bceSAndroid Build Coastguard Worker                                    rangeCase == 5 ? (b << 6) | (b << 1) :
1365*35238bceSAndroid Build Coastguard Worker                                    rangeCase == 6 ? (c << 6) | (b << 5) | (c << 1) | (b << 0) :
1366*35238bceSAndroid Build Coastguard Worker                                                     (uint32_t)-1;
1367*35238bceSAndroid Build Coastguard Worker 
1368*35238bceSAndroid Build Coastguard Worker                 dst[weightNdx] = (((weightGrid[weightNdx].tq * C + B) ^ A) >> 2) | (A & 0x20);
1369*35238bceSAndroid Build Coastguard Worker             }
1370*35238bceSAndroid Build Coastguard Worker         }
1371*35238bceSAndroid Build Coastguard Worker     }
1372*35238bceSAndroid Build Coastguard Worker     else
1373*35238bceSAndroid Build Coastguard Worker     {
1374*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
1375*35238bceSAndroid Build Coastguard Worker 
1376*35238bceSAndroid Build Coastguard Worker         for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
1377*35238bceSAndroid Build Coastguard Worker             dst[weightNdx] = bitReplicationScale(weightGrid[weightNdx].v, iseParams.numBits, 6);
1378*35238bceSAndroid Build Coastguard Worker     }
1379*35238bceSAndroid Build Coastguard Worker 
1380*35238bceSAndroid Build Coastguard Worker     for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
1381*35238bceSAndroid Build Coastguard Worker         dst[weightNdx] += dst[weightNdx] > 32 ? 1 : 0;
1382*35238bceSAndroid Build Coastguard Worker 
1383*35238bceSAndroid Build Coastguard Worker     // Initialize nonexistent weights to poison values
1384*35238bceSAndroid Build Coastguard Worker     for (int weightNdx = numWeights; weightNdx < 64; weightNdx++)
1385*35238bceSAndroid Build Coastguard Worker         dst[weightNdx] = ~0u;
1386*35238bceSAndroid Build Coastguard Worker }
1387*35238bceSAndroid Build Coastguard Worker 
interpolateWeights(TexelWeightPair * dst,const uint32_t (& unquantizedWeights)[64],int blockWidth,int blockHeight,const ASTCBlockMode & blockMode)1388*35238bceSAndroid Build Coastguard Worker void interpolateWeights(TexelWeightPair *dst, const uint32_t (&unquantizedWeights)[64], int blockWidth, int blockHeight,
1389*35238bceSAndroid Build Coastguard Worker                         const ASTCBlockMode &blockMode)
1390*35238bceSAndroid Build Coastguard Worker {
1391*35238bceSAndroid Build Coastguard Worker     const int numWeightsPerTexel = blockMode.isDualPlane ? 2 : 1;
1392*35238bceSAndroid Build Coastguard Worker     const uint32_t scaleX        = (1024 + blockWidth / 2) / (blockWidth - 1);
1393*35238bceSAndroid Build Coastguard Worker     const uint32_t scaleY        = (1024 + blockHeight / 2) / (blockHeight - 1);
1394*35238bceSAndroid Build Coastguard Worker 
1395*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockMode.weightGridWidth * blockMode.weightGridHeight * numWeightsPerTexel <=
1396*35238bceSAndroid Build Coastguard Worker               DE_LENGTH_OF_ARRAY(unquantizedWeights));
1397*35238bceSAndroid Build Coastguard Worker 
1398*35238bceSAndroid Build Coastguard Worker     for (int texelY = 0; texelY < blockHeight; texelY++)
1399*35238bceSAndroid Build Coastguard Worker     {
1400*35238bceSAndroid Build Coastguard Worker         for (int texelX = 0; texelX < blockWidth; texelX++)
1401*35238bceSAndroid Build Coastguard Worker         {
1402*35238bceSAndroid Build Coastguard Worker             const uint32_t gX = (scaleX * texelX * (blockMode.weightGridWidth - 1) + 32) >> 6;
1403*35238bceSAndroid Build Coastguard Worker             const uint32_t gY = (scaleY * texelY * (blockMode.weightGridHeight - 1) + 32) >> 6;
1404*35238bceSAndroid Build Coastguard Worker             const uint32_t jX = gX >> 4;
1405*35238bceSAndroid Build Coastguard Worker             const uint32_t jY = gY >> 4;
1406*35238bceSAndroid Build Coastguard Worker             const uint32_t fX = gX & 0xf;
1407*35238bceSAndroid Build Coastguard Worker             const uint32_t fY = gY & 0xf;
1408*35238bceSAndroid Build Coastguard Worker 
1409*35238bceSAndroid Build Coastguard Worker             const uint32_t w11 = (fX * fY + 8) >> 4;
1410*35238bceSAndroid Build Coastguard Worker             const uint32_t w10 = fY - w11;
1411*35238bceSAndroid Build Coastguard Worker             const uint32_t w01 = fX - w11;
1412*35238bceSAndroid Build Coastguard Worker             const uint32_t w00 = 16 - fX - fY + w11;
1413*35238bceSAndroid Build Coastguard Worker 
1414*35238bceSAndroid Build Coastguard Worker             const uint32_t i00 = jY * blockMode.weightGridWidth + jX;
1415*35238bceSAndroid Build Coastguard Worker             const uint32_t i01 = i00 + 1;
1416*35238bceSAndroid Build Coastguard Worker             const uint32_t i10 = i00 + blockMode.weightGridWidth;
1417*35238bceSAndroid Build Coastguard Worker             const uint32_t i11 = i00 + blockMode.weightGridWidth + 1;
1418*35238bceSAndroid Build Coastguard Worker 
1419*35238bceSAndroid Build Coastguard Worker             // These addresses can be out of bounds, but respective weights will be 0 then.
1420*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(deInBounds32(i00, 0, blockMode.weightGridWidth * blockMode.weightGridHeight) || w00 == 0);
1421*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(deInBounds32(i01, 0, blockMode.weightGridWidth * blockMode.weightGridHeight) || w01 == 0);
1422*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(deInBounds32(i10, 0, blockMode.weightGridWidth * blockMode.weightGridHeight) || w10 == 0);
1423*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(deInBounds32(i11, 0, blockMode.weightGridWidth * blockMode.weightGridHeight) || w11 == 0);
1424*35238bceSAndroid Build Coastguard Worker 
1425*35238bceSAndroid Build Coastguard Worker             for (int texelWeightNdx = 0; texelWeightNdx < numWeightsPerTexel; texelWeightNdx++)
1426*35238bceSAndroid Build Coastguard Worker             {
1427*35238bceSAndroid Build Coastguard Worker                 // & 0x3f clamps address to bounds of unquantizedWeights
1428*35238bceSAndroid Build Coastguard Worker                 const uint32_t p00 = unquantizedWeights[(i00 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
1429*35238bceSAndroid Build Coastguard Worker                 const uint32_t p01 = unquantizedWeights[(i01 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
1430*35238bceSAndroid Build Coastguard Worker                 const uint32_t p10 = unquantizedWeights[(i10 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
1431*35238bceSAndroid Build Coastguard Worker                 const uint32_t p11 = unquantizedWeights[(i11 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
1432*35238bceSAndroid Build Coastguard Worker 
1433*35238bceSAndroid Build Coastguard Worker                 dst[texelY * blockWidth + texelX].w[texelWeightNdx] =
1434*35238bceSAndroid Build Coastguard Worker                     (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;
1435*35238bceSAndroid Build Coastguard Worker             }
1436*35238bceSAndroid Build Coastguard Worker         }
1437*35238bceSAndroid Build Coastguard Worker     }
1438*35238bceSAndroid Build Coastguard Worker }
1439*35238bceSAndroid Build Coastguard Worker 
computeTexelWeights(TexelWeightPair * dst,const Block128 & blockData,int blockWidth,int blockHeight,const ASTCBlockMode & blockMode)1440*35238bceSAndroid Build Coastguard Worker void computeTexelWeights(TexelWeightPair *dst, const Block128 &blockData, int blockWidth, int blockHeight,
1441*35238bceSAndroid Build Coastguard Worker                          const ASTCBlockMode &blockMode)
1442*35238bceSAndroid Build Coastguard Worker {
1443*35238bceSAndroid Build Coastguard Worker     ISEDecodedResult weightGrid[64];
1444*35238bceSAndroid Build Coastguard Worker 
1445*35238bceSAndroid Build Coastguard Worker     {
1446*35238bceSAndroid Build Coastguard Worker         BitAccessStream dataStream(
1447*35238bceSAndroid Build Coastguard Worker             blockData, 127, computeNumRequiredBits(blockMode.weightISEParams, computeNumWeights(blockMode)), false);
1448*35238bceSAndroid Build Coastguard Worker         decodeISE(&weightGrid[0], computeNumWeights(blockMode), dataStream, blockMode.weightISEParams);
1449*35238bceSAndroid Build Coastguard Worker     }
1450*35238bceSAndroid Build Coastguard Worker 
1451*35238bceSAndroid Build Coastguard Worker     {
1452*35238bceSAndroid Build Coastguard Worker         uint32_t unquantizedWeights[64];
1453*35238bceSAndroid Build Coastguard Worker         unquantizeWeights(&unquantizedWeights[0], &weightGrid[0], blockMode);
1454*35238bceSAndroid Build Coastguard Worker         interpolateWeights(dst, unquantizedWeights, blockWidth, blockHeight, blockMode);
1455*35238bceSAndroid Build Coastguard Worker     }
1456*35238bceSAndroid Build Coastguard Worker }
1457*35238bceSAndroid Build Coastguard Worker 
hash52(uint32_t v)1458*35238bceSAndroid Build Coastguard Worker inline uint32_t hash52(uint32_t v)
1459*35238bceSAndroid Build Coastguard Worker {
1460*35238bceSAndroid Build Coastguard Worker     uint32_t p = v;
1461*35238bceSAndroid Build Coastguard Worker     p ^= p >> 15;
1462*35238bceSAndroid Build Coastguard Worker     p -= p << 17;
1463*35238bceSAndroid Build Coastguard Worker     p += p << 7;
1464*35238bceSAndroid Build Coastguard Worker     p += p << 4;
1465*35238bceSAndroid Build Coastguard Worker     p ^= p >> 5;
1466*35238bceSAndroid Build Coastguard Worker     p += p << 16;
1467*35238bceSAndroid Build Coastguard Worker     p ^= p >> 7;
1468*35238bceSAndroid Build Coastguard Worker     p ^= p >> 3;
1469*35238bceSAndroid Build Coastguard Worker     p ^= p << 6;
1470*35238bceSAndroid Build Coastguard Worker     p ^= p >> 17;
1471*35238bceSAndroid Build Coastguard Worker     return p;
1472*35238bceSAndroid Build Coastguard Worker }
1473*35238bceSAndroid Build Coastguard Worker 
computeTexelPartition(uint32_t seedIn,uint32_t xIn,uint32_t yIn,uint32_t zIn,int numPartitions,bool smallBlock)1474*35238bceSAndroid Build Coastguard Worker int computeTexelPartition(uint32_t seedIn, uint32_t xIn, uint32_t yIn, uint32_t zIn, int numPartitions, bool smallBlock)
1475*35238bceSAndroid Build Coastguard Worker {
1476*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(zIn == 0);
1477*35238bceSAndroid Build Coastguard Worker     const uint32_t x    = smallBlock ? xIn << 1 : xIn;
1478*35238bceSAndroid Build Coastguard Worker     const uint32_t y    = smallBlock ? yIn << 1 : yIn;
1479*35238bceSAndroid Build Coastguard Worker     const uint32_t z    = smallBlock ? zIn << 1 : zIn;
1480*35238bceSAndroid Build Coastguard Worker     const uint32_t seed = seedIn + 1024 * (numPartitions - 1);
1481*35238bceSAndroid Build Coastguard Worker     const uint32_t rnum = hash52(seed);
1482*35238bceSAndroid Build Coastguard Worker     uint8_t seed1       = (uint8_t)(rnum & 0xf);
1483*35238bceSAndroid Build Coastguard Worker     uint8_t seed2       = (uint8_t)((rnum >> 4) & 0xf);
1484*35238bceSAndroid Build Coastguard Worker     uint8_t seed3       = (uint8_t)((rnum >> 8) & 0xf);
1485*35238bceSAndroid Build Coastguard Worker     uint8_t seed4       = (uint8_t)((rnum >> 12) & 0xf);
1486*35238bceSAndroid Build Coastguard Worker     uint8_t seed5       = (uint8_t)((rnum >> 16) & 0xf);
1487*35238bceSAndroid Build Coastguard Worker     uint8_t seed6       = (uint8_t)((rnum >> 20) & 0xf);
1488*35238bceSAndroid Build Coastguard Worker     uint8_t seed7       = (uint8_t)((rnum >> 24) & 0xf);
1489*35238bceSAndroid Build Coastguard Worker     uint8_t seed8       = (uint8_t)((rnum >> 28) & 0xf);
1490*35238bceSAndroid Build Coastguard Worker     uint8_t seed9       = (uint8_t)((rnum >> 18) & 0xf);
1491*35238bceSAndroid Build Coastguard Worker     uint8_t seed10      = (uint8_t)((rnum >> 22) & 0xf);
1492*35238bceSAndroid Build Coastguard Worker     uint8_t seed11      = (uint8_t)((rnum >> 26) & 0xf);
1493*35238bceSAndroid Build Coastguard Worker     uint8_t seed12      = (uint8_t)(((rnum >> 30) | (rnum << 2)) & 0xf);
1494*35238bceSAndroid Build Coastguard Worker 
1495*35238bceSAndroid Build Coastguard Worker     seed1  = (uint8_t)(seed1 * seed1);
1496*35238bceSAndroid Build Coastguard Worker     seed2  = (uint8_t)(seed2 * seed2);
1497*35238bceSAndroid Build Coastguard Worker     seed3  = (uint8_t)(seed3 * seed3);
1498*35238bceSAndroid Build Coastguard Worker     seed4  = (uint8_t)(seed4 * seed4);
1499*35238bceSAndroid Build Coastguard Worker     seed5  = (uint8_t)(seed5 * seed5);
1500*35238bceSAndroid Build Coastguard Worker     seed6  = (uint8_t)(seed6 * seed6);
1501*35238bceSAndroid Build Coastguard Worker     seed7  = (uint8_t)(seed7 * seed7);
1502*35238bceSAndroid Build Coastguard Worker     seed8  = (uint8_t)(seed8 * seed8);
1503*35238bceSAndroid Build Coastguard Worker     seed9  = (uint8_t)(seed9 * seed9);
1504*35238bceSAndroid Build Coastguard Worker     seed10 = (uint8_t)(seed10 * seed10);
1505*35238bceSAndroid Build Coastguard Worker     seed11 = (uint8_t)(seed11 * seed11);
1506*35238bceSAndroid Build Coastguard Worker     seed12 = (uint8_t)(seed12 * seed12);
1507*35238bceSAndroid Build Coastguard Worker 
1508*35238bceSAndroid Build Coastguard Worker     const int shA = (seed & 2) != 0 ? 4 : 5;
1509*35238bceSAndroid Build Coastguard Worker     const int shB = numPartitions == 3 ? 6 : 5;
1510*35238bceSAndroid Build Coastguard Worker     const int sh1 = (seed & 1) != 0 ? shA : shB;
1511*35238bceSAndroid Build Coastguard Worker     const int sh2 = (seed & 1) != 0 ? shB : shA;
1512*35238bceSAndroid Build Coastguard Worker     const int sh3 = (seed & 0x10) != 0 ? sh1 : sh2;
1513*35238bceSAndroid Build Coastguard Worker 
1514*35238bceSAndroid Build Coastguard Worker     seed1  = (uint8_t)(seed1 >> sh1);
1515*35238bceSAndroid Build Coastguard Worker     seed2  = (uint8_t)(seed2 >> sh2);
1516*35238bceSAndroid Build Coastguard Worker     seed3  = (uint8_t)(seed3 >> sh1);
1517*35238bceSAndroid Build Coastguard Worker     seed4  = (uint8_t)(seed4 >> sh2);
1518*35238bceSAndroid Build Coastguard Worker     seed5  = (uint8_t)(seed5 >> sh1);
1519*35238bceSAndroid Build Coastguard Worker     seed6  = (uint8_t)(seed6 >> sh2);
1520*35238bceSAndroid Build Coastguard Worker     seed7  = (uint8_t)(seed7 >> sh1);
1521*35238bceSAndroid Build Coastguard Worker     seed8  = (uint8_t)(seed8 >> sh2);
1522*35238bceSAndroid Build Coastguard Worker     seed9  = (uint8_t)(seed9 >> sh3);
1523*35238bceSAndroid Build Coastguard Worker     seed10 = (uint8_t)(seed10 >> sh3);
1524*35238bceSAndroid Build Coastguard Worker     seed11 = (uint8_t)(seed11 >> sh3);
1525*35238bceSAndroid Build Coastguard Worker     seed12 = (uint8_t)(seed12 >> sh3);
1526*35238bceSAndroid Build Coastguard Worker 
1527*35238bceSAndroid Build Coastguard Worker     const int a = 0x3f & (seed1 * x + seed2 * y + seed11 * z + (rnum >> 14));
1528*35238bceSAndroid Build Coastguard Worker     const int b = 0x3f & (seed3 * x + seed4 * y + seed12 * z + (rnum >> 10));
1529*35238bceSAndroid Build Coastguard Worker     const int c = numPartitions >= 3 ? 0x3f & (seed5 * x + seed6 * y + seed9 * z + (rnum >> 6)) : 0;
1530*35238bceSAndroid Build Coastguard Worker     const int d = numPartitions >= 4 ? 0x3f & (seed7 * x + seed8 * y + seed10 * z + (rnum >> 2)) : 0;
1531*35238bceSAndroid Build Coastguard Worker 
1532*35238bceSAndroid Build Coastguard Worker     return a >= b && a >= c && a >= d ? 0 : b >= c && b >= d ? 1 : c >= d ? 2 : 3;
1533*35238bceSAndroid Build Coastguard Worker }
1534*35238bceSAndroid Build Coastguard Worker 
setTexelColors(void * dst,ColorEndpointPair * colorEndpoints,TexelWeightPair * texelWeights,int ccs,uint32_t partitionIndexSeed,int numPartitions,int blockWidth,int blockHeight,bool isSRGB,bool isLDRMode,const uint32_t * colorEndpointModes)1535*35238bceSAndroid Build Coastguard Worker DecompressResult setTexelColors(void *dst, ColorEndpointPair *colorEndpoints, TexelWeightPair *texelWeights, int ccs,
1536*35238bceSAndroid Build Coastguard Worker                                 uint32_t partitionIndexSeed, int numPartitions, int blockWidth, int blockHeight,
1537*35238bceSAndroid Build Coastguard Worker                                 bool isSRGB, bool isLDRMode, const uint32_t *colorEndpointModes)
1538*35238bceSAndroid Build Coastguard Worker {
1539*35238bceSAndroid Build Coastguard Worker     const bool smallBlock   = blockWidth * blockHeight < 31;
1540*35238bceSAndroid Build Coastguard Worker     DecompressResult result = DECOMPRESS_RESULT_VALID_BLOCK;
1541*35238bceSAndroid Build Coastguard Worker     bool isHDREndpoint[4];
1542*35238bceSAndroid Build Coastguard Worker 
1543*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < numPartitions; i++)
1544*35238bceSAndroid Build Coastguard Worker         isHDREndpoint[i] = isColorEndpointModeHDR(colorEndpointModes[i]);
1545*35238bceSAndroid Build Coastguard Worker 
1546*35238bceSAndroid Build Coastguard Worker     for (int texelY = 0; texelY < blockHeight; texelY++)
1547*35238bceSAndroid Build Coastguard Worker         for (int texelX = 0; texelX < blockWidth; texelX++)
1548*35238bceSAndroid Build Coastguard Worker         {
1549*35238bceSAndroid Build Coastguard Worker             const int texelNdx         = texelY * blockWidth + texelX;
1550*35238bceSAndroid Build Coastguard Worker             const int colorEndpointNdx = numPartitions == 1 ? 0 :
1551*35238bceSAndroid Build Coastguard Worker                                                               computeTexelPartition(partitionIndexSeed, texelX, texelY,
1552*35238bceSAndroid Build Coastguard Worker                                                                                     0, numPartitions, smallBlock);
1553*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(colorEndpointNdx < numPartitions);
1554*35238bceSAndroid Build Coastguard Worker             const UVec4 &e0               = colorEndpoints[colorEndpointNdx].e0;
1555*35238bceSAndroid Build Coastguard Worker             const UVec4 &e1               = colorEndpoints[colorEndpointNdx].e1;
1556*35238bceSAndroid Build Coastguard Worker             const TexelWeightPair &weight = texelWeights[texelNdx];
1557*35238bceSAndroid Build Coastguard Worker 
1558*35238bceSAndroid Build Coastguard Worker             if (isLDRMode && isHDREndpoint[colorEndpointNdx])
1559*35238bceSAndroid Build Coastguard Worker             {
1560*35238bceSAndroid Build Coastguard Worker                 if (isSRGB)
1561*35238bceSAndroid Build Coastguard Worker                 {
1562*35238bceSAndroid Build Coastguard Worker                     ((uint8_t *)dst)[texelNdx * 4 + 0] = 0xff;
1563*35238bceSAndroid Build Coastguard Worker                     ((uint8_t *)dst)[texelNdx * 4 + 1] = 0;
1564*35238bceSAndroid Build Coastguard Worker                     ((uint8_t *)dst)[texelNdx * 4 + 2] = 0xff;
1565*35238bceSAndroid Build Coastguard Worker                     ((uint8_t *)dst)[texelNdx * 4 + 3] = 0xff;
1566*35238bceSAndroid Build Coastguard Worker                 }
1567*35238bceSAndroid Build Coastguard Worker                 else
1568*35238bceSAndroid Build Coastguard Worker                 {
1569*35238bceSAndroid Build Coastguard Worker                     ((float *)dst)[texelNdx * 4 + 0] = 1.0f;
1570*35238bceSAndroid Build Coastguard Worker                     ((float *)dst)[texelNdx * 4 + 1] = 0;
1571*35238bceSAndroid Build Coastguard Worker                     ((float *)dst)[texelNdx * 4 + 2] = 1.0f;
1572*35238bceSAndroid Build Coastguard Worker                     ((float *)dst)[texelNdx * 4 + 3] = 1.0f;
1573*35238bceSAndroid Build Coastguard Worker                 }
1574*35238bceSAndroid Build Coastguard Worker 
1575*35238bceSAndroid Build Coastguard Worker                 result = DECOMPRESS_RESULT_ERROR;
1576*35238bceSAndroid Build Coastguard Worker             }
1577*35238bceSAndroid Build Coastguard Worker             else
1578*35238bceSAndroid Build Coastguard Worker             {
1579*35238bceSAndroid Build Coastguard Worker                 for (int channelNdx = 0; channelNdx < 4; channelNdx++)
1580*35238bceSAndroid Build Coastguard Worker                 {
1581*35238bceSAndroid Build Coastguard Worker                     if (!isHDREndpoint[colorEndpointNdx] ||
1582*35238bceSAndroid Build Coastguard Worker                         (channelNdx == 3 && colorEndpointModes[colorEndpointNdx] ==
1583*35238bceSAndroid Build Coastguard Worker                                                 14)) // \note Alpha for mode 14 is treated the same as LDR.
1584*35238bceSAndroid Build Coastguard Worker                     {
1585*35238bceSAndroid Build Coastguard Worker                         const uint32_t c0 = (e0[channelNdx] << 8) | (isSRGB ? 0x80 : e0[channelNdx]);
1586*35238bceSAndroid Build Coastguard Worker                         const uint32_t c1 = (e1[channelNdx] << 8) | (isSRGB ? 0x80 : e1[channelNdx]);
1587*35238bceSAndroid Build Coastguard Worker                         const uint32_t w  = weight.w[ccs == channelNdx ? 1 : 0];
1588*35238bceSAndroid Build Coastguard Worker                         const uint32_t c  = (c0 * (64 - w) + c1 * w + 32) / 64;
1589*35238bceSAndroid Build Coastguard Worker 
1590*35238bceSAndroid Build Coastguard Worker                         if (isSRGB)
1591*35238bceSAndroid Build Coastguard Worker                             ((uint8_t *)dst)[texelNdx * 4 + channelNdx] = (uint8_t)((c & 0xff00) >> 8);
1592*35238bceSAndroid Build Coastguard Worker                         else
1593*35238bceSAndroid Build Coastguard Worker                             ((float *)dst)[texelNdx * 4 + channelNdx] = c == 65535 ? 1.0f : (float)c / 65536.0f;
1594*35238bceSAndroid Build Coastguard Worker                     }
1595*35238bceSAndroid Build Coastguard Worker                     else
1596*35238bceSAndroid Build Coastguard Worker                     {
1597*35238bceSAndroid Build Coastguard Worker                         DE_STATIC_ASSERT((de::meta::TypesSame<deFloat16, uint16_t>::Value));
1598*35238bceSAndroid Build Coastguard Worker                         const uint32_t c0  = e0[channelNdx] << 4;
1599*35238bceSAndroid Build Coastguard Worker                         const uint32_t c1  = e1[channelNdx] << 4;
1600*35238bceSAndroid Build Coastguard Worker                         const uint32_t w   = weight.w[ccs == channelNdx ? 1 : 0];
1601*35238bceSAndroid Build Coastguard Worker                         const uint32_t c   = (c0 * (64 - w) + c1 * w + 32) / 64;
1602*35238bceSAndroid Build Coastguard Worker                         const uint32_t e   = getBits(c, 11, 15);
1603*35238bceSAndroid Build Coastguard Worker                         const uint32_t m   = getBits(c, 0, 10);
1604*35238bceSAndroid Build Coastguard Worker                         const uint32_t mt  = m < 512 ? 3 * m : m >= 1536 ? 5 * m - 2048 : 4 * m - 512;
1605*35238bceSAndroid Build Coastguard Worker                         const deFloat16 cf = (deFloat16)((e << 10) + (mt >> 3));
1606*35238bceSAndroid Build Coastguard Worker 
1607*35238bceSAndroid Build Coastguard Worker                         ((float *)dst)[texelNdx * 4 + channelNdx] = deFloat16To32(isFloat16InfOrNan(cf) ? 0x7bff : cf);
1608*35238bceSAndroid Build Coastguard Worker                     }
1609*35238bceSAndroid Build Coastguard Worker                 }
1610*35238bceSAndroid Build Coastguard Worker             }
1611*35238bceSAndroid Build Coastguard Worker         }
1612*35238bceSAndroid Build Coastguard Worker 
1613*35238bceSAndroid Build Coastguard Worker     return result;
1614*35238bceSAndroid Build Coastguard Worker }
1615*35238bceSAndroid Build Coastguard Worker 
decompressBlock(void * dst,const Block128 & blockData,int blockWidth,int blockHeight,bool isSRGB,bool isLDR)1616*35238bceSAndroid Build Coastguard Worker DecompressResult decompressBlock(void *dst, const Block128 &blockData, int blockWidth, int blockHeight, bool isSRGB,
1617*35238bceSAndroid Build Coastguard Worker                                  bool isLDR)
1618*35238bceSAndroid Build Coastguard Worker {
1619*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isLDR || !isSRGB);
1620*35238bceSAndroid Build Coastguard Worker 
1621*35238bceSAndroid Build Coastguard Worker     // Decode block mode.
1622*35238bceSAndroid Build Coastguard Worker 
1623*35238bceSAndroid Build Coastguard Worker     const ASTCBlockMode blockMode = getASTCBlockMode(blockData.getBits(0, 10));
1624*35238bceSAndroid Build Coastguard Worker 
1625*35238bceSAndroid Build Coastguard Worker     // Check for block mode errors.
1626*35238bceSAndroid Build Coastguard Worker 
1627*35238bceSAndroid Build Coastguard Worker     if (blockMode.isError)
1628*35238bceSAndroid Build Coastguard Worker     {
1629*35238bceSAndroid Build Coastguard Worker         setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
1630*35238bceSAndroid Build Coastguard Worker         return DECOMPRESS_RESULT_ERROR;
1631*35238bceSAndroid Build Coastguard Worker     }
1632*35238bceSAndroid Build Coastguard Worker 
1633*35238bceSAndroid Build Coastguard Worker     // Separate path for void-extent.
1634*35238bceSAndroid Build Coastguard Worker 
1635*35238bceSAndroid Build Coastguard Worker     if (blockMode.isVoidExtent)
1636*35238bceSAndroid Build Coastguard Worker         return decodeVoidExtentBlock(dst, blockData, blockWidth, blockHeight, isSRGB, isLDR);
1637*35238bceSAndroid Build Coastguard Worker 
1638*35238bceSAndroid Build Coastguard Worker     // Compute weight grid values.
1639*35238bceSAndroid Build Coastguard Worker 
1640*35238bceSAndroid Build Coastguard Worker     const int numWeights        = computeNumWeights(blockMode);
1641*35238bceSAndroid Build Coastguard Worker     const int numWeightDataBits = computeNumRequiredBits(blockMode.weightISEParams, numWeights);
1642*35238bceSAndroid Build Coastguard Worker     const int numPartitions     = (int)blockData.getBits(11, 12) + 1;
1643*35238bceSAndroid Build Coastguard Worker 
1644*35238bceSAndroid Build Coastguard Worker     // Check for errors in weight grid, partition and dual-plane parameters.
1645*35238bceSAndroid Build Coastguard Worker 
1646*35238bceSAndroid Build Coastguard Worker     if (numWeights > 64 || numWeightDataBits > 96 || numWeightDataBits < 24 || blockMode.weightGridWidth > blockWidth ||
1647*35238bceSAndroid Build Coastguard Worker         blockMode.weightGridHeight > blockHeight || (numPartitions == 4 && blockMode.isDualPlane))
1648*35238bceSAndroid Build Coastguard Worker     {
1649*35238bceSAndroid Build Coastguard Worker         setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
1650*35238bceSAndroid Build Coastguard Worker         return DECOMPRESS_RESULT_ERROR;
1651*35238bceSAndroid Build Coastguard Worker     }
1652*35238bceSAndroid Build Coastguard Worker 
1653*35238bceSAndroid Build Coastguard Worker     // Compute number of bits available for color endpoint data.
1654*35238bceSAndroid Build Coastguard Worker 
1655*35238bceSAndroid Build Coastguard Worker     const bool isSingleUniqueCem = numPartitions == 1 || blockData.getBits(23, 24) == 0;
1656*35238bceSAndroid Build Coastguard Worker     const int numConfigDataBits  = (numPartitions == 1 ? 17 :
1657*35238bceSAndroid Build Coastguard Worker                                     isSingleUniqueCem  ? 29 :
1658*35238bceSAndroid Build Coastguard Worker                                                          25 + 3 * numPartitions) +
1659*35238bceSAndroid Build Coastguard Worker                                   (blockMode.isDualPlane ? 2 : 0);
1660*35238bceSAndroid Build Coastguard Worker     const int numBitsForColorEndpoints = 128 - numWeightDataBits - numConfigDataBits;
1661*35238bceSAndroid Build Coastguard Worker     const int extraCemBitsStart        = 127 - numWeightDataBits -
1662*35238bceSAndroid Build Coastguard Worker                                   (isSingleUniqueCem  ? -1 :
1663*35238bceSAndroid Build Coastguard Worker                                    numPartitions == 4 ? 7 :
1664*35238bceSAndroid Build Coastguard Worker                                    numPartitions == 3 ? 4 :
1665*35238bceSAndroid Build Coastguard Worker                                    numPartitions == 2 ? 1 :
1666*35238bceSAndroid Build Coastguard Worker                                                         0);
1667*35238bceSAndroid Build Coastguard Worker     // Decode color endpoint modes.
1668*35238bceSAndroid Build Coastguard Worker 
1669*35238bceSAndroid Build Coastguard Worker     uint32_t colorEndpointModes[4];
1670*35238bceSAndroid Build Coastguard Worker     decodeColorEndpointModes(&colorEndpointModes[0], blockData, numPartitions, extraCemBitsStart);
1671*35238bceSAndroid Build Coastguard Worker 
1672*35238bceSAndroid Build Coastguard Worker     const int numColorEndpointValues = computeNumColorEndpointValues(colorEndpointModes, numPartitions);
1673*35238bceSAndroid Build Coastguard Worker 
1674*35238bceSAndroid Build Coastguard Worker     // Check for errors in color endpoint value count.
1675*35238bceSAndroid Build Coastguard Worker 
1676*35238bceSAndroid Build Coastguard Worker     if (numColorEndpointValues > 18 || numBitsForColorEndpoints < deDivRoundUp32(13 * numColorEndpointValues, 5))
1677*35238bceSAndroid Build Coastguard Worker     {
1678*35238bceSAndroid Build Coastguard Worker         setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
1679*35238bceSAndroid Build Coastguard Worker         return DECOMPRESS_RESULT_ERROR;
1680*35238bceSAndroid Build Coastguard Worker     }
1681*35238bceSAndroid Build Coastguard Worker 
1682*35238bceSAndroid Build Coastguard Worker     // Compute color endpoints.
1683*35238bceSAndroid Build Coastguard Worker 
1684*35238bceSAndroid Build Coastguard Worker     ColorEndpointPair colorEndpoints[4];
1685*35238bceSAndroid Build Coastguard Worker     computeColorEndpoints(&colorEndpoints[0], blockData, &colorEndpointModes[0], numPartitions, numColorEndpointValues,
1686*35238bceSAndroid Build Coastguard Worker                           computeMaximumRangeISEParams(numBitsForColorEndpoints, numColorEndpointValues),
1687*35238bceSAndroid Build Coastguard Worker                           numBitsForColorEndpoints);
1688*35238bceSAndroid Build Coastguard Worker 
1689*35238bceSAndroid Build Coastguard Worker     // Compute texel weights.
1690*35238bceSAndroid Build Coastguard Worker 
1691*35238bceSAndroid Build Coastguard Worker     TexelWeightPair texelWeights[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT];
1692*35238bceSAndroid Build Coastguard Worker     computeTexelWeights(&texelWeights[0], blockData, blockWidth, blockHeight, blockMode);
1693*35238bceSAndroid Build Coastguard Worker 
1694*35238bceSAndroid Build Coastguard Worker     // Set texel colors.
1695*35238bceSAndroid Build Coastguard Worker 
1696*35238bceSAndroid Build Coastguard Worker     const int ccs = blockMode.isDualPlane ? (int)blockData.getBits(extraCemBitsStart - 2, extraCemBitsStart - 1) : -1;
1697*35238bceSAndroid Build Coastguard Worker     const uint32_t partitionIndexSeed = numPartitions > 1 ? blockData.getBits(13, 22) : (uint32_t)-1;
1698*35238bceSAndroid Build Coastguard Worker 
1699*35238bceSAndroid Build Coastguard Worker     return setTexelColors(dst, &colorEndpoints[0], &texelWeights[0], ccs, partitionIndexSeed, numPartitions, blockWidth,
1700*35238bceSAndroid Build Coastguard Worker                           blockHeight, isSRGB, isLDR, &colorEndpointModes[0]);
1701*35238bceSAndroid Build Coastguard Worker }
1702*35238bceSAndroid Build Coastguard Worker 
decompress(const PixelBufferAccess & dst,const uint8_t * data,bool isSRGB,bool isLDR)1703*35238bceSAndroid Build Coastguard Worker void decompress(const PixelBufferAccess &dst, const uint8_t *data, bool isSRGB, bool isLDR)
1704*35238bceSAndroid Build Coastguard Worker {
1705*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isLDR || !isSRGB);
1706*35238bceSAndroid Build Coastguard Worker 
1707*35238bceSAndroid Build Coastguard Worker     const int blockWidth  = dst.getWidth();
1708*35238bceSAndroid Build Coastguard Worker     const int blockHeight = dst.getHeight();
1709*35238bceSAndroid Build Coastguard Worker 
1710*35238bceSAndroid Build Coastguard Worker     union
1711*35238bceSAndroid Build Coastguard Worker     {
1712*35238bceSAndroid Build Coastguard Worker         uint8_t sRGB[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
1713*35238bceSAndroid Build Coastguard Worker         float linear[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
1714*35238bceSAndroid Build Coastguard Worker     } decompressedBuffer;
1715*35238bceSAndroid Build Coastguard Worker 
1716*35238bceSAndroid Build Coastguard Worker     const Block128 blockData(data);
1717*35238bceSAndroid Build Coastguard Worker     decompressBlock(isSRGB ? (void *)&decompressedBuffer.sRGB[0] : (void *)&decompressedBuffer.linear[0], blockData,
1718*35238bceSAndroid Build Coastguard Worker                     dst.getWidth(), dst.getHeight(), isSRGB, isLDR);
1719*35238bceSAndroid Build Coastguard Worker 
1720*35238bceSAndroid Build Coastguard Worker     if (isSRGB)
1721*35238bceSAndroid Build Coastguard Worker     {
1722*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < blockHeight; i++)
1723*35238bceSAndroid Build Coastguard Worker             for (int j = 0; j < blockWidth; j++)
1724*35238bceSAndroid Build Coastguard Worker             {
1725*35238bceSAndroid Build Coastguard Worker                 dst.setPixel(IVec4(decompressedBuffer.sRGB[(i * blockWidth + j) * 4 + 0],
1726*35238bceSAndroid Build Coastguard Worker                                    decompressedBuffer.sRGB[(i * blockWidth + j) * 4 + 1],
1727*35238bceSAndroid Build Coastguard Worker                                    decompressedBuffer.sRGB[(i * blockWidth + j) * 4 + 2],
1728*35238bceSAndroid Build Coastguard Worker                                    decompressedBuffer.sRGB[(i * blockWidth + j) * 4 + 3]),
1729*35238bceSAndroid Build Coastguard Worker                              j, i);
1730*35238bceSAndroid Build Coastguard Worker             }
1731*35238bceSAndroid Build Coastguard Worker     }
1732*35238bceSAndroid Build Coastguard Worker     else
1733*35238bceSAndroid Build Coastguard Worker     {
1734*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < blockHeight; i++)
1735*35238bceSAndroid Build Coastguard Worker             for (int j = 0; j < blockWidth; j++)
1736*35238bceSAndroid Build Coastguard Worker             {
1737*35238bceSAndroid Build Coastguard Worker                 dst.setPixel(Vec4(decompressedBuffer.linear[(i * blockWidth + j) * 4 + 0],
1738*35238bceSAndroid Build Coastguard Worker                                   decompressedBuffer.linear[(i * blockWidth + j) * 4 + 1],
1739*35238bceSAndroid Build Coastguard Worker                                   decompressedBuffer.linear[(i * blockWidth + j) * 4 + 2],
1740*35238bceSAndroid Build Coastguard Worker                                   decompressedBuffer.linear[(i * blockWidth + j) * 4 + 3]),
1741*35238bceSAndroid Build Coastguard Worker                              j, i);
1742*35238bceSAndroid Build Coastguard Worker             }
1743*35238bceSAndroid Build Coastguard Worker     }
1744*35238bceSAndroid Build Coastguard Worker }
1745*35238bceSAndroid Build Coastguard Worker 
1746*35238bceSAndroid Build Coastguard Worker // Helper class for setting bits in a 128-bit block.
1747*35238bceSAndroid Build Coastguard Worker class AssignBlock128
1748*35238bceSAndroid Build Coastguard Worker {
1749*35238bceSAndroid Build Coastguard Worker private:
1750*35238bceSAndroid Build Coastguard Worker     typedef uint64_t Word;
1751*35238bceSAndroid Build Coastguard Worker 
1752*35238bceSAndroid Build Coastguard Worker     enum
1753*35238bceSAndroid Build Coastguard Worker     {
1754*35238bceSAndroid Build Coastguard Worker         WORD_BYTES = sizeof(Word),
1755*35238bceSAndroid Build Coastguard Worker         WORD_BITS  = 8 * WORD_BYTES,
1756*35238bceSAndroid Build Coastguard Worker         NUM_WORDS  = 128 / WORD_BITS
1757*35238bceSAndroid Build Coastguard Worker     };
1758*35238bceSAndroid Build Coastguard Worker 
1759*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(128 % WORD_BITS == 0);
1760*35238bceSAndroid Build Coastguard Worker 
1761*35238bceSAndroid Build Coastguard Worker public:
AssignBlock128(void)1762*35238bceSAndroid Build Coastguard Worker     AssignBlock128(void)
1763*35238bceSAndroid Build Coastguard Worker     {
1764*35238bceSAndroid Build Coastguard Worker         for (int wordNdx = 0; wordNdx < NUM_WORDS; wordNdx++)
1765*35238bceSAndroid Build Coastguard Worker             m_words[wordNdx] = 0;
1766*35238bceSAndroid Build Coastguard Worker     }
1767*35238bceSAndroid Build Coastguard Worker 
setBit(int ndx,uint32_t val)1768*35238bceSAndroid Build Coastguard Worker     void setBit(int ndx, uint32_t val)
1769*35238bceSAndroid Build Coastguard Worker     {
1770*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(ndx, 0, 128));
1771*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((val & 1) == val);
1772*35238bceSAndroid Build Coastguard Worker         const int wordNdx = ndx / WORD_BITS;
1773*35238bceSAndroid Build Coastguard Worker         const int bitNdx  = ndx % WORD_BITS;
1774*35238bceSAndroid Build Coastguard Worker         m_words[wordNdx]  = (m_words[wordNdx] & ~((Word)1 << bitNdx)) | ((Word)val << bitNdx);
1775*35238bceSAndroid Build Coastguard Worker     }
1776*35238bceSAndroid Build Coastguard Worker 
setBits(int low,int high,uint32_t bits)1777*35238bceSAndroid Build Coastguard Worker     void setBits(int low, int high, uint32_t bits)
1778*35238bceSAndroid Build Coastguard Worker     {
1779*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(low, 0, 128));
1780*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inBounds(high, 0, 128));
1781*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(de::inRange(high - low + 1, 0, 32));
1782*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((bits & (((Word)1 << (high - low + 1)) - 1)) == bits);
1783*35238bceSAndroid Build Coastguard Worker 
1784*35238bceSAndroid Build Coastguard Worker         if (high - low + 1 == 0)
1785*35238bceSAndroid Build Coastguard Worker             return;
1786*35238bceSAndroid Build Coastguard Worker 
1787*35238bceSAndroid Build Coastguard Worker         const int word0Ndx   = low / WORD_BITS;
1788*35238bceSAndroid Build Coastguard Worker         const int word1Ndx   = high / WORD_BITS;
1789*35238bceSAndroid Build Coastguard Worker         const int lowNdxInW0 = low % WORD_BITS;
1790*35238bceSAndroid Build Coastguard Worker 
1791*35238bceSAndroid Build Coastguard Worker         if (word0Ndx == word1Ndx)
1792*35238bceSAndroid Build Coastguard Worker             m_words[word0Ndx] =
1793*35238bceSAndroid Build Coastguard Worker                 (m_words[word0Ndx] & ~((((Word)1 << (high - low + 1)) - 1) << lowNdxInW0)) | ((Word)bits << lowNdxInW0);
1794*35238bceSAndroid Build Coastguard Worker         else
1795*35238bceSAndroid Build Coastguard Worker         {
1796*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(word1Ndx == word0Ndx + 1);
1797*35238bceSAndroid Build Coastguard Worker 
1798*35238bceSAndroid Build Coastguard Worker             const int highNdxInW1      = high % WORD_BITS;
1799*35238bceSAndroid Build Coastguard Worker             const int numBitsToSetInW0 = WORD_BITS - lowNdxInW0;
1800*35238bceSAndroid Build Coastguard Worker             const Word bitsLowMask     = ((Word)1 << numBitsToSetInW0) - 1;
1801*35238bceSAndroid Build Coastguard Worker 
1802*35238bceSAndroid Build Coastguard Worker             m_words[word0Ndx] =
1803*35238bceSAndroid Build Coastguard Worker                 (m_words[word0Ndx] & (((Word)1 << lowNdxInW0) - 1)) | (((Word)bits & bitsLowMask) << lowNdxInW0);
1804*35238bceSAndroid Build Coastguard Worker             m_words[word1Ndx] = (m_words[word1Ndx] & ~(((Word)1 << (highNdxInW1 + 1)) - 1)) |
1805*35238bceSAndroid Build Coastguard Worker                                 (((Word)bits & ~bitsLowMask) >> numBitsToSetInW0);
1806*35238bceSAndroid Build Coastguard Worker         }
1807*35238bceSAndroid Build Coastguard Worker     }
1808*35238bceSAndroid Build Coastguard Worker 
assignToMemory(uint8_t * dst) const1809*35238bceSAndroid Build Coastguard Worker     void assignToMemory(uint8_t *dst) const
1810*35238bceSAndroid Build Coastguard Worker     {
1811*35238bceSAndroid Build Coastguard Worker         for (int wordNdx = 0; wordNdx < NUM_WORDS; wordNdx++)
1812*35238bceSAndroid Build Coastguard Worker         {
1813*35238bceSAndroid Build Coastguard Worker             for (int byteNdx = 0; byteNdx < WORD_BYTES; byteNdx++)
1814*35238bceSAndroid Build Coastguard Worker                 dst[wordNdx * WORD_BYTES + byteNdx] = (uint8_t)((m_words[wordNdx] >> (8 * byteNdx)) & 0xff);
1815*35238bceSAndroid Build Coastguard Worker         }
1816*35238bceSAndroid Build Coastguard Worker     }
1817*35238bceSAndroid Build Coastguard Worker 
pushBytesToVector(vector<uint8_t> & dst) const1818*35238bceSAndroid Build Coastguard Worker     void pushBytesToVector(vector<uint8_t> &dst) const
1819*35238bceSAndroid Build Coastguard Worker     {
1820*35238bceSAndroid Build Coastguard Worker         const int assignStartIndex = (int)dst.size();
1821*35238bceSAndroid Build Coastguard Worker         dst.resize(dst.size() + BLOCK_SIZE_BYTES);
1822*35238bceSAndroid Build Coastguard Worker         assignToMemory(&dst[assignStartIndex]);
1823*35238bceSAndroid Build Coastguard Worker     }
1824*35238bceSAndroid Build Coastguard Worker 
1825*35238bceSAndroid Build Coastguard Worker private:
1826*35238bceSAndroid Build Coastguard Worker     Word m_words[NUM_WORDS];
1827*35238bceSAndroid Build Coastguard Worker };
1828*35238bceSAndroid Build Coastguard Worker 
1829*35238bceSAndroid Build Coastguard Worker // A helper for sequential access into a AssignBlock128.
1830*35238bceSAndroid Build Coastguard Worker class BitAssignAccessStream
1831*35238bceSAndroid Build Coastguard Worker {
1832*35238bceSAndroid Build Coastguard Worker public:
BitAssignAccessStream(AssignBlock128 & dst,int startNdxInSrc,int length,bool forward)1833*35238bceSAndroid Build Coastguard Worker     BitAssignAccessStream(AssignBlock128 &dst, int startNdxInSrc, int length, bool forward)
1834*35238bceSAndroid Build Coastguard Worker         : m_dst(dst)
1835*35238bceSAndroid Build Coastguard Worker         , m_startNdxInSrc(startNdxInSrc)
1836*35238bceSAndroid Build Coastguard Worker         , m_length(length)
1837*35238bceSAndroid Build Coastguard Worker         , m_forward(forward)
1838*35238bceSAndroid Build Coastguard Worker         , m_ndx(0)
1839*35238bceSAndroid Build Coastguard Worker     {
1840*35238bceSAndroid Build Coastguard Worker     }
1841*35238bceSAndroid Build Coastguard Worker 
1842*35238bceSAndroid Build Coastguard Worker     // Set the next num bits. Bits at positions greater than or equal to m_length are not touched.
setNext(int num,uint32_t bits)1843*35238bceSAndroid Build Coastguard Worker     void setNext(int num, uint32_t bits)
1844*35238bceSAndroid Build Coastguard Worker     {
1845*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((bits & (((uint64_t)1 << num) - 1)) == bits);
1846*35238bceSAndroid Build Coastguard Worker 
1847*35238bceSAndroid Build Coastguard Worker         if (num == 0 || m_ndx >= m_length)
1848*35238bceSAndroid Build Coastguard Worker             return;
1849*35238bceSAndroid Build Coastguard Worker 
1850*35238bceSAndroid Build Coastguard Worker         const int end             = m_ndx + num;
1851*35238bceSAndroid Build Coastguard Worker         const int numBitsToDst    = de::max(0, de::min(m_length, end) - m_ndx);
1852*35238bceSAndroid Build Coastguard Worker         const int low             = m_ndx;
1853*35238bceSAndroid Build Coastguard Worker         const int high            = m_ndx + numBitsToDst - 1;
1854*35238bceSAndroid Build Coastguard Worker         const uint32_t actualBits = getBits(bits, 0, numBitsToDst - 1);
1855*35238bceSAndroid Build Coastguard Worker 
1856*35238bceSAndroid Build Coastguard Worker         m_ndx += num;
1857*35238bceSAndroid Build Coastguard Worker 
1858*35238bceSAndroid Build Coastguard Worker         return m_forward ?
1859*35238bceSAndroid Build Coastguard Worker                    m_dst.setBits(m_startNdxInSrc + low, m_startNdxInSrc + high, actualBits) :
1860*35238bceSAndroid Build Coastguard Worker                    m_dst.setBits(m_startNdxInSrc - high, m_startNdxInSrc - low, reverseBits(actualBits, numBitsToDst));
1861*35238bceSAndroid Build Coastguard Worker     }
1862*35238bceSAndroid Build Coastguard Worker 
1863*35238bceSAndroid Build Coastguard Worker private:
1864*35238bceSAndroid Build Coastguard Worker     AssignBlock128 &m_dst;
1865*35238bceSAndroid Build Coastguard Worker     const int m_startNdxInSrc;
1866*35238bceSAndroid Build Coastguard Worker     const int m_length;
1867*35238bceSAndroid Build Coastguard Worker     const bool m_forward;
1868*35238bceSAndroid Build Coastguard Worker 
1869*35238bceSAndroid Build Coastguard Worker     int m_ndx;
1870*35238bceSAndroid Build Coastguard Worker };
1871*35238bceSAndroid Build Coastguard Worker 
1872*35238bceSAndroid Build Coastguard Worker struct VoidExtentParams
1873*35238bceSAndroid Build Coastguard Worker {
1874*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT((de::meta::TypesSame<deFloat16, uint16_t>::Value));
1875*35238bceSAndroid Build Coastguard Worker     bool isHDR;
1876*35238bceSAndroid Build Coastguard Worker     uint16_t r;
1877*35238bceSAndroid Build Coastguard Worker     uint16_t g;
1878*35238bceSAndroid Build Coastguard Worker     uint16_t b;
1879*35238bceSAndroid Build Coastguard Worker     uint16_t a;
1880*35238bceSAndroid Build Coastguard Worker     // \note Currently extent coordinates are all set to all-ones.
1881*35238bceSAndroid Build Coastguard Worker 
VoidExtentParamstcu::astc::__anone0fc7f7b0111::VoidExtentParams1882*35238bceSAndroid Build Coastguard Worker     VoidExtentParams(bool isHDR_, uint16_t r_, uint16_t g_, uint16_t b_, uint16_t a_)
1883*35238bceSAndroid Build Coastguard Worker         : isHDR(isHDR_)
1884*35238bceSAndroid Build Coastguard Worker         , r(r_)
1885*35238bceSAndroid Build Coastguard Worker         , g(g_)
1886*35238bceSAndroid Build Coastguard Worker         , b(b_)
1887*35238bceSAndroid Build Coastguard Worker         , a(a_)
1888*35238bceSAndroid Build Coastguard Worker     {
1889*35238bceSAndroid Build Coastguard Worker     }
1890*35238bceSAndroid Build Coastguard Worker };
1891*35238bceSAndroid Build Coastguard Worker 
generateVoidExtentBlock(const VoidExtentParams & params)1892*35238bceSAndroid Build Coastguard Worker static AssignBlock128 generateVoidExtentBlock(const VoidExtentParams &params)
1893*35238bceSAndroid Build Coastguard Worker {
1894*35238bceSAndroid Build Coastguard Worker     AssignBlock128 block;
1895*35238bceSAndroid Build Coastguard Worker 
1896*35238bceSAndroid Build Coastguard Worker     block.setBits(0, 8, 0x1fc); // \note Marks void-extent block.
1897*35238bceSAndroid Build Coastguard Worker     block.setBit(9, params.isHDR);
1898*35238bceSAndroid Build Coastguard Worker     block.setBits(10, 11, 3); // \note Spec shows that these bits are both set, although they serve no purpose.
1899*35238bceSAndroid Build Coastguard Worker 
1900*35238bceSAndroid Build Coastguard Worker     // Extent coordinates - currently all-ones.
1901*35238bceSAndroid Build Coastguard Worker     block.setBits(12, 24, 0x1fff);
1902*35238bceSAndroid Build Coastguard Worker     block.setBits(25, 37, 0x1fff);
1903*35238bceSAndroid Build Coastguard Worker     block.setBits(38, 50, 0x1fff);
1904*35238bceSAndroid Build Coastguard Worker     block.setBits(51, 63, 0x1fff);
1905*35238bceSAndroid Build Coastguard Worker 
1906*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!params.isHDR || (!isFloat16InfOrNan(params.r) && !isFloat16InfOrNan(params.g) &&
1907*35238bceSAndroid Build Coastguard Worker                                 !isFloat16InfOrNan(params.b) && !isFloat16InfOrNan(params.a)));
1908*35238bceSAndroid Build Coastguard Worker 
1909*35238bceSAndroid Build Coastguard Worker     block.setBits(64, 79, params.r);
1910*35238bceSAndroid Build Coastguard Worker     block.setBits(80, 95, params.g);
1911*35238bceSAndroid Build Coastguard Worker     block.setBits(96, 111, params.b);
1912*35238bceSAndroid Build Coastguard Worker     block.setBits(112, 127, params.a);
1913*35238bceSAndroid Build Coastguard Worker 
1914*35238bceSAndroid Build Coastguard Worker     return block;
1915*35238bceSAndroid Build Coastguard Worker }
1916*35238bceSAndroid Build Coastguard Worker 
1917*35238bceSAndroid Build Coastguard Worker // An input array of ISE inputs for an entire ASTC block. Can be given as either single values in the
1918*35238bceSAndroid Build Coastguard Worker // range [0, maximumValueOfISERange] or as explicit block value specifications. The latter is needed
1919*35238bceSAndroid Build Coastguard Worker // so we can test all possible values of T and Q in a block, since multiple T or Q values may map
1920*35238bceSAndroid Build Coastguard Worker // to the same set of decoded values.
1921*35238bceSAndroid Build Coastguard Worker struct ISEInput
1922*35238bceSAndroid Build Coastguard Worker {
1923*35238bceSAndroid Build Coastguard Worker     struct Block
1924*35238bceSAndroid Build Coastguard Worker     {
1925*35238bceSAndroid Build Coastguard Worker         uint32_t tOrQValue; //!< The 8-bit T or 7-bit Q in a trit or quint ISE block.
1926*35238bceSAndroid Build Coastguard Worker         uint32_t bitValues[5];
1927*35238bceSAndroid Build Coastguard Worker     };
1928*35238bceSAndroid Build Coastguard Worker 
1929*35238bceSAndroid Build Coastguard Worker     bool isGivenInBlockForm;
1930*35238bceSAndroid Build Coastguard Worker     union
1931*35238bceSAndroid Build Coastguard Worker     {
1932*35238bceSAndroid Build Coastguard Worker         //!< \note 64 comes from the maximum number of weight values in an ASTC block.
1933*35238bceSAndroid Build Coastguard Worker         uint32_t plain[64];
1934*35238bceSAndroid Build Coastguard Worker         Block block[64];
1935*35238bceSAndroid Build Coastguard Worker     } value;
1936*35238bceSAndroid Build Coastguard Worker 
ISEInputtcu::astc::__anone0fc7f7b0111::ISEInput1937*35238bceSAndroid Build Coastguard Worker     ISEInput(void) : isGivenInBlockForm(false)
1938*35238bceSAndroid Build Coastguard Worker     {
1939*35238bceSAndroid Build Coastguard Worker     }
1940*35238bceSAndroid Build Coastguard Worker };
1941*35238bceSAndroid Build Coastguard Worker 
computeISERangeMax(const ISEParams & iseParams)1942*35238bceSAndroid Build Coastguard Worker static inline uint32_t computeISERangeMax(const ISEParams &iseParams)
1943*35238bceSAndroid Build Coastguard Worker {
1944*35238bceSAndroid Build Coastguard Worker     switch (iseParams.mode)
1945*35238bceSAndroid Build Coastguard Worker     {
1946*35238bceSAndroid Build Coastguard Worker     case ISEMODE_TRIT:
1947*35238bceSAndroid Build Coastguard Worker         return (1u << iseParams.numBits) * 3 - 1;
1948*35238bceSAndroid Build Coastguard Worker     case ISEMODE_QUINT:
1949*35238bceSAndroid Build Coastguard Worker         return (1u << iseParams.numBits) * 5 - 1;
1950*35238bceSAndroid Build Coastguard Worker     case ISEMODE_PLAIN_BIT:
1951*35238bceSAndroid Build Coastguard Worker         return (1u << iseParams.numBits) - 1;
1952*35238bceSAndroid Build Coastguard Worker     default:
1953*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1954*35238bceSAndroid Build Coastguard Worker         return -1;
1955*35238bceSAndroid Build Coastguard Worker     }
1956*35238bceSAndroid Build Coastguard Worker }
1957*35238bceSAndroid Build Coastguard Worker 
1958*35238bceSAndroid Build Coastguard Worker struct NormalBlockParams
1959*35238bceSAndroid Build Coastguard Worker {
1960*35238bceSAndroid Build Coastguard Worker     int weightGridWidth;
1961*35238bceSAndroid Build Coastguard Worker     int weightGridHeight;
1962*35238bceSAndroid Build Coastguard Worker     ISEParams weightISEParams;
1963*35238bceSAndroid Build Coastguard Worker     bool isDualPlane;
1964*35238bceSAndroid Build Coastguard Worker     uint32_t ccs; //! \note Irrelevant if !isDualPlane.
1965*35238bceSAndroid Build Coastguard Worker     int numPartitions;
1966*35238bceSAndroid Build Coastguard Worker     uint32_t colorEndpointModes[4];
1967*35238bceSAndroid Build Coastguard Worker     // \note Below members are irrelevant if numPartitions == 1.
1968*35238bceSAndroid Build Coastguard Worker     bool isMultiPartSingleCemMode; //! \note If true, the single CEM is at colorEndpointModes[0].
1969*35238bceSAndroid Build Coastguard Worker     uint32_t partitionSeed;
1970*35238bceSAndroid Build Coastguard Worker 
NormalBlockParamstcu::astc::__anone0fc7f7b0111::NormalBlockParams1971*35238bceSAndroid Build Coastguard Worker     NormalBlockParams(void)
1972*35238bceSAndroid Build Coastguard Worker         : weightGridWidth(-1)
1973*35238bceSAndroid Build Coastguard Worker         , weightGridHeight(-1)
1974*35238bceSAndroid Build Coastguard Worker         , weightISEParams(ISEMODE_LAST, -1)
1975*35238bceSAndroid Build Coastguard Worker         , isDualPlane(true)
1976*35238bceSAndroid Build Coastguard Worker         , ccs((uint32_t)-1)
1977*35238bceSAndroid Build Coastguard Worker         , numPartitions(-1)
1978*35238bceSAndroid Build Coastguard Worker         , isMultiPartSingleCemMode(false)
1979*35238bceSAndroid Build Coastguard Worker         , partitionSeed((uint32_t)-1)
1980*35238bceSAndroid Build Coastguard Worker     {
1981*35238bceSAndroid Build Coastguard Worker         colorEndpointModes[0] = 0;
1982*35238bceSAndroid Build Coastguard Worker         colorEndpointModes[1] = 0;
1983*35238bceSAndroid Build Coastguard Worker         colorEndpointModes[2] = 0;
1984*35238bceSAndroid Build Coastguard Worker         colorEndpointModes[3] = 0;
1985*35238bceSAndroid Build Coastguard Worker     }
1986*35238bceSAndroid Build Coastguard Worker };
1987*35238bceSAndroid Build Coastguard Worker 
1988*35238bceSAndroid Build Coastguard Worker struct NormalBlockISEInputs
1989*35238bceSAndroid Build Coastguard Worker {
1990*35238bceSAndroid Build Coastguard Worker     ISEInput weight;
1991*35238bceSAndroid Build Coastguard Worker     ISEInput endpoint;
1992*35238bceSAndroid Build Coastguard Worker 
NormalBlockISEInputstcu::astc::__anone0fc7f7b0111::NormalBlockISEInputs1993*35238bceSAndroid Build Coastguard Worker     NormalBlockISEInputs(void) : weight(), endpoint()
1994*35238bceSAndroid Build Coastguard Worker     {
1995*35238bceSAndroid Build Coastguard Worker     }
1996*35238bceSAndroid Build Coastguard Worker };
1997*35238bceSAndroid Build Coastguard Worker 
computeNumWeights(const NormalBlockParams & params)1998*35238bceSAndroid Build Coastguard Worker static inline int computeNumWeights(const NormalBlockParams &params)
1999*35238bceSAndroid Build Coastguard Worker {
2000*35238bceSAndroid Build Coastguard Worker     return params.weightGridWidth * params.weightGridHeight * (params.isDualPlane ? 2 : 1);
2001*35238bceSAndroid Build Coastguard Worker }
2002*35238bceSAndroid Build Coastguard Worker 
computeNumBitsForColorEndpoints(const NormalBlockParams & params)2003*35238bceSAndroid Build Coastguard Worker static inline int computeNumBitsForColorEndpoints(const NormalBlockParams &params)
2004*35238bceSAndroid Build Coastguard Worker {
2005*35238bceSAndroid Build Coastguard Worker     const int numWeightBits     = computeNumRequiredBits(params.weightISEParams, computeNumWeights(params));
2006*35238bceSAndroid Build Coastguard Worker     const int numConfigDataBits = (params.numPartitions == 1       ? 17 :
2007*35238bceSAndroid Build Coastguard Worker                                    params.isMultiPartSingleCemMode ? 29 :
2008*35238bceSAndroid Build Coastguard Worker                                                                      25 + 3 * params.numPartitions) +
2009*35238bceSAndroid Build Coastguard Worker                                   (params.isDualPlane ? 2 : 0);
2010*35238bceSAndroid Build Coastguard Worker 
2011*35238bceSAndroid Build Coastguard Worker     return 128 - numWeightBits - numConfigDataBits;
2012*35238bceSAndroid Build Coastguard Worker }
2013*35238bceSAndroid Build Coastguard Worker 
computeNumColorEndpointValues(const uint32_t * endpointModes,int numPartitions,bool isMultiPartSingleCemMode)2014*35238bceSAndroid Build Coastguard Worker static inline int computeNumColorEndpointValues(const uint32_t *endpointModes, int numPartitions,
2015*35238bceSAndroid Build Coastguard Worker                                                 bool isMultiPartSingleCemMode)
2016*35238bceSAndroid Build Coastguard Worker {
2017*35238bceSAndroid Build Coastguard Worker     if (isMultiPartSingleCemMode)
2018*35238bceSAndroid Build Coastguard Worker         return numPartitions * computeNumColorEndpointValues(endpointModes[0]);
2019*35238bceSAndroid Build Coastguard Worker     else
2020*35238bceSAndroid Build Coastguard Worker     {
2021*35238bceSAndroid Build Coastguard Worker         int result = 0;
2022*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < numPartitions; i++)
2023*35238bceSAndroid Build Coastguard Worker             result += computeNumColorEndpointValues(endpointModes[i]);
2024*35238bceSAndroid Build Coastguard Worker         return result;
2025*35238bceSAndroid Build Coastguard Worker     }
2026*35238bceSAndroid Build Coastguard Worker }
2027*35238bceSAndroid Build Coastguard Worker 
isValidBlockParams(const NormalBlockParams & params,int blockWidth,int blockHeight)2028*35238bceSAndroid Build Coastguard Worker static inline bool isValidBlockParams(const NormalBlockParams &params, int blockWidth, int blockHeight)
2029*35238bceSAndroid Build Coastguard Worker {
2030*35238bceSAndroid Build Coastguard Worker     const int numWeights             = computeNumWeights(params);
2031*35238bceSAndroid Build Coastguard Worker     const int numWeightBits          = computeNumRequiredBits(params.weightISEParams, numWeights);
2032*35238bceSAndroid Build Coastguard Worker     const int numColorEndpointValues = computeNumColorEndpointValues(
2033*35238bceSAndroid Build Coastguard Worker         &params.colorEndpointModes[0], params.numPartitions, params.isMultiPartSingleCemMode);
2034*35238bceSAndroid Build Coastguard Worker     const int numBitsForColorEndpoints = computeNumBitsForColorEndpoints(params);
2035*35238bceSAndroid Build Coastguard Worker 
2036*35238bceSAndroid Build Coastguard Worker     return numWeights <= 64 && de::inRange(numWeightBits, 24, 96) && params.weightGridWidth <= blockWidth &&
2037*35238bceSAndroid Build Coastguard Worker            params.weightGridHeight <= blockHeight && !(params.numPartitions == 4 && params.isDualPlane) &&
2038*35238bceSAndroid Build Coastguard Worker            numColorEndpointValues <= 18 && numBitsForColorEndpoints >= deDivRoundUp32(13 * numColorEndpointValues, 5);
2039*35238bceSAndroid Build Coastguard Worker }
2040*35238bceSAndroid Build Coastguard Worker 
2041*35238bceSAndroid Build Coastguard Worker // Write bits 0 to 10 of an ASTC block.
writeBlockMode(AssignBlock128 & dst,const NormalBlockParams & blockParams)2042*35238bceSAndroid Build Coastguard Worker static void writeBlockMode(AssignBlock128 &dst, const NormalBlockParams &blockParams)
2043*35238bceSAndroid Build Coastguard Worker {
2044*35238bceSAndroid Build Coastguard Worker     const uint32_t d = blockParams.isDualPlane != 0;
2045*35238bceSAndroid Build Coastguard Worker     // r and h initialized in switch below.
2046*35238bceSAndroid Build Coastguard Worker     uint32_t r;
2047*35238bceSAndroid Build Coastguard Worker     uint32_t h;
2048*35238bceSAndroid Build Coastguard Worker     // a, b and blockModeLayoutNdx initialized in block mode layout index detecting loop below.
2049*35238bceSAndroid Build Coastguard Worker     uint32_t a = (uint32_t)-1;
2050*35238bceSAndroid Build Coastguard Worker     uint32_t b = (uint32_t)-1;
2051*35238bceSAndroid Build Coastguard Worker     int blockModeLayoutNdx;
2052*35238bceSAndroid Build Coastguard Worker 
2053*35238bceSAndroid Build Coastguard Worker     // Find the values of r and h (ISE range).
2054*35238bceSAndroid Build Coastguard Worker     switch (computeISERangeMax(blockParams.weightISEParams))
2055*35238bceSAndroid Build Coastguard Worker     {
2056*35238bceSAndroid Build Coastguard Worker     case 1:
2057*35238bceSAndroid Build Coastguard Worker         r = 2;
2058*35238bceSAndroid Build Coastguard Worker         h = 0;
2059*35238bceSAndroid Build Coastguard Worker         break;
2060*35238bceSAndroid Build Coastguard Worker     case 2:
2061*35238bceSAndroid Build Coastguard Worker         r = 3;
2062*35238bceSAndroid Build Coastguard Worker         h = 0;
2063*35238bceSAndroid Build Coastguard Worker         break;
2064*35238bceSAndroid Build Coastguard Worker     case 3:
2065*35238bceSAndroid Build Coastguard Worker         r = 4;
2066*35238bceSAndroid Build Coastguard Worker         h = 0;
2067*35238bceSAndroid Build Coastguard Worker         break;
2068*35238bceSAndroid Build Coastguard Worker     case 4:
2069*35238bceSAndroid Build Coastguard Worker         r = 5;
2070*35238bceSAndroid Build Coastguard Worker         h = 0;
2071*35238bceSAndroid Build Coastguard Worker         break;
2072*35238bceSAndroid Build Coastguard Worker     case 5:
2073*35238bceSAndroid Build Coastguard Worker         r = 6;
2074*35238bceSAndroid Build Coastguard Worker         h = 0;
2075*35238bceSAndroid Build Coastguard Worker         break;
2076*35238bceSAndroid Build Coastguard Worker     case 7:
2077*35238bceSAndroid Build Coastguard Worker         r = 7;
2078*35238bceSAndroid Build Coastguard Worker         h = 0;
2079*35238bceSAndroid Build Coastguard Worker         break;
2080*35238bceSAndroid Build Coastguard Worker 
2081*35238bceSAndroid Build Coastguard Worker     case 9:
2082*35238bceSAndroid Build Coastguard Worker         r = 2;
2083*35238bceSAndroid Build Coastguard Worker         h = 1;
2084*35238bceSAndroid Build Coastguard Worker         break;
2085*35238bceSAndroid Build Coastguard Worker     case 11:
2086*35238bceSAndroid Build Coastguard Worker         r = 3;
2087*35238bceSAndroid Build Coastguard Worker         h = 1;
2088*35238bceSAndroid Build Coastguard Worker         break;
2089*35238bceSAndroid Build Coastguard Worker     case 15:
2090*35238bceSAndroid Build Coastguard Worker         r = 4;
2091*35238bceSAndroid Build Coastguard Worker         h = 1;
2092*35238bceSAndroid Build Coastguard Worker         break;
2093*35238bceSAndroid Build Coastguard Worker     case 19:
2094*35238bceSAndroid Build Coastguard Worker         r = 5;
2095*35238bceSAndroid Build Coastguard Worker         h = 1;
2096*35238bceSAndroid Build Coastguard Worker         break;
2097*35238bceSAndroid Build Coastguard Worker     case 23:
2098*35238bceSAndroid Build Coastguard Worker         r = 6;
2099*35238bceSAndroid Build Coastguard Worker         h = 1;
2100*35238bceSAndroid Build Coastguard Worker         break;
2101*35238bceSAndroid Build Coastguard Worker     case 31:
2102*35238bceSAndroid Build Coastguard Worker         r = 7;
2103*35238bceSAndroid Build Coastguard Worker         h = 1;
2104*35238bceSAndroid Build Coastguard Worker         break;
2105*35238bceSAndroid Build Coastguard Worker 
2106*35238bceSAndroid Build Coastguard Worker     default:
2107*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2108*35238bceSAndroid Build Coastguard Worker         r = (uint32_t)-1;
2109*35238bceSAndroid Build Coastguard Worker         h = (uint32_t)-1;
2110*35238bceSAndroid Build Coastguard Worker     }
2111*35238bceSAndroid Build Coastguard Worker 
2112*35238bceSAndroid Build Coastguard Worker     // Find block mode layout index, i.e. appropriate row in the "2d block mode layout" table in ASTC spec.
2113*35238bceSAndroid Build Coastguard Worker 
2114*35238bceSAndroid Build Coastguard Worker     {
2115*35238bceSAndroid Build Coastguard Worker         enum BlockModeLayoutABVariable
2116*35238bceSAndroid Build Coastguard Worker         {
2117*35238bceSAndroid Build Coastguard Worker             Z = 0,
2118*35238bceSAndroid Build Coastguard Worker             A = 1,
2119*35238bceSAndroid Build Coastguard Worker             B = 2
2120*35238bceSAndroid Build Coastguard Worker         };
2121*35238bceSAndroid Build Coastguard Worker 
2122*35238bceSAndroid Build Coastguard Worker         static const struct BlockModeLayout
2123*35238bceSAndroid Build Coastguard Worker         {
2124*35238bceSAndroid Build Coastguard Worker             int aNumBits;
2125*35238bceSAndroid Build Coastguard Worker             int bNumBits;
2126*35238bceSAndroid Build Coastguard Worker             BlockModeLayoutABVariable gridWidthVariableTerm;
2127*35238bceSAndroid Build Coastguard Worker             int gridWidthConstantTerm;
2128*35238bceSAndroid Build Coastguard Worker             BlockModeLayoutABVariable gridHeightVariableTerm;
2129*35238bceSAndroid Build Coastguard Worker             int gridHeightConstantTerm;
2130*35238bceSAndroid Build Coastguard Worker         } blockModeLayouts[] = {{2, 2, B, 4, A, 2},  {2, 2, B, 8, A, 2},  {2, 2, A, 2, B, 8},  {2, 1, A, 2, B, 6},
2131*35238bceSAndroid Build Coastguard Worker                                 {2, 1, B, 2, A, 2},  {2, 0, Z, 12, A, 2}, {2, 0, A, 2, Z, 12}, {0, 0, Z, 6, Z, 10},
2132*35238bceSAndroid Build Coastguard Worker                                 {0, 0, Z, 10, Z, 6}, {2, 2, A, 6, B, 6}};
2133*35238bceSAndroid Build Coastguard Worker 
2134*35238bceSAndroid Build Coastguard Worker         for (blockModeLayoutNdx = 0; blockModeLayoutNdx < DE_LENGTH_OF_ARRAY(blockModeLayouts); blockModeLayoutNdx++)
2135*35238bceSAndroid Build Coastguard Worker         {
2136*35238bceSAndroid Build Coastguard Worker             const BlockModeLayout &layout   = blockModeLayouts[blockModeLayoutNdx];
2137*35238bceSAndroid Build Coastguard Worker             const int aMax                  = (1 << layout.aNumBits) - 1;
2138*35238bceSAndroid Build Coastguard Worker             const int bMax                  = (1 << layout.bNumBits) - 1;
2139*35238bceSAndroid Build Coastguard Worker             const int variableOffsetsMax[3] = {0, aMax, bMax};
2140*35238bceSAndroid Build Coastguard Worker             const int widthMin              = layout.gridWidthConstantTerm;
2141*35238bceSAndroid Build Coastguard Worker             const int heightMin             = layout.gridHeightConstantTerm;
2142*35238bceSAndroid Build Coastguard Worker             const int widthMax              = widthMin + variableOffsetsMax[layout.gridWidthVariableTerm];
2143*35238bceSAndroid Build Coastguard Worker             const int heightMax             = heightMin + variableOffsetsMax[layout.gridHeightVariableTerm];
2144*35238bceSAndroid Build Coastguard Worker 
2145*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(layout.gridWidthVariableTerm != layout.gridHeightVariableTerm ||
2146*35238bceSAndroid Build Coastguard Worker                       layout.gridWidthVariableTerm == Z);
2147*35238bceSAndroid Build Coastguard Worker 
2148*35238bceSAndroid Build Coastguard Worker             if (de::inRange(blockParams.weightGridWidth, widthMin, widthMax) &&
2149*35238bceSAndroid Build Coastguard Worker                 de::inRange(blockParams.weightGridHeight, heightMin, heightMax))
2150*35238bceSAndroid Build Coastguard Worker             {
2151*35238bceSAndroid Build Coastguard Worker                 uint32_t defaultvalue    = 0;
2152*35238bceSAndroid Build Coastguard Worker                 uint32_t &widthVariable  = layout.gridWidthVariableTerm == A ? a :
2153*35238bceSAndroid Build Coastguard Worker                                            layout.gridWidthVariableTerm == B ? b :
2154*35238bceSAndroid Build Coastguard Worker                                                                                defaultvalue;
2155*35238bceSAndroid Build Coastguard Worker                 uint32_t &heightVariable = layout.gridHeightVariableTerm == A ? a :
2156*35238bceSAndroid Build Coastguard Worker                                            layout.gridHeightVariableTerm == B ? b :
2157*35238bceSAndroid Build Coastguard Worker                                                                                 defaultvalue;
2158*35238bceSAndroid Build Coastguard Worker 
2159*35238bceSAndroid Build Coastguard Worker                 widthVariable  = blockParams.weightGridWidth - layout.gridWidthConstantTerm;
2160*35238bceSAndroid Build Coastguard Worker                 heightVariable = blockParams.weightGridHeight - layout.gridHeightConstantTerm;
2161*35238bceSAndroid Build Coastguard Worker 
2162*35238bceSAndroid Build Coastguard Worker                 break;
2163*35238bceSAndroid Build Coastguard Worker             }
2164*35238bceSAndroid Build Coastguard Worker         }
2165*35238bceSAndroid Build Coastguard Worker     }
2166*35238bceSAndroid Build Coastguard Worker 
2167*35238bceSAndroid Build Coastguard Worker     // Set block mode bits.
2168*35238bceSAndroid Build Coastguard Worker 
2169*35238bceSAndroid Build Coastguard Worker     const uint32_t a0 = getBit(a, 0);
2170*35238bceSAndroid Build Coastguard Worker     const uint32_t a1 = getBit(a, 1);
2171*35238bceSAndroid Build Coastguard Worker     const uint32_t b0 = getBit(b, 0);
2172*35238bceSAndroid Build Coastguard Worker     const uint32_t b1 = getBit(b, 1);
2173*35238bceSAndroid Build Coastguard Worker     const uint32_t r0 = getBit(r, 0);
2174*35238bceSAndroid Build Coastguard Worker     const uint32_t r1 = getBit(r, 1);
2175*35238bceSAndroid Build Coastguard Worker     const uint32_t r2 = getBit(r, 2);
2176*35238bceSAndroid Build Coastguard Worker 
2177*35238bceSAndroid Build Coastguard Worker #define SB(NDX, VAL) dst.setBit((NDX), (VAL))
2178*35238bceSAndroid Build Coastguard Worker #define ASSIGN_BITS(B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, B0) \
2179*35238bceSAndroid Build Coastguard Worker     do                                                           \
2180*35238bceSAndroid Build Coastguard Worker     {                                                            \
2181*35238bceSAndroid Build Coastguard Worker         SB(10, (B10));                                           \
2182*35238bceSAndroid Build Coastguard Worker         SB(9, (B9));                                             \
2183*35238bceSAndroid Build Coastguard Worker         SB(8, (B8));                                             \
2184*35238bceSAndroid Build Coastguard Worker         SB(7, (B7));                                             \
2185*35238bceSAndroid Build Coastguard Worker         SB(6, (B6));                                             \
2186*35238bceSAndroid Build Coastguard Worker         SB(5, (B5));                                             \
2187*35238bceSAndroid Build Coastguard Worker         SB(4, (B4));                                             \
2188*35238bceSAndroid Build Coastguard Worker         SB(3, (B3));                                             \
2189*35238bceSAndroid Build Coastguard Worker         SB(2, (B2));                                             \
2190*35238bceSAndroid Build Coastguard Worker         SB(1, (B1));                                             \
2191*35238bceSAndroid Build Coastguard Worker         SB(0, (B0));                                             \
2192*35238bceSAndroid Build Coastguard Worker     } while (false)
2193*35238bceSAndroid Build Coastguard Worker 
2194*35238bceSAndroid Build Coastguard Worker     switch (blockModeLayoutNdx)
2195*35238bceSAndroid Build Coastguard Worker     {
2196*35238bceSAndroid Build Coastguard Worker     case 0:
2197*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, b1, b0, a1, a0, r0, 0, 0, r2, r1);
2198*35238bceSAndroid Build Coastguard Worker         break;
2199*35238bceSAndroid Build Coastguard Worker     case 1:
2200*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, b1, b0, a1, a0, r0, 0, 1, r2, r1);
2201*35238bceSAndroid Build Coastguard Worker         break;
2202*35238bceSAndroid Build Coastguard Worker     case 2:
2203*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, b1, b0, a1, a0, r0, 1, 0, r2, r1);
2204*35238bceSAndroid Build Coastguard Worker         break;
2205*35238bceSAndroid Build Coastguard Worker     case 3:
2206*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 0, b, a1, a0, r0, 1, 1, r2, r1);
2207*35238bceSAndroid Build Coastguard Worker         break;
2208*35238bceSAndroid Build Coastguard Worker     case 4:
2209*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 1, b, a1, a0, r0, 1, 1, r2, r1);
2210*35238bceSAndroid Build Coastguard Worker         break;
2211*35238bceSAndroid Build Coastguard Worker     case 5:
2212*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 0, 0, a1, a0, r0, r2, r1, 0, 0);
2213*35238bceSAndroid Build Coastguard Worker         break;
2214*35238bceSAndroid Build Coastguard Worker     case 6:
2215*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 0, 1, a1, a0, r0, r2, r1, 0, 0);
2216*35238bceSAndroid Build Coastguard Worker         break;
2217*35238bceSAndroid Build Coastguard Worker     case 7:
2218*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 1, 1, 0, 0, r0, r2, r1, 0, 0);
2219*35238bceSAndroid Build Coastguard Worker         break;
2220*35238bceSAndroid Build Coastguard Worker     case 8:
2221*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(d, h, 1, 1, 0, 1, r0, r2, r1, 0, 0);
2222*35238bceSAndroid Build Coastguard Worker         break;
2223*35238bceSAndroid Build Coastguard Worker     case 9:
2224*35238bceSAndroid Build Coastguard Worker         ASSIGN_BITS(b1, b0, 1, 0, a1, a0, r0, r2, r1, 0, 0);
2225*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(d == 0 && h == 0);
2226*35238bceSAndroid Build Coastguard Worker         break;
2227*35238bceSAndroid Build Coastguard Worker     default:
2228*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
2229*35238bceSAndroid Build Coastguard Worker     }
2230*35238bceSAndroid Build Coastguard Worker 
2231*35238bceSAndroid Build Coastguard Worker #undef ASSIGN_BITS
2232*35238bceSAndroid Build Coastguard Worker #undef SB
2233*35238bceSAndroid Build Coastguard Worker }
2234*35238bceSAndroid Build Coastguard Worker 
2235*35238bceSAndroid Build Coastguard Worker // Write color endpoint mode data of an ASTC block.
writeColorEndpointModes(AssignBlock128 & dst,const uint32_t * colorEndpointModes,bool isMultiPartSingleCemMode,int numPartitions,int extraCemBitsStart)2236*35238bceSAndroid Build Coastguard Worker static void writeColorEndpointModes(AssignBlock128 &dst, const uint32_t *colorEndpointModes,
2237*35238bceSAndroid Build Coastguard Worker                                     bool isMultiPartSingleCemMode, int numPartitions, int extraCemBitsStart)
2238*35238bceSAndroid Build Coastguard Worker {
2239*35238bceSAndroid Build Coastguard Worker     if (numPartitions == 1)
2240*35238bceSAndroid Build Coastguard Worker         dst.setBits(13, 16, colorEndpointModes[0]);
2241*35238bceSAndroid Build Coastguard Worker     else
2242*35238bceSAndroid Build Coastguard Worker     {
2243*35238bceSAndroid Build Coastguard Worker         if (isMultiPartSingleCemMode)
2244*35238bceSAndroid Build Coastguard Worker         {
2245*35238bceSAndroid Build Coastguard Worker             dst.setBits(23, 24, 0);
2246*35238bceSAndroid Build Coastguard Worker             dst.setBits(25, 28, colorEndpointModes[0]);
2247*35238bceSAndroid Build Coastguard Worker         }
2248*35238bceSAndroid Build Coastguard Worker         else
2249*35238bceSAndroid Build Coastguard Worker         {
2250*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(numPartitions > 0);
2251*35238bceSAndroid Build Coastguard Worker             const uint32_t minCem      = *std::min_element(&colorEndpointModes[0], &colorEndpointModes[numPartitions]);
2252*35238bceSAndroid Build Coastguard Worker             const uint32_t maxCem      = *std::max_element(&colorEndpointModes[0], &colorEndpointModes[numPartitions]);
2253*35238bceSAndroid Build Coastguard Worker             const uint32_t minCemClass = minCem / 4;
2254*35238bceSAndroid Build Coastguard Worker             const uint32_t maxCemClass = maxCem / 4;
2255*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(maxCemClass - minCemClass <= 1);
2256*35238bceSAndroid Build Coastguard Worker             DE_UNREF(minCemClass); // \note For non-debug builds.
2257*35238bceSAndroid Build Coastguard Worker             const uint32_t highLevelSelector = de::max(1u, maxCemClass);
2258*35238bceSAndroid Build Coastguard Worker 
2259*35238bceSAndroid Build Coastguard Worker             dst.setBits(23, 24, highLevelSelector);
2260*35238bceSAndroid Build Coastguard Worker 
2261*35238bceSAndroid Build Coastguard Worker             for (int partNdx = 0; partNdx < numPartitions; partNdx++)
2262*35238bceSAndroid Build Coastguard Worker             {
2263*35238bceSAndroid Build Coastguard Worker                 const uint32_t c           = colorEndpointModes[partNdx] / 4 == highLevelSelector ? 1 : 0;
2264*35238bceSAndroid Build Coastguard Worker                 const uint32_t m           = colorEndpointModes[partNdx] % 4;
2265*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowMBit0Ndx = numPartitions + 2 * partNdx;
2266*35238bceSAndroid Build Coastguard Worker                 const uint32_t lowMBit1Ndx = numPartitions + 2 * partNdx + 1;
2267*35238bceSAndroid Build Coastguard Worker                 dst.setBit(25 + partNdx, c);
2268*35238bceSAndroid Build Coastguard Worker                 dst.setBit(lowMBit0Ndx < 4 ? 25 + lowMBit0Ndx : extraCemBitsStart + lowMBit0Ndx - 4, getBit(m, 0));
2269*35238bceSAndroid Build Coastguard Worker                 dst.setBit(lowMBit1Ndx < 4 ? 25 + lowMBit1Ndx : extraCemBitsStart + lowMBit1Ndx - 4, getBit(m, 1));
2270*35238bceSAndroid Build Coastguard Worker             }
2271*35238bceSAndroid Build Coastguard Worker         }
2272*35238bceSAndroid Build Coastguard Worker     }
2273*35238bceSAndroid Build Coastguard Worker }
2274*35238bceSAndroid Build Coastguard Worker 
encodeISETritBlock(BitAssignAccessStream & dst,int numBits,bool fromExplicitInputBlock,const ISEInput::Block & blockInput,const uint32_t * nonBlockInput,int numValues)2275*35238bceSAndroid Build Coastguard Worker static void encodeISETritBlock(BitAssignAccessStream &dst, int numBits, bool fromExplicitInputBlock,
2276*35238bceSAndroid Build Coastguard Worker                                const ISEInput::Block &blockInput, const uint32_t *nonBlockInput, int numValues)
2277*35238bceSAndroid Build Coastguard Worker {
2278*35238bceSAndroid Build Coastguard Worker     // tritBlockTValue[t0][t1][t2][t3][t4] is a value of T (not necessarily the only one) that will yield the given trits when decoded.
2279*35238bceSAndroid Build Coastguard Worker     static const uint32_t tritBlockTValue[3][3][3][3][3] = {{{{{0, 128, 96}, {32, 160, 224}, {64, 192, 28}},
2280*35238bceSAndroid Build Coastguard Worker                                                               {{16, 144, 112}, {48, 176, 240}, {80, 208, 156}},
2281*35238bceSAndroid Build Coastguard Worker                                                               {{3, 131, 99}, {35, 163, 227}, {67, 195, 31}}},
2282*35238bceSAndroid Build Coastguard Worker                                                              {{{4, 132, 100}, {36, 164, 228}, {68, 196, 60}},
2283*35238bceSAndroid Build Coastguard Worker                                                               {{20, 148, 116}, {52, 180, 244}, {84, 212, 188}},
2284*35238bceSAndroid Build Coastguard Worker                                                               {{19, 147, 115}, {51, 179, 243}, {83, 211, 159}}},
2285*35238bceSAndroid Build Coastguard Worker                                                              {{{8, 136, 104}, {40, 168, 232}, {72, 200, 92}},
2286*35238bceSAndroid Build Coastguard Worker                                                               {{24, 152, 120}, {56, 184, 248}, {88, 216, 220}},
2287*35238bceSAndroid Build Coastguard Worker                                                               {{12, 140, 108}, {44, 172, 236}, {76, 204, 124}}}},
2288*35238bceSAndroid Build Coastguard Worker                                                             {{{{1, 129, 97}, {33, 161, 225}, {65, 193, 29}},
2289*35238bceSAndroid Build Coastguard Worker                                                               {{17, 145, 113}, {49, 177, 241}, {81, 209, 157}},
2290*35238bceSAndroid Build Coastguard Worker                                                               {{7, 135, 103}, {39, 167, 231}, {71, 199, 63}}},
2291*35238bceSAndroid Build Coastguard Worker                                                              {{{5, 133, 101}, {37, 165, 229}, {69, 197, 61}},
2292*35238bceSAndroid Build Coastguard Worker                                                               {{21, 149, 117}, {53, 181, 245}, {85, 213, 189}},
2293*35238bceSAndroid Build Coastguard Worker                                                               {{23, 151, 119}, {55, 183, 247}, {87, 215, 191}}},
2294*35238bceSAndroid Build Coastguard Worker                                                              {{{9, 137, 105}, {41, 169, 233}, {73, 201, 93}},
2295*35238bceSAndroid Build Coastguard Worker                                                               {{25, 153, 121}, {57, 185, 249}, {89, 217, 221}},
2296*35238bceSAndroid Build Coastguard Worker                                                               {{13, 141, 109}, {45, 173, 237}, {77, 205, 125}}}},
2297*35238bceSAndroid Build Coastguard Worker                                                             {{{{2, 130, 98}, {34, 162, 226}, {66, 194, 30}},
2298*35238bceSAndroid Build Coastguard Worker                                                               {{18, 146, 114}, {50, 178, 242}, {82, 210, 158}},
2299*35238bceSAndroid Build Coastguard Worker                                                               {{11, 139, 107}, {43, 171, 235}, {75, 203, 95}}},
2300*35238bceSAndroid Build Coastguard Worker                                                              {{{6, 134, 102}, {38, 166, 230}, {70, 198, 62}},
2301*35238bceSAndroid Build Coastguard Worker                                                               {{22, 150, 118}, {54, 182, 246}, {86, 214, 190}},
2302*35238bceSAndroid Build Coastguard Worker                                                               {{27, 155, 123}, {59, 187, 251}, {91, 219, 223}}},
2303*35238bceSAndroid Build Coastguard Worker                                                              {{{10, 138, 106}, {42, 170, 234}, {74, 202, 94}},
2304*35238bceSAndroid Build Coastguard Worker                                                               {{26, 154, 122}, {58, 186, 250}, {90, 218, 222}},
2305*35238bceSAndroid Build Coastguard Worker                                                               {{14, 142, 110}, {46, 174, 238}, {78, 206, 126}}}}};
2306*35238bceSAndroid Build Coastguard Worker 
2307*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numValues, 1, 5));
2308*35238bceSAndroid Build Coastguard Worker 
2309*35238bceSAndroid Build Coastguard Worker     uint32_t tritParts[5];
2310*35238bceSAndroid Build Coastguard Worker     uint32_t bitParts[5];
2311*35238bceSAndroid Build Coastguard Worker 
2312*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < 5; i++)
2313*35238bceSAndroid Build Coastguard Worker     {
2314*35238bceSAndroid Build Coastguard Worker         if (i < numValues)
2315*35238bceSAndroid Build Coastguard Worker         {
2316*35238bceSAndroid Build Coastguard Worker             if (fromExplicitInputBlock)
2317*35238bceSAndroid Build Coastguard Worker             {
2318*35238bceSAndroid Build Coastguard Worker                 bitParts[i]  = blockInput.bitValues[i];
2319*35238bceSAndroid Build Coastguard Worker                 tritParts[i] = -1; // \note Won't be used, but silences warning.
2320*35238bceSAndroid Build Coastguard Worker             }
2321*35238bceSAndroid Build Coastguard Worker             else
2322*35238bceSAndroid Build Coastguard Worker             {
2323*35238bceSAndroid Build Coastguard Worker                 // \todo [2016-01-20 pyry] numBits = 0 doesn't make sense
2324*35238bceSAndroid Build Coastguard Worker                 bitParts[i]  = numBits > 0 ? getBits(nonBlockInput[i], 0, numBits - 1) : 0;
2325*35238bceSAndroid Build Coastguard Worker                 tritParts[i] = nonBlockInput[i] >> numBits;
2326*35238bceSAndroid Build Coastguard Worker             }
2327*35238bceSAndroid Build Coastguard Worker         }
2328*35238bceSAndroid Build Coastguard Worker         else
2329*35238bceSAndroid Build Coastguard Worker         {
2330*35238bceSAndroid Build Coastguard Worker             bitParts[i]  = 0;
2331*35238bceSAndroid Build Coastguard Worker             tritParts[i] = 0;
2332*35238bceSAndroid Build Coastguard Worker         }
2333*35238bceSAndroid Build Coastguard Worker     }
2334*35238bceSAndroid Build Coastguard Worker 
2335*35238bceSAndroid Build Coastguard Worker     const uint32_t T = fromExplicitInputBlock ?
2336*35238bceSAndroid Build Coastguard Worker                            blockInput.tOrQValue :
2337*35238bceSAndroid Build Coastguard Worker                            tritBlockTValue[tritParts[0]][tritParts[1]][tritParts[2]][tritParts[3]][tritParts[4]];
2338*35238bceSAndroid Build Coastguard Worker 
2339*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[0]);
2340*35238bceSAndroid Build Coastguard Worker     dst.setNext(2, getBits(T, 0, 1));
2341*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[1]);
2342*35238bceSAndroid Build Coastguard Worker     dst.setNext(2, getBits(T, 2, 3));
2343*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[2]);
2344*35238bceSAndroid Build Coastguard Worker     dst.setNext(1, getBit(T, 4));
2345*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[3]);
2346*35238bceSAndroid Build Coastguard Worker     dst.setNext(2, getBits(T, 5, 6));
2347*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[4]);
2348*35238bceSAndroid Build Coastguard Worker     dst.setNext(1, getBit(T, 7));
2349*35238bceSAndroid Build Coastguard Worker }
2350*35238bceSAndroid Build Coastguard Worker 
encodeISEQuintBlock(BitAssignAccessStream & dst,int numBits,bool fromExplicitInputBlock,const ISEInput::Block & blockInput,const uint32_t * nonBlockInput,int numValues)2351*35238bceSAndroid Build Coastguard Worker static void encodeISEQuintBlock(BitAssignAccessStream &dst, int numBits, bool fromExplicitInputBlock,
2352*35238bceSAndroid Build Coastguard Worker                                 const ISEInput::Block &blockInput, const uint32_t *nonBlockInput, int numValues)
2353*35238bceSAndroid Build Coastguard Worker {
2354*35238bceSAndroid Build Coastguard Worker     // quintBlockQValue[q0][q1][q2] is a value of Q (not necessarily the only one) that will yield the given quints when decoded.
2355*35238bceSAndroid Build Coastguard Worker     static const uint32_t quintBlockQValue[5][5][5] = {{{0, 32, 64, 96, 102},
2356*35238bceSAndroid Build Coastguard Worker                                                         {8, 40, 72, 104, 110},
2357*35238bceSAndroid Build Coastguard Worker                                                         {16, 48, 80, 112, 118},
2358*35238bceSAndroid Build Coastguard Worker                                                         {24, 56, 88, 120, 126},
2359*35238bceSAndroid Build Coastguard Worker                                                         {5, 37, 69, 101, 39}},
2360*35238bceSAndroid Build Coastguard Worker                                                        {{1, 33, 65, 97, 103},
2361*35238bceSAndroid Build Coastguard Worker                                                         {9, 41, 73, 105, 111},
2362*35238bceSAndroid Build Coastguard Worker                                                         {17, 49, 81, 113, 119},
2363*35238bceSAndroid Build Coastguard Worker                                                         {25, 57, 89, 121, 127},
2364*35238bceSAndroid Build Coastguard Worker                                                         {13, 45, 77, 109, 47}},
2365*35238bceSAndroid Build Coastguard Worker                                                        {{2, 34, 66, 98, 70},
2366*35238bceSAndroid Build Coastguard Worker                                                         {10, 42, 74, 106, 78},
2367*35238bceSAndroid Build Coastguard Worker                                                         {18, 50, 82, 114, 86},
2368*35238bceSAndroid Build Coastguard Worker                                                         {26, 58, 90, 122, 94},
2369*35238bceSAndroid Build Coastguard Worker                                                         {21, 53, 85, 117, 55}},
2370*35238bceSAndroid Build Coastguard Worker                                                        {{3, 35, 67, 99, 71},
2371*35238bceSAndroid Build Coastguard Worker                                                         {11, 43, 75, 107, 79},
2372*35238bceSAndroid Build Coastguard Worker                                                         {19, 51, 83, 115, 87},
2373*35238bceSAndroid Build Coastguard Worker                                                         {27, 59, 91, 123, 95},
2374*35238bceSAndroid Build Coastguard Worker                                                         {29, 61, 93, 125, 63}},
2375*35238bceSAndroid Build Coastguard Worker                                                        {{4, 36, 68, 100, 38},
2376*35238bceSAndroid Build Coastguard Worker                                                         {12, 44, 76, 108, 46},
2377*35238bceSAndroid Build Coastguard Worker                                                         {20, 52, 84, 116, 54},
2378*35238bceSAndroid Build Coastguard Worker                                                         {28, 60, 92, 124, 62},
2379*35238bceSAndroid Build Coastguard Worker                                                         {6, 14, 22, 30, 7}}};
2380*35238bceSAndroid Build Coastguard Worker 
2381*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numValues, 1, 3));
2382*35238bceSAndroid Build Coastguard Worker 
2383*35238bceSAndroid Build Coastguard Worker     uint32_t quintParts[3];
2384*35238bceSAndroid Build Coastguard Worker     uint32_t bitParts[3];
2385*35238bceSAndroid Build Coastguard Worker 
2386*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < 3; i++)
2387*35238bceSAndroid Build Coastguard Worker     {
2388*35238bceSAndroid Build Coastguard Worker         if (i < numValues)
2389*35238bceSAndroid Build Coastguard Worker         {
2390*35238bceSAndroid Build Coastguard Worker             if (fromExplicitInputBlock)
2391*35238bceSAndroid Build Coastguard Worker             {
2392*35238bceSAndroid Build Coastguard Worker                 bitParts[i]   = blockInput.bitValues[i];
2393*35238bceSAndroid Build Coastguard Worker                 quintParts[i] = -1; // \note Won't be used, but silences warning.
2394*35238bceSAndroid Build Coastguard Worker             }
2395*35238bceSAndroid Build Coastguard Worker             else
2396*35238bceSAndroid Build Coastguard Worker             {
2397*35238bceSAndroid Build Coastguard Worker                 // \todo [2016-01-20 pyry] numBits = 0 doesn't make sense
2398*35238bceSAndroid Build Coastguard Worker                 bitParts[i]   = numBits > 0 ? getBits(nonBlockInput[i], 0, numBits - 1) : 0;
2399*35238bceSAndroid Build Coastguard Worker                 quintParts[i] = nonBlockInput[i] >> numBits;
2400*35238bceSAndroid Build Coastguard Worker             }
2401*35238bceSAndroid Build Coastguard Worker         }
2402*35238bceSAndroid Build Coastguard Worker         else
2403*35238bceSAndroid Build Coastguard Worker         {
2404*35238bceSAndroid Build Coastguard Worker             bitParts[i]   = 0;
2405*35238bceSAndroid Build Coastguard Worker             quintParts[i] = 0;
2406*35238bceSAndroid Build Coastguard Worker         }
2407*35238bceSAndroid Build Coastguard Worker     }
2408*35238bceSAndroid Build Coastguard Worker 
2409*35238bceSAndroid Build Coastguard Worker     const uint32_t Q =
2410*35238bceSAndroid Build Coastguard Worker         fromExplicitInputBlock ? blockInput.tOrQValue : quintBlockQValue[quintParts[0]][quintParts[1]][quintParts[2]];
2411*35238bceSAndroid Build Coastguard Worker 
2412*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[0]);
2413*35238bceSAndroid Build Coastguard Worker     dst.setNext(3, getBits(Q, 0, 2));
2414*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[1]);
2415*35238bceSAndroid Build Coastguard Worker     dst.setNext(2, getBits(Q, 3, 4));
2416*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, bitParts[2]);
2417*35238bceSAndroid Build Coastguard Worker     dst.setNext(2, getBits(Q, 5, 6));
2418*35238bceSAndroid Build Coastguard Worker }
2419*35238bceSAndroid Build Coastguard Worker 
encodeISEBitBlock(BitAssignAccessStream & dst,int numBits,uint32_t value)2420*35238bceSAndroid Build Coastguard Worker static void encodeISEBitBlock(BitAssignAccessStream &dst, int numBits, uint32_t value)
2421*35238bceSAndroid Build Coastguard Worker {
2422*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(value, 0u, (1u << numBits) - 1));
2423*35238bceSAndroid Build Coastguard Worker     dst.setNext(numBits, value);
2424*35238bceSAndroid Build Coastguard Worker }
2425*35238bceSAndroid Build Coastguard Worker 
encodeISE(BitAssignAccessStream & dst,const ISEParams & params,const ISEInput & input,int numValues)2426*35238bceSAndroid Build Coastguard Worker static void encodeISE(BitAssignAccessStream &dst, const ISEParams &params, const ISEInput &input, int numValues)
2427*35238bceSAndroid Build Coastguard Worker {
2428*35238bceSAndroid Build Coastguard Worker     if (params.mode == ISEMODE_TRIT)
2429*35238bceSAndroid Build Coastguard Worker     {
2430*35238bceSAndroid Build Coastguard Worker         const int numBlocks = deDivRoundUp32(numValues, 5);
2431*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2432*35238bceSAndroid Build Coastguard Worker         {
2433*35238bceSAndroid Build Coastguard Worker             const int numValuesInBlock = blockNdx == numBlocks - 1 ? numValues - 5 * (numBlocks - 1) : 5;
2434*35238bceSAndroid Build Coastguard Worker             encodeISETritBlock(dst, params.numBits, input.isGivenInBlockForm,
2435*35238bceSAndroid Build Coastguard Worker                                input.isGivenInBlockForm ? input.value.block[blockNdx] : ISEInput::Block(),
2436*35238bceSAndroid Build Coastguard Worker                                input.isGivenInBlockForm ? DE_NULL : &input.value.plain[5 * blockNdx], numValuesInBlock);
2437*35238bceSAndroid Build Coastguard Worker         }
2438*35238bceSAndroid Build Coastguard Worker     }
2439*35238bceSAndroid Build Coastguard Worker     else if (params.mode == ISEMODE_QUINT)
2440*35238bceSAndroid Build Coastguard Worker     {
2441*35238bceSAndroid Build Coastguard Worker         const int numBlocks = deDivRoundUp32(numValues, 3);
2442*35238bceSAndroid Build Coastguard Worker         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2443*35238bceSAndroid Build Coastguard Worker         {
2444*35238bceSAndroid Build Coastguard Worker             const int numValuesInBlock = blockNdx == numBlocks - 1 ? numValues - 3 * (numBlocks - 1) : 3;
2445*35238bceSAndroid Build Coastguard Worker             encodeISEQuintBlock(dst, params.numBits, input.isGivenInBlockForm,
2446*35238bceSAndroid Build Coastguard Worker                                 input.isGivenInBlockForm ? input.value.block[blockNdx] : ISEInput::Block(),
2447*35238bceSAndroid Build Coastguard Worker                                 input.isGivenInBlockForm ? DE_NULL : &input.value.plain[3 * blockNdx],
2448*35238bceSAndroid Build Coastguard Worker                                 numValuesInBlock);
2449*35238bceSAndroid Build Coastguard Worker         }
2450*35238bceSAndroid Build Coastguard Worker     }
2451*35238bceSAndroid Build Coastguard Worker     else
2452*35238bceSAndroid Build Coastguard Worker     {
2453*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(params.mode == ISEMODE_PLAIN_BIT);
2454*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < numValues; i++)
2455*35238bceSAndroid Build Coastguard Worker             encodeISEBitBlock(dst, params.numBits,
2456*35238bceSAndroid Build Coastguard Worker                               input.isGivenInBlockForm ? input.value.block[i].bitValues[0] : input.value.plain[i]);
2457*35238bceSAndroid Build Coastguard Worker     }
2458*35238bceSAndroid Build Coastguard Worker }
2459*35238bceSAndroid Build Coastguard Worker 
writeWeightData(AssignBlock128 & dst,const ISEParams & iseParams,const ISEInput & input,int numWeights)2460*35238bceSAndroid Build Coastguard Worker static void writeWeightData(AssignBlock128 &dst, const ISEParams &iseParams, const ISEInput &input, int numWeights)
2461*35238bceSAndroid Build Coastguard Worker {
2462*35238bceSAndroid Build Coastguard Worker     const int numWeightBits = computeNumRequiredBits(iseParams, numWeights);
2463*35238bceSAndroid Build Coastguard Worker     BitAssignAccessStream access(dst, 127, numWeightBits, false);
2464*35238bceSAndroid Build Coastguard Worker     encodeISE(access, iseParams, input, numWeights);
2465*35238bceSAndroid Build Coastguard Worker }
2466*35238bceSAndroid Build Coastguard Worker 
writeColorEndpointData(AssignBlock128 & dst,const ISEParams & iseParams,const ISEInput & input,int numEndpoints,int numBitsForColorEndpoints,int colorEndpointDataStartNdx)2467*35238bceSAndroid Build Coastguard Worker static void writeColorEndpointData(AssignBlock128 &dst, const ISEParams &iseParams, const ISEInput &input,
2468*35238bceSAndroid Build Coastguard Worker                                    int numEndpoints, int numBitsForColorEndpoints, int colorEndpointDataStartNdx)
2469*35238bceSAndroid Build Coastguard Worker {
2470*35238bceSAndroid Build Coastguard Worker     BitAssignAccessStream access(dst, colorEndpointDataStartNdx, numBitsForColorEndpoints, true);
2471*35238bceSAndroid Build Coastguard Worker     encodeISE(access, iseParams, input, numEndpoints);
2472*35238bceSAndroid Build Coastguard Worker }
2473*35238bceSAndroid Build Coastguard Worker 
generateNormalBlock(const NormalBlockParams & blockParams,int blockWidth,int blockHeight,const NormalBlockISEInputs & iseInputs)2474*35238bceSAndroid Build Coastguard Worker static AssignBlock128 generateNormalBlock(const NormalBlockParams &blockParams, int blockWidth, int blockHeight,
2475*35238bceSAndroid Build Coastguard Worker                                           const NormalBlockISEInputs &iseInputs)
2476*35238bceSAndroid Build Coastguard Worker {
2477*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isValidBlockParams(blockParams, blockWidth, blockHeight));
2478*35238bceSAndroid Build Coastguard Worker     DE_UNREF(blockWidth);  // \note For non-debug builds.
2479*35238bceSAndroid Build Coastguard Worker     DE_UNREF(blockHeight); // \note For non-debug builds.
2480*35238bceSAndroid Build Coastguard Worker 
2481*35238bceSAndroid Build Coastguard Worker     AssignBlock128 block;
2482*35238bceSAndroid Build Coastguard Worker     const int numWeights    = computeNumWeights(blockParams);
2483*35238bceSAndroid Build Coastguard Worker     const int numWeightBits = computeNumRequiredBits(blockParams.weightISEParams, numWeights);
2484*35238bceSAndroid Build Coastguard Worker 
2485*35238bceSAndroid Build Coastguard Worker     writeBlockMode(block, blockParams);
2486*35238bceSAndroid Build Coastguard Worker 
2487*35238bceSAndroid Build Coastguard Worker     block.setBits(11, 12, blockParams.numPartitions - 1);
2488*35238bceSAndroid Build Coastguard Worker     if (blockParams.numPartitions > 1)
2489*35238bceSAndroid Build Coastguard Worker         block.setBits(13, 22, blockParams.partitionSeed);
2490*35238bceSAndroid Build Coastguard Worker 
2491*35238bceSAndroid Build Coastguard Worker     {
2492*35238bceSAndroid Build Coastguard Worker         const int extraCemBitsStart = 127 - numWeightBits -
2493*35238bceSAndroid Build Coastguard Worker                                       (blockParams.numPartitions == 1 || blockParams.isMultiPartSingleCemMode ? -1 :
2494*35238bceSAndroid Build Coastguard Worker                                        blockParams.numPartitions == 4                                         ? 7 :
2495*35238bceSAndroid Build Coastguard Worker                                        blockParams.numPartitions == 3                                         ? 4 :
2496*35238bceSAndroid Build Coastguard Worker                                        blockParams.numPartitions == 2                                         ? 1 :
2497*35238bceSAndroid Build Coastguard Worker                                                                                                                 0);
2498*35238bceSAndroid Build Coastguard Worker 
2499*35238bceSAndroid Build Coastguard Worker         writeColorEndpointModes(block, &blockParams.colorEndpointModes[0], blockParams.isMultiPartSingleCemMode,
2500*35238bceSAndroid Build Coastguard Worker                                 blockParams.numPartitions, extraCemBitsStart);
2501*35238bceSAndroid Build Coastguard Worker 
2502*35238bceSAndroid Build Coastguard Worker         if (blockParams.isDualPlane)
2503*35238bceSAndroid Build Coastguard Worker             block.setBits(extraCemBitsStart - 2, extraCemBitsStart - 1, blockParams.ccs);
2504*35238bceSAndroid Build Coastguard Worker     }
2505*35238bceSAndroid Build Coastguard Worker 
2506*35238bceSAndroid Build Coastguard Worker     writeWeightData(block, blockParams.weightISEParams, iseInputs.weight, numWeights);
2507*35238bceSAndroid Build Coastguard Worker 
2508*35238bceSAndroid Build Coastguard Worker     {
2509*35238bceSAndroid Build Coastguard Worker         const int numColorEndpointValues = computeNumColorEndpointValues(
2510*35238bceSAndroid Build Coastguard Worker             &blockParams.colorEndpointModes[0], blockParams.numPartitions, blockParams.isMultiPartSingleCemMode);
2511*35238bceSAndroid Build Coastguard Worker         const int numBitsForColorEndpoints  = computeNumBitsForColorEndpoints(blockParams);
2512*35238bceSAndroid Build Coastguard Worker         const int colorEndpointDataStartNdx = blockParams.numPartitions == 1 ? 17 : 29;
2513*35238bceSAndroid Build Coastguard Worker         const ISEParams &colorEndpointISEParams =
2514*35238bceSAndroid Build Coastguard Worker             computeMaximumRangeISEParams(numBitsForColorEndpoints, numColorEndpointValues);
2515*35238bceSAndroid Build Coastguard Worker 
2516*35238bceSAndroid Build Coastguard Worker         writeColorEndpointData(block, colorEndpointISEParams, iseInputs.endpoint, numColorEndpointValues,
2517*35238bceSAndroid Build Coastguard Worker                                numBitsForColorEndpoints, colorEndpointDataStartNdx);
2518*35238bceSAndroid Build Coastguard Worker     }
2519*35238bceSAndroid Build Coastguard Worker 
2520*35238bceSAndroid Build Coastguard Worker     return block;
2521*35238bceSAndroid Build Coastguard Worker }
2522*35238bceSAndroid Build Coastguard Worker 
2523*35238bceSAndroid Build Coastguard Worker // Generate default ISE inputs for weight and endpoint data - gradient-ish values.
generateDefaultISEInputs(const NormalBlockParams & blockParams)2524*35238bceSAndroid Build Coastguard Worker static NormalBlockISEInputs generateDefaultISEInputs(const NormalBlockParams &blockParams)
2525*35238bceSAndroid Build Coastguard Worker {
2526*35238bceSAndroid Build Coastguard Worker     NormalBlockISEInputs result;
2527*35238bceSAndroid Build Coastguard Worker 
2528*35238bceSAndroid Build Coastguard Worker     {
2529*35238bceSAndroid Build Coastguard Worker         result.weight.isGivenInBlockForm = false;
2530*35238bceSAndroid Build Coastguard Worker 
2531*35238bceSAndroid Build Coastguard Worker         const int numWeights     = computeNumWeights(blockParams);
2532*35238bceSAndroid Build Coastguard Worker         const int weightRangeMax = computeISERangeMax(blockParams.weightISEParams);
2533*35238bceSAndroid Build Coastguard Worker 
2534*35238bceSAndroid Build Coastguard Worker         if (blockParams.isDualPlane)
2535*35238bceSAndroid Build Coastguard Worker         {
2536*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < numWeights; i += 2)
2537*35238bceSAndroid Build Coastguard Worker                 result.weight.value.plain[i] = (i * weightRangeMax + (numWeights - 1) / 2) / (numWeights - 1);
2538*35238bceSAndroid Build Coastguard Worker 
2539*35238bceSAndroid Build Coastguard Worker             for (int i = 1; i < numWeights; i += 2)
2540*35238bceSAndroid Build Coastguard Worker                 result.weight.value.plain[i] =
2541*35238bceSAndroid Build Coastguard Worker                     weightRangeMax - (i * weightRangeMax + (numWeights - 1) / 2) / (numWeights - 1);
2542*35238bceSAndroid Build Coastguard Worker         }
2543*35238bceSAndroid Build Coastguard Worker         else
2544*35238bceSAndroid Build Coastguard Worker         {
2545*35238bceSAndroid Build Coastguard Worker             for (int i = 0; i < numWeights; i++)
2546*35238bceSAndroid Build Coastguard Worker                 result.weight.value.plain[i] = (i * weightRangeMax + (numWeights - 1) / 2) / (numWeights - 1);
2547*35238bceSAndroid Build Coastguard Worker         }
2548*35238bceSAndroid Build Coastguard Worker     }
2549*35238bceSAndroid Build Coastguard Worker 
2550*35238bceSAndroid Build Coastguard Worker     {
2551*35238bceSAndroid Build Coastguard Worker         result.endpoint.isGivenInBlockForm = false;
2552*35238bceSAndroid Build Coastguard Worker 
2553*35238bceSAndroid Build Coastguard Worker         const int numColorEndpointValues = computeNumColorEndpointValues(
2554*35238bceSAndroid Build Coastguard Worker             &blockParams.colorEndpointModes[0], blockParams.numPartitions, blockParams.isMultiPartSingleCemMode);
2555*35238bceSAndroid Build Coastguard Worker         const int numBitsForColorEndpoints = computeNumBitsForColorEndpoints(blockParams);
2556*35238bceSAndroid Build Coastguard Worker         const ISEParams &colorEndpointISEParams =
2557*35238bceSAndroid Build Coastguard Worker             computeMaximumRangeISEParams(numBitsForColorEndpoints, numColorEndpointValues);
2558*35238bceSAndroid Build Coastguard Worker         const int colorEndpointRangeMax = computeISERangeMax(colorEndpointISEParams);
2559*35238bceSAndroid Build Coastguard Worker 
2560*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < numColorEndpointValues; i++)
2561*35238bceSAndroid Build Coastguard Worker             result.endpoint.value.plain[i] =
2562*35238bceSAndroid Build Coastguard Worker                 (i * colorEndpointRangeMax + (numColorEndpointValues - 1) / 2) / (numColorEndpointValues - 1);
2563*35238bceSAndroid Build Coastguard Worker     }
2564*35238bceSAndroid Build Coastguard Worker 
2565*35238bceSAndroid Build Coastguard Worker     return result;
2566*35238bceSAndroid Build Coastguard Worker }
2567*35238bceSAndroid Build Coastguard Worker 
2568*35238bceSAndroid Build Coastguard Worker static const ISEParams s_weightISEParamsCandidates[] = {
2569*35238bceSAndroid Build Coastguard Worker     ISEParams(ISEMODE_PLAIN_BIT, 1), ISEParams(ISEMODE_TRIT, 0), ISEParams(ISEMODE_PLAIN_BIT, 2),
2570*35238bceSAndroid Build Coastguard Worker     ISEParams(ISEMODE_QUINT, 0),     ISEParams(ISEMODE_TRIT, 1), ISEParams(ISEMODE_PLAIN_BIT, 3),
2571*35238bceSAndroid Build Coastguard Worker     ISEParams(ISEMODE_QUINT, 1),     ISEParams(ISEMODE_TRIT, 2), ISEParams(ISEMODE_PLAIN_BIT, 4),
2572*35238bceSAndroid Build Coastguard Worker     ISEParams(ISEMODE_QUINT, 2),     ISEParams(ISEMODE_TRIT, 3), ISEParams(ISEMODE_PLAIN_BIT, 5)};
2573*35238bceSAndroid Build Coastguard Worker 
generateRandomBlock(uint8_t * dst,const IVec3 & blockSize,de::Random & rnd)2574*35238bceSAndroid Build Coastguard Worker void generateRandomBlock(uint8_t *dst, const IVec3 &blockSize, de::Random &rnd)
2575*35238bceSAndroid Build Coastguard Worker {
2576*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockSize.z() == 1);
2577*35238bceSAndroid Build Coastguard Worker 
2578*35238bceSAndroid Build Coastguard Worker     if (rnd.getFloat() < 0.1f)
2579*35238bceSAndroid Build Coastguard Worker     {
2580*35238bceSAndroid Build Coastguard Worker         // Void extent block.
2581*35238bceSAndroid Build Coastguard Worker         const bool isVoidExtentHDR = rnd.getBool();
2582*35238bceSAndroid Build Coastguard Worker         const uint16_t r = isVoidExtentHDR ? deFloat32To16(rnd.getFloat(0.0f, 1.0f)) : (uint16_t)rnd.getInt(0, 0xffff);
2583*35238bceSAndroid Build Coastguard Worker         const uint16_t g = isVoidExtentHDR ? deFloat32To16(rnd.getFloat(0.0f, 1.0f)) : (uint16_t)rnd.getInt(0, 0xffff);
2584*35238bceSAndroid Build Coastguard Worker         const uint16_t b = isVoidExtentHDR ? deFloat32To16(rnd.getFloat(0.0f, 1.0f)) : (uint16_t)rnd.getInt(0, 0xffff);
2585*35238bceSAndroid Build Coastguard Worker         const uint16_t a = isVoidExtentHDR ? deFloat32To16(rnd.getFloat(0.0f, 1.0f)) : (uint16_t)rnd.getInt(0, 0xffff);
2586*35238bceSAndroid Build Coastguard Worker         generateVoidExtentBlock(VoidExtentParams(isVoidExtentHDR, r, g, b, a)).assignToMemory(dst);
2587*35238bceSAndroid Build Coastguard Worker     }
2588*35238bceSAndroid Build Coastguard Worker     else
2589*35238bceSAndroid Build Coastguard Worker     {
2590*35238bceSAndroid Build Coastguard Worker         // Not void extent block.
2591*35238bceSAndroid Build Coastguard Worker 
2592*35238bceSAndroid Build Coastguard Worker         // Generate block params.
2593*35238bceSAndroid Build Coastguard Worker 
2594*35238bceSAndroid Build Coastguard Worker         NormalBlockParams blockParams;
2595*35238bceSAndroid Build Coastguard Worker 
2596*35238bceSAndroid Build Coastguard Worker         do
2597*35238bceSAndroid Build Coastguard Worker         {
2598*35238bceSAndroid Build Coastguard Worker             blockParams.weightGridWidth  = rnd.getInt(2, blockSize.x());
2599*35238bceSAndroid Build Coastguard Worker             blockParams.weightGridHeight = rnd.getInt(2, blockSize.y());
2600*35238bceSAndroid Build Coastguard Worker             blockParams.weightISEParams =
2601*35238bceSAndroid Build Coastguard Worker                 s_weightISEParamsCandidates[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates) - 1)];
2602*35238bceSAndroid Build Coastguard Worker             blockParams.numPartitions            = rnd.getInt(1, 4);
2603*35238bceSAndroid Build Coastguard Worker             blockParams.isMultiPartSingleCemMode = rnd.getFloat() < 0.25f;
2604*35238bceSAndroid Build Coastguard Worker             blockParams.isDualPlane              = blockParams.numPartitions != 4 && rnd.getBool();
2605*35238bceSAndroid Build Coastguard Worker             blockParams.ccs                      = rnd.getInt(0, 3);
2606*35238bceSAndroid Build Coastguard Worker             blockParams.partitionSeed            = rnd.getInt(0, 1023);
2607*35238bceSAndroid Build Coastguard Worker 
2608*35238bceSAndroid Build Coastguard Worker             blockParams.colorEndpointModes[0] = rnd.getInt(0, 15);
2609*35238bceSAndroid Build Coastguard Worker 
2610*35238bceSAndroid Build Coastguard Worker             {
2611*35238bceSAndroid Build Coastguard Worker                 const int cemDiff = blockParams.isMultiPartSingleCemMode    ? 0 :
2612*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[0] == 0  ? 1 :
2613*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[0] == 15 ? -1 :
2614*35238bceSAndroid Build Coastguard Worker                                     rnd.getBool()                           ? 1 :
2615*35238bceSAndroid Build Coastguard Worker                                                                               -1;
2616*35238bceSAndroid Build Coastguard Worker 
2617*35238bceSAndroid Build Coastguard Worker                 for (int i = 1; i < blockParams.numPartitions; i++)
2618*35238bceSAndroid Build Coastguard Worker                     blockParams.colorEndpointModes[i] =
2619*35238bceSAndroid Build Coastguard Worker                         blockParams.colorEndpointModes[0] + (cemDiff == -1 ? rnd.getInt(-1, 0) :
2620*35238bceSAndroid Build Coastguard Worker                                                              cemDiff == 1  ? rnd.getInt(0, 1) :
2621*35238bceSAndroid Build Coastguard Worker                                                                              0);
2622*35238bceSAndroid Build Coastguard Worker             }
2623*35238bceSAndroid Build Coastguard Worker         } while (!isValidBlockParams(blockParams, blockSize.x(), blockSize.y()));
2624*35238bceSAndroid Build Coastguard Worker 
2625*35238bceSAndroid Build Coastguard Worker         // Generate ISE inputs for both weight and endpoint data.
2626*35238bceSAndroid Build Coastguard Worker 
2627*35238bceSAndroid Build Coastguard Worker         NormalBlockISEInputs iseInputs;
2628*35238bceSAndroid Build Coastguard Worker 
2629*35238bceSAndroid Build Coastguard Worker         for (int weightOrEndpoints = 0; weightOrEndpoints <= 1; weightOrEndpoints++)
2630*35238bceSAndroid Build Coastguard Worker         {
2631*35238bceSAndroid Build Coastguard Worker             const bool setWeights = weightOrEndpoints == 0;
2632*35238bceSAndroid Build Coastguard Worker             const int numValues   = setWeights ? computeNumWeights(blockParams) :
2633*35238bceSAndroid Build Coastguard Worker                                                  computeNumColorEndpointValues(&blockParams.colorEndpointModes[0],
2634*35238bceSAndroid Build Coastguard Worker                                                                                blockParams.numPartitions,
2635*35238bceSAndroid Build Coastguard Worker                                                                                blockParams.isMultiPartSingleCemMode);
2636*35238bceSAndroid Build Coastguard Worker             const ISEParams iseParams =
2637*35238bceSAndroid Build Coastguard Worker                 setWeights ? blockParams.weightISEParams :
2638*35238bceSAndroid Build Coastguard Worker                              computeMaximumRangeISEParams(computeNumBitsForColorEndpoints(blockParams), numValues);
2639*35238bceSAndroid Build Coastguard Worker             ISEInput &iseInput = setWeights ? iseInputs.weight : iseInputs.endpoint;
2640*35238bceSAndroid Build Coastguard Worker 
2641*35238bceSAndroid Build Coastguard Worker             iseInput.isGivenInBlockForm = rnd.getBool();
2642*35238bceSAndroid Build Coastguard Worker 
2643*35238bceSAndroid Build Coastguard Worker             if (iseInput.isGivenInBlockForm)
2644*35238bceSAndroid Build Coastguard Worker             {
2645*35238bceSAndroid Build Coastguard Worker                 const int numValuesPerISEBlock = iseParams.mode == ISEMODE_TRIT  ? 5 :
2646*35238bceSAndroid Build Coastguard Worker                                                  iseParams.mode == ISEMODE_QUINT ? 3 :
2647*35238bceSAndroid Build Coastguard Worker                                                                                    1;
2648*35238bceSAndroid Build Coastguard Worker                 const int iseBitMax            = (1 << iseParams.numBits) - 1;
2649*35238bceSAndroid Build Coastguard Worker                 const int numISEBlocks         = deDivRoundUp32(numValues, numValuesPerISEBlock);
2650*35238bceSAndroid Build Coastguard Worker 
2651*35238bceSAndroid Build Coastguard Worker                 for (int iseBlockNdx = 0; iseBlockNdx < numISEBlocks; iseBlockNdx++)
2652*35238bceSAndroid Build Coastguard Worker                 {
2653*35238bceSAndroid Build Coastguard Worker                     iseInput.value.block[iseBlockNdx].tOrQValue = rnd.getInt(0, 255);
2654*35238bceSAndroid Build Coastguard Worker                     for (int i = 0; i < numValuesPerISEBlock; i++)
2655*35238bceSAndroid Build Coastguard Worker                         iseInput.value.block[iseBlockNdx].bitValues[i] = rnd.getInt(0, iseBitMax);
2656*35238bceSAndroid Build Coastguard Worker                 }
2657*35238bceSAndroid Build Coastguard Worker             }
2658*35238bceSAndroid Build Coastguard Worker             else
2659*35238bceSAndroid Build Coastguard Worker             {
2660*35238bceSAndroid Build Coastguard Worker                 const int rangeMax = computeISERangeMax(iseParams);
2661*35238bceSAndroid Build Coastguard Worker 
2662*35238bceSAndroid Build Coastguard Worker                 for (int valueNdx = 0; valueNdx < numValues; valueNdx++)
2663*35238bceSAndroid Build Coastguard Worker                     iseInput.value.plain[valueNdx] = rnd.getInt(0, rangeMax);
2664*35238bceSAndroid Build Coastguard Worker             }
2665*35238bceSAndroid Build Coastguard Worker         }
2666*35238bceSAndroid Build Coastguard Worker 
2667*35238bceSAndroid Build Coastguard Worker         generateNormalBlock(blockParams, blockSize.x(), blockSize.y(), iseInputs).assignToMemory(dst);
2668*35238bceSAndroid Build Coastguard Worker     }
2669*35238bceSAndroid Build Coastguard Worker }
2670*35238bceSAndroid Build Coastguard Worker 
2671*35238bceSAndroid Build Coastguard Worker } // namespace
2672*35238bceSAndroid Build Coastguard Worker 
2673*35238bceSAndroid Build Coastguard Worker // Generate block data for a given BlockTestType and format.
generateBlockCaseTestData(vector<uint8_t> & dst,CompressedTexFormat format,BlockTestType testType)2674*35238bceSAndroid Build Coastguard Worker void generateBlockCaseTestData(vector<uint8_t> &dst, CompressedTexFormat format, BlockTestType testType)
2675*35238bceSAndroid Build Coastguard Worker {
2676*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isAstcFormat(format));
2677*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!(isAstcSRGBFormat(format) && isBlockTestTypeHDROnly(testType)));
2678*35238bceSAndroid Build Coastguard Worker 
2679*35238bceSAndroid Build Coastguard Worker     const IVec3 blockSize = getBlockPixelSize(format);
2680*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockSize.z() == 1);
2681*35238bceSAndroid Build Coastguard Worker 
2682*35238bceSAndroid Build Coastguard Worker     switch (testType)
2683*35238bceSAndroid Build Coastguard Worker     {
2684*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_LDR:
2685*35238bceSAndroid Build Coastguard Worker         // Generate a gradient-like set of LDR void-extent blocks.
2686*35238bceSAndroid Build Coastguard Worker         {
2687*35238bceSAndroid Build Coastguard Worker             const int numBlocks      = 1 << 13;
2688*35238bceSAndroid Build Coastguard Worker             const uint32_t numValues = 1 << 16;
2689*35238bceSAndroid Build Coastguard Worker             dst.reserve(numBlocks * BLOCK_SIZE_BYTES);
2690*35238bceSAndroid Build Coastguard Worker 
2691*35238bceSAndroid Build Coastguard Worker             for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2692*35238bceSAndroid Build Coastguard Worker             {
2693*35238bceSAndroid Build Coastguard Worker                 const uint32_t baseValue = blockNdx * (numValues - 1) / (numBlocks - 1);
2694*35238bceSAndroid Build Coastguard Worker                 const uint16_t r         = (uint16_t)((baseValue + numValues * 0 / 4) % numValues);
2695*35238bceSAndroid Build Coastguard Worker                 const uint16_t g         = (uint16_t)((baseValue + numValues * 1 / 4) % numValues);
2696*35238bceSAndroid Build Coastguard Worker                 const uint16_t b         = (uint16_t)((baseValue + numValues * 2 / 4) % numValues);
2697*35238bceSAndroid Build Coastguard Worker                 const uint16_t a         = (uint16_t)((baseValue + numValues * 3 / 4) % numValues);
2698*35238bceSAndroid Build Coastguard Worker                 AssignBlock128 block;
2699*35238bceSAndroid Build Coastguard Worker 
2700*35238bceSAndroid Build Coastguard Worker                 generateVoidExtentBlock(VoidExtentParams(false, r, g, b, a)).pushBytesToVector(dst);
2701*35238bceSAndroid Build Coastguard Worker             }
2702*35238bceSAndroid Build Coastguard Worker 
2703*35238bceSAndroid Build Coastguard Worker             break;
2704*35238bceSAndroid Build Coastguard Worker         }
2705*35238bceSAndroid Build Coastguard Worker 
2706*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_HDR:
2707*35238bceSAndroid Build Coastguard Worker         // Generate a gradient-like set of HDR void-extent blocks, with values ranging from the largest finite negative to largest finite positive of fp16.
2708*35238bceSAndroid Build Coastguard Worker         {
2709*35238bceSAndroid Build Coastguard Worker             const float minValue = -65504.0f;
2710*35238bceSAndroid Build Coastguard Worker             const float maxValue = +65504.0f;
2711*35238bceSAndroid Build Coastguard Worker             const int numBlocks  = 1 << 13;
2712*35238bceSAndroid Build Coastguard Worker             dst.reserve(numBlocks * BLOCK_SIZE_BYTES);
2713*35238bceSAndroid Build Coastguard Worker 
2714*35238bceSAndroid Build Coastguard Worker             for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2715*35238bceSAndroid Build Coastguard Worker             {
2716*35238bceSAndroid Build Coastguard Worker                 const int rNdx = (blockNdx + numBlocks * 0 / 4) % numBlocks;
2717*35238bceSAndroid Build Coastguard Worker                 const int gNdx = (blockNdx + numBlocks * 1 / 4) % numBlocks;
2718*35238bceSAndroid Build Coastguard Worker                 const int bNdx = (blockNdx + numBlocks * 2 / 4) % numBlocks;
2719*35238bceSAndroid Build Coastguard Worker                 const int aNdx = (blockNdx + numBlocks * 3 / 4) % numBlocks;
2720*35238bceSAndroid Build Coastguard Worker                 const deFloat16 r =
2721*35238bceSAndroid Build Coastguard Worker                     deFloat32To16(minValue + (float)rNdx * (maxValue - minValue) / (float)(numBlocks - 1));
2722*35238bceSAndroid Build Coastguard Worker                 const deFloat16 g =
2723*35238bceSAndroid Build Coastguard Worker                     deFloat32To16(minValue + (float)gNdx * (maxValue - minValue) / (float)(numBlocks - 1));
2724*35238bceSAndroid Build Coastguard Worker                 const deFloat16 b =
2725*35238bceSAndroid Build Coastguard Worker                     deFloat32To16(minValue + (float)bNdx * (maxValue - minValue) / (float)(numBlocks - 1));
2726*35238bceSAndroid Build Coastguard Worker                 const deFloat16 a =
2727*35238bceSAndroid Build Coastguard Worker                     deFloat32To16(minValue + (float)aNdx * (maxValue - minValue) / (float)(numBlocks - 1));
2728*35238bceSAndroid Build Coastguard Worker 
2729*35238bceSAndroid Build Coastguard Worker                 generateVoidExtentBlock(VoidExtentParams(true, r, g, b, a)).pushBytesToVector(dst);
2730*35238bceSAndroid Build Coastguard Worker             }
2731*35238bceSAndroid Build Coastguard Worker 
2732*35238bceSAndroid Build Coastguard Worker             break;
2733*35238bceSAndroid Build Coastguard Worker         }
2734*35238bceSAndroid Build Coastguard Worker 
2735*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_GRID:
2736*35238bceSAndroid Build Coastguard Worker         // Generate different combinations of plane count, weight ISE params, and grid size.
2737*35238bceSAndroid Build Coastguard Worker         {
2738*35238bceSAndroid Build Coastguard Worker             for (int isDualPlane = 0; isDualPlane <= 1; isDualPlane++)
2739*35238bceSAndroid Build Coastguard Worker                 for (int iseParamsNdx = 0; iseParamsNdx < DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates);
2740*35238bceSAndroid Build Coastguard Worker                      iseParamsNdx++)
2741*35238bceSAndroid Build Coastguard Worker                     for (int weightGridWidth = 2; weightGridWidth <= 12; weightGridWidth++)
2742*35238bceSAndroid Build Coastguard Worker                         for (int weightGridHeight = 2; weightGridHeight <= 12; weightGridHeight++)
2743*35238bceSAndroid Build Coastguard Worker                         {
2744*35238bceSAndroid Build Coastguard Worker                             NormalBlockParams blockParams;
2745*35238bceSAndroid Build Coastguard Worker                             NormalBlockISEInputs iseInputs;
2746*35238bceSAndroid Build Coastguard Worker 
2747*35238bceSAndroid Build Coastguard Worker                             blockParams.weightGridWidth       = weightGridWidth;
2748*35238bceSAndroid Build Coastguard Worker                             blockParams.weightGridHeight      = weightGridHeight;
2749*35238bceSAndroid Build Coastguard Worker                             blockParams.isDualPlane           = isDualPlane != 0;
2750*35238bceSAndroid Build Coastguard Worker                             blockParams.weightISEParams       = s_weightISEParamsCandidates[iseParamsNdx];
2751*35238bceSAndroid Build Coastguard Worker                             blockParams.ccs                   = 0;
2752*35238bceSAndroid Build Coastguard Worker                             blockParams.numPartitions         = 1;
2753*35238bceSAndroid Build Coastguard Worker                             blockParams.colorEndpointModes[0] = 0;
2754*35238bceSAndroid Build Coastguard Worker 
2755*35238bceSAndroid Build Coastguard Worker                             if (isValidBlockParams(blockParams, blockSize.x(), blockSize.y()))
2756*35238bceSAndroid Build Coastguard Worker                                 generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
2757*35238bceSAndroid Build Coastguard Worker                                                     generateDefaultISEInputs(blockParams))
2758*35238bceSAndroid Build Coastguard Worker                                     .pushBytesToVector(dst);
2759*35238bceSAndroid Build Coastguard Worker                         }
2760*35238bceSAndroid Build Coastguard Worker 
2761*35238bceSAndroid Build Coastguard Worker             break;
2762*35238bceSAndroid Build Coastguard Worker         }
2763*35238bceSAndroid Build Coastguard Worker 
2764*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_ISE:
2765*35238bceSAndroid Build Coastguard Worker         // For each weight ISE param set, generate blocks that cover:
2766*35238bceSAndroid Build Coastguard Worker         // - each single value of the ISE's range, at each position inside an ISE block
2767*35238bceSAndroid Build Coastguard Worker         // - for trit and quint ISEs, each single T or Q value of an ISE block
2768*35238bceSAndroid Build Coastguard Worker         {
2769*35238bceSAndroid Build Coastguard Worker             for (int iseParamsNdx = 0; iseParamsNdx < DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates); iseParamsNdx++)
2770*35238bceSAndroid Build Coastguard Worker             {
2771*35238bceSAndroid Build Coastguard Worker                 const ISEParams &iseParams = s_weightISEParamsCandidates[iseParamsNdx];
2772*35238bceSAndroid Build Coastguard Worker                 NormalBlockParams blockParams;
2773*35238bceSAndroid Build Coastguard Worker 
2774*35238bceSAndroid Build Coastguard Worker                 blockParams.weightGridWidth  = 4;
2775*35238bceSAndroid Build Coastguard Worker                 blockParams.weightGridHeight = 4;
2776*35238bceSAndroid Build Coastguard Worker                 blockParams.weightISEParams  = iseParams;
2777*35238bceSAndroid Build Coastguard Worker                 blockParams.numPartitions    = 1;
2778*35238bceSAndroid Build Coastguard Worker                 blockParams.isDualPlane =
2779*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridWidth * blockParams.weightGridHeight < 24 ? true : false;
2780*35238bceSAndroid Build Coastguard Worker                 blockParams.ccs                   = 0;
2781*35238bceSAndroid Build Coastguard Worker                 blockParams.colorEndpointModes[0] = 0;
2782*35238bceSAndroid Build Coastguard Worker 
2783*35238bceSAndroid Build Coastguard Worker                 while (!isValidBlockParams(blockParams, blockSize.x(), blockSize.y()))
2784*35238bceSAndroid Build Coastguard Worker                 {
2785*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridWidth--;
2786*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridHeight--;
2787*35238bceSAndroid Build Coastguard Worker                 }
2788*35238bceSAndroid Build Coastguard Worker 
2789*35238bceSAndroid Build Coastguard Worker                 const int numValuesInISEBlock = iseParams.mode == ISEMODE_TRIT  ? 5 :
2790*35238bceSAndroid Build Coastguard Worker                                                 iseParams.mode == ISEMODE_QUINT ? 3 :
2791*35238bceSAndroid Build Coastguard Worker                                                                                   1;
2792*35238bceSAndroid Build Coastguard Worker                 const int numWeights          = computeNumWeights(blockParams);
2793*35238bceSAndroid Build Coastguard Worker 
2794*35238bceSAndroid Build Coastguard Worker                 {
2795*35238bceSAndroid Build Coastguard Worker                     const int numWeightValues           = (int)computeISERangeMax(iseParams) + 1;
2796*35238bceSAndroid Build Coastguard Worker                     const int numBlocks                 = deDivRoundUp32(numWeightValues, numWeights);
2797*35238bceSAndroid Build Coastguard Worker                     NormalBlockISEInputs iseInputs      = generateDefaultISEInputs(blockParams);
2798*35238bceSAndroid Build Coastguard Worker                     iseInputs.weight.isGivenInBlockForm = false;
2799*35238bceSAndroid Build Coastguard Worker 
2800*35238bceSAndroid Build Coastguard Worker                     for (int offset = 0; offset < numValuesInISEBlock; offset++)
2801*35238bceSAndroid Build Coastguard Worker                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2802*35238bceSAndroid Build Coastguard Worker                         {
2803*35238bceSAndroid Build Coastguard Worker                             for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
2804*35238bceSAndroid Build Coastguard Worker                                 iseInputs.weight.value.plain[weightNdx] =
2805*35238bceSAndroid Build Coastguard Worker                                     (blockNdx * numWeights + weightNdx + offset) % numWeightValues;
2806*35238bceSAndroid Build Coastguard Worker 
2807*35238bceSAndroid Build Coastguard Worker                             generateNormalBlock(blockParams, blockSize.x(), blockSize.y(), iseInputs)
2808*35238bceSAndroid Build Coastguard Worker                                 .pushBytesToVector(dst);
2809*35238bceSAndroid Build Coastguard Worker                         }
2810*35238bceSAndroid Build Coastguard Worker                 }
2811*35238bceSAndroid Build Coastguard Worker 
2812*35238bceSAndroid Build Coastguard Worker                 if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
2813*35238bceSAndroid Build Coastguard Worker                 {
2814*35238bceSAndroid Build Coastguard Worker                     NormalBlockISEInputs iseInputs      = generateDefaultISEInputs(blockParams);
2815*35238bceSAndroid Build Coastguard Worker                     iseInputs.weight.isGivenInBlockForm = true;
2816*35238bceSAndroid Build Coastguard Worker 
2817*35238bceSAndroid Build Coastguard Worker                     const int numTQValues          = 1 << (iseParams.mode == ISEMODE_TRIT ? 8 : 7);
2818*35238bceSAndroid Build Coastguard Worker                     const int numISEBlocksPerBlock = deDivRoundUp32(numWeights, numValuesInISEBlock);
2819*35238bceSAndroid Build Coastguard Worker                     const int numBlocks            = deDivRoundUp32(numTQValues, numISEBlocksPerBlock);
2820*35238bceSAndroid Build Coastguard Worker 
2821*35238bceSAndroid Build Coastguard Worker                     for (int offset = 0; offset < numValuesInISEBlock; offset++)
2822*35238bceSAndroid Build Coastguard Worker                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2823*35238bceSAndroid Build Coastguard Worker                         {
2824*35238bceSAndroid Build Coastguard Worker                             for (int iseBlockNdx = 0; iseBlockNdx < numISEBlocksPerBlock; iseBlockNdx++)
2825*35238bceSAndroid Build Coastguard Worker                             {
2826*35238bceSAndroid Build Coastguard Worker                                 for (int i = 0; i < numValuesInISEBlock; i++)
2827*35238bceSAndroid Build Coastguard Worker                                     iseInputs.weight.value.block[iseBlockNdx].bitValues[i] = 0;
2828*35238bceSAndroid Build Coastguard Worker                                 iseInputs.weight.value.block[iseBlockNdx].tOrQValue =
2829*35238bceSAndroid Build Coastguard Worker                                     (blockNdx * numISEBlocksPerBlock + iseBlockNdx + offset) % numTQValues;
2830*35238bceSAndroid Build Coastguard Worker                             }
2831*35238bceSAndroid Build Coastguard Worker 
2832*35238bceSAndroid Build Coastguard Worker                             generateNormalBlock(blockParams, blockSize.x(), blockSize.y(), iseInputs)
2833*35238bceSAndroid Build Coastguard Worker                                 .pushBytesToVector(dst);
2834*35238bceSAndroid Build Coastguard Worker                         }
2835*35238bceSAndroid Build Coastguard Worker                 }
2836*35238bceSAndroid Build Coastguard Worker             }
2837*35238bceSAndroid Build Coastguard Worker 
2838*35238bceSAndroid Build Coastguard Worker             break;
2839*35238bceSAndroid Build Coastguard Worker         }
2840*35238bceSAndroid Build Coastguard Worker 
2841*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CEMS:
2842*35238bceSAndroid Build Coastguard Worker         // For each plane count & partition count combination, generate all color endpoint mode combinations.
2843*35238bceSAndroid Build Coastguard Worker         {
2844*35238bceSAndroid Build Coastguard Worker             for (int isDualPlane = 0; isDualPlane <= 1; isDualPlane++)
2845*35238bceSAndroid Build Coastguard Worker                 for (int numPartitions = 1; numPartitions <= (isDualPlane != 0 ? 3 : 4); numPartitions++)
2846*35238bceSAndroid Build Coastguard Worker                 {
2847*35238bceSAndroid Build Coastguard Worker                     // Multi-partition, single-CEM mode.
2848*35238bceSAndroid Build Coastguard Worker                     if (numPartitions > 1)
2849*35238bceSAndroid Build Coastguard Worker                     {
2850*35238bceSAndroid Build Coastguard Worker                         for (uint32_t singleCem = 0; singleCem < 16; singleCem++)
2851*35238bceSAndroid Build Coastguard Worker                         {
2852*35238bceSAndroid Build Coastguard Worker                             NormalBlockParams blockParams;
2853*35238bceSAndroid Build Coastguard Worker                             blockParams.weightGridWidth          = 4;
2854*35238bceSAndroid Build Coastguard Worker                             blockParams.weightGridHeight         = 4;
2855*35238bceSAndroid Build Coastguard Worker                             blockParams.isDualPlane              = isDualPlane != 0;
2856*35238bceSAndroid Build Coastguard Worker                             blockParams.ccs                      = 0;
2857*35238bceSAndroid Build Coastguard Worker                             blockParams.numPartitions            = numPartitions;
2858*35238bceSAndroid Build Coastguard Worker                             blockParams.isMultiPartSingleCemMode = true;
2859*35238bceSAndroid Build Coastguard Worker                             blockParams.colorEndpointModes[0]    = singleCem;
2860*35238bceSAndroid Build Coastguard Worker                             blockParams.partitionSeed            = 634;
2861*35238bceSAndroid Build Coastguard Worker 
2862*35238bceSAndroid Build Coastguard Worker                             for (int iseParamsNdx = 0; iseParamsNdx < DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates);
2863*35238bceSAndroid Build Coastguard Worker                                  iseParamsNdx++)
2864*35238bceSAndroid Build Coastguard Worker                             {
2865*35238bceSAndroid Build Coastguard Worker                                 blockParams.weightISEParams = s_weightISEParamsCandidates[iseParamsNdx];
2866*35238bceSAndroid Build Coastguard Worker                                 if (isValidBlockParams(blockParams, blockSize.x(), blockSize.y()))
2867*35238bceSAndroid Build Coastguard Worker                                 {
2868*35238bceSAndroid Build Coastguard Worker                                     generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
2869*35238bceSAndroid Build Coastguard Worker                                                         generateDefaultISEInputs(blockParams))
2870*35238bceSAndroid Build Coastguard Worker                                         .pushBytesToVector(dst);
2871*35238bceSAndroid Build Coastguard Worker                                     break;
2872*35238bceSAndroid Build Coastguard Worker                                 }
2873*35238bceSAndroid Build Coastguard Worker                             }
2874*35238bceSAndroid Build Coastguard Worker                         }
2875*35238bceSAndroid Build Coastguard Worker                     }
2876*35238bceSAndroid Build Coastguard Worker 
2877*35238bceSAndroid Build Coastguard Worker                     // Separate-CEM mode.
2878*35238bceSAndroid Build Coastguard Worker                     for (uint32_t cem0 = 0; cem0 < 16; cem0++)
2879*35238bceSAndroid Build Coastguard Worker                         for (uint32_t cem1 = 0; cem1 < (numPartitions >= 2 ? 16u : 1u); cem1++)
2880*35238bceSAndroid Build Coastguard Worker                             for (uint32_t cem2 = 0; cem2 < (numPartitions >= 3 ? 16u : 1u); cem2++)
2881*35238bceSAndroid Build Coastguard Worker                                 for (uint32_t cem3 = 0; cem3 < (numPartitions >= 4 ? 16u : 1u); cem3++)
2882*35238bceSAndroid Build Coastguard Worker                                 {
2883*35238bceSAndroid Build Coastguard Worker                                     NormalBlockParams blockParams;
2884*35238bceSAndroid Build Coastguard Worker                                     blockParams.weightGridWidth          = 4;
2885*35238bceSAndroid Build Coastguard Worker                                     blockParams.weightGridHeight         = 4;
2886*35238bceSAndroid Build Coastguard Worker                                     blockParams.isDualPlane              = isDualPlane != 0;
2887*35238bceSAndroid Build Coastguard Worker                                     blockParams.ccs                      = 0;
2888*35238bceSAndroid Build Coastguard Worker                                     blockParams.numPartitions            = numPartitions;
2889*35238bceSAndroid Build Coastguard Worker                                     blockParams.isMultiPartSingleCemMode = false;
2890*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[0]    = cem0;
2891*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[1]    = cem1;
2892*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[2]    = cem2;
2893*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[3]    = cem3;
2894*35238bceSAndroid Build Coastguard Worker                                     blockParams.partitionSeed            = 634;
2895*35238bceSAndroid Build Coastguard Worker 
2896*35238bceSAndroid Build Coastguard Worker                                     {
2897*35238bceSAndroid Build Coastguard Worker                                         const uint32_t minCem =
2898*35238bceSAndroid Build Coastguard Worker                                             *std::min_element(&blockParams.colorEndpointModes[0],
2899*35238bceSAndroid Build Coastguard Worker                                                               &blockParams.colorEndpointModes[numPartitions]);
2900*35238bceSAndroid Build Coastguard Worker                                         const uint32_t maxCem =
2901*35238bceSAndroid Build Coastguard Worker                                             *std::max_element(&blockParams.colorEndpointModes[0],
2902*35238bceSAndroid Build Coastguard Worker                                                               &blockParams.colorEndpointModes[numPartitions]);
2903*35238bceSAndroid Build Coastguard Worker                                         const uint32_t minCemClass = minCem / 4;
2904*35238bceSAndroid Build Coastguard Worker                                         const uint32_t maxCemClass = maxCem / 4;
2905*35238bceSAndroid Build Coastguard Worker 
2906*35238bceSAndroid Build Coastguard Worker                                         if (maxCemClass - minCemClass > 1)
2907*35238bceSAndroid Build Coastguard Worker                                             continue;
2908*35238bceSAndroid Build Coastguard Worker                                     }
2909*35238bceSAndroid Build Coastguard Worker 
2910*35238bceSAndroid Build Coastguard Worker                                     for (int iseParamsNdx = 0;
2911*35238bceSAndroid Build Coastguard Worker                                          iseParamsNdx < DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates); iseParamsNdx++)
2912*35238bceSAndroid Build Coastguard Worker                                     {
2913*35238bceSAndroid Build Coastguard Worker                                         blockParams.weightISEParams = s_weightISEParamsCandidates[iseParamsNdx];
2914*35238bceSAndroid Build Coastguard Worker                                         if (isValidBlockParams(blockParams, blockSize.x(), blockSize.y()))
2915*35238bceSAndroid Build Coastguard Worker                                         {
2916*35238bceSAndroid Build Coastguard Worker                                             generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
2917*35238bceSAndroid Build Coastguard Worker                                                                 generateDefaultISEInputs(blockParams))
2918*35238bceSAndroid Build Coastguard Worker                                                 .pushBytesToVector(dst);
2919*35238bceSAndroid Build Coastguard Worker                                             break;
2920*35238bceSAndroid Build Coastguard Worker                                         }
2921*35238bceSAndroid Build Coastguard Worker                                     }
2922*35238bceSAndroid Build Coastguard Worker                                 }
2923*35238bceSAndroid Build Coastguard Worker                 }
2924*35238bceSAndroid Build Coastguard Worker 
2925*35238bceSAndroid Build Coastguard Worker             break;
2926*35238bceSAndroid Build Coastguard Worker         }
2927*35238bceSAndroid Build Coastguard Worker 
2928*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_PARTITION_SEED:
2929*35238bceSAndroid Build Coastguard Worker         // Test all partition seeds ("partition pattern indices").
2930*35238bceSAndroid Build Coastguard Worker         {
2931*35238bceSAndroid Build Coastguard Worker             for (int numPartitions = 2; numPartitions <= 4; numPartitions++)
2932*35238bceSAndroid Build Coastguard Worker                 for (uint32_t partitionSeed = 0; partitionSeed < 1 << 10; partitionSeed++)
2933*35238bceSAndroid Build Coastguard Worker                 {
2934*35238bceSAndroid Build Coastguard Worker                     NormalBlockParams blockParams;
2935*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridWidth          = 4;
2936*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridHeight         = 4;
2937*35238bceSAndroid Build Coastguard Worker                     blockParams.weightISEParams          = ISEParams(ISEMODE_PLAIN_BIT, 2);
2938*35238bceSAndroid Build Coastguard Worker                     blockParams.isDualPlane              = false;
2939*35238bceSAndroid Build Coastguard Worker                     blockParams.numPartitions            = numPartitions;
2940*35238bceSAndroid Build Coastguard Worker                     blockParams.isMultiPartSingleCemMode = true;
2941*35238bceSAndroid Build Coastguard Worker                     blockParams.colorEndpointModes[0]    = 0;
2942*35238bceSAndroid Build Coastguard Worker                     blockParams.partitionSeed            = partitionSeed;
2943*35238bceSAndroid Build Coastguard Worker 
2944*35238bceSAndroid Build Coastguard Worker                     generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
2945*35238bceSAndroid Build Coastguard Worker                                         generateDefaultISEInputs(blockParams))
2946*35238bceSAndroid Build Coastguard Worker                         .pushBytesToVector(dst);
2947*35238bceSAndroid Build Coastguard Worker                 }
2948*35238bceSAndroid Build Coastguard Worker 
2949*35238bceSAndroid Build Coastguard Worker             break;
2950*35238bceSAndroid Build Coastguard Worker         }
2951*35238bceSAndroid Build Coastguard Worker 
2952*35238bceSAndroid Build Coastguard Worker     // \note Fall-through.
2953*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_LDR:
2954*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15:
2955*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15:
2956*35238bceSAndroid Build Coastguard Worker         // For each endpoint mode, for each pair of components in the endpoint value, test 10x10 combinations of values for that pair.
2957*35238bceSAndroid Build Coastguard Worker         // \note Separate modes for HDR and mode 15 due to different color scales and biases.
2958*35238bceSAndroid Build Coastguard Worker         {
2959*35238bceSAndroid Build Coastguard Worker             for (uint32_t cem = 0; cem < 16; cem++)
2960*35238bceSAndroid Build Coastguard Worker             {
2961*35238bceSAndroid Build Coastguard Worker                 const bool isHDRCem = cem == 2 || cem == 3 || cem == 7 || cem == 11 || cem == 14 || cem == 15;
2962*35238bceSAndroid Build Coastguard Worker 
2963*35238bceSAndroid Build Coastguard Worker                 if ((testType == BLOCK_TEST_TYPE_ENDPOINT_VALUE_LDR && isHDRCem) ||
2964*35238bceSAndroid Build Coastguard Worker                     (testType == BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15 && (!isHDRCem || cem == 15)) ||
2965*35238bceSAndroid Build Coastguard Worker                     (testType == BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15 && cem != 15))
2966*35238bceSAndroid Build Coastguard Worker                     continue;
2967*35238bceSAndroid Build Coastguard Worker 
2968*35238bceSAndroid Build Coastguard Worker                 NormalBlockParams blockParams;
2969*35238bceSAndroid Build Coastguard Worker                 blockParams.weightGridWidth       = 3;
2970*35238bceSAndroid Build Coastguard Worker                 blockParams.weightGridHeight      = 4;
2971*35238bceSAndroid Build Coastguard Worker                 blockParams.weightISEParams       = ISEParams(ISEMODE_PLAIN_BIT, 2);
2972*35238bceSAndroid Build Coastguard Worker                 blockParams.isDualPlane           = false;
2973*35238bceSAndroid Build Coastguard Worker                 blockParams.numPartitions         = 1;
2974*35238bceSAndroid Build Coastguard Worker                 blockParams.colorEndpointModes[0] = cem;
2975*35238bceSAndroid Build Coastguard Worker 
2976*35238bceSAndroid Build Coastguard Worker                 {
2977*35238bceSAndroid Build Coastguard Worker                     const int numBitsForEndpoints = computeNumBitsForColorEndpoints(blockParams);
2978*35238bceSAndroid Build Coastguard Worker                     const int numEndpointParts    = computeNumColorEndpointValues(cem);
2979*35238bceSAndroid Build Coastguard Worker                     const ISEParams endpointISE   = computeMaximumRangeISEParams(numBitsForEndpoints, numEndpointParts);
2980*35238bceSAndroid Build Coastguard Worker                     const int endpointISERangeMax = computeISERangeMax(endpointISE);
2981*35238bceSAndroid Build Coastguard Worker 
2982*35238bceSAndroid Build Coastguard Worker                     for (int endpointPartNdx0 = 0; endpointPartNdx0 < numEndpointParts; endpointPartNdx0++)
2983*35238bceSAndroid Build Coastguard Worker                         for (int endpointPartNdx1 = endpointPartNdx0 + 1; endpointPartNdx1 < numEndpointParts;
2984*35238bceSAndroid Build Coastguard Worker                              endpointPartNdx1++)
2985*35238bceSAndroid Build Coastguard Worker                         {
2986*35238bceSAndroid Build Coastguard Worker                             NormalBlockISEInputs iseInputs = generateDefaultISEInputs(blockParams);
2987*35238bceSAndroid Build Coastguard Worker                             const int numEndpointValues    = de::min(10, endpointISERangeMax + 1);
2988*35238bceSAndroid Build Coastguard Worker 
2989*35238bceSAndroid Build Coastguard Worker                             for (int endpointValueNdx0 = 0; endpointValueNdx0 < numEndpointValues; endpointValueNdx0++)
2990*35238bceSAndroid Build Coastguard Worker                                 for (int endpointValueNdx1 = 0; endpointValueNdx1 < numEndpointValues;
2991*35238bceSAndroid Build Coastguard Worker                                      endpointValueNdx1++)
2992*35238bceSAndroid Build Coastguard Worker                                 {
2993*35238bceSAndroid Build Coastguard Worker                                     const int endpointValue0 =
2994*35238bceSAndroid Build Coastguard Worker                                         endpointValueNdx0 * endpointISERangeMax / (numEndpointValues - 1);
2995*35238bceSAndroid Build Coastguard Worker                                     const int endpointValue1 =
2996*35238bceSAndroid Build Coastguard Worker                                         endpointValueNdx1 * endpointISERangeMax / (numEndpointValues - 1);
2997*35238bceSAndroid Build Coastguard Worker 
2998*35238bceSAndroid Build Coastguard Worker                                     iseInputs.endpoint.value.plain[endpointPartNdx0] = endpointValue0;
2999*35238bceSAndroid Build Coastguard Worker                                     iseInputs.endpoint.value.plain[endpointPartNdx1] = endpointValue1;
3000*35238bceSAndroid Build Coastguard Worker 
3001*35238bceSAndroid Build Coastguard Worker                                     generateNormalBlock(blockParams, blockSize.x(), blockSize.y(), iseInputs)
3002*35238bceSAndroid Build Coastguard Worker                                         .pushBytesToVector(dst);
3003*35238bceSAndroid Build Coastguard Worker                                 }
3004*35238bceSAndroid Build Coastguard Worker                         }
3005*35238bceSAndroid Build Coastguard Worker                 }
3006*35238bceSAndroid Build Coastguard Worker             }
3007*35238bceSAndroid Build Coastguard Worker 
3008*35238bceSAndroid Build Coastguard Worker             break;
3009*35238bceSAndroid Build Coastguard Worker         }
3010*35238bceSAndroid Build Coastguard Worker 
3011*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_ISE:
3012*35238bceSAndroid Build Coastguard Worker         // Similar to BLOCK_TEST_TYPE_WEIGHT_ISE, see above.
3013*35238bceSAndroid Build Coastguard Worker         {
3014*35238bceSAndroid Build Coastguard Worker             static const uint32_t endpointRangeMaximums[] = {5, 9, 11, 19, 23, 39, 47, 79, 95, 159, 191};
3015*35238bceSAndroid Build Coastguard Worker 
3016*35238bceSAndroid Build Coastguard Worker             for (int endpointRangeNdx = 0; endpointRangeNdx < DE_LENGTH_OF_ARRAY(endpointRangeMaximums);
3017*35238bceSAndroid Build Coastguard Worker                  endpointRangeNdx++)
3018*35238bceSAndroid Build Coastguard Worker             {
3019*35238bceSAndroid Build Coastguard Worker                 bool validCaseGenerated = false;
3020*35238bceSAndroid Build Coastguard Worker 
3021*35238bceSAndroid Build Coastguard Worker                 for (int numPartitions = 1; !validCaseGenerated && numPartitions <= 4; numPartitions++)
3022*35238bceSAndroid Build Coastguard Worker                     for (int isDual = 0; !validCaseGenerated && isDual <= 1; isDual++)
3023*35238bceSAndroid Build Coastguard Worker                         for (int weightISEParamsNdx = 0;
3024*35238bceSAndroid Build Coastguard Worker                              !validCaseGenerated &&
3025*35238bceSAndroid Build Coastguard Worker                              weightISEParamsNdx < DE_LENGTH_OF_ARRAY(s_weightISEParamsCandidates);
3026*35238bceSAndroid Build Coastguard Worker                              weightISEParamsNdx++)
3027*35238bceSAndroid Build Coastguard Worker                             for (int weightGridWidth = 2; !validCaseGenerated && weightGridWidth <= 12;
3028*35238bceSAndroid Build Coastguard Worker                                  weightGridWidth++)
3029*35238bceSAndroid Build Coastguard Worker                                 for (int weightGridHeight = 2; !validCaseGenerated && weightGridHeight <= 12;
3030*35238bceSAndroid Build Coastguard Worker                                      weightGridHeight++)
3031*35238bceSAndroid Build Coastguard Worker                                 {
3032*35238bceSAndroid Build Coastguard Worker                                     NormalBlockParams blockParams;
3033*35238bceSAndroid Build Coastguard Worker                                     blockParams.weightGridWidth  = weightGridWidth;
3034*35238bceSAndroid Build Coastguard Worker                                     blockParams.weightGridHeight = weightGridHeight;
3035*35238bceSAndroid Build Coastguard Worker                                     blockParams.weightISEParams  = s_weightISEParamsCandidates[weightISEParamsNdx];
3036*35238bceSAndroid Build Coastguard Worker                                     blockParams.isDualPlane      = isDual != 0;
3037*35238bceSAndroid Build Coastguard Worker                                     blockParams.ccs              = 0;
3038*35238bceSAndroid Build Coastguard Worker                                     blockParams.numPartitions    = numPartitions;
3039*35238bceSAndroid Build Coastguard Worker                                     blockParams.isMultiPartSingleCemMode = true;
3040*35238bceSAndroid Build Coastguard Worker                                     blockParams.colorEndpointModes[0]    = 12;
3041*35238bceSAndroid Build Coastguard Worker                                     blockParams.partitionSeed            = 634;
3042*35238bceSAndroid Build Coastguard Worker 
3043*35238bceSAndroid Build Coastguard Worker                                     if (isValidBlockParams(blockParams, blockSize.x(), blockSize.y()))
3044*35238bceSAndroid Build Coastguard Worker                                     {
3045*35238bceSAndroid Build Coastguard Worker                                         const ISEParams endpointISEParams = computeMaximumRangeISEParams(
3046*35238bceSAndroid Build Coastguard Worker                                             computeNumBitsForColorEndpoints(blockParams),
3047*35238bceSAndroid Build Coastguard Worker                                             computeNumColorEndpointValues(&blockParams.colorEndpointModes[0],
3048*35238bceSAndroid Build Coastguard Worker                                                                           numPartitions, true));
3049*35238bceSAndroid Build Coastguard Worker 
3050*35238bceSAndroid Build Coastguard Worker                                         if (computeISERangeMax(endpointISEParams) ==
3051*35238bceSAndroid Build Coastguard Worker                                             endpointRangeMaximums[endpointRangeNdx])
3052*35238bceSAndroid Build Coastguard Worker                                         {
3053*35238bceSAndroid Build Coastguard Worker                                             validCaseGenerated = true;
3054*35238bceSAndroid Build Coastguard Worker 
3055*35238bceSAndroid Build Coastguard Worker                                             const int numColorEndpoints = computeNumColorEndpointValues(
3056*35238bceSAndroid Build Coastguard Worker                                                 &blockParams.colorEndpointModes[0], numPartitions,
3057*35238bceSAndroid Build Coastguard Worker                                                 blockParams.isMultiPartSingleCemMode);
3058*35238bceSAndroid Build Coastguard Worker                                             const int numValuesInISEBlock = endpointISEParams.mode == ISEMODE_TRIT ? 5 :
3059*35238bceSAndroid Build Coastguard Worker                                                                             endpointISEParams.mode == ISEMODE_QUINT ?
3060*35238bceSAndroid Build Coastguard Worker                                                                                                                      3 :
3061*35238bceSAndroid Build Coastguard Worker                                                                                                                      1;
3062*35238bceSAndroid Build Coastguard Worker 
3063*35238bceSAndroid Build Coastguard Worker                                             {
3064*35238bceSAndroid Build Coastguard Worker                                                 const int numColorEndpointValues =
3065*35238bceSAndroid Build Coastguard Worker                                                     (int)computeISERangeMax(endpointISEParams) + 1;
3066*35238bceSAndroid Build Coastguard Worker                                                 const int numBlocks =
3067*35238bceSAndroid Build Coastguard Worker                                                     deDivRoundUp32(numColorEndpointValues, numColorEndpoints);
3068*35238bceSAndroid Build Coastguard Worker                                                 NormalBlockISEInputs iseInputs = generateDefaultISEInputs(blockParams);
3069*35238bceSAndroid Build Coastguard Worker                                                 iseInputs.endpoint.isGivenInBlockForm = false;
3070*35238bceSAndroid Build Coastguard Worker 
3071*35238bceSAndroid Build Coastguard Worker                                                 for (int offset = 0; offset < numValuesInISEBlock; offset++)
3072*35238bceSAndroid Build Coastguard Worker                                                     for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
3073*35238bceSAndroid Build Coastguard Worker                                                     {
3074*35238bceSAndroid Build Coastguard Worker                                                         for (int endpointNdx = 0; endpointNdx < numColorEndpoints;
3075*35238bceSAndroid Build Coastguard Worker                                                              endpointNdx++)
3076*35238bceSAndroid Build Coastguard Worker                                                             iseInputs.endpoint.value.plain[endpointNdx] =
3077*35238bceSAndroid Build Coastguard Worker                                                                 (blockNdx * numColorEndpoints + endpointNdx + offset) %
3078*35238bceSAndroid Build Coastguard Worker                                                                 numColorEndpointValues;
3079*35238bceSAndroid Build Coastguard Worker 
3080*35238bceSAndroid Build Coastguard Worker                                                         generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
3081*35238bceSAndroid Build Coastguard Worker                                                                             iseInputs)
3082*35238bceSAndroid Build Coastguard Worker                                                             .pushBytesToVector(dst);
3083*35238bceSAndroid Build Coastguard Worker                                                     }
3084*35238bceSAndroid Build Coastguard Worker                                             }
3085*35238bceSAndroid Build Coastguard Worker 
3086*35238bceSAndroid Build Coastguard Worker                                             if (endpointISEParams.mode == ISEMODE_TRIT ||
3087*35238bceSAndroid Build Coastguard Worker                                                 endpointISEParams.mode == ISEMODE_QUINT)
3088*35238bceSAndroid Build Coastguard Worker                                             {
3089*35238bceSAndroid Build Coastguard Worker                                                 NormalBlockISEInputs iseInputs = generateDefaultISEInputs(blockParams);
3090*35238bceSAndroid Build Coastguard Worker                                                 iseInputs.endpoint.isGivenInBlockForm = true;
3091*35238bceSAndroid Build Coastguard Worker 
3092*35238bceSAndroid Build Coastguard Worker                                                 const int numTQValues =
3093*35238bceSAndroid Build Coastguard Worker                                                     1 << (endpointISEParams.mode == ISEMODE_TRIT ? 8 : 7);
3094*35238bceSAndroid Build Coastguard Worker                                                 const int numISEBlocksPerBlock =
3095*35238bceSAndroid Build Coastguard Worker                                                     deDivRoundUp32(numColorEndpoints, numValuesInISEBlock);
3096*35238bceSAndroid Build Coastguard Worker                                                 const int numBlocks = deDivRoundUp32(numTQValues, numISEBlocksPerBlock);
3097*35238bceSAndroid Build Coastguard Worker 
3098*35238bceSAndroid Build Coastguard Worker                                                 for (int offset = 0; offset < numValuesInISEBlock; offset++)
3099*35238bceSAndroid Build Coastguard Worker                                                     for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
3100*35238bceSAndroid Build Coastguard Worker                                                     {
3101*35238bceSAndroid Build Coastguard Worker                                                         for (int iseBlockNdx = 0; iseBlockNdx < numISEBlocksPerBlock;
3102*35238bceSAndroid Build Coastguard Worker                                                              iseBlockNdx++)
3103*35238bceSAndroid Build Coastguard Worker                                                         {
3104*35238bceSAndroid Build Coastguard Worker                                                             for (int i = 0; i < numValuesInISEBlock; i++)
3105*35238bceSAndroid Build Coastguard Worker                                                                 iseInputs.endpoint.value.block[iseBlockNdx]
3106*35238bceSAndroid Build Coastguard Worker                                                                     .bitValues[i] = 0;
3107*35238bceSAndroid Build Coastguard Worker                                                             iseInputs.endpoint.value.block[iseBlockNdx].tOrQValue =
3108*35238bceSAndroid Build Coastguard Worker                                                                 (blockNdx * numISEBlocksPerBlock + iseBlockNdx +
3109*35238bceSAndroid Build Coastguard Worker                                                                  offset) %
3110*35238bceSAndroid Build Coastguard Worker                                                                 numTQValues;
3111*35238bceSAndroid Build Coastguard Worker                                                         }
3112*35238bceSAndroid Build Coastguard Worker 
3113*35238bceSAndroid Build Coastguard Worker                                                         generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
3114*35238bceSAndroid Build Coastguard Worker                                                                             iseInputs)
3115*35238bceSAndroid Build Coastguard Worker                                                             .pushBytesToVector(dst);
3116*35238bceSAndroid Build Coastguard Worker                                                     }
3117*35238bceSAndroid Build Coastguard Worker                                             }
3118*35238bceSAndroid Build Coastguard Worker                                         }
3119*35238bceSAndroid Build Coastguard Worker                                     }
3120*35238bceSAndroid Build Coastguard Worker                                 }
3121*35238bceSAndroid Build Coastguard Worker 
3122*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(validCaseGenerated);
3123*35238bceSAndroid Build Coastguard Worker             }
3124*35238bceSAndroid Build Coastguard Worker 
3125*35238bceSAndroid Build Coastguard Worker             break;
3126*35238bceSAndroid Build Coastguard Worker         }
3127*35238bceSAndroid Build Coastguard Worker 
3128*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CCS:
3129*35238bceSAndroid Build Coastguard Worker         // For all partition counts, test all values of the CCS (color component selector).
3130*35238bceSAndroid Build Coastguard Worker         {
3131*35238bceSAndroid Build Coastguard Worker             for (int numPartitions = 1; numPartitions <= 3; numPartitions++)
3132*35238bceSAndroid Build Coastguard Worker                 for (uint32_t ccs = 0; ccs < 4; ccs++)
3133*35238bceSAndroid Build Coastguard Worker                 {
3134*35238bceSAndroid Build Coastguard Worker                     NormalBlockParams blockParams;
3135*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridWidth          = 3;
3136*35238bceSAndroid Build Coastguard Worker                     blockParams.weightGridHeight         = 3;
3137*35238bceSAndroid Build Coastguard Worker                     blockParams.weightISEParams          = ISEParams(ISEMODE_PLAIN_BIT, 2);
3138*35238bceSAndroid Build Coastguard Worker                     blockParams.isDualPlane              = true;
3139*35238bceSAndroid Build Coastguard Worker                     blockParams.ccs                      = ccs;
3140*35238bceSAndroid Build Coastguard Worker                     blockParams.numPartitions            = numPartitions;
3141*35238bceSAndroid Build Coastguard Worker                     blockParams.isMultiPartSingleCemMode = true;
3142*35238bceSAndroid Build Coastguard Worker                     blockParams.colorEndpointModes[0]    = 8;
3143*35238bceSAndroid Build Coastguard Worker                     blockParams.partitionSeed            = 634;
3144*35238bceSAndroid Build Coastguard Worker 
3145*35238bceSAndroid Build Coastguard Worker                     generateNormalBlock(blockParams, blockSize.x(), blockSize.y(),
3146*35238bceSAndroid Build Coastguard Worker                                         generateDefaultISEInputs(blockParams))
3147*35238bceSAndroid Build Coastguard Worker                         .pushBytesToVector(dst);
3148*35238bceSAndroid Build Coastguard Worker                 }
3149*35238bceSAndroid Build Coastguard Worker 
3150*35238bceSAndroid Build Coastguard Worker             break;
3151*35238bceSAndroid Build Coastguard Worker         }
3152*35238bceSAndroid Build Coastguard Worker 
3153*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_RANDOM:
3154*35238bceSAndroid Build Coastguard Worker         // Generate a number of random (including invalid) blocks.
3155*35238bceSAndroid Build Coastguard Worker         {
3156*35238bceSAndroid Build Coastguard Worker             const int numBlocks = 16384;
3157*35238bceSAndroid Build Coastguard Worker             const uint32_t seed = 1;
3158*35238bceSAndroid Build Coastguard Worker 
3159*35238bceSAndroid Build Coastguard Worker             dst.resize(numBlocks * BLOCK_SIZE_BYTES);
3160*35238bceSAndroid Build Coastguard Worker 
3161*35238bceSAndroid Build Coastguard Worker             generateRandomBlocks(&dst[0], numBlocks, format, seed);
3162*35238bceSAndroid Build Coastguard Worker 
3163*35238bceSAndroid Build Coastguard Worker             break;
3164*35238bceSAndroid Build Coastguard Worker         }
3165*35238bceSAndroid Build Coastguard Worker 
3166*35238bceSAndroid Build Coastguard Worker     default:
3167*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
3168*35238bceSAndroid Build Coastguard Worker     }
3169*35238bceSAndroid Build Coastguard Worker }
3170*35238bceSAndroid Build Coastguard Worker 
generateRandomBlocks(uint8_t * dst,size_t numBlocks,CompressedTexFormat format,uint32_t seed)3171*35238bceSAndroid Build Coastguard Worker void generateRandomBlocks(uint8_t *dst, size_t numBlocks, CompressedTexFormat format, uint32_t seed)
3172*35238bceSAndroid Build Coastguard Worker {
3173*35238bceSAndroid Build Coastguard Worker     const IVec3 blockSize = getBlockPixelSize(format);
3174*35238bceSAndroid Build Coastguard Worker     de::Random rnd(seed);
3175*35238bceSAndroid Build Coastguard Worker     size_t numBlocksGenerated = 0;
3176*35238bceSAndroid Build Coastguard Worker 
3177*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isAstcFormat(format));
3178*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockSize.z() == 1);
3179*35238bceSAndroid Build Coastguard Worker 
3180*35238bceSAndroid Build Coastguard Worker     for (numBlocksGenerated = 0; numBlocksGenerated < numBlocks; numBlocksGenerated++)
3181*35238bceSAndroid Build Coastguard Worker     {
3182*35238bceSAndroid Build Coastguard Worker         uint8_t *const curBlockPtr = dst + numBlocksGenerated * BLOCK_SIZE_BYTES;
3183*35238bceSAndroid Build Coastguard Worker 
3184*35238bceSAndroid Build Coastguard Worker         generateRandomBlock(curBlockPtr, blockSize, rnd);
3185*35238bceSAndroid Build Coastguard Worker     }
3186*35238bceSAndroid Build Coastguard Worker }
3187*35238bceSAndroid Build Coastguard Worker 
generateRandomValidBlocks(uint8_t * dst,size_t numBlocks,CompressedTexFormat format,TexDecompressionParams::AstcMode mode,uint32_t seed)3188*35238bceSAndroid Build Coastguard Worker void generateRandomValidBlocks(uint8_t *dst, size_t numBlocks, CompressedTexFormat format,
3189*35238bceSAndroid Build Coastguard Worker                                TexDecompressionParams::AstcMode mode, uint32_t seed)
3190*35238bceSAndroid Build Coastguard Worker {
3191*35238bceSAndroid Build Coastguard Worker     const IVec3 blockSize = getBlockPixelSize(format);
3192*35238bceSAndroid Build Coastguard Worker     de::Random rnd(seed);
3193*35238bceSAndroid Build Coastguard Worker     size_t numBlocksGenerated = 0;
3194*35238bceSAndroid Build Coastguard Worker 
3195*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isAstcFormat(format));
3196*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockSize.z() == 1);
3197*35238bceSAndroid Build Coastguard Worker 
3198*35238bceSAndroid Build Coastguard Worker     for (numBlocksGenerated = 0; numBlocksGenerated < numBlocks; numBlocksGenerated++)
3199*35238bceSAndroid Build Coastguard Worker     {
3200*35238bceSAndroid Build Coastguard Worker         uint8_t *const curBlockPtr = dst + numBlocksGenerated * BLOCK_SIZE_BYTES;
3201*35238bceSAndroid Build Coastguard Worker 
3202*35238bceSAndroid Build Coastguard Worker         do
3203*35238bceSAndroid Build Coastguard Worker         {
3204*35238bceSAndroid Build Coastguard Worker             generateRandomBlock(curBlockPtr, blockSize, rnd);
3205*35238bceSAndroid Build Coastguard Worker         } while (!isValidBlock(curBlockPtr, format, mode));
3206*35238bceSAndroid Build Coastguard Worker     }
3207*35238bceSAndroid Build Coastguard Worker }
3208*35238bceSAndroid Build Coastguard Worker 
3209*35238bceSAndroid Build Coastguard Worker // Generate a number of trivial blocks to fill unneeded space in a texture.
generateDefaultVoidExtentBlocks(uint8_t * dst,size_t numBlocks)3210*35238bceSAndroid Build Coastguard Worker void generateDefaultVoidExtentBlocks(uint8_t *dst, size_t numBlocks)
3211*35238bceSAndroid Build Coastguard Worker {
3212*35238bceSAndroid Build Coastguard Worker     AssignBlock128 block = generateVoidExtentBlock(VoidExtentParams(false, 0, 0, 0, 0));
3213*35238bceSAndroid Build Coastguard Worker     for (size_t ndx = 0; ndx < numBlocks; ndx++)
3214*35238bceSAndroid Build Coastguard Worker         block.assignToMemory(&dst[ndx * BLOCK_SIZE_BYTES]);
3215*35238bceSAndroid Build Coastguard Worker }
3216*35238bceSAndroid Build Coastguard Worker 
generateDefaultNormalBlocks(uint8_t * dst,size_t numBlocks,int blockWidth,int blockHeight)3217*35238bceSAndroid Build Coastguard Worker void generateDefaultNormalBlocks(uint8_t *dst, size_t numBlocks, int blockWidth, int blockHeight)
3218*35238bceSAndroid Build Coastguard Worker {
3219*35238bceSAndroid Build Coastguard Worker     NormalBlockParams blockParams;
3220*35238bceSAndroid Build Coastguard Worker 
3221*35238bceSAndroid Build Coastguard Worker     blockParams.weightGridWidth       = 3;
3222*35238bceSAndroid Build Coastguard Worker     blockParams.weightGridHeight      = 3;
3223*35238bceSAndroid Build Coastguard Worker     blockParams.weightISEParams       = ISEParams(ISEMODE_PLAIN_BIT, 5);
3224*35238bceSAndroid Build Coastguard Worker     blockParams.isDualPlane           = false;
3225*35238bceSAndroid Build Coastguard Worker     blockParams.numPartitions         = 1;
3226*35238bceSAndroid Build Coastguard Worker     blockParams.colorEndpointModes[0] = 8;
3227*35238bceSAndroid Build Coastguard Worker 
3228*35238bceSAndroid Build Coastguard Worker     NormalBlockISEInputs iseInputs      = generateDefaultISEInputs(blockParams);
3229*35238bceSAndroid Build Coastguard Worker     iseInputs.weight.isGivenInBlockForm = false;
3230*35238bceSAndroid Build Coastguard Worker 
3231*35238bceSAndroid Build Coastguard Worker     const int numWeights     = computeNumWeights(blockParams);
3232*35238bceSAndroid Build Coastguard Worker     const int weightRangeMax = computeISERangeMax(blockParams.weightISEParams);
3233*35238bceSAndroid Build Coastguard Worker 
3234*35238bceSAndroid Build Coastguard Worker     for (size_t blockNdx = 0; blockNdx < numBlocks; blockNdx++)
3235*35238bceSAndroid Build Coastguard Worker     {
3236*35238bceSAndroid Build Coastguard Worker         for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
3237*35238bceSAndroid Build Coastguard Worker             iseInputs.weight.value.plain[weightNdx] =
3238*35238bceSAndroid Build Coastguard Worker                 (uint32_t)((blockNdx * numWeights + weightNdx) * weightRangeMax / (numBlocks * numWeights - 1));
3239*35238bceSAndroid Build Coastguard Worker 
3240*35238bceSAndroid Build Coastguard Worker         generateNormalBlock(blockParams, blockWidth, blockHeight, iseInputs)
3241*35238bceSAndroid Build Coastguard Worker             .assignToMemory(dst + blockNdx * BLOCK_SIZE_BYTES);
3242*35238bceSAndroid Build Coastguard Worker     }
3243*35238bceSAndroid Build Coastguard Worker }
3244*35238bceSAndroid Build Coastguard Worker 
isValidBlock(const uint8_t * data,CompressedTexFormat format,TexDecompressionParams::AstcMode mode)3245*35238bceSAndroid Build Coastguard Worker bool isValidBlock(const uint8_t *data, CompressedTexFormat format, TexDecompressionParams::AstcMode mode)
3246*35238bceSAndroid Build Coastguard Worker {
3247*35238bceSAndroid Build Coastguard Worker     const tcu::IVec3 blockPixelSize = getBlockPixelSize(format);
3248*35238bceSAndroid Build Coastguard Worker     const bool isSRGB               = isAstcSRGBFormat(format);
3249*35238bceSAndroid Build Coastguard Worker     const bool isLDR                = isSRGB || mode == TexDecompressionParams::ASTCMODE_LDR;
3250*35238bceSAndroid Build Coastguard Worker 
3251*35238bceSAndroid Build Coastguard Worker     // sRGB is not supported in HDR mode
3252*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!(mode == TexDecompressionParams::ASTCMODE_HDR && isSRGB));
3253*35238bceSAndroid Build Coastguard Worker 
3254*35238bceSAndroid Build Coastguard Worker     union
3255*35238bceSAndroid Build Coastguard Worker     {
3256*35238bceSAndroid Build Coastguard Worker         uint8_t sRGB[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
3257*35238bceSAndroid Build Coastguard Worker         float linear[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
3258*35238bceSAndroid Build Coastguard Worker     } tmpBuffer;
3259*35238bceSAndroid Build Coastguard Worker     const Block128 blockData(data);
3260*35238bceSAndroid Build Coastguard Worker     const DecompressResult result =
3261*35238bceSAndroid Build Coastguard Worker         decompressBlock((isSRGB ? (void *)&tmpBuffer.sRGB[0] : (void *)&tmpBuffer.linear[0]), blockData,
3262*35238bceSAndroid Build Coastguard Worker                         blockPixelSize.x(), blockPixelSize.y(), isSRGB, isLDR);
3263*35238bceSAndroid Build Coastguard Worker 
3264*35238bceSAndroid Build Coastguard Worker     return result == DECOMPRESS_RESULT_VALID_BLOCK;
3265*35238bceSAndroid Build Coastguard Worker }
3266*35238bceSAndroid Build Coastguard Worker 
decompress(const PixelBufferAccess & dst,const uint8_t * data,CompressedTexFormat format,TexDecompressionParams::AstcMode mode)3267*35238bceSAndroid Build Coastguard Worker void decompress(const PixelBufferAccess &dst, const uint8_t *data, CompressedTexFormat format,
3268*35238bceSAndroid Build Coastguard Worker                 TexDecompressionParams::AstcMode mode)
3269*35238bceSAndroid Build Coastguard Worker {
3270*35238bceSAndroid Build Coastguard Worker     const bool isSRGBFormat = isAstcSRGBFormat(format);
3271*35238bceSAndroid Build Coastguard Worker 
3272*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
3273*35238bceSAndroid Build Coastguard Worker     const tcu::IVec3 blockPixelSize = getBlockPixelSize(format);
3274*35238bceSAndroid Build Coastguard Worker 
3275*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dst.getWidth() == blockPixelSize.x() && dst.getHeight() == blockPixelSize.y() &&
3276*35238bceSAndroid Build Coastguard Worker               dst.getDepth() == blockPixelSize.z());
3277*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(mode == TexDecompressionParams::ASTCMODE_LDR || mode == TexDecompressionParams::ASTCMODE_HDR);
3278*35238bceSAndroid Build Coastguard Worker #endif
3279*35238bceSAndroid Build Coastguard Worker 
3280*35238bceSAndroid Build Coastguard Worker     // sRGB is not supported in HDR mode
3281*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!(mode == TexDecompressionParams::ASTCMODE_HDR && isSRGBFormat));
3282*35238bceSAndroid Build Coastguard Worker 
3283*35238bceSAndroid Build Coastguard Worker     decompress(dst, data, isSRGBFormat, isSRGBFormat || mode == TexDecompressionParams::ASTCMODE_LDR);
3284*35238bceSAndroid Build Coastguard Worker }
3285*35238bceSAndroid Build Coastguard Worker 
getBlockTestTypeName(BlockTestType testType)3286*35238bceSAndroid Build Coastguard Worker const char *getBlockTestTypeName(BlockTestType testType)
3287*35238bceSAndroid Build Coastguard Worker {
3288*35238bceSAndroid Build Coastguard Worker     switch (testType)
3289*35238bceSAndroid Build Coastguard Worker     {
3290*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_LDR:
3291*35238bceSAndroid Build Coastguard Worker         return "void_extent_ldr";
3292*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_HDR:
3293*35238bceSAndroid Build Coastguard Worker         return "void_extent_hdr";
3294*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_GRID:
3295*35238bceSAndroid Build Coastguard Worker         return "weight_grid";
3296*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_ISE:
3297*35238bceSAndroid Build Coastguard Worker         return "weight_ise";
3298*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CEMS:
3299*35238bceSAndroid Build Coastguard Worker         return "color_endpoint_modes";
3300*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_PARTITION_SEED:
3301*35238bceSAndroid Build Coastguard Worker         return "partition_pattern_index";
3302*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_LDR:
3303*35238bceSAndroid Build Coastguard Worker         return "endpoint_value_ldr";
3304*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15:
3305*35238bceSAndroid Build Coastguard Worker         return "endpoint_value_hdr_cem_not_15";
3306*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15:
3307*35238bceSAndroid Build Coastguard Worker         return "endpoint_value_hdr_cem_15";
3308*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_ISE:
3309*35238bceSAndroid Build Coastguard Worker         return "endpoint_ise";
3310*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CCS:
3311*35238bceSAndroid Build Coastguard Worker         return "color_component_selector";
3312*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_RANDOM:
3313*35238bceSAndroid Build Coastguard Worker         return "random";
3314*35238bceSAndroid Build Coastguard Worker     default:
3315*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
3316*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
3317*35238bceSAndroid Build Coastguard Worker     }
3318*35238bceSAndroid Build Coastguard Worker }
3319*35238bceSAndroid Build Coastguard Worker 
getBlockTestTypeDescription(BlockTestType testType)3320*35238bceSAndroid Build Coastguard Worker const char *getBlockTestTypeDescription(BlockTestType testType)
3321*35238bceSAndroid Build Coastguard Worker {
3322*35238bceSAndroid Build Coastguard Worker     switch (testType)
3323*35238bceSAndroid Build Coastguard Worker     {
3324*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_LDR:
3325*35238bceSAndroid Build Coastguard Worker         return "Test void extent block, LDR mode";
3326*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_VOID_EXTENT_HDR:
3327*35238bceSAndroid Build Coastguard Worker         return "Test void extent block, HDR mode";
3328*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_GRID:
3329*35238bceSAndroid Build Coastguard Worker         return "Test combinations of plane count, weight integer sequence encoding parameters, and weight grid size";
3330*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_WEIGHT_ISE:
3331*35238bceSAndroid Build Coastguard Worker         return "Test different integer sequence encoding block values for weight grid";
3332*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CEMS:
3333*35238bceSAndroid Build Coastguard Worker         return "Test different color endpoint mode combinations, combined with different plane and partition counts";
3334*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_PARTITION_SEED:
3335*35238bceSAndroid Build Coastguard Worker         return "Test different partition pattern indices";
3336*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_LDR:
3337*35238bceSAndroid Build Coastguard Worker         return "Test various combinations of each pair of color endpoint values, for each LDR color endpoint mode";
3338*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15:
3339*35238bceSAndroid Build Coastguard Worker         return "Test various combinations of each pair of color endpoint values, for each HDR color endpoint mode "
3340*35238bceSAndroid Build Coastguard Worker                "other than mode 15";
3341*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15:
3342*35238bceSAndroid Build Coastguard Worker         return "Test various combinations of each pair of color endpoint values, HDR color endpoint mode 15";
3343*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_ENDPOINT_ISE:
3344*35238bceSAndroid Build Coastguard Worker         return "Test different integer sequence encoding block values for color endpoints";
3345*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_CCS:
3346*35238bceSAndroid Build Coastguard Worker         return "Test color component selector, for different partition counts";
3347*35238bceSAndroid Build Coastguard Worker     case BLOCK_TEST_TYPE_RANDOM:
3348*35238bceSAndroid Build Coastguard Worker         return "Random block test";
3349*35238bceSAndroid Build Coastguard Worker     default:
3350*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
3351*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
3352*35238bceSAndroid Build Coastguard Worker     }
3353*35238bceSAndroid Build Coastguard Worker }
3354*35238bceSAndroid Build Coastguard Worker 
isBlockTestTypeHDROnly(BlockTestType testType)3355*35238bceSAndroid Build Coastguard Worker bool isBlockTestTypeHDROnly(BlockTestType testType)
3356*35238bceSAndroid Build Coastguard Worker {
3357*35238bceSAndroid Build Coastguard Worker     return testType == BLOCK_TEST_TYPE_VOID_EXTENT_HDR || testType == BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15 ||
3358*35238bceSAndroid Build Coastguard Worker            testType == BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15;
3359*35238bceSAndroid Build Coastguard Worker }
3360*35238bceSAndroid Build Coastguard Worker 
getBlockTestTypeColorScale(BlockTestType testType)3361*35238bceSAndroid Build Coastguard Worker Vec4 getBlockTestTypeColorScale(BlockTestType testType)
3362*35238bceSAndroid Build Coastguard Worker {
3363*35238bceSAndroid Build Coastguard Worker     switch (testType)
3364*35238bceSAndroid Build Coastguard Worker     {
3365*35238bceSAndroid Build Coastguard Worker     case tcu::astc::BLOCK_TEST_TYPE_VOID_EXTENT_HDR:
3366*35238bceSAndroid Build Coastguard Worker         return Vec4(0.5f / 65504.0f);
3367*35238bceSAndroid Build Coastguard Worker     case tcu::astc::BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_NO_15:
3368*35238bceSAndroid Build Coastguard Worker         return Vec4(1.0f / 65504.0f, 1.0f / 65504.0f, 1.0f / 65504.0f, 1.0f);
3369*35238bceSAndroid Build Coastguard Worker     case tcu::astc::BLOCK_TEST_TYPE_ENDPOINT_VALUE_HDR_15:
3370*35238bceSAndroid Build Coastguard Worker         return Vec4(1.0f / 65504.0f);
3371*35238bceSAndroid Build Coastguard Worker     default:
3372*35238bceSAndroid Build Coastguard Worker         return Vec4(1.0f);
3373*35238bceSAndroid Build Coastguard Worker     }
3374*35238bceSAndroid Build Coastguard Worker }
3375*35238bceSAndroid Build Coastguard Worker 
getBlockTestTypeColorBias(BlockTestType testType)3376*35238bceSAndroid Build Coastguard Worker Vec4 getBlockTestTypeColorBias(BlockTestType testType)
3377*35238bceSAndroid Build Coastguard Worker {
3378*35238bceSAndroid Build Coastguard Worker     switch (testType)
3379*35238bceSAndroid Build Coastguard Worker     {
3380*35238bceSAndroid Build Coastguard Worker     case tcu::astc::BLOCK_TEST_TYPE_VOID_EXTENT_HDR:
3381*35238bceSAndroid Build Coastguard Worker         return Vec4(0.5f);
3382*35238bceSAndroid Build Coastguard Worker     default:
3383*35238bceSAndroid Build Coastguard Worker         return Vec4(0.0f);
3384*35238bceSAndroid Build Coastguard Worker     }
3385*35238bceSAndroid Build Coastguard Worker }
3386*35238bceSAndroid Build Coastguard Worker 
3387*35238bceSAndroid Build Coastguard Worker } // namespace astc
3388*35238bceSAndroid Build Coastguard Worker } // namespace tcu
3389