From e509f011807fcea5c8b978b5e311c4bb57488cf2 Mon Sep 17 00:00:00 2001 From: Laurent Gomila Date: Fri, 22 Jul 2011 22:31:27 +0200 Subject: [PATCH] Split sf::Image into sf::Image and sf::Texture (implements issue #18) --- examples/opengl/OpenGL.cpp | 10 +- examples/pong/Pong.cpp | 20 +- examples/shader/Shader.cpp | 49 +- examples/win32/Win32.cpp | 10 +- include/SFML/Audio/Sound.hpp | 10 +- include/SFML/Audio/SoundBuffer.hpp | 4 +- include/SFML/Graphics.hpp | 3 +- include/SFML/Graphics/Drawable.hpp | 21 +- include/SFML/Graphics/Font.hpp | 16 +- include/SFML/Graphics/Glyph.hpp | 4 +- include/SFML/Graphics/Image.hpp | 320 ++-------- include/SFML/Graphics/RenderTarget.hpp | 4 +- .../{RenderImage.hpp => RenderTexture.hpp} | 124 ++-- include/SFML/Graphics/RenderWindow.hpp | 20 +- include/SFML/Graphics/Renderer.hpp | 53 +- include/SFML/Graphics/Shader.hpp | 36 +- include/SFML/Graphics/Shape.hpp | 2 +- include/SFML/Graphics/Sprite.hpp | 119 ++-- include/SFML/Graphics/Texture.hpp | 551 ++++++++++++++++ include/SFML/Graphics/View.hpp | 4 +- include/SFML/System/InputStream.hpp | 8 +- include/SFML/System/Resource.hpp | 4 +- src/SFML/Audio/Sound.cpp | 6 +- src/SFML/Graphics/CMakeLists.txt | 18 +- src/SFML/Graphics/Drawable.cpp | 28 +- src/SFML/Graphics/Font.cpp | 35 +- src/SFML/Graphics/Image.cpp | 599 ++---------------- .../{RenderImage.cpp => RenderTexture.cpp} | 73 +-- ...derImageImpl.cpp => RenderTextureImpl.cpp} | 4 +- ...derImageImpl.hpp => RenderTextureImpl.hpp} | 22 +- ...fault.cpp => RenderTextureImplDefault.cpp} | 16 +- ...fault.hpp => RenderTextureImplDefault.hpp} | 26 +- ...geImplFBO.cpp => RenderTextureImplFBO.cpp} | 24 +- ...geImplFBO.hpp => RenderTextureImplFBO.hpp} | 30 +- src/SFML/Graphics/RenderWindow.cpp | 25 + src/SFML/Graphics/Renderer.cpp | 12 +- src/SFML/Graphics/Shader.cpp | 2 +- src/SFML/Graphics/Sprite.cpp | 57 +- src/SFML/Graphics/Text.cpp | 4 +- src/SFML/Graphics/Texture.cpp | 506 +++++++++++++++ 40 files changed, 1585 insertions(+), 1294 deletions(-) rename include/SFML/Graphics/{RenderImage.hpp => RenderTexture.hpp} (66%) create mode 100644 include/SFML/Graphics/Texture.hpp rename src/SFML/Graphics/{RenderImage.cpp => RenderTexture.cpp} (58%) rename src/SFML/Graphics/{RenderImageImpl.cpp => RenderTextureImpl.cpp} (91%) rename src/SFML/Graphics/{RenderImageImpl.hpp => RenderTextureImpl.hpp} (80%) rename src/SFML/Graphics/{RenderImageImplDefault.cpp => RenderTextureImplDefault.cpp} (83%) rename src/SFML/Graphics/{RenderImageImplDefault.hpp => RenderTextureImplDefault.hpp} (82%) rename src/SFML/Graphics/{RenderImageImplFBO.cpp => RenderTextureImplFBO.cpp} (79%) rename src/SFML/Graphics/{RenderImageImplFBO.hpp => RenderTextureImplFBO.hpp} (80%) create mode 100644 src/SFML/Graphics/Texture.cpp diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index 0be2ea577..fd00839d5 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -18,14 +18,14 @@ int main() sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL", sf::Style::Default, sf::ContextSettings(32)); // Create a sprite for the background - sf::Image backgroundImage; - if (!backgroundImage.LoadFromFile("resources/background.jpg")) + sf::Texture backgroundTexture; + if (!backgroundTexture.LoadFromFile("resources/background.jpg")) return EXIT_FAILURE; - sf::Sprite background(backgroundImage); + sf::Sprite background(backgroundTexture); // Load an OpenGL texture. - // We could directly use a sf::Image as an OpenGL texture (with its Bind() member function), - // but here we want more control on it (generate mipmaps, ...) so we create a new one from the image pixels + // We could directly use a sf::Texture as an OpenGL texture (with its Bind() member function), + // but here we want more control on it (generate mipmaps, ...) so we create a new one from an image GLuint texture = 0; { sf::Image image; diff --git a/examples/pong/Pong.cpp b/examples/pong/Pong.cpp index 1d03d9ef0..0e9abfc45 100644 --- a/examples/pong/Pong.cpp +++ b/examples/pong/Pong.cpp @@ -33,12 +33,12 @@ int main() } sf::Sound ballSound(ballSoundBuffer); - // Load the images used in the game - sf::Image backgroundImage, leftPaddleImage, rightPaddleImage, ballImage; - if (!backgroundImage.LoadFromFile("resources/background.jpg") || - !leftPaddleImage.LoadFromFile("resources/paddle_left.png") || - !rightPaddleImage.LoadFromFile("resources/paddle_right.png") || - !ballImage.LoadFromFile("resources/ball.png")) + // Load the textures used in the game + sf::Texture backgroundTexture, leftPaddleTexture, rightPaddleTexture, ballTexture; + if (!backgroundTexture.LoadFromFile("resources/background.jpg") || + !leftPaddleTexture.LoadFromFile("resources/paddle_left.png") || + !rightPaddleTexture.LoadFromFile("resources/paddle_right.png") || + !ballTexture.LoadFromFile("resources/ball.png")) { return EXIT_FAILURE; } @@ -56,10 +56,10 @@ int main() end.SetColor(sf::Color(50, 50, 250)); // Create the sprites of the background, the paddles and the ball - sf::Sprite background(backgroundImage); - sf::Sprite leftPaddle(leftPaddleImage); - sf::Sprite rightPaddle(rightPaddleImage); - sf::Sprite ball(ballImage); + sf::Sprite background(backgroundTexture); + sf::Sprite leftPaddle(leftPaddleTexture); + sf::Sprite rightPaddle(rightPaddleTexture); + sf::Sprite ball(ballTexture); leftPaddle.Move(10, (window.GetView().GetSize().y - leftPaddle.GetSize().y) / 2); rightPaddle.Move(window.GetView().GetSize().x - rightPaddle.GetSize().x - 10, (window.GetView().GetSize().y - rightPaddle.GetSize().y) / 2); diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index 5a75fbbb9..40ca7324f 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -4,7 +4,7 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include void DisplayError(); @@ -88,32 +88,31 @@ int main() // Create the main window sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader"); - // Create the render image - sf::RenderImage image; - if (!image.Create(window.GetWidth(), window.GetHeight())) + // Create the render texture + sf::RenderTexture texture; + if (!texture.Create(window.GetWidth(), window.GetHeight())) return EXIT_FAILURE; - // Load a background image to display - sf::Image backgroundImage; - if (!backgroundImage.LoadFromFile("resources/background.jpg")) + // Load a background texture to display + sf::Texture backgroundTexture; + if (!backgroundTexture.LoadFromFile("resources/background.jpg")) return EXIT_FAILURE; - sf::Sprite background(backgroundImage); - backgroundImage.SetSmooth(false); + sf::Sprite background(backgroundTexture); // Load a sprite which we'll move into the scene - sf::Image entityImage; - if (!entityImage.LoadFromFile("resources/sprite.png")) + sf::Texture entityTexture; + if (!entityTexture.LoadFromFile("resources/sprite.png")) return EXIT_FAILURE; - sf::Sprite entity(entityImage); + sf::Sprite entity(entityTexture); // Load the text font sf::Font font; if (!font.LoadFromFile("resources/sansation.ttf")) return EXIT_FAILURE; - // Load the image needed for the wave shader - sf::Image waveImage; - if (!waveImage.LoadFromFile("resources/wave.jpg")) + // Load the texture needed for the wave shader + sf::Texture waveTexture; + if (!waveTexture.LoadFromFile("resources/wave.jpg")) return EXIT_FAILURE; // Load all shaders @@ -138,7 +137,7 @@ int main() shaders["edge"].SetCurrentTexture("texture"); shaders["fisheye"].SetCurrentTexture("texture"); shaders["wave"].SetCurrentTexture("texture"); - shaders["wave"].SetTexture("wave", waveImage); + shaders["wave"].SetTexture("wave", waveTexture); shaders["pixelate"].SetCurrentTexture("texture"); // Define a string for displaying the description of the current shader @@ -211,19 +210,19 @@ int main() globalShader.Update(mouseX, mouseY); // Animate the entity - float entityX = (cos(clock.GetElapsedTime() * 0.0013f) + 1.2f) * 300; - float entityY = (cos(clock.GetElapsedTime() * 0.0008f) + 1.2f) * 200; + float entityX = (std::cos(clock.GetElapsedTime() * 0.0013f) + 1.2f) * 300; + float entityY = (std::cos(clock.GetElapsedTime() * 0.0008f) + 1.2f) * 200; entity.SetPosition(entityX, entityY); entity.Rotate(window.GetFrameTime() * 0.1f); - // Draw the background and the moving entity to the render image - image.Clear(); - image.Draw(background, backgroundShader.GetShader()); - image.Draw(entity, entityShader.GetShader()); - image.Display(); + // Draw the background and the moving entity to the render texture + texture.Clear(); + texture.Draw(background, backgroundShader.GetShader()); + texture.Draw(entity, entityShader.GetShader()); + texture.Display(); - // Draw the contents of the render image to the window - sf::Sprite screen(image.GetImage()); + // Draw the contents of the render texture to the window + sf::Sprite screen(texture.GetTexture()); window.Draw(screen, globalShader.GetShader()); // Draw the interface texts diff --git a/examples/win32/Win32.cpp b/examples/win32/Win32.cpp index 705f482f6..97c94e42d 100644 --- a/examples/win32/Win32.cpp +++ b/examples/win32/Win32.cpp @@ -75,12 +75,12 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT) sf::RenderWindow SFMLView1(view1); sf::RenderWindow SFMLView2(view2); - // Load some images to display - sf::Image image1, image2; - if (!image1.LoadFromFile("resources/image1.jpg") || !image2.LoadFromFile("resources/image2.jpg")) + // Load some textures to display + sf::Texture texture1, texture2; + if (!texture1.LoadFromFile("resources/image1.jpg") || !texture2.LoadFromFile("resources/image2.jpg")) return EXIT_FAILURE; - sf::Sprite sprite1(image1); - sf::Sprite sprite2(image2); + sf::Sprite sprite1(texture1); + sf::Sprite sprite2(texture2); sprite1.SetOrigin(sprite1.GetSize() / 2.f); sprite1.SetPosition(sprite1.GetSize() / 2.f); diff --git a/include/SFML/Audio/Sound.hpp b/include/SFML/Audio/Sound.hpp index efa928ee7..c0d7d8b6d 100644 --- a/include/SFML/Audio/Sound.hpp +++ b/include/SFML/Audio/Sound.hpp @@ -52,16 +52,12 @@ public : Sound(); //////////////////////////////////////////////////////////// - /// \brief Construct the sound with parameters + /// \brief Construct the sound with a buffer /// - /// \param buffer Sound buffer containing the audio data to play with the sound - /// \param loop Should the sound loop? - /// \param pitch Pitch of the sound - /// \param volume Volume of the sound, in the range [0, 100] - /// \param position 3D position of the sound source in the audio scene + /// \param buffer Sound buffer containing the audio data to play with the sound /// //////////////////////////////////////////////////////////// - Sound(const SoundBuffer& buffer, bool loop = false, float pitch = 1.f, float volume = 100.f, const Vector3f& position = Vector3f(0, 0, 0)); + Sound(const SoundBuffer& buffer); //////////////////////////////////////////////////////////// /// \brief Copy constructor diff --git a/include/SFML/Audio/SoundBuffer.hpp b/include/SFML/Audio/SoundBuffer.hpp index 5c7d65e8f..07a717f02 100644 --- a/include/SFML/Audio/SoundBuffer.hpp +++ b/include/SFML/Audio/SoundBuffer.hpp @@ -301,8 +301,8 @@ private : /// The sound is then restituted by playing these samples at /// a high rate (for example, 44100 samples per second is the /// standard rate used for playing CDs). In short, audio samples -/// are like image pixels, and a sf::SoundBuffer is similar to -/// a sf::Image. +/// are like texture pixels, and a sf::SoundBuffer is similar to +/// a sf::Texture. /// /// A sound buffer can be loaded from a file (see LoadFromFile() /// for the complete list of supported formats), from memory, from diff --git a/include/SFML/Graphics.hpp b/include/SFML/Graphics.hpp index 7ad60b2a5..ba9943311 100644 --- a/include/SFML/Graphics.hpp +++ b/include/SFML/Graphics.hpp @@ -35,12 +35,13 @@ #include #include #include -#include +#include #include #include #include #include #include +#include #include diff --git a/include/SFML/Graphics/Drawable.hpp b/include/SFML/Graphics/Drawable.hpp index d1644ea59..fbee1be85 100644 --- a/include/SFML/Graphics/Drawable.hpp +++ b/include/SFML/Graphics/Drawable.hpp @@ -63,17 +63,6 @@ class SFML_API Drawable { public : - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param position Position of the object - /// \param scale Scale factor - /// \param rotation Orientation, in degrees - /// \param color Global color of the object - /// - //////////////////////////////////////////////////////////// - Drawable(const Vector2f& position = Vector2f(0, 0), const Vector2f& scale = Vector2f(1, 1), float rotation = 0.f, const Color& color = Color(255, 255, 255)); - //////////////////////////////////////////////////////////// /// \brief Virtual destructor /// @@ -452,6 +441,12 @@ public : protected : + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Drawable(); + //////////////////////////////////////////////////////////// /// \brief Get the transform matrix of the object /// @@ -532,7 +527,7 @@ private : /// \li transformations (position, rotation, scale, local origin) /// \li global overlay color /// \li blending mode with background pixels -/// \li the ability to be drawn on a sf::RenderTarget (either RenderWindow or RenderImage) +/// \li the ability to be drawn on a sf::RenderTarget (either RenderWindow or RenderTexture) /// /// Please note that all these attributes are hardware accelerated, /// therefore they are extremely cheap to use (unlike older @@ -591,7 +586,7 @@ private : /// target.Draw(mySubSprite); /// } /// -/// sf::Image myTexture; +/// sf::Texture myTexture; /// sf::Sprite mySubSprite; /// }; /// \endcode diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 37945f9ed..d2e37315b 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -174,18 +174,18 @@ public : int GetLineSpacing(unsigned int characterSize) const; //////////////////////////////////////////////////////////// - /// \brief Retrieve the image containing the loaded glyphs of a certain size + /// \brief Retrieve the texture containing the loaded glyphs of a certain size /// - /// The contents of the returned image changes as more glyphs + /// The contents of the returned texture changes as more glyphs /// are requested, thus it is not very relevant. It is mainly /// used internally by sf::Text. /// /// \param characterSize Reference character size /// - /// \return Image containing the glyphs of the requested size + /// \return Texture containing the glyphs of the requested size /// //////////////////////////////////////////////////////////// - const Image& GetImage(unsigned int characterSize) const; + const Texture& GetTexture(unsigned int characterSize) const; //////////////////////////////////////////////////////////// /// \brief Overload of assignment operator @@ -240,8 +240,8 @@ private : Page(); GlyphTable Glyphs; ///< Table mapping code points to their corresponding glyph - Image Texture; ///< Image containing the pixels of the glyphs - unsigned int NextRow; ///< Y position of the next new row in the image + Texture Texture; ///< Texture containing the pixels of the glyphs + unsigned int NextRow; ///< Y position of the next new row in the texture std::vector Rows; ///< List containing the position of all the existing rows }; @@ -288,7 +288,7 @@ private : //////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////// - typedef std::map PageTable; ///< Table mapping a character size to its page (image) + typedef std::map PageTable; ///< Table mapping a character size to its page (texture) //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/Glyph.hpp b/include/SFML/Graphics/Glyph.hpp index 1b7f42f6c..c0a4fdaf2 100644 --- a/include/SFML/Graphics/Glyph.hpp +++ b/include/SFML/Graphics/Glyph.hpp @@ -53,7 +53,7 @@ public : //////////////////////////////////////////////////////////// int Advance; ///< Offset to move horizontically to the next character IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - IntRect SubRect; ///< Texture coordinates of the glyph inside the font's image + IntRect SubRect; ///< Texture coordinates of the glyph inside the font's texture }; } // namespace sf @@ -70,7 +70,7 @@ public : /// /// The sf::Glyph structure provides the information needed /// to handle the glyph: -/// \li its coordinates in the font's image +/// \li its coordinates in the font's texture /// \li its bounding rect /// \li the offset to apply to get the starting position of the next glyph /// diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index 902ffa90e..c1a80acfc 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -29,7 +29,6 @@ // Headers //////////////////////////////////////////////////////////// #include -#include #include #include #include @@ -38,16 +37,13 @@ namespace sf { -class Renderer; -class RenderImage; -class RenderWindow; class InputStream; //////////////////////////////////////////////////////////// /// \brief Class for loading, manipulating and saving images /// //////////////////////////////////////////////////////////// -class SFML_API Image : public Resource, GlResource +class SFML_API Image { public : @@ -60,18 +56,29 @@ public : Image(); //////////////////////////////////////////////////////////// - /// \brief Copy constructor + /// \brief Create the image and fill it with a unique color /// - /// \param copy instance to copy + /// \param width Width of the image + /// \param height Height of the image + /// \param color Fill color /// //////////////////////////////////////////////////////////// - Image(const Image& copy); + void Create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); //////////////////////////////////////////////////////////// - /// \brief Destructor + /// \brief Create the image from an arry of pixels + /// + /// The \a pixels array is assumed to contain 32-bits RGBA pixels, + /// and have the given \a width and \a height. If not, this is + /// an undefined behaviour. + /// If \a pixels is null, an empty image is created. + /// + /// \param width Width of the image + /// \param height Height of the image + /// \param pixels Array of pixels to copy to the image /// //////////////////////////////////////////////////////////// - ~Image(); + void Create(unsigned int width, unsigned int height, const Uint8* pixels); //////////////////////////////////////////////////////////// /// \brief Load the image from a file on disk @@ -79,15 +86,13 @@ public : /// The supported image formats are bmp, png, tga, jpg, gif, /// psd, hdr and pic. Some format options are not supported, /// like progressive jpeg. - /// The maximum size for an image depends on the graphics - /// driver and can be retrieve with the GetMaximumSize function. /// If this function fails, the image is left unchanged. /// /// \param filename Path of the image file to load /// /// \return True if loading was successful /// - /// \see LoadFromMemory, LoadFromStream, LoadFromPixels, SaveToFile + /// \see LoadFromMemory, LoadFromStream, SaveToFile /// //////////////////////////////////////////////////////////// bool LoadFromFile(const std::string& filename); @@ -98,8 +103,6 @@ public : /// The supported image formats are bmp, png, tga, jpg, gif, /// psd, hdr and pic. Some format options are not supported, /// like progressive jpeg. - /// The maximum size for an image depends on the graphics - /// driver and can be retrieve with the GetMaximumSize function. /// If this function fails, the image is left unchanged. /// /// \param data Pointer to the file data in memory @@ -107,7 +110,7 @@ public : /// /// \return True if loading was successful /// - /// \see LoadFromFile, LoadFromStream, LoadFromPixels + /// \see LoadFromFile, LoadFromStream /// //////////////////////////////////////////////////////////// bool LoadFromMemory(const void* data, std::size_t size); @@ -126,30 +129,11 @@ public : /// /// \return True if loading was successful /// - /// \see LoadFromFile, LoadFromMemory, LoadFromPixels + /// \see LoadFromFile, LoadFromMemory /// //////////////////////////////////////////////////////////// bool LoadFromStream(InputStream& stream); - //////////////////////////////////////////////////////////// - /// \brief Load the image from an array of pixels - /// - /// The \a pixels argument must point to an array of 32 bits - /// RGBA pixels. In other words, the pixel array must have - /// this memory layout: [r0 g0 b0 a0 r1 g1 b1 a1 r2...] - /// If this function fails, the image is left unchanged. - /// - /// \param width Width of the image - /// \param height Height of the image - /// \param pixels Pointer to the pixels in memory - /// - /// \return True if loading was successful - /// - /// \see LoadFromFile, LoadFromMemory, SaveToFile - /// - //////////////////////////////////////////////////////////// - bool LoadFromPixels(unsigned int width, unsigned int height, const Uint8* pixels); - //////////////////////////////////////////////////////////// /// \brief Save the image to a file on disk /// @@ -162,27 +146,33 @@ public : /// /// \return True if saving was successful /// - /// \see LoadFromFile, LoadFromMemory, LoadFromPixels + /// \see Create, LoadFromFile, LoadFromMemory /// //////////////////////////////////////////////////////////// bool SaveToFile(const std::string& filename) const; //////////////////////////////////////////////////////////// - /// \brief Create the image and fill it with a unique color + /// \brief Return the width of the image /// - /// If this function fails, the image is left unchanged. + /// \return Width in pixels /// - /// \param width Width of the image - /// \param height Height of the image - /// \param color Fill color - /// - /// \return True if creation was successful + /// \see GetHeight /// //////////////////////////////////////////////////////////// - bool Create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); + unsigned int GetWidth() const; //////////////////////////////////////////////////////////// - /// \brief Create a transparency mask from a specified colorkey + /// \brief Return the height of the image + /// + /// \return Height in pixels + /// + /// \see GetWidth + /// + //////////////////////////////////////////////////////////// + unsigned int GetHeight() const; + + //////////////////////////////////////////////////////////// + /// \brief Create a transparency mask from a specified color-key /// /// This function sets the alpha value of every pixel matching /// the given color to \a alpha (0 by default), so that they @@ -197,11 +187,11 @@ public : //////////////////////////////////////////////////////////// /// \brief Copy pixels from another image onto this one /// - /// This function does a slow pixel copy and should only - /// be used at initialization time. It can be used to prepare - /// a complex static image from several others, but if you - /// need this kind of feature in real-time you'd better use - /// sf::RenderImage. + /// This function does a slow pixel copy and should not be + /// used intensively. It can be used to prepare a complex + /// static image from several others, but if you need this + /// kind of feature in real-time you'd better use sf::RenderTexture. + /// /// If \a sourceRect is empty, the whole image is copied. /// If \a applyAlpha is set to true, the transparency of /// source pixels is applied. If it is false, the pixels are @@ -216,22 +206,6 @@ public : //////////////////////////////////////////////////////////// void Copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false); - //////////////////////////////////////////////////////////// - /// \brief Copy the contents of a window to the image - /// - /// If \a sourceRect is empty, the whole window is copied. - /// Warning: this is a slow operation, if you need to draw - /// dynamic contents to an image then use sf::RenderImage. - /// If this function fails, the image is left unchanged. - /// - /// \param window Window to capture - /// \param sourceRect Sub-rectangle of the screen to copy - /// - /// \return True if copy was successful - /// - //////////////////////////////////////////////////////////// - bool CopyScreen(RenderWindow& window, const IntRect& sourceRect = IntRect(0, 0, 0, 0)); - //////////////////////////////////////////////////////////// /// \brief Change the color of a pixel /// @@ -239,9 +213,9 @@ public : /// coordinates, using out-of-range values will result in /// an undefined behaviour. /// - /// \param x X coordinate of pixel to change - /// \param y Y coordinate of pixel to change - /// \param color New color of the pixel + /// \param x X coordinate of pixel to change + /// \param y Y coordinate of pixel to change + /// \param color New color of the pixel /// /// \see GetPixel /// @@ -273,207 +247,19 @@ public : /// modify the image, so you should never store it for too long. /// If the image is empty, a null pointer is returned. /// - /// \return Const pointer to the array of pixels + /// \return Read-only pointer to the array of pixels /// //////////////////////////////////////////////////////////// const Uint8* GetPixelsPtr() const; - //////////////////////////////////////////////////////////// - /// \brief Update the whole image from an array of pixels - /// - /// The \a pixels array is assumed to have the same size as - /// the image, and to store RGBA 32 bits pixels. - /// See the other overload of this function to update only - /// a sub-rectangle of the image. - /// This function does nothing if \a pixels is null. - /// - /// \param pixels Array of pixels to write to the image - /// - //////////////////////////////////////////////////////////// - void UpdatePixels(const Uint8* pixels); - - //////////////////////////////////////////////////////////// - /// \brief Update a sub-rectangle of the image from an array of pixels - /// - /// The \a pixels array is assumed to store RGBA 32 bits pixels. - /// Warning: for performances reasons, this function doesn't - /// perform any check; thus you're responsible of ensuring that - /// \a rectangle does not exceed the image size, and that - /// \a pixels contains enough elements. - /// This function does nothing if \a pixels is null. - /// See the other overload of this function to update the - /// whole image. - /// - /// \param rectangle Sub-rectangle of the image to update - /// \param pixels Array of pixels to write to the image - /// - //////////////////////////////////////////////////////////// - void UpdatePixels(const Uint8* pixels, const IntRect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Activate the image for rendering - /// - /// This function is mainly used internally by the SFML - /// render system. However it can be useful when - /// using sf::Image together with OpenGL code (it calls - /// glBindTexture). - /// - //////////////////////////////////////////////////////////// - void Bind() const; - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable the smooth filter - /// - /// When the filter is activated, the image appears smoother - /// so that pixels are less noticeable. However if you want - /// the image to look exactly the same as its source file, you - /// should disable it. - /// The smooth filter is disabled by default. - /// - /// \param smooth True to enable smoothing, false to disable it - /// - /// \see IsSmooth - /// - //////////////////////////////////////////////////////////// - void SetSmooth(bool smooth); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether the smooth filter is enabled or not - /// - /// \return True if smoothing is enabled, false if it is disabled - /// - /// \see SetSmooth - /// - //////////////////////////////////////////////////////////// - bool IsSmooth() const; - - //////////////////////////////////////////////////////////// - /// \brief Return the width of the image - /// - /// \return Width in pixels - /// - /// \see GetHeight - /// - //////////////////////////////////////////////////////////// - unsigned int GetWidth() const; - - //////////////////////////////////////////////////////////// - /// \brief Return the height of the image - /// - /// \return Height in pixels - /// - /// \see GetWidth - /// - //////////////////////////////////////////////////////////// - unsigned int GetHeight() const; - - //////////////////////////////////////////////////////////// - /// \brief Convert a rectangle of pixels into texture coordinates - /// - /// This function is used by code that needs to map the image - /// to some OpenGL geometry. It converts the source rectangle, - /// expressed in pixels, to float coordinates in the range [0, 1]. - /// - /// \param rectangle Rectangle to convert - /// - /// \return Texture coordinates corresponding to \a rectangle - /// - //////////////////////////////////////////////////////////// - FloatRect GetTexCoords(const IntRect& rectangle) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the maximum image size allowed - /// - /// This maximum size is defined by the graphics driver. - /// You can expect a value of 512 pixels for low-end graphics - /// card, and up to 8192 pixels for newer hardware. - /// - /// \return Maximum size allowed for images, in pixels - /// - //////////////////////////////////////////////////////////// - static unsigned int GetMaximumSize(); - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - Image& operator =(const Image& right); - private : - friend class Renderer; - friend class RenderImage; - - //////////////////////////////////////////////////////////// - /// \brief Get a valid image size according to hardware support - /// - /// This function checks whether the graphics driver supports - /// non power of two sizes or not, and adjusts the size - /// accordingly. - /// The returned size is greater than or equal to the original size. - /// - /// \param Size size to convert - /// - /// \return Valid nearest size (greater than or equal to specified size) - /// - //////////////////////////////////////////////////////////// - static unsigned int GetValidSize(unsigned int size); - - //////////////////////////////////////////////////////////// - /// \brief Create the OpenGL texture - /// - /// If this function fails, the image's members are left unchanged. - /// - /// \param width Texture width - /// \param height Texture height - /// - /// \return True if texture was successfully created, false if it failed - /// - //////////////////////////////////////////////////////////// - bool CreateTexture(unsigned int width, unsigned int height); - - //////////////////////////////////////////////////////////// - /// \brief Make sure that the texture in video memory is - /// synchronized with the pixels cache - /// - //////////////////////////////////////////////////////////// - void EnsureTextureUpdate() const; - - //////////////////////////////////////////////////////////// - /// \brief Make sure the pixels cache is synchronized with - /// the texture in video memory - /// - //////////////////////////////////////////////////////////// - void EnsureArrayUpdate() const; - - //////////////////////////////////////////////////////////// - /// \brief Make sure that the image is ready to be used - /// - //////////////////////////////////////////////////////////// - void Use() const; - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::vector ColorArray; ///< Array of colors - //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - unsigned int myWidth; ///< Image width - unsigned int myHeight; ///< Image Height - unsigned int myTextureWidth; ///< Actual texture width (can be greater than image width because of padding) - unsigned int myTextureHeight; ///< Actual texture height (can be greater than image height because of padding) - unsigned int myTexture; ///< Internal texture identifier - bool myIsSmooth; ///< Status of the smooth filter - mutable ColorArray myPixels; ///< Pixels of the image - mutable bool myTextureUpdated; ///< Status of synchronization between pixels in central memory and the internal texture un video memory - mutable bool myArrayUpdated; ///< Status of synchronization between pixels in central memory and the internal texture un video memory - mutable bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation + unsigned int myWidth; ///< Image width + unsigned int myHeight; ///< Image Height + std::vector myPixels; ///< Pixels of the image }; } // namespace sf @@ -489,7 +275,7 @@ private : /// sf::Image is an abstraction to manipulate images /// as bidimensional arrays of pixels. The class provides /// functions to load, read, write and save pixels, as well -/// as many other useful functions to... +/// as many other useful functions. /// /// sf::Image can handle a unique internal representation of /// pixels, which is RGBA 32 bits. This means that a pixel @@ -497,8 +283,8 @@ private : /// channels -- just like a sf::Color. /// All the functions that return an array of pixels follow /// this rule, and all parameters that you pass to sf::Image -/// functions (such as LoadFromPixels or UpdatePixels) must -/// use this representation as well. +/// functions (such as LoadFromPixels) must use this +/// representation as well. /// /// A sf::Image can be copied, but it is a heavy resource and /// if possible you should always use [const] references to @@ -506,7 +292,7 @@ private : /// /// Usage example: /// \code -/// // Load an image file +/// // Load an image file from a file /// sf::Image background; /// if (!background.LoadFromFile("background.jpg")) /// return -1; @@ -529,6 +315,6 @@ private : /// return -1; /// \endcode /// -/// \see sf::Sprite +/// \see sf::Texture /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp index 582ecd574..961a26a21 100644 --- a/include/SFML/Graphics/RenderTarget.hpp +++ b/include/SFML/Graphics/RenderTarget.hpp @@ -41,7 +41,7 @@ class Drawable; class Shader; //////////////////////////////////////////////////////////// -/// \brief Base class for all render targets (window, image, ...) +/// \brief Base class for all render targets (window, texture, ...) /// //////////////////////////////////////////////////////////// class SFML_API RenderTarget : NonCopyable @@ -331,6 +331,6 @@ private : /// OpenGL states are not messed up by calling the SaveGLStates / /// RestoreGLStates functions. /// -/// \see sf::RenderWindow, sf::RenderImage, sf::View +/// \see sf::RenderWindow, sf::RenderTexture, sf::View /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderImage.hpp b/include/SFML/Graphics/RenderTexture.hpp similarity index 66% rename from include/SFML/Graphics/RenderImage.hpp rename to include/SFML/Graphics/RenderTexture.hpp index ef6703b95..6dc71dca0 100644 --- a/include/SFML/Graphics/RenderImage.hpp +++ b/include/SFML/Graphics/RenderTexture.hpp @@ -22,13 +22,13 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_RENDERIMAGE_HPP -#define SFML_RENDERIMAGE_HPP +#ifndef SFML_RENDERTEXTURE_HPP +#define SFML_RENDERTEXTURE_HPP //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include @@ -36,48 +36,48 @@ namespace sf { namespace priv { - class RenderImageImpl; + class RenderTextureImpl; } //////////////////////////////////////////////////////////// -/// \brief Target for off-screen 2D rendering into an image +/// \brief Target for off-screen 2D rendering into an texture /// //////////////////////////////////////////////////////////// -class SFML_API RenderImage : public RenderTarget +class SFML_API RenderTexture : public RenderTarget { public : //////////////////////////////////////////////////////////// /// \brief Default constructor /// - /// Constructs an empty, invalid render-image. You must - /// call Create to have a valid render-image. + /// Constructs an empty, invalid render-texture. You must + /// call Create to have a valid render-texture. /// /// \see Create /// //////////////////////////////////////////////////////////// - RenderImage(); + RenderTexture(); //////////////////////////////////////////////////////////// /// \brief Destructor /// //////////////////////////////////////////////////////////// - virtual ~RenderImage(); + virtual ~RenderTexture(); //////////////////////////////////////////////////////////// - /// \brief Create the render-image + /// \brief Create the render-texture /// - /// Before calling this function, the render-image is in + /// 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-image. + /// doing anything with the render-texture. /// The last parameter, \a depthBuffer, is useful if you want - /// to use the render-image for 3D OpenGL rendering that requires + /// to use the render-texture for 3D OpenGL rendering that requires /// a depth-buffer. Otherwise it is unnecessary, and you should /// leave this parameter to false (which is its default value). /// - /// \param width Width of the render-image - /// \param height Height of the render-image - /// \param depthBuffer Do you want this render-image to have a depth buffer? + /// \param width Width of the render-texture + /// \param height Height of the render-texture + /// \param depthBuffer Do you want this render-texture to have a depth buffer? /// /// \return True if creation has been successful /// @@ -85,9 +85,9 @@ public : bool Create(unsigned int width, unsigned int height, bool depthBuffer = false); //////////////////////////////////////////////////////////// - /// \brief Enable or disable image smoothing + /// \brief Enable or disable texture smoothing /// - /// This function is similar to Image::SetSmooth. + /// This function is similar to Texture::SetSmooth. /// This parameter is enabled by default. /// /// \param smooth True to enable smoothing, false to disable it @@ -100,7 +100,7 @@ public : //////////////////////////////////////////////////////////// /// \brief Tell whether the smooth filtering is enabled or not /// - /// \return True if image smoothing is enabled + /// \return True if texture smoothing is enabled /// /// \see SetSmooth /// @@ -108,12 +108,12 @@ public : bool IsSmooth() const; //////////////////////////////////////////////////////////// - /// \brief Activate of deactivate the render-image for rendering + /// \brief Activate of deactivate the render-texture for rendering /// - /// This function makes the render-image's context current for + /// This function makes the render-texture's context current for /// future OpenGL rendering operations (so you shouldn't care /// about it if you're not doing direct OpenGL stuff). - /// Only one context can be current on a thread, so if you + /// Only one context can be current in a thread, so if you /// want to draw OpenGL geometry to another render target /// (like a RenderWindow) don't forget to activate it again. /// @@ -125,18 +125,18 @@ public : bool SetActive(bool active = true); //////////////////////////////////////////////////////////// - /// \brief Update the contents of the target image + /// \brief Update the contents of the target texture /// - /// This function updates the target image with what + /// This function updates the target texture with what /// has been drawn so far. Like for windows, calling this /// function is mandatory at the end of rendering. Not calling - /// it may leave the image in an undefined state. + /// it may leave the texture in an undefined state. /// //////////////////////////////////////////////////////////// void Display(); //////////////////////////////////////////////////////////// - /// \brief Return the width of the rendering region of the image + /// \brief Return the width of the rendering region of the texture /// /// The returned value is the size that you passed to /// the Create function. @@ -149,7 +149,7 @@ public : virtual unsigned int GetWidth() const; //////////////////////////////////////////////////////////// - /// \brief Return the height of the rendering region of the image + /// \brief Return the height of the rendering region of the texture /// /// The returned value is the size that you passed to /// the Create function. @@ -162,25 +162,25 @@ public : virtual unsigned int GetHeight() const; //////////////////////////////////////////////////////////// - /// \brief Get a read-only reference to the target image + /// \brief Get a read-only reference to the target texture /// - /// After drawing to the render-image and calling Display, - /// you can retrieve the updated image using this function, + /// After drawing to the render-texture and calling Display, + /// you can retrieve the updated texture using this function, /// and draw it using a sprite (for example). - /// The internal sf::Image of a render-image is always the + /// The internal sf::Texture of a render-texture is always the /// same instance, so that it is possible to call this function - /// once and keep a reference to the image even after is it + /// once and keep a reference to the texture even after it is /// modified. /// - /// \return Const reference to the image + /// \return Const reference to the texture /// //////////////////////////////////////////////////////////// - const Image& GetImage() const; + const Texture& GetTexture() const; private : //////////////////////////////////////////////////////////// - /// \brief Activate the targt efor rendering + /// \brief Activate the target for rendering /// /// This function is called by the base class /// everytime it's going to use OpenGL calls. @@ -195,28 +195,28 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Image myImage; ///< Target image to draw on - priv::RenderImageImpl* myRenderImage; ///< Platform / hardware specific implementation + Texture myTexture; ///< Target texture to draw on + priv::RenderTextureImpl* myRenderTexture; ///< Platform/hardware specific implementation }; } // namespace sf -#endif // SFML_RENDERIMAGE_HPP +#endif // SFML_RENDERTEXTURE_HPP //////////////////////////////////////////////////////////// -/// \class sf::RenderImage +/// \class sf::RenderTexture /// \ingroup graphics /// -/// sf::RenderImage is the little brother of sf::RenderWindow. +/// sf::RenderTexture is the little brother of sf::RenderWindow. /// It implements the same 2D drawing and OpenGL-related functions /// (see their base class sf::RenderTarget for more details), /// the difference is that the result is stored in an off-screen -/// image rather than being show in a window. +/// texture rather than being show in a window. /// -/// Rendering to an image can be useful in a variety of situations: -/// \li precomputing a complex static image (like a level's background from multiple tiles) +/// Rendering to a texture can be useful in a variety of situations: +/// \li precomputing a complex static texture (like a level's background from multiple tiles) /// \li applying post-effects to the whole scene with shaders /// \li creating a sprite from a 3D object rendered with OpenGL /// \li etc. @@ -224,16 +224,12 @@ private : /// Usage example: /// /// \code -/// // First of all: make sure that rendering to image is supported -/// if (!sf::RenderImage::IsAvailable()) -/// return -1; -/// /// // Create a new render-window /// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); /// -/// // Create a new render-image -/// sf::RenderImage image; -/// if (!image.Create(500, 500)) +/// // Create a new render-texture +/// sf::RenderTexture texture; +/// if (!texture.Create(500, 500)) /// return -1 /// /// // The main loop @@ -242,22 +238,22 @@ private : /// // Event processing /// // ... /// -/// // Clear the whole image with red color -/// image.Clear(sf::Color::Red); +/// // Clear the whole texture with red color +/// texture.Clear(sf::Color::Red); /// -/// // Draw stuff to the image -/// image.Draw(sprite); // sprite is a sf::Sprite -/// image.Draw(shape); // shape is a sf::Shape -/// image.Draw(text); // text is a sf::Text +/// // Draw stuff to the texture +/// texture.Draw(sprite); // sprite is a sf::Sprite +/// texture.Draw(shape); // shape is a sf::Shape +/// texture.Draw(text); // text is a sf::Text /// -/// // We're done drawing to the image -/// image.Display(); +/// // We're done drawing to the texture +/// texture.Display(); /// /// // Now we start rendering to the window, clear it first /// window.Clear(); /// -/// // Draw the image -/// sf::Sprite sprite(image.GetImage()); +/// // Draw the texture +/// sf::Sprite sprite(texture.GetTexture()); /// window.Draw(sprite); /// /// // End the current frame and display its contents on screen @@ -265,11 +261,11 @@ private : /// } /// \endcode /// -/// Like sf::RenderWindow, sf::RenderImage is still able to render direct +/// Like sf::RenderWindow, sf::RenderTexture is still able to render direct /// OpenGL stuff. It is even possible to mix together OpenGL calls /// and regular SFML drawing commands. If you need a depth buffer for -/// 3D rendering, don't forget to request it when calling RenderImage::Create. +/// 3D rendering, don't forget to request it when calling RenderTexture::Create. /// -/// \see sf::RenderTarget, sf::RenderWindow, sf::View +/// \see sf::RenderTarget, sf::RenderWindow, sf::View, sf::Texture /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index 3fddc60a5..b6263d7f0 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -28,8 +28,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include #include +#include #include #include @@ -125,6 +125,22 @@ public : //////////////////////////////////////////////////////////// virtual unsigned int GetHeight() const; + //////////////////////////////////////////////////////////// + /// \brief Copy the current contents of the window to an image + /// + /// This is a slow operation, whose main purpose is to make + /// screenshots of the application. If you want to update an + /// image with the contents of the window and then use it for + /// drawing, you should rather use a sf::Texture and its + /// Update(Window&) function. + /// You can also draw things directly to a texture with the + /// sf::RenderTexture class. + /// + /// \return Image containing the captured contents + /// + //////////////////////////////////////////////////////////// + Image Capture() const; + private : //////////////////////////////////////////////////////////// @@ -260,6 +276,6 @@ private : /// } /// \endcode /// -/// \see sf::Window, sf::RenderTarget, sf::RenderImage, sf::View +/// \see sf::Window, sf::RenderTarget, sf::RenderTexture, sf::View /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Renderer.hpp b/include/SFML/Graphics/Renderer.hpp index b5fe0234a..4d774c804 100644 --- a/include/SFML/Graphics/Renderer.hpp +++ b/include/SFML/Graphics/Renderer.hpp @@ -38,8 +38,8 @@ namespace sf { -class Image; class Shader; +class Texture; //////////////////////////////////////////////////////////// /// \brief Handles the low-level rendering (states and geometry) @@ -120,9 +120,6 @@ public : //////////////////////////////////////////////////////////// /// \brief Set a new model-view matrix /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param matrix New model-view matrix /// /// \see ApplyModelView @@ -133,9 +130,6 @@ public : //////////////////////////////////////////////////////////// /// \brief Combine a new model-view matrix with the current one /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param matrix Model-view matrix to combine /// /// \see SetModelView @@ -146,9 +140,6 @@ public : //////////////////////////////////////////////////////////// /// \brief Set a new projection matrix /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param matrix New projection matrix /// /// \see ApplyProjection @@ -160,8 +151,6 @@ public : /// \brief Set the current global color /// /// This color will be modulated with each vertex's color. - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. /// /// \param color New global color /// @@ -174,8 +163,6 @@ public : /// \brief Modulate the current global color with a new one /// /// This color will be modulated with each vertex's color. - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. /// /// \param color Color to modulate /// @@ -187,9 +174,6 @@ public : //////////////////////////////////////////////////////////// /// \brief Set the current viewport /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param viewport New viewport to apply /// //////////////////////////////////////////////////////////// @@ -198,9 +182,6 @@ public : //////////////////////////////////////////////////////////// /// \brief Set the current alpha-blending mode /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param mode New blending mode /// //////////////////////////////////////////////////////////// @@ -209,20 +190,14 @@ public : //////////////////////////////////////////////////////////// /// \brief Set the current texture /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param texture New texture /// //////////////////////////////////////////////////////////// - void SetTexture(const Image* texture); + void SetTexture(const Texture* texture); //////////////////////////////////////////////////////////// /// \brief Set the current shader /// - /// Note: any call to this function after a call to BeginBatch - /// will be ignored, and delayed until BeginBatch is called again. - /// /// \param shader New Shader /// //////////////////////////////////////////////////////////// @@ -346,18 +321,18 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - RenderTarget& myTarget; ///< Reference to the render target owning this renderer - States myStatesStack[64]; ///< Stack of render states - States* myStates; ///< Current set of render states - const Image* myTexture; ///< Current texture - unsigned int myTextureId; ///< Current texture identifier (the sf::Image instance may be the same, but not the internal OpenGL texture) - const Shader* myShader; ///< Current pixel shader - Blend::Mode myBlendMode; ///< Current blending mode - IntRect myViewport; ///< Current target viewport - bool myTextureIsValid; ///< Is the cached texture valid? (if not, the cached value is ignored) - bool myShaderIsValid; ///< Is the cached shader valid? (if not, the cached value is ignored) - bool myBlendModeIsValid; ///< Is the cached blend mode valid? (if not, the cached value is ignored) - bool myViewportIsValid; ///< Is the cached viewport valid? (if not, the cached value is ignored) + RenderTarget& myTarget; ///< Reference to the render target owning this renderer + States myStatesStack[64]; ///< Stack of render states + States* myStates; ///< Current set of render states + const Texture* myTexture; ///< Current texture + unsigned int myTextureId; ///< Current texture identifier (the sf::Texture instance may be the same, but not the internal OpenGL texture) + const Shader* myShader; ///< Current pixel shader + Blend::Mode myBlendMode; ///< Current blending mode + IntRect myViewport; ///< Current target viewport + bool myTextureIsValid; ///< Is the cached texture valid? (if not, the cached value is ignored) + bool myShaderIsValid; ///< Is the cached shader valid? (if not, the cached value is ignored) + bool myBlendModeIsValid; ///< Is the cached blend mode valid? (if not, the cached value is ignored) + bool myViewportIsValid; ///< Is the cached viewport valid? (if not, the cached value is ignored) }; } // namespace sf diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index ce294b4b0..5f389ff8b 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -29,7 +29,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include #include #include @@ -253,35 +253,35 @@ public : /// \brief Change a texture parameter of the shader /// /// \a name is the name of the texture to change in the shader. - /// This function maps an external image to the texture variable; - /// to use the current texture of the object being drawn, use - /// SetCurrentTexture instead. + /// This function maps an external texture to the given shader + /// variable; to use the current texture of the object being drawn, + /// use SetCurrentTexture instead. /// Example: /// \code /// // These are the variables in the pixel shader - /// uniform sampler2D texture; + /// uniform sampler2D the_texture; /// \endcode /// \code - /// sf::Image image; + /// sf::Texture texture; /// ... - /// shader.SetTexture("texture", image); + /// shader.SetTexture("the_texture", texture); /// \endcode /// It is important to note that \a texture must remain alive as long /// as the shader uses it, no copy is made internally. /// /// \param name Name of the texture in the shader - /// \param texture Image to assign + /// \param texture Texture to assign /// /// \see SetParameter, SetCurrentTexture /// //////////////////////////////////////////////////////////// - void SetTexture(const std::string& name, const Image& texture); + void SetTexture(const std::string& name, const Texture& texture); //////////////////////////////////////////////////////////// /// \brief Set the current object texture in the shader /// /// This function maps a shader texture variable to the - /// image of the object being drawn. + /// texture of the object being drawn. /// Example: /// \code /// // This is the variable in the pixel shader @@ -384,7 +384,7 @@ private : //////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////// - typedef std::map TextureTable; + typedef std::map TextureTable; //////////////////////////////////////////////////////////// // Member data @@ -427,7 +427,7 @@ private : /// \code /// shader.SetParameter("offset", 2.f); /// shader.SetParameter("color", 0.5f, 0.8f, 0.3f); -/// shader.SetTexture("overlay", image); // image is a sf::Image +/// shader.SetTexture("overlay", texture); // texture is a sf::Texture /// shader.SetCurrentTexture("texture"); /// \endcode /// @@ -442,8 +442,8 @@ private : /// /// Shaders can be used on any drawable, but they are mainly /// made for sf::Sprite. Using a shader on a sf::String is more -/// limited, because the texture of the string is not the -/// actual text that you see on screen, it is a big image +/// limited, because the texture of the text is not the +/// actual text that you see on screen, it is a big texture /// containing all the characters of the font in an arbitrary /// order. Thus, texture lookups on pixels other than the current /// one may not give you the expected result. Using a shader @@ -453,18 +453,18 @@ private : /// Shaders can also be used to apply global post-effects to the /// current contents of the target (like the old sf::PostFx class /// in SFML 1). This can be done in two different ways: -/// \li draw everything to a sf::RenderImage, then draw it to +/// \li draw everything to a sf::RenderTexture, then draw it to /// the main target using the shader /// \li draw everything directly to the main target, then use -/// sf::Image::CopyScreen to copy its contents to an image and -/// draw it to the main target using the shader +/// sf::Texture::Update(Window&) to copy its contents to a texture +/// and draw it to the main target using the shader /// /// The first technique is more optimized because it doesn't involve /// retrieving the target's pixels to system memory, but the /// second one doesn't impact the rendering process and can be /// easily inserted anywhere. /// -/// Like sf::Image that can be used as a raw OpenGL texture, +/// Like sf::Texture that can be used as a raw OpenGL texture, /// sf::Shader can also be used directly as a raw fragment /// shader for custom OpenGL geometry. /// \code diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp index e6c38eb59..a183539a4 100644 --- a/include/SFML/Graphics/Shape.hpp +++ b/include/SFML/Graphics/Shape.hpp @@ -534,6 +534,6 @@ private : /// window.Draw(sf::Shape::Circle(500, 500, 20, sf::Color::Blue, 5, sf::Color::Black)); /// \endcode /// -/// \see sf::Image +/// \see sf::Sprite /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp index 2f75ecf73..cb754797d 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -35,10 +35,10 @@ namespace sf { -class Image; +class Texture; //////////////////////////////////////////////////////////// -/// \brief Drawable representation of an image, with its +/// \brief Drawable representation of a texture, with its /// own transformations, color, blend mode, etc. /// //////////////////////////////////////////////////////////// @@ -49,56 +49,50 @@ public : //////////////////////////////////////////////////////////// /// \brief Default constructor /// - /// Creates an empty sprite with no source image. + /// Creates an empty sprite with no source texture. /// //////////////////////////////////////////////////////////// Sprite(); //////////////////////////////////////////////////////////// - /// \brief Construct the sprite from a source image + /// \brief Construct the sprite from a source texture /// - /// \param image Source image, that the sprite will display - /// \param position Position of the sprite in the scene - /// \param scale Scale factor of the sprite - /// \param rotation Rotation angle, in degrees - /// \param color Global color of the sprite - /// - /// \see SetImage + /// \see SetTexture /// //////////////////////////////////////////////////////////// - explicit Sprite(const Image& image, const Vector2f& position = Vector2f(0, 0), const Vector2f& scale = Vector2f(1, 1), float rotation = 0.f, const Color& color = Color(255, 255, 255, 255)); + explicit Sprite(const Texture& texture); //////////////////////////////////////////////////////////// - /// \brief Change the source image of the sprite + /// \brief Change the source texture of the sprite /// - /// The \a image argument refers to an image that must + /// The \a texture argument refers to a texture that must /// exist as long as the sprite uses it. Indeed, the sprite - /// doesn't store its own copy of the image, but rather keeps + /// doesn't store its own copy of the texture, but rather keeps /// a pointer to the one that you passed to this function. - /// If the source image is destroyed and the sprite tries to + /// If the source texture is destroyed and the sprite tries to /// use it, it may appear as a white rectangle. /// If \a adjustToNewSize is true, the SubRect property of - /// the sprite is adjusted to the size of the new image. If + /// the sprite is adjusted to the size of the new texture. If /// it is false, the SubRect is unchanged. /// - /// \param image New image - /// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new image? + /// \param texture New texture + /// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new texture? /// - /// \see GetImage, SetSubRect + /// \see GetTexture, SetSubRect /// //////////////////////////////////////////////////////////// - void SetImage(const Image& image, bool adjustToNewSize = false); + void SetTexture(const Texture& texture, bool adjustToNewSize = false); //////////////////////////////////////////////////////////// - /// \brief Set the part of the image that the sprite will display + /// \brief Set the part of the texture that the sprite will display /// /// The sub-rectangle is useful when you don't want to display - /// the whole image, but rather a part of it. - /// By default, the sub-rectangle covers the entire image. + /// the whole texture, but rather a part of it. + /// By default, the sub-rectangle covers the entire texture. /// - /// \param rectangle Rectangle defining the region of the image to display + /// \param rectangle Rectangle defining the region of the texture to display /// - /// \see GetSubRect, SetImage + /// \see GetSubRect, SetTexture /// //////////////////////////////////////////////////////////// void SetSubRect(const IntRect& rectangle); @@ -157,24 +151,24 @@ public : void FlipY(bool flipped); //////////////////////////////////////////////////////////// - /// \brief Get the source image of the sprite + /// \brief Get the source texture of the sprite /// - /// If the sprite has no source image, or if the image + /// If the sprite has no source texture, or if the texture /// doesn't exist anymore, a NULL pointer is returned. /// The returned pointer is const, which means that you can't - /// modify the image when you retrieve it with this function. + /// modify the texture when you retrieve it with this function. /// - /// \return Pointer to the sprite's image + /// \return Pointer to the sprite's texture /// - /// \see SetImage + /// \see SetTexture /// //////////////////////////////////////////////////////////// - const Image* GetImage() const; + const Texture* GetTexture() const; //////////////////////////////////////////////////////////// - /// \brief Get the region of the image displayed by the sprite + /// \brief Get the region of the texture displayed by the sprite /// - /// \return Rectangle defining the region of the image + /// \return Rectangle defining the region of the texture /// /// \see SetSubRect /// @@ -194,25 +188,6 @@ public : //////////////////////////////////////////////////////////// Vector2f GetSize() const; - //////////////////////////////////////////////////////////// - /// \brief Get the color of a given pixel in the sprite - /// - /// This function returns the source image pixel, multiplied - /// by the global color of the sprite. - /// The input point must be in local coordinates. If you have - /// a global point, you can use the TransformToLocal function - /// to make it local. - /// This function doesn't perform any check, you must ensure that - /// the \a x and \a y coordinates are not out of bounds. - /// - /// \param x X coordinate of the pixel to get - /// \param y Y coordinate of the pixel to get - /// - /// \return Color of the pixel - /// - //////////////////////////////////////////////////////////// - Color GetPixel(unsigned int x, unsigned int y) const; - protected : //////////////////////////////////////////////////////////// @@ -229,10 +204,10 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - ResourcePtr myImage; ///< Image used to draw the sprite - IntRect mySubRect; ///< Sub-rectangle of source image to assign to the sprite - bool myIsFlippedX; ///< Is the sprite flipped on the X axis ? - bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ? + ResourcePtr myTexture; ///< Texture used to draw the sprite + IntRect mySubRect; ///< Sub-rectangle of source texture to assign to the sprite + bool myIsFlippedX; ///< Is the sprite flipped on the X axis ? + bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ? }; } // namespace sf @@ -246,39 +221,39 @@ private : /// \ingroup graphics /// /// sf::Sprite is a drawable class that allows to easily display -/// an image (or a part of it) on a render target. +/// a texture (or a part of it) on a render target. /// /// It inherits all the functions from sf::Drawable: /// position, rotation, scale, origin, global color and blend /// mode. It also adds sprite-specific properties such as the -/// image to use, the part of it to display, and some convenience +/// texture to use, the part of it to display, and some convenience /// functions to flip or resize the sprite. /// -/// sf::Sprite works in combination with the sf::Image class, which -/// loads and provides the pixel data of a given image. +/// sf::Sprite works in combination with the sf::Texture class, which +/// loads and provides the pixel data of a given texture. /// -/// The separation of sf::Sprite and sf::Image allows more flexibility -/// and better performances: indeed a sf::Image is a heavy resource, +/// The separation of sf::Sprite and sf::Texture allows more flexibility +/// and better performances: indeed a sf::Texture is a heavy resource, /// and any operation on it is slow (often too slow for real-time /// applications). On the other side, a sf::Sprite is a lightweight -/// object which can use the pixel data of a sf::Image and draw +/// object which can use the pixel data of a sf::Texture and draw /// it with its own transformation / color / blending attributes. /// /// It is important to note that the sf::Sprite instance doesn't -/// copy the image that it uses, it only keeps a reference to it. -/// Thus, a sf::Image must not be destructed while it is +/// copy the texture that it uses, it only keeps a reference to it. +/// Thus, a sf::Texture must not be destructed while it is /// used by a sf::Sprite (i.e. never write a function that -/// uses a local sf::Image instance for creating a sprite). +/// uses a local sf::Texture instance for creating a sprite). /// /// Usage example: /// \code -/// // Declare and load an image -/// sf::Image image; -/// image.LoadFromFile("image.png"); +/// // Declare and load a texture +/// sf::Texture texture; +/// texture.LoadFromFile("texture.png"); /// /// // Create a sprite /// sf::Sprite sprite; -/// sprite.SetImage(image); +/// sprite.SetTexture(texture); /// sprite.SetSubRect(sf::IntRect(10, 10, 50, 30)); /// sprite.Resize(100, 60); /// @@ -286,6 +261,6 @@ private : /// window.Draw(sprite); // window is a sf::RenderWindow /// \endcode /// -/// \see sf::Image +/// \see sf::Texture /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp new file mode 100644 index 000000000..f4a2a276d --- /dev/null +++ b/include/SFML/Graphics/Texture.hpp @@ -0,0 +1,551 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TEXTURE_HPP +#define SFML_TEXTURE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class Window; +class Renderer; +class RenderTexture; +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Image living on the graphics card that can be used for drawing +/// +//////////////////////////////////////////////////////////// +class SFML_API Texture : public Resource, GlResource +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty texture. + /// + //////////////////////////////////////////////////////////// + Texture(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy instance to copy + /// + //////////////////////////////////////////////////////////// + Texture(const Texture& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Texture(); + + //////////////////////////////////////////////////////////// + /// \brief Create the texture + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param width Width of the texture + /// \param height Height of the texture + /// + /// \return True if creation was successful + /// + //////////////////////////////////////////////////////////// + bool Create(unsigned int width, unsigned int height); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a file on disk + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.LoadFromFile(filename); + /// texture.LoadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the GetMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param filename Path of the image file to load + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see LoadFromMemory, LoadFromStream, LoadFromImage + /// + //////////////////////////////////////////////////////////// + bool LoadFromFile(const std::string& filename, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a file in memory + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.LoadFromMemory(data, size); + /// texture.LoadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the GetMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see LoadFromFile, LoadFromStream, LoadFromImage + /// + //////////////////////////////////////////////////////////// + bool LoadFromMemory(const void* data, std::size_t size, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a file in memory + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.LoadFromStream(stream); + /// texture.LoadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the GetMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param stream Source stream to read from + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see LoadFromFile, LoadFromMemory, LoadFromImage + /// + //////////////////////////////////////////////////////////// + bool LoadFromStream(sf::InputStream& stream, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from an image + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the GetMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param image Image to load into the texture + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see LoadFromFile, LoadFromMemory + /// + //////////////////////////////////////////////////////////// + bool LoadFromImage(const Image& image, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Return the width of the texture + /// + /// \return Width in pixels + /// + /// \see GetHeight + /// + //////////////////////////////////////////////////////////// + unsigned int GetWidth() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the height of the texture + /// + /// \return Height in pixels + /// + /// \see GetWidth + /// + //////////////////////////////////////////////////////////// + unsigned int GetHeight() const; + + //////////////////////////////////////////////////////////// + /// \brief Copy the texture pixels to an image + /// + /// This function performs a slow operation that downloads + /// the texture's pixels from the graphics card and copies + /// them to a new image, potentially applying transformations + /// to pixels if necessary (texture may be padded or flipped). + /// + /// \return Image containing the texture's pixels + /// + /// \see LoadFromImage + /// + //////////////////////////////////////////////////////////// + Image CopyToImage() const; + + //////////////////////////////////////////////////////////// + /// \brief Update the whole texture from an array of pixels + /// + /// The \a pixels array is assumed to have the same size as + /// the \a area rectangle, and to contain 32-bits RGBA pixels. + /// + /// No additional check is performed on the size of the pixel + /// array, passing invalid arguments will lead to an undefined + /// behaviour. + /// + /// This function does nothing if \a pixels is null or if the + /// texture was not previously created. + /// + /// \param pixels Array of pixels to copy to the texture + /// + //////////////////////////////////////////////////////////// + void Update(const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from an array of pixels + /// + /// The size of the \a pixels array must match the \a width and + /// \a height arguments, and it must contain 32-bits RGBA pixels. + /// + /// No additional check is performed on the size of the pixel + /// array or the bounds of the area to update, passing invalid + /// arguments will lead to an undefined behaviour. + /// + /// This function does nothing if \a pixels is null or if the + /// texture was not previously created. + /// + /// \param pixels Array of pixels to copy to the texture + /// \param width Width of the pixel region contained in \a pixels + /// \param height Height of the pixel region contained in \a pixels + /// \param x X offset in the texture where to copy the source pixels + /// \param y Y offset in the texture where to copy the source pixels + /// + //////////////////////////////////////////////////////////// + void Update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Update the texture from an image + /// + /// Although the source image can be smaller than the texture, + /// this function is usually used for updating the whole texture. + /// The other overload, which has (x, y) additional arguments, + /// is more convenient for updating a sub-area of the texture. + /// + /// No additional check is performed on the size of the image, + /// passing an image bigger than the texture will lead to an + /// undefined behaviour. + /// + /// This function does nothing if the texture was not + /// previously created. + /// + /// \param image Image to copy to the texture + /// + //////////////////////////////////////////////////////////// + void Update(const Image& image); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from an image + /// + /// No additional check is performed on the size of the image, + /// passing an invalid combination of image size and offset + /// will lead to an undefined behaviour. + /// + /// This function does nothing if the texture was not + /// previously created. + /// + /// \param image Image to copy to the texture + /// \param x X offset in the texture where to copy the source image + /// \param y Y offset in the texture where to copy the source image + /// + //////////////////////////////////////////////////////////// + void Update(const Image& image, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Update the texture from the contents of a window + /// + /// Although the source window can be smaller than the texture, + /// this function is usually used for updating the whole texture. + /// The other overload, which has (x, y) additional arguments, + /// is more convenient for updating a sub-area of the texture. + /// + /// No additional check is performed on the size of the window, + /// passing a window bigger than the texture will lead to an + /// undefined behaviour. + /// + /// This function does nothing if either the texture or the window + /// was not previously created. + /// + /// \param window Window to copy to the texture + /// + //////////////////////////////////////////////////////////// + void Update(const Window& window); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from the contents of a window + /// + /// No additional check is performed on the size of the window, + /// passing an invalid combination of window size and offset + /// will lead to an undefined behaviour. + /// + /// This function does nothing if either the texture or the window + /// was not previously created. + /// + /// \param window Window to copy to the texture + /// \param x X offset in the texture where to copy the source window + /// \param y Y offset in the texture where to copy the source window + /// + //////////////////////////////////////////////////////////// + void Update(const Window& window, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Activate the texture for rendering + /// + /// This function is mainly used internally by the SFML + /// render system. However it can be useful when + /// using sf::Texture together with OpenGL code (this function + /// is equivalent to glBindTexture). + /// + //////////////////////////////////////////////////////////// + void Bind() const; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable the smooth filter + /// + /// When the filter is activated, the texture appears smoother + /// so that pixels are less noticeable. However if you want + /// the texture to look exactly the same as its source file, + /// you should leave it disabled. + /// The smooth filter is disabled by default. + /// + /// \param smooth True to enable smoothing, false to disable it + /// + /// \see IsSmooth + /// + //////////////////////////////////////////////////////////// + void SetSmooth(bool smooth); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the smooth filter is enabled or not + /// + /// \return True if smoothing is enabled, false if it is disabled + /// + /// \see SetSmooth + /// + //////////////////////////////////////////////////////////// + bool IsSmooth() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a rectangle of pixels into texture coordinates + /// + /// This function is used by code that needs to map the texture + /// to some OpenGL geometry. It converts the source rectangle, + /// expressed in pixels, to float coordinates in the range [0, 1]. + /// + /// \param rectangle Rectangle to convert + /// + /// \return Texture coordinates corresponding to \a rectangle + /// + //////////////////////////////////////////////////////////// + FloatRect GetTexCoords(const IntRect& rectangle) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Texture& operator =(const Texture& right); + + //////////////////////////////////////////////////////////// + /// \brief Get the maximum texture size allowed + /// + /// This maximum size is defined by the graphics driver. + /// You can expect a value of 512 pixels for low-end graphics + /// card, and up to 8192 pixels or more for newer hardware. + /// + /// \return Maximum size allowed for textures, in pixels + /// + //////////////////////////////////////////////////////////// + static unsigned int GetMaximumSize(); + +private : + + friend class Renderer; + friend class RenderTexture; + + //////////////////////////////////////////////////////////// + /// \brief Get a valid image size according to hardware support + /// + /// This function checks whether the graphics driver supports + /// non power of two sizes or not, and adjusts the size + /// accordingly. + /// The returned size is greater than or equal to the original size. + /// + /// \param Size size to convert + /// + /// \return Valid nearest size (greater than or equal to specified size) + /// + //////////////////////////////////////////////////////////// + static unsigned int GetValidSize(unsigned int size); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int myWidth; ///< Image width + unsigned int myHeight; ///< Image Height + unsigned int myTextureWidth; ///< Actual texture width (can be greater than image width because of padding) + unsigned int myTextureHeight; ///< Actual texture height (can be greater than image height because of padding) + unsigned int myTexture; ///< Internal texture identifier + bool myIsSmooth; ///< Status of the smooth filter + mutable bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation +}; + +} // namespace sf + + +#endif // SFML_TEXTURE_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::Texture +/// \ingroup graphics +/// +/// sf::Texture stores pixels that can be drawn, with a sprite +/// for example. A texture lives in the graphics card memory, +/// therefore it is very fast to draw a texture to a render target, +/// or copy a render target to a texture (the graphics card can +/// access both directly). +/// +/// Being stored in the graphics card memory has some drawbacks. +/// A texture cannot be manipulated as freely as a sf::Image, +/// you need to prepare the pixels first and then upload them +/// to the texture in a single operation (see Texture::Update). +/// +/// sf::Texture makes it easy to convert from/to sf::Image, but +/// keep in mind that these calls require transfers between +/// the graphics card and the central memory, therefore they are +/// slow operations. +/// +/// A texture can be loaded from an image, but also directly +/// from a file/memory/stream. The necessary shortcuts are defined +/// so that you don't need an image first for the most common cases. +/// However, if you want to perform some modifications on the pixels +/// before creating the final texture, you can load your file to a +/// sf::Image, do whatever you need with the pixels, and then call +/// Texture::LoadFromImage. +/// +/// Since they live in the graphics card memory, the pixels of a texture +/// cannot be accessed without a slow copy first. And they cannot be +/// accessed individually. Therefore, if you need to read the texture's +/// pixels (like for pixel-perfect collisions), it is recommended to +/// store the collision information separately, for example in an array +/// of booleans. +/// +/// Like sf::Image, sf::Texture can handle a unique internal +/// representation of pixels, which is RGBA 32 bits. This means +/// that a pixel must be composed of 8 bits red, green, blue and +/// alpha channels -- just like a sf::Color. +/// +/// Usage example: +/// \code +/// // This example shows the most common use of sf::Texture: +/// // drawing a sprite +/// +/// // Load a texture from a file +/// sf::Texture texture; +/// if (!texture.LoadFromFile("texture.png")) +/// return -1; +/// +/// // Assign it to a sprite +/// sf::Sprite sprite; +/// sprite.SetTexture(texture); +/// +/// // Draw the textured sprite +/// window.Draw(sprite); // window is a sf::RenderWindow +/// \endcode +/// +/// \code +/// // This example shows another common use of sf::Texture: +/// // streaming real-time data, like video frames +/// +/// // Create an empty texture +/// sf::Texture texture; +/// if (!texture.Create(640, 480)) +/// return -1; +/// +/// // Create a sprite that will display the texture +/// sf::Sprite sprite(texture); +/// +/// while (...) // the main loop +/// { +/// ... +/// +/// // update the texture +/// sf::Uint8* pixels = ...; // get a fresh chunk of pixels (the next frame of a movie, for example) +/// texture.Update(pixels); +/// +/// // draw it +/// window.Draw(sprite); +/// +/// ... +/// } +/// +/// \endcode +/// +/// \see sf::Sprite, sf::Image, sf::RenderTexture +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp index 15474cddb..14a0b9474 100644 --- a/include/SFML/Graphics/View.hpp +++ b/include/SFML/Graphics/View.hpp @@ -297,7 +297,7 @@ private : /// A view is composed of a source rectangle, which defines /// what part of the 2D scene is shown, and a target viewport, /// which defines where the contents of the source rectangle -/// will be displayed on the render target (window or render-image). +/// will be displayed on the render target (window or texture). /// /// The viewport allows to map the scene to a custom part /// of the render target, and can be used for split-screen @@ -336,6 +336,6 @@ private : /// window.Draw(someText); /// \endcode /// -/// \see RenderWindow, RenderImage +/// \see sf::RenderWindow, sf::RenderTexture /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/System/InputStream.hpp b/include/SFML/System/InputStream.hpp index facebc2e2..1d9765571 100644 --- a/include/SFML/System/InputStream.hpp +++ b/include/SFML/System/InputStream.hpp @@ -98,7 +98,7 @@ public : /// This class allows users to define their own file input sources /// from which SFML can load resources. /// -/// SFML resource classes like sf::Image and +/// SFML resource classes like sf::Texture and /// sf::SoundBuffer provide LoadFromFile and LoadFromMemory functions, /// which read data from conventional sources. However, if you /// have data coming from a different source (over a network, @@ -130,11 +130,11 @@ public : /// ... /// }; /// -/// // now you can load images... -/// sf::Image image; +/// // now you can load textures... +/// sf::Texture texture; /// ZipStream stream("resources.zip"); /// stream.Open("images/img.png"); -/// image.LoadFromStream(stream); +/// texture.LoadFromStream(stream); /// /// // musics... /// sf::Music music; diff --git a/include/SFML/System/Resource.hpp b/include/SFML/System/Resource.hpp index ac9a170ca..b31597948 100644 --- a/include/SFML/System/Resource.hpp +++ b/include/SFML/System/Resource.hpp @@ -275,8 +275,8 @@ private : /// /// These two classes are heavily used internally in SFML /// to safely handle resources and the classes that use them: -/// \li sf::Image / sf::Sprite -/// \li sf::Font / sf::String +/// \li sf::Texture / sf::Sprite +/// \li sf::Font / sf::Text /// \li sf::SoundBuffer / sf::Sound /// /// sf::Resource and sf::ResourcePtr are designed for internal use, diff --git a/src/SFML/Audio/Sound.cpp b/src/SFML/Audio/Sound.cpp index 2fc609a45..dc1978a9b 100644 --- a/src/SFML/Audio/Sound.cpp +++ b/src/SFML/Audio/Sound.cpp @@ -39,14 +39,10 @@ Sound::Sound() //////////////////////////////////////////////////////////// -Sound::Sound(const SoundBuffer& buffer, bool loop, float pitch, float volume, const Vector3f& position) : +Sound::Sound(const SoundBuffer& buffer) : myBuffer(NULL) { SetBuffer(buffer); - SetLoop(loop); - SetPitch(pitch); - SetVolume(volume); - SetPosition(position); } diff --git a/src/SFML/Graphics/CMakeLists.txt b/src/SFML/Graphics/CMakeLists.txt index e2855ac3b..a30b89277 100644 --- a/src/SFML/Graphics/CMakeLists.txt +++ b/src/SFML/Graphics/CMakeLists.txt @@ -25,14 +25,14 @@ set(SRC ${INCROOT}/Rect.inl ${SRCROOT}/Renderer.cpp ${INCROOT}/Renderer.hpp - ${SRCROOT}/RenderImage.cpp - ${INCROOT}/RenderImage.hpp - ${SRCROOT}/RenderImageImpl.cpp - ${SRCROOT}/RenderImageImpl.hpp - ${SRCROOT}/RenderImageImplFBO.cpp - ${SRCROOT}/RenderImageImplFBO.hpp - ${SRCROOT}/RenderImageImplDefault.cpp - ${SRCROOT}/RenderImageImplDefault.hpp + ${SRCROOT}/RenderTexture.cpp + ${INCROOT}/RenderTexture.hpp + ${SRCROOT}/RenderTextureImpl.cpp + ${SRCROOT}/RenderTextureImpl.hpp + ${SRCROOT}/RenderTextureImplFBO.cpp + ${SRCROOT}/RenderTextureImplFBO.hpp + ${SRCROOT}/RenderTextureImplDefault.cpp + ${SRCROOT}/RenderTextureImplDefault.hpp ${SRCROOT}/RenderTarget.cpp ${INCROOT}/RenderTarget.hpp ${SRCROOT}/RenderWindow.cpp @@ -45,6 +45,8 @@ set(SRC ${INCROOT}/Sprite.hpp ${SRCROOT}/Text.cpp ${INCROOT}/Text.hpp + ${SRCROOT}/Texture.cpp + ${INCROOT}/Texture.hpp ${SRCROOT}/View.cpp ${INCROOT}/View.hpp ${SRCROOT}/stb_image/stb_image.h diff --git a/src/SFML/Graphics/Drawable.cpp b/src/SFML/Graphics/Drawable.cpp index 6bb7f53f5..5dd4336f6 100644 --- a/src/SFML/Graphics/Drawable.cpp +++ b/src/SFML/Graphics/Drawable.cpp @@ -33,20 +33,6 @@ namespace sf { -//////////////////////////////////////////////////////////// -Drawable::Drawable(const Vector2f& position, const Vector2f& scale, float rotation, const Color& color) : -myPosition (position), -myScale (scale), -myOrigin (0, 0), -myRotation (rotation), -myColor (color), -myBlendMode (Blend::Alpha), -myMatrixUpdated (false), -myInvMatrixUpdated(false) -{ -} - - //////////////////////////////////////////////////////////// Drawable::~Drawable() { @@ -267,6 +253,20 @@ Vector2f Drawable::TransformToGlobal(const Vector2f& point) const } +//////////////////////////////////////////////////////////// +Drawable::Drawable() : +myPosition (0, 0), +myScale (1, 1), +myOrigin (0, 0), +myRotation (0), +myColor (255, 255, 255, 255), +myBlendMode (Blend::Alpha), +myMatrixUpdated (false), +myInvMatrixUpdated(false) +{ +} + + //////////////////////////////////////////////////////////// const Matrix3& Drawable::GetMatrix() const { diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index 3563091b7..5bc51c83a 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -309,7 +309,7 @@ int Font::GetLineSpacing(unsigned int characterSize) const //////////////////////////////////////////////////////////// -const Image& Font::GetImage(unsigned int characterSize) const +const Texture& Font::GetTexture(unsigned int characterSize) const { return myPages[characterSize].Texture; } @@ -493,12 +493,11 @@ Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c } // Write the pixels to the texture - IntRect subrect = glyph.SubRect; - subrect.Left += padding; - subrect.Top += padding; - subrect.Width -= 2 * padding; - subrect.Height -= 2 * padding; - page.Texture.UpdatePixels(&myPixelBuffer[0], subrect); + unsigned int x = glyph.SubRect.Left + padding; + unsigned int y = glyph.SubRect.Top + padding; + unsigned int width = glyph.SubRect.Width - 2 * padding; + unsigned int height = glyph.SubRect.Height - 2 * padding; + page.Texture.Update(&myPixelBuffer[0], width, height, x, y); } // Delete the FT glyph @@ -545,19 +544,17 @@ IntRect Font::FindGlyphRect(Page& page, unsigned int width, unsigned int height) // Not enough space: resize the texture if possible unsigned int textureWidth = page.Texture.GetWidth(); unsigned int textureHeight = page.Texture.GetHeight(); - if ((textureWidth * 2 <= Image::GetMaximumSize()) && (textureHeight * 2 <= Image::GetMaximumSize())) + if ((textureWidth * 2 <= Texture::GetMaximumSize()) && (textureHeight * 2 <= Texture::GetMaximumSize())) { // Make the texture 2 times bigger - std::size_t size = textureWidth * textureHeight * 4; - std::vector pixels(size); - memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size); - page.Texture.Create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0)); - page.Texture.UpdatePixels(&pixels[0], IntRect(0, 0, textureWidth, textureHeight)); + sf::Image pixels = page.Texture.CopyToImage(); + page.Texture.Create(textureWidth * 2, textureHeight * 2); + page.Texture.Update(pixels); } else { // Oops, we've reached the maximum texture size... - Err() << "Failed to add a new character to the font: the maximum image size has been reached" << std::endl; + Err() << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl; return IntRect(0, 0, 2, 2); } } @@ -603,13 +600,17 @@ Font::Page::Page() : NextRow(2) { // Make sure that the texture is initialized by default - Texture.Create(128, 128, Color(255, 255, 255, 0)); - Texture.SetSmooth(true); + sf::Image image; + image.Create(128, 128, Color(255, 255, 255, 0)); // Reserve a 2x2 white square for texturing underlines for (int x = 0; x < 2; ++x) for (int y = 0; y < 2; ++y) - Texture.SetPixel(x, y, Color(255, 255, 255, 255)); + image.SetPixel(x, y, Color(255, 255, 255, 255)); + + // Create the texture + Texture.LoadFromImage(image); + Texture.SetSmooth(true); } } // namespace sf diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index af7b8a24f..851a38dc8 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -27,12 +27,8 @@ //////////////////////////////////////////////////////////// #include #include -#include -#include -#include #include #include -#include #include @@ -40,54 +36,56 @@ namespace sf { //////////////////////////////////////////////////////////// Image::Image() : -myWidth (0), -myHeight (0), -myTextureWidth (0), -myTextureHeight (0), -myTexture (0), -myIsSmooth (false), -myTextureUpdated(true), -myArrayUpdated (true), -myPixelsFlipped (false) +myWidth (0), +myHeight(0) { } //////////////////////////////////////////////////////////// -Image::Image(const Image& copy) : -Resource() +void Image::Create(unsigned int width, unsigned int height, const Color& color) { - // First make sure that the source image is up-to-date - copy.EnsureArrayUpdate(); + // Assign the new size + myWidth = width; + myHeight = height; - // Copy all its members - myWidth = copy.myWidth; - myHeight = copy.myHeight; - myTextureWidth = copy.myTextureWidth; - myTextureHeight = copy.myTextureHeight; - myTexture = 0; - myIsSmooth = copy.myIsSmooth; - myPixels = copy.myPixels; - myTextureUpdated = true; - myArrayUpdated = true; - myPixelsFlipped = false; // pixels can't be flipped, this is handled in copy.EnsureArrayUpdate() + // Resize the pixel buffer + myPixels.resize(width * height * 4); - // Create the texture - CreateTexture(myWidth, myHeight); -} - - -//////////////////////////////////////////////////////////// -Image::~Image() -{ - // Destroy the OpenGL texture - if (myTexture) + // Fill it with the specified color + Uint8* ptr = &myPixels[0]; + Uint8* end = ptr + myPixels.size(); + while (ptr < end) { - EnsureGlContext(); + *ptr++ = color.r; + *ptr++ = color.g; + *ptr++ = color.b; + *ptr++ = color.a; + } +} - GLuint Texture = static_cast(myTexture); - GLCheck(glDeleteTextures(1, &Texture)); + +//////////////////////////////////////////////////////////// +void Image::Create(unsigned int width, unsigned int height, const Uint8* pixels) +{ + if (pixels) + { + // Assign the new size + myWidth = width; + myHeight = height; + + // Copy the pixels + std::size_t size = width * height * 4; + myPixels.resize(size); + std::memcpy(&myPixels[0], pixels, size); // faster than vector::assign + } + else + { + // Create an empty image + myWidth = 0; + myHeight = 0; + myPixels.clear(); } } @@ -95,142 +93,48 @@ Image::~Image() //////////////////////////////////////////////////////////// bool Image::LoadFromFile(const std::string& filename) { - // Forward the job to the image loader - std::vector pixels; - unsigned int width; - unsigned int height; - if (priv::ImageLoader::GetInstance().LoadImageFromFile(filename, pixels, width, height)) - { - // Loading succeeded : we can create the texture - if (CreateTexture(width, height)) - { - // Copy the pixels - myPixels.swap(pixels); - return true; - } - } - - return false; + return priv::ImageLoader::GetInstance().LoadImageFromFile(filename, myPixels, myWidth, myHeight); } //////////////////////////////////////////////////////////// bool Image::LoadFromMemory(const void* data, std::size_t size) { - // Forward the job to the image loader - std::vector pixels; - unsigned int width; - unsigned int height; - if (priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, pixels, width, height)) - { - // Loading succeeded : we can create the texture - if (CreateTexture(width, height)) - { - // Copy the pixels - myPixels.swap(pixels); - return true; - } - } - - return false; + return priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, myPixels, myWidth, myHeight); } //////////////////////////////////////////////////////////// bool Image::LoadFromStream(InputStream& stream) { - // Forward the job to the image loader - std::vector pixels; - unsigned int width; - unsigned int height; - if (priv::ImageLoader::GetInstance().LoadImageFromStream(stream, pixels, width, height)) - { - // Loading succeeded : we can create the texture - if (CreateTexture(width, height)) - { - // Copy the pixels - myPixels.swap(pixels); - return true; - } - } - - return false; -} - - -//////////////////////////////////////////////////////////// -bool Image::LoadFromPixels(unsigned int width, unsigned int height, const Uint8* data) -{ - if (data) - { - // Create the internal texture - if (CreateTexture(width, height)) - { - // Copy the pixels - std::size_t size = width * height * 4; - myPixels.resize(size); - std::memcpy(&myPixels[0], data, size); // faster than vector::assign - return true; - } - else - { - return false; - } - } - else - { - // No data provided : create a white image - return Create(width, height, Color(255, 255, 255)); - } + return priv::ImageLoader::GetInstance().LoadImageFromStream(stream, myPixels, myWidth, myHeight); } //////////////////////////////////////////////////////////// bool Image::SaveToFile(const std::string& filename) const { - // Check if the array of pixels needs to be updated - EnsureArrayUpdate(); - - // Let the image loader save our pixel array into the image return priv::ImageLoader::GetInstance().SaveImageToFile(filename, myPixels, myWidth, myHeight); } //////////////////////////////////////////////////////////// -bool Image::Create(unsigned int width, unsigned int height, const Color& color) +unsigned int Image::GetWidth() const { - // First create the texture - if (CreateTexture(width, height)) - { - // Resize the pixel buffer - myPixels.resize(width * height * 4); + return myWidth; +} - // Fill it with the specified color - Uint8* ptr = &myPixels[0]; - Uint8* end = ptr + myPixels.size(); - while (ptr < end) - { - *ptr++ = color.r; - *ptr++ = color.g; - *ptr++ = color.b; - *ptr++ = color.a; - } - return true; - } - else - { - return false; - } +//////////////////////////////////////////////////////////// +unsigned int Image::GetHeight() const +{ + return myHeight; } //////////////////////////////////////////////////////////// void Image::CreateMaskFromColor(const Color& color, Uint8 alpha) { - // Check if the array of pixels needs to be updated - EnsureArrayUpdate(); - // Make sure that the image is not empty if (!myPixels.empty()) { @@ -243,9 +147,6 @@ void Image::CreateMaskFromColor(const Color& color, Uint8 alpha) ptr[3] = alpha; ptr += 4; } - - // The texture will need to be updated - myTextureUpdated = false; } } @@ -257,10 +158,6 @@ void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, co if ((source.myWidth == 0) || (source.myHeight == 0) || (myWidth == 0) || (myHeight == 0)) return; - // Make sure both images have up-to-date arrays - EnsureArrayUpdate(); - source.EnsureArrayUpdate(); - // Adjust the source rectangle IntRect srcRect = sourceRect; if (srcRect.Width == 0 || (srcRect.Height == 0)) @@ -330,84 +227,24 @@ void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, co dstPixels += dstStride; } } - - // The texture will need an update - myTextureUpdated = false; -} - - -//////////////////////////////////////////////////////////// -bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect) -{ - // Adjust the source rectangle - IntRect rect = sourceRect; - if (rect.Width == 0 || (rect.Height == 0)) - { - rect.Left = 0; - rect.Top = 0; - rect.Width = window.GetWidth(); - rect.Height = window.GetHeight(); - } - else - { - if (rect.Left < 0) rect.Left = 0; - if (rect.Top < 0) rect.Top = 0; - if (rect.Width > static_cast(window.GetWidth())) rect.Width = window.GetWidth(); - if (rect.Height > static_cast(window.GetHeight())) rect.Height = window.GetHeight(); - } - - // We can then create the texture - if (window.SetActive() && CreateTexture(rect.Width, rect.Height)) - { - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - int y = window.GetHeight() - (rect.Top + rect.Height); // Y axis is inverted - GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.Left, y, myWidth, myHeight)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - - myTextureUpdated = true; - myArrayUpdated = false; - myPixelsFlipped = true; - - return true; - } - else - { - return false; - } } //////////////////////////////////////////////////////////// void Image::SetPixel(unsigned int x, unsigned int y, const Color& color) { - // First check if the array of pixels needs to be updated - EnsureArrayUpdate(); - - // Copy the color components Uint8* pixel = &myPixels[(x + y * myWidth) * 4]; *pixel++ = color.r; *pixel++ = color.g; *pixel++ = color.b; *pixel++ = color.a; - - // The texture will need to be updated - myTextureUpdated = false; } //////////////////////////////////////////////////////////// Color Image::GetPixel(unsigned int x, unsigned int y) const { - // First check if the array of pixels needs to be updated - EnsureArrayUpdate(); - - // Get the color at (x, y) const Uint8* pixel = &myPixels[(x + y * myWidth) * 4]; - return Color(pixel[0], pixel[1], pixel[2], pixel[3]); } @@ -415,9 +252,6 @@ Color Image::GetPixel(unsigned int x, unsigned int y) const //////////////////////////////////////////////////////////// const Uint8* Image::GetPixelsPtr() const { - // First check if the array of pixels needs to be updated - EnsureArrayUpdate(); - if (!myPixels.empty()) { return &myPixels[0]; @@ -429,339 +263,4 @@ const Uint8* Image::GetPixelsPtr() const } } - -//////////////////////////////////////////////////////////// -void Image::UpdatePixels(const Uint8* pixels) -{ - if (pixels && myTexture) - { - EnsureGlContext(); - - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - // Update the texture from the array of pixels - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - - myArrayUpdated = false; - myTextureUpdated = true; - } -} - - -//////////////////////////////////////////////////////////// -void Image::UpdatePixels(const Uint8* pixels, const IntRect& rectangle) -{ - // Make sure that the texture is up-to-date - EnsureTextureUpdate(); - - if (pixels && myTexture) - { - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - // Update the texture from the array of pixels - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - - // The pixel cache is no longer up-to-date - myArrayUpdated = false; - } -} - - -//////////////////////////////////////////////////////////// -void Image::Bind() const -{ - // First check if the texture needs to be updated - EnsureTextureUpdate(); - - // Bind it - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); -} - - -//////////////////////////////////////////////////////////// -void Image::SetSmooth(bool smooth) -{ - if (smooth != myIsSmooth) - { - myIsSmooth = smooth; - - if (myTexture) - { - EnsureGlContext(); - - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); - - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - } - } -} - - -//////////////////////////////////////////////////////////// -unsigned int Image::GetWidth() const -{ - return myWidth; -} - - -//////////////////////////////////////////////////////////// -unsigned int Image::GetHeight() const -{ - return myHeight; -} - - -//////////////////////////////////////////////////////////// -bool Image::IsSmooth() const -{ - return myIsSmooth; -} - - -//////////////////////////////////////////////////////////// -FloatRect Image::GetTexCoords(const IntRect& rect) const -{ - if ((myTextureWidth != 0) && (myTextureHeight != 0)) - { - float width = static_cast(myTextureWidth); - float height = static_cast(myTextureHeight); - - if (myPixelsFlipped) - { - return FloatRect( rect.Left / width, - (myHeight - rect.Top) / height, - rect.Width / width, - -rect.Height / height); - } - else - { - return FloatRect(rect.Left / width, - rect.Top / height, - rect.Width / width, - rect.Height / height); - } - } - else - { - return FloatRect(0, 0, 0, 0); - } -} - - -//////////////////////////////////////////////////////////// -unsigned int Image::GetMaximumSize() -{ - EnsureGlContext(); - - GLint size; - GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size)); - - return static_cast(size); -} - - -//////////////////////////////////////////////////////////// -Image& Image::operator =(const Image& right) -{ - Image temp(right); - - std::swap(myWidth, temp.myWidth); - std::swap(myHeight, temp.myHeight); - std::swap(myTextureWidth, temp.myTextureWidth); - std::swap(myTextureHeight, temp.myTextureHeight); - std::swap(myTexture, temp.myTexture); - std::swap(myIsSmooth, temp.myIsSmooth); - std::swap(myArrayUpdated, temp.myArrayUpdated); - std::swap(myTextureUpdated, temp.myTextureUpdated); - std::swap(myPixelsFlipped, temp.myPixelsFlipped); - std::swap(myPixels, temp.myPixels); - - return *this; -} - - -//////////////////////////////////////////////////////////// -unsigned int Image::GetValidSize(unsigned int size) -{ - EnsureGlContext(); - - // Make sure that GLEW is initialized - priv::EnsureGlewInit(); - - if (GLEW_ARB_texture_non_power_of_two) - { - // If hardware supports NPOT textures, then just return the unmodified size - return size; - } - else - { - // If hardware doesn't support NPOT textures, we calculate the nearest power of two - unsigned int powerOfTwo = 1; - while (powerOfTwo < size) - powerOfTwo *= 2; - - return powerOfTwo; - } -} - - -//////////////////////////////////////////////////////////// -bool Image::CreateTexture(unsigned int width, unsigned int height) -{ - // Check if texture parameters are valid before creating it - if (!width || !height) - return false; - - // Compute the internal texture dimensions depending on NPOT textures support - unsigned int textureWidth = GetValidSize(width); - unsigned int textureHeight = GetValidSize(height); - - // Check the maximum texture size - unsigned int maxSize = GetMaximumSize(); - if ((textureWidth > maxSize) || (textureHeight > maxSize)) - { - Err() << "Failed to create image, its internal size is too high " - << "(" << textureWidth << "x" << textureHeight << ", " - << "maximum is " << maxSize << "x" << maxSize << ")" - << std::endl; - return false; - } - - // All the validity checks passed, we can store the new texture settings - myWidth = width; - myHeight = height; - myTextureWidth = textureWidth; - myTextureHeight = textureHeight; - - EnsureGlContext(); - - // Create the OpenGL texture if it doesn't exist yet - if (!myTexture) - { - GLuint texture; - GLCheck(glGenTextures(1, &texture)); - myTexture = static_cast(texture); - } - - // Initialize the texture - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - - myTextureUpdated = false; - - return true; -} - - -//////////////////////////////////////////////////////////// -void Image::EnsureTextureUpdate() const -{ - if (!myTextureUpdated) - { - if (myTexture && !myPixels.empty()) - { - EnsureGlContext(); - - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - // Update the texture with the pixels array in RAM - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0])); - myPixelsFlipped = false; - - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - } - - myTextureUpdated = true; - } -} - - -//////////////////////////////////////////////////////////// -void Image::EnsureArrayUpdate() const -{ - if (!myArrayUpdated) - { - EnsureGlContext(); - - // Save the previous texture - GLint previous; - GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - - // Resize the destination array of pixels - myPixels.resize(myWidth * myHeight * 4); - - if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped) - { - // Texture and array have the same size, we can use a direct copy - - // Copy pixels from texture to array - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0])); - } - else - { - // Texture and array don't have the same size, we have to use a slower algorithm - - // All the pixels will first be copied to a temporary array - ColorArray allPixels(myTextureWidth * myTextureHeight * 4); - GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); - GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0])); - - // Then we copy the useful pixels from the temporary array to the final one - const Uint8* src = &allPixels[0]; - Uint8* dst = &myPixels[0]; - int srcPitch = myTextureWidth * 4; - int dstPitch = myWidth * 4; - - // Handle the case where source pixels are flipped vertically - if (myPixelsFlipped) - { - src += srcPitch * (myHeight - 1); - srcPitch = -srcPitch; - } - - for (unsigned int i = 0; i < myHeight; ++i) - { - std::memcpy(dst, src, dstPitch); - src += srcPitch; - dst += dstPitch; - } - } - - // Restore the previous texture - GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); - - myArrayUpdated = true; - } -} - - -//////////////////////////////////////////////////////////// -void Image::Use() const -{ - EnsureTextureUpdate(); -} - } // namespace sf diff --git a/src/SFML/Graphics/RenderImage.cpp b/src/SFML/Graphics/RenderTexture.cpp similarity index 58% rename from src/SFML/Graphics/RenderImage.cpp rename to src/SFML/Graphics/RenderTexture.cpp index be5a87381..ff0986d1a 100644 --- a/src/SFML/Graphics/RenderImage.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -25,57 +25,57 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include -#include -#include +#include +#include +#include #include namespace sf { //////////////////////////////////////////////////////////// -RenderImage::RenderImage() : -myRenderImage(NULL) +RenderTexture::RenderTexture() : +myRenderTexture(NULL) { } //////////////////////////////////////////////////////////// -RenderImage::~RenderImage() +RenderTexture::~RenderTexture() { - delete myRenderImage; + delete myRenderTexture; } //////////////////////////////////////////////////////////// -bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuffer) +bool RenderTexture::Create(unsigned int width, unsigned int height, bool depthBuffer) { - // Create the image - if (!myImage.Create(width, height)) + // Create the texture + if (!myTexture.Create(width, height)) { - Err() << "Impossible to create render image (failed to create the target image)" << std::endl; + Err() << "Impossible to create render texture (failed to create the target texture)" << std::endl; return false; } - // We disable smoothing by default for render images + // We disable smoothing by default for render textures SetSmooth(false); // Create the implementation - delete myRenderImage; - if (priv::RenderImageImplFBO::IsAvailable()) + delete myRenderTexture; + if (priv::RenderTextureImplFBO::IsAvailable()) { // Use frame-buffer object (FBO) - myRenderImage = new priv::RenderImageImplFBO; + myRenderTexture = new priv::RenderTextureImplFBO; } else { // Use default implementation - myRenderImage = new priv::RenderImageImplDefault; + myRenderTexture = new priv::RenderTextureImplDefault; } - // Initialize the render image - if (!myRenderImage->Create(width, height, myImage.myTexture, depthBuffer)) + // Initialize the render texture + if (!myRenderTexture->Create(width, height, myTexture.myTexture, depthBuffer)) return false; // We can now initialize the render target part @@ -86,64 +86,61 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff //////////////////////////////////////////////////////////// -void RenderImage::SetSmooth(bool smooth) +void RenderTexture::SetSmooth(bool smooth) { - myImage.SetSmooth(smooth); + myTexture.SetSmooth(smooth); } //////////////////////////////////////////////////////////// -bool RenderImage::IsSmooth() const +bool RenderTexture::IsSmooth() const { - return myImage.IsSmooth(); + return myTexture.IsSmooth(); } //////////////////////////////////////////////////////////// -bool RenderImage::SetActive(bool active) +bool RenderTexture::SetActive(bool active) { - return myRenderImage && myRenderImage->Activate(active); + return myRenderTexture && myRenderTexture->Activate(active); } //////////////////////////////////////////////////////////// -void RenderImage::Display() +void RenderTexture::Display() { - // Update the target image + // Update the target texture if (SetActive(true)) { - myRenderImage->UpdateTexture(myImage.myTexture); - - myImage.myPixelsFlipped = true; - myImage.myArrayUpdated = false; - myImage.myTextureUpdated = true; + myRenderTexture->UpdateTexture(myTexture.myTexture); + myTexture.myPixelsFlipped = true; } } //////////////////////////////////////////////////////////// -unsigned int RenderImage::GetWidth() const +unsigned int RenderTexture::GetWidth() const { - return myImage.GetWidth(); + return myTexture.GetWidth(); } //////////////////////////////////////////////////////////// -unsigned int RenderImage::GetHeight() const +unsigned int RenderTexture::GetHeight() const { - return myImage.GetHeight(); + return myTexture.GetHeight(); } //////////////////////////////////////////////////////////// -const Image& RenderImage::GetImage() const +const Texture& RenderTexture::GetTexture() const { - return myImage; + return myTexture; } //////////////////////////////////////////////////////////// -bool RenderImage::Activate(bool active) +bool RenderTexture::Activate(bool active) { return SetActive(active); } diff --git a/src/SFML/Graphics/RenderImageImpl.cpp b/src/SFML/Graphics/RenderTextureImpl.cpp similarity index 91% rename from src/SFML/Graphics/RenderImageImpl.cpp rename to src/SFML/Graphics/RenderTextureImpl.cpp index eebc4113e..0dfc52ba3 100644 --- a/src/SFML/Graphics/RenderImageImpl.cpp +++ b/src/SFML/Graphics/RenderTextureImpl.cpp @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include namespace sf @@ -33,7 +33,7 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -RenderImageImpl::~RenderImageImpl() +RenderTextureImpl::~RenderTextureImpl() { // Nothing to do } diff --git a/src/SFML/Graphics/RenderImageImpl.hpp b/src/SFML/Graphics/RenderTextureImpl.hpp similarity index 80% rename from src/SFML/Graphics/RenderImageImpl.hpp rename to src/SFML/Graphics/RenderTextureImpl.hpp index 0b8bf9bf7..5d25c01f5 100644 --- a/src/SFML/Graphics/RenderImageImpl.hpp +++ b/src/SFML/Graphics/RenderTextureImpl.hpp @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_RENDERIMAGEIMPL_HPP -#define SFML_RENDERIMAGEIMPL_HPP +#ifndef SFML_RENDERTEXTUREIMPL_HPP +#define SFML_RENDERTEXTUREIMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -36,10 +36,10 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -/// \brief Abstract base class for render-image implementations +/// \brief Abstract base class for render-texture implementations /// //////////////////////////////////////////////////////////// -class RenderImageImpl : NonCopyable +class RenderTextureImpl : NonCopyable { public : @@ -47,14 +47,14 @@ public : /// \brief Destructor /// //////////////////////////////////////////////////////////// - virtual ~RenderImageImpl(); + virtual ~RenderTextureImpl(); //////////////////////////////////////////////////////////// - /// \brief Create the render image implementation + /// \brief Create the render texture implementation /// - /// \param width Width of the image to render to - /// \param height Height of the image to render to - /// \param textureId OpenGL texture identifier of the target image + /// \param width Width of the texture to render to + /// \param height Height of the texture to render to + /// \param textureId OpenGL identifier of the target texture /// \param depthBuffer Is a depth buffer requested? /// /// \return True if creation has been successful @@ -63,7 +63,7 @@ public : virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0; //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the render image for rendering + /// \brief Activate or deactivate the render texture for rendering /// /// \param active True to activate, false to deactivate /// @@ -86,4 +86,4 @@ public : } // namespace sf -#endif // SFML_RENDERIMAGEIMPL_HPP +#endif // SFML_RENDERTEXTUREIMPL_HPP diff --git a/src/SFML/Graphics/RenderImageImplDefault.cpp b/src/SFML/Graphics/RenderTextureImplDefault.cpp similarity index 83% rename from src/SFML/Graphics/RenderImageImplDefault.cpp rename to src/SFML/Graphics/RenderTextureImplDefault.cpp index 016a4314a..9450f6e30 100644 --- a/src/SFML/Graphics/RenderImageImplDefault.cpp +++ b/src/SFML/Graphics/RenderTextureImplDefault.cpp @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include #include #include @@ -36,7 +36,7 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -RenderImageImplDefault::RenderImageImplDefault() : +RenderTextureImplDefault::RenderTextureImplDefault() : myContext(0), myWidth (0), myHeight (0) @@ -46,7 +46,7 @@ myHeight (0) //////////////////////////////////////////////////////////// -RenderImageImplDefault::~RenderImageImplDefault() +RenderTextureImplDefault::~RenderTextureImplDefault() { // Destroy the context delete myContext; @@ -54,33 +54,33 @@ RenderImageImplDefault::~RenderImageImplDefault() //////////////////////////////////////////////////////////// -bool RenderImageImplDefault::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) +bool RenderTextureImplDefault::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) { // Store the dimensions myWidth = width; myHeight = height; // Create the in-memory OpenGL context - myContext = new Context(ContextSettings(depthBuffer ? 32 : 0, 0, 4), width, height); + myContext = new Context(ContextSettings(depthBuffer ? 32 : 0), width, height); return true; } //////////////////////////////////////////////////////////// -bool RenderImageImplDefault::Activate(bool active) +bool RenderTextureImplDefault::Activate(bool active) { return myContext->SetActive(active); } //////////////////////////////////////////////////////////// -void RenderImageImplDefault::UpdateTexture(unsigned int textureId) +void RenderTextureImplDefault::UpdateTexture(unsigned int textureId) { GLint previous; GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); - // Copy the rendered pixels to the image + // Copy the rendered pixels to the texture GLCheck(glBindTexture(GL_TEXTURE_2D, textureId)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); diff --git a/src/SFML/Graphics/RenderImageImplDefault.hpp b/src/SFML/Graphics/RenderTextureImplDefault.hpp similarity index 82% rename from src/SFML/Graphics/RenderImageImplDefault.hpp rename to src/SFML/Graphics/RenderTextureImplDefault.hpp index a216c3264..c66b922e8 100644 --- a/src/SFML/Graphics/RenderImageImplDefault.hpp +++ b/src/SFML/Graphics/RenderTextureImplDefault.hpp @@ -22,13 +22,13 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_RENDERIMAGEIMPLDEFAULT_HPP -#define SFML_RENDERIMAGEIMPLDEFAULT_HPP +#ifndef SFML_RENDERTEXTUREIMPLDEFAULT_HPP +#define SFML_RENDERTEXTUREIMPLDEFAULT_HPP //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include #include @@ -38,11 +38,11 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -/// \brief Default specialization of RenderImageImpl, +/// \brief Default specialization of RenderTextureImpl, /// using a in-memory context /// //////////////////////////////////////////////////////////// -class RenderImageImplDefault : public RenderImageImpl, GlResource +class RenderTextureImplDefault : public RenderTextureImpl, GlResource { public : @@ -50,22 +50,22 @@ public : /// \brief Default constructor /// //////////////////////////////////////////////////////////// - RenderImageImplDefault(); + RenderTextureImplDefault(); //////////////////////////////////////////////////////////// /// \brief Destructor /// //////////////////////////////////////////////////////////// - ~RenderImageImplDefault(); + ~RenderTextureImplDefault(); private : //////////////////////////////////////////////////////////// - /// \brief Create the render image implementation + /// \brief Create the render texture implementation /// - /// \param width Width of the image to render to - /// \param height Height of the image to render to - /// \param textureId OpenGL texture identifier of the target image + /// \param width Width of the texture to render to + /// \param height Height of the texture to render to + /// \param textureId OpenGL identifier of the target texture /// \param depthBuffer Is a depth buffer requested? /// /// \return True if creation has been successful @@ -74,7 +74,7 @@ private : virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the render image for rendering + /// \brief Activate or deactivate the render texture for rendering /// /// \param active True to activate, false to deactivate /// @@ -104,4 +104,4 @@ private : } // namespace sf -#endif // SFML_RENDERIMAGEIMPLDEFAULT_HPP +#endif // SFML_RENDERTEXTUREIMPLDEFAULT_HPP diff --git a/src/SFML/Graphics/RenderImageImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp similarity index 79% rename from src/SFML/Graphics/RenderImageImplFBO.cpp rename to src/SFML/Graphics/RenderTextureImplFBO.cpp index 9f12b40df..326452ae7 100644 --- a/src/SFML/Graphics/RenderImageImplFBO.cpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp @@ -25,8 +25,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include -#include +#include +#include #include #include @@ -36,7 +36,7 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -RenderImageImplFBO::RenderImageImplFBO() : +RenderTextureImplFBO::RenderTextureImplFBO() : myFrameBuffer(0), myDepthBuffer(0) { @@ -45,7 +45,7 @@ myDepthBuffer(0) //////////////////////////////////////////////////////////// -RenderImageImplFBO::~RenderImageImplFBO() +RenderTextureImplFBO::~RenderTextureImplFBO() { EnsureGlContext(); @@ -69,7 +69,7 @@ RenderImageImplFBO::~RenderImageImplFBO() //////////////////////////////////////////////////////////// -bool RenderImageImplFBO::IsAvailable() +bool RenderTextureImplFBO::IsAvailable() { EnsureGlContext(); @@ -81,7 +81,7 @@ bool RenderImageImplFBO::IsAvailable() //////////////////////////////////////////////////////////// -bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) +bool RenderTextureImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) { //Create the context myContext = new Context; @@ -92,7 +92,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne myFrameBuffer = static_cast(frameBuffer); if (!myFrameBuffer) { - Err() << "Impossible to create render image (failed to create the frame buffer object)" << std::endl; + Err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl; return false; } GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFrameBuffer)); @@ -105,7 +105,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne myDepthBuffer = static_cast(depth); if (!myDepthBuffer) { - Err() << "Impossible to create render image (failed to create the attached depth buffer)" << std::endl; + Err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl; return false; } GLCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, myDepthBuffer)); @@ -113,14 +113,14 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne GLCheck(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myDepthBuffer)); } - // Link the image to the frame buffer + // Link the texture to the frame buffer GLCheck(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0)); // A final check, just to be sure... if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); - Err() << "Impossible to create render image (failed to link the target image to the frame buffer)" << std::endl; + Err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl; return false; } @@ -129,13 +129,13 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne //////////////////////////////////////////////////////////// -bool RenderImageImplFBO::Activate(bool active) +bool RenderTextureImplFBO::Activate(bool active) { return myContext->SetActive(active); } //////////////////////////////////////////////////////////// -void RenderImageImplFBO::UpdateTexture(unsigned int) +void RenderTextureImplFBO::UpdateTexture(unsigned int) { glFlush(); } diff --git a/src/SFML/Graphics/RenderImageImplFBO.hpp b/src/SFML/Graphics/RenderTextureImplFBO.hpp similarity index 80% rename from src/SFML/Graphics/RenderImageImplFBO.hpp rename to src/SFML/Graphics/RenderTextureImplFBO.hpp index d13a5a910..489341dc4 100644 --- a/src/SFML/Graphics/RenderImageImplFBO.hpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.hpp @@ -22,13 +22,13 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_RENDERIMAGEIMPLFBO_HPP -#define SFML_RENDERIMAGEIMPLFBO_HPP +#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP +#define SFML_RENDERTEXTUREIMPLFBO_HPP //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include #include @@ -38,11 +38,11 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -/// \brief Specialization of RenderImageImpl using the -/// Frame Buffer Object OpenGL extension +/// \brief Specialization of RenderTextureImpl using the +/// FrameBuffer Object OpenGL extension /// //////////////////////////////////////////////////////////// -class RenderImageImplFBO : public RenderImageImpl, GlResource +class RenderTextureImplFBO : public RenderTextureImpl, GlResource { public : @@ -50,18 +50,18 @@ public : /// \brief Default constructor /// //////////////////////////////////////////////////////////// - RenderImageImplFBO(); + RenderTextureImplFBO(); //////////////////////////////////////////////////////////// /// \brief Destructor /// //////////////////////////////////////////////////////////// - ~RenderImageImplFBO(); + ~RenderTextureImplFBO(); //////////////////////////////////////////////////////////// /// \brief Check whether the system supports FBOs or not /// - /// \return True if FBO render images are supported + /// \return True if FBO render textures are supported /// //////////////////////////////////////////////////////////// static bool IsAvailable(); @@ -69,11 +69,11 @@ public : private : //////////////////////////////////////////////////////////// - /// \brief Create the render image implementation + /// \brief Create the render texture implementation /// - /// \param width Width of the image to render to - /// \param height Height of the image to render to - /// \param textureId OpenGL texture identifier of the target image + /// \param width Width of the texture to render to + /// \param height Height of the texture to render to + /// \param textureId OpenGL identifier of the target texture /// \param depthBuffer Is a depth buffer requested? /// /// \return True if creation has been successful @@ -82,7 +82,7 @@ private : virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the render image for rendering + /// \brief Activate or deactivate the render texture for rendering /// /// \param active True to activate, false to deactivate /// @@ -112,4 +112,4 @@ private : } // namespace sf -#endif // SFML_RENDERIMAGEIMPLFBO_HPP +#endif // SFML_RENDERTEXTUREIMPLFBO_HPP diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp index ddbd6a6f9..4fec0f264 100644 --- a/src/SFML/Graphics/RenderWindow.cpp +++ b/src/SFML/Graphics/RenderWindow.cpp @@ -26,6 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include +#include namespace sf @@ -81,6 +82,30 @@ unsigned int RenderWindow::GetHeight() const } +//////////////////////////////////////////////////////////// +Image RenderWindow::Capture() const +{ + Image image; + if (SetActive()) + { + int width = static_cast(GetWidth()); + int height = static_cast(GetHeight()); + + // copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top) + std::vector pixels(width * height * 4); + for (int i = 0; i < height; ++i) + { + Uint8* ptr = &pixels[i * width * 4]; + GLCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr)); + } + + image.Create(width, height, &pixels[0]); + } + + return image; +} + + //////////////////////////////////////////////////////////// void RenderWindow::OnCreate() { diff --git a/src/SFML/Graphics/Renderer.cpp b/src/SFML/Graphics/Renderer.cpp index 379dade1a..82a60a545 100644 --- a/src/SFML/Graphics/Renderer.cpp +++ b/src/SFML/Graphics/Renderer.cpp @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include #include #include @@ -202,7 +202,7 @@ void Renderer::SetBlendMode(Blend::Mode mode) { // Alpha blending // glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target - // is a RenderImage -- in this case the alpha value must be written directly to the target buffer + // is a RenderTexture -- in this case the alpha value must be written directly to the target buffer default : case Blend::Alpha : if (GLEW_EXT_blend_func_separate) @@ -231,7 +231,7 @@ void Renderer::SetBlendMode(Blend::Mode mode) //////////////////////////////////////////////////////////// -void Renderer::SetTexture(const Image* texture) +void Renderer::SetTexture(const Texture* texture) { if ((texture != myTexture) || (texture && (texture->myTexture != myTextureId)) || !myTextureIsValid) { @@ -246,12 +246,6 @@ void Renderer::SetTexture(const Image* texture) myTextureId = texture ? texture->myTexture : 0; myTextureIsValid = true; } - else if (texture && myTextureIsValid) - { - // If the texture was already the current one, make sure that - // it is synchronized (in case it was modified since last use) - texture->Use(); - } } diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index 798decdea..904da0a7d 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -225,7 +225,7 @@ void Shader::SetParameter(const std::string& name, const Vector3f& v) //////////////////////////////////////////////////////////// -void Shader::SetTexture(const std::string& name, const Image& texture) +void Shader::SetTexture(const std::string& name, const Texture& texture) { if (myShaderProgram) { diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp index 38e657eba..19405a7b6 100644 --- a/src/SFML/Graphics/Sprite.cpp +++ b/src/SFML/Graphics/Sprite.cpp @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include #include @@ -35,6 +35,7 @@ namespace sf { //////////////////////////////////////////////////////////// Sprite::Sprite() : +Drawable (), mySubRect (0, 0, 1, 1), myIsFlippedX(false), myIsFlippedY(false) @@ -44,31 +45,31 @@ myIsFlippedY(false) //////////////////////////////////////////////////////////// -Sprite::Sprite(const Image& image, const Vector2f& position, const Vector2f& scale, float rotation, const Color& color) : -Drawable (position, scale, rotation, color), +Sprite::Sprite(const Texture& texture) : +Drawable (), mySubRect (0, 0, 1, 1), myIsFlippedX(false), myIsFlippedY(false) { - SetImage(image); + SetTexture(texture); } //////////////////////////////////////////////////////////// -void Sprite::SetImage(const Image& image, bool adjustToNewSize) +void Sprite::SetTexture(const Texture& texture, bool adjustToNewSize) { - // If there was no valid image before, force adjusting to the new image size - if (!myImage) + // If there was no valid texture before, force adjusting to the new texture size + if (!myTexture) adjustToNewSize = true; - // If we want to adjust the size and the new image is valid, we adjust the source rectangle - if (adjustToNewSize && (image.GetWidth() > 0) && (image.GetHeight() > 0)) + // If we want to adjust the size and the new texture is valid, we adjust the source rectangle + if (adjustToNewSize && (texture.GetWidth() > 0) && (texture.GetHeight() > 0)) { - SetSubRect(IntRect(0, 0, image.GetWidth(), image.GetHeight())); + SetSubRect(IntRect(0, 0, texture.GetWidth(), texture.GetHeight())); } - // Assign the new image - myImage = ℑ + // Assign the new texture + myTexture = &texture; } @@ -109,9 +110,9 @@ void Sprite::FlipY(bool flipped) //////////////////////////////////////////////////////////// -const Image* Sprite::GetImage() const +const Texture* Sprite::GetTexture() const { - return myImage; + return myTexture; } @@ -129,26 +130,6 @@ Vector2f Sprite::GetSize() const } -//////////////////////////////////////////////////////////// -Color Sprite::GetPixel(unsigned int x, unsigned int y) const -{ - if (myImage) - { - unsigned int imageX = mySubRect.Left + x; - unsigned int imageY = mySubRect.Top + y; - - if (myIsFlippedX) imageX = mySubRect.Width - imageX - 1; - if (myIsFlippedY) imageY = mySubRect.Height - imageY - 1; - - return myImage->GetPixel(imageX, imageY) * GetColor(); - } - else - { - return GetColor(); - } -} - - //////////////////////////////////////////////////////////// void Sprite::Render(RenderTarget&, Renderer& renderer) const { @@ -156,10 +137,10 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const float width = static_cast(mySubRect.Width); float height = static_cast(mySubRect.Height); - // Check if the image is valid, and calculate the texture coordinates + // Check if the texture is valid, and calculate the texture coordinates FloatRect coords; - if (myImage) - coords = myImage->GetTexCoords(mySubRect); + if (myTexture) + coords = myTexture->GetTexCoords(mySubRect); // Compute the texture coordinates float left = coords.Left; @@ -170,7 +151,7 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const if (myIsFlippedY) std::swap(top, bottom); // Bind the texture - renderer.SetTexture(myImage); + renderer.SetTexture(myTexture); // Draw the sprite's geometry renderer.Begin(Renderer::TriangleStrip); diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp index b58bdd153..bed9c5e2b 100644 --- a/src/SFML/Graphics/Text.cpp +++ b/src/SFML/Graphics/Text.cpp @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include @@ -190,7 +190,7 @@ void Text::Render(RenderTarget&, Renderer& renderer) const return; // Bind the font texture - const Image& texture = myFont->GetImage(myCharacterSize); + const Texture& texture = myFont->GetTexture(myCharacterSize); renderer.SetTexture(&texture); // Computes values related to the text style diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp new file mode 100644 index 000000000..6bb76912a --- /dev/null +++ b/src/SFML/Graphics/Texture.cpp @@ -0,0 +1,506 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Texture::Texture() : +myWidth (0), +myHeight (0), +myTextureWidth (0), +myTextureHeight(0), +myTexture (0), +myIsSmooth (false), +myPixelsFlipped(false) +{ + +} + + +//////////////////////////////////////////////////////////// +Texture::Texture(const Texture& copy) : +Resource(), +myWidth (0), +myHeight (0), +myTextureWidth (0), +myTextureHeight(0), +myTexture (0), +myIsSmooth (false), +myPixelsFlipped(false) +{ + LoadFromImage(copy.CopyToImage()); +} + + +//////////////////////////////////////////////////////////// +Texture::~Texture() +{ + // Destroy the OpenGL texture + if (myTexture) + { + EnsureGlContext(); + + GLuint Texture = static_cast(myTexture); + GLCheck(glDeleteTextures(1, &Texture)); + } +} + + +//////////////////////////////////////////////////////////// +bool Texture::Create(unsigned int width, unsigned int height) +{ + // Check if texture parameters are valid before creating it + if (!width || !height) + { + Err() << "Failed to create texture, invalid size (" << width << "x" << height << ")" << std::endl; + return false; + } + + // Compute the internal texture dimensions depending on NPOT textures support + unsigned int textureWidth = GetValidSize(width); + unsigned int textureHeight = GetValidSize(height); + + // Check the maximum texture size + unsigned int maxSize = GetMaximumSize(); + if ((textureWidth > maxSize) || (textureHeight > maxSize)) + { + Err() << "Failed to create texture, its internal size is too high " + << "(" << textureWidth << "x" << textureHeight << ", " + << "maximum is " << maxSize << "x" << maxSize << ")" + << std::endl; + return false; + } + + // All the validity checks passed, we can store the new texture settings + myWidth = width; + myHeight = height; + myTextureWidth = textureWidth; + myTextureHeight = textureHeight; + myPixelsFlipped = false; + + EnsureGlContext(); + + // Create the OpenGL texture if it doesn't exist yet + if (!myTexture) + { + GLuint texture; + GLCheck(glGenTextures(1, &texture)); + myTexture = static_cast(texture); + } + + // Save the current texture binding + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + // Initialize the texture + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); + + // Restore the previous texture + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool Texture::LoadFromFile(const std::string& filename, const IntRect& area) +{ + Image image; + return image.LoadFromFile(filename) && LoadFromImage(image, area); +} + + +//////////////////////////////////////////////////////////// +bool Texture::LoadFromMemory(const void* data, std::size_t size, const IntRect& area) +{ + Image image; + return image.LoadFromMemory(data, size) && LoadFromImage(image, area); +} + + +//////////////////////////////////////////////////////////// +bool Texture::LoadFromStream(InputStream& stream, const IntRect& area) +{ + Image image; + return image.LoadFromStream(stream) && LoadFromImage(image, area); +} + + +//////////////////////////////////////////////////////////// +bool Texture::LoadFromImage(const Image& image, const IntRect& area) +{ + // Retrieve the image size + int width = static_cast(image.GetWidth()); + int height = static_cast(image.GetHeight()); + + // Load the entire image if the source area is either empty or contains the whole image + if (area.Width == 0 || (area.Height == 0) || + ((area.Left <= 0) && (area.Top <= 0) && (area.Width >= width) && (area.Height >= height))) + { + // Load the entire image + if (Create(image.GetWidth(), image.GetHeight())) + { + Update(image); + return true; + } + else + { + return false; + } + } + else + { + // Load a sub-area of the image + + // Adjust the rectangle to the size of the image + IntRect rectangle = area; + if (rectangle.Left < 0) rectangle.Left = 0; + if (rectangle.Top < 0) rectangle.Top = 0; + if (rectangle.Width > width) rectangle.Width = width; + if (rectangle.Height > height) rectangle.Height = height; + + // Create the texture and upload the pixels + if (Create(rectangle.Width, rectangle.Height)) + { + // Save the current texture binding + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + // Copy the pixels to the texture, row by row + const Uint8* pixels = image.GetPixelsPtr() + rectangle.Left + (width * rectangle.Top); + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + for (int i = 0; i < rectangle.Height; ++i) + { + GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, myWidth, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); + pixels += width; + } + myPixelsFlipped = false; + + // Restore the previous texture + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + + return true; + } + else + { + return false; + } + } +} + + +//////////////////////////////////////////////////////////// +unsigned int Texture::GetWidth() const +{ + return myWidth; +} + + +//////////////////////////////////////////////////////////// +unsigned int Texture::GetHeight() const +{ + return myHeight; +} + + +//////////////////////////////////////////////////////////// +Image Texture::CopyToImage() const +{ + // Easy case: empty texture + if (!myTexture) + return Image(); + + EnsureGlContext(); + + // Save the previous texture + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + // Create an array of pixels + std::vector pixels(myWidth * myHeight * 4); + + if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped) + { + // Texture is not padded nor flipped, we can use a direct copy + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0])); + } + else + { + // Texture is either padded or flipped, we have to use a slower algorithm + + // All the pixels will first be copied to a temporary array + std::vector allPixels(myTextureWidth * myTextureHeight * 4); + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0])); + + // Then we copy the useful pixels from the temporary array to the final one + const Uint8* src = &allPixels[0]; + Uint8* dst = &pixels[0]; + int srcPitch = myTextureWidth * 4; + int dstPitch = myWidth * 4; + + // Handle the case where source pixels are flipped vertically + if (myPixelsFlipped) + { + src += srcPitch * (myHeight - 1); + srcPitch = -srcPitch; + } + + for (unsigned int i = 0; i < myHeight; ++i) + { + std::memcpy(dst, src, dstPitch); + src += srcPitch; + dst += dstPitch; + } + } + + // Restore the previous texture + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + + // Create the image + Image image; + image.Create(myWidth, myHeight, &pixels[0]); + + return image; +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Uint8* pixels) +{ + // Update the whole texture + Update(pixels, myWidth, myHeight, 0, 0); +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y) +{ + assert(x + width <= myWidth); + assert(y + height <= myHeight); + + if (pixels && myTexture) + { + EnsureGlContext(); + + // Save the current texture binding + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + // Copy pixels from the given array to the texture + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); + myPixelsFlipped = false; + + // Restore the previous texture + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + } +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Image& image) +{ + // Update the whole texture + Update(image.GetPixelsPtr(), image.GetWidth(), image.GetHeight(), 0, 0); +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Image& image, unsigned int x, unsigned int y) +{ + Update(image.GetPixelsPtr(), image.GetWidth(), image.GetHeight(), x, y); +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Window& window) +{ + Update(window, 0, 0); +} + + +//////////////////////////////////////////////////////////// +void Texture::Update(const Window& window, unsigned int x, unsigned int y) +{ + assert(x + window.GetWidth() <= myWidth); + assert(y + window.GetHeight() <= myHeight); + + if (myTexture && window.SetActive(true)) + { + // Save the current texture binding + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + // Copy pixels from the back-buffer to the texture + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 0, 0, window.GetWidth(), window.GetHeight())); + myPixelsFlipped = true; + + // Restore the previous texture + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + } +} + + +//////////////////////////////////////////////////////////// +void Texture::Bind() const +{ + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); +} + + +//////////////////////////////////////////////////////////// +void Texture::SetSmooth(bool smooth) +{ + if (smooth != myIsSmooth) + { + myIsSmooth = smooth; + + if (myTexture) + { + EnsureGlContext(); + + GLint previous; + GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); + + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); + + GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); + } + } +} + + +//////////////////////////////////////////////////////////// +bool Texture::IsSmooth() const +{ + return myIsSmooth; +} + + +//////////////////////////////////////////////////////////// +FloatRect Texture::GetTexCoords(const IntRect& rect) const +{ + if ((myTextureWidth != 0) && (myTextureHeight != 0)) + { + float width = static_cast(myTextureWidth); + float height = static_cast(myTextureHeight); + + if (myPixelsFlipped) + { + return FloatRect( rect.Left / width, + (myHeight - rect.Top) / height, + rect.Width / width, + -rect.Height / height); + } + else + { + return FloatRect(rect.Left / width, + rect.Top / height, + rect.Width / width, + rect.Height / height); + } + } + else + { + return FloatRect(0, 0, 0, 0); + } +} + + +//////////////////////////////////////////////////////////// +unsigned int Texture::GetMaximumSize() +{ + EnsureGlContext(); + + GLint size; + GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size)); + + return static_cast(size); +} + + +//////////////////////////////////////////////////////////// +Texture& Texture::operator =(const Texture& right) +{ + Texture temp(right); + + std::swap(myWidth, temp.myWidth); + std::swap(myHeight, temp.myHeight); + std::swap(myTextureWidth, temp.myTextureWidth); + std::swap(myTextureHeight, temp.myTextureHeight); + std::swap(myTexture, temp.myTexture); + std::swap(myIsSmooth, temp.myIsSmooth); + std::swap(myPixelsFlipped, temp.myPixelsFlipped); + + return *this; +} + + +//////////////////////////////////////////////////////////// +unsigned int Texture::GetValidSize(unsigned int size) +{ + EnsureGlContext(); + + // Make sure that GLEW is initialized + priv::EnsureGlewInit(); + + if (GLEW_ARB_texture_non_power_of_two) + { + // If hardware supports NPOT textures, then just return the unmodified size + return size; + } + else + { + // If hardware doesn't support NPOT textures, we calculate the nearest power of two + unsigned int powerOfTwo = 1; + while (powerOfTwo < size) + powerOfTwo *= 2; + + return powerOfTwo; + } +} + +} // namespace sf