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