summaryrefslogtreecommitdiff
path: root/indra/newview/llvocache.h
blob: bbcc230a82ba17369011b09f52b2cec120b3cd13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/** 
 * @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;
			}			
		}
	};

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 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