Improve texture cache code to use precise subpaths instead of hashes

This commit is contained in:
auria.mg
2017-01-06 21:07:53 -05:00
parent 3e5199334d
commit 67e66b44b0
10 changed files with 121 additions and 67 deletions

View File

@@ -956,7 +956,7 @@ void IrrDriver::applyResolutionSettings()
->getAsset(FileManager::GUI,"options_video.png"))
);
file_manager->pushTextureSearchPath(file_manager->getAsset(FileManager::MODEL,""));
file_manager->pushTextureSearchPath(file_manager->getAsset(FileManager::MODEL,""), "models");
const std::string materials_file =
file_manager->getAssetChecked(FileManager::MODEL, "materials.xml");
if (materials_file != "")
@@ -1576,6 +1576,7 @@ void IrrDriver::unsetTextureErrorMessage()
} // unsetTextureErrorMessage
// ----------------------------------------------------------------------------
#if 0
/** Retrieve all textures in the specified directory, generate a smaller
* version for each of them and save them in the cache. Smaller textures are
* generated only if they do not already exist or if their original version
@@ -1642,7 +1643,7 @@ std::string IrrDriver::getSmallerTexture(const std::string& filename)
} // if !file_manager->fileExists(cached_file)
return cached_file;
} // getSmallerTexture
#endif
// ----------------------------------------------------------------------------
/** Loads a texture from a file and returns the texture object. This is just
* a convenient wrapper which loads the texture from a STK asset directory.

View File

@@ -220,8 +220,10 @@ public:
bool OnEvent(const irr::SEvent &event);
void setAmbientLight(const video::SColorf &light,
bool force_SH_computation = true);
#if 0
std::string generateSmallerTextures(const std::string& dir);
std::string getSmallerTexture(const std::string& texture);
#endif
video::ITexture *getTexture(FileManager::AssetType type,
const std::string &filename,
bool is_premul=false,

View File

@@ -15,6 +15,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config/user_config.hpp"
#include "graphics/stk_texture.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
@@ -79,15 +80,41 @@ void STKTexture::reload(bool no_upload, video::IImage* pre_loaded_tex)
if (!no_upload && m_mesh_texture && CVS->isTextureCompressionEnabled())
{
std::string orig_file = NamedPath.getPtr();
compressed_texture = getHashedName(orig_file);
if (!file_manager->fileIsNewer(orig_file, compressed_texture))
std::string basename = StringUtils::getBasename(orig_file);
//Log::info("STKTexture", "Basename: <%s> / <%s>", basename.c_str(), orig_file.c_str());
std::string container_id;
if (file_manager->searchTextureContainerId(container_id, basename))
{
//Log::info("STKTexture", "container_id: %s", container_id.c_str());
std::string cache_subdir = "hd/";
if ((UserConfigParams::m_high_definition_textures & 0x01) == 0x01)
{
cache_subdir = "hd/";
}
else
{
cache_subdir = StringUtils::insertValues("resized_%i/",
(int)UserConfigParams::m_max_texture_size);
}
std::string cache_dir = file_manager->getCachedTexturesDir() + cache_subdir + container_id;
compressed_texture = cache_dir + "/" + basename + ".stktz";
if (loadCompressedTexture(compressed_texture))
{
Log::info("STKTexture", "Compressed %s for texture %s",
compressed_texture.c_str(), orig_file.c_str());
return;
}
file_manager->checkAndCreateDirectoryP(cache_dir);
}
else
{
Log::warn("STKTexture", "Cannot find container_id for texture '%s'", orig_file.c_str());
}
}
#endif
@@ -402,20 +429,6 @@ void STKTexture::saveCompressedTexture(const std::string& compressed_tex)
#endif
} // saveCompressedTexture
//-----------------------------------------------------------------------------
std::string STKTexture::getHashedName(const std::string& orig_file)
{
std::string result = file_manager->getCachedTexturesDir();
std::stringstream hash;
size_t hash_1 = std::hash<std::string>{}(StringUtils::getPath(orig_file));
size_t hash_2 =
std::hash<std::string>{}(StringUtils::getBasename(orig_file));
const core::dimension2du& max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
hash << std::hex << hash_1 << hash_2 << max_size.Height;
return result + hash.str() + ".stktz";
} // getHashedName
//-----------------------------------------------------------------------------
bool STKTexture::hasMipMaps() const
{

View File

@@ -56,7 +56,7 @@ private:
// ------------------------------------------------------------------------
void saveCompressedTexture(const std::string& file_name);
// ------------------------------------------------------------------------
std::string getHashedName(const std::string& orig_file);
//std::string getHashedName(const std::string& orig_file);
public:
// ------------------------------------------------------------------------

View File

@@ -309,11 +309,11 @@ void FileManager::init()
// Note that we can't push the texture search path in the constructor
// since this also adds a file archive to the file system - and
// m_file_system is deleted (in irr_driver)
pushTextureSearchPath(m_subdir_name[TEXTURE]);
if(fileExists(m_subdir_name[TEXTURE]+"deprecated/"))
pushTextureSearchPath(m_subdir_name[TEXTURE]+"deprecated/");
pushTextureSearchPath(m_subdir_name[TEXTURE], "textures");
if (fileExists(m_subdir_name[TEXTURE]+"deprecated/"))
pushTextureSearchPath(m_subdir_name[TEXTURE]+"deprecated/", "deprecatedtex");
pushTextureSearchPath(m_subdir_name[GUI]);
pushTextureSearchPath(m_subdir_name[GUI], "gui");
pushModelSearchPath (m_subdir_name[MODEL]);
pushMusicSearchPath (m_subdir_name[MUSIC]);
@@ -517,9 +517,9 @@ void FileManager::pushModelSearchPath(const std::string& path)
/** Adds a texture search path to the list of texture search paths.
* This path will be searched before any other existing paths.
*/
void FileManager::pushTextureSearchPath(const std::string& path)
void FileManager::pushTextureSearchPath(const std::string& path, const std::string& container_id)
{
m_texture_search_path.push_back(path);
m_texture_search_path.push_back(TextureSearchPath(path, container_id));
const int n=m_file_system->getFileArchiveCount();
m_file_system->addFileArchive(createAbsoluteFilename(path),
/*ignoreCase*/false,
@@ -548,9 +548,9 @@ void FileManager::popTextureSearchPath()
{
if(!m_texture_search_path.empty())
{
std::string dir = m_texture_search_path.back();
TextureSearchPath dir = m_texture_search_path.back();
m_texture_search_path.pop_back();
m_file_system->removeFileArchive(createAbsoluteFilename(dir));
m_file_system->removeFileArchive(createAbsoluteFilename(dir.m_texture_search_path));
}
} // popTextureSearchPath
@@ -601,6 +601,29 @@ bool FileManager::findFile(std::string& full_path,
return false;
} // findFile
//-----------------------------------------------------------------------------
/** Tries to find the specified file in any of the given search paths.
* \param full_path On return contains the full path of the file, or
* "" if the file is not found.
* \param file_name The name of the file to look for.
* \param search_path The list of paths to search for the file.
* \return True if the file is found, false otherwise.
*/
bool FileManager::findFile(std::string& full_path,
const std::string& file_name,
const std::vector<TextureSearchPath>& search_path) const
{
for (std::vector<TextureSearchPath>::const_reverse_iterator
i = search_path.rbegin();
i != search_path.rend(); ++i)
{
full_path = i->m_texture_search_path + file_name;
if (m_file_system->existFile(full_path.c_str())) return true;
}
full_path = "";
return false;
} // findFile
//-----------------------------------------------------------------------------
std::string FileManager::getAssetChecked(FileManager::AssetType type,
const std::string& name,
@@ -693,6 +716,27 @@ std::string FileManager::searchTexture(const std::string& file_name) const
return path;
} // searchTexture
//-----------------------------------------------------------------------------
bool FileManager::searchTextureContainerId(std::string& container_id,
const std::string& file_name) const
{
std::string full_path;
for (std::vector<TextureSearchPath>::const_reverse_iterator
i = m_texture_search_path.rbegin();
i != m_texture_search_path.rend(); ++i)
{
full_path = i->m_texture_search_path + file_name;
if (m_file_system->existFile(full_path.c_str()))
{
container_id = i->m_container_id;
return true;
}
}
full_path = "";
return false;
} // findFile
//-----------------------------------------------------------------------------
/** Returns the list of all directories in which music files are searched.
*/
@@ -1137,35 +1181,6 @@ void FileManager::redirectOutput()
Log::openOutputFiles(logoutfile);
} // redirectOutput
//-----------------------------------------------------------------------------
/** Returns the theoretical location of the cached version of a texture
* depending of the current config. (This function also works for directories:
* in this case the returned directory will be the cache location for all
* textures that you will find in the specified directory. The specified
* directory must end with '/')
* \note The returned location is where the cached data should be read or
* written but the file itseft does not necessarity exist. However, the
* directory structure is automatically created if it does not exist.
*/
std::string FileManager::getTextureCacheLocation(const std::string& filename)
{
std::string file = StringUtils::getBasename(filename);
std::string parent_dir = StringUtils::getPath(filename);
if (StringUtils::hasSuffix(parent_dir, "/"))
parent_dir = parent_dir.substr(0, parent_dir.size() - 1);
parent_dir = StringUtils::getBasename(parent_dir);
std::string cache_subdir = (UserConfigParams::m_high_definition_textures & 0x01) == 0x01
? "hd/"
: "resized/";
std::string cached_file =
getCachedTexturesDir() + cache_subdir + parent_dir + "/";
checkAndCreateDirectoryP(cached_file);
cached_file += file;
return cached_file;
} // getTextureCacheLocation
//-----------------------------------------------------------------------------
/** Returns the directory for addon files. */
const std::string &FileManager::getAddonsDir() const

View File

@@ -37,6 +37,17 @@ using namespace irr;
#include "io/xml_node.hpp"
#include "utils/no_copy.hpp"
struct TextureSearchPath
{
std::string m_texture_search_path;
std::string m_container_id;
TextureSearchPath(std::string path, std::string container_id) :
m_texture_search_path(path), m_container_id(container_id)
{
}
};
/**
* \brief class handling files and paths
* \ingroup io
@@ -52,6 +63,7 @@ public:
SCRIPT, SFX, SHADER, SKIN, TEXTURE, TTF,
TRANSLATION, ASSET_MAX = TRANSLATION,
ASSET_COUNT};
private:
/** The names of the various subdirectories of the asset types. */
@@ -84,14 +96,19 @@ private:
/** Directory where user-defined grand prix are stored. */
std::string m_gp_dir;
std::vector<TextureSearchPath> m_texture_search_path;
std::vector<std::string>
m_texture_search_path,
m_model_search_path,
m_music_search_path;
bool findFile(std::string& full_path,
const std::string& fname,
const std::vector<std::string>& search_path)
const;
bool findFile(std::string& full_path,
const std::string& fname,
const std::vector<TextureSearchPath>& search_path)
const;
void makePath(std::string& path, const std::string& dir,
const std::string& fname) const;
bool checkAndCreateDirectory(const std::string &path);
@@ -124,7 +141,6 @@ public:
std::string getReplayDir() const;
std::string getCachedTexturesDir() const;
std::string getGPDir() const;
std::string getTextureCacheLocation(const std::string& filename);
bool checkAndCreateDirectoryP(const std::string &path);
const std::string &getAddonsDir() const;
std::string getAddonsFile(const std::string &name);
@@ -157,6 +173,9 @@ public:
return fileExists(std::string(prefix) + path);
}
// ------------------------------------------------------------------------
bool searchTextureContainerId(std::string& container_id,
const std::string& file_name) const;
// ------------------------------------------------------------------------
/** Returns the name of the stdout file for log messages. */
static const std::string& getStdoutName() { return m_stdout_filename; }
// ------------------------------------------------------------------------
@@ -165,7 +184,7 @@ public:
bool make_full_path=false) const;
void pushTextureSearchPath(const std::string& path);
void pushTextureSearchPath(const std::string& path, const std::string& container_id);
void pushModelSearchPath(const std::string& path);
void popTextureSearchPath();
void popModelSearchPath();

View File

@@ -225,8 +225,9 @@ void KartProperties::load(const std::string &filename, const std::string &node)
// Load material
std::string materials_file = m_root+"materials.xml";
file_manager->pushModelSearchPath (m_root);
file_manager->pushTextureSearchPath(m_root);
std::string unique_id = StringUtils::insertValues("karts/%s", m_ident.c_str());
file_manager->pushModelSearchPath(m_root);
file_manager->pushTextureSearchPath(m_root, unique_id);
irr_driver->setTextureErrorMessage("Error while loading kart '%s':",
m_name);

View File

@@ -1574,7 +1574,7 @@ int main(int argc, char *argv[] )
// Both item_manager and powerup_manager load models and therefore
// textures from the model directory. To avoid reading the
// materials.xml twice, we do this here once for both:
file_manager->pushTextureSearchPath(file_manager->getAsset(FileManager::MODEL,""));
file_manager->pushTextureSearchPath(file_manager->getAsset(FileManager::MODEL,""), "models");
const std::string materials_file =
file_manager->getAsset(FileManager::MODEL,"materials.xml");
if(materials_file!="")

View File

@@ -1627,9 +1627,11 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
m_sky_type = SKY_NONE;
m_track_object_manager = new TrackObjectManager();
std::string unique_id = StringUtils::insertValues("tracks/%s", m_ident.c_str());
// Add the track directory to the texture search path
file_manager->pushTextureSearchPath(m_root);
file_manager->pushModelSearchPath (m_root);
file_manager->pushTextureSearchPath(m_root, unique_id);
file_manager->pushModelSearchPath(m_root);
// For now ignore the resize cache, since atm it only handles texturs in
// the track directory.

View File

@@ -232,7 +232,8 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
return;
}
file_manager->pushTextureSearchPath(lib_path + "/");
std::string unique_id = StringUtils::insertValues("library/%s", name.c_str());
file_manager->pushTextureSearchPath(lib_path + "/", unique_id);
file_manager->pushModelSearchPath(lib_path);
material_manager->pushTempMaterial(lib_path + "/materials.xml");
model_def_loader.addToLibrary(name, libroot);
@@ -438,7 +439,7 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
World::getWorld()->getIdent() == IDENT_CUTSCENE);
m_model_file = model_file;
file_manager->pushTextureSearchPath(StringUtils::getPath(model_file));
//file_manager->pushTextureSearchPath(StringUtils::getPath(model_file));
#ifndef SERVER_ONLY
if (file_manager->fileExists(model_file))
{
@@ -466,7 +467,7 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
throw std::runtime_error("Model '" + model_file + "' cannot be found");
}
file_manager->popTextureSearchPath();
//file_manager->popTextureSearchPath();
init(NULL, NULL, true);
} // TrackObjectPresentationMesh