Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 #ifndef CC_RESOURCES_RESOURCE_UTIL_H_ | |
| 6 #define CC_RESOURCES_RESOURCE_UTIL_H_ | |
| 7 | |
| 8 #include <limits> | |
| 9 | |
| 10 #include "base/numerics/safe_math.h" | |
| 11 #include "cc/base/cc_export.h" | |
| 12 #include "cc/base/math_util.h" | |
| 13 #include "cc/resources/resource_format.h" | |
| 14 #include "ui/gfx/geometry/size.h" | |
| 15 | |
| 16 namespace cc { | |
| 17 | |
| 18 class CC_EXPORT ResourceUtil { | |
| 19 public: | |
| 20 // Returns true if the width is valid and fits in bytes, false otherwise. | |
| 21 template <typename T> | |
| 22 static bool VerifyWidthInBytes(int width, ResourceFormat format); | |
| 23 // Returns true if the size is valid and fits in bytes, false otherwise. | |
| 24 template <typename T> | |
| 25 static bool VerifySizeInBytes(const gfx::Size& size, ResourceFormat format); | |
| 26 | |
| 27 // Dies with a CRASH() if the width can not be represented as a positive | |
| 28 // number of bytes. | |
| 29 template <typename T> | |
| 30 static T CheckedWidthInBytes(int width, ResourceFormat format); | |
| 31 // Dies with a CRASH() if the size can not be represented as a positive | |
| 32 // number of bytes. | |
| 33 template <typename T> | |
| 34 static T CheckedSizeInBytes(const gfx::Size& size, ResourceFormat format); | |
| 35 | |
| 36 // Returns the width in bytes but may overflow or return 0. Only do this for | |
| 37 // computing widths for sizes that have already been checked. | |
| 38 template <typename T> | |
| 39 static T UncheckedWidthInBytes(int width, ResourceFormat format); | |
| 40 // Returns the size in bytes but may overflow or return 0. Only do this for | |
| 41 // sizes that have already been checked. | |
| 42 template <typename T> | |
| 43 static T UncheckedSizeInBytes(const gfx::Size& size, ResourceFormat format); | |
| 44 // Returns the width in bytes aligned but may overflow or return 0. Only do | |
| 45 // this for computing widths for sizes that have already been checked. | |
| 46 template <typename T> | |
| 47 static T UncheckedWidthInBytesAligned(int width, ResourceFormat format); | |
| 48 // Returns the size in bytes aligned but may overflow or return 0. Only do | |
| 49 // this for sizes that have already been checked. | |
| 50 template <typename T> | |
| 51 static T UncheckedSizeInBytesAligned(const gfx::Size& size, | |
| 52 ResourceFormat format); | |
| 53 | |
| 54 private: | |
| 55 template <typename T> | |
| 56 static inline void VerifyType(); | |
| 57 | |
| 58 template <typename T> | |
| 59 static bool VerifyRoundUp(T value, T round_up); | |
| 60 | |
| 61 template <typename T> | |
| 62 static bool VerifyFitsInBytesInternal(int width, | |
| 63 int height, | |
| 64 ResourceFormat format, | |
| 65 bool verify_size, | |
| 66 bool aligned); | |
| 67 | |
| 68 template <typename T> | |
| 69 static T BytesInternal(int width, | |
| 70 int height, | |
| 71 ResourceFormat format, | |
| 72 bool verify_size, | |
| 73 bool aligned); | |
| 74 | |
| 75 DISALLOW_COPY_AND_ASSIGN(ResourceUtil); | |
| 76 }; | |
| 77 | |
| 78 template <typename T> | |
| 79 bool ResourceUtil::VerifyWidthInBytes(int width, ResourceFormat format) { | |
| 80 VerifyType<T>(); | |
| 81 return VerifyFitsInBytesInternal<T>(width, 0, format, false, false); | |
| 82 } | |
| 83 | |
| 84 template <typename T> | |
| 85 bool ResourceUtil::VerifySizeInBytes(const gfx::Size& size, | |
| 86 ResourceFormat format) { | |
| 87 VerifyType<T>(); | |
| 88 return VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, | |
| 89 false); | |
| 90 } | |
| 91 | |
| 92 template <typename T> | |
| 93 T ResourceUtil::CheckedWidthInBytes(int width, ResourceFormat format) { | |
| 94 VerifyType<T>(); | |
| 95 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false)); | |
| 96 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); | |
| 97 checked_value *= width; | |
| 98 // TODO(prashant.n): Move the value roundup overflow to MathUtil class. | |
| 99 // http://crbug.com/515566 | |
| 100 CHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); | |
| 101 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); | |
| 102 checked_value /= 8; | |
| 103 return checked_value.ValueOrDie(); | |
| 104 } | |
| 105 | |
| 106 template <typename T> | |
| 107 T ResourceUtil::CheckedSizeInBytes(const gfx::Size& size, | |
| 108 ResourceFormat format) { | |
| 109 VerifyType<T>(); | |
| 110 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, | |
| 111 false)); | |
| 112 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); | |
| 113 checked_value *= size.width(); | |
| 114 CHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); | |
| 115 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); | |
| 116 checked_value /= 8; | |
| 117 checked_value *= size.height(); | |
| 118 return checked_value.ValueOrDie(); | |
| 119 } | |
| 120 | |
| 121 template <typename T> | |
| 122 T ResourceUtil::UncheckedWidthInBytes(int width, ResourceFormat format) { | |
| 123 VerifyType<T>(); | |
| 124 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false)); | |
| 125 return BytesInternal<T>(width, 0, format, false, false); | |
| 126 } | |
| 127 | |
| 128 template <typename T> | |
| 129 T ResourceUtil::UncheckedSizeInBytes(const gfx::Size& size, | |
| 130 ResourceFormat format) { | |
| 131 VerifyType<T>(); | |
| 132 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, | |
| 133 false)); | |
| 134 return BytesInternal<T>(size.width(), size.height(), format, true, false); | |
| 135 } | |
| 136 | |
| 137 template <typename T> | |
| 138 T ResourceUtil::UncheckedWidthInBytesAligned(int width, ResourceFormat format) { | |
| 139 VerifyType<T>(); | |
| 140 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, true)); | |
| 141 return BytesInternal<T>(width, 0, format, false, true); | |
| 142 } | |
| 143 | |
| 144 template <typename T> | |
| 145 T ResourceUtil::UncheckedSizeInBytesAligned(const gfx::Size& size, | |
| 146 ResourceFormat format) { | |
| 147 VerifyType<T>(); | |
| 148 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, | |
| 149 true)); | |
| 150 return BytesInternal<T>(size.width(), size.height(), format, true, true); | |
| 151 } | |
| 152 | |
| 153 template <typename T> | |
| 154 void ResourceUtil::VerifyType() { | |
| 155 static_assert( | |
| 156 std::numeric_limits<T>::is_integer && !std::is_same<T, bool>::value, | |
|
vmpstr
2015/07/30 20:50:58
std::is_same is a c++11 library feature, which we
| |
| 157 "T must be non-bool integer type. Preferred type is size_t."); | |
| 158 } | |
| 159 | |
| 160 template <typename T> | |
| 161 bool ResourceUtil::VerifyRoundUp(T value, T round_up) { | |
| 162 if (round_up == 0) | |
| 163 return false; | |
| 164 if (value == round_up) | |
| 165 return true; | |
| 166 if ((std::numeric_limits<T>::max() - (value - (value % round_up))) >= | |
| 167 round_up) | |
| 168 return true; | |
| 169 return false; | |
| 170 } | |
| 171 | |
| 172 template <typename T> | |
| 173 bool ResourceUtil::VerifyFitsInBytesInternal(int width, | |
| 174 int height, | |
| 175 ResourceFormat format, | |
| 176 bool verify_size, | |
| 177 bool aligned) { | |
| 178 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); | |
| 179 checked_value *= width; | |
| 180 if (!checked_value.IsValid()) | |
| 181 return false; | |
| 182 | |
| 183 // Roundup bits to byte (8 bits) boundary. If width is 3 and BitsPerPixel is | |
| 184 // 4, then it should return 16, so that row pixels do not get truncated. | |
| 185 DCHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); | |
| 186 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); | |
| 187 | |
| 188 // If aligned is true, bytes are aligned on 4-bytes boundaries for upload | |
| 189 // performance, assuming that GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT have | |
| 190 // not changed from default. | |
| 191 if (aligned) { | |
| 192 checked_value /= 8; | |
| 193 if (!checked_value.IsValid()) | |
| 194 return false; | |
| 195 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 4); | |
| 196 checked_value *= 8; | |
| 197 } | |
| 198 | |
| 199 if (verify_size) | |
| 200 checked_value *= height; | |
| 201 if (!checked_value.IsValid()) | |
| 202 return false; | |
| 203 T value = checked_value.ValueOrDie(); | |
| 204 if ((value % 8) != 0) | |
| 205 return false; | |
| 206 return true; | |
| 207 } | |
| 208 | |
| 209 template <typename T> | |
| 210 T ResourceUtil::BytesInternal(int width, | |
| 211 int height, | |
| 212 ResourceFormat format, | |
| 213 bool verify_size, | |
| 214 bool aligned) { | |
| 215 T bytes = BitsPerPixel(format); | |
| 216 bytes *= width; | |
| 217 DCHECK(VerifyRoundUp(bytes, static_cast<T>(8))); | |
| 218 bytes = MathUtil::RoundUp<T>(bytes, 8); | |
| 219 bytes /= 8; | |
| 220 if (aligned) | |
| 221 bytes = MathUtil::RoundUp<T>(bytes, 4); | |
| 222 if (verify_size) | |
| 223 bytes *= height; | |
| 224 | |
| 225 return bytes; | |
| 226 } | |
| 227 | |
| 228 } // namespace cc | |
| 229 | |
| 230 #endif // CC_RESOURCES_RESOURCE_UTIL_H_ | |
| OLD | NEW |