1cc1dc7a3Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 2cc1dc7a3Sopenharmony_ci// ---------------------------------------------------------------------------- 3cc1dc7a3Sopenharmony_ci// Copyright 2011-2023 Arm Limited 4cc1dc7a3Sopenharmony_ci// 5cc1dc7a3Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); you may not 6cc1dc7a3Sopenharmony_ci// use this file except in compliance with the License. You may obtain a copy 7cc1dc7a3Sopenharmony_ci// of the License at: 8cc1dc7a3Sopenharmony_ci// 9cc1dc7a3Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 10cc1dc7a3Sopenharmony_ci// 11cc1dc7a3Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 12cc1dc7a3Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13cc1dc7a3Sopenharmony_ci// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14cc1dc7a3Sopenharmony_ci// License for the specific language governing permissions and limitations 15cc1dc7a3Sopenharmony_ci// under the License. 16cc1dc7a3Sopenharmony_ci// ---------------------------------------------------------------------------- 17cc1dc7a3Sopenharmony_ci 18cc1dc7a3Sopenharmony_ci/** 19cc1dc7a3Sopenharmony_ci * @brief Functions for converting between symbolic and physical encodings. 20cc1dc7a3Sopenharmony_ci */ 21cc1dc7a3Sopenharmony_ci 22cc1dc7a3Sopenharmony_ci#include "astcenc_internal.h" 23cc1dc7a3Sopenharmony_ci 24cc1dc7a3Sopenharmony_ci#include <cassert> 25cc1dc7a3Sopenharmony_ci 26cc1dc7a3Sopenharmony_ci/** 27cc1dc7a3Sopenharmony_ci * @brief Reverse bits in a byte. 28cc1dc7a3Sopenharmony_ci * 29cc1dc7a3Sopenharmony_ci * @param p The value to reverse. 30cc1dc7a3Sopenharmony_ci * 31cc1dc7a3Sopenharmony_ci * @return The reversed result. 32cc1dc7a3Sopenharmony_ci */ 33cc1dc7a3Sopenharmony_cistatic inline int bitrev8(int p) 34cc1dc7a3Sopenharmony_ci{ 35cc1dc7a3Sopenharmony_ci p = ((p & 0x0F) << 4) | ((p >> 4) & 0x0F); 36cc1dc7a3Sopenharmony_ci p = ((p & 0x33) << 2) | ((p >> 2) & 0x33); 37cc1dc7a3Sopenharmony_ci p = ((p & 0x55) << 1) | ((p >> 1) & 0x55); 38cc1dc7a3Sopenharmony_ci return p; 39cc1dc7a3Sopenharmony_ci} 40cc1dc7a3Sopenharmony_ci 41cc1dc7a3Sopenharmony_ci 42cc1dc7a3Sopenharmony_ci/** 43cc1dc7a3Sopenharmony_ci * @brief Read up to 8 bits at an arbitrary bit offset. 44cc1dc7a3Sopenharmony_ci * 45cc1dc7a3Sopenharmony_ci * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so may 46cc1dc7a3Sopenharmony_ci * span two separate bytes in memory. 47cc1dc7a3Sopenharmony_ci * 48cc1dc7a3Sopenharmony_ci * @param bitcount The number of bits to read. 49cc1dc7a3Sopenharmony_ci * @param bitoffset The bit offset to read from, between 0 and 7. 50cc1dc7a3Sopenharmony_ci * @param[in,out] ptr The data pointer to read from. 51cc1dc7a3Sopenharmony_ci * 52cc1dc7a3Sopenharmony_ci * @return The read value. 53cc1dc7a3Sopenharmony_ci */ 54cc1dc7a3Sopenharmony_cistatic inline int read_bits( 55cc1dc7a3Sopenharmony_ci int bitcount, 56cc1dc7a3Sopenharmony_ci int bitoffset, 57cc1dc7a3Sopenharmony_ci const uint8_t* ptr 58cc1dc7a3Sopenharmony_ci) { 59cc1dc7a3Sopenharmony_ci int mask = (1 << bitcount) - 1; 60cc1dc7a3Sopenharmony_ci ptr += bitoffset >> 3; 61cc1dc7a3Sopenharmony_ci bitoffset &= 7; 62cc1dc7a3Sopenharmony_ci int value = ptr[0] | (ptr[1] << 8); 63cc1dc7a3Sopenharmony_ci value >>= bitoffset; 64cc1dc7a3Sopenharmony_ci value &= mask; 65cc1dc7a3Sopenharmony_ci return value; 66cc1dc7a3Sopenharmony_ci} 67cc1dc7a3Sopenharmony_ci 68cc1dc7a3Sopenharmony_ci#if !defined(ASTCENC_DECOMPRESS_ONLY) 69cc1dc7a3Sopenharmony_ci 70cc1dc7a3Sopenharmony_ci/** 71cc1dc7a3Sopenharmony_ci * @brief Write up to 8 bits at an arbitrary bit offset. 72cc1dc7a3Sopenharmony_ci * 73cc1dc7a3Sopenharmony_ci * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so 74cc1dc7a3Sopenharmony_ci * may span two separate bytes in memory. 75cc1dc7a3Sopenharmony_ci * 76cc1dc7a3Sopenharmony_ci * @param value The value to write. 77cc1dc7a3Sopenharmony_ci * @param bitcount The number of bits to write, starting from LSB. 78cc1dc7a3Sopenharmony_ci * @param bitoffset The bit offset to store at, between 0 and 7. 79cc1dc7a3Sopenharmony_ci * @param[in,out] ptr The data pointer to write to. 80cc1dc7a3Sopenharmony_ci */ 81cc1dc7a3Sopenharmony_cistatic inline void write_bits( 82cc1dc7a3Sopenharmony_ci int value, 83cc1dc7a3Sopenharmony_ci int bitcount, 84cc1dc7a3Sopenharmony_ci int bitoffset, 85cc1dc7a3Sopenharmony_ci uint8_t* ptr 86cc1dc7a3Sopenharmony_ci) { 87cc1dc7a3Sopenharmony_ci int mask = (1 << bitcount) - 1; 88cc1dc7a3Sopenharmony_ci value &= mask; 89cc1dc7a3Sopenharmony_ci ptr += bitoffset >> 3; 90cc1dc7a3Sopenharmony_ci bitoffset &= 7; 91cc1dc7a3Sopenharmony_ci value <<= bitoffset; 92cc1dc7a3Sopenharmony_ci mask <<= bitoffset; 93cc1dc7a3Sopenharmony_ci mask = ~mask; 94cc1dc7a3Sopenharmony_ci 95cc1dc7a3Sopenharmony_ci ptr[0] &= mask; 96cc1dc7a3Sopenharmony_ci ptr[0] |= value; 97cc1dc7a3Sopenharmony_ci ptr[1] &= mask >> 8; 98cc1dc7a3Sopenharmony_ci ptr[1] |= value >> 8; 99cc1dc7a3Sopenharmony_ci} 100cc1dc7a3Sopenharmony_ci 101cc1dc7a3Sopenharmony_cistatic const int HIGH_SPEED_PROFILE_COLOR_BYTES = 8; 102cc1dc7a3Sopenharmony_cistatic const int HIGH_SPEED_PROFILE_WEIGHT_BYTES = 16; 103cc1dc7a3Sopenharmony_ci/* See header for documentation. */ 104cc1dc7a3Sopenharmony_civoid symbolic_to_physical( 105cc1dc7a3Sopenharmony_ci const block_size_descriptor& bsd, 106cc1dc7a3Sopenharmony_ci const symbolic_compressed_block& scb, 107cc1dc7a3Sopenharmony_ci uint8_t pcb[16] 108cc1dc7a3Sopenharmony_ci) { 109cc1dc7a3Sopenharmony_ci assert(scb.block_type != SYM_BTYPE_ERROR); 110cc1dc7a3Sopenharmony_ci // Constant color block using UNORM16 colors 111cc1dc7a3Sopenharmony_ci if (scb.block_type == SYM_BTYPE_CONST_U16 && scb.privateProfile != HIGH_SPEED_PROFILE) 112cc1dc7a3Sopenharmony_ci { 113cc1dc7a3Sopenharmony_ci // There is currently no attempt to coalesce larger void-extents 114cc1dc7a3Sopenharmony_ci static const uint8_t cbytes[8] { 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 115cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < 8; i++) 116cc1dc7a3Sopenharmony_ci { 117cc1dc7a3Sopenharmony_ci pcb[i] = cbytes[i]; 118cc1dc7a3Sopenharmony_ci } 119cc1dc7a3Sopenharmony_ci 120cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < BLOCK_MAX_COMPONENTS; i++) 121cc1dc7a3Sopenharmony_ci { 122cc1dc7a3Sopenharmony_ci pcb[2 * i + 8] = scb.constant_color[i] & 0xFF; 123cc1dc7a3Sopenharmony_ci pcb[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; 124cc1dc7a3Sopenharmony_ci } 125cc1dc7a3Sopenharmony_ci 126cc1dc7a3Sopenharmony_ci return; 127cc1dc7a3Sopenharmony_ci } 128cc1dc7a3Sopenharmony_ci 129cc1dc7a3Sopenharmony_ci // Constant color block using FP16 colors 130cc1dc7a3Sopenharmony_ci if (scb.block_type == SYM_BTYPE_CONST_F16 && scb.privateProfile != HIGH_SPEED_PROFILE) 131cc1dc7a3Sopenharmony_ci { 132cc1dc7a3Sopenharmony_ci // There is currently no attempt to coalesce larger void-extents 133cc1dc7a3Sopenharmony_ci static const uint8_t cbytes[8] { 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 134cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < 8; i++) 135cc1dc7a3Sopenharmony_ci { 136cc1dc7a3Sopenharmony_ci pcb[i] = cbytes[i]; 137cc1dc7a3Sopenharmony_ci } 138cc1dc7a3Sopenharmony_ci 139cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < BLOCK_MAX_COMPONENTS; i++) 140cc1dc7a3Sopenharmony_ci { 141cc1dc7a3Sopenharmony_ci pcb[2 * i + 8] = scb.constant_color[i] & 0xFF; 142cc1dc7a3Sopenharmony_ci pcb[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; 143cc1dc7a3Sopenharmony_ci } 144cc1dc7a3Sopenharmony_ci 145cc1dc7a3Sopenharmony_ci return; 146cc1dc7a3Sopenharmony_ci } 147cc1dc7a3Sopenharmony_ci 148cc1dc7a3Sopenharmony_ci unsigned int partition_count = scb.partition_count; 149cc1dc7a3Sopenharmony_ci 150cc1dc7a3Sopenharmony_ci // Compress the weights. 151cc1dc7a3Sopenharmony_ci // They are encoded as an ordinary integer-sequence, then bit-reversed 152cc1dc7a3Sopenharmony_ci uint8_t weightbuf[16] { 0 }; 153cc1dc7a3Sopenharmony_ci 154cc1dc7a3Sopenharmony_ci const auto& bm = bsd.get_block_mode(scb.block_mode); 155cc1dc7a3Sopenharmony_ci const auto& di = bsd.get_decimation_info(bm.decimation_mode); 156cc1dc7a3Sopenharmony_ci int weight_count = di.weight_count; 157cc1dc7a3Sopenharmony_ci quant_method weight_quant_method = bm.get_weight_quant_mode(); 158cc1dc7a3Sopenharmony_ci float weight_quant_levels = static_cast<float>(get_quant_level(weight_quant_method)); 159cc1dc7a3Sopenharmony_ci int is_dual_plane = bm.is_dual_plane; 160cc1dc7a3Sopenharmony_ci 161cc1dc7a3Sopenharmony_ci const auto& qat = quant_and_xfer_tables[weight_quant_method]; 162cc1dc7a3Sopenharmony_ci 163cc1dc7a3Sopenharmony_ci if (scb.privateProfile == HIGH_SPEED_PROFILE) 164cc1dc7a3Sopenharmony_ci { 165cc1dc7a3Sopenharmony_ci uint8_t weights[64]; 166cc1dc7a3Sopenharmony_ci for (int i = 0; i < weight_count; i++) 167cc1dc7a3Sopenharmony_ci { 168cc1dc7a3Sopenharmony_ci float uqw = static_cast<float>(scb.weights[i]); 169cc1dc7a3Sopenharmony_ci float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); 170cc1dc7a3Sopenharmony_ci int qwi = static_cast<int>(qw + 0.5f); 171cc1dc7a3Sopenharmony_ci weights[i] = qat.scramble_map[qwi]; 172cc1dc7a3Sopenharmony_ci } 173cc1dc7a3Sopenharmony_ci encode_ise(QUANT_6, HIGH_SPEED_PROFILE_WEIGHT_BYTES, weights, weightbuf, 0); 174cc1dc7a3Sopenharmony_ci for (int i = 0; i < HIGH_SPEED_PROFILE_WEIGHT_BYTES; i++) 175cc1dc7a3Sopenharmony_ci { 176cc1dc7a3Sopenharmony_ci pcb[i] = static_cast<uint8_t>(bitrev8(weightbuf[HIGH_SPEED_PROFILE_WEIGHT_BYTES - 1 - i])); 177cc1dc7a3Sopenharmony_ci } 178cc1dc7a3Sopenharmony_ci pcb[0] = 0x43; // the first byte of every block stream is 0x43 for HIGH_SPEED_PROFILE 179cc1dc7a3Sopenharmony_ci pcb[1] = 0x80; // the second byte of every block stream is 0x80 for HIGH_SPEED_PROFILE 180cc1dc7a3Sopenharmony_ci pcb[2] = 0x01; // the third (2 idx) byte of every block stream is 0x01 for HIGH_SPEED_PROFILE 181cc1dc7a3Sopenharmony_ci uint8_t values_to_encode[HIGH_SPEED_PROFILE_COLOR_BYTES]; 182cc1dc7a3Sopenharmony_ci for (int j = 0; j < HIGH_SPEED_PROFILE_COLOR_BYTES; j++) 183cc1dc7a3Sopenharmony_ci { 184cc1dc7a3Sopenharmony_ci values_to_encode[j] = scb.color_values[0][j]; 185cc1dc7a3Sopenharmony_ci } 186cc1dc7a3Sopenharmony_ci encode_ise(scb.get_color_quant_mode(), HIGH_SPEED_PROFILE_COLOR_BYTES, 187cc1dc7a3Sopenharmony_ci values_to_encode, pcb, 17); // the color is starting from 17th bit for HIGH_SPEED_PROFILE 188cc1dc7a3Sopenharmony_ci return; 189cc1dc7a3Sopenharmony_ci } 190cc1dc7a3Sopenharmony_ci 191cc1dc7a3Sopenharmony_ci int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count; 192cc1dc7a3Sopenharmony_ci 193cc1dc7a3Sopenharmony_ci int bits_for_weights = get_ise_sequence_bitcount(real_weight_count, weight_quant_method); 194cc1dc7a3Sopenharmony_ci 195cc1dc7a3Sopenharmony_ci uint8_t weights[64]; 196cc1dc7a3Sopenharmony_ci if (is_dual_plane) 197cc1dc7a3Sopenharmony_ci { 198cc1dc7a3Sopenharmony_ci for (int i = 0; i < weight_count; i++) 199cc1dc7a3Sopenharmony_ci { 200cc1dc7a3Sopenharmony_ci float uqw = static_cast<float>(scb.weights[i]); 201cc1dc7a3Sopenharmony_ci float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); 202cc1dc7a3Sopenharmony_ci int qwi = static_cast<int>(qw + 0.5f); 203cc1dc7a3Sopenharmony_ci weights[2 * i] = qat.scramble_map[qwi]; 204cc1dc7a3Sopenharmony_ci 205cc1dc7a3Sopenharmony_ci uqw = static_cast<float>(scb.weights[i + WEIGHTS_PLANE2_OFFSET]); 206cc1dc7a3Sopenharmony_ci qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); 207cc1dc7a3Sopenharmony_ci qwi = static_cast<int>(qw + 0.5f); 208cc1dc7a3Sopenharmony_ci weights[2 * i + 1] = qat.scramble_map[qwi]; 209cc1dc7a3Sopenharmony_ci } 210cc1dc7a3Sopenharmony_ci } 211cc1dc7a3Sopenharmony_ci else 212cc1dc7a3Sopenharmony_ci { 213cc1dc7a3Sopenharmony_ci for (int i = 0; i < weight_count; i++) 214cc1dc7a3Sopenharmony_ci { 215cc1dc7a3Sopenharmony_ci float uqw = static_cast<float>(scb.weights[i]); 216cc1dc7a3Sopenharmony_ci float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); 217cc1dc7a3Sopenharmony_ci int qwi = static_cast<int>(qw + 0.5f); 218cc1dc7a3Sopenharmony_ci weights[i] = qat.scramble_map[qwi]; 219cc1dc7a3Sopenharmony_ci } 220cc1dc7a3Sopenharmony_ci } 221cc1dc7a3Sopenharmony_ci 222cc1dc7a3Sopenharmony_ci encode_ise(weight_quant_method, real_weight_count, weights, weightbuf, 0); 223cc1dc7a3Sopenharmony_ci 224cc1dc7a3Sopenharmony_ci for (int i = 0; i < 16; i++) 225cc1dc7a3Sopenharmony_ci { 226cc1dc7a3Sopenharmony_ci pcb[i] = static_cast<uint8_t>(bitrev8(weightbuf[15 - i])); 227cc1dc7a3Sopenharmony_ci } 228cc1dc7a3Sopenharmony_ci 229cc1dc7a3Sopenharmony_ci write_bits(scb.block_mode, 11, 0, pcb); 230cc1dc7a3Sopenharmony_ci write_bits(partition_count - 1, 2, 11, pcb); 231cc1dc7a3Sopenharmony_ci 232cc1dc7a3Sopenharmony_ci int below_weights_pos = 128 - bits_for_weights; 233cc1dc7a3Sopenharmony_ci 234cc1dc7a3Sopenharmony_ci // Encode partition index and color endpoint types for blocks with 2+ partitions 235cc1dc7a3Sopenharmony_ci if (partition_count > 1) 236cc1dc7a3Sopenharmony_ci { 237cc1dc7a3Sopenharmony_ci write_bits(scb.partition_index, 6, 13, pcb); 238cc1dc7a3Sopenharmony_ci write_bits(scb.partition_index >> 6, PARTITION_INDEX_BITS - 6, 19, pcb); 239cc1dc7a3Sopenharmony_ci 240cc1dc7a3Sopenharmony_ci if (scb.color_formats_matched) 241cc1dc7a3Sopenharmony_ci { 242cc1dc7a3Sopenharmony_ci write_bits(scb.color_formats[0] << 2, 6, 13 + PARTITION_INDEX_BITS, pcb); 243cc1dc7a3Sopenharmony_ci } 244cc1dc7a3Sopenharmony_ci else 245cc1dc7a3Sopenharmony_ci { 246cc1dc7a3Sopenharmony_ci // Check endpoint types for each partition to determine the lowest class present 247cc1dc7a3Sopenharmony_ci int low_class = 4; 248cc1dc7a3Sopenharmony_ci 249cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < partition_count; i++) 250cc1dc7a3Sopenharmony_ci { 251cc1dc7a3Sopenharmony_ci int class_of_format = scb.color_formats[i] >> 2; 252cc1dc7a3Sopenharmony_ci low_class = astc::min(class_of_format, low_class); 253cc1dc7a3Sopenharmony_ci } 254cc1dc7a3Sopenharmony_ci 255cc1dc7a3Sopenharmony_ci if (low_class == 3) 256cc1dc7a3Sopenharmony_ci { 257cc1dc7a3Sopenharmony_ci low_class = 2; 258cc1dc7a3Sopenharmony_ci } 259cc1dc7a3Sopenharmony_ci 260cc1dc7a3Sopenharmony_ci int encoded_type = low_class + 1; 261cc1dc7a3Sopenharmony_ci int bitpos = 2; 262cc1dc7a3Sopenharmony_ci 263cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < partition_count; i++) 264cc1dc7a3Sopenharmony_ci { 265cc1dc7a3Sopenharmony_ci int classbit_of_format = (scb.color_formats[i] >> 2) - low_class; 266cc1dc7a3Sopenharmony_ci encoded_type |= classbit_of_format << bitpos; 267cc1dc7a3Sopenharmony_ci bitpos++; 268cc1dc7a3Sopenharmony_ci } 269cc1dc7a3Sopenharmony_ci 270cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < partition_count; i++) 271cc1dc7a3Sopenharmony_ci { 272cc1dc7a3Sopenharmony_ci int lowbits_of_format = scb.color_formats[i] & 3; 273cc1dc7a3Sopenharmony_ci encoded_type |= lowbits_of_format << bitpos; 274cc1dc7a3Sopenharmony_ci bitpos += 2; 275cc1dc7a3Sopenharmony_ci } 276cc1dc7a3Sopenharmony_ci 277cc1dc7a3Sopenharmony_ci int encoded_type_lowpart = encoded_type & 0x3F; 278cc1dc7a3Sopenharmony_ci int encoded_type_highpart = encoded_type >> 6; 279cc1dc7a3Sopenharmony_ci int encoded_type_highpart_size = (3 * partition_count) - 4; 280cc1dc7a3Sopenharmony_ci int encoded_type_highpart_pos = 128 - bits_for_weights - encoded_type_highpart_size; 281cc1dc7a3Sopenharmony_ci write_bits(encoded_type_lowpart, 6, 13 + PARTITION_INDEX_BITS, pcb); 282cc1dc7a3Sopenharmony_ci write_bits(encoded_type_highpart, encoded_type_highpart_size, encoded_type_highpart_pos, pcb); 283cc1dc7a3Sopenharmony_ci below_weights_pos -= encoded_type_highpart_size; 284cc1dc7a3Sopenharmony_ci } 285cc1dc7a3Sopenharmony_ci } 286cc1dc7a3Sopenharmony_ci else 287cc1dc7a3Sopenharmony_ci { 288cc1dc7a3Sopenharmony_ci write_bits(scb.color_formats[0], 4, 13, pcb); 289cc1dc7a3Sopenharmony_ci } 290cc1dc7a3Sopenharmony_ci 291cc1dc7a3Sopenharmony_ci // In dual-plane mode, encode the color component of the second plane of weights 292cc1dc7a3Sopenharmony_ci if (is_dual_plane) 293cc1dc7a3Sopenharmony_ci { 294cc1dc7a3Sopenharmony_ci write_bits(scb.plane2_component, 2, below_weights_pos - 2, pcb); 295cc1dc7a3Sopenharmony_ci } 296cc1dc7a3Sopenharmony_ci 297cc1dc7a3Sopenharmony_ci // Encode the color components 298cc1dc7a3Sopenharmony_ci uint8_t values_to_encode[32]; 299cc1dc7a3Sopenharmony_ci int valuecount_to_encode = 0; 300cc1dc7a3Sopenharmony_ci 301cc1dc7a3Sopenharmony_ci const uint8_t* pack_table = color_uquant_to_scrambled_pquant_tables[scb.quant_mode - QUANT_6]; 302cc1dc7a3Sopenharmony_ci for (unsigned int i = 0; i < scb.partition_count; i++) 303cc1dc7a3Sopenharmony_ci { 304cc1dc7a3Sopenharmony_ci int vals = 2 * (scb.color_formats[i] >> 2) + 2; 305cc1dc7a3Sopenharmony_ci assert(vals <= 8); 306cc1dc7a3Sopenharmony_ci for (int j = 0; j < vals; j++) 307cc1dc7a3Sopenharmony_ci { 308cc1dc7a3Sopenharmony_ci values_to_encode[j + valuecount_to_encode] = pack_table[scb.color_values[i][j]]; 309cc1dc7a3Sopenharmony_ci } 310cc1dc7a3Sopenharmony_ci valuecount_to_encode += vals; 311cc1dc7a3Sopenharmony_ci } 312cc1dc7a3Sopenharmony_ci 313cc1dc7a3Sopenharmony_ci encode_ise(scb.get_color_quant_mode(), valuecount_to_encode, values_to_encode, pcb, 314cc1dc7a3Sopenharmony_ci scb.partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS); 315cc1dc7a3Sopenharmony_ci} 316cc1dc7a3Sopenharmony_ci 317cc1dc7a3Sopenharmony_ci#endif 318cc1dc7a3Sopenharmony_ci 319cc1dc7a3Sopenharmony_ci/* See header for documentation. */ 320cc1dc7a3Sopenharmony_civoid physical_to_symbolic( 321cc1dc7a3Sopenharmony_ci const block_size_descriptor& bsd, 322cc1dc7a3Sopenharmony_ci const uint8_t pcb[16], 323cc1dc7a3Sopenharmony_ci symbolic_compressed_block& scb 324cc1dc7a3Sopenharmony_ci) { 325cc1dc7a3Sopenharmony_ci uint8_t bswapped[16]; 326cc1dc7a3Sopenharmony_ci 327cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_NONCONST; 328cc1dc7a3Sopenharmony_ci 329cc1dc7a3Sopenharmony_ci // Extract header fields 330cc1dc7a3Sopenharmony_ci int block_mode = read_bits(11, 0, pcb); 331cc1dc7a3Sopenharmony_ci if ((block_mode & 0x1FF) == 0x1FC) 332cc1dc7a3Sopenharmony_ci { 333cc1dc7a3Sopenharmony_ci // Constant color block 334cc1dc7a3Sopenharmony_ci 335cc1dc7a3Sopenharmony_ci // Check what format the data has 336cc1dc7a3Sopenharmony_ci if (block_mode & 0x200) 337cc1dc7a3Sopenharmony_ci { 338cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_CONST_F16; 339cc1dc7a3Sopenharmony_ci } 340cc1dc7a3Sopenharmony_ci else 341cc1dc7a3Sopenharmony_ci { 342cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_CONST_U16; 343cc1dc7a3Sopenharmony_ci } 344cc1dc7a3Sopenharmony_ci 345cc1dc7a3Sopenharmony_ci scb.partition_count = 0; 346cc1dc7a3Sopenharmony_ci for (int i = 0; i < 4; i++) 347cc1dc7a3Sopenharmony_ci { 348cc1dc7a3Sopenharmony_ci scb.constant_color[i] = pcb[2 * i + 8] | (pcb[2 * i + 9] << 8); 349cc1dc7a3Sopenharmony_ci } 350cc1dc7a3Sopenharmony_ci 351cc1dc7a3Sopenharmony_ci // Additionally, check that the void-extent 352cc1dc7a3Sopenharmony_ci if (bsd.zdim == 1) 353cc1dc7a3Sopenharmony_ci { 354cc1dc7a3Sopenharmony_ci // 2D void-extent 355cc1dc7a3Sopenharmony_ci int rsvbits = read_bits(2, 10, pcb); 356cc1dc7a3Sopenharmony_ci if (rsvbits != 3) 357cc1dc7a3Sopenharmony_ci { 358cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 359cc1dc7a3Sopenharmony_ci return; 360cc1dc7a3Sopenharmony_ci } 361cc1dc7a3Sopenharmony_ci 362cc1dc7a3Sopenharmony_ci int vx_low_s = read_bits(8, 12, pcb) | (read_bits(5, 12 + 8, pcb) << 8); 363cc1dc7a3Sopenharmony_ci int vx_high_s = read_bits(8, 25, pcb) | (read_bits(5, 25 + 8, pcb) << 8); 364cc1dc7a3Sopenharmony_ci int vx_low_t = read_bits(8, 38, pcb) | (read_bits(5, 38 + 8, pcb) << 8); 365cc1dc7a3Sopenharmony_ci int vx_high_t = read_bits(8, 51, pcb) | (read_bits(5, 51 + 8, pcb) << 8); 366cc1dc7a3Sopenharmony_ci 367cc1dc7a3Sopenharmony_ci int all_ones = vx_low_s == 0x1FFF && vx_high_s == 0x1FFF && vx_low_t == 0x1FFF && vx_high_t == 0x1FFF; 368cc1dc7a3Sopenharmony_ci 369cc1dc7a3Sopenharmony_ci if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t) && !all_ones) 370cc1dc7a3Sopenharmony_ci { 371cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 372cc1dc7a3Sopenharmony_ci return; 373cc1dc7a3Sopenharmony_ci } 374cc1dc7a3Sopenharmony_ci } 375cc1dc7a3Sopenharmony_ci else 376cc1dc7a3Sopenharmony_ci { 377cc1dc7a3Sopenharmony_ci // 3D void-extent 378cc1dc7a3Sopenharmony_ci int vx_low_s = read_bits(9, 10, pcb); 379cc1dc7a3Sopenharmony_ci int vx_high_s = read_bits(9, 19, pcb); 380cc1dc7a3Sopenharmony_ci int vx_low_t = read_bits(9, 28, pcb); 381cc1dc7a3Sopenharmony_ci int vx_high_t = read_bits(9, 37, pcb); 382cc1dc7a3Sopenharmony_ci int vx_low_p = read_bits(9, 46, pcb); 383cc1dc7a3Sopenharmony_ci int vx_high_p = read_bits(9, 55, pcb); 384cc1dc7a3Sopenharmony_ci 385cc1dc7a3Sopenharmony_ci int all_ones = vx_low_s == 0x1FF && vx_high_s == 0x1FF && vx_low_t == 0x1FF && vx_high_t == 0x1FF && vx_low_p == 0x1FF && vx_high_p == 0x1FF; 386cc1dc7a3Sopenharmony_ci 387cc1dc7a3Sopenharmony_ci if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t || vx_low_p >= vx_high_p) && !all_ones) 388cc1dc7a3Sopenharmony_ci { 389cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 390cc1dc7a3Sopenharmony_ci return; 391cc1dc7a3Sopenharmony_ci } 392cc1dc7a3Sopenharmony_ci } 393cc1dc7a3Sopenharmony_ci 394cc1dc7a3Sopenharmony_ci return; 395cc1dc7a3Sopenharmony_ci } 396cc1dc7a3Sopenharmony_ci 397cc1dc7a3Sopenharmony_ci unsigned int packed_index = bsd.block_mode_packed_index[block_mode]; 398cc1dc7a3Sopenharmony_ci if (packed_index == BLOCK_BAD_BLOCK_MODE) 399cc1dc7a3Sopenharmony_ci { 400cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 401cc1dc7a3Sopenharmony_ci return; 402cc1dc7a3Sopenharmony_ci } 403cc1dc7a3Sopenharmony_ci 404cc1dc7a3Sopenharmony_ci const auto& bm = bsd.get_block_mode(block_mode); 405cc1dc7a3Sopenharmony_ci const auto& di = bsd.get_decimation_info(bm.decimation_mode); 406cc1dc7a3Sopenharmony_ci 407cc1dc7a3Sopenharmony_ci int weight_count = di.weight_count; 408cc1dc7a3Sopenharmony_ci promise(weight_count > 0); 409cc1dc7a3Sopenharmony_ci 410cc1dc7a3Sopenharmony_ci quant_method weight_quant_method = static_cast<quant_method>(bm.quant_mode); 411cc1dc7a3Sopenharmony_ci int is_dual_plane = bm.is_dual_plane; 412cc1dc7a3Sopenharmony_ci 413cc1dc7a3Sopenharmony_ci int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count; 414cc1dc7a3Sopenharmony_ci 415cc1dc7a3Sopenharmony_ci int partition_count = read_bits(2, 11, pcb) + 1; 416cc1dc7a3Sopenharmony_ci promise(partition_count > 0); 417cc1dc7a3Sopenharmony_ci 418cc1dc7a3Sopenharmony_ci scb.block_mode = static_cast<uint16_t>(block_mode); 419cc1dc7a3Sopenharmony_ci scb.partition_count = static_cast<uint8_t>(partition_count); 420cc1dc7a3Sopenharmony_ci 421cc1dc7a3Sopenharmony_ci for (int i = 0; i < 16; i++) 422cc1dc7a3Sopenharmony_ci { 423cc1dc7a3Sopenharmony_ci bswapped[i] = static_cast<uint8_t>(bitrev8(pcb[15 - i])); 424cc1dc7a3Sopenharmony_ci } 425cc1dc7a3Sopenharmony_ci 426cc1dc7a3Sopenharmony_ci int bits_for_weights = get_ise_sequence_bitcount(real_weight_count, weight_quant_method); 427cc1dc7a3Sopenharmony_ci 428cc1dc7a3Sopenharmony_ci int below_weights_pos = 128 - bits_for_weights; 429cc1dc7a3Sopenharmony_ci 430cc1dc7a3Sopenharmony_ci uint8_t indices[64]; 431cc1dc7a3Sopenharmony_ci const auto& qat = quant_and_xfer_tables[weight_quant_method]; 432cc1dc7a3Sopenharmony_ci 433cc1dc7a3Sopenharmony_ci decode_ise(weight_quant_method, real_weight_count, bswapped, indices, 0); 434cc1dc7a3Sopenharmony_ci 435cc1dc7a3Sopenharmony_ci if (is_dual_plane) 436cc1dc7a3Sopenharmony_ci { 437cc1dc7a3Sopenharmony_ci for (int i = 0; i < weight_count; i++) 438cc1dc7a3Sopenharmony_ci { 439cc1dc7a3Sopenharmony_ci scb.weights[i] = qat.unscramble_and_unquant_map[indices[2 * i]]; 440cc1dc7a3Sopenharmony_ci scb.weights[i + WEIGHTS_PLANE2_OFFSET] = qat.unscramble_and_unquant_map[indices[2 * i + 1]]; 441cc1dc7a3Sopenharmony_ci } 442cc1dc7a3Sopenharmony_ci } 443cc1dc7a3Sopenharmony_ci else 444cc1dc7a3Sopenharmony_ci { 445cc1dc7a3Sopenharmony_ci for (int i = 0; i < weight_count; i++) 446cc1dc7a3Sopenharmony_ci { 447cc1dc7a3Sopenharmony_ci scb.weights[i] = qat.unscramble_and_unquant_map[indices[i]]; 448cc1dc7a3Sopenharmony_ci } 449cc1dc7a3Sopenharmony_ci } 450cc1dc7a3Sopenharmony_ci 451cc1dc7a3Sopenharmony_ci if (is_dual_plane && partition_count == 4) 452cc1dc7a3Sopenharmony_ci { 453cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 454cc1dc7a3Sopenharmony_ci return; 455cc1dc7a3Sopenharmony_ci } 456cc1dc7a3Sopenharmony_ci 457cc1dc7a3Sopenharmony_ci scb.color_formats_matched = 0; 458cc1dc7a3Sopenharmony_ci 459cc1dc7a3Sopenharmony_ci // Determine the format of each endpoint pair 460cc1dc7a3Sopenharmony_ci int color_formats[BLOCK_MAX_PARTITIONS]; 461cc1dc7a3Sopenharmony_ci int encoded_type_highpart_size = 0; 462cc1dc7a3Sopenharmony_ci if (partition_count == 1) 463cc1dc7a3Sopenharmony_ci { 464cc1dc7a3Sopenharmony_ci color_formats[0] = read_bits(4, 13, pcb); 465cc1dc7a3Sopenharmony_ci scb.partition_index = 0; 466cc1dc7a3Sopenharmony_ci } 467cc1dc7a3Sopenharmony_ci else 468cc1dc7a3Sopenharmony_ci { 469cc1dc7a3Sopenharmony_ci encoded_type_highpart_size = (3 * partition_count) - 4; 470cc1dc7a3Sopenharmony_ci below_weights_pos -= encoded_type_highpart_size; 471cc1dc7a3Sopenharmony_ci int encoded_type = read_bits(6, 13 + PARTITION_INDEX_BITS, pcb) | 472cc1dc7a3Sopenharmony_ci (read_bits(encoded_type_highpart_size, below_weights_pos, pcb) << 6); 473cc1dc7a3Sopenharmony_ci int baseclass = encoded_type & 0x3; 474cc1dc7a3Sopenharmony_ci if (baseclass == 0) 475cc1dc7a3Sopenharmony_ci { 476cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 477cc1dc7a3Sopenharmony_ci { 478cc1dc7a3Sopenharmony_ci color_formats[i] = (encoded_type >> 2) & 0xF; 479cc1dc7a3Sopenharmony_ci } 480cc1dc7a3Sopenharmony_ci 481cc1dc7a3Sopenharmony_ci below_weights_pos += encoded_type_highpart_size; 482cc1dc7a3Sopenharmony_ci scb.color_formats_matched = 1; 483cc1dc7a3Sopenharmony_ci encoded_type_highpart_size = 0; 484cc1dc7a3Sopenharmony_ci } 485cc1dc7a3Sopenharmony_ci else 486cc1dc7a3Sopenharmony_ci { 487cc1dc7a3Sopenharmony_ci int bitpos = 2; 488cc1dc7a3Sopenharmony_ci baseclass--; 489cc1dc7a3Sopenharmony_ci 490cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 491cc1dc7a3Sopenharmony_ci { 492cc1dc7a3Sopenharmony_ci color_formats[i] = (((encoded_type >> bitpos) & 1) + baseclass) << 2; 493cc1dc7a3Sopenharmony_ci bitpos++; 494cc1dc7a3Sopenharmony_ci } 495cc1dc7a3Sopenharmony_ci 496cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 497cc1dc7a3Sopenharmony_ci { 498cc1dc7a3Sopenharmony_ci color_formats[i] |= (encoded_type >> bitpos) & 3; 499cc1dc7a3Sopenharmony_ci bitpos += 2; 500cc1dc7a3Sopenharmony_ci } 501cc1dc7a3Sopenharmony_ci } 502cc1dc7a3Sopenharmony_ci scb.partition_index = static_cast<uint16_t>(read_bits(6, 13, pcb) | 503cc1dc7a3Sopenharmony_ci (read_bits(PARTITION_INDEX_BITS - 6, 19, pcb) << 6)); 504cc1dc7a3Sopenharmony_ci } 505cc1dc7a3Sopenharmony_ci 506cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 507cc1dc7a3Sopenharmony_ci { 508cc1dc7a3Sopenharmony_ci scb.color_formats[i] = static_cast<uint8_t>(color_formats[i]); 509cc1dc7a3Sopenharmony_ci } 510cc1dc7a3Sopenharmony_ci 511cc1dc7a3Sopenharmony_ci // Determine number of color endpoint integers 512cc1dc7a3Sopenharmony_ci int color_integer_count = 0; 513cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 514cc1dc7a3Sopenharmony_ci { 515cc1dc7a3Sopenharmony_ci int endpoint_class = color_formats[i] >> 2; 516cc1dc7a3Sopenharmony_ci color_integer_count += (endpoint_class + 1) * 2; 517cc1dc7a3Sopenharmony_ci } 518cc1dc7a3Sopenharmony_ci 519cc1dc7a3Sopenharmony_ci if (color_integer_count > 18) 520cc1dc7a3Sopenharmony_ci { 521cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 522cc1dc7a3Sopenharmony_ci return; 523cc1dc7a3Sopenharmony_ci } 524cc1dc7a3Sopenharmony_ci 525cc1dc7a3Sopenharmony_ci // Determine the color endpoint format to use 526cc1dc7a3Sopenharmony_ci static const int color_bits_arr[5] { -1, 115 - 4, 113 - 4 - PARTITION_INDEX_BITS, 113 - 4 - PARTITION_INDEX_BITS, 113 - 4 - PARTITION_INDEX_BITS }; 527cc1dc7a3Sopenharmony_ci int color_bits = color_bits_arr[partition_count] - bits_for_weights - encoded_type_highpart_size; 528cc1dc7a3Sopenharmony_ci if (is_dual_plane) 529cc1dc7a3Sopenharmony_ci { 530cc1dc7a3Sopenharmony_ci color_bits -= 2; 531cc1dc7a3Sopenharmony_ci } 532cc1dc7a3Sopenharmony_ci 533cc1dc7a3Sopenharmony_ci if (color_bits < 0) 534cc1dc7a3Sopenharmony_ci { 535cc1dc7a3Sopenharmony_ci color_bits = 0; 536cc1dc7a3Sopenharmony_ci } 537cc1dc7a3Sopenharmony_ci 538cc1dc7a3Sopenharmony_ci int color_quant_level = quant_mode_table[color_integer_count >> 1][color_bits]; 539cc1dc7a3Sopenharmony_ci if (color_quant_level < QUANT_6) 540cc1dc7a3Sopenharmony_ci { 541cc1dc7a3Sopenharmony_ci scb.block_type = SYM_BTYPE_ERROR; 542cc1dc7a3Sopenharmony_ci return; 543cc1dc7a3Sopenharmony_ci } 544cc1dc7a3Sopenharmony_ci 545cc1dc7a3Sopenharmony_ci // Unpack the integer color values and assign to endpoints 546cc1dc7a3Sopenharmony_ci scb.quant_mode = static_cast<quant_method>(color_quant_level); 547cc1dc7a3Sopenharmony_ci 548cc1dc7a3Sopenharmony_ci uint8_t values_to_decode[32]; 549cc1dc7a3Sopenharmony_ci decode_ise(static_cast<quant_method>(color_quant_level), color_integer_count, pcb, 550cc1dc7a3Sopenharmony_ci values_to_decode, (partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS)); 551cc1dc7a3Sopenharmony_ci 552cc1dc7a3Sopenharmony_ci int valuecount_to_decode = 0; 553cc1dc7a3Sopenharmony_ci const uint8_t* unpack_table = color_scrambled_pquant_to_uquant_tables[scb.quant_mode - QUANT_6]; 554cc1dc7a3Sopenharmony_ci for (int i = 0; i < partition_count; i++) 555cc1dc7a3Sopenharmony_ci { 556cc1dc7a3Sopenharmony_ci int vals = 2 * (color_formats[i] >> 2) + 2; 557cc1dc7a3Sopenharmony_ci for (int j = 0; j < vals; j++) 558cc1dc7a3Sopenharmony_ci { 559cc1dc7a3Sopenharmony_ci scb.color_values[i][j] = unpack_table[values_to_decode[j + valuecount_to_decode]]; 560cc1dc7a3Sopenharmony_ci } 561cc1dc7a3Sopenharmony_ci valuecount_to_decode += vals; 562cc1dc7a3Sopenharmony_ci } 563cc1dc7a3Sopenharmony_ci 564cc1dc7a3Sopenharmony_ci // Fetch component for second-plane in the case of dual plane of weights. 565cc1dc7a3Sopenharmony_ci scb.plane2_component = -1; 566cc1dc7a3Sopenharmony_ci if (is_dual_plane) 567cc1dc7a3Sopenharmony_ci { 568cc1dc7a3Sopenharmony_ci scb.plane2_component = static_cast<int8_t>(read_bits(2, below_weights_pos - 2, pcb)); 569cc1dc7a3Sopenharmony_ci } 570cc1dc7a3Sopenharmony_ci} 571