Make moving Shapes, swapping Textures and swapping VertexBuffers noexcept.

This commit is contained in:
binary1248 2023-03-05 14:03:27 +01:00 committed by Chris Thrasher
parent 66bec29aff
commit f4e0c4b4c0
13 changed files with 73 additions and 55 deletions

View File

@ -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
///

View File

@ -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

View File

@ -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

View File

@ -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 <atomic> 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 <atomic>
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")

View File

@ -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)
{

View File

@ -33,10 +33,10 @@
#include <SFML/Window/Context.hpp>
#include <SFML/Window/Window.hpp>
#include <atomic>
#include <cassert>
#include <climits>
#include <cstring>
#include <mutex>
#include <ostream>
@ -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<std::uint64_t> 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<unsigned int>(size);
glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value));
return static_cast<unsigned int>(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

View File

@ -33,7 +33,6 @@
#include <cstddef>
#include <cstring>
#include <mutex>
#include <ostream>
#include <utility>
@ -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

View File

@ -7,8 +7,8 @@
static_assert(std::is_copy_constructible_v<sf::CircleShape>);
static_assert(std::is_copy_assignable_v<sf::CircleShape>);
static_assert(std::is_move_constructible_v<sf::CircleShape>);
static_assert(std::is_move_assignable_v<sf::CircleShape>);
static_assert(std::is_nothrow_move_constructible_v<sf::CircleShape>);
static_assert(std::is_nothrow_move_assignable_v<sf::CircleShape>);
TEST_CASE("[Graphics] sf::CircleShape")
{

View File

@ -7,8 +7,8 @@
static_assert(std::is_copy_constructible_v<sf::ConvexShape>);
static_assert(std::is_copy_assignable_v<sf::ConvexShape>);
static_assert(std::is_move_constructible_v<sf::ConvexShape>);
static_assert(std::is_move_assignable_v<sf::ConvexShape>);
static_assert(std::is_nothrow_move_constructible_v<sf::ConvexShape>);
static_assert(std::is_nothrow_move_assignable_v<sf::ConvexShape>);
TEST_CASE("[Graphics] sf::ConvexShape")
{

View File

@ -7,8 +7,8 @@
static_assert(std::is_copy_constructible_v<sf::RectangleShape>);
static_assert(std::is_copy_assignable_v<sf::RectangleShape>);
static_assert(std::is_move_constructible_v<sf::RectangleShape>);
static_assert(std::is_move_assignable_v<sf::RectangleShape>);
static_assert(std::is_nothrow_move_constructible_v<sf::RectangleShape>);
static_assert(std::is_nothrow_move_assignable_v<sf::RectangleShape>);
TEST_CASE("[Graphics] sf::RectangleShape")
{

View File

@ -9,7 +9,8 @@ static_assert(!std::is_constructible_v<sf::Shape>);
static_assert(!std::is_copy_constructible_v<sf::Shape>);
static_assert(std::is_copy_assignable_v<sf::Shape>);
static_assert(!std::is_move_constructible_v<sf::Shape>);
static_assert(std::is_move_assignable_v<sf::Shape>);
static_assert(std::is_nothrow_move_assignable_v<sf::Shape>);
static_assert(std::has_virtual_destructor_v<sf::Shape>);
class TriangleShape : public sf::Shape
{

View File

@ -11,6 +11,7 @@ static_assert(std::is_move_constructible_v<sf::Texture>);
static_assert(!std::is_nothrow_move_constructible_v<sf::Texture>);
static_assert(std::is_move_assignable_v<sf::Texture>);
static_assert(!std::is_nothrow_move_assignable_v<sf::Texture>);
static_assert(std::is_nothrow_swappable_v<sf::Texture>);
TEST_CASE("[Graphics] sf::Texture" * doctest::skip(skipDisplayTests))
{

View File

@ -15,6 +15,7 @@ static_assert(std::is_move_constructible_v<sf::VertexBuffer>);
static_assert(!std::is_nothrow_move_constructible_v<sf::VertexBuffer>);
static_assert(std::is_move_assignable_v<sf::VertexBuffer>);
static_assert(!std::is_nothrow_move_assignable_v<sf::VertexBuffer>);
static_assert(std::is_nothrow_swappable_v<sf::VertexBuffer>);
// 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);