[Android] Fixed memory leak when loading asset files

This commit is contained in:
Jonathan De Wachter 2013-11-17 05:31:40 +01:00
parent 891cd261b8
commit 634c3dc2a7
9 changed files with 275 additions and 109 deletions

View File

@ -305,6 +305,9 @@ private :
Info m_info; ///< Information about the font Info m_info; ///< Information about the font
mutable PageTable m_pages; ///< Table containing the glyphs pages by character size mutable PageTable m_pages; ///< Table containing the glyphs pages by character size
mutable std::vector<Uint8> m_pixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture mutable std::vector<Uint8> m_pixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture
#ifdef SFML_SYSTEM_ANDROID
void* m_stream; ///< Asset file streamer (if loaded from file)
#endif
}; };
} // namespace sf } // namespace sf
@ -351,19 +354,19 @@ private :
/// \code /// \code
/// // Declare a new font /// // Declare a new font
/// sf::Font font; /// sf::Font font;
/// ///
/// // Load it from a file /// // Load it from a file
/// if (!font.loadFromFile("arial.ttf")) /// if (!font.loadFromFile("arial.ttf"))
/// { /// {
/// // error... /// // error...
/// } /// }
/// ///
/// // Create a text which uses our font /// // Create a text which uses our font
/// sf::Text text1; /// sf::Text text1;
/// text1.setFont(font); /// text1.setFont(font);
/// text1.setCharacterSize(30); /// text1.setCharacterSize(30);
/// text1.setStyle(sf::Text::Regular); /// text1.setStyle(sf::Text::Regular);
/// ///
/// // Create another text using the same font, but with different parameters /// // Create another text using the same font, but with different parameters
/// sf::Text text2; /// sf::Text text2;
/// text2.setFont(font); /// text2.setFont(font);

View File

@ -55,6 +55,12 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image(); Image();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~Image();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the image and fill it with a unique color /// \brief Create the image and fill it with a unique color
/// ///
@ -259,6 +265,9 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2u m_size; ///< Image size Vector2u m_size; ///< Image size
std::vector<Uint8> m_pixels; ///< Pixels of the image std::vector<Uint8> m_pixels; ///< Pixels of the image
#ifdef SFML_SYSTEM_ANDROID
void* m_stream; ///< Asset file streamer (if loaded from file)
#endif
}; };
} // namespace sf } // namespace sf

View File

@ -27,8 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundFile.hpp> #include <SFML/Audio/SoundFile.hpp>
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/Activity.hpp> #include <SFML/System/Android/ResourceStream.hpp>
#include <SFML/System/Lock.hpp>
#endif #endif
#include <SFML/System/InputStream.hpp> #include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -59,7 +58,11 @@ m_sampleCount (0),
m_channelCount(0), m_channelCount(0),
m_sampleRate (0) m_sampleRate (0)
{ {
#ifdef SFML_SYSTEM_ANDROID
m_resourceStream = NULL;
#endif
} }
@ -68,6 +71,13 @@ SoundFile::~SoundFile()
{ {
if (m_file) if (m_file)
sf_close(m_file); sf_close(m_file);
#ifdef SFML_SYSTEM_ANDROID
if (m_resourceStream)
delete (priv::ResourceStream*)m_resourceStream;
#endif
} }
@ -118,39 +128,11 @@ bool SoundFile::openRead(const std::string& filename)
#else #else
priv::ActivityStates* states = priv::getActivity(NULL); if (m_resourceStream)
Lock lock(states->mutex); delete (priv::ResourceStream*)m_resourceStream;
// Open the file m_resourceStream = new priv::ResourceStream(filename);
AAsset* file = NULL; return openRead(*(priv::ResourceStream*)m_resourceStream);
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load sound \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load sound \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = openRead(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif #endif
} }

View File

@ -218,6 +218,9 @@ private :
std::size_t m_sampleCount; ///< Total number of samples in the file std::size_t m_sampleCount; ///< Total number of samples in the file
unsigned int m_channelCount; ///< Number of channels used by the sound unsigned int m_channelCount; ///< Number of channels used by the sound
unsigned int m_sampleRate; ///< Number of samples per second unsigned int m_sampleRate; ///< Number of samples per second
#ifdef SFML_SYSTEM_ANDROID
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
#endif
}; };
} // namespace priv } // namespace priv

View File

@ -28,8 +28,7 @@
#include <SFML/Graphics/Font.hpp> #include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/Activity.hpp> #include <SFML/System/Android/ResourceStream.hpp>
#include <SFML/System/Lock.hpp>
#endif #endif
#include <SFML/System/InputStream.hpp> #include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -88,6 +87,10 @@ m_info (copy.m_info),
m_pages (copy.m_pages), m_pages (copy.m_pages),
m_pixelBuffer(copy.m_pixelBuffer) m_pixelBuffer(copy.m_pixelBuffer)
{ {
#ifdef SFML_SYSTEM_ANDROID
m_stream = NULL;
#endif
// Note: as FreeType doesn't provide functions for copying/cloning, // Note: as FreeType doesn't provide functions for copying/cloning,
// we must share all the FreeType pointers // we must share all the FreeType pointers
@ -100,6 +103,13 @@ m_pixelBuffer(copy.m_pixelBuffer)
Font::~Font() Font::~Font()
{ {
cleanup(); cleanup();
#ifdef SFML_SYSTEM_ANDROID
if (m_stream)
delete (priv::ResourceStream*)m_stream;
#endif
} }
@ -149,39 +159,11 @@ bool Font::loadFromFile(const std::string& filename)
#else #else
priv::ActivityStates* states = priv::getActivity(NULL); if (m_stream)
Lock lock(states->mutex); delete (priv::ResourceStream*)m_stream;
// Open the file m_stream = new priv::ResourceStream(filename);
AAsset* file = NULL; return loadFromStream(*(priv::ResourceStream*)m_stream);
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load font \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load font \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = loadFromMemory(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif #endif
} }

View File

@ -27,11 +27,10 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp> #include <SFML/Graphics/ImageLoader.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
#endif
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -42,7 +41,23 @@ namespace sf
Image::Image() : Image::Image() :
m_size(0, 0) m_size(0, 0)
{ {
#ifdef SFML_SYSTEM_ANDROID
m_stream = NULL;
#endif
}
////////////////////////////////////////////////////////////
Image::~Image()
{
#ifdef SFML_SYSTEM_ANDROID
if (m_stream)
delete (priv::ResourceStream*)m_stream;
#endif
} }
@ -108,43 +123,15 @@ bool Image::loadFromFile(const std::string& filename)
{ {
#ifndef SFML_SYSTEM_ANDROID #ifndef SFML_SYSTEM_ANDROID
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size); return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
#else #else
priv::ActivityStates* states = priv::getActivity(NULL); if (m_stream)
Lock lock(states->mutex); delete (priv::ResourceStream*)m_stream;
// Open the file m_stream = new priv::ResourceStream(filename);
AAsset* file = NULL; return loadFromStream(*(priv::ResourceStream*)m_stream);
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load image \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load image \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = loadFromMemory(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif #endif
} }

View File

@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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 <SFML/System/Android/ResourceStream.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ResourceStream::ResourceStream(const std::string& filename) :
m_file (NULL)
{
ActivityStates* states = getActivity(NULL);
Lock(states->mutex);
m_file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
}
////////////////////////////////////////////////////////////
ResourceStream::~ResourceStream()
{
AAsset_close(m_file);
}
////////////////////////////////////////////////////////////
Int64 ResourceStream::read(void *data, Int64 size)
{
return AAsset_read(m_file, data, size);
}
////////////////////////////////////////////////////////////
Int64 ResourceStream::seek(Int64 position)
{
AAsset_seek(m_file, position, SEEK_SET);
}
////////////////////////////////////////////////////////////
Int64 ResourceStream::tell()
{
return getSize() - AAsset_getRemainingLength(m_file);
}
////////////////////////////////////////////////////////////
Int64 ResourceStream::getSize()
{
return AAsset_getLength(m_file);
}
} // namespace priv
} // namespace sf

View File

@ -0,0 +1,113 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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_RESOURCESTREAM_HPP
#define SFML_RESOURCESTREAM_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <SFML/System/InputStream.hpp>
#include <android/asset_manager.h>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Read from Android asset files
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API ResourceStream : public InputStream
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param filename Filename of the asset
///
////////////////////////////////////////////////////////////
ResourceStream(const std::string& filename);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~ResourceStream();
////////////////////////////////////////////////////////////
/// \brief Read data from the asset
///
/// \param data Buffer where the asset data is copied
/// \param size Number of bytes read
///
/// \return The number of bytes actually read, or -1 on error
///
////////////////////////////////////////////////////////////
Int64 read(void *data, Int64 size);
////////////////////////////////////////////////////////////
/// \brief Change the current reading position in the asset file
///
/// \param position The position to seek to, from the beginning
///
/// \return The position actually sought to, or -1 on error
///
////////////////////////////////////////////////////////////
Int64 seek(Int64 position);
////////////////////////////////////////////////////////////
/// \brief Get the current reading position in the asset file
///
/// \return The current position, or -1 on error.
///
////////////////////////////////////////////////////////////
Int64 tell();
////////////////////////////////////////////////////////////
/// \brief Return the size of the asset file
///
/// \return The total number of bytes available in the asset, or -1 on error
///
////////////////////////////////////////////////////////////
Int64 getSize();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
AAsset* m_file; ///< The asset file to read
};
} // namespace priv
} // namespace sf
#endif // SFML_RESOURCESTREAM_HPP

View File

@ -71,6 +71,8 @@ else()
set(PLATFORM_SRC ${PLATFORM_SRC} set(PLATFORM_SRC ${PLATFORM_SRC}
${SRCROOT}/Android/Activity.hpp ${SRCROOT}/Android/Activity.hpp
${SRCROOT}/Android/Activity.cpp ${SRCROOT}/Android/Activity.cpp
${SRCROOT}/Android/ResourceStream.cpp
${SRCROOT}/Android/ResourceStream.cpp
) )
endif() endif()
@ -91,7 +93,7 @@ endif()
# pthread is implicitly linked by the NDK # pthread is implicitly linked by the NDK
if(SFML_OS_ANDROID) if(SFML_OS_ANDROID)
set(SYSTEM_EXT_LIBS "") set(SYSTEM_EXT_LIBS android)
endif() endif()
# define the sfml-system target # define the sfml-system target