335 lines
11 KiB
C++
335 lines
11 KiB
C++
/**
|
|
* @file llvocache.h
|
|
* @brief Cache of objects on the viewer.
|
|
*
|
|
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library 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;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#ifndef LL_LLVOCACHE_H
|
|
#define LL_LLVOCACHE_H
|
|
|
|
#include "lluuid.h"
|
|
#include "lldatapacker.h"
|
|
#include "lldir.h"
|
|
#include "llvieweroctree.h"
|
|
#include "llapr.h"
|
|
#include "llgltfmaterial.h"
|
|
|
|
#include <unordered_map>
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Cache entries
|
|
class LLCamera;
|
|
|
|
class LLGLTFOverrideCacheEntry
|
|
{
|
|
public:
|
|
static const std::string VERSION_LABEL;
|
|
static const int VERSION;
|
|
bool fromLLSD(const LLSD& data);
|
|
LLSD toLLSD() const;
|
|
|
|
LLUUID mObjectId;
|
|
U32 mLocalId = 0;
|
|
std::unordered_map<S32, LLSD> mSides; //override LLSD per side
|
|
std::unordered_map<S32, LLPointer<LLGLTFMaterial> > mGLTFMaterial; //GLTF material per side
|
|
U64 mRegionHandle = 0;
|
|
};
|
|
|
|
class LLVOCacheEntry
|
|
: public LLViewerOctreeEntryData
|
|
{
|
|
LL_ALIGN_NEW
|
|
public:
|
|
enum
|
|
{
|
|
//low 16-bit state
|
|
INACTIVE = 0x00000000, //not visible
|
|
IN_QUEUE = 0x00000001, //in visible queue, object to be created
|
|
WAITING = 0x00000002, //object creation request sent
|
|
ACTIVE = 0x00000004, //object created, and in rendering pipeline.
|
|
|
|
//high 16-bit state
|
|
IN_VO_TREE = 0x00010000, //the entry is in the object cache tree.
|
|
|
|
LOW_BITS = 0x0000ffff,
|
|
HIGH_BITS = 0xffff0000
|
|
};
|
|
|
|
struct CompareVOCacheEntry
|
|
{
|
|
bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) const
|
|
{
|
|
F32 lpa = lhs->getSceneContribution();
|
|
F32 rpa = rhs->getSceneContribution();
|
|
|
|
//larger pixel area first
|
|
if(lpa > rpa)
|
|
{
|
|
return true;
|
|
}
|
|
else if(lpa < rpa)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return lhs < rhs;
|
|
}
|
|
}
|
|
};
|
|
// <FS:Beq> Unused, remove to reduce cognitive load
|
|
// struct ExtrasEntry
|
|
// {
|
|
// LLSD extras;
|
|
// std::string extras_raw;
|
|
// };
|
|
// </FS:Beq>
|
|
|
|
protected:
|
|
~LLVOCacheEntry();
|
|
public:
|
|
LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp);
|
|
LLVOCacheEntry(LLAPRFile* apr_file);
|
|
LLVOCacheEntry();
|
|
|
|
void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp);
|
|
|
|
void clearState(U32 state) {mState &= ~state;}
|
|
bool hasState(U32 state) {return mState & state;}
|
|
void setState(U32 state);
|
|
bool isState(U32 state) {return (mState & LOW_BITS) == state;}
|
|
U32 getState() const {return mState & LOW_BITS;}
|
|
|
|
bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold);
|
|
|
|
U32 getLocalID() const { return mLocalID; }
|
|
U32 getCRC() const { return mCRC; }
|
|
S32 getHitCount() const { return mHitCount; }
|
|
S32 getCRCChangeCount() const { return mCRCChangeCount; }
|
|
|
|
void calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 dist_threshold);
|
|
void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;}
|
|
F32 getSceneContribution() const { return mSceneContrib;}
|
|
|
|
void dump() const;
|
|
S32 writeToBuffer(U8 *data_buffer) const;
|
|
LLDataPackerBinaryBuffer *getDP();
|
|
void recordHit();
|
|
void recordDupe() { mDupeCount++; }
|
|
|
|
/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
|
|
|
|
void setParentID(U32 id);
|
|
U32 getParentID() const {return mParentID;}
|
|
bool isChild() const {return mParentID > 0;}
|
|
|
|
void addChild(LLVOCacheEntry* entry);
|
|
void removeChild(LLVOCacheEntry* entry);
|
|
void removeAllChildren();
|
|
LLVOCacheEntry* getChild(); //remove the first child, and return it.
|
|
S32 getNumOfChildren() const { return static_cast<S32>(mChildrenList.size()); }
|
|
|
|
void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message
|
|
void updateParentBoundingInfo();
|
|
void saveBoundingSphere();
|
|
|
|
void setValid(bool valid = true) {mValid = valid;}
|
|
bool isValid() const {return mValid;}
|
|
|
|
void setUpdateFlags(U32 flags) {mUpdateFlags = flags;}
|
|
U32 getUpdateFlags() const {return mUpdateFlags;}
|
|
|
|
static void updateDebugSettings();
|
|
static F32 getSquaredPixelThreshold(bool is_front);
|
|
|
|
private:
|
|
void updateParentBoundingInfo(const LLVOCacheEntry* child);
|
|
|
|
public:
|
|
typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t;
|
|
typedef std::set<LLVOCacheEntry*> vocache_entry_set_t;
|
|
typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;
|
|
|
|
typedef std::unordered_map<U32, LLGLTFOverrideCacheEntry> vocache_gltf_overrides_map_t;
|
|
|
|
S32 mLastCameraUpdated;
|
|
protected:
|
|
U32 mLocalID;
|
|
U32 mParentID;
|
|
U32 mCRC;
|
|
U32 mUpdateFlags; //receive from sim
|
|
S32 mHitCount;
|
|
S32 mDupeCount;
|
|
S32 mCRCChangeCount;
|
|
LLDataPackerBinaryBuffer mDP;
|
|
U8 *mBuffer;
|
|
|
|
F32 mSceneContrib; //projected scene contributuion of this object.
|
|
U32 mState; //high 16 bits reserved for special use.
|
|
vocache_entry_set_t mChildrenList; //children entries in a linked set.
|
|
|
|
bool mValid; //if set, this entry is valid, otherwise it is invalid and will be removed.
|
|
|
|
LLVector4a mBSphereCenter; //bounding sphere center
|
|
F32 mBSphereRadius; //bounding sphere radius
|
|
|
|
public:
|
|
static U32 sMinFrameRange;
|
|
static F32 sNearRadius;
|
|
static F32 sRearFarRadius;
|
|
static F32 sFrontPixelThreshold;
|
|
static F32 sRearPixelThreshold;
|
|
};
|
|
|
|
class LLVOCacheGroup : public LLOcclusionCullingGroup
|
|
{
|
|
public:
|
|
LLVOCacheGroup(OctreeNode* node, LLViewerOctreePartition* part) : LLOcclusionCullingGroup(node, part){}
|
|
|
|
//virtual
|
|
void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
|
|
|
|
protected:
|
|
virtual ~LLVOCacheGroup();
|
|
};
|
|
|
|
class LLVOCachePartition : public LLViewerOctreePartition
|
|
{
|
|
public:
|
|
LLVOCachePartition(LLViewerRegion* regionp);
|
|
virtual ~LLVOCachePartition();
|
|
|
|
bool addEntry(LLViewerOctreeEntry* entry);
|
|
void removeEntry(LLViewerOctreeEntry* entry);
|
|
/*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion);
|
|
void addOccluders(LLViewerOctreeGroup* gp);
|
|
void resetOccluders();
|
|
void processOccluders(LLCamera* camera);
|
|
void removeOccluder(LLVOCacheGroup* group);
|
|
|
|
void setCullHistory(bool has_new_object);
|
|
|
|
bool isFrontCull() const {return mFrontCull;}
|
|
|
|
private:
|
|
void selectBackObjects(LLCamera &camera, F32 projection_area_cutoff, bool use_occlusion); //select objects behind camera.
|
|
|
|
public:
|
|
static bool sNeedsOcclusionCheck;
|
|
|
|
private:
|
|
bool mFrontCull; //the view frustum cull if set, otherwise is back sphere cull.
|
|
U32 mCullHistory;
|
|
U32 mCulledTime[LLViewerCamera::NUM_CAMERAS];
|
|
std::set<LLVOCacheGroup*> mOccludedGroups;
|
|
|
|
S32 mBackSlectionEnabled; //enable to select back objects if > 0.
|
|
U32 mIdleHash;
|
|
};
|
|
|
|
//
|
|
//Note: LLVOCache is not thread-safe
|
|
//
|
|
class LLVOCache : public LLParamSingleton<LLVOCache>
|
|
{
|
|
LLSINGLETON(LLVOCache, bool read_only);
|
|
~LLVOCache() ;
|
|
|
|
private:
|
|
struct HeaderEntryInfo
|
|
{
|
|
HeaderEntryInfo() : mIndex(0), mHandle(0), mTime(0) {}
|
|
S32 mIndex;
|
|
U64 mHandle ;
|
|
U32 mTime ;
|
|
};
|
|
|
|
struct HeaderMetaInfo
|
|
{
|
|
HeaderMetaInfo() : mVersion(0), mAddressSize(0) {}
|
|
|
|
U32 mVersion;
|
|
U32 mAddressSize;
|
|
};
|
|
|
|
struct header_entry_less
|
|
{
|
|
bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const
|
|
{
|
|
if(lhs->mTime == rhs->mTime)
|
|
{
|
|
return lhs < rhs ;
|
|
}
|
|
|
|
return lhs->mTime < rhs->mTime ; // older entry in front of queue (set)
|
|
}
|
|
};
|
|
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
|
|
typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t;
|
|
|
|
public:
|
|
// We need this init to be separate from constructor, since we might construct cache, purge it, then init.
|
|
void initCache(ELLPath location, U32 size, U32 cache_version);
|
|
void removeCache(ELLPath location, bool started = false) ;
|
|
|
|
bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
|
|
void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map);
|
|
|
|
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, bool dirty_cache, bool removal_enabled);
|
|
void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, bool dirty_cache, bool removal_enabled);
|
|
void removeEntry(U64 handle) ;
|
|
void removeGenericExtrasForHandle(U64 handle);
|
|
|
|
U32 getCacheEntries() { return mNumEntries; }
|
|
U32 getCacheEntriesMax() { return mCacheSize; }
|
|
|
|
private:
|
|
void setDirNames(ELLPath location);
|
|
// determine the cache filename for the region from the region handle
|
|
void getObjectCacheFilename(U64 handle, std::string& filename);
|
|
std::string getObjectCacheExtrasFilename(U64 handle);
|
|
void removeFromCache(HeaderEntryInfo* entry);
|
|
void readCacheHeader();
|
|
void writeCacheHeader();
|
|
void clearCacheInMemory();
|
|
void removeCache() ;
|
|
void removeEntry(HeaderEntryInfo* entry) ;
|
|
void purgeEntries(U32 size);
|
|
bool updateEntry(const HeaderEntryInfo* entry);
|
|
|
|
private:
|
|
bool mEnabled;
|
|
bool mInitialized ;
|
|
bool mReadOnly ;
|
|
HeaderMetaInfo mMetaInfo;
|
|
U32 mCacheSize;
|
|
U32 mNumEntries;
|
|
std::string mHeaderFileName ;
|
|
std::string mObjectCacheDirName;
|
|
LLVolatileAPRPool* mLocalAPRFilePoolp ;
|
|
header_entry_queue_t mHeaderEntryQueue;
|
|
handle_entry_map_t mHandleEntryMap;
|
|
};
|
|
|
|
#endif
|