diff --git a/src/AbstractObject.cpp b/src/AbstractObject.cpp new file mode 100644 index 000000000..3f84c2054 --- /dev/null +++ b/src/AbstractObject.cpp @@ -0,0 +1,219 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "AbstractObject.h" + +#include + +#include "Extensions.h" +#include "Implementation/State.h" +#include "Implementation/DebugState.h" + +namespace Magnum { + +namespace { + /* What the hell, Apple? Why you had to create this abomination _after_ + KHR_debug was released?! */ + inline GLenum extTypeFromKhrIdentifier(GLenum khrIdentifier) { + switch(khrIdentifier) { + #ifndef MAGNUM_TARGET_GLES + case GL_BUFFER: + #else + case GL_BUFFER_KHR: + #endif + return GL_BUFFER_OBJECT_EXT; + + #ifndef MAGNUM_TARGET_GLES + case GL_SHADER: + #else + case GL_SHADER_KHR: + #endif + return GL_SHADER_OBJECT_EXT; + + #ifndef MAGNUM_TARGET_GLES + case GL_PROGRAM: + #else + case GL_PROGRAM_KHR: + #endif + return GL_PROGRAM_OBJECT_EXT; + + #ifndef MAGNUM_TARGET_GLES + case GL_VERTEX_ARRAY: + #else + case GL_VERTEX_ARRAY_KHR: + #endif + return GL_VERTEX_ARRAY_OBJECT_EXT; + + #ifndef MAGNUM_TARGET_GLES + case GL_QUERY: + #else + case GL_QUERY_KHR: + #endif + return GL_QUERY_OBJECT_EXT; + + /** @todo Why isn't `GL_PROGRAM_PIPELINE_KHR` in ES's KHR_debug? */ + #ifndef MAGNUM_TARGET_GLES + case GL_PROGRAM_PIPELINE: + #else + case 0x82E4: //GL_PROGRAM_PIPELINE_KHR: + #endif + return GL_PROGRAM_PIPELINE_OBJECT_EXT; + + /** + * @todo Shouldn't ES2's KHR_debug have `GL_TRANSFORM_FEEDBACK_KHR` + * instead of `GL_TRANSFORM_FEEDBACK`? (it's a new enum in 2.0) + */ + case GL_TRANSFORM_FEEDBACK: + #ifndef MAGNUM_TARGET_GLES + case GL_SAMPLER: + #else + case GL_SAMPLER_KHR: + #endif + case GL_TEXTURE: + case GL_RENDERBUFFER: + case GL_FRAMEBUFFER: + return khrIdentifier; + } + + CORRADE_ASSERT_UNREACHABLE(); + } +} + +Int AbstractObject::maxLabelLength() { + if(!Context::current()->isExtensionSupported()) + return 0; + + GLint& value = Context::current()->state().debug->maxLabelLength; + + if(value == 0) { + #ifndef MAGNUM_TARGET_GLES + glGetIntegerv(GL_MAX_LABEL_LENGTH, &value); + #else + glGetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &value); + #endif + } + + return value; +} + +void AbstractObject::labelImplementationNoOp(GLenum, GLuint, const std::string&) {} + +void AbstractObject::labelImplementationKhr(const GLenum identifier, const GLuint name, const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + glObjectLabel(identifier, name, label.size(), label.data()); + #else + static_cast(identifier); + static_cast(name); + static_cast(label); + CORRADE_INTERNAL_ASSERT(false); + //glObjectLabelKHR(identifier, name, label.size(), label.data()); + #endif +} + +void AbstractObject::labelImplementationExt(const GLenum identifier, const GLuint name, const std::string& label) { + const GLenum type = extTypeFromKhrIdentifier(identifier); + /** @todo Re-enable when extension wrangler is available for ES */ + #ifndef MAGNUM_TARGET_GLES + glLabelObjectEXT(type, name, label.size(), label.data()); + #else + static_cast(type); + static_cast(name); + static_cast(label); + CORRADE_INTERNAL_ASSERT(false); + #endif +} + +std::string AbstractObject::getLabelImplementationNoOp(GLenum, GLuint) { return {}; } + +std::string AbstractObject::getLabelImplementationKhr(const GLenum identifier, const GLuint name) { + /** + * @todo Get rid of this workaround when NVidia returns proper size for + * length=0 & label=nullptr (even crashes on length>0 & label=nullptr) + */ + #if 0 + /* Get label size (w/o null terminator) */ + GLsizei size; + #ifndef MAGNUM_TARGET_GLES + glGetObjectLabel(type, name, 0, &size, nullptr); + #else + glGetObjectLabelKHR(type, name, 0, &size, nullptr); + #endif + + /* Make place also for the null terminator */ + std::string label; + label.resize(size+1); + #ifndef MAGNUM_TARGET_GLES + glGetObjectLabel(identifier, name, size+1, nullptr, &label[0]); + #else + glGetObjectLabelKHR(identifier, name, size+1, nullptr, &label[0]); + #endif + + /* Pop null terminator and return the string */ + label.pop_back(); + return label; + #else + GLsizei size; + std::string label; + label.resize(maxLabelLength()); + /** @todo Re-enable when extension wrangler is available for ES */ + #ifndef MAGNUM_TARGET_GLES + glGetObjectLabel(identifier, name, label.size(), &size, &label[0]); + #else + static_cast(identifier); + static_cast(name); + CORRADE_INTERNAL_ASSERT(false); + //glGetObjectLabelKHR(identifier, name, label.size(), &size, &label[0]); + #endif + return label.substr(0, size); + #endif +} + +std::string AbstractObject::getLabelImplementationExt(const GLenum identifier, const GLuint name) { + const GLenum type = extTypeFromKhrIdentifier(identifier); + + /* Get label size (w/o null terminator) */ + GLsizei size; + /** @todo Re-enable when extension wrangler is available for ES */ + #ifndef MAGNUM_TARGET_GLES + glGetObjectLabelEXT(type, name, 0, &size, nullptr); + #else + static_cast(type); + static_cast(name); + CORRADE_INTERNAL_ASSERT(false); + #endif + + /* Make place also for the null terminator */ + std::string label; + label.resize(size+1); + /** @todo Re-enable when extension wrangler is available for ES */ + #ifndef MAGNUM_TARGET_GLES + glGetObjectLabelEXT(identifier, name, size+1, nullptr, &label[0]); + #endif + + /* Pop null terminator and return the string */ + label.pop_back(); + return label; +} + +} diff --git a/src/AbstractObject.h b/src/AbstractObject.h new file mode 100644 index 000000000..cbb75373e --- /dev/null +++ b/src/AbstractObject.h @@ -0,0 +1,81 @@ +#ifndef Magnum_AbstractObject_h +#define Magnum_AbstractObject_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::AbstractObject + */ + +#include + +#include "OpenGL.h" +#include "Types.h" +#include "magnumVisibility.h" + +namespace Magnum { + +namespace Implementation { + struct DebugState; +} + +/** +@brief Base for all OpenGL objects +*/ +class MAGNUM_EXPORT AbstractObject { + friend class Context; + friend class Implementation::DebugState; + + public: + /** + * @brief Max object label length + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If @extension{KHR,debug} desktop or ES extension is + * not available, returns `0`. Note that @extension{EXT,debug_label} + * has no such limit. + * @see @ref AbstractQuery::setLabel(), @ref AbstractShaderProgram::setLabel(), + * @ref AbstractTexture::setLabel(), @ref Buffer::setLabel(), + * @ref BufferTexture::setLabel(), @ref Framebuffer::setLabel(), + * @ref Mesh::setLabel(), @ref Renderbuffer::setLabel(), + * @ref Shader::setLabel(), @fn_gl{Get} with @def_gl{MAX_LABEL_LENGTH} + */ + static Int maxLabelLength(); + + protected: + MAGNUM_LOCAL AbstractObject() = default; + MAGNUM_LOCAL ~AbstractObject() = default; + + private: + static MAGNUM_LOCAL void labelImplementationNoOp(GLenum, GLuint, const std::string&); + static MAGNUM_LOCAL void labelImplementationExt(GLenum identifier, GLuint name, const std::string& label); + static MAGNUM_LOCAL void labelImplementationKhr(GLenum identifier, GLuint name, const std::string& label); + static MAGNUM_LOCAL std::string getLabelImplementationNoOp(GLenum, GLuint); + static MAGNUM_LOCAL std::string getLabelImplementationExt(GLenum identifier, GLuint name); + static MAGNUM_LOCAL std::string getLabelImplementationKhr(GLenum identifier, GLuint name); +}; + +} + +#endif diff --git a/src/AbstractShaderProgram.cpp b/src/AbstractShaderProgram.cpp index 8a0ed38b6..cccaa31c5 100644 --- a/src/AbstractShaderProgram.cpp +++ b/src/AbstractShaderProgram.cpp @@ -27,6 +27,7 @@ #include "Math/RectangularMatrix.h" #include "Extensions.h" #include "Shader.h" +#include "Implementation/DebugState.h" #include "Implementation/ShaderProgramState.h" #include "Implementation/State.h" @@ -251,6 +252,23 @@ AbstractShaderProgram& AbstractShaderProgram::operator=(AbstractShaderProgram&& return *this; } +std::string AbstractShaderProgram::label() const { + #ifndef MAGNUM_TARGET_GLES + return Context::current()->state().debug->getLabelImplementation(GL_PROGRAM, _id); + #else + return Context::current()->state().debug->getLabelImplementation(GL_PROGRAM_KHR, _id); + #endif +} + +AbstractShaderProgram& AbstractShaderProgram::setLabel(const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + Context::current()->state().debug->labelImplementation(GL_PROGRAM, _id, label); + #else + Context::current()->state().debug->labelImplementation(GL_PROGRAM_KHR, _id, label); + #endif + return *this; +} + std::pair AbstractShaderProgram::validate() { glValidateProgram(_id); diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 4ce0e6e46..570566380 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -31,8 +31,8 @@ #include #include +#include "AbstractObject.h" #include "Magnum.h" -#include "OpenGL.h" #include "magnumVisibility.h" namespace Magnum { @@ -317,7 +317,7 @@ comes in handy. status, should be faster -- https://twitter.com/g_truc/status/352778836657700866 @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility}) */ -class MAGNUM_EXPORT AbstractShaderProgram { +class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { friend class Context; public: @@ -508,6 +508,32 @@ class MAGNUM_EXPORT AbstractShaderProgram { /** @brief OpenGL program ID */ GLuint id() const { return _id; } + /** + * @brief %Shader program label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{PROGRAM} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{PROGRAM_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set shader program label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{PROGRAM} or @fn_gl_extension{LabelObject,EXT,object_label} + * with @def_gl{PROGRAM_OBJECT_EXT} + */ + AbstractShaderProgram& setLabel(const std::string& label); + /** * @brief Validate program * diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 3402ee414..0f7d1684e 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -31,6 +31,7 @@ #include "Image.h" #include "Shader.h" #include "TextureFormat.h" +#include "Implementation/DebugState.h" #include "Implementation/State.h" #include "Implementation/TextureState.h" @@ -158,6 +159,15 @@ AbstractTexture& AbstractTexture::operator=(AbstractTexture&& other) { return *this; } +std::string AbstractTexture::label() const { + return Context::current()->state().debug->getLabelImplementation(GL_TEXTURE, _id); +} + +AbstractTexture& AbstractTexture::setLabel(const std::string& label) { + Context::current()->state().debug->labelImplementation(GL_TEXTURE, _id, label); + return *this; +} + void AbstractTexture::bind(Int layer) { Implementation::TextureState* const textureState = Context::current()->state().texture; diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index d05ef82b5..70c74f6d2 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -31,6 +31,7 @@ #include "Array.h" #include "Color.h" #include "Sampler.h" +#include "AbstractObject.h" namespace Magnum { @@ -95,7 +96,7 @@ nothing. @todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done */ -class MAGNUM_EXPORT AbstractTexture { +class MAGNUM_EXPORT AbstractTexture: public AbstractObject { friend class Context; public: @@ -165,6 +166,32 @@ class MAGNUM_EXPORT AbstractTexture { /** @brief Move assignment */ AbstractTexture& operator=(AbstractTexture&& other); + /** + * @brief %Texture label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{TEXTURE} + */ + std::string label() const; + + /** + * @brief Set texture label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or + * @fn_gl_extension{LabelObject,EXT,object_label} with + * @def_gl{TEXTURE} + */ + AbstractTexture& setLabel(const std::string& label); + /** @brief OpenGL texture ID */ GLuint id() const { return _id; } diff --git a/src/Buffer.cpp b/src/Buffer.cpp index a0638faa7..809450ee2 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -30,6 +30,7 @@ #include "Extensions.h" #include "Implementation/State.h" #include "Implementation/BufferState.h" +#include "Implementation/DebugState.h" namespace Magnum { @@ -160,6 +161,23 @@ Buffer::~Buffer() { glDeleteBuffers(1, &_id); } +std::string Buffer::label() const { + #ifndef MAGNUM_TARGET_GLES + return Context::current()->state().debug->getLabelImplementation(GL_BUFFER, _id); + #else + return Context::current()->state().debug->getLabelImplementation(GL_BUFFER_KHR, _id); + #endif +} + +Buffer& Buffer::setLabel(const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + Context::current()->state().debug->labelImplementation(GL_BUFFER, _id, label); + #else + Context::current()->state().debug->labelImplementation(GL_BUFFER_KHR, _id, label); + #endif + return *this; +} + void Buffer::bind(Target target, GLuint id) { GLuint& bound = Context::current()->state().buffer->bindings[Implementation::BufferState::indexForTarget(target)]; diff --git a/src/Buffer.h b/src/Buffer.h index a3fc8ca17..173fbe2a5 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -35,9 +35,8 @@ #include #include +#include "AbstractObject.h" #include "Magnum.h" -#include "OpenGL.h" -#include "magnumVisibility.h" namespace Magnum { @@ -189,7 +188,7 @@ nothing. @todo Support for AMD/ARB's query buffer (@extension{AMD,query_buffer_object}, @extension{ARB,query_buffer_object}) @todo BindBufferRange/BindBufferOffset/BindBufferBase for transform feedback (3.0, @extension{EXT,transform_feedback}) */ -class MAGNUM_EXPORT Buffer { +class MAGNUM_EXPORT Buffer: public AbstractObject { friend class Context; public: @@ -549,6 +548,32 @@ class MAGNUM_EXPORT Buffer { /** @brief OpenGL buffer ID */ GLuint id() const { return _id; } + /** + * @brief %Buffer label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{BUFFER} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{BUFFER_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set buffer label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{BUFFER} or @fn_gl_extension{LabelObject,EXT,object_label} + * with @def_gl{BUFFER_OBJECT_EXT} + */ + Buffer& setLabel(const std::string& label); + /** @brief Target hint */ Target targetHint() const { return _targetHint; } diff --git a/src/BufferTexture.h b/src/BufferTexture.h index 8d92854de..ac9d37286 100644 --- a/src/BufferTexture.h +++ b/src/BufferTexture.h @@ -207,8 +207,20 @@ class MAGNUM_EXPORT BufferTexture: private AbstractTexture { BufferTexture& operator=(BufferTexture&&) = delete; public: + /** @copydoc AbstractTexture::maxLabelLength() */ + static Int maxLabelLength() { return AbstractTexture::maxLabelLength(); } + explicit BufferTexture(): AbstractTexture(GL_TEXTURE_BUFFER) {} + /** @copydoc AbstractTexture::label() */ + std::string label() const { return AbstractTexture::label(); } + + /** @copydoc AbstractTexture::setLabel() */ + BufferTexture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } + /** @copydoc AbstractTexture::bind() */ void bind(Int layer) { AbstractTexture::bind(layer); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1da7f8738..aa9bc7516 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,6 +48,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/magnumConfigure.h.cmake set(Magnum_SRCS AbstractFramebuffer.cpp AbstractImage.cpp + AbstractObject.cpp AbstractTexture.cpp AbstractShaderProgram.cpp Buffer.cpp @@ -69,6 +70,7 @@ set(Magnum_SRCS Timeline.cpp Implementation/BufferState.cpp + Implementation/DebugState.cpp Implementation/State.cpp Implementation/TextureState.cpp diff --git a/src/Context.cpp b/src/Context.cpp index 97f50eb4a..26b34a719 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -420,7 +420,7 @@ Context::Context() { _current = this; /* Initialize state tracker */ - _state = new Implementation::State; + _state = new Implementation::State(*this); /* Initialize functionality based on current OpenGL version and extensions */ AbstractFramebuffer::initializeContextBasedFunctionality(*this); diff --git a/src/CubeMapTexture.h b/src/CubeMapTexture.h index 1183a5081..f55df5418 100644 --- a/src/CubeMapTexture.h +++ b/src/CubeMapTexture.h @@ -224,6 +224,10 @@ class CubeMapTexture: public AbstractTexture { /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT + CubeMapTexture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); return *this; diff --git a/src/CubeMapTextureArray.h b/src/CubeMapTextureArray.h index c28489c90..4d238cdf9 100644 --- a/src/CubeMapTextureArray.h +++ b/src/CubeMapTextureArray.h @@ -229,6 +229,10 @@ class CubeMapTextureArray: public AbstractTexture { /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT + CubeMapTextureArray& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); return *this; diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index be4eea498..79942aad7 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -31,6 +31,7 @@ #include "Renderbuffer.h" #include "Texture.h" +#include "Implementation/DebugState.h" #include "Implementation/State.h" #include "Implementation/FramebufferState.h" @@ -86,6 +87,15 @@ Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &_id); } +std::string Framebuffer::label() const { + return Context::current()->state().debug->getLabelImplementation(GL_FRAMEBUFFER, _id); +} + +Framebuffer& Framebuffer::setLabel(const std::string& label) { + Context::current()->state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label); + return *this; +} + Framebuffer& Framebuffer::mapForDraw(std::initializer_list> attachments) { /* Max attachment location */ std::size_t max = 0; diff --git a/src/Framebuffer.h b/src/Framebuffer.h index c1c5ebffc..af3c74c48 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -100,7 +100,7 @@ documentation for more information. @requires_gl30 %Extension @extension{ARB,framebuffer_object} */ -class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { +class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObject { friend class Context; public: @@ -304,6 +304,32 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { */ ~Framebuffer(); + /** + * @brief %Framebuffer label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{FRAMEBUFFER} + */ + std::string label() const; + + /** + * @brief Set framebuffer label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or + * @fn_gl_extension{LabelObject,EXT,object_label} with + * @def_gl{FRAMEBUFFER} + */ + Framebuffer& setLabel(const std::string& label); + /** * @brief Check framebuffer status * @param target Target for which check the status diff --git a/src/Implementation/DebugState.cpp b/src/Implementation/DebugState.cpp new file mode 100644 index 000000000..f0c1c1e19 --- /dev/null +++ b/src/Implementation/DebugState.cpp @@ -0,0 +1,46 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "DebugState.h" + +#include "AbstractObject.h" +#include "Context.h" +#include "Extensions.h" + +namespace Magnum { namespace Implementation { + +DebugState::DebugState(Context& context): maxLabelLength(0) { + if(context.isExtensionSupported()) { + getLabelImplementation = &AbstractObject::getLabelImplementationKhr; + labelImplementation = &AbstractObject::labelImplementationKhr; + } else if(context.isExtensionSupported()) { + getLabelImplementation = &AbstractObject::getLabelImplementationExt; + labelImplementation = &AbstractObject::labelImplementationExt; + } else { + getLabelImplementation = &AbstractObject::getLabelImplementationNoOp; + labelImplementation = &AbstractObject::labelImplementationNoOp; + } +} + +}} diff --git a/src/Implementation/DebugState.h b/src/Implementation/DebugState.h new file mode 100644 index 000000000..b6f1b2fae --- /dev/null +++ b/src/Implementation/DebugState.h @@ -0,0 +1,48 @@ +#ifndef Magnum_Implementation_DebugState_h +#define Magnum_Implementation_DebugState_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum.h" +#include "OpenGL.h" + +namespace Magnum { namespace Implementation { + +struct DebugState { + DebugState(Context& context); + + typedef std::string(*GetLabelImplementation)(GLenum, GLuint); + GetLabelImplementation getLabelImplementation; + + typedef void(*LabelImplementation)(GLenum, GLuint, const std::string&); + LabelImplementation labelImplementation; + + GLint maxLabelLength; +}; + +}} + +#endif diff --git a/src/Implementation/State.cpp b/src/Implementation/State.cpp index 7fd1619f8..309aa9d6b 100644 --- a/src/Implementation/State.cpp +++ b/src/Implementation/State.cpp @@ -24,7 +24,10 @@ #include "State.h" +#include "Context.h" +#include "Extensions.h" #include "Implementation/BufferState.h" +#include "Implementation/DebugState.h" #include "Implementation/FramebufferState.h" #include "Implementation/MeshState.h" #include "Implementation/RendererState.h" @@ -34,14 +37,23 @@ namespace Magnum { namespace Implementation { -State::State(): +State::State(Context& context): buffer(new BufferState), + debug(new DebugState(context)), framebuffer(new FramebufferState), mesh(new MeshState), renderer(new RendererState), shader(new ShaderState), shaderProgram(new ShaderProgramState), - texture(new TextureState) {} + texture(new TextureState) { + + Debug() << "Using optional features:"; + + if(context.isExtensionSupported()) + Debug() << " " << Extensions::GL::KHR::debug::string(); + else if(context.isExtensionSupported()) + Debug() << " " << Extensions::GL::EXT::debug_label::string(); +} State::~State() { delete texture; @@ -50,6 +62,7 @@ State::~State() { delete renderer; delete mesh; delete framebuffer; + delete debug; delete buffer; } diff --git a/src/Implementation/State.h b/src/Implementation/State.h index 79b322d76..36570baa3 100644 --- a/src/Implementation/State.h +++ b/src/Implementation/State.h @@ -24,9 +24,12 @@ DEALINGS IN THE SOFTWARE. */ +#include "Magnum.h" + namespace Magnum { namespace Implementation { struct BufferState; +struct DebugState; struct FramebufferState; struct MeshState; struct RendererState; @@ -35,10 +38,13 @@ struct ShaderProgramState; struct TextureState; struct State { - State(); + /* Initializes context-based functionality */ + State(Context& context); + ~State(); BufferState* const buffer; + DebugState* const debug; FramebufferState* const framebuffer; MeshState* const mesh; RendererState* const renderer; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 6aa1e8475..7224c78df 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -29,6 +29,7 @@ #include "Buffer.h" #include "Context.h" #include "Extensions.h" +#include "Implementation/DebugState.h" #include "Implementation/BufferState.h" #include "Implementation/MeshState.h" #include "Implementation/State.h" @@ -137,6 +138,23 @@ Mesh& Mesh::operator=(Mesh&& other) noexcept { return *this; } +std::string Mesh::label() const { + #ifndef MAGNUM_TARGET_GLES + return Context::current()->state().debug->getLabelImplementation(GL_VERTEX_ARRAY, _id); + #else + return Context::current()->state().debug->getLabelImplementation(GL_VERTEX_ARRAY_KHR, _id); + #endif +} + +Mesh& Mesh::setLabel(const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + Context::current()->state().debug->labelImplementation(GL_VERTEX_ARRAY, _id, label); + #else + Context::current()->state().debug->labelImplementation(GL_VERTEX_ARRAY_KHR, _id, label); + #endif + return *this; +} + Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) { #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN) CORRADE_ASSERT(buffer.targetHint() == Buffer::Target::ElementArray, diff --git a/src/Mesh.h b/src/Mesh.h index bc61c2956..a76478a1c 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -307,7 +307,7 @@ drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @todo test vertex specification & drawing @todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ -class MAGNUM_EXPORT Mesh { +class MAGNUM_EXPORT Mesh: public AbstractObject { friend class Context; friend class MeshView; @@ -415,6 +415,32 @@ class MAGNUM_EXPORT Mesh { */ GLuint id() const { return _id; } + /** + * @brief %Mesh label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{VERTEX_ARRAY} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{VERTEX_ARRAY_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set mesh label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{VERTEX_ARRAY} or @fn_gl_extension{LabelObject,EXT,object_label} + * with @def_gl{VERTEX_ARRAY_OBJECT_EXT} + */ + Mesh& setLabel(const std::string& label); + /** * @brief Index size * diff --git a/src/Query.cpp b/src/Query.cpp index 79203c0d7..acebc666b 100644 --- a/src/Query.cpp +++ b/src/Query.cpp @@ -26,6 +26,10 @@ #include +#include "Context.h" +#include "Implementation/DebugState.h" +#include "Implementation/State.h" + namespace Magnum { AbstractQuery::AbstractQuery(): target() { @@ -48,6 +52,23 @@ AbstractQuery::~AbstractQuery() { #endif } +std::string AbstractQuery::label() const { + #ifndef MAGNUM_TARGET_GLES + return Context::current()->state().debug->getLabelImplementation(GL_QUERY, _id); + #else + return Context::current()->state().debug->getLabelImplementation(GL_QUERY_KHR, _id); + #endif +} + +AbstractQuery& AbstractQuery::setLabel(const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + Context::current()->state().debug->labelImplementation(GL_QUERY, _id, label); + #else + Context::current()->state().debug->labelImplementation(GL_QUERY_KHR, _id, label); + #endif + return *this; +} + bool AbstractQuery::resultAvailable() { CORRADE_ASSERT(!target, "AbstractQuery::resultAvailable(): the query is currently running", false); diff --git a/src/Query.h b/src/Query.h index 9e4f8fad0..12922bc65 100644 --- a/src/Query.h +++ b/src/Query.h @@ -30,10 +30,8 @@ #include -#include "OpenGL.h" -#include "Types.h" +#include "AbstractObject.h" #include "magnumConfigure.h" -#include "magnumVisibility.h" namespace Magnum { @@ -45,11 +43,37 @@ information. @todo Support for AMD's query buffer (@extension{AMD,query_buffer_object}) @requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} */ -class MAGNUM_EXPORT AbstractQuery { +class MAGNUM_EXPORT AbstractQuery: public AbstractObject { public: /** @brief OpenGL query ID */ GLuint id() const { return _id; } + /** + * @brief %Query label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{QUERY} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{QUERY_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set query label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{QUERY} or @fn_gl_extension{LabelObject,EXT,object_label} + * with @def_gl{QUERY_OBJECT_EXT} + */ + AbstractQuery& setLabel(const std::string& label); + /** * @brief Whether the result is available * @@ -166,6 +190,14 @@ class PrimitiveQuery: public AbstractQuery { void begin(Target target) { AbstractQuery::begin(GLenum(target)); } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + PrimitiveQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + #endif }; #endif @@ -303,6 +335,14 @@ class SampleQuery: public AbstractQuery { glEndConditionalRender(); } #endif + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + SampleQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + #endif }; /** @@ -370,6 +410,14 @@ class TimeQuery: public AbstractQuery { void begin(Target target) { AbstractQuery::begin(GLenum(target)); } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + TimeQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + #endif }; } diff --git a/src/Renderbuffer.cpp b/src/Renderbuffer.cpp index b97d860e0..10900c100 100644 --- a/src/Renderbuffer.cpp +++ b/src/Renderbuffer.cpp @@ -27,8 +27,9 @@ #include "Context.h" #include "Extensions.h" -#include "Implementation/State.h" +#include "Implementation/DebugState.h" #include "Implementation/FramebufferState.h" +#include "Implementation/State.h" namespace Magnum { @@ -78,6 +79,15 @@ Renderbuffer::~Renderbuffer() { glDeleteRenderbuffers(1, &_id); } +std::string Renderbuffer::label() const { + return Context::current()->state().debug->getLabelImplementation(GL_RENDERBUFFER, _id); +} + +Renderbuffer& Renderbuffer::setLabel(const std::string& label) { + Context::current()->state().debug->labelImplementation(GL_RENDERBUFFER, _id, label); + return *this; +} + void Renderbuffer::bind() { GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding; diff --git a/src/Renderbuffer.h b/src/Renderbuffer.h index 1e11819e4..2f1faf58d 100644 --- a/src/Renderbuffer.h +++ b/src/Renderbuffer.h @@ -28,8 +28,8 @@ * @brief Class Magnum::Renderbuffer */ +#include "AbstractObject.h" #include "Magnum.h" -#include "OpenGL.h" #include "magnumVisibility.h" namespace Magnum { @@ -53,7 +53,7 @@ See its documentation for more information. @requires_gl30 %Extension @extension{ARB,framebuffer_object} */ -class MAGNUM_EXPORT Renderbuffer { +class MAGNUM_EXPORT Renderbuffer: public AbstractObject { friend class Context; Renderbuffer(const Renderbuffer&) = delete; @@ -102,6 +102,32 @@ class MAGNUM_EXPORT Renderbuffer { /** @brief OpenGL internal renderbuffer ID */ GLuint id() const { return _id; } + /** + * @brief %Renderbuffer label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{RENDERBUFFER} + */ + std::string label() const; + + /** + * @brief Set renderbuffer label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} or + * @fn_gl_extension{LabelObject,EXT,object_label} with + * @def_gl{RENDERBUFFER} + */ + Renderbuffer& setLabel(const std::string& label); + /** * @brief Set renderbuffer storage * @param internalFormat Internal format diff --git a/src/Shader.cpp b/src/Shader.cpp index f0e345744..b75c91c16 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -29,6 +29,7 @@ #include #include "Extensions.h" +#include "Implementation/DebugState.h" #include "Implementation/State.h" #include "Implementation/ShaderState.h" @@ -581,6 +582,23 @@ Shader& Shader::operator=(Shader&& other) { return *this; } +std::string Shader::label() const { + #ifndef MAGNUM_TARGET_GLES + return Context::current()->state().debug->getLabelImplementation(GL_SHADER, _id); + #else + return Context::current()->state().debug->getLabelImplementation(GL_SHADER_KHR, _id); + #endif +} + +Shader& Shader::setLabel(const std::string& label) { + #ifndef MAGNUM_TARGET_GLES + Context::current()->state().debug->labelImplementation(GL_SHADER, _id, label); + #else + Context::current()->state().debug->labelImplementation(GL_SHADER_KHR, _id, label); + #endif + return *this; +} + Shader& Shader::addSource(std::string source) { if(!source.empty()) { #if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(__MINGW32__) diff --git a/src/Shader.h b/src/Shader.h index 5bfb732f3..9d20c0c81 100644 --- a/src/Shader.h +++ b/src/Shader.h @@ -31,7 +31,7 @@ #include #include -#include "Magnum.h" +#include "AbstractObject.h" #include "Context.h" #include "magnumVisibility.h" @@ -43,7 +43,7 @@ namespace Magnum { See AbstractShaderProgram for more information. */ -class MAGNUM_EXPORT Shader { +class MAGNUM_EXPORT Shader: public AbstractObject { Shader(const Shader&) = delete; Shader& operator=(const Shader&) = delete; @@ -456,6 +456,32 @@ class MAGNUM_EXPORT Shader { /** @brief OpenGL shader ID */ GLuint id() const { return _id; } + /** + * @brief %Shader label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{SHADER} or + * @fn_gl_extension{GetObjectLabel,EXT,object_label} with + * @def_gl{SHADER_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set shader label + * @return Reference to self (for method chaining) + * + * Default is empty string. If neither @extension{KHR,debug} nor + * @extension{EXT,debug_label} desktop or ES extension is available, + * this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{SHADER} or @fn_gl_extension{LabelObject,EXT,object_label} + * with @def_gl{SHADER_OBJECT_EXT} + */ + Shader& setLabel(const std::string& label); + /** * @brief Add shader source * @param source String with shader source diff --git a/src/Test/AbstractObjectGLTest.cpp b/src/Test/AbstractObjectGLTest.cpp new file mode 100644 index 000000000..fe27d3973 --- /dev/null +++ b/src/Test/AbstractObjectGLTest.cpp @@ -0,0 +1,55 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Buffer.h" +#include "Context.h" +#include "Extensions.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class AbstractObjectGLTest: public AbstractOpenGLTester { + public: + explicit AbstractObjectGLTest(); + + void labelNoOp(); +}; + +AbstractObjectGLTest::AbstractObjectGLTest() { + addTests({&AbstractObjectGLTest::labelNoOp}); +} + +void AbstractObjectGLTest::labelNoOp() { + if(Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::KHR::debug::string() + std::string(" is supported.")); + + Buffer buffer; + buffer.setLabel("MyBuffer"); + CORRADE_COMPARE(buffer.label(), ""); + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::AbstractObjectGLTest) diff --git a/src/Test/AbstractQueryGLTest.cpp b/src/Test/AbstractQueryGLTest.cpp new file mode 100644 index 000000000..b7ecd37bf --- /dev/null +++ b/src/Test/AbstractQueryGLTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Query.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class AbstractQueryGLTest: public AbstractOpenGLTester { + public: + explicit AbstractQueryGLTest(); + + void label(); +}; + +AbstractQueryGLTest::AbstractQueryGLTest() { + addTests({&AbstractQueryGLTest::label}); +} + +void AbstractQueryGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + SampleQuery query; + CORRADE_COMPARE(query.label(), ""); + + query.setLabel("MyQuery"); + CORRADE_COMPARE(query.label(), "MyQuery"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::AbstractQueryGLTest) diff --git a/src/Test/AbstractShaderProgramGLTest.cpp b/src/Test/AbstractShaderProgramGLTest.cpp new file mode 100644 index 000000000..3bb3a7a6b --- /dev/null +++ b/src/Test/AbstractShaderProgramGLTest.cpp @@ -0,0 +1,65 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "AbstractShaderProgram.h" +#include "Context.h" +#include "Extensions.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class AbstractShaderProgramGLTest: public AbstractOpenGLTester { + public: + explicit AbstractShaderProgramGLTest(); + + void label(); +}; + +AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() { + addTests({&AbstractShaderProgramGLTest::label}); +} + +void AbstractShaderProgramGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + class MyShader: public AbstractShaderProgram { + public: + explicit MyShader() {} + }; + + MyShader shader; + CORRADE_COMPARE(shader.label(), ""); + + shader.setLabel("MyShader"); + CORRADE_COMPARE(shader.label(), "MyShader"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::AbstractShaderProgramGLTest) diff --git a/src/Test/AbstractTextureGLTest.cpp b/src/Test/AbstractTextureGLTest.cpp new file mode 100644 index 000000000..fdf8d9539 --- /dev/null +++ b/src/Test/AbstractTextureGLTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Texture.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class AbstractTextureGLTest: public AbstractOpenGLTester { + public: + explicit AbstractTextureGLTest(); + + void label(); +}; + +AbstractTextureGLTest::AbstractTextureGLTest() { + addTests({&AbstractTextureGLTest::label}); +} + +void AbstractTextureGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Texture2D texture; + CORRADE_COMPARE(texture.label(), ""); + + texture.setLabel("MyTexture"); + CORRADE_COMPARE(texture.label(), "MyTexture"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::AbstractTextureGLTest) diff --git a/src/Test/BufferGLTest.cpp b/src/Test/BufferGLTest.cpp index 48029b5a8..f510948c8 100644 --- a/src/Test/BufferGLTest.cpp +++ b/src/Test/BufferGLTest.cpp @@ -38,6 +38,7 @@ class BufferGLTest: public AbstractOpenGLTester { explicit BufferGLTest(); void construct(); + void label(); void data(); void map(); #ifdef MAGNUM_TARGET_GLES2 @@ -55,6 +56,7 @@ class BufferGLTest: public AbstractOpenGLTester { BufferGLTest::BufferGLTest() { addTests({&BufferGLTest::construct, + &BufferGLTest::label, &BufferGLTest::data, &BufferGLTest::map, #ifdef MAGNUM_TARGET_GLES2 @@ -81,6 +83,21 @@ void BufferGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void BufferGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Buffer buffer; + CORRADE_COMPARE(buffer.label(), ""); + + buffer.setLabel("MyBuffer"); + CORRADE_COMPARE(buffer.label(), "MyBuffer"); + + MAGNUM_VERIFY_NO_ERROR(); +} + void BufferGLTest::data() { Buffer buffer; diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 855cd581b..42496328b 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -35,8 +35,16 @@ corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES MagnumTes corrade_add_test(SamplerTest SamplerTest.cpp LIBRARIES Magnum) if(BUILD_GL_TESTS) + corrade_add_test(AbstractObjectGLTest AbstractObjectGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(AbstractQueryGLTest AbstractQueryGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(AbstractShaderProgramGLTest AbstractShaderProgramGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(AbstractTextureGLTest AbstractTextureGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(BufferGLTest BufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(ContextGLTest ContextGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(FramebufferGLTest FramebufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(MeshGLTest MeshGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(RenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(ShaderGLTest ShaderGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) endif() set_target_properties(ResourceManagerTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) diff --git a/src/Test/FramebufferGLTest.cpp b/src/Test/FramebufferGLTest.cpp new file mode 100644 index 000000000..3b3dd7b9e --- /dev/null +++ b/src/Test/FramebufferGLTest.cpp @@ -0,0 +1,62 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Framebuffer.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class FramebufferGLTest: public AbstractOpenGLTester { + public: + explicit FramebufferGLTest(); + + void label(); +}; + +FramebufferGLTest::FramebufferGLTest() { + addTests({&FramebufferGLTest::label}); +} + +void FramebufferGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Framebuffer framebuffer({{}, Vector2i(32)}); + + CORRADE_COMPARE(framebuffer.label(), ""); + MAGNUM_VERIFY_NO_ERROR(); + + framebuffer.setLabel("MyFramebuffer"); + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(framebuffer.label(), "MyFramebuffer"); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::FramebufferGLTest) diff --git a/src/Test/MeshGLTest.cpp b/src/Test/MeshGLTest.cpp new file mode 100644 index 000000000..6efd4dc20 --- /dev/null +++ b/src/Test/MeshGLTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Mesh.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class MeshGLTest: public AbstractOpenGLTester { + public: + explicit MeshGLTest(); + + void label(); +}; + +MeshGLTest::MeshGLTest() { + addTests({&MeshGLTest::label}); +} + +void MeshGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Mesh mesh; + CORRADE_COMPARE(mesh.label(), ""); + + mesh.setLabel("MyMesh"); + CORRADE_COMPARE(mesh.label(), "MyMesh"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) diff --git a/src/Test/RenderbufferGLTest.cpp b/src/Test/RenderbufferGLTest.cpp new file mode 100644 index 000000000..f6cd2862c --- /dev/null +++ b/src/Test/RenderbufferGLTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Renderbuffer.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class RenderbufferGLTest: public AbstractOpenGLTester { + public: + explicit RenderbufferGLTest(); + + void label(); +}; + +RenderbufferGLTest::RenderbufferGLTest() { + addTests({&RenderbufferGLTest::label}); +} + +void RenderbufferGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Renderbuffer renderbuffer; + CORRADE_COMPARE(renderbuffer.label(), ""); + + renderbuffer.setLabel("MyRenderbuffer"); + CORRADE_COMPARE(renderbuffer.label(), "MyRenderbuffer"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::RenderbufferGLTest) diff --git a/src/Test/ShaderGLTest.cpp b/src/Test/ShaderGLTest.cpp new file mode 100644 index 000000000..909f3a03f --- /dev/null +++ b/src/Test/ShaderGLTest.cpp @@ -0,0 +1,60 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Context.h" +#include "Extensions.h" +#include "Shader.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class ShaderGLTest: public AbstractOpenGLTester { + public: + explicit ShaderGLTest(); + + void label(); +}; + +ShaderGLTest::ShaderGLTest() { + addTests({&ShaderGLTest::label}); +} + +void ShaderGLTest::label() { + /* No-Op version is tested in AbstractObjectGLTest */ + if(!Context::current()->isExtensionSupported() && + !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available"); + + Shader shader(Version::GL210, Shader::Type::Vertex); + CORRADE_COMPARE(shader.label(), ""); + + shader.setLabel("MyShader"); + CORRADE_COMPARE(shader.label(), "MyShader"); + + MAGNUM_VERIFY_NO_ERROR(); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::ShaderGLTest) diff --git a/src/Texture.h b/src/Texture.h index 6ed901b4d..e94a60a3a 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -423,6 +423,10 @@ template class Texture: public AbstractTexture { /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT + Texture& setLabel(const std::string& label) { + AbstractTexture::setLabel(label); + return *this; + } Texture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); return *this;