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