• 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