1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 
7 #include "components/viz/common/resources/resource_sizes.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace viz {
11 namespace {
12 
13 struct TestFormat {
14   ResourceFormat format;
15   size_t expected_bytes;
16   size_t expected_bytes_aligned;
17 };
18 
19 // Modify this constant as per TestFormat variables defined in following tests.
20 const int kTestFormats = 4;
21 
22 class ResourceUtilTest : public testing::Test {
23  public:
TestVerifyWidthInBytes(int width,const TestFormat * test_formats)24   void TestVerifyWidthInBytes(int width, const TestFormat* test_formats) {
25     for (int i = 0; i < kTestFormats; ++i) {
26       EXPECT_TRUE(ResourceSizes::VerifyWidthInBytes<size_t>(
27           width, test_formats[i].format));
28     }
29   }
30 
TestCheckedWidthInBytes(int width,const TestFormat * test_formats)31   void TestCheckedWidthInBytes(int width, const TestFormat* test_formats) {
32     for (int i = 0; i < kTestFormats; ++i) {
33       size_t bytes = ResourceSizes::CheckedWidthInBytes<size_t>(
34           width, test_formats[i].format);
35       EXPECT_EQ(bytes, test_formats[i].expected_bytes);
36     }
37   }
38 
TestUncheckedWidthInBytes(int width,const TestFormat * test_formats)39   void TestUncheckedWidthInBytes(int width, const TestFormat* test_formats) {
40     for (int i = 0; i < kTestFormats; ++i) {
41       size_t bytes = ResourceSizes::UncheckedWidthInBytes<size_t>(
42           width, test_formats[i].format);
43       EXPECT_EQ(bytes, test_formats[i].expected_bytes);
44     }
45   }
46 
TestUncheckedWidthInBytesAligned(int width,const TestFormat * test_formats)47   void TestUncheckedWidthInBytesAligned(int width,
48                                         const TestFormat* test_formats) {
49     for (int i = 0; i < kTestFormats; ++i) {
50       size_t bytes = ResourceSizes::UncheckedWidthInBytesAligned<size_t>(
51           width, test_formats[i].format);
52       EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned);
53     }
54   }
55 
TestVerifySizeInBytes(const gfx::Size & size,const TestFormat * test_formats)56   void TestVerifySizeInBytes(const gfx::Size& size,
57                              const TestFormat* test_formats) {
58     for (int i = 0; i < kTestFormats; ++i) {
59       EXPECT_TRUE(ResourceSizes::VerifySizeInBytes<size_t>(
60           size, test_formats[i].format));
61     }
62   }
63 
TestCheckedSizeInBytes(const gfx::Size & size,const TestFormat * test_formats)64   void TestCheckedSizeInBytes(const gfx::Size& size,
65                               const TestFormat* test_formats) {
66     for (int i = 0; i < kTestFormats; ++i) {
67       size_t bytes = ResourceSizes::CheckedSizeInBytes<size_t>(
68           size, test_formats[i].format);
69       EXPECT_EQ(bytes, test_formats[i].expected_bytes);
70     }
71   }
72 
TestUncheckedSizeInBytes(const gfx::Size & size,const TestFormat * test_formats)73   void TestUncheckedSizeInBytes(const gfx::Size& size,
74                                 const TestFormat* test_formats) {
75     for (int i = 0; i < kTestFormats; ++i) {
76       size_t bytes = ResourceSizes::UncheckedSizeInBytes<size_t>(
77           size, test_formats[i].format);
78       EXPECT_EQ(bytes, test_formats[i].expected_bytes);
79     }
80   }
81 
TestUncheckedSizeInBytesAligned(const gfx::Size & size,const TestFormat * test_formats)82   void TestUncheckedSizeInBytesAligned(const gfx::Size& size,
83                                        const TestFormat* test_formats) {
84     for (int i = 0; i < kTestFormats; ++i) {
85       size_t bytes = ResourceSizes::UncheckedSizeInBytesAligned<size_t>(
86           size, test_formats[i].format);
87       EXPECT_EQ(bytes, test_formats[i].expected_bytes_aligned);
88     }
89   }
90 };
91 
TEST_F(ResourceUtilTest,WidthInBytes)92 TEST_F(ResourceUtilTest, WidthInBytes) {
93   // Check bytes for even width.
94   int width = 10;
95   TestFormat test_formats[] = {
96       {RGBA_8888, 40, 40},  // for 32 bits
97       {RGBA_4444, 20, 20},  // for 16 bits
98       {ALPHA_8, 10, 12},    // for 8 bits
99       {ETC1, 5, 8}          // for 4 bits
100   };
101 
102   TestVerifyWidthInBytes(width, test_formats);
103   TestCheckedWidthInBytes(width, test_formats);
104   TestUncheckedWidthInBytes(width, test_formats);
105   TestUncheckedWidthInBytesAligned(width, test_formats);
106 
107   // Check bytes for odd width.
108   int width_odd = 11;
109   TestFormat test_formats_odd[] = {
110       {RGBA_8888, 44, 44},  // for 32 bits
111       {RGBA_4444, 22, 24},  // for 16 bits
112       {ALPHA_8, 11, 12},    // for 8 bits
113       {ETC1, 6, 8}          // for 4 bits
114   };
115 
116   TestVerifyWidthInBytes(width_odd, test_formats_odd);
117   TestCheckedWidthInBytes(width_odd, test_formats_odd);
118   TestUncheckedWidthInBytes(width_odd, test_formats_odd);
119   TestUncheckedWidthInBytesAligned(width_odd, test_formats_odd);
120 }
121 
TEST_F(ResourceUtilTest,SizeInBytes)122 TEST_F(ResourceUtilTest, SizeInBytes) {
123   // Check bytes for even size.
124   gfx::Size size(10, 10);
125   TestFormat test_formats[] = {
126       {RGBA_8888, 400, 400},  // for 32 bits
127       {RGBA_4444, 200, 200},  // for 16 bits
128       {ALPHA_8, 100, 120},    // for 8 bits
129       {ETC1, 50, 80}          // for 4 bits
130   };
131 
132   TestVerifySizeInBytes(size, test_formats);
133   TestCheckedSizeInBytes(size, test_formats);
134   TestUncheckedSizeInBytes(size, test_formats);
135   TestUncheckedSizeInBytesAligned(size, test_formats);
136 
137   // Check bytes for odd size.
138   gfx::Size size_odd(11, 11);
139   TestFormat test_formats_odd[] = {
140       {RGBA_8888, 484, 484},  // for 32 bits
141       {RGBA_4444, 242, 264},  // for 16 bits
142       {ALPHA_8, 121, 132},    // for 8 bits
143       {ETC1, 66, 88}          // for 4 bits
144   };
145 
146   TestVerifySizeInBytes(size_odd, test_formats_odd);
147   TestCheckedSizeInBytes(size_odd, test_formats_odd);
148   TestUncheckedSizeInBytes(size_odd, test_formats_odd);
149   TestUncheckedSizeInBytesAligned(size_odd, test_formats_odd);
150 }
151 
TEST_F(ResourceUtilTest,WidthInBytesOverflow)152 TEST_F(ResourceUtilTest, WidthInBytesOverflow) {
153   int width = 10;
154   // 10 * 16 = 160 bits, overflows in char, but fits in unsigned char.
155   EXPECT_FALSE(
156       ResourceSizes::VerifyWidthInBytes<signed char>(width, RGBA_4444));
157   EXPECT_TRUE(
158       ResourceSizes::VerifyWidthInBytes<unsigned char>(width, RGBA_4444));
159 }
160 
TEST_F(ResourceUtilTest,SizeInBytesOverflow)161 TEST_F(ResourceUtilTest, SizeInBytesOverflow) {
162   gfx::Size size(10, 10);
163   // 10 * 16 * 10 = 1600 bits, overflows in char, but fits in int.
164   EXPECT_FALSE(ResourceSizes::VerifySizeInBytes<signed char>(size, RGBA_4444));
165   EXPECT_TRUE(ResourceSizes::VerifySizeInBytes<int>(size, RGBA_4444));
166 }
167 
TEST_F(ResourceUtilTest,WidthOverflowDoesNotCrash)168 TEST_F(ResourceUtilTest, WidthOverflowDoesNotCrash) {
169   gfx::Size size(0x20000000, 1);
170   // 0x20000000 * 4 = 0x80000000 which overflows int. Should return false, not
171   // crash.
172   int bytes;
173   EXPECT_FALSE(
174       ResourceSizes::MaybeWidthInBytes<int>(size.width(), BGRA_8888, &bytes));
175   EXPECT_FALSE(ResourceSizes::MaybeSizeInBytes<int>(size, BGRA_8888, &bytes));
176 }
177 
178 // Checks that we do not incorrectly indicate that a size has overflowed when
179 // only the size in bits overflows, but not the size in bytes.
TEST_F(ResourceUtilTest,SizeInBitsOverflowBytesOk)180 TEST_F(ResourceUtilTest, SizeInBitsOverflowBytesOk) {
181   gfx::Size size(10000, 10000);
182   // 8192 * 8192 * 32 = 0x80000000, overflows int.
183   // Bytes are /8 and do not overflow.
184   EXPECT_TRUE(ResourceSizes::VerifySizeInBytes<int>(size, BGRA_8888));
185 }
186 
187 // Checks that we correctly identify overflow in cases caused by rounding.
TEST_F(ResourceUtilTest,RoundingOverflows)188 TEST_F(ResourceUtilTest, RoundingOverflows) {
189   gfx::Size size(0x1FFFFFFF, 1);
190   // 0x1FFFFFFF * 4 = 0x7FFFFFFC. Will overflow when rounded up.
191   EXPECT_FALSE(ResourceSizes::VerifySizeInBytes<int>(size, ETC1));
192 }
193 
194 }  // namespace
195 }  // namespace viz
196