diff --git a/src/Magnum/Renderbuffer.cpp b/src/Magnum/Renderbuffer.cpp index ef5a978cb..5f0292c12 100644 --- a/src/Magnum/Renderbuffer.cpp +++ b/src/Magnum/Renderbuffer.cpp @@ -64,7 +64,7 @@ Int Renderbuffer::maxSamples() { return value; } -Renderbuffer::Renderbuffer() { glGenRenderbuffers(1, &_id); } +Renderbuffer::Renderbuffer(): _created{false} { glGenRenderbuffers(1, &_id); } Renderbuffer::~Renderbuffer() { /* Moved out, nothing to do */ @@ -77,11 +77,24 @@ Renderbuffer::~Renderbuffer() { glDeleteRenderbuffers(1, &_id); } -std::string Renderbuffer::label() const { +inline void Renderbuffer::createIfNotAlready() { + if(_created) return; + + /* glGen*() does not create the object, just reserves the name. Some + commands (such as glObjectLabel()) operate with IDs directly and they + require the object to be created. Binding the renderbuffer finally + creates it. Also all EXT DSA functions implicitly create it. */ + bind(); + CORRADE_INTERNAL_ASSERT(_created); +} + +std::string Renderbuffer::label() { + createIfNotAlready(); return Context::current()->state().debug->getLabelImplementation(GL_RENDERBUFFER, _id); } Renderbuffer& Renderbuffer::setLabelInternal(const Containers::ArrayReference label) { + createIfNotAlready(); Context::current()->state().debug->labelImplementation(GL_RENDERBUFFER, _id, label); return *this; } @@ -99,7 +112,9 @@ void Renderbuffer::bind() { if(binding == _id) return; + /* Binding the renderbuffer finally creates it */ binding = _id; + _created = true; glBindRenderbuffer(GL_RENDERBUFFER, _id); } @@ -110,6 +125,7 @@ void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalForma #ifndef MAGNUM_TARGET_GLES void Renderbuffer::storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size) { + _created = true; glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y()); } #endif @@ -147,6 +163,7 @@ void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, con #ifndef MAGNUM_TARGET_GLES void Renderbuffer::storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size) { + _created = true; glNamedRenderbufferStorageMultisampleEXT(_id, samples, GLenum(internalFormat), size.x(), size.y()); } #endif diff --git a/src/Magnum/Renderbuffer.h b/src/Magnum/Renderbuffer.h index 3173e3d6d..6764ace61 100644 --- a/src/Magnum/Renderbuffer.h +++ b/src/Magnum/Renderbuffer.h @@ -124,7 +124,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with * @def_gl{RENDERBUFFER} */ - std::string label() const; + std::string label(); /** * @brief Set renderbuffer label @@ -178,6 +178,8 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size); private: + void MAGNUM_LOCAL createIfNotAlready(); + Renderbuffer& setLabelInternal(Containers::ArrayReference label); void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size); @@ -198,14 +200,16 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject { void MAGNUM_LOCAL bind(); GLuint _id; + bool _created; /* see createIfNotAlready() for details */ }; -inline Renderbuffer::Renderbuffer(Renderbuffer&& other) noexcept: _id(other._id) { +inline Renderbuffer::Renderbuffer(Renderbuffer&& other) noexcept: _id{other._id}, _created{other._created} { other._id = 0; } inline Renderbuffer& Renderbuffer::operator=(Renderbuffer&& other) noexcept { std::swap(_id, other._id); + std::swap(_created, other._created); return *this; } diff --git a/src/Magnum/Test/RenderbufferGLTest.cpp b/src/Magnum/Test/RenderbufferGLTest.cpp index a19a0a23f..eab8cc786 100644 --- a/src/Magnum/Test/RenderbufferGLTest.cpp +++ b/src/Magnum/Test/RenderbufferGLTest.cpp @@ -111,29 +111,15 @@ void RenderbufferGLTest::label() { CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not available.")); #endif - /* No-Op version is tested in AbstractObjectGLTest */ - if(!Context::current()->isExtensionSupported() && - !Context::current()->isExtensionSupported()) - CORRADE_SKIP("Required extension is not available"); - - { - /** @todo Is this even legal optimization? */ - CORRADE_EXPECT_FAIL("The object must be used at least once before setting/querying label."); - CORRADE_VERIFY(false); - } Renderbuffer renderbuffer; - #ifndef MAGNUM_TARGET_GLES2 - renderbuffer.setStorage(RenderbufferFormat::RGBA8, {128, 128}); - #else - renderbuffer.setStorage(RenderbufferFormat::RGBA4, {128, 128}); - #endif CORRADE_COMPARE(renderbuffer.label(), ""); + MAGNUM_VERIFY_NO_ERROR(); renderbuffer.setLabel("MyRenderbuffer"); - CORRADE_COMPARE(renderbuffer.label(), "MyRenderbuffer"); - MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(renderbuffer.label(), "MyRenderbuffer"); } void RenderbufferGLTest::setStorage() {