• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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