|
|
@@ -25,143 +25,71 @@ OTHER DEALINGS IN THE SOFTWARE.
|
|
|
*/
|
|
|
|
|
|
#include <algorithm>
|
|
|
-#include <cstdio>
|
|
|
|
|
|
#include "Types.h"
|
|
|
#include "ResourceManager.h"
|
|
|
+#include "ResourceRegistry.h"
|
|
|
#include "StringUtils.h"
|
|
|
#include "Hash.h"
|
|
|
-#include "Path.h"
|
|
|
-#include "Log.h"
|
|
|
-#include "Device.h"
|
|
|
-#include "Filesystem.h"
|
|
|
-#include "TextReader.h"
|
|
|
-#include "DiskFile.h"
|
|
|
-#include "TextureResource.h"
|
|
|
-#include "MeshResource.h"
|
|
|
-#include "SoundResource.h"
|
|
|
+#include "TempAllocator.h"
|
|
|
|
|
|
namespace crown
|
|
|
{
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-ResourceManager::ResourceManager(Bundle& bundle) :
|
|
|
- m_resource_bundle(bundle),
|
|
|
- m_resources(m_allocator),
|
|
|
- m_loading_queue(m_allocator),
|
|
|
- m_loaded_queue(m_allocator),
|
|
|
- m_seed(0),
|
|
|
- m_background_thread_should_run(true),
|
|
|
- m_thread(ResourceManager::background_thread, (void*)this, "resource-loader-thread")
|
|
|
+ResourceManager::ResourceManager(Bundle& bundle, uint32_t seed) :
|
|
|
+ m_resource_heap("resource", default_allocator()),
|
|
|
+ m_loader(bundle, m_resource_heap),
|
|
|
+ m_seed(seed),
|
|
|
+ m_resources(default_allocator())
|
|
|
{
|
|
|
- DiskFile* seed_file = device()->filesystem()->open("seed.ini", FOM_READ);
|
|
|
- TextReader reader(*seed_file);
|
|
|
-
|
|
|
- char tmp_buf[32];
|
|
|
- reader.read_string(tmp_buf, 32);
|
|
|
-
|
|
|
- device()->filesystem()->close(seed_file);
|
|
|
-
|
|
|
- sscanf(tmp_buf, "%u", &m_seed);
|
|
|
+ m_loader.start();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
ResourceManager::~ResourceManager()
|
|
|
{
|
|
|
- m_background_thread_should_run = false;
|
|
|
+ m_loader.stop();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-ResourceId ResourceManager::load(const char* name)
|
|
|
+ResourceId ResourceManager::load(const char* type, const char* name)
|
|
|
{
|
|
|
- char basename[512];
|
|
|
- char extension[512];
|
|
|
-
|
|
|
- path::filename_without_extension(name, basename, 512);
|
|
|
- path::extension(name, extension, 512);
|
|
|
-
|
|
|
- uint32_t name_hash = hash::murmur2_32(basename, string::strlen(basename), m_seed);
|
|
|
- uint32_t type_hash = hash::murmur2_32(extension, string::strlen(extension), 0);
|
|
|
-
|
|
|
- return load(name_hash, type_hash);
|
|
|
+ return load(resource_id(type, name));
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
void ResourceManager::unload(ResourceId name)
|
|
|
{
|
|
|
CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
|
|
|
-
|
|
|
- m_resources_mutex.lock();
|
|
|
|
|
|
- ResourceEntry& entry = m_resources[name.index];
|
|
|
+ ResourceEntry* entry = find(name);
|
|
|
|
|
|
- entry.references--;
|
|
|
+ entry->references--;
|
|
|
|
|
|
- if (entry.references == 0 && entry.state == RS_LOADED)
|
|
|
+ if (entry->references == 0 && entry->state == RS_LOADED)
|
|
|
{
|
|
|
- unload_by_type(name, entry.resource);
|
|
|
-
|
|
|
- entry.state = RS_UNLOADED;
|
|
|
- entry.resource = NULL;
|
|
|
-
|
|
|
+ resource_on_unload(name.type, m_resource_heap, entry->resource);
|
|
|
|
|
|
+ entry->state = RS_UNLOADED;
|
|
|
+ entry->resource = NULL;
|
|
|
}
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void ResourceManager::reload(ResourceId name)
|
|
|
-{
|
|
|
- CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
|
|
|
-
|
|
|
- m_resources_mutex.lock();
|
|
|
-
|
|
|
- ResourceEntry& entry = m_resources[name.index];
|
|
|
-
|
|
|
- if (entry.state == RS_LOADED)
|
|
|
- {
|
|
|
- unload_by_type(name, entry.resource);
|
|
|
-
|
|
|
- entry.state = RS_UNLOADED;
|
|
|
- entry.resource = NULL;
|
|
|
-
|
|
|
- entry.resource = load_by_type(name);
|
|
|
- entry.state = RS_LOADED;
|
|
|
- }
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
bool ResourceManager::has(ResourceId name) const
|
|
|
{
|
|
|
- bool has_resource = false;
|
|
|
-
|
|
|
- m_resources_mutex.lock();
|
|
|
+ ResourceEntry* entry = find(name);
|
|
|
|
|
|
- if (m_resources.size() > name.index)
|
|
|
- {
|
|
|
- has_resource = (m_resources[name.index].id.name == name.name);
|
|
|
- }
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-
|
|
|
- return has_resource;
|
|
|
+ return entry != NULL;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
const void* ResourceManager::data(ResourceId name) const
|
|
|
{
|
|
|
CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
|
|
|
-
|
|
|
- m_resources_mutex.lock();
|
|
|
|
|
|
- void* resource = m_resources[name.index].resource;
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-
|
|
|
- return resource;
|
|
|
+ return find(name)->resource;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@@ -169,13 +97,7 @@ bool ResourceManager::is_loaded(ResourceId name) const
|
|
|
{
|
|
|
CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
|
|
|
|
|
|
- m_resources_mutex.lock();
|
|
|
-
|
|
|
- bool loaded = m_resources[name.index].state == RS_LOADED;
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-
|
|
|
- return loaded;
|
|
|
+ return find(name)->state == RS_LOADED;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@@ -183,50 +105,15 @@ uint32_t ResourceManager::references(ResourceId name) const
|
|
|
{
|
|
|
CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
|
|
|
|
|
|
- m_resources_mutex.lock();
|
|
|
-
|
|
|
- bool loaded = m_resources[name.index].references;
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-
|
|
|
- return loaded;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-uint32_t ResourceManager::remaining() const
|
|
|
-{
|
|
|
- uint32_t count = 0;
|
|
|
-
|
|
|
- m_loading_mutex.lock();
|
|
|
-
|
|
|
- count = m_loading_queue.size();
|
|
|
-
|
|
|
- m_loading_mutex.unlock();
|
|
|
-
|
|
|
- return count;
|
|
|
+ return find(name)->references;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
void ResourceManager::flush()
|
|
|
{
|
|
|
- check_load_queue();
|
|
|
-
|
|
|
- while (true)
|
|
|
- {
|
|
|
- // Wait for all the resources to be loaded
|
|
|
- // by the background thread
|
|
|
- m_loading_mutex.lock();
|
|
|
- while (m_loading_queue.size() > 0)
|
|
|
- {
|
|
|
- m_all_loaded.wait(m_loading_mutex);
|
|
|
- }
|
|
|
- m_loading_mutex.unlock();
|
|
|
-
|
|
|
- // When all loaded, bring them online
|
|
|
- bring_loaded_online();
|
|
|
+ while (m_loader.remaining() > 0) ;
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
+ poll_resource_loader();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@@ -236,63 +123,61 @@ uint32_t ResourceManager::seed() const
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void ResourceManager::check_load_queue()
|
|
|
+ResourceId ResourceManager::resource_id(const char* type, const char* name) const
|
|
|
{
|
|
|
- m_loading_mutex.lock();
|
|
|
-
|
|
|
- if (m_loading_queue.size() > 0)
|
|
|
- {
|
|
|
- m_loading_requests.signal();
|
|
|
- }
|
|
|
+ ResourceId id;
|
|
|
+ id.type = hash::murmur2_32(type, string::strlen(type), 0);
|
|
|
+ id.name = hash::murmur2_32(name, string::strlen(name), m_seed);
|
|
|
|
|
|
- m_loading_mutex.unlock();
|
|
|
+ return id;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void ResourceManager::bring_loaded_online()
|
|
|
+ResourceEntry* ResourceManager::find(ResourceId id) const
|
|
|
{
|
|
|
- m_loaded_mutex.lock();
|
|
|
+ const ResourceEntry* entry = std::find(m_resources.begin(), m_resources.end(), id);
|
|
|
+
|
|
|
+ return entry != m_resources.end() ? const_cast<ResourceEntry*>(entry) : NULL;
|
|
|
+}
|
|
|
|
|
|
- while (m_loaded_queue.size() > 0)
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ResourceManager::poll_resource_loader()
|
|
|
+{
|
|
|
+ if (m_loader.num_loaded() != 0)
|
|
|
{
|
|
|
- LoadedResource lr = m_loaded_queue.front();
|
|
|
- m_loaded_queue.pop_front();
|
|
|
+ TempAllocator1024 alloc;
|
|
|
+ List<LoadedResource> loaded(alloc);
|
|
|
+ m_loader.get_loaded(loaded);
|
|
|
|
|
|
- online(lr.resource, lr.data);
|
|
|
+ for (uint32_t i = 0; i < loaded.size(); i++)
|
|
|
+ {
|
|
|
+ online(loaded[i].resource, loaded[i].data);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- m_loaded_mutex.unlock();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-ResourceId ResourceManager::load(uint32_t name, uint32_t type)
|
|
|
+ResourceId ResourceManager::load(ResourceId name)
|
|
|
{
|
|
|
- ResourceId id;
|
|
|
- id.name = name;
|
|
|
- id.type = type;
|
|
|
-
|
|
|
// Search for an already existent resource
|
|
|
- ResourceEntry* entry = std::find(m_resources.begin(), m_resources.end(), id);
|
|
|
+ ResourceEntry* entry = find(name);
|
|
|
|
|
|
// If resource not found, create a new one
|
|
|
- if (entry == m_resources.end())
|
|
|
+ if (entry == NULL)
|
|
|
{
|
|
|
- id.index = m_resources.size();
|
|
|
-
|
|
|
ResourceEntry entry;
|
|
|
|
|
|
- entry.id = id;
|
|
|
+ entry.id = name;
|
|
|
entry.state = RS_UNLOADED;
|
|
|
entry.references = 1;
|
|
|
entry.resource = NULL;
|
|
|
|
|
|
m_resources.push_back(entry);
|
|
|
|
|
|
- m_loading_mutex.lock();
|
|
|
- m_loading_queue.push_back(id);
|
|
|
- m_loading_mutex.unlock();
|
|
|
+ // Issue request to resource loader
|
|
|
+ m_loader.load(name);
|
|
|
|
|
|
- return id;
|
|
|
+ return name;
|
|
|
}
|
|
|
|
|
|
// Else, increment its reference count
|
|
|
@@ -301,103 +186,14 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
|
|
|
return entry->id;
|
|
|
}
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void ResourceManager::background_load()
|
|
|
-{
|
|
|
- while (m_background_thread_should_run)
|
|
|
- {
|
|
|
- m_loading_mutex.lock();
|
|
|
- while (m_loading_queue.size() == 0)
|
|
|
- {
|
|
|
- m_loading_requests.wait(m_loading_mutex);
|
|
|
- }
|
|
|
-
|
|
|
- ResourceId resource = m_loading_queue.front();
|
|
|
- m_loading_queue.pop_front();
|
|
|
-
|
|
|
- m_loading_mutex.unlock();
|
|
|
-
|
|
|
- void* data = load_by_type(resource);
|
|
|
-
|
|
|
- LoadedResource lr;
|
|
|
- lr.resource = resource;
|
|
|
- lr.data = data;
|
|
|
-
|
|
|
- m_loaded_mutex.lock();
|
|
|
- m_loaded_queue.push_back(lr);
|
|
|
- m_loaded_mutex.unlock();
|
|
|
-
|
|
|
- m_loading_mutex.lock();
|
|
|
- if (m_loading_queue.size() == 0)
|
|
|
- {
|
|
|
- m_all_loaded.signal();
|
|
|
- }
|
|
|
- m_loading_mutex.unlock();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void* ResourceManager::load_by_type(ResourceId name)
|
|
|
-{
|
|
|
- switch (name.type)
|
|
|
- {
|
|
|
- case TEXTURE_TYPE: return TextureResource::load(m_resource_allocator, m_resource_bundle, name);
|
|
|
- case MESH_TYPE: return MeshResource::load(m_resource_allocator, m_resource_bundle, name);
|
|
|
- case SOUND_TYPE: return SoundResource::load(m_resource_allocator, m_resource_bundle, name);
|
|
|
- default: return NULL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void ResourceManager::unload_by_type(ResourceId name, void* resource)
|
|
|
-{
|
|
|
- switch (name.type)
|
|
|
- {
|
|
|
- case TEXTURE_TYPE: return TextureResource::unload(m_resource_allocator, resource);
|
|
|
- case MESH_TYPE: return MeshResource::unload(m_resource_allocator, resource);
|
|
|
- case SOUND_TYPE: return SoundResource::unload(m_resource_allocator, resource);
|
|
|
- }
|
|
|
-
|
|
|
- return;
|
|
|
-}
|
|
|
-
|
|
|
//-----------------------------------------------------------------------------
|
|
|
void ResourceManager::online(ResourceId name, void* resource)
|
|
|
{
|
|
|
- switch (name.type)
|
|
|
- {
|
|
|
- case TEXTURE_TYPE:
|
|
|
- {
|
|
|
- TextureResource::online(resource);
|
|
|
- break;
|
|
|
- }
|
|
|
- case MESH_TYPE:
|
|
|
- {
|
|
|
- MeshResource::online(resource);
|
|
|
- break;
|
|
|
- }
|
|
|
- case SOUND_TYPE:
|
|
|
- {
|
|
|
- SoundResource::online(resource);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- m_resources_mutex.lock();
|
|
|
-
|
|
|
- ResourceEntry& entry = m_resources[name.index];
|
|
|
- entry.resource = resource;
|
|
|
- entry.state = RS_LOADED;
|
|
|
-
|
|
|
- m_resources_mutex.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void* ResourceManager::background_thread(void* thiz)
|
|
|
-{
|
|
|
- ((ResourceManager*)thiz)->background_load();
|
|
|
+ resource_on_online(name.type, resource);
|
|
|
|
|
|
- return NULL;
|
|
|
+ ResourceEntry* entry = find(name);
|
|
|
+ entry->resource = resource;
|
|
|
+ entry->state = RS_LOADED;
|
|
|
}
|
|
|
|
|
|
} // namespace crown
|