khanat-opennel-code/code/nel/include/nel/3d/async_texture_manager.h

250 lines
7.8 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_ASYNC_TEXTURE_MANAGER_H
#define NL_ASYNC_TEXTURE_MANAGER_H
#include "nel/misc/types_nl.h"
#include "nel/3d/texture_file.h"
#include "nel/3d/hls_texture_manager.h"
#include <vector>
#include "nel/misc/bitmap.h"
namespace NL3D
{
class CMeshBaseInstance;
// ***************************************************************************
/**
* Async Loader of textures and Texture Load Balancer.
* Additionaly, store in RAM for each texture load a very low, DXTC1 compressed version of the texture.
* Used for some Lod systems.
* \author Lionel Berenguier
* \author Nevrax France
* \date 2002
*/
class CAsyncTextureManager
{
public:
/// User is free to add bank to this manager. Other methods are used by the async manager
CHLSTextureManager HLSManager;
public:
/// Constructor
CAsyncTextureManager();
~CAsyncTextureManager();
/** setup the mipMap levels.
* \baseLevel When the texture is first added, it is loaded skipping the baseLevel
* first mipmap
* \maxLevel During time, further mipmap are loaded, according to instance position etc... maxLevel
* tells where to stop. If 0, the texture will finally be entirely uploaded.
* Default is 3,1.
*/
void setupLod(uint baseLevel, uint maxLevel);
/// Setup max texture upload in driver per update() call (in bytes). Default to 64K
void setupMaxUploadPerFrame(uint maxup);
/// Setup max texture HLS Coloring per update() call (in bytes). Default to 20K.
void setupMaxHLSColoringPerFrame(uint maxCol);
/// Setup max total texture size allowed. Default is 10Mo
void setupMaxTotalTextureSize(uint maxText);
/** Add a reference to a texture owned by an instance.
* If the texture still exists, only the refcount is incremented
* Else if texture is found in the HLSTextureManager, it is builded (async) from it, else Begin Async loading
*
* Therefore, only CTextureFile are possible. Also note that the texture is uploaded with mipmap by default, and
* UpLoadFormat is also default (say ITexture::Auto)
*
* If the texture file is not a DDS with mipmap, this is an error. But the system doesn't fail and
* the file is entirely loaded and uploaded. The problem is that upload is not cut according to maxUpLoadPerFrame, so
* some freeze may occur.
*/
uint addTextureRef(const std::string &textName, CMeshBaseInstance *instance, const NLMISC::CVector &position);
/// release a texture-instance tuple. The texture is released if no more instance use it.
void releaseTexture(uint id, CMeshBaseInstance *instance);
/// tells if a texture is loaded in the driver (ie. ready to use)
bool isTextureUpLoaded(uint id) const;
/** get the RAM LowDef version of a texture. Used For CLodCharacters
* return NULL if bad Id or if the texture is still not loaded.
* The bitmap returned has no mipmaps and should be in DXTC1 (not guaranteed).
*/
const NLMISC::CBitmap *getCoarseBitmap(uint id) const;
/** update the manager. New loaded textures are uploaded. Instances are updated to know if all their
* pending textures have been uploaded.
*/
void update(IDriver *pDriver);
/// get the async texture size asked (ie. maybe bigger than MaxTotalTextureSize).
uint getTotalTextureSizeAsked() const {return _TotalTextureSizeAsked;}
/// get what the system really allows
uint getLastTextureSizeGot() const {return _LastTextureSizeGot;}
// ***************************************************************************
private:
typedef std::map<std::string, uint> TTextureEntryMap;
typedef TTextureEntryMap::iterator ItTextureEntryMap;
// A base texture uploadable.
class CTextureBase
{
public:
// the texture currently loaded / uploaded.
NLMISC::CSmartPtr<CTextureFile> Texture;
bool isTextureEntry() const {return IsTextureEntry;}
protected:
bool IsTextureEntry;
};
class CTextureEntry;
// A Lod version of a texture entry.
class CTextureLod : public CTextureBase
{
public:
CTextureLod();
// A Ptr on the real texture used.
CTextureEntry *TextureEntry;
// Weight of the lod, according to distance and level.
float Weight;
// the level of this Lod. 0 means full original texture resolution.
uint8 Level;
// True if loading has ended
bool Loaded;
// True if TextureEntry has at least this lod in VRAM
bool UpLoaded;
// The size that this lod takes in VRAM (minus TextureEntry->BaseSize)
uint ExtraSize;
};
struct CTextureLodToSort
{
CTextureLod *Lod;
CVector Position;
bool operator<(const CTextureLodToSort &other) const
{
return Lod->Weight<other.Lod->Weight;
}
};
// A texture entry
class CTextureEntry : public CTextureBase
{
public:
// The it in the map.
ItTextureEntryMap ItMap;
// true if async loading has ended
bool Loaded;
// true if the texture is loaded in the driver (at least the coarsest level).
bool UpLoaded;
// true if first loading ended, and if DXTC with mipmap
bool CanHaveLOD;
// true if this texture must be built from the HLSManager (at first load)
bool BuildFromHLSManager;
// if BuildFromHLSManager, gives the text id in the manager
sint HLSManagerTextId;
// Base Size of the texture, without HDLod
uint BaseSize;
// list of instances currently using this texture.
std::vector<CMeshBaseInstance*> Instances;
// min distance of all Instances.
float MinDistance;
// min position.
NLMISC::CVector MinPosition;
// with all mipmaps loaded, what place this takes.
uint TotalTextureSizeAsked;
// The High Def Lod.
CTextureLod HDLod;
// The Coarse Bitmap stored in RAM for CLod
NLMISC::CBitmap CoarseBitmap;
public:
CTextureEntry();
void createCoarseBitmap();
};
private:
uint _BaseLodLevel, _MaxLodLevel;
uint _MaxUploadPerFrame;
uint _MaxHLSColoringPerFrame;
uint _MaxTotalTextureSize;
uint _TotalTextureSizeAsked;
uint _LastTextureSizeGot;
// Textures Entries.
std::vector<CTextureEntry*> _TextureEntries;
std::vector<uint> _FreeTextureIds;
TTextureEntryMap _TextureEntryMap;
std::vector<uint> _WaitingTextures;
// Upload of texture piece by piece.
CTextureBase *_CurrentUploadTexture;
uint _CurrentUploadTextureMipMap;
uint _CurrentUploadTextureLine;
// The current HDLod async loaded (NB: loaded / or upLoaded)
CTextureLod *_CurrentTextureLodLoaded;
// For texture profiling
NLMISC::CSmartPtr<ITexture::CTextureCategory> _TextureCategory;
private:
static bool validDXTCMipMap(ITexture *pText);
// delete the texture and all references in map/array, instance refcount etc...
void deleteTexture(uint id);
// Fill _CurrentUploadTexture with next texture to upload, or set NULL if none
void getNextTextureToUpLoad(uint &nTotalColored, IDriver *pDriver);
bool uploadTexturePart(ITexture *pText, IDriver *pDriver, uint &nTotalUpload);
// update list of texture lods.
void updateTextureLodSystem(IDriver *pDriver);
};
} // NL3D
#endif // NL_ASYNC_TEXTURE_MANAGER_H
/* End of async_texture_manager.h */