include/gltexture.hpp
694871da
 #ifndef GLTEXTURE_HPP_
 #define GLTEXTURE_HPP_
 
 
 #include <cstddef>
 #include <string>
 #include <vector>
 
 #include <globject.hpp>
 
 
 /// Class
 
 class GLTexture : public GLObject<GL_TEXTURE, glGenTextures, glDeleteTextures>
 {
 public:
 
     /// Special member functions
 
     explicit GLTexture(
         std::string object_label,
         GLenum      target,
         GLenum      binding,
         GLenum      internal_format = 0,
         GLenum      wrap            = 0,
         GLenum      min_filter      = 0,
         GLenum      mag_filter      = 0
     );
 
     /// Core
 
     GLOBJECT_ACCESS_THREAD(GLfloat, anisotropy)
 
     GLint unit(bool force_active = false) const;
 
     template<typename Data = GLubyte>
     std::vector<Data> data(
         GLenum target    = 0,
         GLenum format    = DataTraits<Data>::format,
         GLint  alignment = 1
     ) const;
 
     template<typename Data = GLubyte>
     GLTexture & data(
         std::vector<Data> const & data,
         GLenum                    target    = 0,
         GLenum                    format    = DataTraits<Data>::format,
         GLint                     alignment = 1
     );
 
     template<typename Data = GLubyte>
     GLTexture & clear(
         Data   value     = Data{},
         GLenum target    = 0,
         GLenum format    = DataTraits<Data>::format,
         GLint  alignment = 1
     );
 
     /// Path
 
     GLOBJECT_ACCESS_THREAD(Path, prefix)
 
 protected:
 
     /// Core
 
     template<typename GLTextureDerived>
     GLTextureDerived static const & empty_();
 
     bool min_filter_mipmap_() const;
 
     std::size_t virtual data_size_() const = 0;
 
     void virtual data_(
         void const * data,
         GLenum       target,
         GLenum       format,
         GLenum       type
     ) = 0;
 
     /// Check
 
     void check_unit_active_() const;
     void check_unit_texture_() const;
     void check_data_size_(std::size_t data_size) const;
 
     /// String
 
     std::string static str_target_(GLenum target);
 
 protected:
 
     GLenum const target_;
 
 private:
 
     /// Core
 
     GLfloat static thread_local anisotropy_;
 
     GLenum const   binding_;
     GLenum const   min_filter_;
     GLuint mutable unit_;
 
     /// Path
 
     Path static thread_local prefix_;
 };
 
 
 /// Core
 
 template<typename Data>
 inline std::vector<Data> GLTexture::data(
     GLenum target,
     GLenum format,
     GLint  alignment
 ) const
 try
 {
     if (!target)
         target = target_;
     auto data = std::vector<Data>(data_size_());
     unit(true);
     glPixelStorei(GL_PACK_ALIGNMENT, alignment);
     glGetTexImage(target, 0, format, DataTraits<Data>::type, data.data());
     GLOBJECT_DEBUG_IF(1)
         check_error_(glGetError());
     return data;
 }
 catch (...)
 {
     fail_action_("get data of");
 }
 
 template<typename Data>
 inline GLTexture & GLTexture::data(
     std::vector<Data> const & data,
     GLenum                    target,
     GLenum                    format,
     GLint                     alignment
 )
 try
 {
     if (!target)
         target = target_;
     check_data_size_(data.size());
     unit(true);
     glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
     data_(data.data(), target, format, DataTraits<Data>::type);
     GLOBJECT_DEBUG_IF(1)
         check_error_(glGetError());
     if (min_filter_mipmap_())
         if (supported({3, 0}, "GL_ARB_framebuffer_object"))
             glGenerateMipmap(target);
     return *this;
 }
 catch (...)
 {
     fail_action_("set data of");
 }
 
 template<typename Data>
 GLTexture & GLTexture::clear(
     Data   value,
     GLenum target,
     GLenum format,
     GLint  alignment
 )
 {
     auto static clear = std::vector<Data>{};
     clear.resize(data_size_());
     std::fill(clear.begin(), clear.end(), value);
     data(clear, target, format, alignment);
     return *this;
 }
 
 template<typename GLTextureDerived>
 inline GLTextureDerived const & GLTexture::empty_()
 {
     auto static const empty = []()
     {
         auto size = typename GLTextureDerived::Size{};
         size.fill(1);
         auto tmp = GLTextureDerived("empty", size);
         tmp.clear();
         return tmp;
     }();
     return empty;
 }
 
 
 #endif // GLTEXTURE_HPP_