diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp index 51686aa7f..23e3375b1 100644 --- a/include/SFML/Graphics/Shape.hpp +++ b/include/SFML/Graphics/Shape.hpp @@ -46,12 +46,6 @@ class Texture; class SFML_GRAPHICS_API Shape : public Drawable, public Transformable { public: - //////////////////////////////////////////////////////////// - /// \brief Virtual destructor - /// - //////////////////////////////////////////////////////////// - ~Shape() override; - //////////////////////////////////////////////////////////// /// \brief Change the source texture of the shape /// diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index ea387875c..1ecc1e716 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -518,7 +518,7 @@ public: /// \param right Instance to swap with /// //////////////////////////////////////////////////////////// - void swap(Texture& right); + void swap(Texture& right) noexcept; //////////////////////////////////////////////////////////// /// \brief Get the underlying OpenGL handle of the texture. @@ -621,6 +621,15 @@ private: std::uint64_t m_cacheId; //!< Unique number that identifies the texture to the render target's cache }; +//////////////////////////////////////////////////////////// +/// \brief Swap the contents of one texture with those of another +/// +/// \param left First instance to swap +/// \param right Second instance to swap +/// +//////////////////////////////////////////////////////////// +void swap(Texture& left, Texture& right) noexcept; + } // namespace sf diff --git a/include/SFML/Graphics/VertexBuffer.hpp b/include/SFML/Graphics/VertexBuffer.hpp index 0e8459814..a76a4098c 100644 --- a/include/SFML/Graphics/VertexBuffer.hpp +++ b/include/SFML/Graphics/VertexBuffer.hpp @@ -224,7 +224,7 @@ public: /// \param right Instance to swap with /// //////////////////////////////////////////////////////////// - void swap(VertexBuffer& right); + void swap(VertexBuffer& right) noexcept; //////////////////////////////////////////////////////////// /// \brief Get the underlying OpenGL handle of the vertex buffer. @@ -338,6 +338,15 @@ private: Usage m_usage{Stream}; //!< How this vertex buffer is to be used }; +//////////////////////////////////////////////////////////// +/// \brief Swap the contents of one vertex buffer with those of another +/// +/// \param left First instance to swap +/// \param right Second instance to swap +/// +//////////////////////////////////////////////////////////// +void swap(VertexBuffer& left, VertexBuffer& right) noexcept; + } // namespace sf diff --git a/src/SFML/Graphics/CMakeLists.txt b/src/SFML/Graphics/CMakeLists.txt index e595331aa..a72408b32 100644 --- a/src/SFML/Graphics/CMakeLists.txt +++ b/src/SFML/Graphics/CMakeLists.txt @@ -126,6 +126,17 @@ endif() sfml_find_package(Freetype INCLUDE "FREETYPE_INCLUDE_DIRS" LINK "FREETYPE_LIBRARY") target_link_libraries(sfml-graphics PRIVATE Freetype) +# on some platforms (e.g. Raspberry Pi 3 armhf), GCC requires linking libatomic to use features +# that aren't supported by native CPU instructions (64-bit atomic operations on 32-bit architecture) +if(SFML_COMPILER_GCC) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles("#include + int main(){std::atomic_ullong x(1); return x.fetch_add(1);}" ATOMIC_TEST) + if(NOT ATOMIC_TEST) + target_link_libraries(sfml-graphics PRIVATE atomic) + endif() +endif() + # add preprocessor symbols target_compile_definitions(sfml-graphics PRIVATE "STBI_FAILURE_USERMSG") diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp index 94c99cd1f..749071bcd 100644 --- a/src/SFML/Graphics/Shape.cpp +++ b/src/SFML/Graphics/Shape.cpp @@ -48,10 +48,6 @@ sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2) namespace sf { -//////////////////////////////////////////////////////////// -Shape::~Shape() = default; - - //////////////////////////////////////////////////////////// void Shape::setTexture(const Texture* texture, bool resetRect) { diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 5cc113eff..ed1346015 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -33,10 +33,10 @@ #include #include +#include #include #include #include -#include #include @@ -45,18 +45,13 @@ namespace // A nested named namespace is used here to allow unity builds of SFML. namespace TextureImpl { -std::recursive_mutex idMutex; -std::recursive_mutex maximumSizeMutex; - // Thread-safe unique identifier generator, // is used for states cache (see RenderTarget) -std::uint64_t getUniqueId() +std::uint64_t getUniqueId() noexcept { - std::lock_guard lock(idMutex); + static std::atomic id(1); // start at 1, zero is "no texture" - static std::uint64_t id = 1; // start at 1, zero is "no texture" - - return id++; + return id.fetch_add(1); } } // namespace TextureImpl } // namespace @@ -832,21 +827,18 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType) //////////////////////////////////////////////////////////// unsigned int Texture::getMaximumSize() { - std::lock_guard lock(TextureImpl::maximumSizeMutex); - - static bool checked = false; - static GLint size = 0; - - if (!checked) + static const unsigned int size = []() { - checked = true; - TransientContextLock transientLock; - glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size)); - } + GLint value = 0; - return static_cast(size); + glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value)); + + return static_cast(value); + }(); + + return size; } @@ -862,7 +854,7 @@ Texture& Texture::operator=(const Texture& right) //////////////////////////////////////////////////////////// -void Texture::swap(Texture& right) +void Texture::swap(Texture& right) noexcept { std::swap(m_size, right.m_size); std::swap(m_actualSize, right.m_actualSize); @@ -905,4 +897,11 @@ unsigned int Texture::getValidSize(unsigned int size) } } + +//////////////////////////////////////////////////////////// +void swap(Texture& left, Texture& right) noexcept +{ + left.swap(right); +} + } // namespace sf diff --git a/src/SFML/Graphics/VertexBuffer.cpp b/src/SFML/Graphics/VertexBuffer.cpp index ccc4fbe81..8d3cd5c65 100644 --- a/src/SFML/Graphics/VertexBuffer.cpp +++ b/src/SFML/Graphics/VertexBuffer.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include @@ -42,8 +41,6 @@ namespace // A nested named namespace is used here to allow unity builds of SFML. namespace VertexBufferImpl { -std::recursive_mutex isAvailableMutex; - GLenum usageToGlEnum(sf::VertexBuffer::Usage usage) { switch (usage) @@ -274,7 +271,7 @@ VertexBuffer& VertexBuffer::operator=(const VertexBuffer& right) //////////////////////////////////////////////////////////// -void VertexBuffer::swap(VertexBuffer& right) +void VertexBuffer::swap(VertexBuffer& right) noexcept { std::swap(m_size, right.m_size); std::swap(m_buffer, right.m_buffer); @@ -333,22 +330,15 @@ VertexBuffer::Usage VertexBuffer::getUsage() const //////////////////////////////////////////////////////////// bool VertexBuffer::isAvailable() { - std::lock_guard lock(VertexBufferImpl::isAvailableMutex); - - static bool checked = false; - static bool available = false; - - if (!checked) + static const bool available = []() -> bool { - checked = true; - TransientContextLock contextLock; // Make sure that extensions are initialized sf::priv::ensureExtensionsInit(); - available = GLEXT_vertex_buffer_object; - } + return GLEXT_vertex_buffer_object; + }(); return available; } @@ -361,4 +351,11 @@ void VertexBuffer::draw(RenderTarget& target, const RenderStates& states) const target.draw(*this, 0, m_size, states); } + +//////////////////////////////////////////////////////////// +void swap(VertexBuffer& left, VertexBuffer& right) noexcept +{ + left.swap(right); +} + } // namespace sf diff --git a/test/Graphics/CircleShape.test.cpp b/test/Graphics/CircleShape.test.cpp index 3f766126f..20b225afa 100644 --- a/test/Graphics/CircleShape.test.cpp +++ b/test/Graphics/CircleShape.test.cpp @@ -7,8 +7,8 @@ static_assert(std::is_copy_constructible_v); static_assert(std::is_copy_assignable_v); -static_assert(std::is_move_constructible_v); -static_assert(std::is_move_assignable_v); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_assignable_v); TEST_CASE("[Graphics] sf::CircleShape") { diff --git a/test/Graphics/ConvexShape.test.cpp b/test/Graphics/ConvexShape.test.cpp index 04e7cbb9c..29329c96d 100644 --- a/test/Graphics/ConvexShape.test.cpp +++ b/test/Graphics/ConvexShape.test.cpp @@ -7,8 +7,8 @@ static_assert(std::is_copy_constructible_v); static_assert(std::is_copy_assignable_v); -static_assert(std::is_move_constructible_v); -static_assert(std::is_move_assignable_v); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_assignable_v); TEST_CASE("[Graphics] sf::ConvexShape") { diff --git a/test/Graphics/RectangleShape.test.cpp b/test/Graphics/RectangleShape.test.cpp index 0a49d23a4..9fe3ebe1c 100644 --- a/test/Graphics/RectangleShape.test.cpp +++ b/test/Graphics/RectangleShape.test.cpp @@ -7,8 +7,8 @@ static_assert(std::is_copy_constructible_v); static_assert(std::is_copy_assignable_v); -static_assert(std::is_move_constructible_v); -static_assert(std::is_move_assignable_v); +static_assert(std::is_nothrow_move_constructible_v); +static_assert(std::is_nothrow_move_assignable_v); TEST_CASE("[Graphics] sf::RectangleShape") { diff --git a/test/Graphics/Shape.test.cpp b/test/Graphics/Shape.test.cpp index 411426280..495f8445d 100644 --- a/test/Graphics/Shape.test.cpp +++ b/test/Graphics/Shape.test.cpp @@ -9,7 +9,8 @@ static_assert(!std::is_constructible_v); static_assert(!std::is_copy_constructible_v); static_assert(std::is_copy_assignable_v); static_assert(!std::is_move_constructible_v); -static_assert(std::is_move_assignable_v); +static_assert(std::is_nothrow_move_assignable_v); +static_assert(std::has_virtual_destructor_v); class TriangleShape : public sf::Shape { diff --git a/test/Graphics/Texture.test.cpp b/test/Graphics/Texture.test.cpp index 20ac4aef2..729aebe66 100644 --- a/test/Graphics/Texture.test.cpp +++ b/test/Graphics/Texture.test.cpp @@ -11,6 +11,7 @@ static_assert(std::is_move_constructible_v); static_assert(!std::is_nothrow_move_constructible_v); static_assert(std::is_move_assignable_v); static_assert(!std::is_nothrow_move_assignable_v); +static_assert(std::is_nothrow_swappable_v); TEST_CASE("[Graphics] sf::Texture" * doctest::skip(skipDisplayTests)) { diff --git a/test/Graphics/VertexBuffer.test.cpp b/test/Graphics/VertexBuffer.test.cpp index 63f20dbf0..2d3521427 100644 --- a/test/Graphics/VertexBuffer.test.cpp +++ b/test/Graphics/VertexBuffer.test.cpp @@ -15,6 +15,7 @@ static_assert(std::is_move_constructible_v); static_assert(!std::is_nothrow_move_constructible_v); static_assert(std::is_move_assignable_v); static_assert(!std::is_nothrow_move_assignable_v); +static_assert(std::is_nothrow_swappable_v); // Skip these tests because they produce flakey failures in CI when using xvfb-run TEST_CASE("[Graphics] sf::VertexBuffer" * doctest::skip(true)) @@ -148,7 +149,7 @@ TEST_CASE("[Graphics] sf::VertexBuffer" * doctest::skip(true)) sf::VertexBuffer vertexBuffer2(sf::PrimitiveType::TriangleStrip, sf::VertexBuffer::Stream); CHECK(vertexBuffer2.create(60)); - vertexBuffer1.swap(vertexBuffer2); + std::swap(vertexBuffer1, vertexBuffer2); CHECK(vertexBuffer1.getVertexCount() == 60); CHECK(vertexBuffer1.getNativeHandle() != 0);