1//
2// Copyright (c) 2002-2014 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
23namespace angle
24{
25
26#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
27using Microsoft::WRL::ComPtr;
28#endif // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
29
30class 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
41extern const uintptr_t DirtyPointer;
42
43} // namespace angle
44
45template <typename T, size_t N>
46constexpr inline size_t ArraySize(T (&)[N])
47{
48 return N;
49}
50
51template <typename T>
52class WrappedArray final : angle::NonCopyable
53{
54 public:
55 template <size_t N>
56 constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N)
57 {}
58
59 constexpr WrappedArray() : mArray(nullptr), mSize(0) {}
60 constexpr WrappedArray(const T *data, size_t size) : mArray(data), mSize(size) {}
61
62 WrappedArray(WrappedArray &&other) : WrappedArray()
63 {
64 std::swap(mArray, other.mArray);
65 std::swap(mSize, other.mSize);
66 }
67
68 ~WrappedArray() {}
69
70 constexpr const T *get() const { return mArray; }
71 constexpr size_t size() const { return mSize; }
72
73 private:
74 const T *mArray;
75 size_t mSize;
76};
77
78template <typename T, unsigned int N>
79void SafeRelease(T (&resourceBlock)[N])
80{
81 for (unsigned int i = 0; i < N; i++)
82 {
83 SafeRelease(resourceBlock[i]);
84 }
85}
86
87template <typename T>
88void SafeRelease(T &resource)
89{
90 if (resource)
91 {
92 resource->Release();
93 resource = nullptr;
94 }
95}
96
97template <typename T>
98void SafeDelete(T *&resource)
99{
100 delete resource;
101 resource = nullptr;
102}
103
104template <typename T>
105void SafeDeleteContainer(T &resource)
106{
107 for (auto &element : resource)
108 {
109 SafeDelete(element);
110 }
111 resource.clear();
112}
113
114template <typename T>
115void 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
123template <typename T>
124inline 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
131template <typename T>
132inline bool StructEquals(const T &a, const T &b)
133{
134 return (memcmp(&a, &b, sizeof(T)) == 0);
135}
136
137template <typename T>
138inline void StructZero(T *obj)
139{
140 memset(obj, 0, sizeof(T));
141}
142
143template <typename T>
144inline bool IsMaskFlagSet(T mask, T flag)
145{
146 // Handles multibit flags as well
147 return (mask & flag) == flag;
148}
149
150inline 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
163std::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.
167std::string ArrayIndexString(const std::vector<unsigned int> &indices);
168
169inline std::string Str(int i)
170{
171 std::stringstream strstr;
172 strstr << i;
173 return strstr.str();
174}
175
176size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char> &buffer);
177
178template <typename T>
179std::string ToString(const T &value)
180{
181 std::ostringstream o;
182 o << value;
183 return o.str();
184}
185
186// snprintf is not defined with MSVC prior to to msvc14
187#if defined(_MSC_VER) && _MSC_VER < 1900
188# define snprintf _snprintf
189#endif
190
191#define GL_A1RGB5_ANGLEX 0x6AC5
192#define GL_BGRX8_ANGLEX 0x6ABA
193#define GL_BGR565_ANGLEX 0x6ABB
194#define GL_BGRA4_ANGLEX 0x6ABC
195#define GL_BGR5_A1_ANGLEX 0x6ABD
196#define GL_INT_64_ANGLEX 0x6ABE
197#define GL_UINT_64_ANGLEX 0x6ABF
198#define GL_BGRA8_SRGB_ANGLEX 0x6AC0
199
200// These are dummy formats used to fit typeless D3D textures that can be bound to EGL pbuffers into
201// the format system (for extension EGL_ANGLE_d3d_texture_client_buffer):
202#define GL_RGBA8_TYPELESS_ANGLEX 0x6AC1
203#define GL_RGBA8_TYPELESS_SRGB_ANGLEX 0x6AC2
204#define GL_BGRA8_TYPELESS_ANGLEX 0x6AC3
205#define GL_BGRA8_TYPELESS_SRGB_ANGLEX 0x6AC4
206
207#define GL_R8_SSCALED_ANGLEX 0x6AC6
208#define GL_RG8_SSCALED_ANGLEX 0x6AC7
209#define GL_RGB8_SSCALED_ANGLEX 0x6AC8
210#define GL_RGBA8_SSCALED_ANGLEX 0x6AC9
211#define GL_R8_USCALED_ANGLEX 0x6ACA
212#define GL_RG8_USCALED_ANGLEX 0x6ACB
213#define GL_RGB8_USCALED_ANGLEX 0x6ACC
214#define GL_RGBA8_USCALED_ANGLEX 0x6ACD
215
216#define GL_R16_SSCALED_ANGLEX 0x6ACE
217#define GL_RG16_SSCALED_ANGLEX 0x6ACF
218#define GL_RGB16_SSCALED_ANGLEX 0x6AD0
219#define GL_RGBA16_SSCALED_ANGLEX 0x6AD1
220#define GL_R16_USCALED_ANGLEX 0x6AD2
221#define GL_RG16_USCALED_ANGLEX 0x6AD3
222#define GL_RGB16_USCALED_ANGLEX 0x6AD4
223#define GL_RGBA16_USCALED_ANGLEX 0x6AD5
224
225#define GL_R32_SSCALED_ANGLEX 0x6AD6
226#define GL_RG32_SSCALED_ANGLEX 0x6AD7
227#define GL_RGB32_SSCALED_ANGLEX 0x6AD8
228#define GL_RGBA32_SSCALED_ANGLEX 0x6AD9
229#define GL_R32_USCALED_ANGLEX 0x6ADA
230#define GL_RG32_USCALED_ANGLEX 0x6ADB
231#define GL_RGB32_USCALED_ANGLEX 0x6ADC
232#define GL_RGBA32_USCALED_ANGLEX 0x6ADD
233
234#define GL_R32_SNORM_ANGLEX 0x6ADE
235#define GL_RG32_SNORM_ANGLEX 0x6ADF
236#define GL_RGB32_SNORM_ANGLEX 0x6AE0
237#define GL_RGBA32_SNORM_ANGLEX 0x6AE1
238#define GL_R32_UNORM_ANGLEX 0x6AE2
239#define GL_RG32_UNORM_ANGLEX 0x6AE3
240#define GL_RGB32_UNORM_ANGLEX 0x6AE4
241#define GL_RGBA32_UNORM_ANGLEX 0x6AE5
242
243#define GL_R32_FIXED_ANGLEX 0x6AE6
244#define GL_RG32_FIXED_ANGLEX 0x6AE7
245#define GL_RGB32_FIXED_ANGLEX 0x6AE8
246#define GL_RGBA32_FIXED_ANGLEX 0x6AE9
247
248#define GL_RGB10_A2_SINT_ANGLEX 0x6AEA
249#define GL_RGB10_A2_SNORM_ANGLEX 0x6AEB
250#define GL_RGB10_A2_SSCALED_ANGLEX 0x6AEC
251#define GL_RGB10_A2_USCALED_ANGLEX 0x6AED
252
253#define ANGLE_CHECK_GL_ALLOC(context, result) \
254 ANGLE_CHECK(context, result, "Failed to allocate host memory", GL_OUT_OF_MEMORY)
255
256#define ANGLE_CHECK_GL_MATH(context, result) \
257 ANGLE_CHECK(context, result, "Integer overflow.", GL_INVALID_OPERATION)
258
259#define ANGLE_GL_UNREACHABLE(context) \
260 UNREACHABLE(); \
261 ANGLE_CHECK(context, false, "Unreachable Code.", GL_INVALID_OPERATION)
262
263// The below inlining code lifted from V8.
264#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
265# define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
266# define ANGLE_HAS___FORCEINLINE 0
267#elif defined(_MSC_VER)
268# define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
269# define ANGLE_HAS___FORCEINLINE 1
270#else
271# define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
272# define ANGLE_HAS___FORCEINLINE 0
273#endif
274
275#if defined(NDEBUG) && ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE
276# define ANGLE_INLINE inline __attribute__((always_inline))
277#elif defined(NDEBUG) && ANGLE_HAS___FORCEINLINE
278# define ANGLE_INLINE __forceinline
279#else
280# define ANGLE_INLINE inline
281#endif
282
283#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
284# if __has_attribute(noinline)
285# define ANGLE_NOINLINE __attribute__((noinline))
286# else
287# define ANGLE_NOINLINE
288# endif
289#elif defined(_MSC_VER)
290# define ANGLE_NOINLINE __declspec(noinline)
291#else
292# define ANGLE_NOINLINE
293#endif
294
295#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
296# if __has_attribute(format)
297# define ANGLE_FORMAT_PRINTF(fmt, args) __attribute__((format(__printf__, fmt, args)))
298# else
299# define ANGLE_FORMAT_PRINTF(fmt, args)
300# endif
301#else
302# define ANGLE_FORMAT_PRINTF(fmt, args)
303#endif
304
305// Format messes up the # inside the macro.
306// clang-format off
307#ifndef ANGLE_STRINGIFY
308# define ANGLE_STRINGIFY(x) #x
309#endif
310// clang-format on
311
312#ifndef ANGLE_MACRO_STRINGIFY
313# define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
314#endif
315
316// Detect support for C++17 [[nodiscard]]
317#if !defined(__has_cpp_attribute)
318# define __has_cpp_attribute(name) 0
319#endif // !defined(__has_cpp_attribute)
320
321#if __has_cpp_attribute(nodiscard)
322# define ANGLE_NO_DISCARD [[nodiscard]]
323#else
324# define ANGLE_NO_DISCARD
325#endif // __has_cpp_attribute(nodiscard)
326
327#if __has_cpp_attribute(maybe_unused)
328# define ANGLE_MAYBE_UNUSED [[maybe_unused]]
329#else
330# define ANGLE_MAYBE_UNUSED
331#endif // __has_cpp_attribute(maybe_unused)
332
333#endif // COMMON_ANGLEUTILS_H_
334