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 // TODO(prashant.n): Replace IsSameType with std::is_same once C++11 is used |
| 56 // on all platforms. |
| 57 template <typename T, typename U> |
| 58 struct IsSameType { |
| 59 static const bool value = false; |
| 60 }; |
| 61 |
| 62 template <typename T> |
| 63 struct IsSameType<T, T> { |
| 64 static const bool value = true; |
| 65 }; |
| 66 |
| 67 template <typename T> |
| 68 static inline void VerifyType(); |
| 69 |
| 70 template <typename T> |
| 71 static bool VerifyRoundUp(T value, T round_up); |
| 72 |
| 73 template <typename T> |
| 74 static bool VerifyFitsInBytesInternal(int width, |
| 75 int height, |
| 76 ResourceFormat format, |
| 77 bool verify_size, |
| 78 bool aligned); |
| 79 |
| 80 template <typename T> |
| 81 static T BytesInternal(int width, |
| 82 int height, |
| 83 ResourceFormat format, |
| 84 bool verify_size, |
| 85 bool aligned); |
| 86 |
| 87 DISALLOW_COPY_AND_ASSIGN(ResourceUtil); |
| 88 }; |
| 89 |
| 90 template <typename T> |
| 91 bool ResourceUtil::VerifyWidthInBytes(int width, ResourceFormat format) { |
| 92 VerifyType<T>(); |
| 93 return VerifyFitsInBytesInternal<T>(width, 0, format, false, false); |
| 94 } |
| 95 |
| 96 template <typename T> |
| 97 bool ResourceUtil::VerifySizeInBytes(const gfx::Size& size, |
| 98 ResourceFormat format) { |
| 99 VerifyType<T>(); |
| 100 return VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, |
| 101 false); |
| 102 } |
| 103 |
| 104 template <typename T> |
| 105 T ResourceUtil::CheckedWidthInBytes(int width, ResourceFormat format) { |
| 106 VerifyType<T>(); |
| 107 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false)); |
| 108 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); |
| 109 checked_value *= width; |
| 110 // TODO(prashant.n): Move the value roundup overflow to MathUtil class. |
| 111 // http://crbug.com/515566 |
| 112 CHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); |
| 113 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); |
| 114 checked_value /= 8; |
| 115 return checked_value.ValueOrDie(); |
| 116 } |
| 117 |
| 118 template <typename T> |
| 119 T ResourceUtil::CheckedSizeInBytes(const gfx::Size& size, |
| 120 ResourceFormat format) { |
| 121 VerifyType<T>(); |
| 122 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, |
| 123 false)); |
| 124 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); |
| 125 checked_value *= size.width(); |
| 126 CHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); |
| 127 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); |
| 128 checked_value /= 8; |
| 129 checked_value *= size.height(); |
| 130 return checked_value.ValueOrDie(); |
| 131 } |
| 132 |
| 133 template <typename T> |
| 134 T ResourceUtil::UncheckedWidthInBytes(int width, ResourceFormat format) { |
| 135 VerifyType<T>(); |
| 136 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, false)); |
| 137 return BytesInternal<T>(width, 0, format, false, false); |
| 138 } |
| 139 |
| 140 template <typename T> |
| 141 T ResourceUtil::UncheckedSizeInBytes(const gfx::Size& size, |
| 142 ResourceFormat format) { |
| 143 VerifyType<T>(); |
| 144 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, |
| 145 false)); |
| 146 return BytesInternal<T>(size.width(), size.height(), format, true, false); |
| 147 } |
| 148 |
| 149 template <typename T> |
| 150 T ResourceUtil::UncheckedWidthInBytesAligned(int width, ResourceFormat format) { |
| 151 VerifyType<T>(); |
| 152 DCHECK(VerifyFitsInBytesInternal<T>(width, 0, format, false, true)); |
| 153 return BytesInternal<T>(width, 0, format, false, true); |
| 154 } |
| 155 |
| 156 template <typename T> |
| 157 T ResourceUtil::UncheckedSizeInBytesAligned(const gfx::Size& size, |
| 158 ResourceFormat format) { |
| 159 VerifyType<T>(); |
| 160 DCHECK(VerifyFitsInBytesInternal<T>(size.width(), size.height(), format, true, |
| 161 true)); |
| 162 return BytesInternal<T>(size.width(), size.height(), format, true, true); |
| 163 } |
| 164 |
| 165 template <typename T> |
| 166 void ResourceUtil::VerifyType() { |
| 167 static_assert( |
| 168 std::numeric_limits<T>::is_integer && !IsSameType<T, bool>::value, |
| 169 "T must be non-bool integer type. Preferred type is size_t."); |
| 170 } |
| 171 |
| 172 template <typename T> |
| 173 bool ResourceUtil::VerifyRoundUp(T value, T round_up) { |
| 174 if (round_up == 0) |
| 175 return false; |
| 176 if (value == round_up) |
| 177 return true; |
| 178 if ((std::numeric_limits<T>::max() - (value - (value % round_up))) >= |
| 179 round_up) |
| 180 return true; |
| 181 return false; |
| 182 } |
| 183 |
| 184 template <typename T> |
| 185 bool ResourceUtil::VerifyFitsInBytesInternal(int width, |
| 186 int height, |
| 187 ResourceFormat format, |
| 188 bool verify_size, |
| 189 bool aligned) { |
| 190 base::CheckedNumeric<T> checked_value = BitsPerPixel(format); |
| 191 checked_value *= width; |
| 192 if (!checked_value.IsValid()) |
| 193 return false; |
| 194 |
| 195 // Roundup bits to byte (8 bits) boundary. If width is 3 and BitsPerPixel is |
| 196 // 4, then it should return 16, so that row pixels do not get truncated. |
| 197 DCHECK(VerifyRoundUp(checked_value.ValueOrDie(), static_cast<T>(8))); |
| 198 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 8); |
| 199 |
| 200 // If aligned is true, bytes are aligned on 4-bytes boundaries for upload |
| 201 // performance, assuming that GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT have |
| 202 // not changed from default. |
| 203 if (aligned) { |
| 204 checked_value /= 8; |
| 205 if (!checked_value.IsValid()) |
| 206 return false; |
| 207 checked_value = MathUtil::RoundUp<T>(checked_value.ValueOrDie(), 4); |
| 208 checked_value *= 8; |
| 209 } |
| 210 |
| 211 if (verify_size) |
| 212 checked_value *= height; |
| 213 if (!checked_value.IsValid()) |
| 214 return false; |
| 215 T value = checked_value.ValueOrDie(); |
| 216 if ((value % 8) != 0) |
| 217 return false; |
| 218 return true; |
| 219 } |
| 220 |
| 221 template <typename T> |
| 222 T ResourceUtil::BytesInternal(int width, |
| 223 int height, |
| 224 ResourceFormat format, |
| 225 bool verify_size, |
| 226 bool aligned) { |
| 227 T bytes = BitsPerPixel(format); |
| 228 bytes *= width; |
| 229 DCHECK(VerifyRoundUp(bytes, static_cast<T>(8))); |
| 230 bytes = MathUtil::RoundUp<T>(bytes, 8); |
| 231 bytes /= 8; |
| 232 if (aligned) |
| 233 bytes = MathUtil::RoundUp<T>(bytes, 4); |
| 234 if (verify_size) |
| 235 bytes *= height; |
| 236 |
| 237 return bytes; |
| 238 } |
| 239 |
| 240 } // namespace cc |
| 241 |
| 242 #endif // CC_RESOURCES_RESOURCE_UTIL_H_ |
OLD | NEW |