/*
* Copyright 2010 Inalogic® Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License, as
* published by the Free Software Foundation; either version 2.1 or 3.0
* of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the applicable version of the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of both the GNU Lesser General Public
* License along with this program. If not, see
*
* Authored by: Jay Taoko
*
*/
#ifndef GLRESOURCEMANAGER_H
#define GLRESOURCEMANAGER_H
namespace nux
{
// class BaseTexture;
// class Texture2D;
// class TextureRectangle;
// class TextureCube;
// class TextureVolume;
// class TextureFrameAnimation;
//
// class NVertexBuffer;
// class NIndexBuffer;
//
// class CachedTexture2D;
// class CachedTextureRectangle;
// class CachedTextureCube;
// class CachedTextureVolume;
// class CachedTextureFrameAnimation;
// ResourceData CachedResourceData
// | |
// BaseTexture CachedBaseTexture
// | |
// Texture2D CachedTexture2D
//
//
// NResourceFactory
// |
// NGLResourceFactory
// |
// TGLResourceFactory
//
//
// NResourceSet
// |
// TResourceCache
// |
// NResourceCache: TResourceCache
//
//
//! Base class for all types of resources.
class ResourceData: public Object
{
NUX_DECLARE_OBJECT_TYPE (ResourceData, Object);
public:
ResourceData (NUX_FILE_LINE_PROTO);
virtual ~ResourceData ();
int GetResourceIndex () const;
private:
int m_ResourceIndex;
};
class CachedResourceData;
class NResourceSet
{
public:
NResourceSet();
virtual ~NResourceSet() {};
protected:
CachedResourceData *FirstResource;
// Flush
virtual void Flush() {}
// FreeResource - Called when a potentially cached resource has been freed.
virtual void FreeResource (ResourceData *Resource) {}
// FlushResource - Removes a resource from the set.
virtual void FlushResource (CachedResourceData *Resource) {}
friend class CachedResourceData;
};
enum EResourceUpdateHint
{
RUH_Static, // The resource is updated once, at creation time.
RUH_CacheableDynamic, // The resource is updated occasionally, but not every frame.
RUH_Dynamic // The resource changes every frame.
};
class CachedResourceData: public Object
{
NUX_DECLARE_OBJECT_TYPE (CachedResourceData, Object);
public:
CachedResourceData (NResourceSet *InSet);
virtual ~CachedResourceData();
//! Returns the size in bytes of the resource.
/*! Returns the size in bytes of the resource.
@return Size of the resource in bytes.
*/
virtual unsigned int GetSize() const
{
return Size;
}
//! Returns the size of the max LOD of the resource.
/*!
Returns the size of the max LOD of the resource. For a texture, this is the size of mipmap 0.
Texture resource overwrite this function.
@return Size of the resource in bytes.
*/
virtual unsigned int GetMaxLodSize() const
{
return Size;
}
/*!
Updates the resource.
*/
virtual bool UpdateResource (ResourceData *Resource) = 0;
protected:
NResourceSet *Set;
bool _cached;
unsigned int NumRefs;
NObjectType *ResourceType;
unsigned int Size;
EResourceUpdateHint UpdateHint;
CachedResourceData *PrevResource;
CachedResourceData *NextResource;
template
friend class TResourceCache;
friend class NResourceCache;
};
//! Device independent resource factory.
class NResourceFactory
{
public:
NResourceFactory (NObjectType *Type)
: m_ResourceType (Type)
{}
// Returns the resource type for this factory
const NObjectType &Type() const
{
return *m_ResourceType;
}
/*!
Returns true if the given ResourceData is created by this factory.
@param Resource - the resource in question.
*/
bool BuildsThisResource (ResourceData *Resource)
{
return Resource->Type().IsObjectType (Type() );
}
virtual CachedResourceData *BuildResource (NResourceSet *ResourceManager, ResourceData *Resource)
{
return NULL;
}
private:
//! Type associated with this factory class.
NObjectType *m_ResourceType;
};
template
class TGLResourceFactory : public NResourceFactory
{
public:
/*!
Constructor.
@param type - resource class type to associate w/ this factory.
*/
TGLResourceFactory (NObjectType *Type)
: NResourceFactory (Type)
{}
virtual ~TGLResourceFactory (void)
{}
//! Create a new resource.
/*! Create a new resource for the given ResourceData.
@param ResourceManager The resource manager.
@param Resource Resource to build and cache.
@return The built resource.
*/
virtual CachedResourceData *BuildResource(NResourceSet *ResourceManager, ResourceData *Resource)
{
return new U(ResourceManager, (T *)Resource);
}
};
//! Device independent resource updater.
class NResourceUpdater
{
public:
NResourceUpdater (NObjectType *Type)
: m_ResourceType (Type)
{}
//! Returns the resource type for this factory.
const NObjectType &Type() const
{
return *m_ResourceType;
}
/*!
Returns true if the given ResourceData can be updated by this factory.
@param Resource The resource in question.
*/
bool UpdatesThisResource (ResourceData *Resource)
{
return Resource->Type().IsObjectType (Type() );
}
virtual bool UpdateResource (ObjectPtr< CachedResourceData > DeviceResource, ResourceData *Resource) const
{
return DeviceResource->UpdateResource (Resource);
}
private:
//! Type associated with this factory class.
NObjectType *m_ResourceType;
};
template
class TResourceCache: public NResourceSet
{
public:
std::map< IdType, ObjectPtr< ResourceType > > ResourceMap;
// Resource factory instances for each ResourceData/CachedResourceData pair.
std::vector ResourceFactories;
// Resource updater instances for each ResourceData type.
std::vector ResourceUpdaters;
TResourceCache()
: NResourceSet()
{}
void Flush()
{
// See the language FAQ 35.18 at http://www.parashift.com/c++-faq-lite/templates.html for why the "typename".
typename std::map< IdType, ObjectPtr< ResourceType > >::iterator It;
for (It = ResourceMap.begin(); It != ResourceMap.end(); It++)
{
// ObjectPtr< ResourceType > CachedResource = (*It).second;
// CachedResource->_cached = 0;
// CachedResource.Release();
(*It).second->_cached = 0;
(*It).second.Release();
}
// Erases all elements from the map.
ResourceMap.clear();
}
void AddCachedResource (const IdType &Id, ObjectPtr< ResourceType > Resource)
{
typedef std::map< IdType, ObjectPtr< ResourceType > > MapType;
ResourceMap.insert (typename MapType::value_type (Id, Resource) );
Resource->_cached = 1;
}
ObjectPtr FindCachedResourceById (const IdType &Id)
{
typedef std::map< IdType, ObjectPtr< ResourceType > > MapType;
typename MapType::iterator it = ResourceMap.find (Id);
if (it != ResourceMap.end() )
return (*it).second;
return ObjectPtr (0);
}
/*!
Remove a cached resource from the cache. The cached resource may still have references to it.
The resource internal flag "_cached" is set to false.
*/
void FlushResourceId(const IdType &Id)
{
ObjectPtr CachedResource(0);
typedef std::map > MapType;
typename MapType::iterator it = ResourceMap.find(Id);
if(it != ResourceMap.end())
CachedResource = (*it).second;
if(CachedResource.IsValid())
{
ResourceMap.erase(it);
CachedResource->_cached = false;
}
}
virtual void FlushResource (CachedResourceData *Resource)
{
typedef std::map< IdType, ObjectPtr< ResourceType > > MapType;
typename MapType::iterator it;
for (it = ResourceMap.begin(); it != ResourceMap.end(); it++)
{
ObjectPtr< ResourceType > CachedResource = (*it).second;
if (CachedResource == Resource)
{
ResourceMap.erase (it);
CachedResource->_cached = 0; // Make sure that if the following line deletes the resource, it doesn't try to remove itself from the TDynamicMap we're iterating over.
return;
}
}
}
// Register CachedResourceData with the corresponding ResourceData
virtual void InitializeResourceFactories() = 0;
std::vector& GetResourceFactories (void)
{
return (ResourceFactories);
}
std::vector& GetResourceUpdaters (void)
{
return (ResourceUpdaters);
}
};
class NResourceCache: public TResourceCache
{
public:
NResourceCache()
: TResourceCache()
{}
ObjectPtr< CachedResourceData > GetCachedResource (ResourceData *Source);
bool IsCachedResource (ResourceData *Source);
virtual void InitializeResourceFactories();
// virtual void FreeResource (ResourceData *Resource)
// {
// FlushResourceId(Resource->GetResourceIndex());
// }
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif // GLRESOURCEMANAGER_H