/// Guards #ifndef GLBASE_HPP_ #define GLBASE_HPP_ /// Includes #include #include #include #include #include #include #ifndef GLBASE_INCLUDE #define GLBASE_INCLUDE #endif #include GLBASE_INCLUDE // IWYU pragma: export /// Accessors #define GLBASE_GET_(TYPE, NAME, STATIC, CONST) \ TYPE STATIC const & NAME() CONST \ { \ return NAME##_; \ } #define GLBASE_SET_(TYPE, NAME, STATIC, CONST) \ template \ TYPE STATIC NAME(Type && NAME) \ { \ auto NAME##_old = std::move (NAME##_); \ NAME##_ = std::forward(NAME); \ return NAME##_old; \ } #define GLBASE_GET( TYPE, NAME) GLBASE_GET_(TYPE, NAME,, const) #define GLBASE_SET( TYPE, NAME) GLBASE_SET_(TYPE, NAME,, const) #define GLBASE_GET_GLOBAL(TYPE, NAME) GLBASE_GET_(TYPE, NAME, static,) #define GLBASE_SET_GLOBAL(TYPE, NAME) GLBASE_SET_(TYPE, NAME, static,) #define GLBASE_ACCESS(TYPE, NAME) \ GLBASE_GET(TYPE, NAME) \ GLBASE_SET(TYPE, NAME) #define GLBASE_ACCESS_GLOBAL(TYPE, NAME) \ GLBASE_GET_GLOBAL(TYPE, NAME) \ GLBASE_SET_GLOBAL(TYPE, NAME) #define GLBASE_GLOBAL(NAME, INIT) \ decltype(NAME) thread_local NAME INIT; /// GLBase class GLBase { public: //// Base using Version = std::array; GLBASE_ACCESS_GLOBAL(Version, version_max) bool static supported( Version version_min, std::string const & extension = {} ); char static const * string (GLenum name); char static const * string (GLenum name, GLuint index); GLint static integer(GLenum name); //// Path using Path = std::string; using Paths = std::vector; //// Exceptions struct Exception : std::runtime_error { using std::runtime_error::runtime_error; }; //// Debug using DebugCallback = std::function; GLBASE_GET_GLOBAL(int, debug) int static debug(int debug); GLBASE_ACCESS_GLOBAL(DebugCallback, debug_callback) void static debug_message(std::string const & message) { if (debug_callback()) debug_callback()(message); } //// Check void static check_supported( Version version_min, std::string const & extension = {} ); protected: //// Special member functions explicit GLBase() = default; ~GLBase() = default; //// Path Path static path_prefix_( Path const & path, Path const & prefix ); //// TGA class TGA_ { public: using Size = std::array; using Data = std::vector; explicit TGA_(Size size, Data data, Path const & path = {}); TGA_ static read (Path const & path); void write (Path const & path) const; GLBASE_GET(Size, size); GLBASE_GET(Data, data); protected: struct Header_ : std::array { explicit Header_(Size size); Size tga_size() const; }; std::string static name_(Path const & path); void static check_header_(Header_ const & header); void check_data_size_() const; private: Size size_; Data data_; }; //// Debug void static debug_action_( std::string const & action, std::string const & name ); //// Check void static check_path_(Path const & path); void static check_error_(GLenum error); void static check_type_( GLenum type, GLenum type_expected ); void static check_format_( GLenum format, GLenum format_expected ); void static check_internal_format_( GLenum internal_format ); //// Fail [[noreturn]] void static fail_action_( std::string const & action, std::string const & name ); //// String std::string static str_path_ (Path const & path); std::string static str_paths_ (Paths const & paths); std::string static str_enum_ (GLenum name); std::string static str_error_ (GLenum error); std::string static str_object_type_ (GLenum object_type); std::string static str_glsl_ (GLenum glsl); std::string static str_format_ (GLenum format); std::string static str_type_ (GLenum type); std::string static str_internal_format_(GLenum internal_format); private: //// Base Version static thread_local version_max_; //// Debug int static thread_local debug_; DebugCallback static thread_local debug_callback_; }; /// Guards #endif