1 | // |
2 | // Copyright 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 | // Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors |
7 | // and optional error messages. |
8 | |
9 | #ifndef LIBANGLE_ERROR_H_ |
10 | #define LIBANGLE_ERROR_H_ |
11 | |
12 | #include <EGL/egl.h> |
13 | #include <EGL/eglext.h> |
14 | #include "angle_gl.h" |
15 | #include "common/angleutils.h" |
16 | #include "common/debug.h" |
17 | |
18 | #include <memory> |
19 | #include <ostream> |
20 | #include <string> |
21 | |
22 | namespace angle |
23 | { |
24 | template <typename ErrorT, typename ErrorBaseT, ErrorBaseT NoErrorVal, typename CodeT, CodeT EnumT> |
25 | class ErrorStreamBase : angle::NonCopyable |
26 | { |
27 | public: |
28 | ErrorStreamBase() : mID(EnumT) {} |
29 | ErrorStreamBase(GLuint id) : mID(id) {} |
30 | |
31 | template <typename T> |
32 | ErrorStreamBase &operator<<(T value) |
33 | { |
34 | mErrorStream << value; |
35 | return *this; |
36 | } |
37 | |
38 | operator ErrorT() { return ErrorT(EnumT, mID, mErrorStream.str()); } |
39 | |
40 | private: |
41 | GLuint mID; |
42 | std::ostringstream mErrorStream; |
43 | }; |
44 | } // namespace angle |
45 | |
46 | namespace egl |
47 | { |
48 | class Error; |
49 | } // namespace egl |
50 | |
51 | namespace egl |
52 | { |
53 | |
54 | class [[nodiscard]] Error final |
55 | { |
56 | public: |
57 | explicit inline Error(EGLint errorCode); |
58 | Error(EGLint errorCode, std::string &&message); |
59 | Error(EGLint errorCode, EGLint id, std::string &&message); |
60 | inline Error(const Error &other); |
61 | inline Error(Error &&other); |
62 | inline ~Error() = default; |
63 | |
64 | inline Error &operator=(const Error &other); |
65 | inline Error &operator=(Error &&other); |
66 | |
67 | inline EGLint getCode() const; |
68 | inline EGLint getID() const; |
69 | inline bool isError() const; |
70 | |
71 | inline void setCode(EGLint code); |
72 | |
73 | const std::string &getMessage() const; |
74 | |
75 | static inline Error NoError(); |
76 | |
77 | private: |
78 | void createMessageString() const; |
79 | |
80 | friend std::ostream &operator<<(std::ostream &os, const Error &err); |
81 | |
82 | EGLint mCode; |
83 | EGLint mID; |
84 | mutable std::unique_ptr<std::string> mMessage; |
85 | }; |
86 | |
87 | namespace priv |
88 | { |
89 | |
90 | template <EGLint EnumT> |
91 | using ErrorStream = angle::ErrorStreamBase<Error, EGLint, EGL_SUCCESS, EGLint, EnumT>; |
92 | |
93 | } // namespace priv |
94 | |
95 | using EglBadAccess = priv::ErrorStream<EGL_BAD_ACCESS>; |
96 | using EglBadAlloc = priv::ErrorStream<EGL_BAD_ALLOC>; |
97 | using EglBadAttribute = priv::ErrorStream<EGL_BAD_ATTRIBUTE>; |
98 | using EglBadConfig = priv::ErrorStream<EGL_BAD_CONFIG>; |
99 | using EglBadContext = priv::ErrorStream<EGL_BAD_CONTEXT>; |
100 | using EglBadCurrentSurface = priv::ErrorStream<EGL_BAD_CURRENT_SURFACE>; |
101 | using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>; |
102 | using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>; |
103 | using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>; |
104 | using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>; |
105 | using EglBadNativePixmap = priv::ErrorStream<EGL_BAD_NATIVE_PIXMAP>; |
106 | using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>; |
107 | using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>; |
108 | using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>; |
109 | using EglBadSurface = priv::ErrorStream<EGL_BAD_SURFACE>; |
110 | using EglContextLost = priv::ErrorStream<EGL_CONTEXT_LOST>; |
111 | using EglNotInitialized = priv::ErrorStream<EGL_NOT_INITIALIZED>; |
112 | |
113 | inline Error NoError() |
114 | { |
115 | return Error::NoError(); |
116 | } |
117 | |
118 | } // namespace egl |
119 | |
120 | #define ANGLE_CONCAT1(x, y) x##y |
121 | #define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y) |
122 | #define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__) |
123 | |
124 | #define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \ |
125 | do \ |
126 | { \ |
127 | auto ANGLE_LOCAL_VAR = EXPR; \ |
128 | if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ |
129 | { \ |
130 | FUNC(ANGLE_LOCAL_VAR); \ |
131 | } \ |
132 | } while (0) |
133 | |
134 | #define ANGLE_RETURN(X) return X; |
135 | #define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN) |
136 | |
137 | // TODO(jmadill): Remove after EGL error refactor. http://anglebug.com/3041 |
138 | #define ANGLE_SWALLOW_ERR(EXPR) \ |
139 | do \ |
140 | { \ |
141 | auto ANGLE_LOCAL_VAR = EXPR; \ |
142 | if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ |
143 | { \ |
144 | ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \ |
145 | } \ |
146 | } while (0) |
147 | |
148 | #undef ANGLE_LOCAL_VAR |
149 | #undef ANGLE_CONCAT2 |
150 | #undef ANGLE_CONCAT1 |
151 | |
152 | #define ANGLE_CHECK(CONTEXT, EXPR, MESSAGE, ERROR) \ |
153 | do \ |
154 | { \ |
155 | if (ANGLE_UNLIKELY(!(EXPR))) \ |
156 | { \ |
157 | CONTEXT->handleError(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ |
158 | return angle::Result::Stop; \ |
159 | } \ |
160 | } while (0) |
161 | |
162 | namespace angle |
163 | { |
164 | // Result signals if calling code should continue running or early exit. A value of Stop can |
165 | // either indicate an Error or a non-Error early exit condition such as a detected no-op. |
166 | // Incomplete signals special cases that are neither success nor failure but require |
167 | // special attention. |
168 | enum class [[nodiscard]] Result |
169 | { |
170 | Continue, |
171 | Stop, |
172 | Incomplete, |
173 | }; |
174 | |
175 | // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 |
176 | egl::Error ResultToEGL(Result result); |
177 | } // namespace angle |
178 | |
179 | // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 |
180 | inline bool IsError(angle::Result result) |
181 | { |
182 | return result == angle::Result::Stop; |
183 | } |
184 | |
185 | // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 |
186 | inline bool IsError(const egl::Error &err) |
187 | { |
188 | return err.isError(); |
189 | } |
190 | |
191 | // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 |
192 | inline bool IsError(bool value) |
193 | { |
194 | return !value; |
195 | } |
196 | |
197 | // Utility macro for handling implementation methods inside Validation. |
198 | #define ANGLE_HANDLE_VALIDATION_ERR(X) \ |
199 | do \ |
200 | { \ |
201 | (void)(X); \ |
202 | return false; \ |
203 | } while (0) |
204 | |
205 | #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR) |
206 | |
207 | #include "Error.inc" |
208 | |
209 | #endif // LIBANGLE_ERROR_H_ |
210 | |