Remove default empty state of sf::Texture

This commit is contained in:
Chris Thrasher 2024-05-23 23:05:13 -06:00
parent 24dc6b5ea9
commit bfd65989e9
22 changed files with 214 additions and 298 deletions

View File

@ -21,9 +21,7 @@
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window"); /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML window");
/// ///
/// // Load a sprite to display /// // Load a sprite to display
/// sf::Texture texture; /// const auto texture = sf::Texture::loadFromFile("cute_image.jpg").value();
/// if (!texture.loadFromFile("cute_image.jpg"))
/// return EXIT_FAILURE;
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);
/// ///
/// // Create a graphical text to display /// // Create a graphical text to display

View File

@ -86,9 +86,7 @@ int main(int argc, char* argv[])
sf::RenderWindow window(screen, ""); sf::RenderWindow window(screen, "");
window.setFramerateLimit(30); window.setFramerateLimit(30);
sf::Texture texture; const auto texture = sf::Texture::loadFromFile("image.png").value();
if (!texture.loadFromFile("image.png"))
return EXIT_FAILURE;
sf::Sprite image(texture); sf::Sprite image(texture);
image.setPosition(sf::Vector2f(screen.size) / 2.f); image.setPosition(sf::Vector2f(screen.size) / 2.f);

View File

@ -41,9 +41,6 @@ struct SFMLmainWindow
{ {
SFMLmainWindow(sf::WindowHandle win) : renderWindow(win) SFMLmainWindow(sf::WindowHandle win) : renderWindow(win)
{ {
if (!logo.loadFromFile(resPath / "logo.png"))
NSLog(@"Couldn't load the logo image");
logo.setSmooth(true); logo.setSmooth(true);
sprite.setOrigin(sprite.getLocalBounds().getCenter()); sprite.setOrigin(sprite.getLocalBounds().getCenter());
@ -57,7 +54,7 @@ struct SFMLmainWindow
sf::RenderWindow renderWindow; sf::RenderWindow renderWindow;
sf::Font font{sf::Font::loadFromFile(resPath / "tuffy.ttf").value()}; sf::Font font{sf::Font::loadFromFile(resPath / "tuffy.ttf").value()};
sf::Text text{font}; sf::Text text{font};
sf::Texture logo; sf::Texture logo{sf::Texture::loadFromFile(resPath / "logo.png").value()};
sf::Sprite sprite{logo}; sf::Sprite sprite{logo};
sf::Color background{sf::Color::Blue}; sf::Color background{sf::Color::Blue};
}; };

View File

@ -58,10 +58,7 @@ int main()
window.setMaximumSize(sf::Vector2u(1200, 900)); window.setMaximumSize(sf::Vector2u(1200, 900));
// Create a sprite for the background // Create a sprite for the background
sf::Texture backgroundTexture; const auto backgroundTexture = sf::Texture::loadFromFile(resourcesDir() / "background.jpg", sRgb).value();
backgroundTexture.setSrgb(sRgb);
if (!backgroundTexture.loadFromFile(resourcesDir() / "background.jpg"))
return EXIT_FAILURE;
const sf::Sprite background(backgroundTexture); const sf::Sprite background(backgroundTexture);
// Create some text to draw on top of our OpenGL object // Create some text to draw on top of our OpenGL object
@ -78,9 +75,7 @@ int main()
mipmapInstructions.setPosition({200.f, 550.f}); mipmapInstructions.setPosition({200.f, 550.f});
// Load a texture to apply to our 3D cube // Load a texture to apply to our 3D cube
sf::Texture texture; auto texture = sf::Texture::loadFromFile(resourcesDir() / "logo.png").value();
if (!texture.loadFromFile(resourcesDir() / "logo.png"))
return EXIT_FAILURE;
// Attempt to generate a mipmap for our cube texture // Attempt to generate a mipmap for our cube texture
// We don't check the return value here since // We don't check the return value here since
@ -230,8 +225,7 @@ int main()
if (mipmapEnabled) if (mipmapEnabled)
{ {
// We simply reload the texture to disable mipmapping // We simply reload the texture to disable mipmapping
if (!texture.loadFromFile(resourcesDir() / "logo.png")) texture = sf::Texture::loadFromFile(resourcesDir() / "logo.png").value();
return EXIT_FAILURE;
mipmapEnabled = false; mipmapEnabled = false;
} }

View File

@ -34,9 +34,9 @@ public:
bool onLoad() override bool onLoad() override
{ {
// Load the texture and initialize the sprite // Load the texture and initialize the sprite
if (!m_texture.loadFromFile("resources/background.jpg")) if (!(m_texture = sf::Texture::loadFromFile("resources/background.jpg")))
return false; return false;
m_sprite.emplace(m_texture); m_sprite.emplace(*m_texture);
// Load the shader // Load the shader
if (!(m_shader = sf::Shader::loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment))) if (!(m_shader = sf::Shader::loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment)))
@ -58,7 +58,7 @@ public:
} }
private: private:
sf::Texture m_texture; std::optional<sf::Texture> m_texture;
std::optional<sf::Sprite> m_sprite; std::optional<sf::Sprite> m_sprite;
std::optional<sf::Shader> m_shader; std::optional<sf::Shader> m_shader;
}; };
@ -193,21 +193,21 @@ public:
m_surface->setSmooth(true); m_surface->setSmooth(true);
// Load the textures // Load the textures
if (!m_backgroundTexture.loadFromFile("resources/sfml.png")) if (!(m_backgroundTexture = sf::Texture::loadFromFile("resources/sfml.png")))
return false; return false;
m_backgroundTexture.setSmooth(true); m_backgroundTexture->setSmooth(true);
if (!m_entityTexture.loadFromFile("resources/devices.png")) if (!(m_entityTexture = sf::Texture::loadFromFile("resources/devices.png")))
return false; return false;
m_entityTexture.setSmooth(true); m_entityTexture->setSmooth(true);
// Initialize the background sprite // Initialize the background sprite
m_backgroundSprite.emplace(m_backgroundTexture); m_backgroundSprite.emplace(*m_backgroundTexture);
m_backgroundSprite->setPosition({135.f, 100.f}); m_backgroundSprite->setPosition({135.f, 100.f});
// Load the moving entities // Load the moving entities
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
{ {
const sf::Sprite entity(m_entityTexture, sf::IntRect({96 * i, 0}, {96, 96})); const sf::Sprite entity(*m_entityTexture, sf::IntRect({96 * i, 0}, {96, 96}));
m_entities.push_back(entity); m_entities.push_back(entity);
} }
@ -250,8 +250,8 @@ public:
private: private:
std::optional<sf::RenderTexture> m_surface; std::optional<sf::RenderTexture> m_surface;
sf::Texture m_backgroundTexture; std::optional<sf::Texture> m_backgroundTexture;
sf::Texture m_entityTexture; std::optional<sf::Texture> m_entityTexture;
std::optional<sf::Sprite> m_backgroundSprite; std::optional<sf::Sprite> m_backgroundSprite;
std::vector<sf::Sprite> m_entities; std::vector<sf::Sprite> m_entities;
std::optional<sf::Shader> m_shader; std::optional<sf::Shader> m_shader;
@ -284,7 +284,7 @@ public:
} }
// Load the texture // Load the texture
if (!m_logoTexture.loadFromFile("resources/logo.png")) if (!(m_logoTexture = sf::Texture::loadFromFile("resources/logo.png")))
return false; return false;
// Load the shader // Load the shader
@ -320,7 +320,7 @@ public:
{ {
// Prepare the render state // Prepare the render state
states.shader = &*m_shader; states.shader = &*m_shader;
states.texture = &m_logoTexture; states.texture = &*m_logoTexture;
states.transform = m_transform; states.transform = m_transform;
// Draw the point cloud // Draw the point cloud
@ -328,7 +328,7 @@ public:
} }
private: private:
sf::Texture m_logoTexture; std::optional<sf::Texture> m_logoTexture;
sf::Transform m_transform; sf::Transform m_transform;
std::optional<sf::Shader> m_shader; std::optional<sf::Shader> m_shader;
sf::VertexArray m_pointCloud; sf::VertexArray m_pointCloud;
@ -367,9 +367,7 @@ int main()
effect->load(); effect->load();
// Create the messages background // Create the messages background
sf::Texture textBackgroundTexture; const auto textBackgroundTexture = sf::Texture::loadFromFile("resources/text-background.png").value();
if (!textBackgroundTexture.loadFromFile("resources/text-background.png"))
return EXIT_FAILURE;
sf::Sprite textBackground(textBackgroundTexture); sf::Sprite textBackground(textBackgroundTexture);
textBackground.setPosition({0.f, 520.f}); textBackground.setPosition({0.f, 520.f});
textBackground.setColor(sf::Color(255, 255, 255, 200)); textBackground.setColor(sf::Color(255, 255, 255, 200));

View File

@ -1080,9 +1080,7 @@ int main()
effects[current]->start(); effects[current]->start();
// Create the messages background // Create the messages background
sf::Texture textBackgroundTexture; const auto textBackgroundTexture = sf::Texture::loadFromFile(resourcesDir() / "text-background.png").value();
if (!textBackgroundTexture.loadFromFile(resourcesDir() / "text-background.png"))
return EXIT_FAILURE;
sf::Sprite textBackground(textBackgroundTexture); sf::Sprite textBackground(textBackgroundTexture);
textBackground.setPosition({0.f, 520.f}); textBackground.setPosition({0.f, 520.f});
textBackground.setColor(sf::Color(255, 255, 255, 200)); textBackground.setColor(sf::Color(255, 255, 255, 200));

View File

@ -53,9 +53,7 @@ int main()
sf::Sound ballSound(ballSoundBuffer); sf::Sound ballSound(ballSoundBuffer);
// Create the SFML logo texture: // Create the SFML logo texture:
sf::Texture sfmlLogoTexture; const auto sfmlLogoTexture = sf::Texture::loadFromFile(resourcesDir() / "sfml_logo.png").value();
if (!sfmlLogoTexture.loadFromFile(resourcesDir() / "sfml_logo.png"))
return EXIT_FAILURE;
sf::Sprite sfmlLogo(sfmlLogoTexture); sf::Sprite sfmlLogo(sfmlLogoTexture);
sfmlLogo.setPosition({170.f, 50.f}); sfmlLogo.setPosition({170.f, 50.f});

View File

@ -111,10 +111,8 @@ int main()
sf::RenderWindow sfmlView2(view2); sf::RenderWindow sfmlView2(view2);
// Load some textures to display // Load some textures to display
sf::Texture texture1; const auto texture1 = sf::Texture::loadFromFile("resources/image1.jpg").value();
sf::Texture texture2; const auto texture2 = sf::Texture::loadFromFile("resources/image2.jpg").value();
if (!texture1.loadFromFile("resources/image1.jpg") || !texture2.loadFromFile("resources/image2.jpg"))
return EXIT_FAILURE;
sf::Sprite sprite1(texture1); sf::Sprite sprite1(texture1);
sf::Sprite sprite2(texture2); sf::Sprite sprite2(texture2);
sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f); sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f);

View File

@ -315,7 +315,8 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
struct Page struct Page
{ {
explicit Page(bool smooth); [[nodiscard]] static std::optional<Page> make(bool smooth);
explicit Page(Texture&& texture);
GlyphTable glyphs; //!< Table mapping code points to their corresponding glyph GlyphTable glyphs; //!< Table mapping code points to their corresponding glyph
Texture texture; //!< Texture containing the pixels of the glyphs Texture texture; //!< Texture containing the pixels of the glyphs

View File

@ -266,11 +266,7 @@ private:
/// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL"); /// sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML OpenGL");
/// ///
/// // Create a sprite and a text to display /// // Create a sprite and a text to display
/// sf::Texture texture; /// const auto texture = sf::Texture::loadFromFile("circle.png").value();
/// if (!texture.loadFromFile("circle.png"))
/// {
/// // error...
/// }
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);
/// const auto font = sf::Font::loadFromFile("arial.ttf").value(); /// const auto font = sf::Font::loadFromFile("arial.ttf").value();
/// sf::Text text(font); /// sf::Text text(font);

View File

@ -266,12 +266,8 @@ private:
/// ///
/// Usage example: /// Usage example:
/// \code /// \code
/// // Declare and load a texture /// // Load a texture
/// sf::Texture texture; /// const auto texture = sf::Texture::loadFromFile("texture.png").value();
/// if (!texture.loadFromFile("texture.png"))
/// {
/// // Handle error...
/// }
/// ///
/// // Create a sprite /// // Create a sprite
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);

View File

@ -37,6 +37,7 @@
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <filesystem> #include <filesystem>
#include <optional>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@ -55,14 +56,6 @@ class Image;
class SFML_GRAPHICS_API Texture : GlResource class SFML_GRAPHICS_API Texture : GlResource
{ {
public: public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty texture.
///
////////////////////////////////////////////////////////////
Texture();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
/// ///
@ -101,11 +94,12 @@ public:
/// If this function fails, the texture is left unchanged. /// If this function fails, the texture is left unchanged.
/// ///
/// \param size Width and height of the texture /// \param size Width and height of the texture
/// \param sRgb True to enable sRGB conversion, false to disable it
/// ///
/// \return True if creation was successful /// \return Texture if creation was successful, otherwise `std::nullopt`
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool create(const Vector2u& size); [[nodiscard]] static std::optional<Texture> create(const Vector2u& size, bool sRgb = false);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Load the texture from a file on disk /// \brief Load the texture from a file on disk
@ -122,14 +116,17 @@ public:
/// If this function fails, the texture is left unchanged. /// If this function fails, the texture is left unchanged.
/// ///
/// \param filename Path of the image file to load /// \param filename Path of the image file to load
/// \param sRgb True to enable sRGB conversion, false to disable it
/// \param area Area of the image to load /// \param area Area of the image to load
/// ///
/// \return True if loading was successful /// \return Texture if loading was successful, otherwise `std::nullopt`
/// ///
/// \see loadFromMemory, loadFromStream, loadFromImage /// \see loadFromMemory, loadFromStream, loadFromImage
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, const IntRect& area = {}); [[nodiscard]] static std::optional<Texture> loadFromFile(const std::filesystem::path& filename,
bool sRgb = false,
const IntRect& area = {});
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Load the texture from a file in memory /// \brief Load the texture from a file in memory
@ -147,14 +144,19 @@ public:
/// ///
/// \param data Pointer to the file data in memory /// \param data Pointer to the file data in memory
/// \param size Size of the data to load, in bytes /// \param size Size of the data to load, in bytes
/// \param sRgb True to enable sRGB conversion, false to disable it
/// \param area Area of the image to load /// \param area Area of the image to load
/// ///
/// \return True if loading was successful /// \return Texture if loading was successful, otherwise `std::nullopt`
/// ///
/// \see loadFromFile, loadFromStream, loadFromImage /// \see loadFromFile, loadFromStream, loadFromImage
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size, const IntRect& area = {}); [[nodiscard]] static std::optional<Texture> loadFromMemory(
const void* data,
std::size_t size,
bool sRgb = false,
const IntRect& area = {});
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Load the texture from a custom stream /// \brief Load the texture from a custom stream
@ -171,14 +173,15 @@ public:
/// If this function fails, the texture is left unchanged. /// If this function fails, the texture is left unchanged.
/// ///
/// \param stream Source stream to read from /// \param stream Source stream to read from
/// \param sRgb True to enable sRGB conversion, false to disable it
/// \param area Area of the image to load /// \param area Area of the image to load
/// ///
/// \return True if loading was successful /// \return Texture if loading was successful, otherwise `std::nullopt`
/// ///
/// \see loadFromFile, loadFromMemory, loadFromImage /// \see loadFromFile, loadFromMemory, loadFromImage
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream, const IntRect& area = {}); [[nodiscard]] static std::optional<Texture> loadFromStream(InputStream& stream, bool sRgb = false, const IntRect& area = {});
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Load the texture from an image /// \brief Load the texture from an image
@ -195,14 +198,15 @@ public:
/// If this function fails, the texture is left unchanged. /// If this function fails, the texture is left unchanged.
/// ///
/// \param image Image to load into the texture /// \param image Image to load into the texture
/// \param sRgb True to enable sRGB conversion, false to disable it
/// \param area Area of the image to load /// \param area Area of the image to load
/// ///
/// \return True if loading was successful /// \return Texture if loading was successful, otherwise `std::nullopt`
/// ///
/// \see loadFromFile, loadFromMemory /// \see loadFromFile, loadFromMemory
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromImage(const Image& image, const IntRect& area = {}); [[nodiscard]] static std::optional<Texture> loadFromImage(const Image& image, bool sRgb = false, const IntRect& area = {});
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Return the size of the texture /// \brief Return the size of the texture
@ -402,31 +406,6 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool isSmooth() const; bool isSmooth() const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable conversion from sRGB
///
/// When providing texture data from an image file or memory, it can
/// either be stored in a linear color space or an sRGB color space.
/// Most digital images account for gamma correction already, so they
/// would need to be "uncorrected" back to linear color space before
/// being processed by the hardware. The hardware can automatically
/// convert it from the sRGB color space to a linear color space when
/// it gets sampled. When the rendered image gets output to the final
/// framebuffer, it gets converted back to sRGB.
///
/// After enabling or disabling sRGB conversion, make sure to reload
/// the texture data in order for the setting to take effect.
///
/// This option is only useful in conjunction with an sRGB capable
/// framebuffer. This can be requested during window creation.
///
/// \param sRgb True to enable sRGB conversion, false to disable it
///
/// \see isSrgb
///
////////////////////////////////////////////////////////////
void setSrgb(bool sRgb);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Tell whether the texture source is converted from sRGB or not /// \brief Tell whether the texture source is converted from sRGB or not
/// ///
@ -566,6 +545,14 @@ private:
friend class RenderTexture; friend class RenderTexture;
friend class RenderTarget; friend class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty texture.
///
////////////////////////////////////////////////////////////
Texture(const Vector2u& size, const Vector2u& actualSize, unsigned int texture, bool sRgb);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get a valid image size according to hardware support /// \brief Get a valid image size according to hardware support
/// ///
@ -657,15 +644,25 @@ SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
/// that a pixel must be composed of 8 bits red, green, blue and /// that a pixel must be composed of 8 bits red, green, blue and
/// alpha channels -- just like a sf::Color. /// alpha channels -- just like a sf::Color.
/// ///
/// When providing texture data from an image file or memory, it can
/// either be stored in a linear color space or an sRGB color space.
/// Most digital images account for gamma correction already, so they
/// would need to be "uncorrected" back to linear color space before
/// being processed by the hardware. The hardware can automatically
/// convert it from the sRGB color space to a linear color space when
/// it gets sampled. When the rendered image gets output to the final
/// framebuffer, it gets converted back to sRGB.
///
/// This option is only useful in conjunction with an sRGB capable
/// framebuffer. This can be requested during window creation.
///
/// Usage example: /// Usage example:
/// \code /// \code
/// // This example shows the most common use of sf::Texture: /// // This example shows the most common use of sf::Texture:
/// // drawing a sprite /// // drawing a sprite
/// ///
/// // Load a texture from a file /// // Load a texture from a file
/// sf::Texture texture; /// const auto texture = sf::Texture::loadFromFile("texture.png").value();
/// if (!texture.loadFromFile("texture.png"))
/// return -1;
/// ///
/// // Assign it to a sprite /// // Assign it to a sprite
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);
@ -679,9 +676,7 @@ SFML_GRAPHICS_API void swap(Texture& left, Texture& right) noexcept;
/// // streaming real-time data, like video frames /// // streaming real-time data, like video frames
/// ///
/// // Create an empty texture /// // Create an empty texture
/// sf::Texture texture; /// auto texture = sf::Texture::create({640, 480}).value();
/// if (!texture.create({640, 480}))
/// return -1;
/// ///
/// // Create a sprite that will display the texture /// // Create a sprite that will display the texture
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);

View File

@ -133,7 +133,6 @@ public:
/// }; /// };
/// ///
/// // now you can load textures... /// // now you can load textures...
/// sf::Texture texture;
/// ZipStream stream("resources.zip"); /// ZipStream stream("resources.zip");
/// ///
/// if (!stream.open("images/img.png")) /// if (!stream.open("images/img.png"))
@ -141,10 +140,7 @@ public:
/// // Handle error... /// // Handle error...
/// } /// }
/// ///
/// if (!texture.loadFromStream(stream)) /// const auto texture = sf::Texture::loadFromStream(stream).value();
/// {
/// // Handle error...
/// }
/// ///
/// // musics... /// // musics...
/// sf::Music music; /// sf::Music music;

View File

@ -45,6 +45,7 @@
#include <ostream> #include <ostream>
#include <utility> #include <utility>
#include <cassert>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
@ -469,7 +470,9 @@ bool Font::isSmooth() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Font::Page& Font::loadPage(unsigned int characterSize) const Font::Page& Font::loadPage(unsigned int characterSize) const
{ {
return m_pages.try_emplace(characterSize, m_isSmooth).first->second; auto page = Page::make(m_isSmooth);
assert(page && "Font::loadPage() Failed to load page");
return m_pages.try_emplace(characterSize, std::move(*page)).first->second;
} }
@ -679,16 +682,16 @@ IntRect Font::findGlyphRect(Page& page, const Vector2u& size) const
if ((textureSize.x * 2 <= Texture::getMaximumSize()) && (textureSize.y * 2 <= Texture::getMaximumSize())) if ((textureSize.x * 2 <= Texture::getMaximumSize()) && (textureSize.y * 2 <= Texture::getMaximumSize()))
{ {
// Make the texture 2 times bigger // Make the texture 2 times bigger
Texture newTexture; auto newTexture = sf::Texture::create(textureSize * 2u);
if (!newTexture.create(textureSize * 2u)) if (!newTexture)
{ {
err() << "Failed to create new page texture" << std::endl; err() << "Failed to create new page texture" << std::endl;
return {{0, 0}, {2, 2}}; return {{0, 0}, {2, 2}};
} }
newTexture.setSmooth(m_isSmooth); newTexture->setSmooth(m_isSmooth);
newTexture.update(page.texture); newTexture->update(page.texture);
page.texture.swap(newTexture); page.texture.swap(*newTexture);
} }
else else
{ {
@ -757,7 +760,7 @@ bool Font::setCurrentSize(unsigned int characterSize) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Font::Page::Page(bool smooth) std::optional<Font::Page> Font::Page::make(bool smooth)
{ {
// Make sure that the texture is initialized by default // Make sure that the texture is initialized by default
Image image({128, 128}, Color::Transparent); Image image({128, 128}, Color::Transparent);
@ -768,12 +771,21 @@ Font::Page::Page(bool smooth)
image.setPixel({x, y}, Color::White); image.setPixel({x, y}, Color::White);
// Create the texture // Create the texture
if (!texture.loadFromImage(image)) auto texture = sf::Texture::loadFromImage(image);
if (!texture)
{ {
err() << "Failed to load font page texture" << std::endl; err() << "Failed to load font page texture" << std::endl;
return std::nullopt;
} }
texture.setSmooth(smooth); texture->setSmooth(smooth);
return Page(std::move(*texture));
}
////////////////////////////////////////////////////////////
Font::Page::Page(Texture&& theTexture) : texture(std::move(theTexture))
{
} }
} // namespace sf } // namespace sf

View File

@ -52,19 +52,15 @@ RenderTexture& RenderTexture::operator=(RenderTexture&&) noexcept = default;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::optional<RenderTexture> RenderTexture::create(const Vector2u& size, const ContextSettings& settings) std::optional<RenderTexture> RenderTexture::create(const Vector2u& size, const ContextSettings& settings)
{ {
sf::Texture texture;
// Set texture to be in sRGB scale if requested
texture.setSrgb(settings.sRgbCapable);
// Create the texture // Create the texture
if (!texture.create(size)) auto texture = sf::Texture::create(size, settings.sRgbCapable);
if (!texture)
{ {
err() << "Impossible to create render texture (failed to create the target texture)" << std::endl; err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
return std::nullopt; return std::nullopt;
} }
RenderTexture renderTexture(std::move(texture)); RenderTexture renderTexture(std::move(*texture));
// We disable smoothing by default for render textures // We disable smoothing by default for render textures
renderTexture.setSmooth(false); renderTexture.setSmooth(false);

View File

@ -66,7 +66,12 @@ std::uint64_t getUniqueId() noexcept
namespace sf namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Texture::Texture() : m_cacheId(TextureImpl::getUniqueId()) Texture::Texture(const Vector2u& size, const Vector2u& actualSize, unsigned int texture, bool sRgb) :
m_size(size),
m_actualSize(actualSize),
m_texture(texture),
m_sRgb(sRgb),
m_cacheId(TextureImpl::getUniqueId())
{ {
} }
@ -79,10 +84,9 @@ m_sRgb(copy.m_sRgb),
m_isRepeated(copy.m_isRepeated), m_isRepeated(copy.m_isRepeated),
m_cacheId(TextureImpl::getUniqueId()) m_cacheId(TextureImpl::getUniqueId())
{ {
if (copy.m_texture) if (auto texture = create(copy.getSize(), copy.isSrgb()))
{
if (create(copy.getSize()))
{ {
*this = std::move(*texture);
update(copy); update(copy);
} }
else else
@ -90,7 +94,6 @@ m_cacheId(TextureImpl::getUniqueId())
err() << "Failed to copy texture, failed to create new texture" << std::endl; err() << "Failed to copy texture, failed to create new texture" << std::endl;
} }
} }
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -151,13 +154,13 @@ Texture& Texture::operator=(Texture&& right) noexcept
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::create(const Vector2u& size) std::optional<Texture> Texture::create(const Vector2u& size, bool sRgb)
{ {
// Check if texture parameters are valid before creating it // Check if texture parameters are valid before creating it
if ((size.x == 0) || (size.y == 0)) if ((size.x == 0) || (size.y == 0))
{ {
err() << "Failed to create texture, invalid size (" << size.x << "x" << size.y << ")" << std::endl; err() << "Failed to create texture, invalid size (" << size.x << "x" << size.y << ")" << std::endl;
return false; return std::nullopt;
} }
const TransientContextLock lock; const TransientContextLock lock;
@ -175,22 +178,16 @@ bool Texture::create(const Vector2u& size)
err() << "Failed to create texture, its internal size is too high " err() << "Failed to create texture, its internal size is too high "
<< "(" << actualSize.x << "x" << actualSize.y << ", " << "(" << actualSize.x << "x" << actualSize.y << ", "
<< "maximum is " << maxSize << "x" << maxSize << ")" << std::endl; << "maximum is " << maxSize << "x" << maxSize << ")" << std::endl;
return false; return std::nullopt;
} }
// Create the OpenGL texture
GLuint glTexture = 0;
glCheck(glGenTextures(1, &glTexture));
assert(glTexture);
// All the validity checks passed, we can store the new texture settings // All the validity checks passed, we can store the new texture settings
m_size = size; Texture texture(size, actualSize, glTexture, sRgb);
m_actualSize = actualSize;
m_pixelsFlipped = false;
m_fboAttachment = false;
// Create the OpenGL texture if it doesn't exist yet
if (!m_texture)
{
GLuint texture = 0;
glCheck(glGenTextures(1, &texture));
m_texture = texture;
}
// Make sure that the current texture binding will be preserved // Make sure that the current texture binding will be preserved
const priv::TextureSaver save; const priv::TextureSaver save;
@ -198,7 +195,7 @@ bool Texture::create(const Vector2u& size)
static const bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_GL_VERSION_1_2 || static const bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_GL_VERSION_1_2 ||
Context::isExtensionAvailable("GL_EXT_texture_edge_clamp"); Context::isExtensionAvailable("GL_EXT_texture_edge_clamp");
if (!m_isRepeated && !textureEdgeClamp) if (!textureEdgeClamp)
{ {
static bool warned = false; static bool warned = false;
@ -214,7 +211,7 @@ bool Texture::create(const Vector2u& size)
static const bool textureSrgb = GLEXT_texture_sRGB; static const bool textureSrgb = GLEXT_texture_sRGB;
if (m_sRgb && !textureSrgb) if (texture.m_sRgb && !textureSrgb)
{ {
static bool warned = false; static bool warned = false;
@ -230,70 +227,70 @@ bool Texture::create(const Vector2u& size)
warned = true; warned = true;
} }
m_sRgb = false; texture.m_sRgb = false;
} }
#ifndef SFML_OPENGL_ES #ifndef SFML_OPENGL_ES
const GLint textureWrapParam = m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP); const GLint textureWrapParam = textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP;
#else #else
const GLint textureWrapParam = m_isRepeated ? GL_REPEAT : GLEXT_GL_CLAMP_TO_EDGE; const GLint textureWrapParam = GLEXT_GL_CLAMP_TO_EDGE;
#endif #endif
// Initialize the texture // Initialize the texture
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glBindTexture(GL_TEXTURE_2D, texture.m_texture));
glCheck(glTexImage2D(GL_TEXTURE_2D, glCheck(glTexImage2D(GL_TEXTURE_2D,
0, 0,
(m_sRgb ? GLEXT_GL_SRGB8_ALPHA8 : GL_RGBA), (texture.m_sRgb ? GLEXT_GL_SRGB8_ALPHA8 : GL_RGBA),
static_cast<GLsizei>(m_actualSize.x), static_cast<GLsizei>(texture.m_actualSize.x),
static_cast<GLsizei>(m_actualSize.y), static_cast<GLsizei>(texture.m_actualSize.y),
0, 0,
GL_RGBA, GL_RGBA,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
nullptr)); nullptr));
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapParam)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapParam));
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapParam)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapParam));
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
m_cacheId = TextureImpl::getUniqueId(); texture.m_cacheId = TextureImpl::getUniqueId();
m_hasMipmap = false; texture.m_hasMipmap = false;
return true; return texture;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::loadFromFile(const std::filesystem::path& filename, const IntRect& area) std::optional<Texture> Texture::loadFromFile(const std::filesystem::path& filename, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromFile(filename); const auto image = sf::Image::loadFromFile(filename);
if (!image) if (!image)
return false; return std::nullopt;
return loadFromImage(*image, area); return loadFromImage(*image, sRgb, area);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::loadFromMemory(const void* data, std::size_t size, const IntRect& area) std::optional<Texture> Texture::loadFromMemory(const void* data, std::size_t size, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromMemory(data, size); const auto image = sf::Image::loadFromMemory(data, size);
if (!image) if (!image)
return false; return std::nullopt;
return loadFromImage(*image, area); return loadFromImage(*image, sRgb, area);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::loadFromStream(InputStream& stream, const IntRect& area) std::optional<Texture> Texture::loadFromStream(InputStream& stream, bool sRgb, const IntRect& area)
{ {
const auto image = sf::Image::loadFromStream(stream); const auto image = sf::Image::loadFromStream(stream);
if (!image) if (!image)
return false; return std::nullopt;
return loadFromImage(*image, area); return loadFromImage(*image, sRgb, area);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::loadFromImage(const Image& image, const IntRect& area) std::optional<Texture> Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area)
{ {
// Retrieve the image size // Retrieve the image size
const auto [width, height] = Vector2i(image.getSize()); const auto [width, height] = Vector2i(image.getSize());
@ -303,15 +300,15 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
((area.left <= 0) && (area.top <= 0) && (area.width >= width) && (area.height >= height))) ((area.left <= 0) && (area.top <= 0) && (area.width >= width) && (area.height >= height)))
{ {
// Load the entire image // Load the entire image
if (create(image.getSize())) if (auto texture = sf::Texture::create(image.getSize(), sRgb))
{ {
update(image); texture->update(image);
return true; return texture;
} }
else else
{ {
return false; return std::nullopt;
} }
} }
else else
@ -326,7 +323,7 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
rectangle.height = std::min(rectangle.height, height - rectangle.top); rectangle.height = std::min(rectangle.height, height - rectangle.top);
// Create the texture and upload the pixels // Create the texture and upload the pixels
if (create(Vector2u(rectangle.getSize()))) if (auto texture = sf::Texture::create(Vector2u(rectangle.getSize()), sRgb))
{ {
const TransientContextLock lock; const TransientContextLock lock;
@ -335,25 +332,25 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
// Copy the pixels to the texture, row by row // Copy the pixels to the texture, row by row
const std::uint8_t* pixels = image.getPixelsPtr() + 4 * (rectangle.left + (width * rectangle.top)); const std::uint8_t* pixels = image.getPixelsPtr() + 4 * (rectangle.left + (width * rectangle.top));
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glBindTexture(GL_TEXTURE_2D, texture->m_texture));
for (int i = 0; i < rectangle.height; ++i) for (int i = 0; i < rectangle.height; ++i)
{ {
glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.width, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.width, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
pixels += 4 * width; pixels += 4 * width;
} }
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
m_hasMipmap = false; texture->m_hasMipmap = false;
// Force an OpenGL flush, so that the texture will appear updated // Force an OpenGL flush, so that the texture will appear updated
// in all contexts immediately (solves problems in multi-threaded apps) // in all contexts immediately (solves problems in multi-threaded apps)
glCheck(glFlush()); glCheck(glFlush());
return true; return texture;
} }
else else
{ {
return false; return std::nullopt;
} }
} }
} }
@ -736,13 +733,6 @@ bool Texture::isSmooth() const
} }
////////////////////////////////////////////////////////////
void Texture::setSrgb(bool sRgb)
{
m_sRgb = sRgb;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Texture::isSrgb() const bool Texture::isSrgb() const
{ {

View File

@ -75,8 +75,7 @@ TEST_CASE("[Graphics] sf::RenderWindow", runDisplayTests())
sf::ContextSettings{}); sf::ContextSettings{});
REQUIRE(window.getSize() == sf::Vector2u(256, 256)); REQUIRE(window.getSize() == sf::Vector2u(256, 256));
sf::Texture texture; auto texture = sf::Texture::create(window.getSize()).value();
REQUIRE(texture.create(window.getSize()));
window.clear(sf::Color::Red); window.clear(sf::Color::Red);
texture.update(window); texture.update(window);

View File

@ -66,7 +66,7 @@ TEST_CASE("[Graphics] sf::Shape", runDisplayTests())
SECTION("Set/get texture") SECTION("Set/get texture")
{ {
const sf::Texture texture; const auto texture = sf::Texture::create({64, 64}).value();
TriangleShape triangleShape({}); TriangleShape triangleShape({});
triangleShape.setTexture(&texture, true); triangleShape.setTexture(&texture, true);
CHECK(triangleShape.getTexture() == &texture); CHECK(triangleShape.getTexture() == &texture);

View File

@ -19,7 +19,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Sprite>); STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Sprite>);
} }
const sf::Texture texture; const auto texture = sf::Texture::create({64, 64}).value();
SECTION("Construction") SECTION("Construction")
{ {
@ -27,10 +27,10 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
{ {
const sf::Sprite sprite(texture); const sf::Sprite sprite(texture);
CHECK(&sprite.getTexture() == &texture); CHECK(&sprite.getTexture() == &texture);
CHECK(sprite.getTextureRect() == sf::IntRect()); CHECK(sprite.getTextureRect() == sf::IntRect({}, {64, 64}));
CHECK(sprite.getColor() == sf::Color::White); CHECK(sprite.getColor() == sf::Color::White);
CHECK(sprite.getLocalBounds() == sf::FloatRect()); CHECK(sprite.getLocalBounds() == sf::FloatRect({}, {64, 64}));
CHECK(sprite.getGlobalBounds() == sf::FloatRect()); CHECK(sprite.getGlobalBounds() == sf::FloatRect({}, {64, 64}));
} }
SECTION("Texture and rectangle constructor") SECTION("Texture and rectangle constructor")
@ -47,7 +47,7 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
SECTION("Set/get texture") SECTION("Set/get texture")
{ {
sf::Sprite sprite(texture); sf::Sprite sprite(texture);
const sf::Texture otherTexture; const sf::Texture otherTexture = sf::Texture::create({64, 64}).value();
sprite.setTexture(otherTexture); sprite.setTexture(otherTexture);
CHECK(&sprite.getTexture() == &otherTexture); CHECK(&sprite.getTexture() == &otherTexture);
} }

View File

@ -15,6 +15,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
{ {
SECTION("Type traits") SECTION("Type traits")
{ {
STATIC_CHECK(!std::is_default_constructible_v<sf::Texture>);
STATIC_CHECK(std::is_copy_constructible_v<sf::Texture>); STATIC_CHECK(std::is_copy_constructible_v<sf::Texture>);
STATIC_CHECK(std::is_copy_assignable_v<sf::Texture>); STATIC_CHECK(std::is_copy_assignable_v<sf::Texture>);
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::Texture>); STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::Texture>);
@ -22,71 +23,58 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
STATIC_CHECK(std::is_nothrow_swappable_v<sf::Texture>); STATIC_CHECK(std::is_nothrow_swappable_v<sf::Texture>);
} }
SECTION("Construction")
{
const sf::Texture texture;
CHECK(texture.getSize() == sf::Vector2u());
CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb());
CHECK(!texture.isRepeated());
CHECK(texture.getNativeHandle() == 0);
}
SECTION("Move semantics") SECTION("Move semantics")
{ {
SECTION("Construction") SECTION("Construction")
{ {
sf::Texture movedTexture; sf::Texture movedTexture = sf::Texture::create({64, 64}).value();
const sf::Texture texture = std::move(movedTexture); const sf::Texture texture = std::move(movedTexture);
CHECK(texture.getSize() == sf::Vector2u()); CHECK(texture.getSize() == sf::Vector2u(64, 64));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb()); CHECK(!texture.isSrgb());
CHECK(!texture.isRepeated()); CHECK(!texture.isRepeated());
CHECK(texture.getNativeHandle() == 0); CHECK(texture.getNativeHandle() != 0);
} }
SECTION("Assignment") SECTION("Assignment")
{ {
sf::Texture movedTexture; sf::Texture movedTexture = sf::Texture::create({64, 64}).value();
sf::Texture texture; sf::Texture texture = sf::Texture::create({128, 128}).value();
texture = std::move(movedTexture); texture = std::move(movedTexture);
CHECK(texture.getSize() == sf::Vector2u()); CHECK(texture.getSize() == sf::Vector2u(64, 64));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb()); CHECK(!texture.isSrgb());
CHECK(!texture.isRepeated()); CHECK(!texture.isRepeated());
CHECK(texture.getNativeHandle() == 0); CHECK(texture.getNativeHandle() != 0);
} }
} }
SECTION("create()") SECTION("create()")
{ {
sf::Texture texture;
SECTION("At least one zero dimension") SECTION("At least one zero dimension")
{ {
CHECK(!texture.create({})); CHECK(!sf::Texture::create({}));
CHECK(!texture.create({0, 1})); CHECK(!sf::Texture::create({0, 1}));
CHECK(!texture.create({1, 0})); CHECK(!sf::Texture::create({1, 0}));
} }
SECTION("Valid size") SECTION("Valid size")
{ {
CHECK(texture.create({100, 100})); const auto texture = sf::Texture::create({100, 100}).value();
CHECK(texture.getSize() == sf::Vector2u(100, 100)); CHECK(texture.getSize() == sf::Vector2u(100, 100));
CHECK(texture.getNativeHandle() != 0); CHECK(texture.getNativeHandle() != 0);
} }
SECTION("Too large") SECTION("Too large")
{ {
CHECK(!texture.create({100'000, 100'000})); CHECK(!sf::Texture::create({100'000, 100'000}));
CHECK(!texture.create({1'000'000, 1'000'000})); CHECK(!sf::Texture::create({1'000'000, 1'000'000}));
} }
} }
SECTION("loadFromFile()") SECTION("loadFromFile()")
{ {
sf::Texture texture; const auto texture = sf::Texture::loadFromFile("Graphics/sfml-logo-big.png").value();
REQUIRE(texture.loadFromFile("Graphics/sfml-logo-big.png"));
CHECK(texture.getSize() == sf::Vector2u(1001, 304)); CHECK(texture.getSize() == sf::Vector2u(1001, 304));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb()); CHECK(!texture.isSrgb());
@ -97,8 +85,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("loadFromMemory()") SECTION("loadFromMemory()")
{ {
const auto memory = loadIntoMemory("Graphics/sfml-logo-big.png"); const auto memory = loadIntoMemory("Graphics/sfml-logo-big.png");
sf::Texture texture; const auto texture = sf::Texture::loadFromMemory(memory.data(), memory.size()).value();
REQUIRE(texture.loadFromMemory(memory.data(), memory.size()));
CHECK(texture.getSize() == sf::Vector2u(1001, 304)); CHECK(texture.getSize() == sf::Vector2u(1001, 304));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb()); CHECK(!texture.isSrgb());
@ -108,10 +95,9 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::Texture texture;
sf::FileInputStream stream; sf::FileInputStream stream;
REQUIRE(stream.open("Graphics/sfml-logo-big.png")); REQUIRE(stream.open("Graphics/sfml-logo-big.png"));
REQUIRE(texture.loadFromStream(stream)); const auto texture = sf::Texture::loadFromStream(stream).value();
CHECK(texture.getSize() == sf::Vector2u(1001, 304)); CHECK(texture.getSize() == sf::Vector2u(1001, 304));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
CHECK(!texture.isSrgb()); CHECK(!texture.isSrgb());
@ -124,36 +110,35 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Subarea of image") SECTION("Subarea of image")
{ {
const sf::Image image(sf::Vector2u(10, 15)); const sf::Image image(sf::Vector2u(10, 15));
sf::Texture texture;
SECTION("Non-truncated area") SECTION("Non-truncated area")
{ {
REQUIRE(texture.loadFromImage(image, {{0, 0}, {5, 10}})); const auto texture = sf::Texture::loadFromImage(image, false, {{0, 0}, {5, 10}}).value();
CHECK(texture.getSize() == sf::Vector2u(5, 10)); CHECK(texture.getSize() == sf::Vector2u(5, 10));
CHECK(texture.getNativeHandle() != 0);
} }
SECTION("Truncated area (negative position)") SECTION("Truncated area (negative position)")
{ {
REQUIRE(texture.loadFromImage(image, {{-5, -5}, {4, 8}})); const auto texture = sf::Texture::loadFromImage(image, false, {{-5, -5}, {4, 8}}).value();
CHECK(texture.getSize() == sf::Vector2u(4, 8)); CHECK(texture.getSize() == sf::Vector2u(4, 8));
CHECK(texture.getNativeHandle() != 0);
} }
SECTION("Truncated area (width/height too big)") SECTION("Truncated area (width/height too big)")
{ {
REQUIRE(texture.loadFromImage(image, {{5, 5}, {12, 18}})); const auto texture = sf::Texture::loadFromImage(image, false, {{5, 5}, {12, 18}}).value();
CHECK(texture.getSize() == sf::Vector2u(5, 10)); CHECK(texture.getSize() == sf::Vector2u(5, 10));
}
CHECK(texture.getNativeHandle() != 0); CHECK(texture.getNativeHandle() != 0);
} }
} }
}
SECTION("Copy semantics") SECTION("Copy semantics")
{ {
constexpr std::uint8_t red[] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; constexpr std::uint8_t red[] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};
sf::Texture texture; auto texture = sf::Texture::create({1, 2}).value();
REQUIRE(texture.create(sf::Vector2u(1, 2)));
texture.update(red); texture.update(red);
SECTION("Construction") SECTION("Construction")
@ -165,7 +150,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Assignment") SECTION("Assignment")
{ {
sf::Texture textureCopy; sf::Texture textureCopy = sf::Texture::create({64, 64}).value();
textureCopy = texture; textureCopy = texture;
REQUIRE(textureCopy.getSize() == sf::Vector2u(1, 2)); REQUIRE(textureCopy.getSize() == sf::Vector2u(1, 2));
CHECK(textureCopy.copyToImage().getPixel(sf::Vector2u(0, 1)) == sf::Color::Red); CHECK(textureCopy.copyToImage().getPixel(sf::Vector2u(0, 1)) == sf::Color::Red);
@ -177,18 +162,16 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
constexpr std::uint8_t yellow[] = {0xFF, 0xFF, 0x00, 0xFF}; constexpr std::uint8_t yellow[] = {0xFF, 0xFF, 0x00, 0xFF};
constexpr std::uint8_t cyan[] = {0x00, 0xFF, 0xFF, 0xFF}; constexpr std::uint8_t cyan[] = {0x00, 0xFF, 0xFF, 0xFF};
sf::Texture texture;
SECTION("Pixels") SECTION("Pixels")
{ {
REQUIRE(texture.create(sf::Vector2u(1, 1))); auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value();
texture.update(yellow); texture.update(yellow);
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
} }
SECTION("Pixels, size and destination") SECTION("Pixels, size and destination")
{ {
REQUIRE(texture.create(sf::Vector2u(2, 1))); auto texture = sf::Texture::create(sf::Vector2u(2, 1)).value();
texture.update(yellow, sf::Vector2u(1, 1), sf::Vector2u(0, 0)); texture.update(yellow, sf::Vector2u(1, 1), sf::Vector2u(0, 0));
texture.update(cyan, sf::Vector2u(1, 1), sf::Vector2u(1, 0)); texture.update(cyan, sf::Vector2u(1, 1), sf::Vector2u(1, 0));
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Yellow);
@ -197,22 +180,19 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Another texture") SECTION("Another texture")
{ {
sf::Texture otherTexture; auto otherTexture = sf::Texture::create(sf::Vector2u(1, 1)).value();
REQUIRE(otherTexture.create(sf::Vector2u(1, 1)));
otherTexture.update(cyan); otherTexture.update(cyan);
REQUIRE(texture.create(sf::Vector2u(1, 1))); auto texture = sf::Texture::create(sf::Vector2u(1, 1)).value();
texture.update(otherTexture); texture.update(otherTexture);
CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Cyan); CHECK(texture.copyToImage().getPixel(sf::Vector2u(0, 0)) == sf::Color::Cyan);
} }
SECTION("Another texture and destination") SECTION("Another texture and destination")
{ {
REQUIRE(texture.create(sf::Vector2u(2, 1))); auto texture = sf::Texture::create(sf::Vector2u(2, 1)).value();
sf::Texture otherTexture1; auto otherTexture1 = sf::Texture::create(sf::Vector2u(1, 1)).value();
REQUIRE(otherTexture1.create(sf::Vector2u(1, 1)));
otherTexture1.update(cyan); otherTexture1.update(cyan);
sf::Texture otherTexture2; auto otherTexture2 = sf::Texture::create(sf::Vector2u(1, 1)).value();
REQUIRE(otherTexture2.create(sf::Vector2u(1, 1)));
otherTexture2.update(yellow); otherTexture2.update(yellow);
texture.update(otherTexture1, sf::Vector2u(0, 0)); texture.update(otherTexture1, sf::Vector2u(0, 0));
texture.update(otherTexture2, sf::Vector2u(1, 0)); texture.update(otherTexture2, sf::Vector2u(1, 0));
@ -222,7 +202,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Image") SECTION("Image")
{ {
REQUIRE(texture.create(sf::Vector2u(16, 32))); auto texture = sf::Texture::create(sf::Vector2u(16, 32)).value();
const sf::Image image(sf::Vector2u(16, 32), sf::Color::Red); const sf::Image image(sf::Vector2u(16, 32), sf::Color::Red);
texture.update(image); texture.update(image);
CHECK(texture.copyToImage().getPixel(sf::Vector2u(7, 15)) == sf::Color::Red); CHECK(texture.copyToImage().getPixel(sf::Vector2u(7, 15)) == sf::Color::Red);
@ -230,7 +210,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Image and destination") SECTION("Image and destination")
{ {
REQUIRE(texture.create(sf::Vector2u(16, 32))); auto texture = sf::Texture::create(sf::Vector2u(16, 32)).value();
const sf::Image image1(sf::Vector2u(16, 16), sf::Color::Red); const sf::Image image1(sf::Vector2u(16, 16), sf::Color::Red);
texture.update(image1); texture.update(image1);
const sf::Image image2(sf::Vector2u(16, 16), sf::Color::Green); const sf::Image image2(sf::Vector2u(16, 16), sf::Color::Green);
@ -243,7 +223,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("Set/get smooth") SECTION("Set/get smooth")
{ {
sf::Texture texture; sf::Texture texture = sf::Texture::create({64, 64}).value();
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
texture.setSmooth(true); texture.setSmooth(true);
CHECK(texture.isSmooth()); CHECK(texture.isSmooth());
@ -251,19 +231,9 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());
} }
SECTION("Set/get srgb")
{
sf::Texture texture;
CHECK(!texture.isSrgb());
texture.setSrgb(true);
CHECK(texture.isSrgb());
texture.setSrgb(false);
CHECK(!texture.isSrgb());
}
SECTION("Set/get repeated") SECTION("Set/get repeated")
{ {
sf::Texture texture; sf::Texture texture = sf::Texture::create({64, 64}).value();
CHECK(!texture.isRepeated()); CHECK(!texture.isRepeated());
texture.setRepeated(true); texture.setRepeated(true);
CHECK(texture.isRepeated()); CHECK(texture.isRepeated());
@ -273,9 +243,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("generateMipmap()") SECTION("generateMipmap()")
{ {
sf::Texture texture; sf::Texture texture = sf::Texture::create({100, 100}).value();
CHECK(!texture.generateMipmap());
CHECK(texture.create({100, 100}));
CHECK(texture.generateMipmap()); CHECK(texture.generateMipmap());
} }
@ -284,17 +252,13 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
constexpr std::uint8_t blue[] = {0x00, 0x00, 0xFF, 0xFF}; constexpr std::uint8_t blue[] = {0x00, 0x00, 0xFF, 0xFF};
constexpr std::uint8_t green[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF}; constexpr std::uint8_t green[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF};
sf::Texture texture1; auto texture1 = sf::Texture::create(sf::Vector2u(1, 1), true).value();
REQUIRE(texture1.create(sf::Vector2u(1, 1)));
texture1.update(blue); texture1.update(blue);
texture1.setSrgb(true);
texture1.setSmooth(false); texture1.setSmooth(false);
texture1.setRepeated(true); texture1.setRepeated(true);
sf::Texture texture2; auto texture2 = sf::Texture::create(sf::Vector2u(2, 1), false).value();
REQUIRE(texture2.create(sf::Vector2u(2, 1)));
texture2.update(green); texture2.update(green);
texture2.setSrgb(false);
texture2.setSmooth(true); texture2.setSmooth(true);
texture2.setRepeated(false); texture2.setRepeated(false);
@ -302,7 +266,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
CHECK_FALSE(texture1.isSrgb()); CHECK_FALSE(texture1.isSrgb());
CHECK(texture1.isSmooth()); CHECK(texture1.isSmooth());
CHECK_FALSE(texture1.isRepeated()); CHECK_FALSE(texture1.isRepeated());
CHECK(texture2.isSrgb()); // Cannot check texture2.isSrgb() because Srgb is sometimes disabled when using OpenGL ES
CHECK_FALSE(texture2.isSmooth()); CHECK_FALSE(texture2.isSmooth());
CHECK(texture2.isRepeated()); CHECK(texture2.isRepeated());

View File

@ -30,11 +30,7 @@ int main()
window.setIcon(icon); window.setIcon(icon);
// Load a sprite to display // Load a sprite to display
sf::Texture texture; const auto texture = sf::Texture::loadFromFile(resourcePath() / "background.jpg").value();
if (!texture.loadFromFile(resourcePath() / "background.jpg"))
{
return EXIT_FAILURE;
}
sf::Sprite sprite(texture); sf::Sprite sprite(texture);
// Create a graphical text to display // Create a graphical text to display

View File

@ -28,11 +28,7 @@ int main()
window.setIcon(icon); window.setIcon(icon);
// Load a sprite to display // Load a sprite to display
sf::Texture texture; const auto texture = sf::Texture::loadFromFile("background.jpg").value();
if (!texture.loadFromFile("background.jpg"))
{
return EXIT_FAILURE;
}
sf::Sprite sprite(texture); sf::Sprite sprite(texture);
// Create a graphical text to display // Create a graphical text to display