• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/decoder/physical_astc_block.h"
16 #include "src/base/uint128.h"
17 
18 #include <gtest/gtest.h>
19 
20 #include <string>
21 #include <vector>
22 
23 using astc_codec::PhysicalASTCBlock;
24 using astc_codec::ColorEndpointMode;
25 using astc_codec::base::UInt128;
26 
27 namespace {
28 
29 static const PhysicalASTCBlock kErrorBlock(UInt128(0));
30 
31 // Test to make sure that each of the constructors work and that
32 // they produce the same block encodings, since the ASTC blocks
33 // are little-endian
TEST(PhysicalASTCBlockTest,TestConstructors)34 TEST(PhysicalASTCBlockTest, TestConstructors) {
35   // Little-endian reading of bytes
36   PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
37   PhysicalASTCBlock blk2(
38       std::string("\x73\x01\x00\xFE\x01\x00\x00\x00\x00"
39                   "\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16));
40   EXPECT_EQ(blk1.GetBlockBits(), blk2.GetBlockBits());
41 }
42 
43 // Test to see if we properly decode the maximum value that a weight
44 // can take in an ASTC block based on the block mode encoding. We test
45 // against a valid case and various error cases
TEST(PhysicalASTCBlockTest,TestWeightRange)46 TEST(PhysicalASTCBlockTest, TestWeightRange) {
47   PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
48   auto weight_range = blk1.WeightRange();
49   ASSERT_TRUE(weight_range);
50   EXPECT_EQ(weight_range.value(), 7);
51 
52   // If we flip the high bit then we should have a range of 31,
53   // although then we have too many bits and this should error.
54   PhysicalASTCBlock blk2(0x0000000001FE000373ULL);
55   EXPECT_FALSE(blk2.WeightRange());
56 
57   // One bit per weight -- range of 1
58   PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
59   weight_range = non_shared_cem.WeightRange();
60   ASSERT_TRUE(weight_range);
61   EXPECT_EQ(weight_range.value(), 1);
62 
63   // Error blocks have no weight range
64   EXPECT_FALSE(kErrorBlock.WeightRange());
65 }
66 
67 // Test to see if we properly decode the weight grid width and height
68 // in an ASTC block based on the block mode encoding. We test against
69 // a valid case and various error cases
TEST(PhysicalASTCBlockTest,TestWeightDims)70 TEST(PhysicalASTCBlockTest, TestWeightDims) {
71   PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
72   auto weight_dims = blk1.WeightGridDims();
73   EXPECT_TRUE(weight_dims);
74   EXPECT_EQ(weight_dims.value()[0], 6);
75   EXPECT_EQ(weight_dims.value()[1], 5);
76 
77   // If we flip the high bit then we should have a range of 31,
78   // although then we have too many bits for the weight grid
79   // and this should error.
80   PhysicalASTCBlock blk2(0x0000000001FE000373ULL);
81   EXPECT_FALSE(blk2.WeightGridDims());
82   EXPECT_EQ(blk2.IsIllegalEncoding().value(),
83             "Too many bits required for weight grid");
84 
85   // Dual plane block with 3x5 weight dims
86   PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
87   weight_dims = blk3.WeightGridDims();
88   ASSERT_TRUE(weight_dims);
89   EXPECT_EQ(weight_dims->at(0), 3);
90   EXPECT_EQ(weight_dims->at(1), 5);
91 
92   // Error blocks shouldn't have any weight dims
93   EXPECT_FALSE(kErrorBlock.WeightGridDims());
94 
95   PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
96   weight_dims = non_shared_cem.WeightGridDims();
97   ASSERT_TRUE(weight_dims);
98   EXPECT_EQ(weight_dims->at(0), 8);
99   EXPECT_EQ(weight_dims->at(1), 8);
100 }
101 
102 // Test to see whether or not the presence of a dual-plane bit
103 // is decoded properly. Error encodings are tested to *not* return
104 // that they have dual planes.
TEST(PhysicalASTCBlockTest,TestDualPlane)105 TEST(PhysicalASTCBlockTest, TestDualPlane) {
106   PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
107   EXPECT_FALSE(blk1.IsDualPlane());
108   EXPECT_FALSE(kErrorBlock.IsDualPlane());
109 
110   // If we flip the dual plane bit, we will have too many bits
111   // for the weight grid and this should error
112   PhysicalASTCBlock blk2(0x0000000001FE000573ULL);
113   EXPECT_FALSE(blk2.IsDualPlane());
114   EXPECT_FALSE(blk2.WeightGridDims());
115   EXPECT_EQ(blk2.IsIllegalEncoding().value(),
116             "Too many bits required for weight grid");
117 
118   // A dual plane with 3x5 weight grid should be supported
119   PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
120   EXPECT_TRUE(blk3.IsDualPlane());
121 
122   // If we use the wrong block mode, then a valid block
123   // shouldn't have any dual plane
124   PhysicalASTCBlock blk4(0x0000000001FE000108ULL);
125   EXPECT_FALSE(blk4.IsDualPlane());
126   EXPECT_FALSE(blk4.IsIllegalEncoding());
127 }
128 
129 // Make sure that we properly calculate the number of bits used to encode
130 // the weight grid. Given error encodings or void extent blocks, this number
131 // should be zero
TEST(PhysicalASTCBlockTest,TestNumWeightBits)132 TEST(PhysicalASTCBlockTest, TestNumWeightBits) {
133   // 6x5 single-plane weight grid with 3-bit weights
134   // should have 90 bits for the weights.
135   PhysicalASTCBlock blk1(0x0000000001FE000173ULL);
136   EXPECT_EQ(90, blk1.NumWeightBits());
137 
138   // Error block has no weight bits
139   EXPECT_FALSE(kErrorBlock.NumWeightBits());
140 
141   // Void extent blocks have no weight bits
142   EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumWeightBits());
143 
144   // If we flip the dual plane bit, we will have too many bits
145   // for the weight grid and this should error and return no bits
146   PhysicalASTCBlock blk2(0x0000000001FE000573ULL);
147   EXPECT_FALSE(blk2.NumWeightBits());
148 
149   // 3x5 dual-plane weight grid with 3-bit weights
150   // should have 90 bits for the weights.
151   PhysicalASTCBlock blk3(0x0000000001FE0005FFULL);
152   EXPECT_EQ(90, blk3.NumWeightBits());
153 }
154 
155 // Test to make sure that our weight bits start where we expect them to.
156 // In other words, make sure that the calculation based on the block mode for
157 // where the weight bits start is accurate.
TEST(PhysicalASTCBlockTest,TestStartWeightBit)158 TEST(PhysicalASTCBlockTest, TestStartWeightBit) {
159   EXPECT_EQ(PhysicalASTCBlock(0x4000000000800D44ULL).WeightStartBit(), 64);
160 
161   // Error blocks have no weight start bit
162   EXPECT_FALSE(kErrorBlock.WeightStartBit());
163 
164   // Void extent blocks have no weight start bit
165   EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).WeightStartBit());
166 }
167 
168 // Test to make sure that we catch various different reasons for error encoding
169 // of ASTC blocks, but also that certain encodings aren't errors.
TEST(PhysicalASTCBlockTest,TestErrorBlocks)170 TEST(PhysicalASTCBlockTest, TestErrorBlocks) {
171   // Various valid block modes
172   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).IsIllegalEncoding());
173   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE0005FFULL).IsIllegalEncoding());
174   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000108ULL).IsIllegalEncoding());
175 
176   // This is an error because it uses an invalid block mode
177   EXPECT_EQ(kErrorBlock.IsIllegalEncoding().value(), "Reserved block mode");
178 
179   // This is an error because we have too many weight bits
180   PhysicalASTCBlock err_blk(0x0000000001FE000573ULL);
181   EXPECT_EQ(err_blk.IsIllegalEncoding().value(),
182             "Too many bits required for weight grid");
183 
184   // This is an error because we have too many weights
185   PhysicalASTCBlock err_blk2 = PhysicalASTCBlock(0x0000000001FE0005A8ULL);
186   EXPECT_EQ(err_blk2.IsIllegalEncoding().value(), "Too many weights specified");
187 
188   PhysicalASTCBlock err_blk3 = PhysicalASTCBlock(0x0000000001FE000588ULL);
189   EXPECT_EQ(err_blk3.IsIllegalEncoding().value(), "Too many weights specified");
190 
191   // This is an error because we have too few weights
192   PhysicalASTCBlock err_blk4 = PhysicalASTCBlock(0x0000000001FE00002ULL);
193   EXPECT_EQ(err_blk4.IsIllegalEncoding().value(),
194             "Too few bits required for weight grid");
195 
196   // Four partitions, dual plane -- should be error
197   // 2x2 weight grid, 3 bits per weight
198   PhysicalASTCBlock dual_plane_four_parts(0x000000000000001D1FULL);
199   EXPECT_FALSE(dual_plane_four_parts.NumPartitions());
200   EXPECT_EQ(dual_plane_four_parts.IsIllegalEncoding().value(),
201             "Both four partitions and dual plane specified");
202 }
203 
204 // Test to make sure that we properly identify and can manipulate void-extent
205 // blocks. These are ASTC blocks that only define a single color for the entire
206 // block.
TEST(PhysicalASTCBlockTest,TestVoidExtentBlocks)207 TEST(PhysicalASTCBlockTest, TestVoidExtentBlocks) {
208   // Various valid block modes that aren't void extent blocks
209   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).IsVoidExtent());
210   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE0005FFULL).IsVoidExtent());
211   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000108ULL).IsVoidExtent());
212 
213   // Error block is not a void extent block
214   EXPECT_FALSE(kErrorBlock.IsVoidExtent());
215 
216   // Void extent block is void extent block...
217   UInt128 void_extent_encoding(0, 0xFFF8003FFE000DFCULL);
218   EXPECT_FALSE(PhysicalASTCBlock(void_extent_encoding).IsIllegalEncoding());
219   EXPECT_TRUE(PhysicalASTCBlock(void_extent_encoding).IsVoidExtent());
220 
221   // If we modify the high 64 bits it shouldn't change anything
222   void_extent_encoding |= UInt128(0xdeadbeefdeadbeef, 0);
223   EXPECT_FALSE(PhysicalASTCBlock(void_extent_encoding).IsIllegalEncoding());
224   EXPECT_TRUE(PhysicalASTCBlock(void_extent_encoding).IsVoidExtent());
225 }
226 
TEST(PhysicalASTCBlockTest,TestVoidExtentCoordinates)227 TEST(PhysicalASTCBlockTest, TestVoidExtentCoordinates) {
228   // The void extent block should have texture coordinates from 0-8191
229   auto coords = PhysicalASTCBlock(0xFFF8003FFE000DFCULL).VoidExtentCoords();
230   EXPECT_EQ(coords->at(0), 0);
231   EXPECT_EQ(coords->at(1), 8191);
232   EXPECT_EQ(coords->at(2), 0);
233   EXPECT_EQ(coords->at(3), 8191);
234 
235   // If we set the coords to all 1's then it's still a void extent
236   // block, but there aren't any void extent coords.
237   EXPECT_FALSE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).IsIllegalEncoding());
238   EXPECT_TRUE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).IsVoidExtent());
239   EXPECT_FALSE(PhysicalASTCBlock(0xFFFFFFFFFFFFFDFCULL).VoidExtentCoords());
240 
241   // If we set the void extent coords to something where the coords are
242   // >= each other, then the encoding is illegal.
243   EXPECT_TRUE(PhysicalASTCBlock(0x0008004002001DFCULL).IsIllegalEncoding());
244   EXPECT_TRUE(PhysicalASTCBlock(0x0007FFC001FFFDFCULL).IsIllegalEncoding());
245 }
246 
247 // Test to see if we can properly identify the number of partitions in a block
248 // In particular -- we need to make sure we properly identify single and
249 // multi-partition blocks, but also that void extent and error blocks don't
250 // return valid numbers of partitions
TEST(PhysicalASTCBlockTest,TestNumPartitions)251 TEST(PhysicalASTCBlockTest, TestNumPartitions) {
252   // Various valid block modes, but all single partition
253   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumPartitions(), 1);
254   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE0005FFULL).NumPartitions(), 1);
255   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000108ULL).NumPartitions(), 1);
256 
257   // Two to four partitions don't have enough bits for color.
258   EXPECT_FALSE(PhysicalASTCBlock(0x000000000000000973ULL).NumPartitions());
259   EXPECT_FALSE(PhysicalASTCBlock(0x000000000000001173ULL).NumPartitions());
260   EXPECT_FALSE(PhysicalASTCBlock(0x000000000000001973ULL).NumPartitions());
261 
262   // Test against having more than one partition
263   PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
264   EXPECT_EQ(non_shared_cem.NumPartitions(), 2);
265 }
266 
267 // Test the color endpoint modes specified for how the endpoints are encoded.
268 // In particular, test that shared color endpoint modes work for multi-partition
269 // blocks and that non-shared color endpoint modes also work.
TEST(PhysicalASTCBlockTest,TestColorEndpointModes)270 TEST(PhysicalASTCBlockTest, TestColorEndpointModes) {
271   // Four partitions -- one shared CEM
272   const auto blk1 = PhysicalASTCBlock(0x000000000000001961ULL);
273   for (int i = 0; i < 4; ++i) {
274     EXPECT_EQ(blk1.GetEndpointMode(i), ColorEndpointMode::kLDRLumaDirect);
275   }
276 
277   // Void extent blocks have no endpoint modes
278   EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).GetEndpointMode(0));
279 
280   // Test out of range partitions
281   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(1));
282   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(-1));
283   EXPECT_FALSE(PhysicalASTCBlock(0x0000000001FE000173ULL).GetEndpointMode(100));
284 
285   // Error blocks have no endpoint modes
286   EXPECT_FALSE(kErrorBlock.GetEndpointMode(0));
287 
288   // Test non-shared CEMs
289   PhysicalASTCBlock non_shared_cem(0x4000000000800D44ULL);
290   EXPECT_EQ(non_shared_cem.GetEndpointMode(0),
291             ColorEndpointMode::kLDRLumaDirect);
292   EXPECT_EQ(non_shared_cem.GetEndpointMode(1),
293             ColorEndpointMode::kLDRLumaBaseOffset);
294 }
295 
296 // Make sure that if we have more than one partition then we have proper
297 // partition IDs (these determine which pixels correspond to which partition)
TEST(PhysicalASTCBlockTest,TestPartitionID)298 TEST(PhysicalASTCBlockTest, TestPartitionID) {
299   // Valid partitions
300   EXPECT_EQ(PhysicalASTCBlock(0x4000000000FFED44ULL).PartitionID(), 0x3FF);
301   EXPECT_EQ(PhysicalASTCBlock(0x4000000000AAAD44ULL).PartitionID(), 0x155);
302 
303   // Error blocks have no partition IDs
304   EXPECT_FALSE(kErrorBlock.PartitionID());
305 
306   // Void extent blocks have no endpoint modes
307   EXPECT_FALSE(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).PartitionID());
308 }
309 
310 // Make sure that we're properly attributing the number of bits associated with
311 // the encoded color values.
TEST(PhysicalASTCBlockTest,TestNumColorBits)312 TEST(PhysicalASTCBlockTest, TestNumColorBits) {
313   // If we're using a direct luma channel, then the number of color bits is 16
314   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumColorValues(), 2);
315   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).NumColorBits(), 16);
316 
317   // Error blocks have nothing
318   EXPECT_FALSE(kErrorBlock.NumColorValues());
319   EXPECT_FALSE(kErrorBlock.NumColorBits());
320 
321   // Void extent blocks have four color values and 64 bits of color
322   EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumColorValues(), 4);
323   EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).NumColorBits(), 64);
324 }
325 
326 // Make sure that we're properly decoding the range of values that each of the
327 // encoded color values can take
TEST(PhysicalASTCBlockTest,TestColorValuesRange)328 TEST(PhysicalASTCBlockTest, TestColorValuesRange) {
329   // If we're using a direct luma channel, then we use two color values up to
330   // a full byte each.
331   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).ColorValuesRange(), 255);
332 
333   // Error blocks have nothing
334   EXPECT_FALSE(kErrorBlock.ColorValuesRange());
335 
336   // Void extent blocks have four color values and 64 bits of color, so the
337   // color range for each is sixteen bits.
338   EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).ColorValuesRange(),
339             (1 << 16) - 1);
340 }
341 
342 // Test that we know where the color data starts. This is different mostly
343 // depending on whether or not the block is single-partition or void extent.
TEST(PhysicalASTCBlockTest,TestColorStartBits)344 TEST(PhysicalASTCBlockTest, TestColorStartBits) {
345   // Void extent blocks start at bit 64
346   EXPECT_EQ(PhysicalASTCBlock(0xFFF8003FFE000DFCULL).ColorStartBit(), 64);
347 
348   // Error blocks don't start anywhere
349   EXPECT_FALSE(kErrorBlock.ColorStartBit());
350 
351   // Single partition blocks start at bit 17
352   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000173ULL).ColorStartBit(), 17);
353   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE0005FFULL).ColorStartBit(), 17);
354   EXPECT_EQ(PhysicalASTCBlock(0x0000000001FE000108ULL).ColorStartBit(), 17);
355 
356   // Multi-partition blocks start at bit 29
357   EXPECT_EQ(PhysicalASTCBlock(0x4000000000FFED44ULL).ColorStartBit(), 29);
358   EXPECT_EQ(PhysicalASTCBlock(0x4000000000AAAD44ULL).ColorStartBit(), 29);
359 }
360 
361 }  // namespace
362