include/glbase.hpp
58cc126e
 /// Guards
 
 #ifndef GLBASE_HPP_
 #define GLBASE_HPP_
 
 
 /// Includes
 
 #include <array>
 #include <functional>
 #include <stdexcept>
 #include <string>
 #include <utility>
 #include <vector>
 
 #ifndef GLBASE_INCLUDE
 #define GLBASE_INCLUDE <GL/glew.h>
 #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<typename Type> \
     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<GLint, 2>;
 
     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<Path>;
 
     //// Exceptions
 
     struct Exception : std::runtime_error
     {
         using std::runtime_error::runtime_error;
     };
 
     //// Debug
 
     using DebugCallback = std::function<void (std::string const & message)>;
 
     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<GLsizei, 2>;
         using Data = std::vector<GLubyte>;
         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<GLubyte, 18>
         {
             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