diff --git a/src/Query.cpp b/src/Query.cpp index acebc666b..c98178168 100644 --- a/src/Query.cpp +++ b/src/Query.cpp @@ -43,6 +43,9 @@ AbstractQuery::AbstractQuery(): target() { } AbstractQuery::~AbstractQuery() { + /* Moved out, nothing to do */ + if(!_id) return; + /** @todo Get some extension wrangler instead to avoid undeclared glGenQueries() on ES2 */ #ifndef MAGNUM_TARGET_GLES2 glDeleteQueries(1, &_id); diff --git a/src/Query.h b/src/Query.h index 8ac079f13..e268f17df 100644 --- a/src/Query.h +++ b/src/Query.h @@ -45,6 +45,18 @@ information. */ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { public: + /** @brief Copying is not allowed */ + AbstractQuery(const AbstractQuery&) = delete; + + /** @brief Move constructor */ + AbstractQuery(AbstractQuery&& other) noexcept; + + /** @brief Copying is not allowed */ + AbstractQuery& operator=(const AbstractQuery&) = delete; + + /** @brief Move assignment */ + AbstractQuery& operator=(AbstractQuery&& other) noexcept; + /** @brief OpenGL query ID */ GLuint id() const { return _id; } @@ -420,6 +432,17 @@ class TimeQuery: public AbstractQuery { #endif }; + +inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), target(other.target) { + other._id = 0; +} + +inline AbstractQuery& AbstractQuery::operator=(AbstractQuery&& other) noexcept { + std::swap(_id, other._id); + std::swap(target, other.target); + return *this; +} + } #endif diff --git a/src/Test/AbstractQueryGLTest.cpp b/src/Test/AbstractQueryGLTest.cpp index b7ecd37bf..5060f9df9 100644 --- a/src/Test/AbstractQueryGLTest.cpp +++ b/src/Test/AbstractQueryGLTest.cpp @@ -33,14 +33,75 @@ class AbstractQueryGLTest: public AbstractOpenGLTester { public: explicit AbstractQueryGLTest(); + void construct(); + void constructCopy(); + void constructMove(); + void label(); }; AbstractQueryGLTest::AbstractQueryGLTest() { - addTests({&AbstractQueryGLTest::label}); + addTests({&AbstractQueryGLTest::construct, + &AbstractQueryGLTest::constructCopy, + &AbstractQueryGLTest::constructMove, + + &AbstractQueryGLTest::label}); +} + +void AbstractQueryGLTest::construct() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + #endif + + { + const SampleQuery query; + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(query.id() > 0); + } + + MAGNUM_VERIFY_NO_ERROR(); +} + +void AbstractQueryGLTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void AbstractQueryGLTest::constructMove() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + #endif + + SampleQuery a; + const Int id = a.id(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(id > 0); + + SampleQuery b(std::move(a)); + + CORRADE_COMPARE(a.id(), 0); + CORRADE_COMPARE(b.id(), id); + + SampleQuery c; + const Int cId = c.id(); + c = std::move(b); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(cId > 0); + CORRADE_COMPARE(b.id(), cId); + CORRADE_COMPARE(c.id(), id); } void AbstractQueryGLTest::label() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + #endif + /* No-Op version is tested in AbstractObjectGLTest */ if(!Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported())