#ifndef GLTEXTURE_HPP_ #define GLTEXTURE_HPP_ #include #include #include #include /// Class class GLTexture : public GLObject { 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 std::vector data( GLenum target = 0, GLenum format = DataTraits::format, GLint alignment = 1 ) const; template GLTexture & data( std::vector const & data, GLenum target = 0, GLenum format = DataTraits::format, GLint alignment = 1 ); template GLTexture & clear( Data value = Data{}, GLenum target = 0, GLenum format = DataTraits::format, GLint alignment = 1 ); /// Path GLOBJECT_ACCESS_THREAD(Path, prefix) protected: /// Core template 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 inline std::vector GLTexture::data( GLenum target, GLenum format, GLint alignment ) const try { if (!target) target = target_; auto data = std::vector(data_size_()); unit(true); glPixelStorei(GL_PACK_ALIGNMENT, alignment); glGetTexImage(target, 0, format, DataTraits::type, data.data()); GLOBJECT_DEBUG_IF(1) check_error_(glGetError()); return data; } catch (...) { fail_action_("get data of"); } template inline GLTexture & GLTexture::data( std::vector 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::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 GLTexture & GLTexture::clear( Data value, GLenum target, GLenum format, GLint alignment ) { auto static clear = std::vector{}; clear.resize(data_size_()); std::fill(clear.begin(), clear.end(), value); data(clear, target, format, alignment); return *this; } template 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_