aboutsummaryrefslogtreecommitdiff
path: root/src/decoder/test/physical_astc_block_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder/test/physical_astc_block_test.cc')
-rw-r--r--src/decoder/test/physical_astc_block_test.cc361
1 files changed, 361 insertions, 0 deletions
diff --git a/src/decoder/test/physical_astc_block_test.cc b/src/decoder/test/physical_astc_block_test.cc
new file mode 100644
index 0000000..8eafe46
--- /dev/null
+++ b/src/decoder/test/physical_astc_block_test.cc
@@ -0,0 +1,361 @@
+// Copyright 2018 Google LLC
+//
+// 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
+//
+// https://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 "src/decoder/physical_astc_block.h"
+#include "src/base/uint128.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+using astc_codec::PhysicalASTCBlock;
+using astc_codec::ColorEndpointMode;
+using astc_codec::base::UInt128;
+
+namespace {
+
+static const PhysicalASTCBlock kErrorBlock(UInt128(0));
+
+// Test to make sure that each of the constructors work and that
+// they produce the same block encodings, since the ASTC blocks
+// are little-endian
+TEST(PhysicalASTCBlockTest, TestConstructors) {
+ // Little-endian reading of bytes
+ PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
+ PhysicalASTCBlock blk2(
+ std::string("\x73\x01\x00\xFE\x01\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16));
+ EXPECT_EQ(blk1.GetBlockBits(), blk2.GetBlockBits());
+}
+
+// Test to see if we properly decode the maximum value that a weight
+// can take in an ASTC block based on the block mode encoding. We test
+// against a valid case and various error cases
+TEST(PhysicalASTCBlockTest, TestWeightRange) {
+ PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
+ auto weight_range = blk1.WeightRange();
+ ASSERT_TRUE(weight_range);
+ EXPECT_EQ(weight_range.value(), 7);
+
+ // If we flip the high bit then we should have a range of 31,
+ // although then we have too many bits and this should error.
+ PhysicalASTCBlock blk2(0x0000000001FE000373ULL);
+ EXPECT_FALSE(blk2.WeightRange());
+
+ // One bit per weight -- range of 1
+ PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
+ weight_range = non_shared_cem.WeightRange();
+ ASSERT_TRUE(weight_range);
+ EXPECT_EQ(weight_range.value(), 1);
+
+ // Error blocks have no weight range
+ EXPECT_FALSE(kErrorBlock.WeightRange());
+}
+
+// Test to see if we properly decode the weight grid width and height
+// in an ASTC block based on the block mode encoding. We test against
+// a valid case and various error cases
+TEST(PhysicalASTCBlockTest, TestWeightDims) {
+ PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
+ auto weight_dims = blk1.WeightGridDims();
+ EXPECT_TRUE(weight_dims);
+ EXPECT_EQ(weight_dims.value()[0], 6);
+ EXPECT_EQ(weight_dims.value()[1], 5);
+
+ // If we flip the high bit then we should have a range of 31,
+ // although then we have too many bits for the weight grid
+ // and this should error.
+ PhysicalASTCBlock blk2(0x0000000001FE000373ULL);
+ EXPECT_FALSE(blk2.WeightGridDims());
+ EXPECT_EQ(blk2.IsIllegalEncoding().value(),
+ "Too many bits required for weight grid");
+
+ // Dual plane block with 3x5 weight dims
+ PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
+ weight_dims = blk3.WeightGridDims();
+ ASSERT_TRUE(weight_dims);
+ EXPECT_EQ(weight_dims->at(0), 3);
+ EXPECT_EQ(weight_dims->at(1), 5);
+
+ // Error blocks shouldn't have any weight dims
+ EXPECT_FALSE(kErrorBlock.WeightGridDims());
+
+ PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
+ weight_dims = non_shared_cem.WeightGridDims();
+ ASSERT_TRUE(weight_dims);
+ EXPECT_EQ(weight_dims->at(0), 8);
+ EXPECT_EQ(weight_dims->at(1), 8);
+}
+
+// Test to see whether or not the presence of a dual-plane bit
+// is decoded properly. Error encodings are tested to *not* return
+// that they have dual planes.
+TEST(PhysicalASTCBlockTest, TestDualPlane) {
+ PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
+ EXPECT_FALSE(blk1.IsDualPlane());
+ EXPECT_FALSE(kErrorBlock.IsDualPlane());
+
+ // If we flip the dual plane bit, we will have too many bits
+ // for the weight grid and this should error
+ PhysicalASTCBlock blk2(0x0000000001FE000573ULL);
+ EXPECT_FALSE(blk2.IsDualPlane());
+ EXPECT_FALSE(blk2.WeightGridDims());
+ EXPECT_EQ(blk2.IsIllegalEncoding().value(),
+ "Too many bits required for weight grid");
+
+ // A dual plane with 3x5 weight grid should be supported
+ PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
+ EXPECT_TRUE(blk3.IsDualPlane());
+
+ // If we use the wrong block mode, then a valid block
+ // shouldn't have any dual plane
+ PhysicalASTCBlock blk4(0x0000000001FE000108ULL);
+ EXPECT_FALSE(blk4.IsDualPlane());
+ EXPECT_FALSE(blk4.IsIllegalEncoding());
+}
+
+// Make sure that we properly calculate the number of bits used to encode
+// the weight grid. Given error encodings or void extent blocks, this number
+// should be zero
+TEST(PhysicalASTCBlockTest, TestNumWeightBits) {
+ // 6x5 single-plane weight grid with 3-bit weights
+ // should have 90 bits for the weights.
+ PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
+ EXPECT_EQ(90, blk1.NumWeightBits());
+
+ // Error block has no weight bits
+ EXPECT_FALSE(kErrorBlock.NumWeightBits());
+
+ // Void extent blocks have no weight bits
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumWeightBits());
+
+ // If we flip the dual plane bit, we will have too many bits
+ // for the weight grid and this should error and return no bits
+ PhysicalASTCBlock blk2(0x0000000001FE000573ULL);
+ EXPECT_FALSE(blk2.NumWeightBits());
+
+ // 3x5 dual-plane weight grid with 3-bit weights
+ // should have 90 bits for the weights.
+ PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
+ EXPECT_EQ(90, blk3.NumWeightBits());
+}
+
+// Test to make sure that our weight bits start where we expect them to.
+// In other words, make sure that the calculation based on the block mode for
+// where the weight bits start is accurate.
+TEST(PhysicalASTCBlockTest, TestStartWeightBit) {
+ EXPECT_EQ(PhysicalASTCBlock(0x4000000000800D44ULL).WeightStartBit(), 64);
+
+ // Error blocks have no weight start bit
+ EXPECT_FALSE(kErrorBlock.WeightStartBit());
+
+ // Void extent blocks have no weight start bit
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).WeightStartBit());
+}
+
+// Test to make sure that we catch various different reasons for error encoding
+// of ASTC blocks, but also that certain encodings aren't errors.
+TEST(PhysicalASTCBlockTest, TestErrorBlocks) {
+ // Various valid block modes
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).IsIllegalEncoding());
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE0005FFULL).IsIllegalEncoding());
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000108ULL).IsIllegalEncoding());
+
+ // This is an error because it uses an invalid block mode
+ EXPECT_EQ(kErrorBlock.IsIllegalEncoding().value(), "Reserved block mode");
+
+ // This is an error because we have too many weight bits
+ PhysicalASTCBlock err_blk(0x0000000001FE000573ULL);
+ EXPECT_EQ(err_blk.IsIllegalEncoding().value(),
+ "Too many bits required for weight grid");
+
+ // This is an error because we have too many weights
+ PhysicalASTCBlock err_blk2 = PhysicalASTCBlock(0x0000000001FE0005A8ULL);
+ EXPECT_EQ(err_blk2.IsIllegalEncoding().value(), "Too many weights specified");
+
+ PhysicalASTCBlock err_blk3 = PhysicalASTCBlock(0x0000000001FE000588ULL);
+ EXPECT_EQ(err_blk3.IsIllegalEncoding().value(), "Too many weights specified");
+
+ // This is an error because we have too few weights
+ PhysicalASTCBlock err_blk4 = PhysicalASTCBlock(0x0000000001FE00002ULL);
+ EXPECT_EQ(err_blk4.IsIllegalEncoding().value(),
+ "Too few bits required for weight grid");
+
+ // Four partitions, dual plane -- should be error
+ // 2x2 weight grid, 3 bits per weight
+ PhysicalASTCBlock dual_plane_four_parts(0x000000000000001D1FULL);
+ EXPECT_FALSE(dual_plane_four_parts.NumPartitions());
+ EXPECT_EQ(dual_plane_four_parts.IsIllegalEncoding().value(),
+ "Both four partitions and dual plane specified");
+}
+
+// Test to make sure that we properly identify and can manipulate void-extent
+// blocks. These are ASTC blocks that only define a single color for the entire
+// block.
+TEST(PhysicalASTCBlockTest, TestVoidExtentBlocks) {
+ // Various valid block modes that aren't void extent blocks
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).IsVoidExtent());
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE0005FFULL).IsVoidExtent());
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000108ULL).IsVoidExtent());
+
+ // Error block is not a void extent block
+ EXPECT_FALSE(kErrorBlock.IsVoidExtent());
+
+ // Void extent block is void extent block...
+ UInt128 void_extent_encoding(0, 0xFFF8003FFE000DFCULL);
+ EXPECT_FALSE(PhysicalASTCBlock(void_extent_encoding).IsIllegalEncoding());
+ EXPECT_TRUE(PhysicalASTCBlock(void_extent_encoding).IsVoidExtent());
+
+ // If we modify the high 64 bits it shouldn't change anything
+ void_extent_encoding |= UInt128(0xdeadbeefdeadbeef, 0);
+ EXPECT_FALSE(PhysicalASTCBlock(void_extent_encoding).IsIllegalEncoding());
+ EXPECT_TRUE(PhysicalASTCBlock(void_extent_encoding).IsVoidExtent());
+}
+
+TEST(PhysicalASTCBlockTest, TestVoidExtentCoordinates) {
+ // The void extent block should have texture coordinates from 0-8191
+ auto coords = PhysicalASTCBlock(0xFFF8003FFE000DFCULL).VoidExtentCoords();
+ EXPECT_EQ(coords->at(0), 0);
+ EXPECT_EQ(coords->at(1), 8191);
+ EXPECT_EQ(coords->at(2), 0);
+ EXPECT_EQ(coords->at(3), 8191);
+
+ // If we set the coords to all 1's then it's still a void extent
+ // block, but there aren't any void extent coords.
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).IsIllegalEncoding());
+ EXPECT_TRUE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).IsVoidExtent());
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).VoidExtentCoords());
+
+ // If we set the void extent coords to something where the coords are
+ // >= each other, then the encoding is illegal.
+ EXPECT_TRUE(PhysicalASTCBlock(0x0008004002001DFCULL).IsIllegalEncoding());
+ EXPECT_TRUE(PhysicalASTCBlock(0x0007FFC001FFFDFCULL).IsIllegalEncoding());
+}
+
+// Test to see if we can properly identify the number of partitions in a block
+// In particular -- we need to make sure we properly identify single and
+// multi-partition blocks, but also that void extent and error blocks don't
+// return valid numbers of partitions
+TEST(PhysicalASTCBlockTest, TestNumPartitions) {
+ // Various valid block modes, but all single partition
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumPartitions(), 1);
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE0005FFULL).NumPartitions(), 1);
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000108ULL).NumPartitions(), 1);
+
+ // Two to four partitions don't have enough bits for color.
+ EXPECT_FALSE(PhysicalASTCBlock(0x000000000000000973ULL).NumPartitions());
+ EXPECT_FALSE(PhysicalASTCBlock(0x000000000000001173ULL).NumPartitions());
+ EXPECT_FALSE(PhysicalASTCBlock(0x000000000000001973ULL).NumPartitions());
+
+ // Test against having more than one partition
+ PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
+ EXPECT_EQ(non_shared_cem.NumPartitions(), 2);
+}
+
+// Test the color endpoint modes specified for how the endpoints are encoded.
+// In particular, test that shared color endpoint modes work for multi-partition
+// blocks and that non-shared color endpoint modes also work.
+TEST(PhysicalASTCBlockTest, TestColorEndpointModes) {
+ // Four partitions -- one shared CEM
+ const auto blk1 = PhysicalASTCBlock(0x000000000000001961ULL);
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_EQ(blk1.GetEndpointMode(i), ColorEndpointMode::kLDRLumaDirect);
+ }
+
+ // Void extent blocks have no endpoint modes
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).GetEndpointMode(0));
+
+ // Test out of range partitions
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(1));
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(-1));
+ EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(100));
+
+ // Error blocks have no endpoint modes
+ EXPECT_FALSE(kErrorBlock.GetEndpointMode(0));
+
+ // Test non-shared CEMs
+ PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
+ EXPECT_EQ(non_shared_cem.GetEndpointMode(0),
+ ColorEndpointMode::kLDRLumaDirect);
+ EXPECT_EQ(non_shared_cem.GetEndpointMode(1),
+ ColorEndpointMode::kLDRLumaBaseOffset);
+}
+
+// Make sure that if we have more than one partition then we have proper
+// partition IDs (these determine which pixels correspond to which partition)
+TEST(PhysicalASTCBlockTest, TestPartitionID) {
+ // Valid partitions
+ EXPECT_EQ(PhysicalASTCBlock(0x4000000000FFED44ULL).PartitionID(), 0x3FF);
+ EXPECT_EQ(PhysicalASTCBlock(0x4000000000AAAD44ULL).PartitionID(), 0x155);
+
+ // Error blocks have no partition IDs
+ EXPECT_FALSE(kErrorBlock.PartitionID());
+
+ // Void extent blocks have no endpoint modes
+ EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).PartitionID());
+}
+
+// Make sure that we're properly attributing the number of bits associated with
+// the encoded color values.
+TEST(PhysicalASTCBlockTest, TestNumColorBits) {
+ // If we're using a direct luma channel, then the number of color bits is 16
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumColorValues(), 2);
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumColorBits(), 16);
+
+ // Error blocks have nothing
+ EXPECT_FALSE(kErrorBlock.NumColorValues());
+ EXPECT_FALSE(kErrorBlock.NumColorBits());
+
+ // Void extent blocks have four color values and 64 bits of color
+ EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumColorValues(), 4);
+ EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumColorBits(), 64);
+}
+
+// Make sure that we're properly decoding the range of values that each of the
+// encoded color values can take
+TEST(PhysicalASTCBlockTest, TestColorValuesRange) {
+ // If we're using a direct luma channel, then we use two color values up to
+ // a full byte each.
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).ColorValuesRange(), 255);
+
+ // Error blocks have nothing
+ EXPECT_FALSE(kErrorBlock.ColorValuesRange());
+
+ // Void extent blocks have four color values and 64 bits of color, so the
+ // color range for each is sixteen bits.
+ EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).ColorValuesRange(),
+ (1 << 16) - 1);
+}
+
+// Test that we know where the color data starts. This is different mostly
+// depending on whether or not the block is single-partition or void extent.
+TEST(PhysicalASTCBlockTest, TestColorStartBits) {
+ // Void extent blocks start at bit 64
+ EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).ColorStartBit(), 64);
+
+ // Error blocks don't start anywhere
+ EXPECT_FALSE(kErrorBlock.ColorStartBit());
+
+ // Single partition blocks start at bit 17
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).ColorStartBit(), 17);
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE0005FFULL).ColorStartBit(), 17);
+ EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000108ULL).ColorStartBit(), 17);
+
+ // Multi-partition blocks start at bit 29
+ EXPECT_EQ(PhysicalASTCBlock(0x4000000000FFED44ULL).ColorStartBit(), 29);
+ EXPECT_EQ(PhysicalASTCBlock(0x4000000000AAAD44ULL).ColorStartBit(), 29);
+}
+
+} // namespace