Implement ASTC support
This cl adds both LDR and HDR support for ASTC compressed
textures. Only LDR formats are exposed in the
PhysicalDevice's properties, but HDR support can be added
trivially later by adding the HDR formats and exposing
"VK_EXT_texture_compression_astc_hdr".
Pulled from: https://github.com/ARM-software/astc-encoder
Git hash: 81a5e50741b4c8302cf7d78f314a53e44ee68e1f
The astc-encode git repo was added to third-party, with a
few minor modifications:
1) All encoding related code has been ripped out, only
decoding related code remains
2) Replaced ASTC_CODEC_INTERNAL_ERROR() with UNREACHABLE()
in a switch statement in astc_color_unquantize.cpp
3) Some functions were using a lot of stack memory, so I
added a unique_ptr to allocate the same objects on the
heap, to avoid potential issues.
LDR ASTC is decoded to 8bit unsigned RGBA.
HDR ASTC is decoded to 32b floating point.
Tests: dEQP-VK.*astc*
Bug: b/150130101
Change-Id: I6b03fed6e1f326a95c7aefe9f9a9d0a89cf24428
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41568
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 538d360..5d80303 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -330,6 +330,7 @@
set(OPENGL_COMPILER_DIR ${OPENGL_DIR}/compiler)
set(VULKAN_DIR ${SOURCE_DIR}/Vulkan)
set(THIRD_PARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party)
+set(ASTC_DIR ${THIRD_PARTY_DIR}/astc-encoder)
set(LLVM_DIR ${THIRD_PARTY_DIR}/llvm-7.0/llvm)
set(LLVM_CONFIG_DIR ${THIRD_PARTY_DIR}/llvm-7.0/configs)
set(LIBBACKTRACE_DIR ${THIRD_PARTY_DIR}/libbacktrace/src)
@@ -1865,6 +1866,8 @@
${SOURCE_DIR}/WSI/VkSurfaceKHR.hpp
${SOURCE_DIR}/WSI/VkSwapchainKHR.cpp
${SOURCE_DIR}/WSI/VkSwapchainKHR.hpp
+ ${ASTC_DIR}/Source/*.cpp
+ ${ASTC_DIR}/Source/*.h
${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan/*.h}
)
diff --git a/src/Android.bp b/src/Android.bp
index 65debb5..a400a4c 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -589,6 +589,28 @@
},
}
+cc_library_static {
+ name: "swiftshader_debug",
+
+ vendor_available: true,
+
+ cflags: [
+ "-DLOG_TAG=\"swiftshader\"",
+ ],
+
+ srcs: [
+ "System/Debug.cpp",
+ ],
+
+ export_include_dirs: [
+ ".",
+ ],
+
+ shared_libs: [
+ "liblog",
+ ],
+}
+
cc_defaults {
name: "libvk_swiftshader_common_defaults",
@@ -601,7 +623,6 @@
"System/Build.cpp",
"System/Configurator.cpp",
"System/CPUID.cpp",
- "System/Debug.cpp",
"System/GrallocAndroid.cpp",
"System/Half.cpp",
"System/Linux/MemFd.cpp",
@@ -615,6 +636,8 @@
],
static_libs: [
+ "swiftshader_astc",
+ "swiftshader_debug",
"swiftshader_marl",
"swiftshader_spirv-tools",
],
diff --git a/src/Device/ASTC_Decoder.cpp b/src/Device/ASTC_Decoder.cpp
new file mode 100644
index 0000000..344988d
--- /dev/null
+++ b/src/Device/ASTC_Decoder.cpp
@@ -0,0 +1,127 @@
+// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "ASTC_Decoder.hpp"
+#include "../third_party/astc-encoder/Source/astc_codec_internals.h"
+#include "System/Math.hpp"
+
+#include <memory>
+#include <unordered_map>
+
+namespace {
+
+void write_imageblock(unsigned char *img,
+ // picture-block to initialize with image data. We assume that orig_data is valid
+ const imageblock *pb,
+ // output dimensions
+ int xsize, int ysize, int zsize,
+ // output format
+ int bytes, int destPitchB, int destSliceB, bool isUnsignedByte,
+ // block dimensions
+ int xdim, int ydim, int zdim,
+ // position to write the block to
+ int xpos, int ypos, int zpos)
+{
+ const float *fptr = pb->orig_data;
+ const uint8_t *nptr = pb->nan_texel;
+
+ for(int z = 0; z < zdim; z++)
+ {
+ for(int y = 0; y < ydim; y++)
+ {
+ for(int x = 0; x < xdim; x++)
+ {
+ int xi = xpos + x;
+ int yi = ypos + y;
+ int zi = zpos + z;
+
+ if(xi >= 0 && yi >= 0 && zi >= 0 && xi < xsize && yi < ysize && zi < zsize)
+ {
+ unsigned char *pix = &img[zi * destSliceB + yi * destPitchB + xi * bytes];
+
+ if(isUnsignedByte)
+ {
+ if(*nptr)
+ {
+ // NaN-pixel, but we can't display it. Display purple instead.
+ pix[0] = 0xFF;
+ pix[1] = 0x00;
+ pix[2] = 0xFF;
+ pix[3] = 0xFF;
+ }
+ else
+ {
+ pix[0] = static_cast<unsigned char>(sw::clamp(fptr[0], 0.0f, 1.0f) * 255.0f + 0.5f);
+ pix[1] = static_cast<unsigned char>(sw::clamp(fptr[1], 0.0f, 1.0f) * 255.0f + 0.5f);
+ pix[2] = static_cast<unsigned char>(sw::clamp(fptr[2], 0.0f, 1.0f) * 255.0f + 0.5f);
+ pix[3] = static_cast<unsigned char>(sw::clamp(fptr[3], 0.0f, 1.0f) * 255.0f + 0.5f);
+ }
+ }
+ else
+ {
+ if(*nptr)
+ {
+ unsigned int *pixu = reinterpret_cast<unsigned int *>(pix);
+ pixu[0] = pixu[1] = pixu[2] = pixu[3] = 0x7FFFFFFF; // QNaN
+ }
+ else
+ {
+ float *pixf = reinterpret_cast<float *>(pix);
+ pixf[0] = fptr[0];
+ pixf[1] = fptr[1];
+ pixf[2] = fptr[2];
+ pixf[3] = fptr[3];
+ }
+ }
+ }
+ fptr += 4;
+ nptr++;
+ }
+ }
+ }
+}
+
+} // namespace
+
+void ASTC_Decoder::Decode(const unsigned char *source, unsigned char *dest,
+ int destWidth, int destHeight, int destDepth,
+ int bytes, int destPitchB, int destSliceB,
+ int xBlockSize, int yBlockSize, int zBlockSize,
+ int xblocks, int yblocks, int zblocks, bool isUnsignedByte)
+{
+ build_quantization_mode_table();
+
+ astc_decode_mode decode_mode = isUnsignedByte ? DECODE_LDR : DECODE_HDR;
+
+ std::unique_ptr<block_size_descriptor> bsd(new block_size_descriptor);
+ init_block_size_descriptor(xBlockSize, yBlockSize, zBlockSize, bsd.get());
+
+ std::unique_ptr<imageblock> ib(new imageblock);
+ std::unique_ptr<symbolic_compressed_block> scb(new symbolic_compressed_block);
+ for(int z = 0; z < zblocks; z++)
+ {
+ for(int y = 0; y < yblocks; y++)
+ {
+ for(int x = 0; x < xblocks; x++, source += 16)
+ {
+ physical_to_symbolic(bsd.get(), *(physical_compressed_block *)source, scb.get());
+ decompress_symbolic_block(decode_mode, bsd.get(), x * xBlockSize, y * yBlockSize, z * zBlockSize, scb.get(), ib.get());
+ write_imageblock(dest, ib.get(), destWidth, destHeight, destDepth, bytes, destPitchB, destSliceB, isUnsignedByte,
+ xBlockSize, yBlockSize, zBlockSize, x * xBlockSize, y * yBlockSize, z * zBlockSize);
+ }
+ }
+ }
+
+ term_block_size_descriptor(bsd.get());
+}
diff --git a/src/Device/ASTC_Decoder.hpp b/src/Device/ASTC_Decoder.hpp
new file mode 100644
index 0000000..c1a05e5
--- /dev/null
+++ b/src/Device/ASTC_Decoder.hpp
@@ -0,0 +1,22 @@
+// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+struct ASTC_Decoder
+{
+ static void Decode(const unsigned char *source, unsigned char *dest,
+ int destWidth, int destHeight, int destDepth,
+ int bytes, int destPitchB, int destSliceB,
+ int xBlockSize, int yBlockSize, int zBlockSize,
+ int xblocks, int yblocks, int zblocks, bool isUnsignedByte);
+};
\ No newline at end of file
diff --git a/src/Device/BUILD.gn b/src/Device/BUILD.gn
index 7a874d7..23193f6 100644
--- a/src/Device/BUILD.gn
+++ b/src/Device/BUILD.gn
@@ -16,6 +16,7 @@
swiftshader_source_set("Device_headers") {
sources = [
+ "ASTC_Decoder.hpp",
"BC_Decoder.hpp",
"Blitter.hpp",
"Clipper.hpp",
@@ -30,11 +31,14 @@
"Renderer.hpp",
"SetupProcessor.hpp",
"VertexProcessor.hpp",
+ "../../third_party/astc-encoder/Source/astc_codec_internals.h",
+ "../../third_party/astc-encoder/Source/astc_mathlib.h",
]
}
swiftshader_source_set("Device") {
sources = [
+ "ASTC_Decoder.cpp",
"BC_Decoder.cpp",
"Blitter.cpp",
"Clipper.cpp",
@@ -48,6 +52,18 @@
"Renderer.cpp",
"SetupProcessor.cpp",
"VertexProcessor.cpp",
+ "../../third_party/astc-encoder/Source/astc_block_sizes2.cpp",
+ "../../third_party/astc-encoder/Source/astc_color_unquantize.cpp",
+ "../../third_party/astc-encoder/Source/astc_decompress_symbolic.cpp",
+ "../../third_party/astc-encoder/Source/astc_image_load_store.cpp",
+ "../../third_party/astc-encoder/Source/astc_integer_sequence.cpp",
+ "../../third_party/astc-encoder/Source/astc_mathlib.cpp",
+ "../../third_party/astc-encoder/Source/astc_mathlib_softfloat.cpp",
+ "../../third_party/astc-encoder/Source/astc_partition_tables.cpp",
+ "../../third_party/astc-encoder/Source/astc_percentile_tables.cpp",
+ "../../third_party/astc-encoder/Source/astc_quantization.cpp",
+ "../../third_party/astc-encoder/Source/astc_symbolic_physical.cpp",
+ "../../third_party/astc-encoder/Source/astc_weight_quant_xfer_tables.cpp",
]
include_dirs = [
diff --git a/src/System/Math.hpp b/src/System/Math.hpp
index 7dcffd7..8c6a069 100644
--- a/src/System/Math.hpp
+++ b/src/System/Math.hpp
@@ -133,9 +133,6 @@
!!((x)&0xFFFFFFFE) + \
!!((x)&0xFFFFFFFF))
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
inline unsigned long log2i(int x)
{
#if defined(_MSC_VER)
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index 837e8ca..72cef97 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -310,6 +310,20 @@
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
case VK_FORMAT_BC2_SRGB_BLOCK:
case VK_FORMAT_BC3_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
return true;
default:
return false;
@@ -531,6 +545,20 @@
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return true;
default:
return false;
@@ -578,6 +606,51 @@
return VK_FORMAT_R8G8_UNORM;
case VK_FORMAT_BC5_SNORM_BLOCK:
return VK_FORMAT_R8G8_SNORM;
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ return VK_FORMAT_R8G8B8A8_UNORM;
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ return VK_FORMAT_R8G8B8A8_SRGB;
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
default:
UNSUPPORTED("format: %d", int(format));
return VK_FORMAT_UNDEFINED;
@@ -933,37 +1006,51 @@
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
return 4;
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
return 5;
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
return 6;
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
return 8;
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
return 10;
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return 12;
default:
return 1;
@@ -1002,37 +1089,51 @@
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
return 4;
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
return 5;
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
return 6;
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
return 8;
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
return 10;
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return 12;
default:
return 1;
@@ -1098,6 +1199,20 @@
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return 16;
default:
return bytes();
@@ -1265,6 +1380,48 @@
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return 4;
default:
UNSUPPORTED("Format: %d", int(format));
@@ -1366,6 +1523,34 @@
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
return true;
case VK_FORMAT_R8G8B8A8_SNORM:
case VK_FORMAT_R8G8B8A8_SSCALED:
@@ -1394,6 +1579,20 @@
case VK_FORMAT_BC5_SNORM_BLOCK:
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
// YCbCr formats treated as signed because VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
// expects chroma components to be in range [-0.5, 0.5]
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
@@ -1659,6 +1858,20 @@
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
UNSUPPORTED("format: %d", int(format));
return 0;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
@@ -1709,37 +1922,51 @@
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
return 16 * ((width + 3) / 4); // 128 bit per 4x4 block, computed per 4 rows
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
return 16 * ((width + 4) / 5);
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
return 16 * ((width + 5) / 6);
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
return 16 * ((width + 7) / 8);
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
return 16 * ((width + 9) / 10);
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return 16 * ((width + 11) / 12);
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
@@ -1785,37 +2012,51 @@
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 3) / 4); // Pitch computed per 4 rows
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 4) / 5); // Pitch computed per 5 rows
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 5) / 6); // Pitch computed per 6 rows
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 7) / 8); // Pitch computed per 8 rows
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 9) / 10); // Pitch computed per 10 rows
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
return pitchB(width, border, target) * ((height + 11) / 12); // Pitch computed per 12 rows
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 82b0c53..a85b301 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -16,6 +16,7 @@
#include "VkBuffer.hpp"
#include "VkDevice.hpp"
#include "VkDeviceMemory.hpp"
+#include "Device/ASTC_Decoder.hpp"
#include "Device/BC_Decoder.hpp"
#include "Device/Blitter.hpp"
#include "Device/ETC_Decoder.hpp"
@@ -660,7 +661,15 @@
ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
- return getFormat(aspect).pitchB(getMipLevelExtent(aspect, mipLevel).width, borderSize(), true);
+ VkExtent3D mipLevelExtent = getMipLevelExtent(aspect, mipLevel);
+ Format usedFormat = getFormat(aspect);
+ if(usedFormat.isCompressed())
+ {
+ VkExtent3D extentInBlocks = imageExtentInBlocks(mipLevelExtent, aspect);
+ return extentInBlocks.width * usedFormat.bytesPerBlock();
+ }
+
+ return usedFormat.pitchB(mipLevelExtent.width, borderSize(), true);
}
int Image::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
@@ -673,8 +682,8 @@
Format usedFormat = getFormat(aspect);
if(usedFormat.isCompressed())
{
- sw::align(mipLevelExtent.width, usedFormat.blockWidth());
- sw::align(mipLevelExtent.height, usedFormat.blockHeight());
+ VkExtent3D extentInBlocks = imageExtentInBlocks(mipLevelExtent, aspect);
+ return extentInBlocks.height * extentInBlocks.width * usedFormat.bytesPerBlock();
}
return usedFormat.sliceB(mipLevelExtent.width, mipLevelExtent.height, borderSize(), true);
@@ -977,6 +986,50 @@
case VK_FORMAT_BC5_SNORM_BLOCK:
decodeBC(subresourceRange);
break;
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
+ case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
+ decodeASTC(subresourceRange);
+ break;
default:
break;
}
@@ -1087,4 +1140,49 @@
}
}
+void Image::decodeASTC(const VkImageSubresourceRange &subresourceRange) const
+{
+ ASSERT(decompressedImage);
+
+ int xBlockSize = format.blockWidth();
+ int yBlockSize = format.blockHeight();
+ int zBlockSize = 1;
+ bool isUnsigned = format.isUnsignedComponent(0);
+
+ uint32_t lastLayer = getLastLayerIndex(subresourceRange);
+ uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
+
+ int bytes = decompressedImage->format.bytes();
+
+ VkImageSubresourceLayers subresourceLayers = { subresourceRange.aspectMask, subresourceRange.baseMipLevel, subresourceRange.baseArrayLayer, 1 };
+ for(; subresourceLayers.baseArrayLayer <= lastLayer; subresourceLayers.baseArrayLayer++)
+ {
+ for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
+ {
+ VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
+
+ int xblocks = (mipLevelExtent.width + xBlockSize - 1) / xBlockSize;
+ int yblocks = (mipLevelExtent.height + yBlockSize - 1) / yBlockSize;
+ int zblocks = (zBlockSize > 1) ? (mipLevelExtent.depth + zBlockSize - 1) / zBlockSize : 1;
+
+ if(xblocks <= 0 || yblocks <= 0 || zblocks <= 0)
+ {
+ continue;
+ }
+
+ int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
+ int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
+
+ for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
+ {
+ uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresourceLayers));
+ uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresourceLayers));
+
+ ASTC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, mipLevelExtent.depth, bytes, pitchB, sliceB,
+ xBlockSize, yBlockSize, zBlockSize, xblocks, yblocks, zblocks, isUnsigned);
+ }
+ }
+ }
+}
+
} // namespace vk
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index d5303ea..23092e4 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -113,6 +113,7 @@
int borderSize() const;
void decodeETC2(const VkImageSubresourceRange &subresourceRange) const;
void decodeBC(const VkImageSubresourceRange &subresourceRange) const;
+ void decodeASTC(const VkImageSubresourceRange &subresourceRange) const;
const Device *const device = nullptr;
DeviceMemory *deviceMemory = nullptr;
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 42d9a8c..03df1e5 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -76,7 +76,7 @@
VK_FALSE, // multiViewport
VK_TRUE, // samplerAnisotropy
VK_TRUE, // textureCompressionETC2
- VK_FALSE, // textureCompressionASTC_LDR
+ VK_TRUE, // textureCompressionASTC_LDR
VK_FALSE, // textureCompressionBC
VK_FALSE, // occlusionQueryPrecise
VK_FALSE, // pipelineStatisticsQuery
@@ -527,6 +527,34 @@
case VK_FORMAT_EAC_R11_SNORM_BLOCK:
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
+ case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
+ case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
diff --git a/third_party/astc-encoder/Android.bp b/third_party/astc-encoder/Android.bp
new file mode 100644
index 0000000..0c81fa2
--- /dev/null
+++ b/third_party/astc-encoder/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "swiftshader_astc",
+
+ vendor_available: true,
+
+ cflags: [
+ "-DLOG_TAG=\"swiftshader\"",
+ ],
+
+ srcs: [
+ "Source/*.cpp",
+ ],
+
+ local_include_dirs: [
+ "Source",
+ ],
+
+ static_libs: [
+ "swiftshader_debug",
+ ]
+}
\ No newline at end of file
diff --git a/third_party/astc-encoder/LICENSE.txt b/third_party/astc-encoder/LICENSE.txt
new file mode 100644
index 0000000..b82735a
--- /dev/null
+++ b/third_party/astc-encoder/LICENSE.txt
@@ -0,0 +1,175 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/third_party/astc-encoder/Source/astc_block_sizes2.cpp b/third_party/astc-encoder/Source/astc_block_sizes2.cpp
new file mode 100644
index 0000000..a2a5423
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_block_sizes2.cpp
@@ -0,0 +1,910 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions to generate block size descriptor and decimation tables.
+ */
+
+#include "astc_codec_internals.h"
+#include <memory>
+
+struct TexelWeight
+{
+ int weightcount_of_texel[MAX_TEXELS_PER_BLOCK];
+ int grid_weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
+ int weights_of_texel[MAX_TEXELS_PER_BLOCK][4];
+
+ int texelcount_of_weight[MAX_WEIGHTS_PER_BLOCK];
+ int texels_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
+ int texelweights_of_weight[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK];
+};
+
+// return 0 on invalid mode, 1 on valid mode.
+static int decode_block_mode_2d(
+ int blockmode,
+ int* Nval,
+ int* Mval,
+ int* dual_weight_plane,
+ int* quant_mode
+) {
+ int base_quant_mode = (blockmode >> 4) & 1;
+ int H = (blockmode >> 9) & 1;
+ int D = (blockmode >> 10) & 1;
+
+ int A = (blockmode >> 5) & 0x3;
+
+ int N = 0, M = 0;
+
+ if ((blockmode & 3) != 0)
+ {
+ base_quant_mode |= (blockmode & 3) << 1;
+ int B = (blockmode >> 7) & 3;
+ switch ((blockmode >> 2) & 3)
+ {
+ case 0:
+ N = B + 4;
+ M = A + 2;
+ break;
+ case 1:
+ N = B + 8;
+ M = A + 2;
+ break;
+ case 2:
+ N = A + 2;
+ M = B + 8;
+ break;
+ case 3:
+ B &= 1;
+ if (blockmode & 0x100)
+ {
+ N = B + 2;
+ M = A + 2;
+ }
+ else
+ {
+ N = A + 2;
+ M = B + 6;
+ }
+ break;
+ }
+ }
+ else
+ {
+ base_quant_mode |= ((blockmode >> 2) & 3) << 1;
+ if (((blockmode >> 2) & 3) == 0)
+ return 0;
+ int B = (blockmode >> 9) & 3;
+ switch ((blockmode >> 7) & 3)
+ {
+ case 0:
+ N = 12;
+ M = A + 2;
+ break;
+ case 1:
+ N = A + 2;
+ M = 12;
+ break;
+ case 2:
+ N = A + 6;
+ M = B + 6;
+ D = 0;
+ H = 0;
+ break;
+ case 3:
+ switch ((blockmode >> 5) & 3)
+ {
+ case 0:
+ N = 6;
+ M = 10;
+ break;
+ case 1:
+ N = 10;
+ M = 6;
+ break;
+ case 2:
+ case 3:
+ return 0;
+ }
+ break;
+ }
+ }
+
+ int weight_count = N * M * (D + 1);
+ int qmode = (base_quant_mode - 2) + 6 * H;
+
+ int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
+ if (weight_count > MAX_WEIGHTS_PER_BLOCK || weightbits < MIN_WEIGHT_BITS_PER_BLOCK || weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
+ return 0;
+
+ *Nval = N;
+ *Mval = M;
+ *dual_weight_plane = D;
+ *quant_mode = qmode;
+ return 1;
+}
+
+static int decode_block_mode_3d(
+ int blockmode,
+ int* Nval,
+ int* Mval,
+ int* Qval,
+ int* dual_weight_plane,
+ int* quant_mode
+) {
+ int base_quant_mode = (blockmode >> 4) & 1;
+ int H = (blockmode >> 9) & 1;
+ int D = (blockmode >> 10) & 1;
+
+ int A = (blockmode >> 5) & 0x3;
+
+ int N = 0, M = 0, Q = 0;
+
+ if ((blockmode & 3) != 0)
+ {
+ base_quant_mode |= (blockmode & 3) << 1;
+ int B = (blockmode >> 7) & 3;
+ int C = (blockmode >> 2) & 0x3;
+ N = A + 2;
+ M = B + 2;
+ Q = C + 2;
+ }
+ else
+ {
+ base_quant_mode |= ((blockmode >> 2) & 3) << 1;
+ if (((blockmode >> 2) & 3) == 0)
+ return 0;
+ int B = (blockmode >> 9) & 3;
+ if (((blockmode >> 7) & 3) != 3)
+ {
+ D = 0;
+ H = 0;
+ }
+ switch ((blockmode >> 7) & 3)
+ {
+ case 0:
+ N = 6;
+ M = B + 2;
+ Q = A + 2;
+ break;
+ case 1:
+ N = A + 2;
+ M = 6;
+ Q = B + 2;
+ break;
+ case 2:
+ N = A + 2;
+ M = B + 2;
+ Q = 6;
+ break;
+ case 3:
+ N = 2;
+ M = 2;
+ Q = 2;
+ switch ((blockmode >> 5) & 3)
+ {
+ case 0:
+ N = 6;
+ break;
+ case 1:
+ M = 6;
+ break;
+ case 2:
+ Q = 6;
+ break;
+ case 3:
+ return 0;
+ }
+ break;
+ }
+ }
+
+ int weight_count = N * M * Q * (D + 1);
+ int qmode = (base_quant_mode - 2) + 6 * H;
+
+ int weightbits = compute_ise_bitcount(weight_count, (quantization_method) qmode);
+ if (weight_count > MAX_WEIGHTS_PER_BLOCK ||
+ weightbits < MIN_WEIGHT_BITS_PER_BLOCK ||
+ weightbits > MAX_WEIGHT_BITS_PER_BLOCK)
+ return 0;
+
+ *Nval = N;
+ *Mval = M;
+ *Qval = Q;
+ *dual_weight_plane = D;
+ *quant_mode = qmode;
+ return 1;
+}
+
+static void initialize_decimation_table_2d(
+ int xdim,
+ int ydim,
+ int x_weights,
+ int y_weights,
+ decimation_table* dt
+) {
+ int i, j;
+ int x, y;
+
+ int texels_per_block = xdim * ydim;
+ int weights_per_block = x_weights * y_weights;
+
+ std::unique_ptr<TexelWeight> tw(new TexelWeight);
+
+ for (i = 0; i < weights_per_block; i++)
+ tw->texelcount_of_weight[i] = 0;
+ for (i = 0; i < texels_per_block; i++)
+ tw->weightcount_of_texel[i] = 0;
+
+ for (y = 0; y < ydim; y++)
+ for (x = 0; x < xdim; x++)
+ {
+ int texel = y * xdim + x;
+
+ int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
+ int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
+
+ int x_weight_frac = x_weight & 0xF;
+ int y_weight_frac = y_weight & 0xF;
+ int x_weight_int = x_weight >> 4;
+ int y_weight_int = y_weight >> 4;
+ int qweight[4];
+ int weight[4];
+ qweight[0] = x_weight_int + y_weight_int * x_weights;
+ qweight[1] = qweight[0] + 1;
+ qweight[2] = qweight[0] + x_weights;
+ qweight[3] = qweight[2] + 1;
+
+ // truncated-precision bilinear interpolation.
+ int prod = x_weight_frac * y_weight_frac;
+
+ weight[3] = (prod + 8) >> 4;
+ weight[1] = x_weight_frac - weight[3];
+ weight[2] = y_weight_frac - weight[3];
+ weight[0] = 16 - x_weight_frac - y_weight_frac + weight[3];
+
+ for (i = 0; i < 4; i++)
+ if (weight[i] != 0)
+ {
+ tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
+ tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
+ tw->weightcount_of_texel[texel]++;
+ tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
+ tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
+ tw->texelcount_of_weight[qweight[i]]++;
+ }
+ }
+
+ for (i = 0; i < texels_per_block; i++)
+ {
+ dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
+
+ // ensure that all 4 entries are actually initialized.
+ // This allows a branch-free implementation of compute_value_of_texel_flt()
+ for (j = 0; j < 4; j++)
+ {
+ dt->texel_weights_int[i][j] = 0;
+ dt->texel_weights_float[i][j] = 0.0f;
+ dt->texel_weights[i][j] = 0;
+ }
+
+ for (j = 0; j < tw->weightcount_of_texel[i]; j++)
+ {
+ dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
+ dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
+ dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
+ }
+ }
+
+ for (i = 0; i < weights_per_block; i++)
+ {
+ dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
+
+ for (j = 0; j < tw->texelcount_of_weight[i]; j++)
+ {
+ int texel = tw->texels_of_weight[i][j];
+ dt->weight_texel[i][j] = (uint8_t)texel;
+ dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
+ dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
+
+ // perform a layer of array unrolling. An aspect of this unrolling is that
+ // one of the texel-weight indexes is an identity-mapped index; we will use this
+ // fact to reorder the indexes so that the first one is the identity index.
+ int swap_idx = -1;
+ for (int k = 0; k < 4; k++)
+ {
+ int dttw = dt->texel_weights[texel][k];
+ float dttwf = dt->texel_weights_float[texel][k];
+ if (dttw == i && dttwf != 0.0f)
+ swap_idx = k;
+ dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
+ dt->texel_weights_float_texel[i][j][k] = dttwf;
+ }
+
+ if (swap_idx != 0)
+ {
+ int vi = dt->texel_weights_texel[i][j][0];
+ float vf = dt->texel_weights_float_texel[i][j][0];
+ dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
+ dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
+ dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
+ dt->texel_weights_float_texel[i][j][swap_idx] = vf;
+ }
+ }
+ }
+
+ dt->num_texels = texels_per_block;
+ dt->num_weights = weights_per_block;
+}
+
+static void initialize_decimation_table_3d(
+ int xdim,
+ int ydim,
+ int zdim,
+ int x_weights,
+ int y_weights,
+ int z_weights,
+ decimation_table* dt
+) {
+ int i, j;
+ int x, y, z;
+
+ int texels_per_block = xdim * ydim * zdim;
+ int weights_per_block = x_weights * y_weights * z_weights;
+
+ std::unique_ptr<TexelWeight> tw(new TexelWeight);
+
+ for (i = 0; i < weights_per_block; i++)
+ tw->texelcount_of_weight[i] = 0;
+ for (i = 0; i < texels_per_block; i++)
+ tw->weightcount_of_texel[i] = 0;
+
+ for (z = 0; z < zdim; z++)
+ {
+ for (y = 0; y < ydim; y++)
+ {
+ for (x = 0; x < xdim; x++)
+ {
+ int texel = (z * ydim + y) * xdim + x;
+
+ int x_weight = (((1024 + xdim / 2) / (xdim - 1)) * x * (x_weights - 1) + 32) >> 6;
+ int y_weight = (((1024 + ydim / 2) / (ydim - 1)) * y * (y_weights - 1) + 32) >> 6;
+ int z_weight = (((1024 + zdim / 2) / (zdim - 1)) * z * (z_weights - 1) + 32) >> 6;
+
+ int x_weight_frac = x_weight & 0xF;
+ int y_weight_frac = y_weight & 0xF;
+ int z_weight_frac = z_weight & 0xF;
+ int x_weight_int = x_weight >> 4;
+ int y_weight_int = y_weight >> 4;
+ int z_weight_int = z_weight >> 4;
+ int qweight[4];
+ int weight[4];
+ qweight[0] = (z_weight_int * y_weights + y_weight_int) * x_weights + x_weight_int;
+ qweight[3] = ((z_weight_int + 1) * y_weights + (y_weight_int + 1)) * x_weights + (x_weight_int + 1);
+
+ // simplex interpolation
+ int fs = x_weight_frac;
+ int ft = y_weight_frac;
+ int fp = z_weight_frac;
+
+ int cas = ((fs > ft) << 2) + ((ft > fp) << 1) + ((fs > fp));
+ int N = x_weights;
+ int NM = x_weights * y_weights;
+
+ int s1, s2, w0, w1, w2, w3;
+ switch (cas)
+ {
+ case 7:
+ s1 = 1;
+ s2 = N;
+ w0 = 16 - fs;
+ w1 = fs - ft;
+ w2 = ft - fp;
+ w3 = fp;
+ break;
+ case 3:
+ s1 = N;
+ s2 = 1;
+ w0 = 16 - ft;
+ w1 = ft - fs;
+ w2 = fs - fp;
+ w3 = fp;
+ break;
+ case 5:
+ s1 = 1;
+ s2 = NM;
+ w0 = 16 - fs;
+ w1 = fs - fp;
+ w2 = fp - ft;
+ w3 = ft;
+ break;
+ case 4:
+ s1 = NM;
+ s2 = 1;
+ w0 = 16 - fp;
+ w1 = fp - fs;
+ w2 = fs - ft;
+ w3 = ft;
+ break;
+ case 2:
+ s1 = N;
+ s2 = NM;
+ w0 = 16 - ft;
+ w1 = ft - fp;
+ w2 = fp - fs;
+ w3 = fs;
+ break;
+ case 0:
+ s1 = NM;
+ s2 = N;
+ w0 = 16 - fp;
+ w1 = fp - ft;
+ w2 = ft - fs;
+ w3 = fs;
+ break;
+
+ default:
+ s1 = NM;
+ s2 = N;
+ w0 = 16 - fp;
+ w1 = fp - ft;
+ w2 = ft - fs;
+ w3 = fs;
+ break;
+ }
+
+ qweight[1] = qweight[0] + s1;
+ qweight[2] = qweight[1] + s2;
+ weight[0] = w0;
+ weight[1] = w1;
+ weight[2] = w2;
+ weight[3] = w3;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (weight[i] != 0)
+ {
+ tw->grid_weights_of_texel[texel][tw->weightcount_of_texel[texel]] = qweight[i];
+ tw->weights_of_texel[texel][tw->weightcount_of_texel[texel]] = weight[i];
+ tw->weightcount_of_texel[texel]++;
+ tw->texels_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = texel;
+ tw->texelweights_of_weight[qweight[i]][tw->texelcount_of_weight[qweight[i]]] = weight[i];
+ tw->texelcount_of_weight[qweight[i]]++;
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < texels_per_block; i++)
+ {
+ dt->texel_num_weights[i] = tw->weightcount_of_texel[i];
+
+ // ensure that all 4 entries are actually initialized.
+ // This allows a branch-free implementation of compute_value_of_texel_flt()
+ for (j = 0; j < 4; j++)
+ {
+ dt->texel_weights_int[i][j] = 0;
+ dt->texel_weights_float[i][j] = 0.0f;
+ dt->texel_weights[i][j] = 0;
+ }
+
+ for (j = 0; j < tw->weightcount_of_texel[i]; j++)
+ {
+ dt->texel_weights_int[i][j] = (uint8_t)(tw->weights_of_texel[i][j]);
+ dt->texel_weights_float[i][j] = ((float)(tw->weights_of_texel[i][j])) * (1.0f / TEXEL_WEIGHT_SUM);
+ dt->texel_weights[i][j] = (uint8_t)(tw->grid_weights_of_texel[i][j]);
+ }
+ }
+
+ for (i = 0; i < weights_per_block; i++)
+ {
+ dt->weight_num_texels[i] = tw->texelcount_of_weight[i];
+ for (j = 0; j < tw->texelcount_of_weight[i]; j++)
+ {
+ int texel = tw->texels_of_weight[i][j];
+ dt->weight_texel[i][j] = (uint8_t)texel;
+ dt->weights_int[i][j] = (uint8_t)(tw->texelweights_of_weight[i][j]);
+ dt->weights_flt[i][j] = (float)(tw->texelweights_of_weight[i][j]);
+
+ // perform a layer of array unrolling. An aspect of this unrolling is that
+ // one of the texel-weight indexes is an identity-mapped index; we will use this
+ // fact to reorder the indexes so that the first one is the identity index.
+ int swap_idx = -1;
+ for (int k = 0; k < 4; k++)
+ {
+ int dttw = dt->texel_weights[texel][k];
+ float dttwf = dt->texel_weights_float[texel][k];
+ if (dttw == i && dttwf != 0.0f)
+ swap_idx = k;
+ dt->texel_weights_texel[i][j][k] = (uint8_t)dttw;
+ dt->texel_weights_float_texel[i][j][k] = dttwf;
+ }
+
+ if (swap_idx != 0)
+ {
+ int vi = dt->texel_weights_texel[i][j][0];
+ float vf = dt->texel_weights_float_texel[i][j][0];
+ dt->texel_weights_texel[i][j][0] = dt->texel_weights_texel[i][j][swap_idx];
+ dt->texel_weights_float_texel[i][j][0] = dt->texel_weights_float_texel[i][j][swap_idx];
+ dt->texel_weights_texel[i][j][swap_idx] = (uint8_t)vi;
+ dt->texel_weights_float_texel[i][j][swap_idx] = vf;
+ }
+ }
+ }
+
+ dt->num_texels = texels_per_block;
+ dt->num_weights = weights_per_block;
+}
+
+static void construct_block_size_descriptor_2d(
+ int xdim,
+ int ydim,
+ block_size_descriptor* bsd
+) {
+ int decimation_mode_index[256]; // for each of the 256 entries in the decim_table_array, its index
+ int decimation_mode_count = 0;
+
+ bsd->xdim = xdim;
+ bsd->ydim = ydim;
+ bsd->zdim = 1;
+ bsd->texel_count = xdim * ydim;
+
+ for (int i = 0; i < 256; i++)
+ {
+ decimation_mode_index[i] = -1;
+ }
+
+ // gather all the infill-modes that can be used with the current block size
+ for (int x_weights = 2; x_weights <= 12; x_weights++)
+ {
+ for (int y_weights = 2; y_weights <= 12; y_weights++)
+ {
+ if (x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
+ {
+ continue;
+ }
+
+ decimation_table *dt = new decimation_table;
+ decimation_mode_index[y_weights * 16 + x_weights] = decimation_mode_count;
+ initialize_decimation_table_2d(xdim, ydim, x_weights, y_weights, dt);
+
+ int weight_count = x_weights * y_weights;
+
+ int maxprec_1plane = -1;
+ int maxprec_2planes = -1;
+ for (int i = 0; i < 12; i++)
+ {
+ int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
+ int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
+ if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
+ maxprec_1plane = i;
+ if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
+ maxprec_2planes = i;
+ }
+
+ if (2 * x_weights * y_weights > MAX_WEIGHTS_PER_BLOCK)
+ {
+ maxprec_2planes = -1;
+ }
+
+ bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim);
+
+ bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
+ bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
+ bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
+ bsd->decimation_tables[decimation_mode_count] = dt;
+
+ decimation_mode_count++;
+ }
+ }
+
+ for (int i = 0; i < MAX_DECIMATION_MODES; i++)
+ {
+ bsd->decimation_mode_percentile[i] = 1.0f;
+ }
+
+ for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
+ {
+ bsd->permit_encode[i] = 0;
+ bsd->decimation_mode_samples[i] = 0;
+ bsd->decimation_mode_maxprec_1plane[i] = -1;
+ bsd->decimation_mode_maxprec_2planes[i] = -1;
+ }
+
+ bsd->decimation_mode_count = decimation_mode_count;
+
+ const float *percentiles = get_2d_percentile_table(xdim, ydim);
+
+ // then construct the list of block formats
+ for (int i = 0; i < 2048; i++)
+ {
+ int x_weights, y_weights;
+ int is_dual_plane;
+ int quantization_mode;
+ int fail = 0;
+ int permit_encode = 1;
+
+ if (decode_block_mode_2d(i, &x_weights, &y_weights, &is_dual_plane, &quantization_mode))
+ {
+ if (x_weights > xdim || y_weights > ydim)
+ permit_encode = 0;
+ }
+ else
+ {
+ fail = 1;
+ permit_encode = 0;
+ }
+
+ if (fail)
+ {
+ bsd->block_modes[i].decimation_mode = -1;
+ bsd->block_modes[i].quantization_mode = -1;
+ bsd->block_modes[i].is_dual_plane = -1;
+ bsd->block_modes[i].permit_encode = 0;
+ bsd->block_modes[i].permit_decode = 0;
+ bsd->block_modes[i].percentile = 1.0f;
+ }
+ else
+ {
+ int decimation_mode = decimation_mode_index[y_weights * 16 + x_weights];
+ bsd->block_modes[i].decimation_mode = decimation_mode;
+ bsd->block_modes[i].quantization_mode = quantization_mode;
+ bsd->block_modes[i].is_dual_plane = is_dual_plane;
+ bsd->block_modes[i].permit_encode = permit_encode;
+ bsd->block_modes[i].permit_decode = permit_encode; // disallow decode of grid size larger than block size.
+ bsd->block_modes[i].percentile = percentiles[i];
+
+ if (bsd->decimation_mode_percentile[decimation_mode] > percentiles[i])
+ bsd->decimation_mode_percentile[decimation_mode] = percentiles[i];
+ }
+ }
+
+ delete[] percentiles;
+
+ if (xdim * ydim <= 64)
+ {
+ bsd->texelcount_for_bitmap_partitioning = xdim * ydim;
+ for (int i = 0; i < xdim * ydim; i++)
+ {
+ bsd->texels_for_bitmap_partitioning[i] = i;
+ }
+ }
+ else
+ {
+ uint64_t rng_state[2];
+ astc::rand_init(rng_state);
+
+ // pick 64 random texels for use with bitmap partitioning.
+ int arr[MAX_TEXELS_PER_BLOCK];
+ for (int i = 0; i < xdim * ydim; i++)
+ {
+ arr[i] = 0;
+ }
+
+ int arr_elements_set = 0;
+ while (arr_elements_set < 64)
+ {
+ unsigned int idx = (unsigned int)astc::rand(rng_state);
+ idx %= xdim * ydim;
+ if (arr[idx] == 0)
+ {
+ arr_elements_set++;
+ arr[idx] = 1;
+ }
+ }
+
+ int texel_weights_written = 0;
+ int idx = 0;
+ while (texel_weights_written < 64)
+ {
+ if (arr[idx])
+ {
+ bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
+ }
+ idx++;
+ }
+
+ bsd->texelcount_for_bitmap_partitioning = 64;
+ }
+}
+
+static void construct_block_size_descriptor_3d(
+ int xdim,
+ int ydim,
+ int zdim,
+ block_size_descriptor * bsd
+) {
+ int decimation_mode_index[512]; // for each of the 512 entries in the decim_table_array, its index
+ int decimation_mode_count = 0;
+
+ bsd->xdim = xdim;
+ bsd->ydim = ydim;
+ bsd->zdim = zdim;
+ bsd->texel_count = xdim * ydim * zdim;
+
+ for (int i = 0; i < 512; i++)
+ {
+ decimation_mode_index[i] = -1;
+ }
+
+ // gather all the infill-modes that can be used with the current block size
+ for (int x_weights = 2; x_weights <= 6; x_weights++)
+ {
+ for (int y_weights = 2; y_weights <= 6; y_weights++)
+ {
+ for (int z_weights = 2; z_weights <= 6; z_weights++)
+ {
+ if ((x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
+ continue;
+ decimation_table *dt = new decimation_table;
+ decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights] = decimation_mode_count;
+ initialize_decimation_table_3d(xdim, ydim, zdim, x_weights, y_weights, z_weights, dt);
+
+ int weight_count = x_weights * y_weights * z_weights;
+
+ int maxprec_1plane = -1;
+ int maxprec_2planes = -1;
+ for (int i = 0; i < 12; i++)
+ {
+ int bits_1plane = compute_ise_bitcount(weight_count, (quantization_method) i);
+ int bits_2planes = compute_ise_bitcount(2 * weight_count, (quantization_method) i);
+ if (bits_1plane >= MIN_WEIGHT_BITS_PER_BLOCK && bits_1plane <= MAX_WEIGHT_BITS_PER_BLOCK)
+ maxprec_1plane = i;
+ if (bits_2planes >= MIN_WEIGHT_BITS_PER_BLOCK && bits_2planes <= MAX_WEIGHT_BITS_PER_BLOCK)
+ maxprec_2planes = i;
+ }
+
+ if ((2 * x_weights * y_weights * z_weights) > MAX_WEIGHTS_PER_BLOCK)
+ maxprec_2planes = -1;
+
+ bsd->permit_encode[decimation_mode_count] = (x_weights <= xdim && y_weights <= ydim && z_weights <= zdim);
+
+ bsd->decimation_mode_samples[decimation_mode_count] = weight_count;
+ bsd->decimation_mode_maxprec_1plane[decimation_mode_count] = maxprec_1plane;
+ bsd->decimation_mode_maxprec_2planes[decimation_mode_count] = maxprec_2planes;
+ bsd->decimation_tables[decimation_mode_count] = dt;
+
+ decimation_mode_count++;
+ }
+ }
+ }
+
+ for (int i = 0; i < MAX_DECIMATION_MODES; i++)
+ {
+ bsd->decimation_mode_percentile[i] = 1.0f;
+ }
+
+ for (int i = decimation_mode_count; i < MAX_DECIMATION_MODES; i++)
+ {
+ bsd->permit_encode[i] = 0;
+ bsd->decimation_mode_samples[i] = 0;
+ bsd->decimation_mode_maxprec_1plane[i] = -1;
+ bsd->decimation_mode_maxprec_2planes[i] = -1;
+ }
+
+ bsd->decimation_mode_count = decimation_mode_count;
+
+ // then construct the list of block formats
+ for (int i = 0; i < 2048; i++)
+ {
+ int x_weights, y_weights, z_weights;
+ int is_dual_plane;
+ int quantization_mode;
+ int fail = 0;
+ int permit_encode = 1;
+
+ if (decode_block_mode_3d(i, &x_weights, &y_weights, &z_weights, &is_dual_plane, &quantization_mode))
+ {
+ if (x_weights > xdim || y_weights > ydim || z_weights > zdim)
+ permit_encode = 0;
+ }
+ else
+ {
+ fail = 1;
+ permit_encode = 0;
+ }
+ if (fail)
+ {
+ bsd->block_modes[i].decimation_mode = -1;
+ bsd->block_modes[i].quantization_mode = -1;
+ bsd->block_modes[i].is_dual_plane = -1;
+ bsd->block_modes[i].permit_encode = 0;
+ bsd->block_modes[i].permit_decode = 0;
+ bsd->block_modes[i].percentile = 1.0f;
+ }
+ else
+ {
+ int decimation_mode = decimation_mode_index[z_weights * 64 + y_weights * 8 + x_weights];
+ bsd->block_modes[i].decimation_mode = decimation_mode;
+ bsd->block_modes[i].quantization_mode = quantization_mode;
+ bsd->block_modes[i].is_dual_plane = is_dual_plane;
+ bsd->block_modes[i].permit_encode = permit_encode;
+ bsd->block_modes[i].permit_decode = permit_encode;
+
+ bsd->block_modes[i].percentile = 0.0f; // No percentile table
+ if (bsd->decimation_mode_percentile[decimation_mode] > 0.0f)
+ bsd->decimation_mode_percentile[decimation_mode] = 0.0f;
+ }
+ }
+
+ if (xdim * ydim * zdim <= 64)
+ {
+ bsd->texelcount_for_bitmap_partitioning = xdim * ydim * zdim;
+ for (int i = 0; i < xdim * ydim * zdim; i++)
+ {
+ bsd->texels_for_bitmap_partitioning[i] = i;
+ }
+ }
+ else
+ {
+ uint64_t rng_state[2];
+ astc::rand_init(rng_state);
+
+ // pick 64 random texels for use with bitmap partitioning.
+ int arr[MAX_TEXELS_PER_BLOCK];
+ for (int i = 0; i < xdim * ydim * zdim; i++)
+ {
+ arr[i] = 0;
+ }
+
+ int arr_elements_set = 0;
+ while (arr_elements_set < 64)
+ {
+ unsigned int idx = (unsigned int)astc::rand(rng_state);
+ idx %= xdim * ydim * zdim;
+ if (arr[idx] == 0)
+ {
+ arr_elements_set++;
+ arr[idx] = 1;
+ }
+ }
+
+ int texel_weights_written = 0;
+ int idx = 0;
+ while (texel_weights_written < 64)
+ {
+ if (arr[idx])
+ bsd->texels_for_bitmap_partitioning[texel_weights_written++] = idx;
+ idx++;
+ }
+ bsd->texelcount_for_bitmap_partitioning = 64;
+ }
+}
+
+/* Public function, see header file for detailed documentation */
+void init_block_size_descriptor(
+ int xdim,
+ int ydim,
+ int zdim,
+ block_size_descriptor* bsd
+) {
+ if (zdim > 1)
+ construct_block_size_descriptor_3d(xdim, ydim, zdim, bsd);
+ else
+ construct_block_size_descriptor_2d(xdim, ydim, bsd);
+
+ init_partition_tables(bsd);
+}
+
+void term_block_size_descriptor(
+ block_size_descriptor* bsd)
+{
+ for(int i = 0; i < bsd->decimation_mode_count; i++)
+ {
+ delete bsd->decimation_tables[i];
+ }
+}
diff --git a/third_party/astc-encoder/Source/astc_codec_internals.h b/third_party/astc-encoder/Source/astc_codec_internals.h
new file mode 100644
index 0000000..64fba10
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_codec_internals.h
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions and data declarations.
+ */
+
+#ifndef ASTC_CODEC_INTERNALS_INCLUDED
+#define ASTC_CODEC_INTERNALS_INCLUDED
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+#include "astc_mathlib.h"
+
+// ASTC parameters
+#define MAX_TEXELS_PER_BLOCK 216
+#define MAX_WEIGHTS_PER_BLOCK 64
+#define MIN_WEIGHT_BITS_PER_BLOCK 24
+#define MAX_WEIGHT_BITS_PER_BLOCK 96
+#define PARTITION_BITS 10
+#define PARTITION_COUNT (1 << PARTITION_BITS)
+
+// the sum of weights for one texel.
+#define TEXEL_WEIGHT_SUM 16
+#define MAX_DECIMATION_MODES 87
+#define MAX_WEIGHT_MODES 2048
+
+enum astc_decode_mode
+{
+ DECODE_LDR_SRGB,
+ DECODE_LDR,
+ DECODE_HDR
+};
+
+/*
+ Partition table representation:
+ For each block size, we have 3 tables, each with 1024 partitionings;
+ these three tables correspond to 2, 3 and 4 partitions respectively.
+ For each partitioning, we have:
+ * a 4-entry table indicating how many texels there are in each of the 4 partitions.
+ This may be from 0 to a very large value.
+ * a table indicating the partition index of each of the texels in the block.
+ Each index may be 0, 1, 2 or 3.
+ * Each element in the table is an uint8_t indicating partition index (0, 1, 2 or 3)
+*/
+
+struct partition_info
+{
+ int partition_count;
+ uint8_t texels_per_partition[4];
+ uint8_t partition_of_texel[MAX_TEXELS_PER_BLOCK];
+ uint8_t texels_of_partition[4][MAX_TEXELS_PER_BLOCK];
+ uint64_t coverage_bitmaps[4];
+};
+
+/*
+ In ASTC, we don't necessarily provide a weight for every texel.
+ As such, for each block size, there are a number of patterns where some texels
+ have their weights computed as a weighted average of more than 1 weight.
+ As such, the codec uses a data structure that tells us: for each texel, which
+ weights it is a combination of for each weight, which texels it contributes to.
+ The decimation_table is this data structure.
+*/
+struct decimation_table
+{
+ int num_texels;
+ int num_weights;
+ uint8_t texel_num_weights[MAX_TEXELS_PER_BLOCK]; // number of indices that go into the calculation for a texel
+ uint8_t texel_weights_int[MAX_TEXELS_PER_BLOCK][4]; // the weight to assign to each weight
+ float texel_weights_float[MAX_TEXELS_PER_BLOCK][4]; // the weight to assign to each weight
+ uint8_t texel_weights[MAX_TEXELS_PER_BLOCK][4]; // the weights that go into a texel calculation
+ uint8_t weight_num_texels[MAX_WEIGHTS_PER_BLOCK]; // the number of texels that a given weight contributes to
+ uint8_t weight_texel[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK]; // the texels that the weight contributes to
+ uint8_t weights_int[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK]; // the weights that the weight contributes to a texel.
+ float weights_flt[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK]; // the weights that the weight contributes to a texel.
+
+ // folded data structures:
+ // * texel_weights_texel[i][j] = texel_weights[weight_texel[i][j]];
+ // * texel_weights_float_texel[i][j] = texel_weights_float[weight_texel[i][j]
+ uint8_t texel_weights_texel[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK][4];
+ float texel_weights_float_texel[MAX_WEIGHTS_PER_BLOCK][MAX_TEXELS_PER_BLOCK][4];
+};
+
+/*
+ data structure describing information that pertains to a block size and its associated block modes.
+*/
+struct block_mode
+{
+ int8_t decimation_mode;
+ int8_t quantization_mode;
+ int8_t is_dual_plane;
+ int8_t permit_encode;
+ int8_t permit_decode;
+ float percentile;
+};
+
+struct block_size_descriptor
+{
+ int xdim;
+ int ydim;
+ int zdim;
+ int texel_count;
+
+ int decimation_mode_count;
+ int decimation_mode_samples[MAX_DECIMATION_MODES];
+ int decimation_mode_maxprec_1plane[MAX_DECIMATION_MODES];
+ int decimation_mode_maxprec_2planes[MAX_DECIMATION_MODES];
+ float decimation_mode_percentile[MAX_DECIMATION_MODES];
+ int permit_encode[MAX_DECIMATION_MODES];
+ const decimation_table *decimation_tables[MAX_DECIMATION_MODES];
+ block_mode block_modes[MAX_WEIGHT_MODES];
+
+ // for the k-means bed bitmap partitioning algorithm, we don't
+ // want to consider more than 64 texels; this array specifies
+ // which 64 texels (if that many) to consider.
+ int texelcount_for_bitmap_partitioning;
+ int texels_for_bitmap_partitioning[64];
+
+ // All the partitioning information for this block size
+ partition_info partitions[(3*PARTITION_COUNT)+1];
+};
+
+// data structure representing one block of an image.
+// it is expanded to float prior to processing to save some computation time
+// on conversions to/from uint8_t (this also allows us to handle HDR textures easily)
+struct imageblock
+{
+ float orig_data[MAX_TEXELS_PER_BLOCK * 4]; // original input data
+ float data_r[MAX_TEXELS_PER_BLOCK]; // the data that we will compress, either linear or LNS (0..65535 in both cases)
+ float data_g[MAX_TEXELS_PER_BLOCK];
+ float data_b[MAX_TEXELS_PER_BLOCK];
+ float data_a[MAX_TEXELS_PER_BLOCK];
+
+ uint8_t rgb_lns[MAX_TEXELS_PER_BLOCK]; // 1 if RGB data are being treated as LNS
+ uint8_t alpha_lns[MAX_TEXELS_PER_BLOCK]; // 1 if Alpha data are being treated as LNS
+ uint8_t nan_texel[MAX_TEXELS_PER_BLOCK]; // 1 if the texel is a NaN-texel.
+
+ float red_min, red_max;
+ float green_min, green_max;
+ float blue_min, blue_max;
+ float alpha_min, alpha_max;
+ int grayscale; // 1 if R=G=B for every pixel, 0 otherwise
+
+ int xpos, ypos, zpos;
+};
+
+void update_imageblock_flags(
+ imageblock* pb,
+ int xdim,
+ int ydim,
+ int zdim);
+
+void imageblock_initialize_orig_from_work(
+ imageblock * pb,
+ int pixelcount);
+
+void imageblock_initialize_work_from_orig(
+ imageblock * pb,
+ int pixelcount);
+
+// enumeration of all the quantization methods we support under this format.
+enum quantization_method
+{
+ QUANT_2 = 0,
+ QUANT_3 = 1,
+ QUANT_4 = 2,
+ QUANT_5 = 3,
+ QUANT_6 = 4,
+ QUANT_8 = 5,
+ QUANT_10 = 6,
+ QUANT_12 = 7,
+ QUANT_16 = 8,
+ QUANT_20 = 9,
+ QUANT_24 = 10,
+ QUANT_32 = 11,
+ QUANT_40 = 12,
+ QUANT_48 = 13,
+ QUANT_64 = 14,
+ QUANT_80 = 15,
+ QUANT_96 = 16,
+ QUANT_128 = 17,
+ QUANT_160 = 18,
+ QUANT_192 = 19,
+ QUANT_256 = 20
+};
+
+/**
+ * @brief Weight quantization transfer table.
+ *
+ * ASTC can store texel weights at many quantization levels, so for performance
+ * we store essential information about each level as a precomputed data
+ * structure.
+ *
+ * Unquantized weights are integers in the range [0, 64], or floats [0, 1].
+ *
+ * This structure provides the following information:
+ * A table, used to estimate the closest quantized
+ weight for a given floating-point weight. For each quantized weight, the corresponding unquantized
+ and floating-point values. For each quantized weight, a previous-value and a next-value.
+*/
+struct quantization_and_transfer_table
+{
+ /** The quantization level used */
+ quantization_method method;
+ /** The unscrambled unquantized value. */
+ // TODO: Converted to floats to support AVX gathers
+ float unquantized_value_unsc[33];
+ /** The scrambling order: value[map[i]] == value_unsc[i] */
+ // TODO: Converted to u32 to support AVX gathers
+ int32_t scramble_map[32];
+ /** The scrambled unquantized values. */
+ uint8_t unquantized_value[32];
+ /**
+ * An encoded table of previous-and-next weight values, indexed by the
+ * current unquantized value.
+ * * bits 7:0 = previous-index, unquantized
+ * * bits 15:8 = next-index, unquantized
+ * * bits 23:16 = previous-index, quantized
+ * * bits 31:24 = next-index, quantized
+ */
+ uint32_t prev_next_values[65];
+};
+
+extern const quantization_and_transfer_table quant_and_xfer_tables[12];
+
+enum endpoint_formats
+{
+ FMT_LUMINANCE = 0,
+ FMT_LUMINANCE_DELTA = 1,
+ FMT_HDR_LUMINANCE_LARGE_RANGE = 2,
+ FMT_HDR_LUMINANCE_SMALL_RANGE = 3,
+ FMT_LUMINANCE_ALPHA = 4,
+ FMT_LUMINANCE_ALPHA_DELTA = 5,
+ FMT_RGB_SCALE = 6,
+ FMT_HDR_RGB_SCALE = 7,
+ FMT_RGB = 8,
+ FMT_RGB_DELTA = 9,
+ FMT_RGB_SCALE_ALPHA = 10,
+ FMT_HDR_RGB = 11,
+ FMT_RGBA = 12,
+ FMT_RGBA_DELTA = 13,
+ FMT_HDR_RGB_LDR_ALPHA = 14,
+ FMT_HDR_RGBA = 15,
+};
+
+struct symbolic_compressed_block
+{
+ int error_block; // 1 marks error block, 0 marks non-error-block.
+ int block_mode; // 0 to 2047. Negative value marks constant-color block (-1: FP16, -2:UINT16)
+ int partition_count; // 1 to 4; Zero marks a constant-color block.
+ int partition_index; // 0 to 1023
+ int color_formats[4]; // color format for each endpoint color pair.
+ int color_formats_matched; // color format for all endpoint pairs are matched.
+ int color_values[4][12]; // quantized endpoint color pairs.
+ int color_quantization_level;
+ uint8_t plane1_weights[MAX_WEIGHTS_PER_BLOCK]; // quantized and decimated weights
+ uint8_t plane2_weights[MAX_WEIGHTS_PER_BLOCK];
+ int plane2_color_component; // color component for the secondary plane of weights
+ int constant_color[4]; // constant-color, as FP16 or UINT16. Used for constant-color blocks only.
+};
+
+struct physical_compressed_block
+{
+ uint8_t data[16];
+};
+
+/* ============================================================================
+ Functions and data pertaining to quantization and encoding
+============================================================================ */
+
+/**
+ * @brief Populate the blocksize descriptor for the target block size.
+ *
+ * This will also initialize the partition table metadata, which is stored
+ * as part of the BSD structure.
+ *
+ * @param xdim The x axis size of the block.
+ * @param ydim The y axis size of the block.
+ * @param zdim The z axis size of the block.
+ * @param bsd The structure to populate.
+ */
+void init_block_size_descriptor(
+ int xdim,
+ int ydim,
+ int zdim,
+ block_size_descriptor* bsd);
+
+void term_block_size_descriptor(
+ block_size_descriptor* bsd);
+
+/**
+ * @brief Populate the partition tables for the target block size.
+ *
+ * Note the block_size_size descriptor must be initialized before calling this
+ * function.
+ *
+ * @param bsd The structure to populate.
+ */
+void init_partition_tables(
+ block_size_descriptor* bsd);
+
+static inline const partition_info *get_partition_table(
+ const block_size_descriptor* bsd,
+ int partition_count
+) {
+ if (partition_count == 1) {
+ partition_count = 5;
+ }
+ int index = (partition_count - 2) * PARTITION_COUNT;
+ return bsd->partitions + index;
+}
+
+/**
+ * @brief Get the percentile table for 2D block modes.
+ *
+ * This is an empirically determined prioritization of which block modes to
+ * use in the search in terms of their centile (lower centiles = more useful).
+ *
+ * Returns a dynamically allocated array; caller must free with delete[].
+ *
+ * @param xdim The block x size.
+ * @param ydim The block y size.
+ *
+ * @return The unpacked table.
+ */
+const float *get_2d_percentile_table(
+ int xdim,
+ int ydim);
+
+// ***********************************************************
+// functions and data pertaining to quantization and encoding
+// **********************************************************
+
+extern const uint8_t color_unquantization_tables[21][256];
+extern int quantization_mode_table[17][128];
+
+void decode_ise(
+ int quantization_level,
+ int elements,
+ const uint8_t* input_data,
+ uint8_t* output_data,
+ int bit_offset);
+
+int compute_ise_bitcount(
+ int items,
+ quantization_method quant);
+
+void build_quantization_mode_table(void);
+
+// unpack a pair of color endpoints from a series of integers.
+void unpack_color_endpoints(
+ astc_decode_mode decode_mode,
+ int format,
+ int quantization_level,
+ const int* input,
+ int* rgb_hdr,
+ int* alpha_hdr,
+ int* nan_endpoint,
+ uint4* output0,
+ uint4* output1);
+
+/* *********************************** high-level encode and decode functions ************************************ */
+
+void decompress_symbolic_block(
+ astc_decode_mode decode_mode,
+ const block_size_descriptor* bsd,
+ int xpos,
+ int ypos,
+ int zpos,
+ const symbolic_compressed_block* scb,
+ imageblock* blk);
+
+void physical_to_symbolic(
+ const block_size_descriptor* bsd,
+ physical_compressed_block pb,
+ symbolic_compressed_block* res);
+
+uint16_t unorm16_to_sf16(
+ uint16_t p);
+
+uint16_t lns_to_sf16(
+ uint16_t p);
+
+#endif
diff --git a/third_party/astc-encoder/Source/astc_color_unquantize.cpp b/third_party/astc-encoder/Source/astc_color_unquantize.cpp
new file mode 100644
index 0000000..b510cef
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_color_unquantize.cpp
@@ -0,0 +1,997 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions for color unquantization.
+ */
+
+#include "astc_codec_internals.h"
+#include "System/Debug.hpp"
+
+static int rgb_delta_unpack(
+ const int input[6],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ // unquantize the color endpoints
+ int r0 = color_unquantization_tables[quantization_level][input[0]];
+ int g0 = color_unquantization_tables[quantization_level][input[2]];
+ int b0 = color_unquantization_tables[quantization_level][input[4]];
+
+ int r1 = color_unquantization_tables[quantization_level][input[1]];
+ int g1 = color_unquantization_tables[quantization_level][input[3]];
+ int b1 = color_unquantization_tables[quantization_level][input[5]];
+
+ // perform the bit-transfer procedure
+ r0 |= (r1 & 0x80) << 1;
+ g0 |= (g1 & 0x80) << 1;
+ b0 |= (b1 & 0x80) << 1;
+ r1 &= 0x7F;
+ g1 &= 0x7F;
+ b1 &= 0x7F;
+ if (r1 & 0x40)
+ r1 -= 0x80;
+ if (g1 & 0x40)
+ g1 -= 0x80;
+ if (b1 & 0x40)
+ b1 -= 0x80;
+
+ r0 >>= 1;
+ g0 >>= 1;
+ b0 >>= 1;
+ r1 >>= 1;
+ g1 >>= 1;
+ b1 >>= 1;
+
+ int rgbsum = r1 + g1 + b1;
+
+ r1 += r0;
+ g1 += g0;
+ b1 += b0;
+
+ int retval;
+
+ int r0e, g0e, b0e;
+ int r1e, g1e, b1e;
+
+ if (rgbsum >= 0)
+ {
+ r0e = r0;
+ g0e = g0;
+ b0e = b0;
+
+ r1e = r1;
+ g1e = g1;
+ b1e = b1;
+
+ retval = 0;
+ }
+ else
+ {
+ r0e = (r1 + b1) >> 1;
+ g0e = (g1 + b1) >> 1;
+ b0e = b1;
+
+ r1e = (r0 + b0) >> 1;
+ g1e = (g0 + b0) >> 1;
+ b1e = b0;
+
+ retval = 1;
+ }
+
+ if (r0e < 0)
+ r0e = 0;
+ else if (r0e > 255)
+ r0e = 255;
+
+ if (g0e < 0)
+ g0e = 0;
+ else if (g0e > 255)
+ g0e = 255;
+
+ if (b0e < 0)
+ b0e = 0;
+ else if (b0e > 255)
+ b0e = 255;
+
+ if (r1e < 0)
+ r1e = 0;
+ else if (r1e > 255)
+ r1e = 255;
+
+ if (g1e < 0)
+ g1e = 0;
+ else if (g1e > 255)
+ g1e = 255;
+
+ if (b1e < 0)
+ b1e = 0;
+ else if (b1e > 255)
+ b1e = 255;
+
+ output0->x = r0e;
+ output0->y = g0e;
+ output0->z = b0e;
+ output0->w = 0xFF;
+
+ output1->x = r1e;
+ output1->y = g1e;
+ output1->z = b1e;
+ output1->w = 0xFF;
+
+ return retval;
+}
+
+static int rgb_unpack(
+ const int input[6],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int ri0b = color_unquantization_tables[quantization_level][input[0]];
+ int ri1b = color_unquantization_tables[quantization_level][input[1]];
+ int gi0b = color_unquantization_tables[quantization_level][input[2]];
+ int gi1b = color_unquantization_tables[quantization_level][input[3]];
+ int bi0b = color_unquantization_tables[quantization_level][input[4]];
+ int bi1b = color_unquantization_tables[quantization_level][input[5]];
+
+ if (ri0b + gi0b + bi0b > ri1b + gi1b + bi1b)
+ {
+ // blue-contraction
+ ri0b = (ri0b + bi0b) >> 1;
+ gi0b = (gi0b + bi0b) >> 1;
+ ri1b = (ri1b + bi1b) >> 1;
+ gi1b = (gi1b + bi1b) >> 1;
+
+ output0->x = ri1b;
+ output0->y = gi1b;
+ output0->z = bi1b;
+ output0->w = 255;
+
+ output1->x = ri0b;
+ output1->y = gi0b;
+ output1->z = bi0b;
+ output1->w = 255;
+ return 1;
+ }
+ else
+ {
+ output0->x = ri0b;
+ output0->y = gi0b;
+ output0->z = bi0b;
+ output0->w = 255;
+
+ output1->x = ri1b;
+ output1->y = gi1b;
+ output1->z = bi1b;
+ output1->w = 255;
+ return 0;
+ }
+}
+
+static void rgba_unpack(
+ const int input[8],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int order = rgb_unpack(input, quantization_level, output0, output1);
+ if (order == 0)
+ {
+ output0->w = color_unquantization_tables[quantization_level][input[6]];
+ output1->w = color_unquantization_tables[quantization_level][input[7]];
+ }
+ else
+ {
+ output0->w = color_unquantization_tables[quantization_level][input[7]];
+ output1->w = color_unquantization_tables[quantization_level][input[6]];
+ }
+}
+
+static void rgba_delta_unpack(
+ const int input[8],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int a0 = color_unquantization_tables[quantization_level][input[6]];
+ int a1 = color_unquantization_tables[quantization_level][input[7]];
+ a0 |= (a1 & 0x80) << 1;
+ a1 &= 0x7F;
+ if (a1 & 0x40)
+ a1 -= 0x80;
+ a0 >>= 1;
+ a1 >>= 1;
+ a1 += a0;
+
+ if (a1 < 0)
+ a1 = 0;
+ else if (a1 > 255)
+ a1 = 255;
+
+ int order = rgb_delta_unpack(input, quantization_level, output0, output1);
+ if (order == 0)
+ {
+ output0->w = a0;
+ output1->w = a1;
+ }
+ else
+ {
+ output0->w = a1;
+ output1->w = a0;
+ }
+}
+
+static void rgb_scale_unpack(
+ const int input[4],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int ir = color_unquantization_tables[quantization_level][input[0]];
+ int ig = color_unquantization_tables[quantization_level][input[1]];
+ int ib = color_unquantization_tables[quantization_level][input[2]];
+
+ int iscale = color_unquantization_tables[quantization_level][input[3]];
+
+ *output1 = uint4(ir, ig, ib, 255);
+ *output0 = uint4((ir * iscale) >> 8, (ig * iscale) >> 8, (ib * iscale) >> 8, 255);
+}
+
+static void rgb_scale_alpha_unpack(
+ const int input[6],
+ int quantization_level,
+ uint4 * output0,
+ uint4 * output1
+) {
+ rgb_scale_unpack(input, quantization_level, output0, output1);
+ output0->w = color_unquantization_tables[quantization_level][input[4]];
+ output1->w = color_unquantization_tables[quantization_level][input[5]];
+}
+
+static void luminance_unpack(
+ const int input[2],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int lum0 = color_unquantization_tables[quantization_level][input[0]];
+ int lum1 = color_unquantization_tables[quantization_level][input[1]];
+ *output0 = uint4(lum0, lum0, lum0, 255);
+ *output1 = uint4(lum1, lum1, lum1, 255);
+}
+
+static void luminance_delta_unpack(
+ const int input[2],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int v0 = color_unquantization_tables[quantization_level][input[0]];
+ int v1 = color_unquantization_tables[quantization_level][input[1]];
+ int l0 = (v0 >> 2) | (v1 & 0xC0);
+ int l1 = l0 + (v1 & 0x3F);
+
+ if (l1 > 255)
+ l1 = 255;
+
+ *output0 = uint4(l0, l0, l0, 255);
+ *output1 = uint4(l1, l1, l1, 255);
+}
+
+static void luminance_alpha_unpack(
+ const int input[4],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int lum0 = color_unquantization_tables[quantization_level][input[0]];
+ int lum1 = color_unquantization_tables[quantization_level][input[1]];
+ int alpha0 = color_unquantization_tables[quantization_level][input[2]];
+ int alpha1 = color_unquantization_tables[quantization_level][input[3]];
+ *output0 = uint4(lum0, lum0, lum0, alpha0);
+ *output1 = uint4(lum1, lum1, lum1, alpha1);
+}
+
+static void luminance_alpha_delta_unpack(
+ const int input[4],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int lum0 = color_unquantization_tables[quantization_level][input[0]];
+ int lum1 = color_unquantization_tables[quantization_level][input[1]];
+ int alpha0 = color_unquantization_tables[quantization_level][input[2]];
+ int alpha1 = color_unquantization_tables[quantization_level][input[3]];
+
+ lum0 |= (lum1 & 0x80) << 1;
+ alpha0 |= (alpha1 & 0x80) << 1;
+ lum1 &= 0x7F;
+ alpha1 &= 0x7F;
+ if (lum1 & 0x40)
+ lum1 -= 0x80;
+ if (alpha1 & 0x40)
+ alpha1 -= 0x80;
+
+ lum0 >>= 1;
+ lum1 >>= 1;
+ alpha0 >>= 1;
+ alpha1 >>= 1;
+ lum1 += lum0;
+ alpha1 += alpha0;
+
+ if (lum1 < 0)
+ lum1 = 0;
+ else if (lum1 > 255)
+ lum1 = 255;
+
+ if (alpha1 < 0)
+ alpha1 = 0;
+ else if (alpha1 > 255)
+ alpha1 = 255;
+
+ *output0 = uint4(lum0, lum0, lum0, alpha0);
+ *output1 = uint4(lum1, lum1, lum1, alpha1);
+}
+
+// RGB-offset format
+static void hdr_rgbo_unpack3(
+ const int input[4],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int v0 = color_unquantization_tables[quantization_level][input[0]];
+ int v1 = color_unquantization_tables[quantization_level][input[1]];
+ int v2 = color_unquantization_tables[quantization_level][input[2]];
+ int v3 = color_unquantization_tables[quantization_level][input[3]];
+
+ int modeval = ((v0 & 0xC0) >> 6) | (((v1 & 0x80) >> 7) << 2) | (((v2 & 0x80) >> 7) << 3);
+
+ int majcomp;
+ int mode;
+ if ((modeval & 0xC) != 0xC)
+ {
+ majcomp = modeval >> 2;
+ mode = modeval & 3;
+ }
+ else if (modeval != 0xF)
+ {
+ majcomp = modeval & 3;
+ mode = 4;
+ }
+ else
+ {
+ majcomp = 0;
+ mode = 5;
+ }
+
+ int red = v0 & 0x3F;
+ int green = v1 & 0x1F;
+ int blue = v2 & 0x1F;
+ int scale = v3 & 0x1F;
+
+ int bit0 = (v1 >> 6) & 1;
+ int bit1 = (v1 >> 5) & 1;
+ int bit2 = (v2 >> 6) & 1;
+ int bit3 = (v2 >> 5) & 1;
+ int bit4 = (v3 >> 7) & 1;
+ int bit5 = (v3 >> 6) & 1;
+ int bit6 = (v3 >> 5) & 1;
+
+ int ohcomp = 1 << mode;
+
+ if (ohcomp & 0x30)
+ green |= bit0 << 6;
+ if (ohcomp & 0x3A)
+ green |= bit1 << 5;
+ if (ohcomp & 0x30)
+ blue |= bit2 << 6;
+ if (ohcomp & 0x3A)
+ blue |= bit3 << 5;
+
+ if (ohcomp & 0x3D)
+ scale |= bit6 << 5;
+ if (ohcomp & 0x2D)
+ scale |= bit5 << 6;
+ if (ohcomp & 0x04)
+ scale |= bit4 << 7;
+
+ if (ohcomp & 0x3B)
+ red |= bit4 << 6;
+ if (ohcomp & 0x04)
+ red |= bit3 << 6;
+
+ if (ohcomp & 0x10)
+ red |= bit5 << 7;
+ if (ohcomp & 0x0F)
+ red |= bit2 << 7;
+
+ if (ohcomp & 0x05)
+ red |= bit1 << 8;
+ if (ohcomp & 0x0A)
+ red |= bit0 << 8;
+
+ if (ohcomp & 0x05)
+ red |= bit0 << 9;
+ if (ohcomp & 0x02)
+ red |= bit6 << 9;
+
+ if (ohcomp & 0x01)
+ red |= bit3 << 10;
+ if (ohcomp & 0x02)
+ red |= bit5 << 10;
+
+ // expand to 12 bits.
+ static const int shamts[6] = { 1, 1, 2, 3, 4, 5 };
+ int shamt = shamts[mode];
+ red <<= shamt;
+ green <<= shamt;
+ blue <<= shamt;
+ scale <<= shamt;
+
+ // on modes 0 to 4, the values stored for "green" and "blue" are differentials,
+ // not absolute values.
+ if (mode != 5)
+ {
+ green = red - green;
+ blue = red - blue;
+ }
+
+ // switch around components.
+ int temp;
+ switch (majcomp)
+ {
+ case 1:
+ temp = red;
+ red = green;
+ green = temp;
+ break;
+ case 2:
+ temp = red;
+ red = blue;
+ blue = temp;
+ break;
+ default:
+ break;
+ }
+
+ int red0 = red - scale;
+ int green0 = green - scale;
+ int blue0 = blue - scale;
+
+ // clamp to [0,0xFFF].
+ if (red < 0)
+ red = 0;
+ if (green < 0)
+ green = 0;
+ if (blue < 0)
+ blue = 0;
+
+ if (red0 < 0)
+ red0 = 0;
+ if (green0 < 0)
+ green0 = 0;
+ if (blue0 < 0)
+ blue0 = 0;
+
+ *output0 = uint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
+ *output1 = uint4(red << 4, green << 4, blue << 4, 0x7800);
+}
+
+static void hdr_rgb_unpack3(
+ const int input[6],
+ int quantization_level,
+ uint4* output0,
+ uint4 * output1
+) {
+
+ int v0 = color_unquantization_tables[quantization_level][input[0]];
+ int v1 = color_unquantization_tables[quantization_level][input[1]];
+ int v2 = color_unquantization_tables[quantization_level][input[2]];
+ int v3 = color_unquantization_tables[quantization_level][input[3]];
+ int v4 = color_unquantization_tables[quantization_level][input[4]];
+ int v5 = color_unquantization_tables[quantization_level][input[5]];
+
+ // extract all the fixed-placement bitfields
+ int modeval = ((v1 & 0x80) >> 7) | (((v2 & 0x80) >> 7) << 1) | (((v3 & 0x80) >> 7) << 2);
+
+ int majcomp = ((v4 & 0x80) >> 7) | (((v5 & 0x80) >> 7) << 1);
+
+ if (majcomp == 3)
+ {
+ *output0 = uint4(v0 << 8, v2 << 8, (v4 & 0x7F) << 9, 0x7800);
+ *output1 = uint4(v1 << 8, v3 << 8, (v5 & 0x7F) << 9, 0x7800);
+ return;
+ }
+
+ int a = v0 | ((v1 & 0x40) << 2);
+ int b0 = v2 & 0x3f;
+ int b1 = v3 & 0x3f;
+ int c = v1 & 0x3f;
+ int d0 = v4 & 0x7f;
+ int d1 = v5 & 0x7f;
+
+ // get hold of the number of bits in 'd0' and 'd1'
+ static const int dbits_tab[8] = { 7, 6, 7, 6, 5, 6, 5, 6 };
+ int dbits = dbits_tab[modeval];
+
+ // extract six variable-placement bits
+ int bit0 = (v2 >> 6) & 1;
+ int bit1 = (v3 >> 6) & 1;
+
+ int bit2 = (v4 >> 6) & 1;
+ int bit3 = (v5 >> 6) & 1;
+ int bit4 = (v4 >> 5) & 1;
+ int bit5 = (v5 >> 5) & 1;
+
+ // and prepend the variable-placement bits depending on mode.
+ int ohmod = 1 << modeval; // one-hot-mode
+ if (ohmod & 0xA4)
+ a |= bit0 << 9;
+ if (ohmod & 0x8)
+ a |= bit2 << 9;
+ if (ohmod & 0x50)
+ a |= bit4 << 9;
+
+ if (ohmod & 0x50)
+ a |= bit5 << 10;
+ if (ohmod & 0xA0)
+ a |= bit1 << 10;
+
+ if (ohmod & 0xC0)
+ a |= bit2 << 11;
+
+ if (ohmod & 0x4)
+ c |= bit1 << 6;
+ if (ohmod & 0xE8)
+ c |= bit3 << 6;
+
+ if (ohmod & 0x20)
+ c |= bit2 << 7;
+
+ if (ohmod & 0x5B)
+ b0 |= bit0 << 6;
+ if (ohmod & 0x5B)
+ b1 |= bit1 << 6;
+
+ if (ohmod & 0x12)
+ b0 |= bit2 << 7;
+ if (ohmod & 0x12)
+ b1 |= bit3 << 7;
+
+ if (ohmod & 0xAF)
+ d0 |= bit4 << 5;
+ if (ohmod & 0xAF)
+ d1 |= bit5 << 5;
+ if (ohmod & 0x5)
+ d0 |= bit2 << 6;
+ if (ohmod & 0x5)
+ d1 |= bit3 << 6;
+
+ // sign-extend 'd0' and 'd1'
+ // note: this code assumes that signed right-shift actually sign-fills, not zero-fills.
+ int32_t d0x = d0;
+ int32_t d1x = d1;
+ int sx_shamt = 32 - dbits;
+ d0x <<= sx_shamt;
+ d0x >>= sx_shamt;
+ d1x <<= sx_shamt;
+ d1x >>= sx_shamt;
+ d0 = d0x;
+ d1 = d1x;
+
+ // expand all values to 12 bits, with left-shift as needed.
+ int val_shamt = (modeval >> 1) ^ 3;
+ a <<= val_shamt;
+ b0 <<= val_shamt;
+ b1 <<= val_shamt;
+ c <<= val_shamt;
+ d0 <<= val_shamt;
+ d1 <<= val_shamt;
+
+ // then compute the actual color values.
+ int red1 = a;
+ int green1 = a - b0;
+ int blue1 = a - b1;
+ int red0 = a - c;
+ int green0 = a - b0 - c - d0;
+ int blue0 = a - b1 - c - d1;
+
+ // clamp the color components to [0,2^12 - 1]
+ if (red0 < 0)
+ red0 = 0;
+ else if (red0 > 0xFFF)
+ red0 = 0xFFF;
+
+ if (green0 < 0)
+ green0 = 0;
+ else if (green0 > 0xFFF)
+ green0 = 0xFFF;
+
+ if (blue0 < 0)
+ blue0 = 0;
+ else if (blue0 > 0xFFF)
+ blue0 = 0xFFF;
+
+ if (red1 < 0)
+ red1 = 0;
+ else if (red1 > 0xFFF)
+ red1 = 0xFFF;
+
+ if (green1 < 0)
+ green1 = 0;
+ else if (green1 > 0xFFF)
+ green1 = 0xFFF;
+
+ if (blue1 < 0)
+ blue1 = 0;
+ else if (blue1 > 0xFFF)
+ blue1 = 0xFFF;
+
+ // switch around the color components
+ int temp0, temp1;
+ switch (majcomp)
+ {
+ case 1: // switch around red and green
+ temp0 = red0;
+ temp1 = red1;
+ red0 = green0;
+ red1 = green1;
+ green0 = temp0;
+ green1 = temp1;
+ break;
+ case 2: // switch around red and blue
+ temp0 = red0;
+ temp1 = red1;
+ red0 = blue0;
+ red1 = blue1;
+ blue0 = temp0;
+ blue1 = temp1;
+ break;
+ case 0: // no switch
+ break;
+ }
+
+ *output0 = uint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
+ *output1 = uint4(red1 << 4, green1 << 4, blue1 << 4, 0x7800);
+}
+
+static void hdr_rgb_ldr_alpha_unpack3(
+ const int input[8],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ hdr_rgb_unpack3(input, quantization_level, output0, output1);
+
+ int v6 = color_unquantization_tables[quantization_level][input[6]];
+ int v7 = color_unquantization_tables[quantization_level][input[7]];
+ output0->w = v6;
+ output1->w = v7;
+}
+
+static void hdr_luminance_small_range_unpack(
+ const int input[2],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int v0 = color_unquantization_tables[quantization_level][input[0]];
+ int v1 = color_unquantization_tables[quantization_level][input[1]];
+
+ int y0, y1;
+ if (v0 & 0x80)
+ {
+ y0 = ((v1 & 0xE0) << 4) | ((v0 & 0x7F) << 2);
+ y1 = (v1 & 0x1F) << 2;
+ }
+ else
+ {
+ y0 = ((v1 & 0xF0) << 4) | ((v0 & 0x7F) << 1);
+ y1 = (v1 & 0xF) << 1;
+ }
+
+ y1 += y0;
+ if (y1 > 0xFFF)
+ y1 = 0xFFF;
+
+ *output0 = uint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
+ *output1 = uint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
+}
+
+static void hdr_luminance_large_range_unpack(
+ const int input[2],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ int v0 = color_unquantization_tables[quantization_level][input[0]];
+ int v1 = color_unquantization_tables[quantization_level][input[1]];
+
+ int y0, y1;
+ if (v1 >= v0)
+ {
+ y0 = v0 << 4;
+ y1 = v1 << 4;
+ }
+ else
+ {
+ y0 = (v1 << 4) + 8;
+ y1 = (v0 << 4) - 8;
+ }
+ *output0 = uint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
+ *output1 = uint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
+}
+
+static void hdr_alpha_unpack(
+ const int input[2],
+ int quantization_level,
+ int *a0,
+ int *a1
+) {
+
+ int v6 = color_unquantization_tables[quantization_level][input[0]];
+ int v7 = color_unquantization_tables[quantization_level][input[1]];
+
+ int selector = ((v6 >> 7) & 1) | ((v7 >> 6) & 2);
+ v6 &= 0x7F;
+ v7 &= 0x7F;
+ if (selector == 3)
+ {
+ *a0 = v6 << 5;
+ *a1 = v7 << 5;
+ }
+ else
+ {
+ v6 |= (v7 << (selector + 1)) & 0x780;
+ v7 &= (0x3f >> selector);
+ v7 ^= 32 >> selector;
+ v7 -= 32 >> selector;
+ v6 <<= (4 - selector);
+ v7 <<= (4 - selector);
+ v7 += v6;
+
+ if (v7 < 0)
+ v7 = 0;
+ else if (v7 > 0xFFF)
+ v7 = 0xFFF;
+
+ *a0 = v6;
+ *a1 = v7;
+ }
+
+ *a0 <<= 4;
+ *a1 <<= 4;
+}
+
+static void hdr_rgb_hdr_alpha_unpack3(
+ const int input[8],
+ int quantization_level,
+ uint4* output0,
+ uint4* output1
+) {
+ hdr_rgb_unpack3(input, quantization_level, output0, output1);
+
+ int alpha0, alpha1;
+ hdr_alpha_unpack(input + 6, quantization_level, &alpha0, &alpha1);
+
+ output0->w = alpha0;
+ output1->w = alpha1;
+}
+
+void unpack_color_endpoints(
+ astc_decode_mode decode_mode,
+ int format,
+ int quantization_level,
+ const int* input,
+ int* rgb_hdr,
+ int* alpha_hdr,
+ int* nan_endpoint,
+ uint4* output0,
+ uint4* output1
+) {
+ *nan_endpoint = 0;
+
+ switch (format)
+ {
+ case FMT_LUMINANCE:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ luminance_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_DELTA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ luminance_delta_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_LUMINANCE_SMALL_RANGE:
+ *rgb_hdr = 1;
+ *alpha_hdr = -1;
+ hdr_luminance_small_range_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_LUMINANCE_LARGE_RANGE:
+ *rgb_hdr = 1;
+ *alpha_hdr = -1;
+ hdr_luminance_large_range_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_ALPHA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ luminance_alpha_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_ALPHA_DELTA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ luminance_alpha_delta_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGB_SCALE:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgb_scale_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGB_SCALE_ALPHA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgb_scale_alpha_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_RGB_SCALE:
+ *rgb_hdr = 1;
+ *alpha_hdr = -1;
+ hdr_rgbo_unpack3(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGB:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgb_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGB_DELTA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgb_delta_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_RGB:
+ *rgb_hdr = 1;
+ *alpha_hdr = -1;
+ hdr_rgb_unpack3(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGBA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgba_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_RGBA_DELTA:
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ rgba_delta_unpack(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_RGB_LDR_ALPHA:
+ *rgb_hdr = 1;
+ *alpha_hdr = 0;
+ hdr_rgb_ldr_alpha_unpack3(input, quantization_level, output0, output1);
+ break;
+
+ case FMT_HDR_RGBA:
+ *rgb_hdr = 1;
+ *alpha_hdr = 1;
+ hdr_rgb_hdr_alpha_unpack3(input, quantization_level, output0, output1);
+ break;
+
+ default:
+ UNREACHABLE("endpoint_format %d", int(format));
+ }
+
+ if (*alpha_hdr == -1)
+ {
+ {
+ output0->w = 0x00FF;
+ output1->w = 0x00FF;
+ *alpha_hdr = 0;
+ }
+ }
+
+ switch (decode_mode)
+ {
+ case DECODE_LDR_SRGB:
+ if (*rgb_hdr == 1)
+ {
+ output0->x = 0xFF00;
+ output0->y = 0x0000;
+ output0->z = 0xFF00;
+ output0->w = 0xFF00;
+ output1->x = 0xFF00;
+ output1->y = 0x0000;
+ output1->z = 0xFF00;
+ output1->w = 0xFF00;
+ }
+ else
+ {
+ output0->x *= 257;
+ output0->y *= 257;
+ output0->z *= 257;
+ output0->w *= 257;
+ output1->x *= 257;
+ output1->y *= 257;
+ output1->z *= 257;
+ output1->w *= 257;
+ }
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ break;
+
+ case DECODE_LDR:
+ if (*rgb_hdr == 1)
+ {
+ output0->x = 0xFFFF;
+ output0->y = 0xFFFF;
+ output0->z = 0xFFFF;
+ output0->w = 0xFFFF;
+ output1->x = 0xFFFF;
+ output1->y = 0xFFFF;
+ output1->z = 0xFFFF;
+ output1->w = 0xFFFF;
+ *nan_endpoint = 1;
+ }
+ else
+ {
+ output0->x *= 257;
+ output0->y *= 257;
+ output0->z *= 257;
+ output0->w *= 257;
+ output1->x *= 257;
+ output1->y *= 257;
+ output1->z *= 257;
+ output1->w *= 257;
+ }
+ *rgb_hdr = 0;
+ *alpha_hdr = 0;
+ break;
+
+ case DECODE_HDR:
+
+ if (*rgb_hdr == 0)
+ {
+ output0->x *= 257;
+ output0->y *= 257;
+ output0->z *= 257;
+ output1->x *= 257;
+ output1->y *= 257;
+ output1->z *= 257;
+ }
+ if (*alpha_hdr == 0)
+ {
+ output0->w *= 257;
+ output1->w *= 257;
+ }
+ break;
+ }
+}
diff --git a/third_party/astc-encoder/Source/astc_decompress_symbolic.cpp b/third_party/astc-encoder/Source/astc_decompress_symbolic.cpp
new file mode 100644
index 0000000..8a7dac6
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_decompress_symbolic.cpp
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions to decompress a symbolic block.
+ */
+
+#include "astc_codec_internals.h"
+
+static int compute_value_of_texel_int(
+ int texel_to_get,
+ const decimation_table* it,
+ const int* weights
+) {
+ int i;
+ int summed_value = 8;
+ int weights_to_evaluate = it->texel_num_weights[texel_to_get];
+ for (i = 0; i < weights_to_evaluate; i++)
+ {
+ summed_value += weights[it->texel_weights[texel_to_get][i]] * it->texel_weights_int[texel_to_get][i];
+ }
+ return summed_value >> 4;
+}
+
+static uint4 lerp_color_int(
+ astc_decode_mode decode_mode,
+ uint4 color0,
+ uint4 color1,
+ int weight,
+ int plane2_weight,
+ int plane2_color_component // -1 in 1-plane mode
+) {
+ int4 ecolor0 = int4(color0.x, color0.y, color0.z, color0.w);
+ int4 ecolor1 = int4(color1.x, color1.y, color1.z, color1.w);
+
+ int4 eweight1 = int4(weight, weight, weight, weight);
+ switch (plane2_color_component)
+ {
+ case 0:
+ eweight1.x = plane2_weight;
+ break;
+ case 1:
+ eweight1.y = plane2_weight;
+ break;
+ case 2:
+ eweight1.z = plane2_weight;
+ break;
+ case 3:
+ eweight1.w = plane2_weight;
+ break;
+ default:
+ break;
+ }
+
+ int4 eweight0 = int4(64, 64, 64, 64) - eweight1;
+
+ if (decode_mode == DECODE_LDR_SRGB)
+ {
+ ecolor0 = int4(ecolor0.x >> 8, ecolor0.y >> 8, ecolor0.z >> 8, ecolor0.w >> 8);
+ ecolor1 = int4(ecolor1.x >> 8, ecolor1.y >> 8, ecolor1.z >> 8, ecolor1.w >> 8);
+ }
+ int4 color = (ecolor0 * eweight0) + (ecolor1 * eweight1) + int4(32, 32, 32, 32);
+ color = int4(color.x >> 6, color.y >> 6, color.z >> 6, color.w >> 6);
+
+ if (decode_mode == DECODE_LDR_SRGB)
+ color = color * 257;
+
+ return uint4(color.x, color.y, color.z, color.w);
+}
+
+void decompress_symbolic_block(
+ astc_decode_mode decode_mode,
+ const block_size_descriptor* bsd,
+ int xpos,
+ int ypos,
+ int zpos,
+ const symbolic_compressed_block* scb,
+ imageblock* blk
+) {
+ blk->xpos = xpos;
+ blk->ypos = ypos;
+ blk->zpos = zpos;
+
+ int i;
+
+ // if we detected an error-block, blow up immediately.
+ if (scb->error_block)
+ {
+ if (decode_mode == DECODE_LDR_SRGB)
+ {
+ for (i = 0; i < bsd->texel_count; i++)
+ {
+ blk->orig_data[4 * i] = 1.0f;
+ blk->orig_data[4 * i + 1] = 0.0f;
+ blk->orig_data[4 * i + 2] = 1.0f;
+ blk->orig_data[4 * i + 3] = 1.0f;
+ blk->rgb_lns[i] = 0;
+ blk->alpha_lns[i] = 0;
+ blk->nan_texel[i] = 0;
+ }
+ }
+ else
+ {
+ for (i = 0; i < bsd->texel_count; i++)
+ {
+ blk->orig_data[4 * i] = 0.0f;
+ blk->orig_data[4 * i + 1] = 0.0f;
+ blk->orig_data[4 * i + 2] = 0.0f;
+ blk->orig_data[4 * i + 3] = 0.0f;
+ blk->rgb_lns[i] = 0;
+ blk->alpha_lns[i] = 0;
+ blk->nan_texel[i] = 1;
+ }
+ }
+
+ imageblock_initialize_work_from_orig(blk, bsd->texel_count);
+ update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
+ return;
+ }
+
+ if (scb->block_mode < 0)
+ {
+ float red = 0, green = 0, blue = 0, alpha = 0;
+ int use_lns = 0;
+ int use_nan = 0;
+
+ if (scb->block_mode == -2)
+ {
+ // For sRGB decoding, we should return only the top 8 bits.
+ int mask = (decode_mode == DECODE_LDR_SRGB) ? 0xFF00 : 0xFFFF;
+
+ red = sf16_to_float(unorm16_to_sf16(scb->constant_color[0] & mask));
+ green = sf16_to_float(unorm16_to_sf16(scb->constant_color[1] & mask));
+ blue = sf16_to_float(unorm16_to_sf16(scb->constant_color[2] & mask));
+ alpha = sf16_to_float(unorm16_to_sf16(scb->constant_color[3] & mask));
+ use_lns = 0;
+ use_nan = 0;
+ }
+ else
+ {
+ switch (decode_mode)
+ {
+ case DECODE_LDR_SRGB:
+ red = 1.0f;
+ green = 0.0f;
+ blue = 1.0f;
+ alpha = 1.0f;
+ use_lns = 0;
+ use_nan = 0;
+ break;
+ case DECODE_LDR:
+ red = 0.0f;
+ green = 0.0f;
+ blue = 0.0f;
+ alpha = 0.0f;
+ use_lns = 0;
+ use_nan = 1;
+ break;
+ case DECODE_HDR:
+ // constant-color block; unpack from FP16 to FP32.
+ red = sf16_to_float(scb->constant_color[0]);
+ green = sf16_to_float(scb->constant_color[1]);
+ blue = sf16_to_float(scb->constant_color[2]);
+ alpha = sf16_to_float(scb->constant_color[3]);
+ use_lns = 1;
+ use_nan = 0;
+ break;
+ }
+ }
+
+ for (i = 0; i < bsd->texel_count; i++)
+ {
+ blk->orig_data[4 * i] = red;
+ blk->orig_data[4 * i + 1] = green;
+ blk->orig_data[4 * i + 2] = blue;
+ blk->orig_data[4 * i + 3] = alpha;
+ blk->rgb_lns[i] = use_lns;
+ blk->alpha_lns[i] = use_lns;
+ blk->nan_texel[i] = use_nan;
+ }
+
+ imageblock_initialize_work_from_orig(blk, bsd->texel_count);
+ update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
+ return;
+ }
+
+ // get the appropriate partition-table entry
+ int partition_count = scb->partition_count;
+ const partition_info *pt = get_partition_table(bsd, partition_count);
+ pt += scb->partition_index;
+
+ // get the appropriate block descriptor
+ const decimation_table *const *ixtab2 = bsd->decimation_tables;
+
+ const decimation_table *it = ixtab2[bsd->block_modes[scb->block_mode].decimation_mode];
+
+ int is_dual_plane = bsd->block_modes[scb->block_mode].is_dual_plane;
+
+ int weight_quantization_level = bsd->block_modes[scb->block_mode].quantization_mode;
+
+ // decode the color endpoints
+ uint4 color_endpoint0[4];
+ uint4 color_endpoint1[4];
+ int rgb_hdr_endpoint[4];
+ int alpha_hdr_endpoint[4];
+ int nan_endpoint[4];
+
+ for (i = 0; i < partition_count; i++)
+ unpack_color_endpoints(decode_mode,
+ scb->color_formats[i],
+ scb->color_quantization_level,
+ scb->color_values[i],
+ &(rgb_hdr_endpoint[i]),
+ &(alpha_hdr_endpoint[i]),
+ &(nan_endpoint[i]),
+ &(color_endpoint0[i]),
+ &(color_endpoint1[i]));
+
+ // first unquantize the weights
+ int uq_plane1_weights[MAX_WEIGHTS_PER_BLOCK];
+ int uq_plane2_weights[MAX_WEIGHTS_PER_BLOCK];
+ int weight_count = it->num_weights;
+
+ const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[weight_quantization_level]);
+
+ for (i = 0; i < weight_count; i++)
+ {
+ uq_plane1_weights[i] = qat->unquantized_value[scb->plane1_weights[i]];
+ }
+
+ if (is_dual_plane)
+ {
+ for (i = 0; i < weight_count; i++)
+ uq_plane2_weights[i] = qat->unquantized_value[scb->plane2_weights[i]];
+ }
+
+ // then undecimate them.
+ int weights[MAX_TEXELS_PER_BLOCK];
+ int plane2_weights[MAX_TEXELS_PER_BLOCK];
+
+ for (i = 0; i < bsd->texel_count; i++)
+ weights[i] = compute_value_of_texel_int(i, it, uq_plane1_weights);
+
+ if (is_dual_plane)
+ for (i = 0; i < bsd->texel_count; i++)
+ plane2_weights[i] = compute_value_of_texel_int(i, it, uq_plane2_weights);
+
+ int plane2_color_component = scb->plane2_color_component;
+
+ // now that we have endpoint colors and weights, we can unpack actual colors for
+ // each texel.
+ for (i = 0; i < bsd->texel_count; i++)
+ {
+ int partition = pt->partition_of_texel[i];
+
+ uint4 color = lerp_color_int(decode_mode,
+ color_endpoint0[partition],
+ color_endpoint1[partition],
+ weights[i],
+ plane2_weights[i],
+ is_dual_plane ? plane2_color_component : -1);
+
+ blk->rgb_lns[i] = rgb_hdr_endpoint[partition];
+ blk->alpha_lns[i] = alpha_hdr_endpoint[partition];
+ blk->nan_texel[i] = nan_endpoint[partition];
+
+ blk->data_r[i] = (float)color.x;
+ blk->data_g[i] = (float)color.y;
+ blk->data_b[i] = (float)color.z;
+ blk->data_a[i] = (float)color.w;
+ }
+
+ imageblock_initialize_orig_from_work(blk, bsd->texel_count);
+
+ update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
+}
diff --git a/third_party/astc-encoder/Source/astc_image_load_store.cpp b/third_party/astc-encoder/Source/astc_image_load_store.cpp
new file mode 100644
index 0000000..1be06ed
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_image_load_store.cpp
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions for loading/storing ASTC compressed images.
+ */
+
+
+#include "astc_codec_internals.h"
+
+// conversion functions between the LNS representation and the FP16 representation.
+float float_to_lns(float p)
+{
+ if (astc::isnan(p) || p <= 1.0f / 67108864.0f)
+ {
+ // underflow or NaN value, return 0.
+ // We count underflow if the input value is smaller than 2^-26.
+ return 0;
+ }
+
+ if (fabsf(p) >= 65536.0f)
+ {
+ // overflow, return a +INF value
+ return 65535;
+ }
+
+ int expo;
+ float normfrac = frexpf(p, &expo);
+ float p1;
+ if (expo < -13)
+ {
+ // input number is smaller than 2^-14. In this case, multiply by 2^25.
+ p1 = p * 33554432.0f;
+ expo = 0;
+ }
+ else
+ {
+ expo += 14;
+ p1 = (normfrac - 0.5f) * 4096.0f;
+ }
+
+ if (p1 < 384.0f)
+ p1 *= 4.0f / 3.0f;
+ else if (p1 <= 1408.0f)
+ p1 += 128.0f;
+ else
+ p1 = (p1 + 512.0f) * (4.0f / 5.0f);
+
+ p1 += expo * 2048.0f;
+ return p1 + 1.0f;
+}
+
+uint16_t lns_to_sf16(uint16_t p)
+{
+ uint16_t mc = p & 0x7FF;
+ uint16_t ec = p >> 11;
+ uint16_t mt;
+ if (mc < 512)
+ mt = 3 * mc;
+ else if (mc < 1536)
+ mt = 4 * mc - 512;
+ else
+ mt = 5 * mc - 2048;
+
+ uint16_t res = (ec << 10) | (mt >> 3);
+ if (res >= 0x7BFF)
+ res = 0x7BFF;
+ return res;
+}
+
+// conversion function from 16-bit LDR value to FP16.
+// note: for LDR interpolation, it is impossible to get a denormal result;
+// this simplifies the conversion.
+// FALSE; we can receive a very small UNORM16 through the constant-block.
+uint16_t unorm16_to_sf16(uint16_t p)
+{
+ if (p == 0xFFFF)
+ return 0x3C00; // value of 1.0 .
+ if (p < 4)
+ return p << 8;
+
+ int lz = clz32(p) - 16;
+ p <<= (lz + 1);
+ p >>= 6;
+ p |= (14 - lz) << 10;
+ return p;
+}
+
+// helper function to initialize the work-data from the orig-data
+void imageblock_initialize_work_from_orig(
+ imageblock* pb,
+ int pixelcount
+) {
+ float *fptr = pb->orig_data;
+
+ for (int i = 0; i < pixelcount; i++)
+ {
+ if (pb->rgb_lns[i])
+ {
+ pb->data_r[i] = float_to_lns(fptr[0]);
+ pb->data_g[i] = float_to_lns(fptr[1]);
+ pb->data_b[i] = float_to_lns(fptr[2]);
+ }
+ else
+ {
+ pb->data_r[i] = fptr[0] * 65535.0f;
+ pb->data_g[i] = fptr[1] * 65535.0f;
+ pb->data_b[i] = fptr[2] * 65535.0f;
+ }
+
+ if (pb->alpha_lns[i])
+ {
+ pb->data_a[i] = float_to_lns(fptr[3]);
+ }
+ else
+ {
+ pb->data_a[i] = fptr[3] * 65535.0f;
+ }
+
+ fptr += 4;
+ }
+}
+
+// helper function to initialize the orig-data from the work-data
+void imageblock_initialize_orig_from_work(
+ imageblock* pb,
+ int pixelcount
+) {
+ float *fptr = pb->orig_data;
+
+ for (int i = 0; i < pixelcount; i++)
+ {
+ if (pb->rgb_lns[i])
+ {
+ fptr[0] = sf16_to_float(lns_to_sf16((uint16_t)pb->data_r[i]));
+ fptr[1] = sf16_to_float(lns_to_sf16((uint16_t)pb->data_g[i]));
+ fptr[2] = sf16_to_float(lns_to_sf16((uint16_t)pb->data_b[i]));
+ }
+ else
+ {
+ fptr[0] = sf16_to_float(unorm16_to_sf16((uint16_t)pb->data_r[i]));
+ fptr[1] = sf16_to_float(unorm16_to_sf16((uint16_t)pb->data_g[i]));
+ fptr[2] = sf16_to_float(unorm16_to_sf16((uint16_t)pb->data_b[i]));
+ }
+
+ if (pb->alpha_lns[i])
+ {
+ fptr[3] = sf16_to_float(lns_to_sf16((uint16_t)pb->data_a[i]));
+ }
+ else
+ {
+ fptr[3] = sf16_to_float(unorm16_to_sf16((uint16_t)pb->data_a[i]));
+ }
+
+ fptr += 4;
+ }
+}
+
+/*
+ For an imageblock, update its flags.
+ The updating is done based on data, not orig_data.
+*/
+void update_imageblock_flags(
+ imageblock* pb,
+ int xdim,
+ int ydim,
+ int zdim
+) {
+ int i;
+ float red_min = 1e38f, red_max = -1e38f;
+ float green_min = 1e38f, green_max = -1e38f;
+ float blue_min = 1e38f, blue_max = -1e38f;
+ float alpha_min = 1e38f, alpha_max = -1e38f;
+
+ int texels_per_block = xdim * ydim * zdim;
+
+ int grayscale = 1;
+
+ for (i = 0; i < texels_per_block; i++)
+ {
+ float red = pb->data_r[i];
+ float green = pb->data_g[i];
+ float blue = pb->data_b[i];
+ float alpha = pb->data_a[i];
+ if (red < red_min)
+ red_min = red;
+ if (red > red_max)
+ red_max = red;
+ if (green < green_min)
+ green_min = green;
+ if (green > green_max)
+ green_max = green;
+ if (blue < blue_min)
+ blue_min = blue;
+ if (blue > blue_max)
+ blue_max = blue;
+ if (alpha < alpha_min)
+ alpha_min = alpha;
+ if (alpha > alpha_max)
+ alpha_max = alpha;
+
+ if (grayscale == 1 && (red != green || red != blue))
+ grayscale = 0;
+ }
+
+ pb->red_min = red_min;
+ pb->red_max = red_max;
+ pb->green_min = green_min;
+ pb->green_max = green_max;
+ pb->blue_min = blue_min;
+ pb->blue_max = blue_max;
+ pb->alpha_min = alpha_min;
+ pb->alpha_max = alpha_max;
+ pb->grayscale = grayscale;
+}
+
diff --git a/third_party/astc-encoder/Source/astc_integer_sequence.cpp b/third_party/astc-encoder/Source/astc_integer_sequence.cpp
new file mode 100644
index 0000000..2f122e5
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_integer_sequence.cpp
@@ -0,0 +1,373 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions for encoding/decoding Bounded Integer Sequence Encoding.
+ */
+
+#include "astc_codec_internals.h"
+
+// unpacked quint triplets <low,middle,high> for each packed-quint value
+static const uint8_t quints_of_integer[128][3] = {
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {0, 3, 3}, {1, 3, 3}, {2, 3, 3}, {3, 3, 3},
+ {4, 3, 3}, {3, 4, 3}, {0, 3, 4}, {1, 3, 4}
+};
+
+// unpacked trit quintuplets <low,_,_,_,high> for each packed-quint value
+static const uint8_t trits_of_integer[256][5] = {
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {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}, {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},
+ {0, 2, 2, 2, 2}, {1, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 1, 2, 2, 2}
+};
+
+void find_number_of_bits_trits_quints(
+ int quantization_level,
+ int* bits,
+ int* trits,
+ int* quints
+) {
+ *bits = 0;
+ *trits = 0;
+ *quints = 0;
+ switch (quantization_level)
+ {
+ case QUANT_2:
+ *bits = 1;
+ break;
+ case QUANT_3:
+ *bits = 0;
+ *trits = 1;
+ break;
+ case QUANT_4:
+ *bits = 2;
+ break;
+ case QUANT_5:
+ *bits = 0;
+ *quints = 1;
+ break;
+ case QUANT_6:
+ *bits = 1;
+ *trits = 1;
+ break;
+ case QUANT_8:
+ *bits = 3;
+ break;
+ case QUANT_10:
+ *bits = 1;
+ *quints = 1;
+ break;
+ case QUANT_12:
+ *bits = 2;
+ *trits = 1;
+ break;
+ case QUANT_16:
+ *bits = 4;
+ break;
+ case QUANT_20:
+ *bits = 2;
+ *quints = 1;
+ break;
+ case QUANT_24:
+ *bits = 3;
+ *trits = 1;
+ break;
+ case QUANT_32:
+ *bits = 5;
+ break;
+ case QUANT_40:
+ *bits = 3;
+ *quints = 1;
+ break;
+ case QUANT_48:
+ *bits = 4;
+ *trits = 1;
+ break;
+ case QUANT_64:
+ *bits = 6;
+ break;
+ case QUANT_80:
+ *bits = 4;
+ *quints = 1;
+ break;
+ case QUANT_96:
+ *bits = 5;
+ *trits = 1;
+ break;
+ case QUANT_128:
+ *bits = 7;
+ break;
+ case QUANT_160:
+ *bits = 5;
+ *quints = 1;
+ break;
+ case QUANT_192:
+ *bits = 6;
+ *trits = 1;
+ break;
+ case QUANT_256:
+ *bits = 8;
+ break;
+ }
+}
+
+// routine to read up to 8 bits
+static inline int read_bits(
+ int bitcount,
+ int bitoffset,
+ const uint8_t* ptr
+) {
+ int mask = (1 << bitcount) - 1;
+ ptr += bitoffset >> 3;
+ bitoffset &= 7;
+ int value = ptr[0] | (ptr[1] << 8);
+ value >>= bitoffset;
+ value &= mask;
+ return value;
+}
+
+void decode_ise(
+ int quantization_level,
+ int elements,
+ const uint8_t* input_data,
+ uint8_t* output_data,
+ int bit_offset
+) {
+ int i;
+ // note: due to how the trit/quint-block unpacking is done in this function,
+ // we may write more temporary results than the number of outputs
+ // The maximum actual number of results is 64 bit, but we keep 4 additional elements
+ // of padding.
+ uint8_t results[68];
+ uint8_t tq_blocks[22]; // trit-blocks or quint-blocks
+
+ int bits, trits, quints;
+ find_number_of_bits_trits_quints(quantization_level, &bits, &trits, &quints);
+
+ int lcounter = 0;
+ int hcounter = 0;
+
+ // trit-blocks or quint-blocks must be zeroed out before we collect them in the loop below.
+ for (i = 0; i < 22; i++)
+ tq_blocks[i] = 0;
+
+ // collect bits for each element, as well as bits for any trit-blocks and quint-blocks.
+ for (i = 0; i < elements; i++)
+ {
+ results[i] = read_bits(bits, bit_offset, input_data);
+ bit_offset += bits;
+
+ if (trits)
+ {
+ static const int bits_to_read[5] = { 2, 2, 1, 2, 1 };
+ static const int block_shift[5] = { 0, 2, 4, 5, 7 };
+ static const int next_lcounter[5] = { 1, 2, 3, 4, 0 };
+ static const int hcounter_incr[5] = { 0, 0, 0, 0, 1 };
+ int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
+ bit_offset += bits_to_read[lcounter];
+ tq_blocks[hcounter] |= tdata << block_shift[lcounter];
+ hcounter += hcounter_incr[lcounter];
+ lcounter = next_lcounter[lcounter];
+ }
+
+ if (quints)
+ {
+ static const int bits_to_read[3] = { 3, 2, 2 };
+ static const int block_shift[3] = { 0, 3, 5 };
+ static const int next_lcounter[3] = { 1, 2, 0 };
+ static const int hcounter_incr[3] = { 0, 0, 1 };
+ int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data);
+ bit_offset += bits_to_read[lcounter];
+ tq_blocks[hcounter] |= tdata << block_shift[lcounter];
+ hcounter += hcounter_incr[lcounter];
+ lcounter = next_lcounter[lcounter];
+ }
+ }
+
+ // unpack trit-blocks or quint-blocks as needed
+ if (trits)
+ {
+ int trit_blocks = (elements + 4) / 5;
+ for (i = 0; i < trit_blocks; i++)
+ {
+ const uint8_t *tritptr = trits_of_integer[tq_blocks[i]];
+ results[5 * i] |= tritptr[0] << bits;
+ results[5 * i + 1] |= tritptr[1] << bits;
+ results[5 * i + 2] |= tritptr[2] << bits;
+ results[5 * i + 3] |= tritptr[3] << bits;
+ results[5 * i + 4] |= tritptr[4] << bits;
+ }
+ }
+
+ if (quints)
+ {
+ int quint_blocks = (elements + 2) / 3;
+ for (i = 0; i < quint_blocks; i++)
+ {
+ const uint8_t *quintptr = quints_of_integer[tq_blocks[i]];
+ results[3 * i] |= quintptr[0] << bits;
+ results[3 * i + 1] |= quintptr[1] << bits;
+ results[3 * i + 2] |= quintptr[2] << bits;
+ }
+ }
+
+ for (i = 0; i < elements; i++)
+ output_data[i] = results[i];
+}
+
+int compute_ise_bitcount(
+ int items,
+ quantization_method quant
+) {
+ switch (quant)
+ {
+ case QUANT_2:
+ return items;
+ case QUANT_3:
+ return (8 * items + 4) / 5;
+ case QUANT_4:
+ return 2 * items;
+ case QUANT_5:
+ return (7 * items + 2) / 3;
+ case QUANT_6:
+ return (13 * items + 4) / 5;
+ case QUANT_8:
+ return 3 * items;
+ case QUANT_10:
+ return (10 * items + 2) / 3;
+ case QUANT_12:
+ return (18 * items + 4) / 5;
+ case QUANT_16:
+ return items * 4;
+ case QUANT_20:
+ return (13 * items + 2) / 3;
+ case QUANT_24:
+ return (23 * items + 4) / 5;
+ case QUANT_32:
+ return 5 * items;
+ case QUANT_40:
+ return (16 * items + 2) / 3;
+ case QUANT_48:
+ return (28 * items + 4) / 5;
+ case QUANT_64:
+ return 6 * items;
+ case QUANT_80:
+ return (19 * items + 2) / 3;
+ case QUANT_96:
+ return (33 * items + 4) / 5;
+ case QUANT_128:
+ return 7 * items;
+ case QUANT_160:
+ return (22 * items + 2) / 3;
+ case QUANT_192:
+ return (38 * items + 4) / 5;
+ case QUANT_256:
+ return 8 * items;
+ default:
+ return 100000;
+ }
+}
diff --git a/third_party/astc-encoder/Source/astc_mathlib.cpp b/third_party/astc-encoder/Source/astc_mathlib.cpp
new file mode 100644
index 0000000..61aaf25
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_mathlib.cpp
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+#include "astc_mathlib.h"
+
+/**
+ * @brief 64-bit rotate left.
+ *
+ * @param val The value to rotate.
+ * @param count The rotation, in bits.
+ */
+static inline uint64_t rotl(uint64_t val, int count)
+{
+ return (val << count) | (val >> (64 - count));
+}
+
+/* Public function, see header file for detailed documentation */
+void astc::rand_init(uint64_t state[2])
+{
+ state[0] = 0xfaf9e171cea1ec6bULL;
+ state[1] = 0xf1b318cc06af5d71ULL;
+}
+
+/* Public function, see header file for detailed documentation */
+uint64_t astc::rand(uint64_t state[2])
+{
+ uint64_t s0 = state[0];
+ uint64_t s1 = state[1];
+ uint64_t res = s0 + s1;
+ s1 ^= s0;
+ state[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);
+ state[1] = rotl(s1, 37);
+ return res;
+}
diff --git a/third_party/astc-encoder/Source/astc_mathlib.h b/third_party/astc-encoder/Source/astc_mathlib.h
new file mode 100644
index 0000000..7f504e9
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_mathlib.h
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/*
+ * This module implements a variety of mathematical data types and library
+ * functions used by the codec.
+ */
+
+#ifndef ASTC_MATHLIB_H_INCLUDED
+#define ASTC_MATHLIB_H_INCLUDED
+
+#include <cmath>
+#include <cstdint>
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846
+#endif
+
+/* ============================================================================
+ Fast math library; note that many of the higher-order functions in this set
+ use approximations which are less accurate, but faster, than <cmath> standard
+ library equivalents.
+
+ Note: Many of these are not necessarily faster than simple C versions when
+ used on a single scalar value, but are included for testing purposes as most
+ have an option based on SSE intrinsics and therefore provide an obvious route
+ to future vectorization.
+============================================================================ */
+
+// We support scalar versions of many maths functions which use SSE intrinsics
+// as an "optimized" path, using just one lane from the SIMD hardware. In
+// reality these are often slower than standard C due to setup and scheduling
+// overheads, and the fact that we're not offsetting that cost with any actual
+// vectorization.
+//
+// These variants are only included as a means to test that the accuracy of an
+// SSE implementation would be acceptable before refactoring code paths to use
+// an actual vectorized implementation which gets some advantage from SSE. It
+// is therefore expected that the code will go *slower* with this macro
+// set to 1 ...
+#define USE_SCALAR_SSE 0
+
+// These are namespaced to avoid colliding with C standard library functions.
+namespace astc
+{
+
+/**
+ * @brief Test if a float value is a nan.
+ *
+ * @param val The value test.
+ *
+ * @return Zero is not a NaN, non-zero otherwise.
+ */
+static inline int isnan(float val)
+{
+ return val != val;
+}
+
+/**
+ * @brief Initialize the seed structure for a random number generator.
+ *
+ * Important note: For the purposes of ASTC we want sets of random numbers to
+ * use the codec, but we want the same seed value across instances and threads
+ * to ensure that image output is stable across compressor runs and across
+ * platforms. Every PRNG created by this call will therefore return the same
+ * sequence of values ...
+ *
+ * @param state The state structure to initialize.
+ */
+void rand_init(uint64_t state[2]);
+
+/**
+ * @brief Return the next random number from the generator.
+ *
+ * This RNG is an implementation of the "xoroshoro-128+ 1.0" PRNG, based on the
+ * public-domain implementation given by David Blackman & Sebastiano Vigna at
+ * http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c
+ *
+ * @param state The state structure to use/update.
+ */
+uint64_t rand(uint64_t state[2]);
+
+}
+
+/* ============================================================================
+ Utility vector template classes with basic operations
+============================================================================ */
+
+template <typename T> class vtype4
+{
+public:
+ T x, y, z, w;
+ vtype4() {}
+ vtype4(T p, T q, T r, T s) : x(p), y(q), z(r), w(s) {}
+ vtype4(const vtype4 & p) : x(p.x), y(p.y), z(p.z), w(p.w) {}
+ vtype4 &operator =(const vtype4 &s) {
+ this->x = s.x;
+ this->y = s.y;
+ this->z = s.z;
+ this->w = s.w;
+ return *this;
+ }
+};
+
+typedef vtype4<int> int4;
+typedef vtype4<unsigned int> uint4;
+
+static inline int4 operator+(int4 p, int4 q) { return int4( p.x + q.x, p.y + q.y, p.z + q.z, p.w + q.w ); }
+static inline uint4 operator+(uint4 p, uint4 q) { return uint4( p.x + q.x, p.y + q.y, p.z + q.z, p.w + q.w ); }
+
+static inline int4 operator-(int4 p, int4 q) { return int4( p.x - q.x, p.y - q.y, p.z - q.z, p.w - q.w ); }
+static inline uint4 operator-(uint4 p, uint4 q) { return uint4( p.x - q.x, p.y - q.y, p.z - q.z, p.w - q.w ); }
+
+static inline int4 operator*(int4 p, int4 q) { return int4( p.x * q.x, p.y * q.y, p.z * q.z, p.w * q.w ); }
+static inline uint4 operator*(uint4 p, uint4 q) { return uint4( p.x * q.x, p.y * q.y, p.z * q.z, p.w * q.w ); }
+
+static inline int4 operator*(int4 p, int q) { return int4( p.x * q, p.y * q, p.z * q, p.w * q ); }
+static inline uint4 operator*(uint4 p, uint32_t q) { return uint4( p.x * q, p.y * q, p.z * q, p.w * q ); }
+
+static inline int4 operator*(int p, int4 q) { return q * p; }
+static inline uint4 operator*(uint32_t p, uint4 q) { return q * p; }
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+/* ============================================================================
+ Softfloat library with fp32 and fp16 conversion functionality.
+============================================================================ */
+typedef union if32_
+{
+ uint32_t u;
+ int32_t s;
+ float f;
+} if32;
+
+uint32_t clz32(uint32_t p);
+
+/* sized soft-float types. These are mapped to the sized integer
+ types of C99, instead of C's floating-point types; this is because
+ the library needs to maintain exact, bit-level control on all
+ operations on these data types. */
+typedef uint16_t sf16;
+typedef uint32_t sf32;
+
+/* widening float->float conversions */
+sf32 sf16_to_sf32(sf16);
+
+float sf16_to_float(sf16);
+
+#endif
diff --git a/third_party/astc-encoder/Source/astc_mathlib_softfloat.cpp b/third_party/astc-encoder/Source/astc_mathlib_softfloat.cpp
new file mode 100644
index 0000000..975db2c
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_mathlib_softfloat.cpp
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Soft-float library for IEEE-754.
+ */
+
+#include "astc_mathlib.h"
+
+/******************************************
+ helper functions and their lookup tables
+ ******************************************/
+/* count leading zeros functions. Only used when the input is nonzero. */
+
+#if defined(__GNUC__) && (defined(__i386) || defined(__amd64))
+#elif defined(__arm__) && defined(__ARMCC_VERSION)
+#elif defined(__arm__) && defined(__GNUC__)
+#else
+ /* table used for the slow default versions. */
+ static const uint8_t clz_table[256] =
+ {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+#endif
+
+/*
+ 32-bit count-leading-zeros function: use the Assembly instruction whenever possible. */
+uint32_t clz32(uint32_t inp)
+{
+ #if defined(__GNUC__) && (defined(__i386) || defined(__amd64))
+ uint32_t bsr;
+ __asm__("bsrl %1, %0": "=r"(bsr):"r"(inp | 1));
+ return 31 - bsr;
+ #else
+ #if defined(__arm__) && defined(__ARMCC_VERSION)
+ return __clz(inp); /* armcc builtin */
+ #else
+ #if defined(__arm__) && defined(__GNUC__)
+ uint32_t lz;
+ __asm__("clz %0, %1": "=r"(lz):"r"(inp));
+ return lz;
+ #else
+ /* slow default version */
+ uint32_t summa = 24;
+ if (inp >= UINT32_C(0x10000))
+ {
+ inp >>= 16;
+ summa -= 16;
+ }
+ if (inp >= UINT32_C(0x100))
+ {
+ inp >>= 8;
+ summa -= 8;
+ }
+ return summa + clz_table[inp];
+ #endif
+ #endif
+ #endif
+}
+
+/* convert from FP16 to FP32. */
+sf32 sf16_to_sf32(sf16 inp)
+{
+ uint32_t inpx = inp;
+
+ /*
+ This table contains, for every FP16 sign/exponent value combination,
+ the difference between the input FP16 value and the value obtained
+ by shifting the correct FP32 result right by 13 bits.
+ This table allows us to handle every case except denormals and NaN
+ with just 1 table lookup, 2 shifts and 1 add.
+ */
+
+ #define WITH_MB(a) INT32_C((a) | (1 << 31))
+ static const int32_t tbl[64] =
+ {
+ WITH_MB(0x00000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000),
+ INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000),
+ INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000),
+ INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), INT32_C(0x1C000), WITH_MB(0x38000),
+ WITH_MB(0x38000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000),
+ INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000),
+ INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000),
+ INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), INT32_C(0x54000), WITH_MB(0x70000)
+ };
+
+ int32_t res = tbl[inpx >> 10];
+ res += inpx;
+
+ /* the normal cases: the MSB of 'res' is not set. */
+ if (res >= 0) /* signed compare */
+ return res << 13;
+
+ /* Infinity and Zero: the bottom 10 bits of 'res' are clear. */
+ if ((res & UINT32_C(0x3FF)) == 0)
+ return res << 13;
+
+ /* NaN: the exponent field of 'inp' is not zero; NaNs must be quietened. */
+ if ((inpx & 0x7C00) != 0)
+ return (res << 13) | UINT32_C(0x400000);
+
+ /* the remaining cases are Denormals. */
+ {
+ uint32_t sign = (inpx & UINT32_C(0x8000)) << 16;
+ uint32_t mskval = inpx & UINT32_C(0x7FFF);
+ uint32_t leadingzeroes = clz32(mskval);
+ mskval <<= leadingzeroes;
+ return (mskval >> 8) + ((0x85 - leadingzeroes) << 23) + sign;
+ }
+}
+
+/* convert from soft-float to native-float */
+float sf16_to_float(sf16 p)
+{
+ if32 i;
+ i.u = sf16_to_sf32(p);
+ return i.f;
+}
+
diff --git a/third_party/astc-encoder/Source/astc_partition_tables.cpp b/third_party/astc-encoder/Source/astc_partition_tables.cpp
new file mode 100644
index 0000000..618c777
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_partition_tables.cpp
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions for generating partition tables on demand.
+ */
+
+#include "astc_codec_internals.h"
+
+/*
+ Produce a canonicalized representation of a partition pattern
+
+ The largest possible such representation is 432 bits, equal to 7 uint64_t values.
+*/
+static void gen_canonicalized_partition_table(
+ int texel_count,
+ const uint8_t* partition_table,
+ uint64_t canonicalized[7]
+) {
+ int i;
+ for (i = 0; i < 7; i++)
+ canonicalized[i] = 0;
+
+ int mapped_index[4];
+ int map_weight_count = 0;
+ for (i = 0; i < 4; i++)
+ mapped_index[i] = -1;
+
+ for (i = 0; i < texel_count; i++)
+ {
+ int index = partition_table[i];
+ if (mapped_index[index] == -1)
+ mapped_index[index] = map_weight_count++;
+ uint64_t xlat_index = mapped_index[index];
+ canonicalized[i >> 5] |= xlat_index << (2 * (i & 0x1F));
+ }
+}
+
+static int compare_canonicalized_partition_tables(
+ const uint64_t part1[7],
+ const uint64_t part2[7]
+) {
+ if (part1[0] != part2[0])
+ return 0;
+ if (part1[1] != part2[1])
+ return 0;
+ if (part1[2] != part2[2])
+ return 0;
+ if (part1[3] != part2[3])
+ return 0;
+ if (part1[4] != part2[4])
+ return 0;
+ if (part1[5] != part2[5])
+ return 0;
+ if (part1[6] != part2[6])
+ return 0;
+ return 1;
+}
+
+/*
+ For a partition table, detect partitionss that are equivalent, then mark them as invalid. This reduces the number of partitions that the codec has to consider and thus improves encode
+ performance. */
+static void partition_table_zap_equal_elements(
+ int texel_count,
+ partition_info* pi
+) {
+ int partition_tables_zapped = 0;
+ int i, j;
+ uint64_t *canonicalizeds = new uint64_t[PARTITION_COUNT * 7];
+
+
+ for (i = 0; i < PARTITION_COUNT; i++)
+ {
+ gen_canonicalized_partition_table(texel_count, pi[i].partition_of_texel, canonicalizeds + i * 7);
+ }
+
+ for (i = 0; i < PARTITION_COUNT; i++)
+ {
+ for (j = 0; j < i; j++)
+ {
+ if (compare_canonicalized_partition_tables(canonicalizeds + 7 * i, canonicalizeds + 7 * j))
+ {
+ pi[i].partition_count = 0;
+ partition_tables_zapped++;
+ break;
+ }
+ }
+ }
+ delete[]canonicalizeds;
+}
+
+static uint32_t hash52(uint32_t inp)
+{
+ inp ^= inp >> 15;
+
+ inp *= 0xEEDE0891; // (2^4+1)*(2^7+1)*(2^17-1)
+ inp ^= inp >> 5;
+ inp += inp << 16;
+ inp ^= inp >> 7;
+ inp ^= inp >> 3;
+ inp ^= inp << 6;
+ inp ^= inp >> 17;
+ return inp;
+}
+
+static int select_partition(
+ int seed,
+ int x,
+ int y,
+ int z,
+ int partitioncount,
+ int small_block
+) {
+ if (small_block)
+ {
+ x <<= 1;
+ y <<= 1;
+ z <<= 1;
+ }
+
+ seed += (partitioncount - 1) * 1024;
+
+ uint32_t rnum = hash52(seed);
+
+ uint8_t seed1 = rnum & 0xF;
+ uint8_t seed2 = (rnum >> 4) & 0xF;
+ uint8_t seed3 = (rnum >> 8) & 0xF;
+ uint8_t seed4 = (rnum >> 12) & 0xF;
+ uint8_t seed5 = (rnum >> 16) & 0xF;
+ uint8_t seed6 = (rnum >> 20) & 0xF;
+ uint8_t seed7 = (rnum >> 24) & 0xF;
+ uint8_t seed8 = (rnum >> 28) & 0xF;
+ uint8_t seed9 = (rnum >> 18) & 0xF;
+ uint8_t seed10 = (rnum >> 22) & 0xF;
+ uint8_t seed11 = (rnum >> 26) & 0xF;
+ uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF;
+
+ // squaring all the seeds in order to bias their distribution
+ // towards lower values.
+ seed1 *= seed1;
+ seed2 *= seed2;
+ seed3 *= seed3;
+ seed4 *= seed4;
+ seed5 *= seed5;
+ seed6 *= seed6;
+ seed7 *= seed7;
+ seed8 *= seed8;
+ seed9 *= seed9;
+ seed10 *= seed10;
+ seed11 *= seed11;
+ seed12 *= seed12;
+
+ int sh1, sh2, sh3;
+ if (seed & 1)
+ {
+ sh1 = (seed & 2 ? 4 : 5);
+ sh2 = (partitioncount == 3 ? 6 : 5);
+ }
+ else
+ {
+ sh1 = (partitioncount == 3 ? 6 : 5);
+ sh2 = (seed & 2 ? 4 : 5);
+ }
+ sh3 = (seed & 0x10) ? sh1 : sh2;
+
+ seed1 >>= sh1;
+ seed2 >>= sh2;
+ seed3 >>= sh1;
+ seed4 >>= sh2;
+ seed5 >>= sh1;
+ seed6 >>= sh2;
+ seed7 >>= sh1;
+ seed8 >>= sh2;
+
+ seed9 >>= sh3;
+ seed10 >>= sh3;
+ seed11 >>= sh3;
+ seed12 >>= sh3;
+
+ int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
+ int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
+ int c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6);
+ int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2);
+
+ // apply the saw
+ a &= 0x3F;
+ b &= 0x3F;
+ c &= 0x3F;
+ d &= 0x3F;
+
+ // remove some of the components if we are to output < 4 partitions.
+ if (partitioncount <= 3)
+ d = 0;
+ if (partitioncount <= 2)
+ c = 0;
+ if (partitioncount <= 1)
+ b = 0;
+
+ int partition;
+ if (a >= b && a >= c && a >= d)
+ partition = 0;
+ else if (b >= c && b >= d)
+ partition = 1;
+ else if (c >= d)
+ partition = 2;
+ else
+ partition = 3;
+ return partition;
+}
+
+static void generate_one_partition_table(
+ const block_size_descriptor* bsd,
+ int partition_count,
+ int partition_index,
+ partition_info* pt
+) {
+ int texels_per_block = bsd->texel_count;
+ int small_block = texels_per_block < 32;
+
+ uint8_t *partition_of_texel = pt->partition_of_texel;
+ int x, y, z, i;
+
+ for (z = 0; z < bsd->zdim; z++)
+ for (y = 0; y < bsd->ydim; y++)
+ for (x = 0; x < bsd->xdim; x++)
+ {
+ uint8_t part = select_partition(partition_index, x, y, z, partition_count, small_block);
+ *partition_of_texel++ = part;
+ }
+
+ int counts[4];
+ for (i = 0; i < 4; i++)
+ counts[i] = 0;
+
+ for (i = 0; i < texels_per_block; i++)
+ {
+ int partition = pt->partition_of_texel[i];
+ pt->texels_of_partition[partition][counts[partition]++] = i;
+ }
+
+ for (i = 0; i < 4; i++)
+ pt->texels_per_partition[i] = counts[i];
+
+ if (counts[0] == 0)
+ pt->partition_count = 0;
+ else if (counts[1] == 0)
+ pt->partition_count = 1;
+ else if (counts[2] == 0)
+ pt->partition_count = 2;
+ else if (counts[3] == 0)
+ pt->partition_count = 3;
+ else
+ pt->partition_count = 4;
+
+ for (i = 0; i < 4; i++)
+ pt->coverage_bitmaps[i] = 0ULL;
+
+ int texels_to_process = bsd->texelcount_for_bitmap_partitioning;
+ for (i = 0; i < texels_to_process; i++)
+ {
+ int idx = bsd->texels_for_bitmap_partitioning[i];
+ pt->coverage_bitmaps[pt->partition_of_texel[idx]] |= 1ULL << i;
+ }
+}
+
+/* Public function, see header file for detailed documentation */
+void init_partition_tables(
+ block_size_descriptor* bsd
+) {
+ partition_info *par_tab2 = bsd->partitions;
+ partition_info *par_tab3 = par_tab2 + PARTITION_COUNT;
+ partition_info *par_tab4 = par_tab3 + PARTITION_COUNT;
+ partition_info *par_tab1 = par_tab4 + PARTITION_COUNT;
+
+ generate_one_partition_table(bsd, 1, 0, par_tab1);
+ for (int i = 0; i < 1024; i++)
+ {
+ generate_one_partition_table(bsd, 2, i, par_tab2 + i);
+ generate_one_partition_table(bsd, 3, i, par_tab3 + i);
+ generate_one_partition_table(bsd, 4, i, par_tab4 + i);
+ }
+
+ partition_table_zap_equal_elements(bsd->texel_count, par_tab2);
+ partition_table_zap_equal_elements(bsd->texel_count, par_tab3);
+ partition_table_zap_equal_elements(bsd->texel_count, par_tab4);
+}
diff --git a/third_party/astc-encoder/Source/astc_percentile_tables.cpp b/third_party/astc-encoder/Source/astc_percentile_tables.cpp
new file mode 100644
index 0000000..1698f7a
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_percentile_tables.cpp
@@ -0,0 +1,1149 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Percentile data tables for different block encodings.
+ *
+ * To reduce binary size the tables are stored using a packed differential
+ * encoding
+ */
+
+#include "astc_codec_internals.h"
+
+/**
+ * @brief Structure containing packed percentile metadata.
+ *
+ * Note that percentile tables do not exist for 3D textures, so no zdim is
+ * stored as they are all known to be 2D.
+ */
+struct packed_percentile_table
+{
+ /** The block X dimension. */
+ uint8_t xdim;
+ /** The block Y dimension. */
+ uint8_t ydim;
+ /** The number of packed items in the 1 and 2 plane data. */
+ uint16_t itemcounts[2];
+ /** The accumulator divisor for 1 and 2 plane data. */
+ uint16_t difscales[2];
+ /** The initital accumulator values for 1 and 2 plane data. */
+ uint16_t initial_percs[2];
+ /** The packed data for the 1 and 2 plane data. */
+ const uint16_t *items[2];
+};
+
+static const uint16_t percentile_arr_4x4_0[61] = {
+ 0x0242,0x7243,0x6A51,0x6A52,0x5A41,0x4A53,0x8851,0x3842,
+ 0x3852,0x3853,0x3043,0xFA33,0x1BDF,0x2022,0x1032,0x29CE,
+ 0x21DE,0x2823,0x0813,0x0A13,0x0A31,0x0A23,0x09CF,0x0833,
+ 0x0A32,0x01DF,0x0BDD,0x0BCF,0x0221,0x095F,0x0A01,0x0BDE,
+ 0x0BCD,0x0A22,0x09AF,0x0B5F,0x0B4D,0x0BCE,0x0BBF,0x0A11,
+ 0x01BF,0x0202,0x0B5D,0x1203,0x034E,0x0B8E,0x035E,0x0212,
+ 0x032E,0x0B4F,0x03AF,0x03AD,0x03BD,0x0BBE,0x03AE,0x039F,
+ 0x039E,0x033E,0x033F,0x038F,0x032F
+};
+
+static const uint16_t percentile_arr_4x4_1[84] = {
+ 0x0452,0xFFAE,0x2433,0x1DDF,0x17CD,0x1E21,0x1C43,0x1442,
+ 0x3FBE,0x1FDD,0x0E31,0x0F4F,0x1423,0x0FBD,0x1451,0x0E03,
+ 0x05CF,0x0C32,0x0DDE,0x27AD,0x274E,0x0E02,0x0F5E,0x07AF,
+ 0x0F5F,0x0DCE,0x0C41,0x0422,0x0613,0x0E12,0x0611,0x0F3F,
+ 0x0601,0x0DBF,0x05DD,0x075D,0x0C02,0x054E,0x0431,0x0413,
+ 0x079F,0x05BE,0x0F4D,0x0403,0x05AF,0x055F,0x05AE,0x054F,
+ 0x0421,0x05BD,0x0DCD,0x0411,0x0412,0x055E,0x055D,0x073D,
+ 0x058E,0x072F,0x072D,0x079D,0x0D2E,0x0453,0x078D,0x053E,
+ 0x053F,0x059E,0x052F,0x058F,0x072E,0x078F,0x059F,0x078E,
+ 0x071F,0x073E,0x051F,0x070D,0x079E,0x070E,0x071D,0x0622,
+ 0x070F,0x071E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_4x4 =
+{
+ 4, 4,
+ { 61, 84 },
+ { 184, 141 },
+ { 0, 53 },
+ { percentile_arr_4x4_0, percentile_arr_4x4_1 }
+};
+
+static const uint16_t percentile_arr_5x4_0[91] = {
+ 0x02C1,0xFAD1,0xE8D3,0xDAC2,0xA8D2,0x70D1,0x50C2,0x80C3,
+ 0xD2C3,0x4AA2,0x2AD2,0x2242,0x2251,0x42A3,0x1A43,0x4A52,
+ 0x32B3,0x2A41,0x1042,0x1851,0x5892,0x10A2,0x2253,0x10B2,
+ 0x10B3,0x13DF,0x3083,0x08B1,0x1043,0x12B1,0x0AB2,0x1A93,
+ 0x1852,0x1A33,0x09CE,0x08A3,0x1022,0x1283,0x0853,0x1AA1,
+ 0x1093,0x11DE,0x135F,0x1832,0x195F,0x0A81,0x11CF,0x0A31,
+ 0x09DF,0x0B4D,0x09AF,0x03CF,0x0813,0x03DD,0x0A92,0x0A82,
+ 0x03CD,0x0023,0x0BDE,0x0BBF,0x1232,0x0221,0x0291,0x0A23,
+ 0x0833,0x035D,0x0BCE,0x01BF,0x0222,0x134E,0x0213,0x0A01,
+ 0x0B4F,0x0B5E,0x038E,0x032E,0x03AF,0x0A11,0x03AD,0x0203,
+ 0x0202,0x0BBD,0x033E,0x03AE,0x03BE,0x0212,0x033F,0x039E,
+ 0x039F,0x032F,0x038F
+};
+
+static const uint16_t percentile_arr_5x4_1[104] = {
+ 0x0433,0xB621,0x5452,0x4443,0x7FAE,0xFCA3,0x7CC2,0x24B2,
+ 0x45DF,0x44B3,0x7631,0x27CD,0x1CD1,0x1E03,0x4FBE,0x774F,
+ 0x1C42,0x7691,0x24A2,0x2681,0x3C23,0x3C93,0x0FBD,0x1C32,
+ 0x1E82,0x1E12,0x0F4E,0x1602,0x0FAD,0x0C51,0x1FDD,0x0E13,
+ 0x0DCF,0x175E,0x0C22,0x175F,0x15DE,0x0CB1,0x17AF,0x1CC1,
+ 0x1F3F,0x1483,0x0441,0x0C91,0x04D2,0x0DCE,0x154E,0x079F,
+ 0x0CA1,0x0F5D,0x0431,0x15DD,0x05BF,0x0C92,0x0611,0x0C82,
+ 0x0402,0x074D,0x0DBD,0x055E,0x05BE,0x0DCD,0x0421,0x05AF,
+ 0x0403,0x0D4F,0x055F,0x05AE,0x0413,0x0E01,0x055D,0x073D,
+ 0x0C12,0x0692,0x0411,0x072D,0x078D,0x079D,0x058E,0x0D2E,
+ 0x0453,0x072F,0x059E,0x052F,0x071F,0x053F,0x053E,0x078F,
+ 0x058F,0x051F,0x0F2E,0x059F,0x078E,0x073E,0x071D,0x070D,
+ 0x070E,0x079E,0x0622,0x0683,0x070F,0x071E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_5x4 =
+{
+ 5, 4,
+ { 91, 104 },
+ { 322, 464 },
+ { 0, 202 },
+ { percentile_arr_5x4_0, percentile_arr_5x4_1 }
+};
+
+static const uint16_t percentile_arr_5x5_0[129] = {
+ 0x00F3,0xF8F2,0x70E3,0x62E1,0x60E1,0x4AC1,0x3261,0x38D3,
+ 0x3271,0x5AF1,0x5873,0x2AD1,0x28E2,0x28F1,0x2262,0x9AC2,
+ 0x18D2,0x1072,0x1071,0x22A2,0x2062,0x1A51,0x10C2,0x0892,
+ 0x08D1,0x1AA3,0x23EE,0x08C3,0x0BEF,0x2242,0x0863,0x0AB3,
+ 0x0BFF,0x0A93,0x08A2,0x0A41,0x1083,0x0842,0x10B3,0x21EE,
+ 0x10B2,0x00B1,0x1263,0x12C3,0x0A83,0x0851,0x11FE,0x0253,
+ 0x09FD,0x0A72,0x09FF,0x1AB2,0x0BDF,0x0A33,0x0243,0x0B7F,
+ 0x0AB1,0x12D2,0x0252,0x096F,0x00A3,0x0893,0x0822,0x0843,
+ 0x097E,0x097F,0x01EF,0x09CE,0x03FE,0x0A81,0x036F,0x0052,
+ 0x13FD,0x0AA1,0x1853,0x036D,0x0A92,0x0832,0x01DE,0x0A82,
+ 0x0BED,0x0231,0x0BBF,0x03DD,0x0B6E,0x01AF,0x0813,0x0023,
+ 0x0A91,0x015F,0x037E,0x01CF,0x0232,0x0BCD,0x0221,0x0BDE,
+ 0x0213,0x035F,0x0B7D,0x0223,0x01BF,0x0BCF,0x01DF,0x0033,
+ 0x0222,0x03CE,0x0A01,0x03AF,0x034D,0x0B8E,0x032E,0x0203,
+ 0x0211,0x0202,0x0B5D,0x03AD,0x034E,0x03AE,0x034F,0x033F,
+ 0x039F,0x03BD,0x03BE,0x035E,0x0212,0x033E,0x039E,0x032F,
+ 0x038F
+};
+
+static const uint16_t percentile_arr_5x5_1[126] = {
+ 0x0443,0x6452,0xFE21,0x27AE,0x2433,0x1FCD,0x25DF,0x6CC2,
+ 0x2C62,0x1F4F,0x4C42,0x1FBE,0x0DEF,0x34A3,0x0E03,0x54B2,
+ 0x1F7D,0x17DD,0x0DFF,0x0CD1,0x0E31,0x0C71,0x1CF1,0x15FE,
+ 0x1691,0x1681,0x24B3,0x174E,0x0F6E,0x0493,0x175E,0x1C51,
+ 0x17BD,0x076D,0x2CA2,0x05EE,0x1472,0x2423,0x0DCF,0x0432,
+ 0x15DE,0x0612,0x0CD2,0x0682,0x0F5F,0x07AD,0x0602,0x0CE1,
+ 0x0C91,0x0FAF,0x073F,0x0E13,0x0D7F,0x0DCE,0x0422,0x0D7D,
+ 0x0441,0x05FD,0x0CB1,0x0C83,0x04C1,0x0461,0x0F9F,0x0DDD,
+ 0x056E,0x0C92,0x0482,0x0431,0x05ED,0x0D6F,0x075D,0x0402,
+ 0x057E,0x0DBF,0x04A1,0x054E,0x0F4D,0x0403,0x05CD,0x0453,
+ 0x05AE,0x0421,0x0F1F,0x05BE,0x0601,0x0611,0x05BD,0x05AF,
+ 0x078D,0x072D,0x073D,0x055E,0x0F9D,0x0411,0x0413,0x0412,
+ 0x055F,0x077E,0x055D,0x052E,0x054F,0x053E,0x058E,0x078F,
+ 0x059E,0x071D,0x0E92,0x053F,0x059F,0x051F,0x072F,0x052F,
+ 0x070D,0x079E,0x058F,0x072E,0x070E,0x078E,0x070F,0x073E,
+ 0x0622,0x0683,0x071E,0x076F,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_5x5 =
+{
+ 5, 5,
+ { 129, 126 },
+ { 258, 291 },
+ { 0, 116 },
+ { percentile_arr_5x5_0, percentile_arr_5x5_1 }
+};
+
+static const uint16_t percentile_arr_6x5_0[165] = {
+ 0x0163,0xF8F3,0x9962,0x8972,0x7961,0x7173,0x6953,0x5943,
+ 0x4B41,0x3AE1,0x38E3,0x6971,0x32C1,0x28D3,0x2A61,0xC8F2,
+ 0x2271,0x4873,0x5B21,0x3AD1,0x1B13,0x1952,0x1B51,0x12F1,
+ 0x1A62,0x1322,0x1951,0x10E2,0x1B31,0x20F1,0x2102,0x2072,
+ 0x10D2,0x1142,0x2912,0x3871,0x2BEE,0x0862,0x1123,0x0AC2,
+ 0x12A2,0x0A51,0x1922,0x0941,0x1BEF,0x0B42,0x08D1,0x13FF,
+ 0x1933,0x08C3,0x08C2,0x1131,0x08E1,0x2903,0x0863,0x0B32,
+ 0x1132,0x1AC3,0x0A42,0x1A41,0x0042,0x21EE,0x09FF,0x03DF,
+ 0x0AA3,0x11FE,0x02B3,0x0B11,0x10B3,0x0B03,0x11FD,0x0913,
+ 0x0A53,0x037F,0x1263,0x0051,0x0A33,0x0B01,0x016F,0x0A72,
+ 0x1312,0x08A2,0x10B1,0x0BFE,0x11EF,0x0B02,0x0A52,0x0043,
+ 0x0822,0x01CE,0x0A43,0x097F,0x036F,0x08B2,0x03FD,0x0A83,
+ 0x0B33,0x0AB1,0x017E,0x0B23,0x0852,0x02D2,0x0BBF,0x0BDD,
+ 0x03ED,0x0AB2,0x02A1,0x0853,0x036D,0x0892,0x0032,0x0A31,
+ 0x0083,0x09DE,0x0A93,0x08A3,0x1213,0x0BDE,0x03CD,0x036E,
+ 0x037E,0x0A21,0x0023,0x0BCF,0x01CF,0x0013,0x01AF,0x0A92,
+ 0x0232,0x035F,0x0093,0x0B7D,0x015F,0x0282,0x01BF,0x09DF,
+ 0x03CE,0x0223,0x0833,0x0222,0x03AF,0x0A01,0x0291,0x0B4D,
+ 0x032E,0x038E,0x0203,0x0281,0x035D,0x03AD,0x0B9F,0x0202,
+ 0x034F,0x03BE,0x0211,0x03AE,0x03BD,0x0212,0x034E,0x033F,
+ 0x033E,0x035E,0x039E,0x032F,0x038F
+};
+
+static const uint16_t percentile_arr_6x5_1[145] = {
+ 0x0443,0xEFAE,0x2CC2,0x2E21,0x2C52,0x7C33,0x47CD,0x25DF,
+ 0x3CA3,0xFFBE,0x2551,0x24B3,0x474F,0x1513,0x2691,0x1603,
+ 0x1462,0x1D32,0x14B2,0x5442,0x2CD2,0x35EF,0x0CD1,0x3D22,
+ 0x17BD,0x0FDD,0x0DFF,0x2631,0x177D,0x0CF1,0x1E81,0x0E82,
+ 0x1DFE,0x0F5E,0x0701,0x2CA2,0x1D03,0x0F4E,0x1471,0x0C51,
+ 0x1F6E,0x2FAF,0x0561,0x0C72,0x176D,0x0FAD,0x0DEE,0x05CF,
+ 0x0E13,0x0F5F,0x0E12,0x0C23,0x1E02,0x1D12,0x0CB1,0x0C32,
+ 0x0C93,0x15DE,0x0F9F,0x0F3F,0x0D41,0x0C41,0x0CC1,0x0D31,
+ 0x0C22,0x05FD,0x057F,0x0D01,0x0461,0x04E1,0x0D7D,0x05CE,
+ 0x0502,0x0C31,0x05ED,0x05DD,0x0511,0x0F11,0x0491,0x0D6F,
+ 0x0521,0x056E,0x0C83,0x0D23,0x04A1,0x0C02,0x075D,0x05BF,
+ 0x0C21,0x079D,0x0482,0x05BD,0x0DBE,0x05CD,0x054E,0x057E,
+ 0x0DAE,0x074D,0x078D,0x0542,0x0492,0x05AF,0x0611,0x0F3D,
+ 0x0601,0x071F,0x055E,0x059E,0x0571,0x054F,0x0412,0x0453,
+ 0x058E,0x0413,0x0D3E,0x077E,0x072D,0x052E,0x059F,0x055D,
+ 0x072F,0x0403,0x0411,0x058F,0x055F,0x0692,0x078E,0x053F,
+ 0x0D2F,0x078F,0x070D,0x071D,0x051F,0x072E,0x079E,0x070E,
+ 0x070F,0x073E,0x0622,0x0683,0x0702,0x071E,0x076F,0x07BF,
+ 0x07CE
+};
+
+static const packed_percentile_table block_pcd_6x5 =
+{
+ 6, 5,
+ { 165, 145 },
+ { 388, 405 },
+ { 0, 156 },
+ { percentile_arr_6x5_0, percentile_arr_6x5_1 }
+};
+
+static const uint16_t percentile_arr_6x6_0[206] = {
+ 0x006F,0xF908,0xF104,0xE918,0xE963,0xD114,0xB0F3,0xA07E,
+ 0x7972,0x705F,0x687F,0x6162,0x5953,0x586E,0x610C,0x524D,
+ 0x5973,0x9943,0x98E3,0x904F,0x8341,0x7AC1,0x3A61,0x70D3,
+ 0xA073,0x6AE1,0x30F2,0x3313,0x2B21,0x9A2E,0x4322,0x225D,
+ 0x2331,0x2271,0x22D1,0x1A2D,0x221F,0x22F1,0x1971,0x6952,
+ 0x1951,0x187D,0x18F1,0x1902,0x185E,0x1B51,0x105D,0x1A3D,
+ 0x30E2,0x10D2,0x1961,0x12A2,0x6072,0x3942,0x386D,0x33EE,
+ 0x104E,0x4923,0x101E,0x2122,0x1251,0x1141,0x182F,0x3133,
+ 0x080E,0x1262,0x123E,0x1B32,0x102E,0x1931,0x10D1,0x1912,
+ 0x0871,0x12C2,0x08C2,0x1103,0x0B03,0x1062,0x083D,0x08E1,
+ 0x1132,0x184D,0x0863,0x08C3,0x303F,0x083E,0x10B3,0x12A3,
+ 0x0BEF,0x0B11,0x1A42,0x2233,0x13FF,0x080F,0x0A41,0x0AC3,
+ 0x0842,0x1A63,0x0BDF,0x09FF,0x12B3,0x124E,0x0B12,0x0B42,
+ 0x0A2F,0x1253,0x0913,0x1051,0x0B01,0x120F,0x0B02,0x08A2,
+ 0x0BBF,0x00B1,0x22B1,0x01EE,0x1B33,0x0B23,0x0283,0x13FD,
+ 0x0AB2,0x11FD,0x09FE,0x0A43,0x08B2,0x0A1D,0x0A52,0x023F,
+ 0x101F,0x01CE,0x0A31,0x0BDD,0x0293,0x1822,0x12A1,0x03FE,
+ 0x121E,0x0843,0x0272,0x0B6F,0x0052,0x0A0D,0x0BED,0x12D2,
+ 0x1B7F,0x1053,0x0032,0x01DE,0x08A3,0x020E,0x0883,0x09EF,
+ 0x0892,0x0A21,0x03CD,0x0B5F,0x0213,0x0A32,0x016F,0x1292,
+ 0x03DE,0x017E,0x0BAF,0x0223,0x1093,0x0BCF,0x037E,0x01DF,
+ 0x09CF,0x015F,0x09AF,0x0023,0x01BF,0x0222,0x0282,0x03CE,
+ 0x1013,0x036E,0x097F,0x0033,0x0A01,0x0B6D,0x03BE,0x037D,
+ 0x0281,0x0BAE,0x0203,0x032E,0x034D,0x034F,0x0291,0x0211,
+ 0x038E,0x03BD,0x039E,0x0BAD,0x033E,0x034E,0x039F,0x0202,
+ 0x035D,0x0212,0x033F,0x035E,0x038F,0x032F
+};
+
+static const uint16_t percentile_arr_6x6_1[164] = {
+ 0x07AE,0x8443,0x7E21,0x77CD,0x6C62,0x9433,0x6452,0x34C2,
+ 0x5DDF,0xC7BE,0x25EF,0x24A3,0x3CF1,0xFDFF,0x177D,0x1F4F,
+ 0xC551,0x5CB3,0x1532,0x1513,0x143E,0x245D,0x14B2,0x2472,
+ 0x14D2,0x1FBD,0x1631,0x2DFE,0x1691,0x17DD,0x2E03,0x376E,
+ 0x2442,0x0F6D,0x3C71,0x2CD1,0x2522,0x6C51,0x260D,0x17AF,
+ 0x0DEE,0x1C1F,0x2F01,0x142E,0x0CA2,0x0FAD,0x3D03,0x275E,
+ 0x1681,0x274E,0x1682,0x1C23,0x273F,0x0F5F,0x05DE,0x15FD,
+ 0x0DCF,0x1E02,0x04B1,0x144D,0x0E12,0x0D12,0x1CC1,0x0E13,
+ 0x1C6D,0x0C32,0x043D,0x0C61,0x0F9F,0x04E1,0x0DCE,0x0D41,
+ 0x1C93,0x0C22,0x061D,0x0D7F,0x0C41,0x0561,0x0531,0x0D21,
+ 0x0711,0x0C91,0x0501,0x0C1E,0x040F,0x15DD,0x0431,0x0C2F,
+ 0x057D,0x0C2D,0x0DBE,0x040E,0x0D02,0x0D11,0x054E,0x040D,
+ 0x0D23,0x0DBF,0x04A1,0x05ED,0x0C1D,0x05BD,0x072D,0x056E,
+ 0x0483,0x0F3D,0x0482,0x078D,0x0F5D,0x0453,0x0D9E,0x0C4E,
+ 0x05CD,0x079D,0x0402,0x05AE,0x0F1F,0x0542,0x074D,0x056F,
+ 0x0421,0x0D4F,0x0601,0x0571,0x0492,0x059F,0x053F,0x05AF,
+ 0x0611,0x055E,0x0D8E,0x053E,0x055D,0x047D,0x0411,0x052E,
+ 0x058F,0x051F,0x055F,0x0D7E,0x072F,0x052F,0x0412,0x078F,
+ 0x0403,0x077E,0x070D,0x070E,0x078E,0x0F1D,0x072E,0x0413,
+ 0x070F,0x0692,0x079E,0x060E,0x0622,0x0683,0x0702,0x071E,
+ 0x073E,0x076F,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_6x6 =
+{
+ 6, 6,
+ { 206, 164 },
+ { 769, 644 },
+ { 0, 256 },
+ { percentile_arr_6x6_0, percentile_arr_6x6_1 }
+};
+
+static const uint16_t percentile_arr_8x5_0[226] = {
+ 0x0066,0xF865,0xE963,0xA856,0xA1F2,0x9875,0x91C3,0x91E2,
+ 0x80F3,0x8076,0x61E3,0x6153,0x5172,0x59D2,0x51D3,0x5047,
+ 0xA943,0x49B3,0x4846,0x4962,0xC037,0x4173,0x39F1,0x7027,
+ 0xA2C1,0x3AE1,0x9341,0x30D3,0x5225,0x2A61,0x33C1,0x28E3,
+ 0x53A1,0x49C2,0x2A06,0x4055,0x2006,0x21D1,0x2271,0x4321,
+ 0x3873,0x18F2,0x2015,0x1A15,0x1857,0x52D1,0x3045,0x4835,
+ 0x1952,0x29E1,0x3207,0x1036,0x1816,0x2A16,0x2971,0x13B1,
+ 0x2A17,0x2351,0x1025,0x1826,0x30E2,0x1262,0x20F1,0x1007,
+ 0x1072,0x1151,0x10D2,0x1235,0x1205,0x1062,0x4AF1,0x1251,
+ 0x0B31,0x1381,0x13EE,0x1B92,0x13EF,0x0942,0x1AA2,0x13FF,
+ 0x1161,0x0B93,0x19A2,0x11B1,0x08D1,0x12C2,0x0B13,0x1B22,
+ 0x2123,0x09A3,0x2071,0x1B7F,0x1817,0x0A42,0x10C2,0x1233,
+ 0x08C3,0x0A41,0x0B42,0x09C1,0x0933,0x1AB3,0x1382,0x1BDF,
+ 0x2122,0x0A53,0x0AC3,0x20E1,0x0941,0x0931,0x0042,0x0BA2,
+ 0x0AA3,0x0992,0x0863,0x08B3,0x11B2,0x0902,0x1283,0x09FF,
+ 0x0B83,0x0982,0x0932,0x0BFE,0x0B32,0x0BBF,0x11FE,0x036F,
+ 0x0851,0x08B1,0x18A2,0x11EE,0x0A52,0x0BB2,0x01FD,0x0A43,
+ 0x1A63,0x1193,0x0B91,0x0043,0x1231,0x0A26,0x0AB1,0x03FD,
+ 0x096F,0x00B2,0x0983,0x0A72,0x01CE,0x0BDD,0x0022,0x0B11,
+ 0x1213,0x0B6D,0x017E,0x1333,0x0112,0x0852,0x02D2,0x097F,
+ 0x01EF,0x0AB2,0x0293,0x0853,0x0BED,0x0B12,0x1303,0x02A1,
+ 0x0892,0x0032,0x0883,0x0B6E,0x0292,0x0A32,0x037E,0x0B23,
+ 0x0103,0x0A21,0x0B01,0x0302,0x0BCD,0x00A3,0x0BCF,0x0BDE,
+ 0x0113,0x01DE,0x0B5F,0x0013,0x0BAF,0x0223,0x0222,0x0A82,
+ 0x0833,0x0023,0x09CF,0x037D,0x01AF,0x095F,0x03CE,0x09DF,
+ 0x01BF,0x0893,0x0203,0x0201,0x0B4D,0x03BE,0x032E,0x03AE,
+ 0x0291,0x0A02,0x0211,0x039F,0x0281,0x038E,0x03AD,0x033F,
+ 0x035D,0x033E,0x034E,0x034F,0x0212,0x03BD,0x032F,0x035E,
+ 0x038F,0x039E
+};
+
+static const uint16_t percentile_arr_8x5_1[167] = {
+ 0x0621,0xFCC2,0x3443,0xA433,0x5532,0x2551,0x6CA3,0x27AE,
+ 0x6452,0x8E03,0x3CB3,0x4DA2,0x6DDF,0x37CD,0x6F01,0x1691,
+ 0x2E82,0x27BE,0x1513,0x34D2,0x1D22,0x3E31,0x2593,0x2CB2,
+ 0x1C16,0x374F,0x0DD1,0x2583,0x6613,0x0CD1,0x0C35,0x1462,
+ 0x3E81,0x2612,0x2C42,0x3407,0x14A2,0x0E02,0x1CF1,0x0C06,
+ 0x17BD,0x0F7D,0x1D23,0x35B1,0x179F,0x0D92,0x0F5E,0x1451,
+ 0x04B1,0x1F6E,0x0DEF,0x0D31,0x374E,0x15C1,0x0541,0x2405,
+ 0x17AD,0x0471,0x1472,0x0DFE,0x0711,0x0FDD,0x0DFF,0x0432,
+ 0x1D82,0x0423,0x0F6D,0x07AF,0x0F5F,0x04C1,0x1542,0x0561,
+ 0x0DCF,0x1D03,0x1493,0x0422,0x0445,0x0D12,0x0C25,0x0415,
+ 0x0DA1,0x1591,0x0DEE,0x05DE,0x0C31,0x0491,0x0441,0x0D21,
+ 0x078D,0x057D,0x0C61,0x0F3F,0x0581,0x0D6E,0x0501,0x0CA1,
+ 0x04E1,0x0DFD,0x057F,0x0502,0x0511,0x0C82,0x0483,0x0C03,
+ 0x079D,0x0402,0x0DDD,0x0611,0x05AE,0x0DCE,0x056F,0x0421,
+ 0x057E,0x071F,0x0DBF,0x05BE,0x0412,0x059F,0x054E,0x077E,
+ 0x0C26,0x05ED,0x073D,0x0601,0x0492,0x0453,0x075D,0x058E,
+ 0x0F2D,0x05CD,0x0571,0x053E,0x0692,0x05BD,0x054F,0x055E,
+ 0x0411,0x0F1D,0x074D,0x059E,0x05AF,0x070D,0x053F,0x058F,
+ 0x0413,0x070F,0x055D,0x070E,0x078F,0x052E,0x072F,0x055F,
+ 0x078E,0x0F2E,0x052F,0x051F,0x0417,0x071E,0x0781,0x0622,
+ 0x0683,0x0702,0x073E,0x076F,0x079E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_8x5 =
+{
+ 8, 5,
+ { 226, 167 },
+ { 763, 517 },
+ { 0, 178 },
+ { percentile_arr_8x5_0, percentile_arr_8x5_1 }
+};
+
+static const uint16_t percentile_arr_8x6_0[273] = {
+ 0x0154,0xF944,0xE066,0xA128,0x9963,0x8118,0x806F,0x79F2,
+ 0x79E2,0x7108,0xD934,0x6056,0x69C3,0x60F3,0x5972,0x59E3,
+ 0x5075,0x91B3,0xC9D2,0x807E,0x385F,0x4153,0x3943,0x4162,
+ 0x3837,0x3847,0x7173,0x31D3,0x6948,0x3046,0x307F,0x5827,
+ 0x3114,0x32C1,0x3076,0x2A4D,0x58E3,0x306E,0x2924,0x2A61,
+ 0x29F1,0x50D3,0x704F,0x210C,0x2BA1,0x2225,0x2873,0x4865,
+ 0x2206,0x8341,0x2006,0x3B21,0x18F2,0x21C2,0x1A1F,0x23C1,
+ 0x3AE1,0x1855,0x19D1,0x1A15,0x3815,0x1207,0x1835,0x2A2E,
+ 0x1A16,0x1836,0x2271,0x2845,0x1A2D,0x11E1,0x1816,0x1171,
+ 0x2217,0x1952,0x12D1,0x3904,0x125D,0x4BB1,0x207D,0x10E2,
+ 0x1026,0x2025,0x12F1,0x28F1,0x105D,0x1235,0x12A2,0x1007,
+ 0x123D,0x1A05,0x1072,0x1331,0x101E,0x0951,0x10D2,0x1057,
+ 0x1B92,0x185E,0x1251,0x19A2,0x186D,0x0B81,0x2BEE,0x080E,
+ 0x1A33,0x1942,0x0B13,0x0B51,0x11A3,0x0923,0x2322,0x09B1,
+ 0x184E,0x1161,0x18D1,0x0933,0x0B93,0x4A62,0x1017,0x082F,
+ 0x0A42,0x0B82,0x0AA3,0x0A41,0x08C2,0x08B3,0x0A3E,0x22B3,
+ 0x0871,0x1BBF,0x09C1,0x0AC2,0x09B2,0x0BEF,0x082E,0x1062,
+ 0x0922,0x08C3,0x1063,0x0A53,0x0BDF,0x080F,0x0B42,0x0A83,
+ 0x084D,0x103F,0x0931,0x08E1,0x0A0F,0x1BA2,0x09FF,0x1332,
+ 0x03FF,0x0941,0x12C3,0x0A63,0x003D,0x0842,0x083E,0x0B83,
+ 0x0BB2,0x0A31,0x0932,0x1102,0x0992,0x0982,0x1051,0x08B1,
+ 0x0A2F,0x121E,0x02B1,0x0A4E,0x11EE,0x00A2,0x1022,0x0043,
+ 0x0A52,0x0A1D,0x0226,0x1193,0x03DD,0x08B2,0x0BFD,0x0A43,
+ 0x0A13,0x0AB2,0x01FD,0x09FE,0x020D,0x081F,0x0B33,0x0053,
+ 0x0B91,0x0293,0x0B11,0x0B7F,0x0AA1,0x0B03,0x0A0E,0x03FE,
+ 0x01CE,0x0B6F,0x0183,0x0912,0x023F,0x0852,0x0A21,0x0323,
+ 0x03ED,0x0A32,0x13AF,0x0272,0x08A3,0x0B12,0x0083,0x0832,
+ 0x13CD,0x0223,0x0A92,0x0092,0x0AD2,0x0301,0x0302,0x0BDE,
+ 0x0A22,0x01EF,0x0B5F,0x0103,0x0BCF,0x096F,0x017E,0x0113,
+ 0x01DE,0x0823,0x0282,0x0B6E,0x015F,0x0813,0x01AF,0x01CF,
+ 0x0B7E,0x0033,0x01DF,0x0BCE,0x01BF,0x036D,0x0A03,0x017F,
+ 0x03BE,0x0201,0x0893,0x038E,0x034D,0x03AE,0x0202,0x039F,
+ 0x0291,0x0A11,0x032E,0x033F,0x034F,0x0281,0x037D,0x03BD,
+ 0x0212,0x033E,0x035E,0x034E,0x035D,0x03AD,0x032F,0x038F,
+ 0x039E
+};
+
+static const uint16_t percentile_arr_8x6_1[186] = {
+ 0x0621,0xFC33,0x37AE,0x1CC2,0x2C43,0xAD32,0x34A3,0x4551,
+ 0x6452,0x5C62,0x1FCD,0x14F1,0x4CB3,0x24D2,0x15DF,0x0FBE,
+ 0x2603,0x3DA2,0x2E31,0x25D1,0x25EF,0x0D22,0x2E91,0x1E82,
+ 0x0FBD,0x1513,0x0CB2,0x0CD1,0x0F4F,0x1F7D,0x1701,0x0C16,
+ 0x2593,0x2C42,0x0C72,0x14A2,0x0F6E,0x0C35,0x0C71,0x0D83,
+ 0x0C07,0x1DFF,0x043E,0x1613,0x07DD,0x0FAD,0x1451,0x076D,
+ 0x0E81,0x05FE,0x0406,0x0E0D,0x045D,0x2612,0x0E02,0x07AF,
+ 0x0DB1,0x0F5E,0x15C1,0x0C23,0x1523,0x0C1F,0x0D92,0x04B1,
+ 0x0D31,0x0432,0x0D61,0x0F4E,0x0D41,0x0DEE,0x0D42,0x04C1,
+ 0x0CE1,0x079F,0x0C2E,0x0405,0x0C22,0x0461,0x0E1D,0x0582,
+ 0x073F,0x0571,0x0C4D,0x0DFD,0x05CE,0x0C6D,0x05DE,0x0415,
+ 0x0C45,0x075F,0x0C41,0x0D03,0x05A1,0x0711,0x05CF,0x0425,
+ 0x0C93,0x0D21,0x0591,0x043D,0x0D12,0x0501,0x040F,0x0511,
+ 0x0431,0x0C03,0x04A1,0x078D,0x0581,0x041E,0x040D,0x0C02,
+ 0x040E,0x05DD,0x057F,0x079D,0x042D,0x0D9F,0x0502,0x056E,
+ 0x0412,0x071F,0x044E,0x05BF,0x0C1D,0x0482,0x05AE,0x042F,
+ 0x057D,0x0491,0x054E,0x047D,0x0DBE,0x0611,0x0492,0x0601,
+ 0x05BD,0x05CD,0x0426,0x05ED,0x072D,0x073D,0x0483,0x0F5D,
+ 0x0421,0x056F,0x053F,0x058E,0x054F,0x078F,0x053E,0x059E,
+ 0x057E,0x051F,0x055D,0x0413,0x070D,0x05AF,0x0411,0x0453,
+ 0x0D5E,0x077E,0x052F,0x070F,0x074D,0x0692,0x070E,0x072F,
+ 0x072E,0x058F,0x071D,0x052E,0x0417,0x073E,0x0781,0x078E,
+ 0x055F,0x060E,0x0622,0x0683,0x0702,0x071E,0x076F,0x079E,
+ 0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_8x6 =
+{
+ 8, 6,
+ { 273, 186 },
+ { 880, 300 },
+ { 0, 64 },
+ { percentile_arr_8x6_0, percentile_arr_8x6_1 }
+};
+
+static const uint16_t percentile_arr_8x8_0[347] = {
+ 0x0334,0xFD44,0xDD14,0x9154,0x9B08,0x906A,0x8928,0x8108,
+ 0xE866,0xC918,0x606F,0xC0FE,0x5963,0x58EE,0x6534,0x505A,
+ 0x51E2,0xA8CF,0x5354,0x5314,0x5134,0x5524,0x48F3,0x504B,
+ 0x487E,0x5344,0x49C3,0x4972,0x49F2,0x4856,0xD0EF,0x81D2,
+ 0x78DE,0x4261,0x3AC1,0x71E3,0x6879,0x390C,0x3143,0x31B3,
+ 0x385F,0x3153,0x306E,0x3037,0x30DF,0x3162,0x304F,0x3075,
+ 0xB03B,0x2847,0x28E3,0x2914,0x507F,0x28BF,0x5173,0x5073,
+ 0x20D3,0x2A06,0x2827,0x2508,0x2229,0x29D3,0x204A,0x207A,
+ 0x2046,0x4148,0x20FD,0x4225,0x23A1,0x3944,0x2065,0x1924,
+ 0x2324,0x1806,0x19F1,0x2215,0x1876,0x22AD,0x502B,0x1B04,
+ 0x18F2,0x3A4D,0x3216,0x3504,0x18DD,0x1B21,0x10CE,0x1869,
+ 0x1B41,0x1855,0x1207,0x1AE1,0x2845,0x19D1,0x2A0A,0x1A2D,
+ 0x2A1A,0x11C2,0x1A0B,0x1217,0x2816,0x121B,0x1271,0x2AD1,
+ 0x1035,0x1015,0x287D,0x12F1,0x43C1,0x1171,0x1A05,0x08E2,
+ 0x11E1,0x3251,0x2049,0x20F1,0x12CD,0x0A39,0x1219,0x1059,
+ 0x1104,0x1036,0x1872,0x3007,0x08ED,0x205E,0x1026,0x0952,
+ 0x1392,0x1019,0x0951,0x100A,0x13EE,0x08D2,0x1242,0x0ABD,
+ 0x22A2,0x0BDF,0x2B81,0x0A35,0x13B1,0x0839,0x13BF,0x0A33,
+ 0x1B31,0x205D,0x1241,0x183A,0x2025,0x0B93,0x0A3D,0x1017,
+ 0x1313,0x1253,0x082A,0x204E,0x09A2,0x080B,0x0A1F,0x125D,
+ 0x0A2E,0x081A,0x08D1,0x082F,0x086D,0x1B82,0x0A09,0x0B22,
+ 0x1062,0x11A3,0x2161,0x0923,0x129F,0x1A62,0x0871,0x0942,
+ 0x081B,0x1133,0x18AE,0x0A9E,0x0863,0x09FF,0x18C2,0x0B51,
+ 0x08BD,0x0AA3,0x09B1,0x1AC2,0x08B3,0x0829,0x0BEF,0x0B83,
+ 0x0AAE,0x0A8D,0x1857,0x185B,0x08AF,0x103F,0x08C3,0x09B2,
+ 0x0A4E,0x11C1,0x0A31,0x0B42,0x0A83,0x0BFF,0x13DD,0x00CD,
+ 0x0AB3,0x0842,0x08BE,0x0922,0x1A8E,0x08E1,0x002E,0x0BA2,
+ 0x0A8F,0x2263,0x0252,0x0B32,0x0AC3,0x0941,0x0A43,0x083D,
+ 0x083E,0x0A3E,0x084D,0x1131,0x136F,0x0AB1,0x0193,0x0BFD,
+ 0x0391,0x0851,0x13AF,0x0843,0x0213,0x1226,0x0932,0x03B2,
+ 0x0902,0x0BCD,0x0221,0x089E,0x00B1,0x0BDE,0x03FE,0x02A1,
+ 0x0982,0x009F,0x080E,0x0B5F,0x02BE,0x0A32,0x0A2A,0x01EE,
+ 0x0053,0x0AB2,0x0192,0x09FD,0x0052,0x0B03,0x0293,0x00A2,
+ 0x0B7F,0x0BED,0x0311,0x08B2,0x0A72,0x088E,0x0333,0x0B12,
+ 0x0A23,0x0822,0x0083,0x11CE,0x021D,0x08A3,0x088F,0x029D,
+ 0x0A22,0x0A3F,0x01FE,0x020F,0x0983,0x02D2,0x0292,0x0B23,
+ 0x001E,0x0BCF,0x03CE,0x09AF,0x0B02,0x0301,0x022F,0x137E,
+ 0x021E,0x09EF,0x016F,0x0112,0x097E,0x080F,0x020D,0x0092,
+ 0x01DE,0x09DF,0x0032,0x0033,0x0A82,0x03BE,0x0B6E,0x001F,
+ 0x020E,0x0023,0x09CF,0x0113,0x0103,0x0013,0x0BAE,0x0203,
+ 0x0BAD,0x01BF,0x034F,0x095F,0x036D,0x0202,0x017F,0x0093,
+ 0x0201,0x034D,0x0212,0x035D,0x03BD,0x0B3F,0x035E,0x0211,
+ 0x0281,0x0291,0x032E,0x037D,0x034E,0x038E,0x039F,0x032F,
+ 0x033E,0x038F,0x039E
+};
+
+static const uint16_t percentile_arr_8x8_1[208] = {
+ 0x0621,0x3443,0x47CD,0x97AE,0xFC62,0x14F1,0x24C2,0x25DF,
+ 0x3C33,0x1C52,0x9C72,0x0FBE,0x0C5D,0x343E,0x24A3,0x1551,
+ 0x5D32,0x1CD2,0x15EF,0x4E31,0x04DD,0x1FDD,0x174F,0x0DD1,
+ 0x3E0D,0x15FF,0x0DA2,0x1E03,0x17BD,0x177D,0x14B3,0x0471,
+ 0x0CAE,0x1C1F,0x04D1,0x0F6E,0x0DFE,0x1C42,0x0C16,0x0D22,
+ 0x0C9F,0x2C2E,0x0FAD,0x0571,0x147D,0x0C07,0x04B2,0x0F6D,
+ 0x0F5E,0x07AF,0x146D,0x0C51,0x0593,0x2583,0x0C4E,0x040B,
+ 0x0C35,0x0513,0x0E91,0x0406,0x073F,0x144D,0x0561,0x048F,
+ 0x0F01,0x0F4E,0x0CA2,0x075F,0x1682,0x04E1,0x0C1A,0x04BD,
+ 0x0542,0x0D41,0x0DEE,0x04CD,0x0DCF,0x04B1,0x0C15,0x0C3D,
+ 0x0423,0x0592,0x0DDE,0x0422,0x0432,0x05FD,0x0DC1,0x05B1,
+ 0x0DCE,0x0612,0x0C2F,0x0445,0x0602,0x0531,0x0439,0x0E81,
+ 0x0582,0x0C61,0x061D,0x049E,0x0405,0x0409,0x0DBE,0x079F,
+ 0x0D21,0x04C1,0x0C0A,0x0E13,0x04AD,0x040E,0x0581,0x0419,
+ 0x05DD,0x0D03,0x049D,0x0449,0x0429,0x048E,0x0DA1,0x0425,
+ 0x0512,0x0501,0x0431,0x0523,0x0441,0x042D,0x040F,0x0D7D,
+ 0x0511,0x0502,0x05BF,0x04A1,0x0C03,0x0402,0x079D,0x05AE,
+ 0x075D,0x057F,0x041D,0x048D,0x042A,0x0453,0x05AF,0x078D,
+ 0x0C0D,0x073D,0x0491,0x0591,0x05BD,0x072D,0x057E,0x051F,
+ 0x0482,0x0492,0x041E,0x0412,0x0D9F,0x0421,0x0493,0x0711,
+ 0x056E,0x059E,0x054E,0x0611,0x05ED,0x074D,0x070F,0x056F,
+ 0x052F,0x053F,0x071F,0x054F,0x05CD,0x0483,0x055E,0x072F,
+ 0x0E01,0x0426,0x058F,0x0413,0x078F,0x071D,0x055F,0x058E,
+ 0x0411,0x053E,0x071E,0x055D,0x077E,0x052E,0x0692,0x0417,
+ 0x070D,0x078E,0x070E,0x072E,0x041B,0x060E,0x0622,0x0683,
+ 0x068D,0x0702,0x073E,0x076F,0x0781,0x079E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_8x8 =
+{
+ 8, 8,
+ { 347, 208 },
+ { 1144, 267 },
+ { 0, 38 },
+ { percentile_arr_8x8_0, percentile_arr_8x8_1 }
+};
+
+static const uint16_t percentile_arr_10x5_0[274] = {
+ 0x0165,0xF975,0xD866,0xC056,0xA946,0x90C6,0x90F5,0x8963,
+ 0x80D6,0x80E6,0x60F3,0x61C3,0x59F2,0xA927,0x5075,0x4847,
+ 0x5153,0x4955,0x49E2,0x48B6,0x41D2,0x4943,0x8305,0x8172,
+ 0x4046,0x4037,0x40A7,0x70B7,0x7AC1,0x31E3,0x7027,0x30E5,
+ 0x69D3,0x99B3,0x3315,0x6115,0x3136,0x3076,0x3173,0x30D5,
+ 0x3106,0x8962,0x2916,0x30C7,0x5126,0x30D3,0x2956,0x5117,
+ 0x2B41,0x2AE1,0x2A61,0x29F1,0x2306,0x2145,0x4A85,0x2057,
+ 0x40E3,0x4137,0x3B21,0x23C1,0x2065,0x1925,0x51C2,0x5225,
+ 0x4935,0x1AD1,0x23A1,0x19D1,0x1A71,0x4055,0x1873,0x1A86,
+ 0x1295,0x18F2,0x28A6,0x1952,0x4AA5,0x20B5,0x10C5,0x2AA2,
+ 0x11E1,0x1107,0x10D2,0x2171,0x1351,0x3036,0x1331,0x1BEE,
+ 0x2035,0x1045,0x1313,0x0A15,0x1087,0x1296,0x13EF,0x18E2,
+ 0x1151,0x1086,0x10F1,0x08A5,0x12C2,0x1BFF,0x1095,0x1A62,
+ 0x1322,0x0942,0x1026,0x1872,0x1062,0x0897,0x1123,0x08D1,
+ 0x1A06,0x0806,0x137F,0x13B1,0x13DF,0x1A51,0x09B1,0x0A83,
+ 0x1015,0x22F1,0x0961,0x0B81,0x12B3,0x0A35,0x0AA3,0x20B3,
+ 0x08C3,0x2342,0x0933,0x0A33,0x09A2,0x10C2,0x0896,0x2205,
+ 0x0825,0x20E1,0x0922,0x1242,0x0B16,0x0B32,0x09A3,0x0AC3,
+ 0x0BBF,0x0B93,0x0071,0x0931,0x0A41,0x2392,0x13FE,0x09C1,
+ 0x0B07,0x0016,0x1182,0x09B2,0x0A26,0x0132,0x0941,0x0A93,
+ 0x0992,0x1063,0x1217,0x01FF,0x11EE,0x1216,0x0B23,0x0B82,
+ 0x0042,0x1102,0x0213,0x0B6F,0x09FE,0x1207,0x0807,0x18B1,
+ 0x0253,0x0AB1,0x08A2,0x13FD,0x01FD,0x1983,0x0AB2,0x0A31,
+ 0x016F,0x0B11,0x00B2,0x0851,0x0AD2,0x0993,0x0BDD,0x12A1,
+ 0x017F,0x0A97,0x1022,0x0383,0x0843,0x0A52,0x03A2,0x097E,
+ 0x0817,0x03B2,0x0A43,0x09EF,0x0A63,0x0B33,0x0B03,0x0292,
+ 0x0272,0x09CE,0x0287,0x136D,0x0053,0x0B12,0x0083,0x0892,
+ 0x0112,0x1282,0x03ED,0x0852,0x0301,0x1391,0x0232,0x0B7E,
+ 0x0221,0x08A3,0x0BCD,0x0BCF,0x036E,0x09DE,0x0103,0x03DE,
+ 0x0832,0x0BAF,0x0302,0x13CE,0x035F,0x0093,0x0A23,0x01DF,
+ 0x0013,0x0A22,0x0023,0x0113,0x09AF,0x01BF,0x0033,0x095F,
+ 0x0203,0x0281,0x09CF,0x037D,0x0201,0x0B4D,0x03AE,0x03BE,
+ 0x0291,0x035E,0x038E,0x0B9F,0x03AD,0x0202,0x034F,0x0211,
+ 0x035D,0x0212,0x032E,0x039E,0x033F,0x034E,0x03BD,0x032F,
+ 0x033E,0x038F
+};
+
+static const uint16_t percentile_arr_10x5_1[180] = {
+ 0x0532,0xFCA3,0x3621,0x6E82,0x2CC2,0x3D51,0x3F01,0x2691,
+ 0x17AE,0x35A2,0x74B3,0x1603,0x4433,0x3C43,0x6C35,0x25D1,
+ 0x1D13,0x15DF,0x37CD,0x0D93,0x1D22,0x0E81,0x1452,0x0CD2,
+ 0x37BE,0x0CB2,0x3407,0x1523,0x0C16,0x0CB5,0x0C96,0x1486,
+ 0x2631,0x1506,0x0F4F,0x1583,0x0CD1,0x2CA2,0x2612,0x1613,
+ 0x1602,0x1F11,0x179F,0x17BD,0x15B1,0x0406,0x1D41,0x0CF1,
+ 0x0D31,0x0442,0x1C62,0x0F6E,0x077D,0x0C51,0x0445,0x0D15,
+ 0x2592,0x0CB1,0x05EF,0x0542,0x17AF,0x1425,0x075E,0x0FAD,
+ 0x0CC1,0x0503,0x0512,0x15C1,0x0C95,0x0415,0x0505,0x0F4E,
+ 0x04A5,0x0493,0x0C32,0x0F5F,0x04E1,0x0521,0x0C85,0x07DD,
+ 0x0582,0x15FF,0x05CF,0x0405,0x0D91,0x05A1,0x05FE,0x0C23,
+ 0x0561,0x0472,0x0471,0x0C22,0x0DEE,0x076D,0x0502,0x0426,
+ 0x0C61,0x0D7D,0x0525,0x05DE,0x0DCE,0x079D,0x0692,0x0441,
+ 0x0C91,0x05DD,0x0511,0x057F,0x0611,0x0DFD,0x078D,0x056E,
+ 0x0492,0x04A1,0x073F,0x0C31,0x05BE,0x0483,0x0571,0x056F,
+ 0x0D9F,0x0581,0x0501,0x057E,0x05BF,0x078F,0x0516,0x05ED,
+ 0x0402,0x0F7E,0x0482,0x054E,0x075D,0x071F,0x05CD,0x0535,
+ 0x05AE,0x0C11,0x058F,0x05AF,0x0421,0x0413,0x0601,0x054F,
+ 0x073D,0x059E,0x0487,0x070F,0x078E,0x0781,0x053E,0x0403,
+ 0x072D,0x055D,0x05BD,0x079E,0x0D8E,0x0412,0x052E,0x074D,
+ 0x053F,0x051F,0x070E,0x055F,0x072F,0x052F,0x070D,0x055E,
+ 0x0417,0x0453,0x072E,0x0622,0x0683,0x0702,0x071D,0x071E,
+ 0x073E,0x076F,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_10x5 =
+{
+ 10, 5,
+ { 274, 180 },
+ { 954, 324 },
+ { 0, 79 },
+ { percentile_arr_10x5_0, percentile_arr_10x5_1 }
+};
+
+static const uint16_t percentile_arr_10x6_0[325] = {
+ 0x01A4,0xF954,0xA066,0x9975,0x80F5,0x7056,0x6918,0x6963,
+ 0x58C6,0x5946,0x5928,0x5174,0x586F,0xA0E6,0x5108,0x48D6,
+ 0x49E2,0x40F3,0x9172,0x41F2,0xB875,0x3927,0x39C3,0xA953,
+ 0x3934,0x3305,0x30B6,0x6943,0x31D2,0x3876,0x3037,0x2955,
+ 0x30A7,0x32C1,0x29B3,0x3027,0x287E,0x30B7,0x29E3,0x5846,
+ 0x2B15,0x2847,0x3162,0x5173,0x4936,0x285F,0x48D3,0x2164,
+ 0x4906,0x20E5,0x2915,0x2116,0x407F,0x20D5,0x2A61,0x4117,
+ 0x20E3,0x2126,0x4148,0x206E,0x39D3,0x2145,0x41B4,0x1B06,
+ 0x2114,0x2165,0x5321,0x5A85,0x1A4D,0x1A1F,0x19F1,0x3341,
+ 0x184F,0x1956,0x3125,0x30C7,0x28F2,0x1937,0x1AE1,0x1073,
+ 0x1BA1,0x1935,0x110C,0x1BC1,0x3A25,0x19C2,0x1295,0x122E,
+ 0x1944,0x11D1,0x1124,0x1857,0x22D1,0x2286,0x1A2D,0x12A2,
+ 0x2107,0x1055,0x2065,0x0A71,0x2152,0x10C5,0x10D2,0x1331,
+ 0x08B5,0x1171,0x2836,0x10A6,0x0904,0x123D,0x20F1,0x12A5,
+ 0x10E2,0x107D,0x1AF1,0x1313,0x0951,0x11E1,0x1B22,0x1B51,
+ 0x0835,0x101E,0x0A5D,0x0A15,0x3045,0x0A96,0x08A5,0x1142,
+ 0x12A3,0x1872,0x085D,0x09B1,0x100E,0x0887,0x0886,0x086D,
+ 0x0933,0x12B3,0x0897,0x08B3,0x0A33,0x0923,0x1095,0x0BEE,
+ 0x2BB1,0x085E,0x1283,0x0A51,0x1026,0x0A06,0x12C2,0x08D1,
+ 0x11A2,0x13BF,0x08C3,0x10C2,0x0A3E,0x0BDF,0x0B81,0x13EF,
+ 0x0A35,0x0B16,0x082F,0x2161,0x1B32,0x0806,0x084E,0x11A3,
+ 0x1015,0x1122,0x2931,0x0342,0x0825,0x0A0F,0x0896,0x0A05,
+ 0x0241,0x09C1,0x083F,0x0A42,0x0071,0x0B07,0x082E,0x0393,
+ 0x12B1,0x0A62,0x0226,0x0A2F,0x0B92,0x0063,0x0932,0x0862,
+ 0x09FF,0x0A31,0x00E1,0x12B2,0x09B2,0x0AC3,0x0941,0x0293,
+ 0x1323,0x104D,0x003E,0x083D,0x0992,0x1382,0x03FF,0x0A13,
+ 0x1016,0x0A53,0x0182,0x1007,0x0AA1,0x080F,0x0A16,0x0A1E,
+ 0x0042,0x0902,0x13DD,0x0BB2,0x0A63,0x00A2,0x08B1,0x03FE,
+ 0x1207,0x08B2,0x0B83,0x09EE,0x0311,0x0A87,0x0BAF,0x03A2,
+ 0x09FD,0x0051,0x0B33,0x020D,0x09CE,0x0217,0x021D,0x0817,
+ 0x020E,0x0A4E,0x001F,0x0BFD,0x0297,0x0983,0x0A92,0x0252,
+ 0x0243,0x0B03,0x0193,0x036F,0x0B12,0x0043,0x0822,0x0A21,
+ 0x01FE,0x0853,0x037F,0x023F,0x0BED,0x02D2,0x0B91,0x0232,
+ 0x0282,0x0912,0x08A3,0x0852,0x0223,0x0BCD,0x0083,0x0301,
+ 0x0832,0x01EF,0x0892,0x0302,0x0A72,0x03DE,0x0893,0x0BCF,
+ 0x09DE,0x03CE,0x035F,0x0833,0x0023,0x0103,0x017E,0x0813,
+ 0x01CF,0x01BF,0x016F,0x0A22,0x037E,0x0113,0x01AF,0x0B6E,
+ 0x03BE,0x0201,0x0A03,0x01DF,0x036D,0x03AE,0x015F,0x0281,
+ 0x033E,0x0A02,0x038E,0x017F,0x0291,0x034D,0x03BD,0x0B7D,
+ 0x03AD,0x0211,0x0212,0x034F,0x032E,0x039F,0x034E,0x035D,
+ 0x035E,0x033F,0x039E,0x032F,0x038F
+};
+
+static const uint16_t percentile_arr_10x6_1[199] = {
+ 0x0621,0xBD32,0x5CA3,0x1FAE,0x64C2,0x1D51,0x6C33,0xFC43,
+ 0x5CB3,0x25A2,0x2E82,0x35D1,0x4F01,0x3FBE,0x3691,0x2DDF,
+ 0x2E03,0x3FCD,0x14D2,0x1CF1,0x0C52,0x3C35,0x2D22,0x1513,
+ 0x1462,0x54B2,0x0E31,0x4E81,0x1593,0x1D23,0x1CD1,0x14B5,
+ 0x2FBD,0x0C07,0x1D06,0x0DEF,0x14A2,0x1612,0x1F4F,0x0C16,
+ 0x1F7D,0x0C96,0x0486,0x1F9F,0x0D42,0x4583,0x0E02,0x0472,
+ 0x0DB1,0x1613,0x0FAD,0x0D41,0x0F11,0x0E0D,0x1C42,0x143E,
+ 0x076E,0x04B1,0x0FAF,0x0D61,0x0531,0x0C71,0x0DFF,0x0DFE,
+ 0x0406,0x0C45,0x0451,0x0D15,0x05C1,0x2CC1,0x141F,0x0CE1,
+ 0x0FDD,0x0C22,0x0582,0x0D92,0x0571,0x0F6D,0x0C93,0x045D,
+ 0x0F5E,0x044D,0x0423,0x0D05,0x0425,0x0C95,0x04A5,0x0DCE,
+ 0x075F,0x0E1D,0x0503,0x042E,0x0D91,0x0512,0x0DDE,0x05A1,
+ 0x074E,0x0C32,0x0431,0x0415,0x0D21,0x05EE,0x040E,0x0DDD,
+ 0x0485,0x1525,0x0491,0x0C26,0x046D,0x0C05,0x05CF,0x05FD,
+ 0x0E92,0x073F,0x0C0D,0x043D,0x0502,0x0C1E,0x041D,0x0461,
+ 0x04A1,0x0511,0x0581,0x05BD,0x0C41,0x059F,0x05BF,0x040F,
+ 0x0C7D,0x0402,0x054E,0x057D,0x0403,0x078D,0x05AE,0x042D,
+ 0x0483,0x079D,0x0D7F,0x0482,0x0611,0x056E,0x0516,0x05BE,
+ 0x0535,0x044E,0x05AF,0x0DED,0x042F,0x0492,0x058E,0x078F,
+ 0x0412,0x057E,0x053E,0x0F1F,0x073D,0x0601,0x0501,0x075D,
+ 0x059E,0x05CD,0x053F,0x054F,0x055E,0x055D,0x0421,0x074D,
+ 0x051F,0x072F,0x0781,0x0411,0x0D6F,0x077E,0x0487,0x070E,
+ 0x070F,0x072D,0x058F,0x078E,0x079E,0x052E,0x0413,0x072E,
+ 0x071D,0x052F,0x055F,0x073E,0x0417,0x0453,0x060E,0x0622,
+ 0x0683,0x0702,0x070D,0x071E,0x076F,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_10x6 =
+{
+ 10, 6,
+ { 325, 199 },
+ { 922, 381 },
+ { 0, 78 },
+ { percentile_arr_10x6_0, percentile_arr_10x6_1 }
+};
+
+static const uint16_t percentile_arr_10x8_0[400] = {
+ 0x0154,0xAB34,0xAD44,0x8308,0x7866,0x7B64,0x79A4,0x7975,
+ 0x686A,0x6908,0xC514,0x6174,0x6128,0x6118,0x5B54,0x5163,
+ 0xF856,0x50F5,0x986F,0xDD34,0x48FE,0x4972,0x48E6,0x4146,
+ 0x48EE,0x40F3,0x4AC1,0x38C6,0x41E2,0xBB05,0x707E,0x38D6,
+ 0x3927,0x6B14,0x384B,0x3948,0x3153,0x385A,0x3134,0x6B15,
+ 0x39F2,0x30CF,0x3143,0x91D2,0x31C3,0x60EF,0x5973,0x3076,
+ 0x28D3,0x3261,0x2875,0x28DE,0x290C,0x51E3,0x28A7,0x20E3,
+ 0x2962,0x2B06,0x2917,0x483B,0x20B6,0x2D24,0x206E,0x285F,
+ 0x20B7,0x2936,0x4047,0x2037,0x20DF,0x28BF,0x21B4,0x21B3,
+ 0x1D08,0x2027,0x404F,0x3846,0x2116,0x187F,0x1879,0x2285,
+ 0x1A29,0x3915,0x4873,0x1955,0x3114,0x1B44,0x2165,0x107A,
+ 0x1956,0x6137,0x1106,0x3145,0x1B21,0x19D3,0x12AD,0x1B41,
+ 0x1AD1,0x1126,0x18F2,0x282B,0x40E5,0x20D5,0x2A0A,0x284A,
+ 0x1286,0x1295,0x121A,0x2A0B,0x321B,0x122D,0x10FD,0x13A1,
+ 0x32A2,0x12E1,0x1164,0x13C1,0x124D,0x1239,0x4504,0x10C7,
+ 0x22F1,0x11F1,0x0AC2,0x2125,0x1225,0x0B04,0x1107,0x1069,
+ 0x1A19,0x13BF,0x2A96,0x08D2,0x1271,0x0952,0x2BDF,0x0B31,
+ 0x1251,0x2124,0x0B13,0x12BD,0x1233,0x13EE,0x2144,0x0B16,
+ 0x0A15,0x18E2,0x08DD,0x1097,0x0857,0x0B24,0x0AA5,0x12A3,
+ 0x11C2,0x11D1,0x10CE,0x0865,0x123D,0x08B3,0x0B51,0x1971,
+ 0x0A41,0x0A06,0x1039,0x080A,0x0B22,0x0923,0x0836,0x08C3,
+ 0x0A1F,0x1072,0x080B,0x0935,0x0855,0x18A6,0x0A42,0x1133,
+ 0x0A83,0x0A09,0x0ACD,0x0A2E,0x0887,0x083A,0x10C5,0x085E,
+ 0x13B1,0x087D,0x0819,0x0A9F,0x0049,0x08F1,0x0BEF,0x1161,
+ 0x0B42,0x09E1,0x0A05,0x0904,0x12AE,0x029E,0x0A31,0x09FF,
+ 0x0951,0x0859,0x001A,0x082F,0x0B81,0x08B5,0x0A35,0x082A,
+ 0x08ED,0x1142,0x1262,0x0B32,0x08A5,0x12D2,0x03DD,0x0B07,
+ 0x18AE,0x083F,0x00AF,0x0AB3,0x086D,0x0287,0x0A93,0x025D,
+ 0x0816,0x13FF,0x0A8D,0x005D,0x08D1,0x0392,0x0845,0x0AC3,
+ 0x08C2,0x01A3,0x0AB1,0x09A2,0x005B,0x0B93,0x02B2,0x1086,
+ 0x001B,0x0863,0x0216,0x0AA1,0x0896,0x0A8F,0x084E,0x0A8E,
+ 0x0A53,0x0026,0x0A26,0x0382,0x0807,0x0862,0x0029,0x0871,
+ 0x00BD,0x0835,0x024E,0x0806,0x0941,0x0895,0x03AF,0x0A13,
+ 0x0932,0x03ED,0x0BFD,0x0207,0x0B83,0x0993,0x09B1,0x03CD,
+ 0x0A3E,0x03FE,0x0A21,0x0015,0x0B11,0x0A43,0x00E1,0x136F,
+ 0x00BE,0x00A2,0x0842,0x0043,0x0825,0x082E,0x0A2A,0x03DE,
+ 0x0BA2,0x0122,0x0BCF,0x004D,0x0323,0x09C1,0x0292,0x083E,
+ 0x0252,0x0017,0x0A72,0x00CD,0x0182,0x0A63,0x0131,0x09B2,
+ 0x0303,0x0902,0x0053,0x035F,0x0A32,0x003D,0x0992,0x0A2F,
+ 0x03B2,0x0ABE,0x009F,0x0183,0x0312,0x08B1,0x0B02,0x0A17,
+ 0x0B7F,0x0333,0x0297,0x0A23,0x020F,0x0282,0x0851,0x0822,
+ 0x03CE,0x01EE,0x000E,0x08B2,0x0083,0x0A1D,0x00A3,0x0222,
+ 0x088F,0x0112,0x029D,0x0092,0x0A3F,0x0391,0x089E,0x0301,
+ 0x01FD,0x09BF,0x01CE,0x0852,0x01FE,0x0013,0x0903,0x088E,
+ 0x037E,0x021E,0x01EF,0x095F,0x016F,0x09DE,0x03BE,0x020E,
+ 0x0113,0x01DF,0x080F,0x020D,0x0833,0x03AE,0x0032,0x03BD,
+ 0x0823,0x001E,0x01AF,0x0203,0x034F,0x0093,0x0A81,0x036E,
+ 0x0291,0x038E,0x0A01,0x001F,0x017F,0x01CF,0x017E,0x0202,
+ 0x0BAD,0x0211,0x035D,0x035E,0x039F,0x0212,0x032E,0x033F,
+ 0x034D,0x034E,0x036D,0x032F,0x033E,0x037D,0x038F,0x039E
+};
+
+static const uint16_t percentile_arr_10x8_1[221] = {
+ 0x0621,0xDFAE,0x2443,0x54C2,0x37CD,0x1CF1,0xFCA3,0x14D2,
+ 0x2D32,0x5551,0x7DDF,0x5C33,0x15D1,0x3462,0x24B3,0x7452,
+ 0x5FBE,0x6472,0x65A2,0x1D06,0x445D,0x15EF,0x0E31,0x1D71,
+ 0x343E,0x0D42,0x0CDD,0x1F01,0x4691,0x1435,0x0E82,0x0DFF,
+ 0x17DD,0x0D22,0x24B2,0x1603,0x04B5,0x24AE,0x060D,0x2D13,
+ 0x0C7D,0x0496,0x17BD,0x1F4F,0x1F7D,0x1486,0x0593,0x1C16,
+ 0x0C07,0x15FE,0x041F,0x14D1,0x0C9F,0x0E81,0x0D15,0x27AF,
+ 0x0C2E,0x0D23,0x176E,0x0FAD,0x1C06,0x1561,0x0DB1,0x040B,
+ 0x1C4E,0x0D83,0x1711,0x0C42,0x0C71,0x1C1A,0x0D25,0x04A2,
+ 0x0C45,0x076D,0x0F9F,0x075F,0x0E12,0x046D,0x048F,0x1D92,
+ 0x0602,0x0C39,0x174E,0x0C51,0x0CA1,0x075E,0x05C1,0x14BD,
+ 0x0D31,0x0423,0x0F3F,0x0495,0x0C93,0x049E,0x0D05,0x04E1,
+ 0x0DEE,0x0415,0x04B1,0x0503,0x0CCD,0x042F,0x0DCF,0x044D,
+ 0x0541,0x1582,0x05DE,0x0D01,0x0487,0x040A,0x0516,0x0CA5,
+ 0x05FD,0x05BF,0x057D,0x0DA1,0x0426,0x040F,0x071F,0x0613,
+ 0x0432,0x0D12,0x043D,0x0425,0x0461,0x061D,0x0D21,0x0591,
+ 0x079D,0x048D,0x0429,0x0C49,0x04C1,0x042A,0x040E,0x0485,
+ 0x0511,0x0405,0x0502,0x0441,0x0C19,0x0692,0x0535,0x058F,
+ 0x041D,0x059F,0x072D,0x04AD,0x049D,0x05CE,0x048E,0x0C31,
+ 0x057F,0x078D,0x0409,0x041E,0x05AE,0x0611,0x058E,0x05DD,
+ 0x05CD,0x056E,0x0483,0x073D,0x054E,0x0D9E,0x0402,0x0491,
+ 0x040D,0x056F,0x042D,0x0581,0x0421,0x057E,0x0781,0x053E,
+ 0x0482,0x078F,0x0413,0x052E,0x0601,0x0422,0x0492,0x055E,
+ 0x05BE,0x0F9E,0x072F,0x074D,0x0412,0x070F,0x075D,0x05BD,
+ 0x051F,0x071D,0x073E,0x077E,0x0403,0x0411,0x078E,0x055D,
+ 0x05AF,0x05ED,0x052F,0x053F,0x070D,0x070E,0x072E,0x054F,
+ 0x0417,0x041B,0x0453,0x055F,0x060E,0x0622,0x0683,0x068D,
+ 0x0702,0x071E,0x076F,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_10x8 =
+{
+ 10, 8,
+ { 400, 221 },
+ { 1119, 376 },
+ { 0, 52 },
+ { percentile_arr_10x8_0, percentile_arr_10x8_1 }
+};
+
+static const uint16_t percentile_arr_10x10_0[453] = {
+ 0x0334,0x9514,0x8954,0x806A,0x6F14,0x6724,0x6108,0x6364,
+ 0x5175,0x5D44,0x5866,0x5118,0x5308,0xA179,0x5128,0xF534,
+ 0x49A4,0x5354,0x9174,0x486F,0x48EA,0x40F3,0x4963,0x414A,
+ 0xF8F9,0x3984,0x4172,0x387E,0x405A,0x38DA,0x38F5,0x9B05,
+ 0x30EE,0x32C1,0x3261,0x3D08,0x31E2,0x3056,0x292B,0x3146,
+ 0x3127,0x3315,0x58CA,0x58E6,0x290C,0x3314,0x8134,0x28E3,
+ 0x28FE,0x2948,0x28C6,0x78DE,0x28BB,0x68D6,0x286E,0x2173,
+ 0x2962,0x21D2,0x205F,0x49F2,0x2917,0x2306,0x207F,0x404F,
+ 0x2153,0x2943,0x20CF,0x21C3,0x2073,0x20D3,0x2136,0x183B,
+ 0x430A,0x40A7,0x18B6,0x2079,0x2309,0x2075,0x184B,0x20EF,
+ 0x187A,0x7837,0x1B19,0x20AB,0x18BA,0x20B7,0x1994,0x19E3,
+ 0x21B4,0x49B3,0x38BF,0x193B,0x1876,0x182B,0x30F2,0x193A,
+ 0x1827,0x1965,0x1914,0x184A,0x4047,0x1916,0x1285,0x1937,
+ 0x122D,0x1915,0x1321,0x1955,0x1046,0x191B,0x2106,0x2919,
+ 0x1344,0x1524,0x12E1,0x3926,0x10E5,0x2295,0x1159,0x1145,
+ 0x10DF,0x124D,0x1271,0x092A,0x2169,0x1704,0x22A2,0x1164,
+ 0x13EE,0x12F1,0x0AD1,0x128A,0x110A,0x11D3,0x1286,0x115A,
+ 0x2BA1,0x0BBF,0x3956,0x2A89,0x12AD,0x10E9,0x0B41,0x1A29,
+ 0x2225,0x08FD,0x1107,0x08D5,0x191A,0x1125,0x1A96,0x0B04,
+ 0x18D9,0x2B16,0x11F1,0x0A33,0x0924,0x131A,0x1149,0x1324,
+ 0x0BEF,0x0A99,0x08CB,0x123D,0x1331,0x0BDF,0x0872,0x22A3,
+ 0x0AC2,0x1144,0x0D04,0x08D2,0x08CE,0x0AA9,0x0A9A,0x0B13,
+ 0x1251,0x0865,0x1069,0x0897,0x1215,0x18B3,0x1A62,0x08C7,
+ 0x185E,0x10E2,0x0AA5,0x21FF,0x090B,0x0952,0x09E1,0x0A42,
+ 0x08F1,0x0A06,0x0B22,0x087D,0x1139,0x021F,0x122E,0x082F,
+ 0x09C2,0x0887,0x0A0A,0x03C1,0x0929,0x0A5D,0x0A83,0x0BFF,
+ 0x0935,0x085B,0x0104,0x08DD,0x0923,0x083F,0x0241,0x09D1,
+ 0x0A39,0x0863,0x0A8B,0x08A6,0x008B,0x1133,0x13B1,0x089B,
+ 0x0AB3,0x0036,0x0BDD,0x08ED,0x0857,0x0971,0x0219,0x1235,
+ 0x0AB1,0x0ACD,0x036F,0x0A31,0x08AA,0x003A,0x08C3,0x0A05,
+ 0x02BD,0x0B92,0x0B07,0x12B2,0x08C5,0x0B51,0x0381,0x0A8D,
+ 0x01A3,0x0896,0x0855,0x0BFD,0x005D,0x0BFE,0x023E,0x08AF,
+ 0x00B9,0x0A93,0x00B5,0x0862,0x0A0B,0x0A09,0x0A72,0x0332,
+ 0x0AA1,0x08C9,0x024E,0x1382,0x0951,0x00A5,0x0A2A,0x0059,
+ 0x0A9E,0x0B42,0x004E,0x0942,0x03ED,0x09B2,0x02D2,0x0849,
+ 0x0035,0x0216,0x0961,0x0BAF,0x00AE,0x0826,0x0287,0x0A1A,
+ 0x0393,0x0221,0x09A2,0x086D,0x0226,0x0871,0x0039,0x082A,
+ 0x08C2,0x08E1,0x0845,0x0207,0x0B23,0x0015,0x00D1,0x0B83,
+ 0x037F,0x0252,0x08A9,0x0099,0x0A13,0x0053,0x0807,0x03CD,
+ 0x0BDE,0x0016,0x089A,0x0232,0x035F,0x0A8E,0x0AC3,0x022F,
+ 0x0263,0x0829,0x004D,0x0132,0x0806,0x0311,0x01B1,0x0941,
+ 0x0086,0x000B,0x1122,0x0025,0x0842,0x00BD,0x0BCF,0x03A2,
+ 0x0043,0x0B03,0x0895,0x0A8F,0x008A,0x09EF,0x0253,0x0A1B,
+ 0x0182,0x0243,0x0A92,0x00CD,0x083E,0x030B,0x0223,0x081A,
+ 0x0A9F,0x0193,0x00BE,0x0017,0x0931,0x0391,0x037E,0x09C1,
+ 0x0312,0x0333,0x03B2,0x083D,0x08B1,0x00B2,0x002E,0x021D,
+ 0x0A9D,0x0192,0x02AE,0x0102,0x0022,0x081B,0x0222,0x009E,
+ 0x021E,0x000A,0x089F,0x0217,0x0BCE,0x0052,0x020F,0x0A97,
+ 0x0282,0x008E,0x0A3F,0x01FD,0x00A3,0x0019,0x08A2,0x0301,
+ 0x036E,0x01FE,0x03BE,0x0ABE,0x01CE,0x0302,0x029B,0x0051,
+ 0x0883,0x008F,0x0BAE,0x01DF,0x0183,0x0912,0x000E,0x020D,
+ 0x01EE,0x0B4F,0x0033,0x0103,0x020E,0x0832,0x01AF,0x0913,
+ 0x01DE,0x0203,0x001E,0x0092,0x0093,0x000F,0x015F,0x0291,
+ 0x0281,0x0813,0x001F,0x01CF,0x033F,0x0023,0x01BF,0x0202,
+ 0x016F,0x017E,0x03AD,0x0201,0x034E,0x0BBD,0x036D,0x017F,
+ 0x0211,0x038E,0x0212,0x032E,0x034D,0x035E,0x037D,0x039E,
+ 0x032F,0x033E,0x035D,0x038F,0x039F
+};
+
+static const uint16_t percentile_arr_10x10_1[234] = {
+ 0x07CD,0x6E21,0x24F1,0x8443,0xD7AE,0x24C2,0x1C62,0xCCA3,
+ 0x1C33,0xFDEF,0x2532,0x55DF,0x1472,0x6C3E,0x14D2,0x34DD,
+ 0x1452,0x745D,0x4D51,0x8DD1,0x247D,0x75FF,0x0CB3,0x17BE,
+ 0x6CAE,0x17DD,0x1571,0x3D06,0x4E31,0x0DA2,0x67BD,0x160D,
+ 0x2C4E,0x0D22,0x176E,0x3CB2,0x142E,0x4DFE,0x0F4F,0x1435,
+ 0x0F01,0x0D42,0x0F7D,0x0CB5,0x1E03,0x149F,0x1C96,0x141F,
+ 0x14B9,0x0FAF,0x0439,0x0E91,0x2682,0x1D13,0x1FAD,0x0407,
+ 0x3471,0x0C86,0x0F6D,0x0D15,0x0D61,0x040B,0x0C6D,0x0C16,
+ 0x0C9A,0x0D0A,0x0593,0x0CD1,0x248F,0x0C2F,0x3C42,0x1523,
+ 0x0445,0x0E81,0x0CA2,0x1525,0x0406,0x1C8A,0x0C1A,0x04BD,
+ 0x0F5E,0x0F3F,0x1F4E,0x0E1D,0x0423,0x0DCF,0x044D,0x0D92,
+ 0x0583,0x0DB1,0x1449,0x15EE,0x0F5F,0x079F,0x0D19,0x0409,
+ 0x04CD,0x05FD,0x143D,0x0612,0x0D03,0x0D82,0x04B1,0x0C95,
+ 0x0C2A,0x049E,0x05AF,0x0D31,0x05BE,0x04E1,0x0D05,0x0516,
+ 0x0711,0x05C1,0x0509,0x0D41,0x0493,0x048E,0x0602,0x05BF,
+ 0x0CA5,0x0529,0x0535,0x0D12,0x0539,0x0451,0x0C29,0x071F,
+ 0x040A,0x0F3D,0x0432,0x059F,0x0425,0x0C99,0x05DE,0x05CE,
+ 0x0C0F,0x0489,0x051A,0x0501,0x0415,0x057F,0x0431,0x0E13,
+ 0x040D,0x041D,0x075D,0x0C53,0x0502,0x04C1,0x049D,0x0426,
+ 0x040E,0x05A1,0x055F,0x0781,0x0591,0x04A9,0x048B,0x0D8E,
+ 0x052E,0x0412,0x0521,0x0405,0x04AD,0x074D,0x0611,0x077E,
+ 0x078F,0x078D,0x048D,0x041E,0x0487,0x0461,0x0C85,0x05ED,
+ 0x0402,0x0483,0x0419,0x0511,0x0491,0x0482,0x059E,0x068D,
+ 0x055D,0x072E,0x05DD,0x054E,0x0441,0x0422,0x052F,0x057D,
+ 0x072D,0x079D,0x0CA1,0x072F,0x079E,0x0581,0x042D,0x055E,
+ 0x0601,0x0413,0x0692,0x0403,0x051F,0x053F,0x054F,0x05CD,
+ 0x070F,0x071D,0x05AE,0x05BD,0x0492,0x056E,0x0411,0x0417,
+ 0x041B,0x0421,0x053E,0x056F,0x057E,0x058F,0x060E,0x0622,
+ 0x0683,0x0702,0x070D,0x070E,0x071E,0x073E,0x076F,0x078E,
+ 0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_10x10 =
+{
+ 10, 10,
+ { 453, 234 },
+ { 1095, 472 },
+ { 0, 70 },
+ { percentile_arr_10x10_0, percentile_arr_10x10_1 }
+};
+
+static const uint16_t percentile_arr_12x10_0[491] = {
+ 0x0334,0x9954,0x8514,0x7128,0x6364,0xC174,0x5D34,0x5866,
+ 0x5975,0x5354,0xAF14,0x506A,0x5108,0x5724,0x5308,0x4544,
+ 0x4918,0x4064,0x49E2,0x4179,0x8163,0x4054,0xF81C,0x394A,
+ 0x38F3,0x4172,0x38F5,0xA06F,0x68EA,0x69F2,0x3134,0x31A4,
+ 0x305A,0x68DA,0x3056,0x3146,0x31F5,0x3148,0x5A61,0x32C1,
+ 0x31D2,0x307E,0x29E3,0x30E6,0x59C3,0x2984,0x29B6,0x28F9,
+ 0x5204,0x28EE,0x50CA,0x2997,0x48C6,0x4838,0x2953,0x200C,
+ 0x2943,0x2173,0x2D08,0x4162,0x29B4,0x2314,0x21B3,0x212B,
+ 0x210C,0x48E3,0x60DE,0x205F,0x20FE,0x2028,0x21A6,0x404F,
+ 0x20D6,0x2214,0x2127,0x1873,0x40CF,0x206E,0x1B09,0x21C6,
+ 0x2075,0x19D5,0x2305,0x18D3,0x2076,0x1804,0x230A,0x304B,
+ 0x20BB,0x18B6,0x1936,0x1B19,0x3037,0x187F,0x18A7,0x1B85,
+ 0x30BA,0x183B,0x1027,0x18EF,0x1B21,0x1879,0x10AB,0x1917,
+ 0x1114,0x18BF,0x1074,0x1994,0x2847,0x111B,0x28F2,0x11E5,
+ 0x19A7,0x113A,0x1046,0x28B7,0x207A,0x182B,0x1155,0x104A,
+ 0x1344,0x293B,0x11D3,0x2014,0x1044,0x1018,0x13A1,0x1315,
+ 0x2524,0x20DF,0x10E5,0x1126,0x12A2,0x1824,0x2271,0x11F1,
+ 0x2964,0x12D1,0x115A,0x092A,0x2341,0x1A2D,0x12E1,0x090A,
+ 0x13BF,0x0A4D,0x2119,0x0BC1,0x1233,0x1A8A,0x2008,0x1159,
+ 0x1A89,0x08D5,0x1156,0x0834,0x13EE,0x1169,0x1187,0x1AA3,
+ 0x1229,0x1331,0x0A85,0x0937,0x1704,0x08FD,0x2124,0x0B13,
+ 0x1251,0x0AAD,0x082C,0x091A,0x18D9,0x0A99,0x1848,0x18E9,
+ 0x0B95,0x1144,0x0AF1,0x1A25,0x131A,0x09C5,0x0986,0x1BDF,
+ 0x0B24,0x0965,0x1262,0x0949,0x0872,0x09C2,0x12C2,0x0916,
+ 0x085E,0x0B06,0x08CB,0x08C7,0x1242,0x1BEF,0x0A9A,0x1152,
+ 0x08B3,0x0AA9,0x090B,0x08D2,0x1B22,0x0B04,0x0865,0x0A15,
+ 0x1286,0x0A83,0x0A95,0x09D1,0x0A06,0x0196,0x1139,0x0A3D,
+ 0x0933,0x13B1,0x0123,0x0D04,0x08E2,0x122E,0x08A6,0x00CE,
+ 0x0A31,0x1241,0x0B51,0x1057,0x1171,0x007D,0x1145,0x0A0A,
+ 0x0129,0x09FF,0x089B,0x085B,0x0063,0x0AB1,0x0A1F,0x0A5D,
+ 0x0AA5,0x0036,0x0904,0x0B86,0x0A8B,0x0897,0x11E1,0x0332,
+ 0x083F,0x0A19,0x02B3,0x0859,0x08C3,0x0855,0x11B5,0x01A5,
+ 0x0AB2,0x0392,0x10DD,0x09A3,0x00ED,0x0907,0x1161,0x002F,
+ 0x0887,0x0216,0x0ABD,0x0B81,0x0A93,0x0A21,0x003A,0x0ACD,
+ 0x0AA1,0x0A35,0x0272,0x0BDD,0x03FE,0x0BAF,0x0869,0x0213,
+ 0x088B,0x020B,0x00B5,0x1035,0x08F1,0x0151,0x0A4E,0x0239,
+ 0x0BA2,0x00AA,0x0896,0x0382,0x0A08,0x0A05,0x0A09,0x0142,
+ 0x086D,0x004E,0x0B23,0x0106,0x0807,0x036F,0x0995,0x03FD,
+ 0x08AF,0x08C5,0x0062,0x0053,0x0B42,0x0826,0x021A,0x01A2,
+ 0x09B1,0x00C9,0x09B2,0x0045,0x0207,0x08B9,0x00A5,0x0AD2,
+ 0x0095,0x003E,0x0A32,0x0383,0x0849,0x0135,0x029E,0x0A26,
+ 0x023E,0x0BFF,0x0A52,0x0311,0x001B,0x0915,0x0A8D,0x0223,
+ 0x022A,0x0BED,0x0086,0x0A96,0x0222,0x035F,0x0A43,0x085D,
+ 0x0303,0x0393,0x0A63,0x082A,0x037F,0x0932,0x0043,0x0292,
+ 0x03CD,0x0BDE,0x009F,0x0125,0x08A9,0x0253,0x0015,0x0192,
+ 0x0A17,0x08C2,0x0316,0x00D1,0x0282,0x0871,0x0312,0x0122,
+ 0x0A9F,0x02AE,0x0006,0x0A8E,0x08E1,0x0016,0x0B0B,0x00AE,
+ 0x0025,0x0193,0x0AC3,0x0017,0x0307,0x00BD,0x08BE,0x0039,
+ 0x0BB2,0x021B,0x01FD,0x084D,0x03CE,0x00A3,0x0302,0x0BCF,
+ 0x0033,0x0391,0x028F,0x0852,0x0287,0x008A,0x0333,0x080B,
+ 0x0131,0x01C1,0x037E,0x0A0F,0x00B1,0x002E,0x0099,0x0902,
+ 0x009A,0x003D,0x0982,0x0301,0x00CD,0x0941,0x0042,0x0183,
+ 0x029D,0x08A2,0x021D,0x001A,0x0A97,0x01EF,0x01CE,0x0051,
+ 0x0BAE,0x022F,0x03BE,0x021E,0x000A,0x09DF,0x0029,0x020D,
+ 0x02BE,0x029B,0x09EE,0x00B2,0x0912,0x036E,0x009E,0x0022,
+ 0x0019,0x0892,0x0032,0x01FE,0x0083,0x023F,0x0B96,0x000E,
+ 0x008F,0x0113,0x0103,0x001E,0x0A0E,0x0013,0x008E,0x0281,
+ 0x09AF,0x017E,0x0203,0x016F,0x0291,0x0023,0x0093,0x03BD,
+ 0x001F,0x01CF,0x01DE,0x0201,0x01BF,0x0B4F,0x000F,0x0202,
+ 0x037D,0x038E,0x0211,0x0212,0x034E,0x039F,0x03AD,0x015F,
+ 0x017F,0x032E,0x033F,0x034D,0x035E,0x036D,0x032F,0x033E,
+ 0x035D,0x038F,0x039E
+};
+
+static const uint16_t percentile_arr_12x10_1[240] = {
+ 0x0621,0xA443,0xFCC2,0x3CA3,0x1D32,0x14F1,0x7462,0x1433,
+ 0x27CD,0x2571,0x57AE,0x5DD1,0x64B3,0x44D2,0x2C72,0x25A2,
+ 0x1E31,0x55DF,0x4C52,0x1DEF,0x0D51,0x3C5D,0x3C3E,0x74DD,
+ 0x347D,0x27BE,0x5CB5,0x17DD,0x2C14,0x0CAE,0x24B2,0x15FF,
+ 0x2701,0x0D42,0x1FBD,0x0C35,0x1603,0x060D,0x1D93,0x0C96,
+ 0x1C07,0x1522,0x0D06,0x0F4F,0x0C9F,0x1F6E,0x0D86,0x0C2E,
+ 0x1DFE,0x0682,0x1E91,0x0F7D,0x0C86,0x040B,0x1513,0x044E,
+ 0x14D1,0x0C39,0x14B9,0x1C71,0x05B1,0x0C1F,0x0681,0x1445,
+ 0x0C16,0x0D95,0x1583,0x0D61,0x0FAD,0x1442,0x048F,0x0D0A,
+ 0x049A,0x0F6D,0x146D,0x0C2F,0x0D25,0x0406,0x0C1A,0x0D23,
+ 0x0612,0x0FAF,0x0F11,0x0592,0x0515,0x14E1,0x0602,0x048A,
+ 0x0E1D,0x0CBD,0x0F9F,0x0423,0x075E,0x174E,0x0426,0x0404,
+ 0x0C22,0x0CA2,0x0DEE,0x0CA5,0x0F3F,0x05C1,0x0CCD,0x0503,
+ 0x044D,0x0D16,0x0449,0x0D82,0x0613,0x0585,0x0519,0x0C95,
+ 0x075F,0x0D35,0x04B1,0x0509,0x0531,0x0DA1,0x049E,0x040A,
+ 0x05CF,0x0D41,0x0415,0x0692,0x05FD,0x0C25,0x04A1,0x0529,
+ 0x0591,0x0C93,0x057F,0x04C1,0x0512,0x051A,0x078D,0x0451,
+ 0x0C0F,0x0487,0x0611,0x0432,0x042A,0x05AF,0x0461,0x072D,
+ 0x0409,0x0405,0x0D39,0x05DE,0x048E,0x0499,0x0483,0x04A9,
+ 0x0491,0x042D,0x049D,0x0429,0x040E,0x05AE,0x0521,0x043D,
+ 0x0581,0x05DD,0x0492,0x0CAD,0x041E,0x058F,0x071F,0x072F,
+ 0x0419,0x073D,0x057D,0x0511,0x05CE,0x041D,0x0485,0x056E,
+ 0x0412,0x0431,0x05BF,0x0441,0x054E,0x0489,0x0421,0x0502,
+ 0x0408,0x040D,0x051F,0x059F,0x073E,0x078F,0x0482,0x079D,
+ 0x0C02,0x05BE,0x048B,0x0411,0x0505,0x057E,0x052E,0x074D,
+ 0x077E,0x054F,0x0601,0x055F,0x068D,0x070D,0x070F,0x071E,
+ 0x072E,0x05CD,0x0403,0x0501,0x055D,0x059E,0x0781,0x0413,
+ 0x0417,0x041B,0x0453,0x048D,0x052F,0x053E,0x053F,0x055E,
+ 0x056F,0x058E,0x05BD,0x05ED,0x060E,0x0622,0x0683,0x0702,
+ 0x070E,0x071D,0x075D,0x076F,0x078E,0x079E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_12x10 =
+{
+ 12, 10,
+ { 491, 240 },
+ { 1099, 341 },
+ { 0, 23 },
+ { percentile_arr_12x10_0, percentile_arr_12x10_1 }
+};
+
+static const uint16_t percentile_arr_12x12_0[529] = {
+ 0x0334,0xF534,0x8514,0x8954,0x7F14,0xFB54,0x7B08,0x7128,
+ 0x7974,0x6179,0x6B64,0x6908,0x606A,0x6724,0xB544,0xB066,
+ 0xA14A,0x5118,0x9975,0x51F9,0x981C,0x49CA,0x4854,0x886F,
+ 0x88D4,0x48EE,0x41E2,0x4163,0x40F3,0x4261,0x4064,0x407E,
+ 0x385A,0x42C1,0x4172,0x38EA,0x3946,0x78CF,0xA056,0x38DE,
+ 0x3D08,0x38F9,0x3B14,0x38FE,0xA134,0x38B8,0x31A4,0x71D2,
+ 0x60DA,0x39C3,0x99BA,0x60CA,0x39F2,0x30F5,0x304F,0x31B6,
+ 0x31F5,0x3204,0x3148,0x305F,0x2953,0x3194,0x3184,0x310C,
+ 0x889C,0x300C,0x2943,0x30EF,0x28C6,0x2997,0x2838,0x58E6,
+ 0x20E4,0x28E3,0x2873,0x29E3,0x2A84,0x28D3,0x492B,0x2962,
+ 0x286E,0x20BF,0x21AA,0x29A6,0x6A14,0x2828,0x89C6,0x21B3,
+ 0x2305,0x29B4,0x2173,0x2127,0x20D6,0x407F,0x2294,0x21D9,
+ 0x21D5,0x2004,0x404B,0x18DF,0x2079,0x219B,0x18A8,0x2385,
+ 0x1936,0x21AB,0x188C,0x1B09,0x18BA,0x203B,0x187A,0x1875,
+ 0x2344,0x18BB,0x18B6,0x193A,0x1837,0x1914,0x1846,0x1876,
+ 0x1884,0x1D24,0x182B,0x284A,0x18A7,0x18AB,0x1917,0x322D,
+ 0x1047,0x1874,0x1818,0x18F2,0x1164,0x1B89,0x2959,0x1B21,
+ 0x39E5,0x1827,0x10F4,0x18B7,0x11D3,0x1A4D,0x1315,0x12AD,
+ 0x1AD1,0x3A71,0x1319,0x11A7,0x2044,0x2F04,0x2341,0x10E5,
+ 0x1155,0x195A,0x1024,0x111B,0x1251,0x1233,0x12E1,0x13A1,
+ 0x13BF,0x212A,0x22A2,0x113B,0x23DF,0x10D5,0x2399,0x0814,
+ 0x1126,0x13EE,0x1285,0x10C4,0x18FD,0x20D9,0x0987,0x1242,
+ 0x29C5,0x2313,0x0898,0x13C1,0x08C8,0x11F1,0x1034,0x1B24,
+ 0x0B0A,0x11E9,0x0808,0x125D,0x18E9,0x0848,0x1395,0x0965,
+ 0x123D,0x2186,0x1295,0x18CE,0x098B,0x0BEF,0x1504,0x082C,
+ 0x0A41,0x1144,0x0A89,0x0956,0x1331,0x085E,0x0B04,0x128A,
+ 0x12A3,0x1937,0x19C2,0x0952,0x0872,0x08B4,0x1262,0x1124,
+ 0x1969,0x1063,0x0AF1,0x1225,0x0894,0x11C9,0x18D2,0x0ACD,
+ 0x0A29,0x0B06,0x09B5,0x18C7,0x0916,0x1088,0x09FF,0x2206,
+ 0x0A15,0x08B3,0x0B51,0x0A1F,0x18CB,0x0AC2,0x0A2E,0x1865,
+ 0x08AC,0x0A31,0x08A4,0x138A,0x0A99,0x09D1,0x0A86,0x189B,
+ 0x0283,0x0BDD,0x0ABD,0x1933,0x083F,0x1386,0x0923,0x0322,
+ 0x0869,0x10DD,0x13B1,0x082F,0x087D,0x11B9,0x085B,0x08ED,
+ 0x00C3,0x08E2,0x084E,0x0887,0x0855,0x0A0A,0x0857,0x0B92,
+ 0x1036,0x12A5,0x0293,0x0945,0x08A6,0x0196,0x19A3,0x036F,
+ 0x0904,0x1205,0x09E1,0x0381,0x0971,0x1219,0x0BAF,0x0949,
+ 0x00AF,0x0AA9,0x018A,0x0907,0x0BFD,0x003A,0x0BCD,0x0AB2,
+ 0x088B,0x0252,0x0A4E,0x03FF,0x0845,0x0897,0x0059,0x090B,
+ 0x0B42,0x0807,0x0A16,0x0853,0x0A8D,0x01B2,0x0AB1,0x091A,
+ 0x0195,0x0A35,0x00B5,0x10AA,0x0115,0x0A21,0x0096,0x0A08,
+ 0x03FE,0x0B7F,0x08B9,0x12B3,0x023E,0x0A23,0x029E,0x08F1,
+ 0x01A9,0x0BDE,0x0843,0x02D2,0x0A1A,0x08C5,0x0151,0x0A43,
+ 0x0332,0x0383,0x0826,0x0BED,0x10C2,0x00AE,0x0B82,0x0213,
+ 0x0232,0x085D,0x02A1,0x101B,0x035F,0x0303,0x0A39,0x0207,
+ 0x0A53,0x0142,0x01A5,0x082A,0x0099,0x0A17,0x03CF,0x0906,
+ 0x0125,0x0A96,0x0A9A,0x0209,0x0393,0x0961,0x0131,0x0A88,
+ 0x0139,0x099A,0x0292,0x0272,0x0862,0x08BE,0x0141,0x02C3,
+ 0x0886,0x0039,0x08A9,0x01A2,0x01B1,0x0851,0x020B,0x086D,
+ 0x0312,0x08CD,0x020F,0x0311,0x0BCE,0x0135,0x0006,0x0849,
+ 0x0132,0x0A8F,0x022F,0x022A,0x0AAE,0x0A8E,0x0263,0x03A2,
+ 0x083E,0x009A,0x021B,0x0835,0x0323,0x0871,0x0993,0x0226,
+ 0x0302,0x0922,0x0119,0x0222,0x021D,0x0B07,0x08C9,0x037E,
+ 0x08BD,0x0042,0x00D1,0x0B33,0x01C1,0x0B9A,0x0282,0x088A,
+ 0x0182,0x083D,0x004D,0x010A,0x0A1E,0x0019,0x00B2,0x0999,
+ 0x00A5,0x0095,0x0817,0x0022,0x031A,0x0902,0x00A3,0x01BF,
+ 0x029F,0x0816,0x03B2,0x0015,0x0391,0x0BBE,0x01FE,0x1129,
+ 0x002E,0x01DF,0x0301,0x0033,0x0B6E,0x00E1,0x0297,0x00B1,
+ 0x009F,0x0B16,0x000A,0x001A,0x0052,0x080B,0x030B,0x029D,
+ 0x0BAE,0x01FD,0x020E,0x00A2,0x0A3F,0x0192,0x0ABE,0x020D,
+ 0x008F,0x028B,0x0083,0x0025,0x09EE,0x01EF,0x0029,0x0291,
+ 0x0B4F,0x0396,0x0287,0x008E,0x0092,0x0B4E,0x017E,0x001E,
+ 0x009E,0x0103,0x080F,0x000E,0x0113,0x0203,0x01CF,0x0183,
+ 0x01CE,0x001F,0x0112,0x01DE,0x038E,0x0832,0x033E,0x0212,
+ 0x029B,0x0023,0x016F,0x0201,0x09AF,0x0202,0x0281,0x035E,
+ 0x034D,0x037D,0x03AD,0x0013,0x0093,0x015F,0x0211,0x033F,
+ 0x036D,0x039F,0x03BD,0x017F,0x032E,0x032F,0x035D,0x038F,
+ 0x039E
+};
+
+static const uint16_t percentile_arr_12x12_1[246] = {
+ 0x0443,0xFFCD,0x2C62,0x2E21,0x3CF1,0x34C2,0x4CDD,0x2452,
+ 0xD5DF,0x1DD1,0x0FAE,0x64A3,0x0C7D,0x3433,0x1CD2,0x2DEF,
+ 0x0C3E,0x1D71,0xA472,0x0D32,0x54B3,0x4D51,0x445D,0x0E31,
+ 0x1FDD,0x0DFF,0x0CAE,0x45A2,0x2FBE,0xA4B9,0x1C4E,0x2C9F,
+ 0x160D,0x0D42,0x342E,0x074F,0x1414,0x0F6E,0x0CB2,0x34B5,
+ 0x0DFE,0x0D86,0x1496,0x1D22,0x0691,0x140B,0x041F,0x0C35,
+ 0x1D93,0x1506,0x1439,0x0C9A,0x0F01,0x2442,0x0C8F,0x04D1,
+ 0x1486,0x0C6D,0x0513,0x0C71,0x0E82,0x177D,0x0E03,0x07BD,
+ 0x0C2F,0x0D83,0x07AF,0x0D61,0x1407,0x0DB1,0x050A,0x0C94,
+ 0x07AD,0x0D8A,0x0C04,0x0416,0x0C49,0x0445,0x15C1,0x0C1A,
+ 0x0525,0x0595,0x0C8A,0x075E,0x0CBD,0x0681,0x0F4E,0x075F,
+ 0x061D,0x1541,0x0CB1,0x0F3F,0x0406,0x076D,0x0DCF,0x05EE,
+ 0x0D23,0x0599,0x0CCD,0x0711,0x0C23,0x079F,0x0D15,0x0585,
+ 0x04A2,0x042A,0x0D31,0x05BF,0x0D92,0x0C26,0x043D,0x0C93,
+ 0x0502,0x0C15,0x048B,0x0D03,0x0613,0x0516,0x0495,0x0C29,
+ 0x04A5,0x040F,0x0425,0x0539,0x0D19,0x04E1,0x05BE,0x0422,
+ 0x0432,0x0C0A,0x0431,0x041E,0x0492,0x04A9,0x0582,0x0529,
+ 0x0487,0x0C4D,0x0512,0x049E,0x0505,0x0451,0x0D7F,0x0489,
+ 0x0602,0x05DE,0x0591,0x0535,0x074D,0x055E,0x04C1,0x0612,
+ 0x05DD,0x05FD,0x0C61,0x0521,0x0484,0x05CE,0x0581,0x0491,
+ 0x051A,0x04A1,0x048E,0x040D,0x0499,0x071F,0x072E,0x075D,
+ 0x0441,0x0589,0x057E,0x0CAD,0x0501,0x054F,0x0692,0x0511,
+ 0x049D,0x0509,0x056E,0x040E,0x0409,0x0601,0x048D,0x0413,
+ 0x053E,0x0419,0x072D,0x0408,0x0485,0x042D,0x041D,0x05A1,
+ 0x0781,0x0402,0x05ED,0x0C82,0x0403,0x057D,0x05CD,0x0611,
+ 0x0488,0x0411,0x054E,0x051F,0x053F,0x056F,0x059F,0x070F,
+ 0x071D,0x073D,0x073E,0x077E,0x078F,0x0405,0x079D,0x079E,
+ 0x058E,0x0412,0x055D,0x05AE,0x041B,0x0421,0x0453,0x0417,
+ 0x0483,0x052E,0x052F,0x055F,0x058F,0x059E,0x05AF,0x05BD,
+ 0x060E,0x0622,0x0683,0x068D,0x0702,0x070D,0x070E,0x071E,
+ 0x072F,0x076F,0x078D,0x078E,0x07BF,0x07CE
+};
+
+static const packed_percentile_table block_pcd_12x12 =
+{
+ 12, 12,
+ { 529, 246 },
+ { 1435, 335 },
+ { 0, 22 },
+ { percentile_arr_12x12_0, percentile_arr_12x12_1 }
+};
+
+/**
+ * @brief Fetch the packed percentile table for the given 2D block size.
+ *
+ * @param xdim The block x size.
+ * @param ydim The block y size.
+ *
+ * @return The packed table.
+ */
+static const packed_percentile_table *get_packed_table(
+ int xdim,
+ int ydim
+) {
+ int idx = (ydim << 8) | xdim;
+ switch (idx)
+ {
+ case 0x0404: return &block_pcd_4x4;
+ case 0x0405: return &block_pcd_5x4;
+ case 0x0505: return &block_pcd_5x5;
+ case 0x0506: return &block_pcd_6x5;
+ case 0x0606: return &block_pcd_6x6;
+ case 0x0508: return &block_pcd_8x5;
+ case 0x0608: return &block_pcd_8x6;
+ case 0x0808: return &block_pcd_8x8;
+ case 0x050A: return &block_pcd_10x5;
+ case 0x060A: return &block_pcd_10x6;
+ case 0x080A: return &block_pcd_10x8;
+ case 0x0A0A: return &block_pcd_10x10;
+ case 0x0A0C: return &block_pcd_12x10;
+ case 0x0C0C: return &block_pcd_12x12;
+ };
+
+ // Should never hit this with a valid 2D block size
+ return nullptr;
+}
+
+/* Public function, see header file for detailed documentation */
+const float *get_2d_percentile_table(
+ int xdim,
+ int ydim
+) {
+ float* unpacked_table = new float[2048];
+ const packed_percentile_table *apt = get_packed_table(xdim, ydim);
+
+ // Set the default percentile
+ for (int i=0; i < 2048; i++)
+ {
+ unpacked_table[i] = 1.0f;
+ }
+
+ // Populate the unpacked percentile values
+ for (int i = 0; i < 2; i++)
+ {
+ int itemcount = apt->itemcounts[i];
+ int difscale = apt->difscales[i];
+ int accum = apt->initial_percs[i];
+ const uint16_t *item_ptr = apt->items[i];
+
+ for (int j = 0; j < itemcount; j++)
+ {
+ uint16_t item = item_ptr[j];
+ int idx = item & 0x7FF;
+ int weight = (item >> 11) & 0x1F;
+ accum += weight;
+ unpacked_table[idx] = (float)accum / (float)difscale;
+ }
+ }
+
+ return unpacked_table;
+}
diff --git a/third_party/astc-encoder/Source/astc_quantization.cpp b/third_party/astc-encoder/Source/astc_quantization.cpp
new file mode 100644
index 0000000..a146859
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_quantization.cpp
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions and data tables for numeric quantization..
+ */
+
+#include "astc_codec_internals.h"
+
+const uint8_t color_unquantization_tables[21][256] = {
+ {
+ 0, 255
+ },
+ {
+ 0, 128, 255
+ },
+ {
+ 0, 85, 170, 255
+ },
+ {
+ 0, 64, 128, 192, 255
+ },
+ {
+ 0, 255, 51, 204, 102, 153
+ },
+ {
+ 0, 36, 73, 109, 146, 182, 219, 255
+ },
+ {
+ 0, 255, 28, 227, 56, 199, 84, 171, 113, 142
+ },
+ {
+ 0, 255, 69, 186, 23, 232, 92, 163, 46, 209, 116, 139
+ },
+ {
+ 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
+ },
+ {
+ 0, 255, 67, 188, 13, 242, 80, 175, 27, 228, 94, 161, 40, 215, 107, 148,
+ 54, 201, 121, 134
+ },
+ {
+ 0, 255, 33, 222, 66, 189, 99, 156, 11, 244, 44, 211, 77, 178, 110, 145,
+ 22, 233, 55, 200, 88, 167, 121, 134
+ },
+ {
+ 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255
+ },
+ {
+ 0, 255, 32, 223, 65, 190, 97, 158, 6, 249, 39, 216, 71, 184, 104, 151,
+ 13, 242, 45, 210, 78, 177, 110, 145, 19, 236, 52, 203, 84, 171, 117, 138,
+ 26, 229, 58, 197, 91, 164, 123, 132
+ },
+ {
+ 0, 255, 16, 239, 32, 223, 48, 207, 65, 190, 81, 174, 97, 158, 113, 142,
+ 5, 250, 21, 234, 38, 217, 54, 201, 70, 185, 86, 169, 103, 152, 119, 136,
+ 11, 244, 27, 228, 43, 212, 59, 196, 76, 179, 92, 163, 108, 147, 124, 131
+ },
+ {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
+ 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190,
+ 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255
+ },
+ {
+ 0, 255, 16, 239, 32, 223, 48, 207, 64, 191, 80, 175, 96, 159, 112, 143,
+ 3, 252, 19, 236, 35, 220, 51, 204, 67, 188, 83, 172, 100, 155, 116, 139,
+ 6, 249, 22, 233, 38, 217, 54, 201, 71, 184, 87, 168, 103, 152, 119, 136,
+ 9, 246, 25, 230, 42, 213, 58, 197, 74, 181, 90, 165, 106, 149, 122, 133,
+ 13, 242, 29, 226, 45, 210, 61, 194, 77, 178, 93, 162, 109, 146, 125, 130
+ },
+ {
+ 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199,
+ 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135,
+ 2, 253, 10, 245, 18, 237, 26, 229, 35, 220, 43, 212, 51, 204, 59, 196,
+ 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132,
+ 5, 250, 13, 242, 21, 234, 29, 226, 37, 218, 45, 210, 53, 202, 61, 194,
+ 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129
+ },
+ {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
+ 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
+ 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
+ 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159,
+ 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191,
+ 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223,
+ 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255
+ },
+ {
+ 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199,
+ 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135,
+ 1, 254, 9, 246, 17, 238, 25, 230, 33, 222, 41, 214, 49, 206, 57, 198,
+ 65, 190, 73, 182, 81, 174, 89, 166, 97, 158, 105, 150, 113, 142, 121, 134,
+ 3, 252, 11, 244, 19, 236, 27, 228, 35, 220, 43, 212, 51, 204, 59, 196,
+ 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132,
+ 4, 251, 12, 243, 20, 235, 28, 227, 36, 219, 44, 211, 52, 203, 60, 195,
+ 68, 187, 76, 179, 84, 171, 92, 163, 100, 155, 108, 147, 116, 139, 124, 131,
+ 6, 249, 14, 241, 22, 233, 30, 225, 38, 217, 46, 209, 54, 201, 62, 193,
+ 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129
+ },
+ {
+ 0, 255, 4, 251, 8, 247, 12, 243, 16, 239, 20, 235, 24, 231, 28, 227,
+ 32, 223, 36, 219, 40, 215, 44, 211, 48, 207, 52, 203, 56, 199, 60, 195,
+ 64, 191, 68, 187, 72, 183, 76, 179, 80, 175, 84, 171, 88, 167, 92, 163,
+ 96, 159, 100, 155, 104, 151, 108, 147, 112, 143, 116, 139, 120, 135, 124, 131,
+ 1, 254, 5, 250, 9, 246, 13, 242, 17, 238, 21, 234, 25, 230, 29, 226,
+ 33, 222, 37, 218, 41, 214, 45, 210, 49, 206, 53, 202, 57, 198, 61, 194,
+ 65, 190, 69, 186, 73, 182, 77, 178, 81, 174, 85, 170, 89, 166, 93, 162,
+ 97, 158, 101, 154, 105, 150, 109, 146, 113, 142, 117, 138, 121, 134, 125, 130,
+ 2, 253, 6, 249, 10, 245, 14, 241, 18, 237, 22, 233, 26, 229, 30, 225,
+ 34, 221, 38, 217, 42, 213, 46, 209, 50, 205, 54, 201, 58, 197, 62, 193,
+ 66, 189, 70, 185, 74, 181, 78, 177, 82, 173, 86, 169, 90, 165, 94, 161,
+ 98, 157, 102, 153, 106, 149, 110, 145, 114, 141, 118, 137, 122, 133, 126, 129
+ },
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ }
+};
+
+// quantization_mode_table[integercount/2][bits] gives
+// us the quantization level for a given integer count and number of bits that
+// the integer may fit into. This is needed for color decoding,
+// and for the color encoding.
+int quantization_mode_table[17][128];
+
+void build_quantization_mode_table()
+{
+ int i, j;
+ for (i = 0; i <= 16; i++)
+ {
+ for (j = 0; j < 128; j++)
+ {
+ quantization_mode_table[i][j] = -1;
+ }
+ }
+
+ for (i = 0; i < 21; i++)
+ {
+ for (j = 1; j <= 16; j++)
+ {
+ int p = compute_ise_bitcount(2 * j, (quantization_method) i);
+ if (p < 128)
+ quantization_mode_table[j][p] = i;
+ }
+ }
+
+ for (i = 0; i <= 16; i++)
+ {
+ int largest_value_so_far = -1;
+ for (j = 0; j < 128; j++)
+ {
+ if (quantization_mode_table[i][j] > largest_value_so_far)
+ largest_value_so_far = quantization_mode_table[i][j];
+ else
+ quantization_mode_table[i][j] = largest_value_so_far;
+ }
+ }
+}
diff --git a/third_party/astc-encoder/Source/astc_symbolic_physical.cpp b/third_party/astc-encoder/Source/astc_symbolic_physical.cpp
new file mode 100644
index 0000000..9c5bd56
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_symbolic_physical.cpp
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Functions for converting between symbolic and physical encodings.
+ */
+
+#include "astc_codec_internals.h"
+
+// routine to read up to 8 bits
+static inline int read_bits(
+ int bitcount,
+ int bitoffset,
+ const uint8_t* ptr
+) {
+ int mask = (1 << bitcount) - 1;
+ ptr += bitoffset >> 3;
+ bitoffset &= 7;
+ int value = ptr[0] | (ptr[1] << 8);
+ value >>= bitoffset;
+ value &= mask;
+ return value;
+}
+
+static inline int bitrev8(int p)
+{
+ p = ((p & 0xF) << 4) | ((p >> 4) & 0xF);
+ p = ((p & 0x33) << 2) | ((p >> 2) & 0x33);
+ p = ((p & 0x55) << 1) | ((p >> 1) & 0x55);
+ return p;
+}
+
+void physical_to_symbolic(
+ const block_size_descriptor* bsd,
+ physical_compressed_block pb,
+ symbolic_compressed_block* res
+) {
+ uint8_t bswapped[16];
+ int i, j;
+
+ res->error_block = 0;
+
+ // get hold of the decimation tables.
+ const decimation_table *const *ixtab2 = bsd->decimation_tables;
+
+ // extract header fields
+ int block_mode = read_bits(11, 0, pb.data);
+ if ((block_mode & 0x1FF) == 0x1FC)
+ {
+ // void-extent block!
+
+ // check what format the data has
+ if (block_mode & 0x200)
+ res->block_mode = -1; // floating-point
+ else
+ res->block_mode = -2; // unorm16.
+
+ res->partition_count = 0;
+ for (i = 0; i < 4; i++)
+ {
+ res->constant_color[i] = pb.data[2 * i + 8] | (pb.data[2 * i + 9] << 8);
+ }
+
+ // additionally, check that the void-extent
+ if (bsd->zdim == 1)
+ {
+ // 2D void-extent
+ int rsvbits = read_bits(2, 10, pb.data);
+ if (rsvbits != 3)
+ res->error_block = 1;
+
+ int vx_low_s = read_bits(8, 12, pb.data) | (read_bits(5, 12 + 8, pb.data) << 8);
+ int vx_high_s = read_bits(8, 25, pb.data) | (read_bits(5, 25 + 8, pb.data) << 8);
+ int vx_low_t = read_bits(8, 38, pb.data) | (read_bits(5, 38 + 8, pb.data) << 8);
+ int vx_high_t = read_bits(8, 51, pb.data) | (read_bits(5, 51 + 8, pb.data) << 8);
+
+ int all_ones = vx_low_s == 0x1FFF && vx_high_s == 0x1FFF && vx_low_t == 0x1FFF && vx_high_t == 0x1FFF;
+
+ if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t) && !all_ones)
+ res->error_block = 1;
+ }
+ else
+ {
+ // 3D void-extent
+ int vx_low_s = read_bits(9, 10, pb.data);
+ int vx_high_s = read_bits(9, 19, pb.data);
+ int vx_low_t = read_bits(9, 28, pb.data);
+ int vx_high_t = read_bits(9, 37, pb.data);
+ int vx_low_p = read_bits(9, 46, pb.data);
+ int vx_high_p = read_bits(9, 55, pb.data);
+
+ 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;
+
+ if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t || vx_low_p >= vx_high_p) && !all_ones)
+ res->error_block = 1;
+ }
+
+ return;
+ }
+
+ if (bsd->block_modes[block_mode].permit_decode == 0)
+ {
+ res->error_block = 1;
+ return;
+ }
+
+ int weight_count = ixtab2[bsd->block_modes[block_mode].decimation_mode]->num_weights;
+ int weight_quantization_method = bsd->block_modes[block_mode].quantization_mode;
+ int is_dual_plane = bsd->block_modes[block_mode].is_dual_plane;
+
+ int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count;
+
+ int partition_count = read_bits(2, 11, pb.data) + 1;
+
+ res->block_mode = block_mode;
+ res->partition_count = partition_count;
+
+ for (i = 0; i < 16; i++)
+ bswapped[i] = bitrev8(pb.data[15 - i]);
+
+ int bits_for_weights = compute_ise_bitcount(real_weight_count,
+ (quantization_method) weight_quantization_method);
+
+ int below_weights_pos = 128 - bits_for_weights;
+
+ if (is_dual_plane)
+ {
+ uint8_t indices[64];
+ decode_ise(weight_quantization_method, real_weight_count, bswapped, indices, 0);
+ for (i = 0; i < weight_count; i++)
+ {
+ res->plane1_weights[i] = indices[2 * i];
+ res->plane2_weights[i] = indices[2 * i + 1];
+ }
+ }
+ else
+ {
+ decode_ise(weight_quantization_method, weight_count, bswapped, res->plane1_weights, 0);
+ }
+
+ if (is_dual_plane && partition_count == 4)
+ res->error_block = 1;
+
+ res->color_formats_matched = 0;
+
+ // then, determine the format of each endpoint pair
+ int color_formats[4];
+ int encoded_type_highpart_size = 0;
+ if (partition_count == 1)
+ {
+ color_formats[0] = read_bits(4, 13, pb.data);
+ res->partition_index = 0;
+ }
+ else
+ {
+ encoded_type_highpart_size = (3 * partition_count) - 4;
+ below_weights_pos -= encoded_type_highpart_size;
+ int encoded_type = read_bits(6, 13 + PARTITION_BITS, pb.data) | (read_bits(encoded_type_highpart_size, below_weights_pos, pb.data) << 6);
+ int baseclass = encoded_type & 0x3;
+ if (baseclass == 0)
+ {
+ for (i = 0; i < partition_count; i++)
+ {
+ color_formats[i] = (encoded_type >> 2) & 0xF;
+ }
+ below_weights_pos += encoded_type_highpart_size;
+ res->color_formats_matched = 1;
+ encoded_type_highpart_size = 0;
+ }
+ else
+ {
+ int bitpos = 2;
+ baseclass--;
+ for (i = 0; i < partition_count; i++)
+ {
+ color_formats[i] = (((encoded_type >> bitpos) & 1) + baseclass) << 2;
+ bitpos++;
+ }
+ for (i = 0; i < partition_count; i++)
+ {
+ color_formats[i] |= (encoded_type >> bitpos) & 3;
+ bitpos += 2;
+ }
+ }
+ res->partition_index = read_bits(6, 13, pb.data) | (read_bits(PARTITION_BITS - 6, 19, pb.data) << 6);
+ }
+
+ for (i = 0; i < partition_count; i++)
+ res->color_formats[i] = color_formats[i];
+
+ // then, determine the number of integers we need to unpack for the endpoint pairs
+ int color_integer_count = 0;
+ for (i = 0; i < partition_count; i++)
+ {
+ int endpoint_class = color_formats[i] >> 2;
+ color_integer_count += (endpoint_class + 1) * 2;
+ }
+
+ if (color_integer_count > 18)
+ res->error_block = 1;
+
+ // then, determine the color endpoint format to use for these integers
+ static const int color_bits_arr[5] = { -1, 115 - 4, 113 - 4 - PARTITION_BITS, 113 - 4 - PARTITION_BITS, 113 - 4 - PARTITION_BITS };
+ int color_bits = color_bits_arr[partition_count] - bits_for_weights - encoded_type_highpart_size;
+ if (is_dual_plane)
+ color_bits -= 2;
+ if (color_bits < 0)
+ color_bits = 0;
+
+ int color_quantization_level = quantization_mode_table[color_integer_count >> 1][color_bits];
+ res->color_quantization_level = color_quantization_level;
+ if (color_quantization_level < 4)
+ res->error_block = 1;
+
+ // then unpack the integer-bits
+ uint8_t values_to_decode[32];
+ decode_ise(color_quantization_level, color_integer_count, pb.data, values_to_decode, (partition_count == 1 ? 17 : 19 + PARTITION_BITS));
+
+ // and distribute them over the endpoint types
+ int valuecount_to_decode = 0;
+
+ for (i = 0; i < partition_count; i++)
+ {
+ int vals = 2 * (color_formats[i] >> 2) + 2;
+ for (j = 0; j < vals; j++)
+ res->color_values[i][j] = values_to_decode[j + valuecount_to_decode];
+ valuecount_to_decode += vals;
+ }
+
+ // get hold of color component for second-plane in the case of dual plane of weights.
+ if (is_dual_plane)
+ res->plane2_color_component = read_bits(2, below_weights_pos - 2, pb.data);
+}
diff --git a/third_party/astc-encoder/Source/astc_weight_quant_xfer_tables.cpp b/third_party/astc-encoder/Source/astc_weight_quant_xfer_tables.cpp
new file mode 100644
index 0000000..9a1b6ae
--- /dev/null
+++ b/third_party/astc-encoder/Source/astc_weight_quant_xfer_tables.cpp
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2020 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+/**
+ * @brief Data tables for quantization transfer.
+ */
+
+#include "astc_codec_internals.h"
+
+#define _ 0 // using _ to indicate an entry that will not be used.
+
+const quantization_and_transfer_table quant_and_xfer_tables[12] = {
+ // quantization method 0, range 0..1
+ {
+ QUANT_2,
+ {0, 64, 255},
+ {0, 1},
+ {0, 64},
+ {0x01004000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
+ 0x01004000}
+ },
+ // quantization method 1, range 0..2
+ {
+ QUANT_3,
+ {0, 32, 64, 255},
+ {0, 1, 2},
+ {0, 32, 64},
+ {0x01002000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
+ _,_,0x02004000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,0x02014020}
+ },
+ // quantization method 2, range 0..3
+ {
+ QUANT_4,
+ {0, 21, 43, 64, 255},
+ {0, 1, 2, 3},
+ {0, 21, 43, 64},
+ {0x01001500,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x02002b00,_,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x03014015,_,_,_,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,_,_,0x0302402b}
+ },
+ // quantization method 3, range 0..4
+ {
+ QUANT_5,
+ {0, 16, 32, 48, 64, 255},
+ {0, 1, 2, 3, 4},
+ {0, 16, 32, 48, 64},
+ {0x01001000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x02002000,_,_,_,_,_,_,_,_,_,
+ _,_,_,_,_,_,0x03013010,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x04024020,_,_,_,
+ _,_,_,_,_,_,_,_,_,_,_,_,0x04034030}
+ },
+ // quantization method 4, range 0..5
+ {
+ QUANT_6,
+ {0, 12, 25, 39, 52, 64, 255},
+ {0, 2, 4, 5, 3, 1},
+ {0, 64, 12, 52, 25, 39},
+ {0x02000c00,_,_,_,_,_,_,_,_,_,_,_,0x04001900,_,_,_,_,_,_,_,_,_,_,_,_,
+ 0x0502270c,_,_,_,_,_,_,_,_,_,_,_,_,_,0x03043419,_,_,_,_,_,_,_,_,_,_,
+ _,_,0x01054027,_,_,_,_,_,_,_,_,_,_,_,0x01034034}
+ },
+ // quantization method 5, range 0..7
+ {
+ QUANT_8,
+ {0, 9, 18, 27, 37, 46, 55, 64, 255},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {0, 9, 18, 27, 37, 46, 55, 64},
+ {0x01000900,_,_,_,_,_,_,_,_,0x02001200,_,_,_,_,_,_,_,_,0x03011b09,_,_,
+ _,_,_,_,_,_,0x04022512,_,_,_,_,_,_,_,_,_,0x05032e1b,_,_,_,_,_,_,_,_,
+ 0x06043725,_,_,_,_,_,_,_,_,0x0705402e,_,_,_,_,_,_,_,_,0x07064037}
+ },
+ // quantization method 6, range 0..9
+ {
+ QUANT_10,
+ {0, 7, 14, 21, 28, 36, 43, 50, 57, 64, 255},
+ {0, 2, 4, 6, 8, 9, 7, 5, 3, 1},
+ {0, 64, 7, 57, 14, 50, 21, 43, 28, 36},
+ {0x02000700,_,_,_,_,_,_,0x04000e00,_,_,_,_,_,_,0x06021507,_,_,_,_,_,_,
+ 0x08041c0e,_,_,_,_,_,_,0x09062415,_,_,_,_,_,_,_,0x07082b1c,_,_,_,_,_,
+ _,0x05093224,_,_,_,_,_,_,0x0307392b,_,_,_,_,_,_,0x01054032,_,_,_,_,_,
+ _,0x01034039}
+ },
+ // quantization method 7, range 0..11
+ {
+ QUANT_12,
+ {0, 5, 11, 17, 23, 28, 36, 41, 47, 53, 59, 64, 255},
+ {0, 4, 8, 2, 6, 10, 11, 7, 3, 9, 5, 1},
+ {0, 64, 17, 47, 5, 59, 23, 41, 11, 53, 28, 36},
+ {0x04000500,_,_,_,_,0x08000b00,_,_,_,_,_,0x02041105,_,_,_,_,_,
+ 0x0608170b,_,_,_,_,_,0x0a021c11,_,_,_,_,0x0b062417,_,_,_,_,_,_,_,
+ 0x070a291c,_,_,_,_,0x030b2f24,_,_,_,_,_,0x09073529,_,_,_,_,_,
+ 0x05033b2f,_,_,_,_,_,0x01094035,_,_,_,_,0x0105403b}
+ },
+ // quantization method 8, range 0..15
+ {
+ QUANT_16,
+ {0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64, 255},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64},
+ {0x01000400,_,_,_,0x02000800,_,_,_,0x03010c04,_,_,_,0x04021108,_,_,_,_,
+ 0x0503150c,_,_,_,0x06041911,_,_,_,0x07051d15,_,_,_,0x08062319,_,_,_,_,
+ _,0x0907271d,_,_,_,0x0a082b23,_,_,_,0x0b092f27,_,_,_,0x0c0a342b,_,_,_,
+ _,0x0d0b382f,_,_,_,0x0e0c3c34,_,_,_,0x0f0d4038,_,_,_,0x0f0e403c}
+ },
+ // quantization method 9, range 0..19
+ {
+ QUANT_20,
+ {0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 35, 38, 41, 45, 48, 51, 55, 58,
+ 61, 64, 255},
+ {0, 4, 8, 12, 16, 2, 6, 10, 14, 18, 19, 15, 11, 7, 3, 17, 13, 9, 5, 1},
+ {0, 64, 16, 48, 3, 61, 19, 45, 6, 58, 23, 41, 9, 55, 26, 38, 13, 51,
+ 29, 35},
+ {0x04000300,_,_,0x08000600,_,_,0x0c040903,_,_,0x10080d06,_,_,_,
+ 0x020c1009,_,_,0x0610130d,_,_,0x0a021710,_,_,_,0x0e061a13,_,_,
+ 0x120a1d17,_,_,0x130e231a,_,_,_,_,_,0x0f12261d,_,_,0x0b132923,_,_,
+ 0x070f2d26,_,_,_,0x030b3029,_,_,0x1107332d,_,_,0x0d033730,_,_,_,
+ 0x09113a33,_,_,0x050d3d37,_,_,0x0109403a,_,_,0x0105403d}
+ },
+ // quantization method 10, range 0..23
+ {
+ QUANT_24,
+ {0, 2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 34, 37, 40, 42, 45, 48,
+ 51, 53, 56, 59, 62, 64, 255},
+ {0, 8, 16, 2, 10, 18, 4, 12, 20, 6, 14, 22, 23, 15, 7, 21, 13, 5, 19,
+ 11, 3, 17, 9, 1},
+ {0, 64, 8, 56, 16, 48, 24, 40, 2, 62, 11, 53, 19, 45, 27, 37, 5, 59,
+ 13, 51, 22, 42, 30, 34},
+ {0x08000200,_,0x10000500,_,_,0x02080802,_,_,0x0a100b05,_,_,0x12020d08,
+ _,0x040a100b,_,_,0x0c12130d,_,_,0x14041610,_,_,0x060c1813,_,
+ 0x0e141b16,_,_,0x16061e18,_,_,0x170e221b,_,_,_,0x0f16251e,_,_,
+ 0x07172822,_,_,0x150f2a25,_,0x0d072d28,_,_,0x0515302a,_,_,0x130d332d,
+ _,_,0x0b053530,_,0x03133833,_,_,0x110b3b35,_,_,0x09033e38,_,_,
+ 0x0111403b,_,0x0109403e}
+ },
+ // quantization method 11, range 0..31
+ {
+ QUANT_32,
+ {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38,
+ 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 255},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+ {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38,
+ 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64},
+ {0x01000200,_,0x02000400,_,0x03010602,_,0x04020804,_,0x05030a06,_,
+ 0x06040c08,_,0x07050e0a,_,0x0806100c,_,0x0907120e,_,0x0a081410,_,
+ 0x0b091612,_,0x0c0a1814,_,0x0d0b1a16,_,0x0e0c1c18,_,0x0f0d1e1a,_,
+ 0x100e221c,_,_,_,0x110f241e,_,0x12102622,_,0x13112824,_,0x14122a26,_,
+ 0x15132c28,_,0x16142e2a,_,0x1715302c,_,0x1816322e,_,0x19173430,_,
+ 0x1a183632,_,0x1b193834,_,0x1c1a3a36,_,0x1d1b3c38,_,0x1e1c3e3a,_,
+ 0x1f1d403c,_,0x1f1e403e}
+ }
+};