1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // angleutils.h: Common ANGLE utilities. 8 9 #ifndef COMMON_ANGLEUTILS_H_ 10 #define COMMON_ANGLEUTILS_H_ 11 12 #include "common/platform.h" 13 14 #if defined(ANGLE_USE_ABSEIL) 15 # include "absl/container/flat_hash_map.h" 16 # include "absl/container/flat_hash_set.h" 17 #endif // defined(ANGLE_USE_ABSEIL) 18 19 #if defined(ANGLE_WITH_LSAN) 20 # include <sanitizer/lsan_interface.h> 21 #endif // defined(ANGLE_WITH_LSAN) 22 23 #include <climits> 24 #include <cstdarg> 25 #include <cstddef> 26 #include <fstream> 27 #include <set> 28 #include <sstream> 29 #include <string> 30 #include <unordered_map> 31 #include <unordered_set> 32 #include <vector> 33 34 // A helper class to disallow copy and assignment operators 35 namespace angle 36 { 37 38 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) 39 using Microsoft::WRL::ComPtr; 40 #endif // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) 41 42 #if defined(ANGLE_USE_ABSEIL) 43 template <typename Key, typename T, class Hash = absl::container_internal::hash_default_hash<Key>> 44 using HashMap = absl::flat_hash_map<Key, T, Hash>; 45 template <typename Key, class Hash = absl::container_internal::hash_default_hash<Key>> 46 using HashSet = absl::flat_hash_set<Key, Hash>; 47 #else 48 template <typename Key, typename T, class Hash = std::hash<Key>> 49 using HashMap = std::unordered_map<Key, T, Hash>; 50 template <typename Key, class Hash = std::hash<Key>> 51 using HashSet = std::unordered_set<Key, Hash>; 52 #endif // defined(ANGLE_USE_ABSEIL) 53 54 class NonCopyable 55 { 56 protected: 57 constexpr NonCopyable() = default; 58 ~NonCopyable() = default; 59 60 private: 61 NonCopyable(const NonCopyable &) = delete; 62 void operator=(const NonCopyable &) = delete; 63 }; 64 65 extern const uintptr_t DirtyPointer; 66 67 struct SaveFileHelper 68 { 69 public: 70 // We always use ios::binary to avoid inconsistent line endings when captured on Linux vs Win. 71 SaveFileHelper(const std::string &filePathIn); 72 ~SaveFileHelper(); 73 74 template <typename T> 75 SaveFileHelper &operator<<(const T &value) 76 { 77 mOfs << value; 78 checkError(); 79 return *this; 80 } 81 82 void write(const uint8_t *data, size_t size); 83 84 private: 85 void checkError(); 86 87 std::ofstream mOfs; 88 std::string mFilePath; 89 }; 90 91 } // namespace angle 92 93 template <typename T, size_t N> ArraySize(T (&)[N])94 constexpr inline size_t ArraySize(T (&)[N]) 95 { 96 return N; 97 } 98 99 template <typename T> 100 class WrappedArray final : angle::NonCopyable 101 { 102 public: 103 template <size_t N> WrappedArray(const T (& data)[N])104 constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N) 105 {} 106 WrappedArray()107 constexpr WrappedArray() : mArray(nullptr), mSize(0) {} WrappedArray(const T * data,size_t size)108 constexpr WrappedArray(const T *data, size_t size) : mArray(data), mSize(size) {} 109 WrappedArray(WrappedArray && other)110 WrappedArray(WrappedArray &&other) : WrappedArray() 111 { 112 std::swap(mArray, other.mArray); 113 std::swap(mSize, other.mSize); 114 } 115 ~WrappedArray()116 ~WrappedArray() {} 117 get()118 constexpr const T *get() const { return mArray; } size()119 constexpr size_t size() const { return mSize; } 120 121 private: 122 const T *mArray; 123 size_t mSize; 124 }; 125 126 template <typename T, unsigned int N> SafeRelease(T (& resourceBlock)[N])127 void SafeRelease(T (&resourceBlock)[N]) 128 { 129 for (unsigned int i = 0; i < N; i++) 130 { 131 SafeRelease(resourceBlock[i]); 132 } 133 } 134 135 template <typename T> SafeRelease(T & resource)136 void SafeRelease(T &resource) 137 { 138 if (resource) 139 { 140 resource->Release(); 141 resource = nullptr; 142 } 143 } 144 145 template <typename T> SafeDelete(T * & resource)146 void SafeDelete(T *&resource) 147 { 148 delete resource; 149 resource = nullptr; 150 } 151 152 template <typename T> SafeDeleteContainer(T & resource)153 void SafeDeleteContainer(T &resource) 154 { 155 for (auto &element : resource) 156 { 157 SafeDelete(element); 158 } 159 resource.clear(); 160 } 161 162 template <typename T> SafeDeleteArray(T * & resource)163 void SafeDeleteArray(T *&resource) 164 { 165 delete[] resource; 166 resource = nullptr; 167 } 168 169 // Provide a less-than function for comparing structs 170 // Note: struct memory must be initialized to zero, because of packing gaps 171 template <typename T> StructLessThan(const T & a,const T & b)172 inline bool StructLessThan(const T &a, const T &b) 173 { 174 return (memcmp(&a, &b, sizeof(T)) < 0); 175 } 176 177 // Provide a less-than function for comparing structs 178 // Note: struct memory must be initialized to zero, because of packing gaps 179 template <typename T> StructEquals(const T & a,const T & b)180 inline bool StructEquals(const T &a, const T &b) 181 { 182 return (memcmp(&a, &b, sizeof(T)) == 0); 183 } 184 185 template <typename T> StructZero(T * obj)186 inline void StructZero(T *obj) 187 { 188 memset(obj, 0, sizeof(T)); 189 } 190 191 template <typename T> IsMaskFlagSet(T mask,T flag)192 inline bool IsMaskFlagSet(T mask, T flag) 193 { 194 // Handles multibit flags as well 195 return (mask & flag) == flag; 196 } 197 MakeStaticString(const std::string & str)198 inline const char *MakeStaticString(const std::string &str) 199 { 200 // On the heap so that no destructor runs on application exit. 201 static std::set<std::string> *strings = new std::set<std::string>; 202 std::set<std::string>::iterator it = strings->find(str); 203 if (it != strings->end()) 204 { 205 return it->c_str(); 206 } 207 208 return strings->insert(str).first->c_str(); 209 } 210 211 std::string ArrayString(unsigned int i); 212 213 // Indices are stored in vectors with the outermost index in the back. In the output of the function 214 // the indices are reversed. 215 std::string ArrayIndexString(const std::vector<unsigned int> &indices); 216 Str(int i)217 inline std::string Str(int i) 218 { 219 std::stringstream strstr; 220 strstr << i; 221 return strstr.str(); 222 } 223 224 size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char> &buffer); 225 226 template <typename T> ToString(const T & value)227 std::string ToString(const T &value) 228 { 229 std::ostringstream o; 230 o << value; 231 return o.str(); 232 } 233 IsLittleEndian()234 inline bool IsLittleEndian() 235 { 236 constexpr uint32_t kEndiannessTest = 1; 237 const bool isLittleEndian = *reinterpret_cast<const uint8_t *>(&kEndiannessTest) == 1; 238 return isLittleEndian; 239 } 240 241 // snprintf is not defined with MSVC prior to to msvc14 242 #if defined(_MSC_VER) && _MSC_VER < 1900 243 # define snprintf _snprintf 244 #endif 245 246 #define GL_A1RGB5_ANGLEX 0x6AC5 247 #define GL_BGRX8_ANGLEX 0x6ABA 248 #define GL_BGR565_ANGLEX 0x6ABB 249 #define GL_BGRA4_ANGLEX 0x6ABC 250 #define GL_BGR5_A1_ANGLEX 0x6ABD 251 #define GL_INT_64_ANGLEX 0x6ABE 252 #define GL_UINT_64_ANGLEX 0x6ABF 253 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0 254 #define GL_BGR10_A2_ANGLEX 0x6AF9 255 256 // These are fake formats used to fit typeless D3D textures that can be bound to EGL pbuffers into 257 // the format system (for extension EGL_ANGLE_d3d_texture_client_buffer): 258 #define GL_RGBA8_TYPELESS_ANGLEX 0x6AC1 259 #define GL_RGBA8_TYPELESS_SRGB_ANGLEX 0x6AC2 260 #define GL_BGRA8_TYPELESS_ANGLEX 0x6AC3 261 #define GL_BGRA8_TYPELESS_SRGB_ANGLEX 0x6AC4 262 263 #define GL_R8_SSCALED_ANGLEX 0x6AC6 264 #define GL_RG8_SSCALED_ANGLEX 0x6AC7 265 #define GL_RGB8_SSCALED_ANGLEX 0x6AC8 266 #define GL_RGBA8_SSCALED_ANGLEX 0x6AC9 267 #define GL_R8_USCALED_ANGLEX 0x6ACA 268 #define GL_RG8_USCALED_ANGLEX 0x6ACB 269 #define GL_RGB8_USCALED_ANGLEX 0x6ACC 270 #define GL_RGBA8_USCALED_ANGLEX 0x6ACD 271 272 #define GL_R16_SSCALED_ANGLEX 0x6ACE 273 #define GL_RG16_SSCALED_ANGLEX 0x6ACF 274 #define GL_RGB16_SSCALED_ANGLEX 0x6AD0 275 #define GL_RGBA16_SSCALED_ANGLEX 0x6AD1 276 #define GL_R16_USCALED_ANGLEX 0x6AD2 277 #define GL_RG16_USCALED_ANGLEX 0x6AD3 278 #define GL_RGB16_USCALED_ANGLEX 0x6AD4 279 #define GL_RGBA16_USCALED_ANGLEX 0x6AD5 280 281 #define GL_R32_SSCALED_ANGLEX 0x6AD6 282 #define GL_RG32_SSCALED_ANGLEX 0x6AD7 283 #define GL_RGB32_SSCALED_ANGLEX 0x6AD8 284 #define GL_RGBA32_SSCALED_ANGLEX 0x6AD9 285 #define GL_R32_USCALED_ANGLEX 0x6ADA 286 #define GL_RG32_USCALED_ANGLEX 0x6ADB 287 #define GL_RGB32_USCALED_ANGLEX 0x6ADC 288 #define GL_RGBA32_USCALED_ANGLEX 0x6ADD 289 290 #define GL_R32_SNORM_ANGLEX 0x6ADE 291 #define GL_RG32_SNORM_ANGLEX 0x6ADF 292 #define GL_RGB32_SNORM_ANGLEX 0x6AE0 293 #define GL_RGBA32_SNORM_ANGLEX 0x6AE1 294 #define GL_R32_UNORM_ANGLEX 0x6AE2 295 #define GL_RG32_UNORM_ANGLEX 0x6AE3 296 #define GL_RGB32_UNORM_ANGLEX 0x6AE4 297 #define GL_RGBA32_UNORM_ANGLEX 0x6AE5 298 299 #define GL_R32_FIXED_ANGLEX 0x6AE6 300 #define GL_RG32_FIXED_ANGLEX 0x6AE7 301 #define GL_RGB32_FIXED_ANGLEX 0x6AE8 302 #define GL_RGBA32_FIXED_ANGLEX 0x6AE9 303 304 #define GL_RGB10_A2_SINT_ANGLEX 0x6AEA 305 #define GL_RGB10_A2_SNORM_ANGLEX 0x6AEB 306 #define GL_RGB10_A2_SSCALED_ANGLEX 0x6AEC 307 #define GL_RGB10_A2_USCALED_ANGLEX 0x6AED 308 309 // EXT_texture_type_2_10_10_10_REV 310 #define GL_RGB10_UNORM_ANGLEX 0x6AEE 311 312 // These are fake formats for OES_vertex_type_10_10_10_2 313 #define GL_A2_RGB10_UNORM_ANGLEX 0x6AEF 314 #define GL_A2_RGB10_SNORM_ANGLEX 0x6AF0 315 #define GL_A2_RGB10_USCALED_ANGLEX 0x6AF1 316 #define GL_A2_RGB10_SSCALED_ANGLEX 0x6AF2 317 #define GL_X2_RGB10_UINT_ANGLEX 0x6AF3 318 #define GL_X2_RGB10_SINT_ANGLEX 0x6AF4 319 #define GL_X2_RGB10_USCALED_ANGLEX 0x6AF5 320 #define GL_X2_RGB10_SSCALED_ANGLEX 0x6AF6 321 #define GL_X2_RGB10_UNORM_ANGLEX 0x6AF7 322 #define GL_X2_RGB10_SNORM_ANGLEX 0x6AF8 323 324 #define ANGLE_CHECK_GL_ALLOC(context, result) \ 325 ANGLE_CHECK(context, result, "Failed to allocate host memory", GL_OUT_OF_MEMORY) 326 327 #define ANGLE_CHECK_GL_MATH(context, result) \ 328 ANGLE_CHECK(context, result, "Integer overflow.", GL_INVALID_OPERATION) 329 330 #define ANGLE_GL_UNREACHABLE(context) \ 331 UNREACHABLE(); \ 332 ANGLE_CHECK(context, false, "Unreachable Code.", GL_INVALID_OPERATION) 333 334 #if defined(ANGLE_WITH_LSAN) 335 # define ANGLE_SCOPED_DISABLE_LSAN() __lsan::ScopedDisabler lsanDisabler 336 #else 337 # define ANGLE_SCOPED_DISABLE_LSAN() 338 #endif 339 340 // The ANGLE_NO_SANITIZE_MEMORY macro suppresses MemorySanitizer checks for 341 // use-of-uninitialized-data. It can be used to decorate functions with known 342 // false positives. 343 #ifdef __clang__ 344 # define ANGLE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) 345 #else 346 # define ANGLE_NO_SANITIZE_MEMORY 347 #endif 348 349 // Similar to the above, but for thread sanitization. 350 #ifdef __clang__ 351 # define ANGLE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) 352 #else 353 # define ANGLE_NO_SANITIZE_THREAD 354 #endif 355 356 // The below inlining code lifted from V8. 357 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute)) 358 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline)) 359 # define ANGLE_HAS___FORCEINLINE 0 360 #elif defined(_MSC_VER) 361 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0 362 # define ANGLE_HAS___FORCEINLINE 1 363 #else 364 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0 365 # define ANGLE_HAS___FORCEINLINE 0 366 #endif 367 368 #if defined(NDEBUG) && ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 369 # define ANGLE_INLINE inline __attribute__((always_inline)) 370 #elif defined(NDEBUG) && ANGLE_HAS___FORCEINLINE 371 # define ANGLE_INLINE __forceinline 372 #else 373 # define ANGLE_INLINE inline 374 #endif 375 376 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute)) 377 # if __has_attribute(noinline) 378 # define ANGLE_NOINLINE __attribute__((noinline)) 379 # else 380 # define ANGLE_NOINLINE 381 # endif 382 #elif defined(_MSC_VER) 383 # define ANGLE_NOINLINE __declspec(noinline) 384 #else 385 # define ANGLE_NOINLINE 386 #endif 387 388 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute)) 389 # if __has_attribute(format) 390 # define ANGLE_FORMAT_PRINTF(fmt, args) __attribute__((format(__printf__, fmt, args))) 391 # else 392 # define ANGLE_FORMAT_PRINTF(fmt, args) 393 # endif 394 #else 395 # define ANGLE_FORMAT_PRINTF(fmt, args) 396 #endif 397 398 // Format messes up the # inside the macro. 399 // clang-format off 400 #ifndef ANGLE_STRINGIFY 401 # define ANGLE_STRINGIFY(x) #x 402 #endif 403 // clang-format on 404 405 #ifndef ANGLE_MACRO_STRINGIFY 406 # define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x) 407 #endif 408 409 // Detect support for C++17 [[nodiscard]] 410 #if !defined(__has_cpp_attribute) 411 # define __has_cpp_attribute(name) 0 412 #endif // !defined(__has_cpp_attribute) 413 414 #if __has_cpp_attribute(nodiscard) 415 # define ANGLE_NO_DISCARD [[nodiscard]] 416 #else 417 # define ANGLE_NO_DISCARD 418 #endif // __has_cpp_attribute(nodiscard) 419 420 #if __has_cpp_attribute(maybe_unused) 421 # define ANGLE_MAYBE_UNUSED [[maybe_unused]] 422 #else 423 # define ANGLE_MAYBE_UNUSED 424 #endif // __has_cpp_attribute(maybe_unused) 425 426 #if __has_cpp_attribute(require_constant_initialization) 427 # define ANGLE_REQUIRE_CONSTANT_INIT [[require_constant_initialization]] 428 #else 429 # define ANGLE_REQUIRE_CONSTANT_INIT 430 #endif // __has_cpp_attribute(require_constant_initialization) 431 432 #if __has_cpp_attribute(clang::fallthrough) 433 # define ANGLE_FALLTHROUGH [[clang::fallthrough]] 434 #else 435 # define ANGLE_FALLTHROUGH 436 #endif 437 438 // Compiler configs. IsASan()439 inline bool IsASan() 440 { 441 #if defined(ANGLE_WITH_ASAN) 442 return true; 443 #else 444 return false; 445 #endif // defined(ANGLE_WITH_ASAN) 446 } 447 IsTSan()448 inline bool IsTSan() 449 { 450 #if defined(ANGLE_WITH_TSAN) 451 return true; 452 #else 453 return false; 454 #endif // defined(ANGLE_WITH_TSAN) 455 } 456 IsUBSan()457 inline bool IsUBSan() 458 { 459 #if defined(ANGLE_WITH_UBSAN) 460 return true; 461 #else 462 return false; 463 #endif // defined(ANGLE_WITH_UBSAN) 464 } 465 #endif // COMMON_ANGLEUTILS_H_ 466