Error.h (6899B)
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 const std::string &getMessage() const; 72 73 static inline Error NoError(); 74 75 private: 76 void createMessageString() const; 77 78 friend std::ostream &operator<<(std::ostream &os, const Error &err); 79 80 EGLint mCode; 81 EGLint mID; 82 mutable std::unique_ptr<std::string> mMessage; 83 }; 84 85 namespace priv 86 { 87 88 template <EGLint EnumT> 89 using ErrorStream = angle::ErrorStreamBase<Error, EGLint, EGL_SUCCESS, EGLint, EnumT>; 90 91 } // namespace priv 92 93 using EglBadAccess = priv::ErrorStream<EGL_BAD_ACCESS>; 94 using EglBadAlloc = priv::ErrorStream<EGL_BAD_ALLOC>; 95 using EglBadAttribute = priv::ErrorStream<EGL_BAD_ATTRIBUTE>; 96 using EglBadConfig = priv::ErrorStream<EGL_BAD_CONFIG>; 97 using EglBadContext = priv::ErrorStream<EGL_BAD_CONTEXT>; 98 using EglBadCurrentSurface = priv::ErrorStream<EGL_BAD_CURRENT_SURFACE>; 99 using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>; 100 using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>; 101 using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>; 102 using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>; 103 using EglBadNativePixmap = priv::ErrorStream<EGL_BAD_NATIVE_PIXMAP>; 104 using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>; 105 using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>; 106 using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>; 107 using EglBadSurface = priv::ErrorStream<EGL_BAD_SURFACE>; 108 using EglContextLost = priv::ErrorStream<EGL_CONTEXT_LOST>; 109 using EglNotInitialized = priv::ErrorStream<EGL_NOT_INITIALIZED>; 110 111 inline Error NoError() 112 { 113 return Error::NoError(); 114 } 115 116 } // namespace egl 117 118 #define ANGLE_CONCAT1(x, y) x##y 119 #define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y) 120 #define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__) 121 122 #define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \ 123 do \ 124 { \ 125 auto ANGLE_LOCAL_VAR = EXPR; \ 126 if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ 127 { \ 128 FUNC(ANGLE_LOCAL_VAR); \ 129 } \ 130 } while (0) 131 132 #define ANGLE_RETURN(X) return X; 133 #define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN) 134 135 // TODO(jmadill): Remove after EGL error refactor. http://anglebug.com/3041 136 #define ANGLE_SWALLOW_ERR(EXPR) \ 137 do \ 138 { \ 139 auto ANGLE_LOCAL_VAR = EXPR; \ 140 if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ 141 { \ 142 ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \ 143 } \ 144 } while (0) 145 146 #undef ANGLE_LOCAL_VAR 147 #undef ANGLE_CONCAT2 148 #undef ANGLE_CONCAT1 149 150 #define ANGLE_CHECK(CONTEXT, EXPR, MESSAGE, ERROR) \ 151 do \ 152 { \ 153 if (ANGLE_UNLIKELY(!(EXPR))) \ 154 { \ 155 CONTEXT->handleError(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ 156 return angle::Result::Stop; \ 157 } \ 158 } while (0) 159 160 namespace angle 161 { 162 // Result signals if calling code should continue running or early exit. A value of Stop can 163 // either indicate an Error or a non-Error early exit condition such as a detected no-op. 164 // Incomplete signals special cases that are neither success nor failure but require 165 // special attention. 166 enum class [[nodiscard]] Result{ 167 Continue, 168 Stop, 169 Incomplete, 170 }; 171 172 // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 173 egl::Error ResultToEGL(Result result); 174 } // namespace angle 175 176 // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 177 inline bool IsError(angle::Result result) 178 { 179 return result == angle::Result::Stop; 180 } 181 182 // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 183 inline bool IsError(const egl::Error &err) 184 { 185 return err.isError(); 186 } 187 188 // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 189 inline bool IsError(bool value) 190 { 191 return !value; 192 } 193 194 // Utility macro for handling implementation methods inside Validation. 195 #define ANGLE_HANDLE_VALIDATION_ERR(X) \ 196 do \ 197 { \ 198 (void)(X); \ 199 return false; \ 200 } while (0) 201 202 #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR) 203 204 #include "Error.inc" 205 206 #endif // LIBANGLE_ERROR_H_