diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index 1096d2ae7..151dc8d18 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -182,9 +182,6 @@ public: bool onLoad() override { - // Create the off-screen surface - if (!m_surface.create({800, 600})) - return false; m_surface.setSmooth(true); // Load the textures @@ -242,7 +239,7 @@ public: } private: - sf::RenderTexture m_surface; + sf::RenderTexture m_surface{sf::RenderTexture::create({800, 600}).value()}; sf::Texture m_backgroundTexture; sf::Texture m_entityTexture; std::optional m_backgroundSprite; diff --git a/include/SFML/Graphics/RenderTexture.hpp b/include/SFML/Graphics/RenderTexture.hpp index 7487011f5..e5c6fc07e 100644 --- a/include/SFML/Graphics/RenderTexture.hpp +++ b/include/SFML/Graphics/RenderTexture.hpp @@ -37,6 +37,7 @@ #include #include +#include namespace sf @@ -53,17 +54,6 @@ class RenderTextureImpl; class SFML_GRAPHICS_API RenderTexture : public RenderTarget { public: - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Constructs an empty, invalid render-texture. You must - /// call create to have a valid render-texture. - /// - /// \see create - /// - //////////////////////////////////////////////////////////// - RenderTexture(); - //////////////////////////////////////////////////////////// /// \brief Destructor /// @@ -97,10 +87,6 @@ public: //////////////////////////////////////////////////////////// /// \brief Create the render-texture /// - /// Before calling this function, the render-texture is in - /// an invalid state, thus it is mandatory to call it before - /// doing anything with the render-texture. - /// /// The last parameter, \a settings, is useful if you want to enable /// multi-sampling or use the render-texture for OpenGL rendering that /// requires a depth or stencil buffer. Otherwise it is unnecessary, and @@ -112,10 +98,11 @@ public: /// \param size Width and height of the render-texture /// \param settings Additional settings for the underlying OpenGL texture and context /// - /// \return True if creation has been successful + /// \return Render texture if creation has been successful, otherwise `std::nullopt` /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool create(const Vector2u& size, const ContextSettings& settings = ContextSettings()); + [[nodiscard]] static std::optional create(const Vector2u& size, + const ContextSettings& settings = ContextSettings()); //////////////////////////////////////////////////////////// /// \brief Get the maximum anti-aliasing level supported by the system @@ -226,7 +213,6 @@ public: //////////////////////////////////////////////////////////// Vector2u getSize() const override; - //////////////////////////////////////////////////////////// /// \brief Tell if the render-texture will use sRGB encoding when drawing on it /// @@ -255,6 +241,12 @@ public: const Texture& getTexture() const; private: + //////////////////////////////////////////////////////////// + /// \brief Construct from texture + /// + //////////////////////////////////////////////////////////// + explicit RenderTexture(Texture&& texture); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// @@ -288,9 +280,7 @@ private: /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); /// /// // Create a new render-texture -/// sf::RenderTexture texture; -/// if (!texture.create({500, 500})) -/// return -1; +/// auto texture = sf::RenderTexture::create({500, 500}).value(); /// /// // The main loop /// while (window.isOpen()) diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp index 488a957a8..7bb47fe26 100644 --- a/src/SFML/Graphics/RenderTexture.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -34,15 +34,9 @@ #include #include -#include - namespace sf { -//////////////////////////////////////////////////////////// -RenderTexture::RenderTexture() = default; - - //////////////////////////////////////////////////////////// RenderTexture::~RenderTexture() = default; @@ -56,45 +50,49 @@ RenderTexture& RenderTexture::operator=(RenderTexture&&) noexcept = default; //////////////////////////////////////////////////////////// -bool RenderTexture::create(const Vector2u& size, const ContextSettings& settings) +std::optional RenderTexture::create(const Vector2u& size, const ContextSettings& settings) { + sf::Texture texture; + // Set texture to be in sRGB scale if requested - m_texture.setSrgb(settings.sRgbCapable); + texture.setSrgb(settings.sRgbCapable); // Create the texture - if (!m_texture.create(size)) + if (!texture.create(size)) { err() << "Impossible to create render texture (failed to create the target texture)" << std::endl; - return false; + return std::nullopt; } + RenderTexture renderTexture(std::move(texture)); + // We disable smoothing by default for render textures - setSmooth(false); + renderTexture.setSmooth(false); // Create the implementation if (priv::RenderTextureImplFBO::isAvailable()) { // Use frame-buffer object (FBO) - m_impl = std::make_unique(); + renderTexture.m_impl = std::make_unique(); // Mark the texture as being a framebuffer object attachment - m_texture.m_fboAttachment = true; + renderTexture.m_texture.m_fboAttachment = true; } else { // Use default implementation - m_impl = std::make_unique(); + renderTexture.m_impl = std::make_unique(); } // Initialize the render texture // We pass the actual size of our texture since OpenGL ES requires that all attachments have identical sizes - if (!m_impl->create(m_texture.m_actualSize, m_texture.m_texture, settings)) - return false; + if (!renderTexture.m_impl->create(renderTexture.m_texture.m_actualSize, renderTexture.m_texture.m_texture, settings)) + return std::nullopt; // We can now initialize the render target part - RenderTarget::initialize(); + renderTexture.initialize(); - return true; + return renderTexture; } @@ -151,7 +149,7 @@ bool RenderTexture::generateMipmap() bool RenderTexture::setActive(bool active) { // Update RenderTarget tracking - if (m_impl && m_impl->activate(active)) + if (m_impl->activate(active)) return RenderTarget::setActive(active); return false; @@ -161,26 +159,23 @@ bool RenderTexture::setActive(bool active) //////////////////////////////////////////////////////////// void RenderTexture::display() { - if (m_impl) + if (priv::RenderTextureImplFBO::isAvailable()) { - if (priv::RenderTextureImplFBO::isAvailable()) - { - // Perform a RenderTarget-only activation if we are using FBOs - if (!RenderTarget::setActive()) - return; - } - else - { - // Perform a full activation if we are not using FBOs - if (!setActive()) - return; - } - - // Update the target texture - m_impl->updateTexture(m_texture.m_texture); - m_texture.m_pixelsFlipped = true; - m_texture.invalidateMipmap(); + // Perform a RenderTarget-only activation if we are using FBOs + if (!RenderTarget::setActive()) + return; } + else + { + // Perform a full activation if we are not using FBOs + if (!setActive()) + return; + } + + // Update the target texture + m_impl->updateTexture(m_texture.m_texture); + m_texture.m_pixelsFlipped = true; + m_texture.invalidateMipmap(); } @@ -194,7 +189,6 @@ Vector2u RenderTexture::getSize() const //////////////////////////////////////////////////////////// bool RenderTexture::isSrgb() const { - assert(m_impl && "Must call RenderTexture::create first"); return m_impl->isSrgb(); } @@ -205,4 +199,11 @@ const Texture& RenderTexture::getTexture() const return m_texture; } + +//////////////////////////////////////////////////////////// +RenderTexture::RenderTexture(Texture&& texture) : m_texture(std::move(texture)) +{ +} + + } // namespace sf diff --git a/test/Graphics/Drawable.test.cpp b/test/Graphics/Drawable.test.cpp index 8e1372a61..3dafc19ca 100644 --- a/test/Graphics/Drawable.test.cpp +++ b/test/Graphics/Drawable.test.cpp @@ -46,8 +46,7 @@ TEST_CASE("[Graphics] sf::Drawable", runDisplayTests()) SECTION("draw()") { const DrawableTest drawableTest; - sf::RenderTexture renderTexture; - CHECK(renderTexture.create({32, 32})); + auto renderTexture = sf::RenderTexture::create({32, 32}).value(); CHECK(drawableTest.callCount() == 0); renderTexture.draw(drawableTest); CHECK(drawableTest.callCount() == 1); diff --git a/test/Graphics/Render.test.cpp b/test/Graphics/Render.test.cpp index eac9860fb..c6c1e64c8 100644 --- a/test/Graphics/Render.test.cpp +++ b/test/Graphics/Render.test.cpp @@ -12,8 +12,7 @@ TEST_CASE("[Graphics] Render Tests", runDisplayTests()) { SECTION("Stencil Tests") { - sf::RenderTexture renderTexture; - REQUIRE(renderTexture.create({100, 100}, sf::ContextSettings(0, 8)) == true); + auto renderTexture = sf::RenderTexture::create({100, 100}, sf::ContextSettings(0, 8)).value(); renderTexture.clear(sf::Color::Red, 127); sf::RectangleShape shape1({100, 100}); diff --git a/test/Graphics/RenderTexture.test.cpp b/test/Graphics/RenderTexture.test.cpp index 6d37448c8..8d47a8b74 100644 --- a/test/Graphics/RenderTexture.test.cpp +++ b/test/Graphics/RenderTexture.test.cpp @@ -9,33 +9,31 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests()) { SECTION("Type traits") { + STATIC_CHECK(!std::is_default_constructible_v); STATIC_CHECK(!std::is_copy_constructible_v); STATIC_CHECK(!std::is_copy_assignable_v); STATIC_CHECK(std::is_nothrow_move_constructible_v); STATIC_CHECK(std::is_nothrow_move_assignable_v); } - SECTION("Construction") - { - const sf::RenderTexture renderTexture; - CHECK(!renderTexture.isSmooth()); - CHECK(!renderTexture.isRepeated()); - CHECK(renderTexture.getSize() == sf::Vector2u(0, 0)); - } - SECTION("create()") { - sf::RenderTexture renderTexture; - CHECK(!renderTexture.create({1'000'000, 1'000'000})); - CHECK(renderTexture.create({480, 360})); + CHECK(!sf::RenderTexture::create({1'000'000, 1'000'000})); + + CHECK(sf::RenderTexture::create({100, 100}, sf::ContextSettings(8, 0))); + CHECK(sf::RenderTexture::create({100, 100}, sf::ContextSettings(0, 8))); + + const auto renderTexture = sf::RenderTexture::create({360, 480}).value(); + CHECK(renderTexture.getSize() == sf::Vector2u(360, 480)); CHECK(!renderTexture.isSmooth()); CHECK(!renderTexture.isRepeated()); - CHECK(renderTexture.getSize() == sf::Vector2u(480, 360)); CHECK(!renderTexture.isSrgb()); - CHECK(renderTexture.create({360, 480})); - CHECK(renderTexture.getSize() == sf::Vector2u(360, 480)); - CHECK(renderTexture.create({100, 100}, sf::ContextSettings(8, 0))); - CHECK(renderTexture.create({100, 100}, sf::ContextSettings(0, 8))); + const auto& texture = renderTexture.getTexture(); + CHECK(texture.getSize() == sf::Vector2u(360, 480)); + CHECK(!texture.isSmooth()); + CHECK(!texture.isSrgb()); + CHECK(!texture.isRepeated()); + CHECK(texture.getNativeHandle() != 0); } SECTION("getMaximumAntialiasingLevel()") @@ -45,39 +43,35 @@ TEST_CASE("[Graphics] sf::RenderTexture", runDisplayTests()) SECTION("Set/get smooth") { - sf::RenderTexture renderTexture; + auto renderTexture = sf::RenderTexture::create({64, 64}).value(); renderTexture.setSmooth(true); CHECK(renderTexture.isSmooth()); } SECTION("Set/get repeated") { - sf::RenderTexture renderTexture; + auto renderTexture = sf::RenderTexture::create({64, 64}).value(); renderTexture.setRepeated(true); CHECK(renderTexture.isRepeated()); } SECTION("generateMipmap()") { - sf::RenderTexture renderTexture; - CHECK(!renderTexture.generateMipmap()); - CHECK(renderTexture.create({480, 360})); + auto renderTexture = sf::RenderTexture::create({64, 64}).value(); CHECK(renderTexture.generateMipmap()); } SECTION("setActive()") { - sf::RenderTexture renderTexture; - CHECK(!renderTexture.setActive()); - CHECK(renderTexture.create({480, 360})); + auto renderTexture = sf::RenderTexture::create({64, 64}).value(); CHECK(renderTexture.setActive()); + CHECK(renderTexture.setActive(false)); + CHECK(renderTexture.setActive(true)); } SECTION("getTexture()") { - sf::RenderTexture renderTexture; - CHECK(renderTexture.getTexture().getSize() == sf::Vector2u(0, 0)); - CHECK(renderTexture.create({480, 360})); - CHECK(renderTexture.getTexture().getSize() == sf::Vector2u(480, 360)); + const auto renderTexture = sf::RenderTexture::create({64, 64}).value(); + CHECK(renderTexture.getTexture().getSize() == sf::Vector2u(64, 64)); } }