// // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors // and optional error messages. #ifndef LIBANGLE_ERROR_H_ #define LIBANGLE_ERROR_H_ #include #include #include "angle_gl.h" #include "common/angleutils.h" #include "common/debug.h" #include #include #include namespace angle { template class ErrorStreamBase : angle::NonCopyable { public: ErrorStreamBase() : mID(EnumT) {} ErrorStreamBase(GLuint id) : mID(id) {} template ErrorStreamBase &operator<<(T value) { mErrorStream << value; return *this; } operator ErrorT() { return ErrorT(EnumT, mID, mErrorStream.str()); } private: GLuint mID; std::ostringstream mErrorStream; }; } // namespace angle namespace egl { class Error; } // namespace egl namespace egl { class [[nodiscard]] Error final { public: explicit inline Error(EGLint errorCode); Error(EGLint errorCode, std::string &&message); Error(EGLint errorCode, EGLint id, std::string &&message); inline Error(const Error &other); inline Error(Error &&other); inline ~Error() = default; inline Error &operator=(const Error &other); inline Error &operator=(Error &&other); inline EGLint getCode() const; inline EGLint getID() const; inline bool isError() const; const std::string &getMessage() const; static inline Error NoError(); private: void createMessageString() const; friend std::ostream &operator<<(std::ostream &os, const Error &err); EGLint mCode; EGLint mID; mutable std::unique_ptr mMessage; }; namespace priv { template using ErrorStream = angle::ErrorStreamBase; } // namespace priv using EglBadAccess = priv::ErrorStream; using EglBadAlloc = priv::ErrorStream; using EglBadAttribute = priv::ErrorStream; using EglBadConfig = priv::ErrorStream; using EglBadContext = priv::ErrorStream; using EglBadCurrentSurface = priv::ErrorStream; using EglBadDevice = priv::ErrorStream; using EglBadDisplay = priv::ErrorStream; using EglBadMatch = priv::ErrorStream; using EglBadNativeWindow = priv::ErrorStream; using EglBadNativePixmap = priv::ErrorStream; using EglBadParameter = priv::ErrorStream; using EglBadState = priv::ErrorStream; using EglBadStream = priv::ErrorStream; using EglBadSurface = priv::ErrorStream; using EglContextLost = priv::ErrorStream; using EglNotInitialized = priv::ErrorStream; inline Error NoError() { return Error::NoError(); } } // namespace egl #define ANGLE_CONCAT1(x, y) x##y #define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y) #define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__) #define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \ do \ { \ auto ANGLE_LOCAL_VAR = EXPR; \ if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ { \ FUNC(ANGLE_LOCAL_VAR); \ } \ } while (0) #define ANGLE_RETURN(X) return X; #define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN) // TODO(jmadill): Remove after EGL error refactor. http://anglebug.com/3041 #define ANGLE_SWALLOW_ERR(EXPR) \ do \ { \ auto ANGLE_LOCAL_VAR = EXPR; \ if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \ { \ ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \ } \ } while (0) #undef ANGLE_LOCAL_VAR #undef ANGLE_CONCAT2 #undef ANGLE_CONCAT1 #define ANGLE_CHECK(CONTEXT, EXPR, MESSAGE, ERROR) \ do \ { \ if (ANGLE_UNLIKELY(!(EXPR))) \ { \ CONTEXT->handleError(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ return angle::Result::Stop; \ } \ } while (0) namespace angle { // Result signals if calling code should continue running or early exit. A value of Stop can // either indicate an Error or a non-Error early exit condition such as a detected no-op. // Incomplete signals special cases that are neither success nor failure but require // special attention. enum class [[nodiscard]] Result{ Continue, Stop, Incomplete, }; // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 egl::Error ResultToEGL(Result result); } // namespace angle // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 inline bool IsError(angle::Result result) { return result == angle::Result::Stop; } // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 inline bool IsError(const egl::Error &err) { return err.isError(); } // TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041 inline bool IsError(bool value) { return !value; } // Utility macro for handling implementation methods inside Validation. #define ANGLE_HANDLE_VALIDATION_ERR(X) \ do \ { \ (void)(X); \ return false; \ } while (0) #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR) #include "Error.inc" #endif // LIBANGLE_ERROR_H_