/// Guards #ifndef GLOBJECT_HPP_ #define GLOBJECT_HPP_ /// Includes #include #include #include /// GLObject template class GLObject; template<> class GLObject<0> : protected GLBase { protected: //// Object std::string static label_( GLenum object_type, GLuint object ); void static label_( GLenum object_type, GLuint object, std::string const & label ); //// Name std::string static name_( GLenum object_type, GLuint object, std::string const & label = {} ); }; template class GLObject : public GLObject<0>, protected GLTraits::Object { public: //// Special member functions template explicit GLObject(std::string const & label, Args... args) try : object_{0} { if (debug() >= 2) this->debug_action_("construct", name_(object_type, 0, label)); this->gen_objects(1, &object_, args...); try { // Strictly speaking `glObjectLabel` needs a *created* object. // `glGen*s` does not create objects (`glCreate*` does though), it // just reserves names for them. *Binding* that name for the first // time creates the object. Therefore, the below is not guaranteed // to work, but seems to on most drivers... Forcing our subclasses // to bind the name and call us back to set the label is deemed too // inconvenient so here we are. label_(object_type, object_, label); check_error_(glGetError()); } catch (...) { this->delete_objects(1, &object_); object_ = 0; throw; } } catch (...) { this->fail_action_("construct", name_(object_type, 0, label)); } ~GLObject() { if (debug() >= 2) debug_action_("destroy"); this->delete_objects(1, &object_); } GLObject(GLObject && other) noexcept : object_{other.object_} { if (debug() >= 2) debug_action_("move construct"); other.object_ = 0; } GLObject & operator=(GLObject && other) noexcept { if (debug() >= 2) debug_action_("move assign"); if (&other != this) { this->delete_objects(1, &object_); object_ = other.object_; other.object_ = 0; } return *this; } GLObject(GLObject const &) = delete; GLObject & operator=(GLObject const &) = delete; //// Object GLBASE_GET(GLuint, object) operator GLuint() const { return object(); } //// Name std::string name() const { return name_(object_type, object_); } protected: //// Debug void debug_action_(std::string const & action) const { return this->debug_action_(action, name()); } //// Fail void fail_action_(std::string const & action) const { return this->fail_action_(action, name()); } private: //// Object GLuint object_; }; /// Guards #endif