aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerimage.h
blob: 7d646be362099f56d01e943d105e29fb0fa31a01 (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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/** 
 * @file llviewerimage.h
 * @brief Object for managing images and their textures
 *
 * $LicenseInfo:firstyear=2000&license=viewergpl$
 * 
 * Copyright (c) 2000-2009, Linden Research, Inc.
 * 
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 * 
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 * 
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 * 
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#ifndef LL_LLVIEWERIMAGE_H					
#define LL_LLVIEWERIMAGE_H

#include "llimagegl.h"
#include "lltimer.h"
#include "llframetimer.h"
#include "llhost.h"

#include <map>
#include <list>


#define MIN_VIDEO_RAM_IN_MEGA_BYTES    32
#define MAX_VIDEO_RAM_IN_MEGA_BYTES    512 // 512MB max for performance reasons.

class LLViewerImage;
class LLTextureAtlas ;
class LLFace ;

typedef	void	(*loaded_callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );

class LLVFile;
class LLMessageSystem;
 
class LLLoadedCallbackEntry
{
public:
	LLLoadedCallbackEntry(loaded_callback_func cb,
						  S32 discard_level,
						  BOOL need_imageraw, // Needs image raw for the callback
						  void* userdata ) 
		: mCallback(cb),
		  mLastUsedDiscard(MAX_DISCARD_LEVEL+1),
		  mDesiredDiscard(discard_level),
		  mNeedsImageRaw(need_imageraw),
		  mUserData(userdata)
	{
	}

	loaded_callback_func	mCallback;
	S32						mLastUsedDiscard;
	S32						mDesiredDiscard;
	BOOL					mNeedsImageRaw;
	void*					mUserData;
};

class LLTextureBar;

//=====================================
struct LLViewerImageBoostLevel
{
	enum
	{
		BOOST_NONE 			= 0,
		BOOST_AVATAR_BAKED	= 1,
		BOOST_AVATAR		= 2,
		BOOST_CLOUDS		= 3,
		BOOST_SCULPTED      = 4,
		
		BOOST_HIGH 			= 5,
		BOOST_TERRAIN		, // has to be high priority for minimap / low detail
		BOOST_SELECTED		,
		BOOST_HUD			,
		BOOST_AVATAR_BAKED_SELF	,
		BOOST_UI			,
		BOOST_PREVIEW		,
		BOOST_MAP			,
		BOOST_MAP_VISIBLE	,
		BOOST_AVATAR_SELF	,// needed for baking avatar
		BOOST_MAX_LEVEL,

		//LLImageGLCategory
		TEXLAYER_BUMP = BOOST_MAX_LEVEL,
		AVATAR_SCRATCH_TEX,
		FONT,
		BUMP_IMAGE,
		DYNAMIC_TEX,
		TEXLAYER_CACHE,
		MEDIA,
		ATLAS,
		OTHER,
		MAX_GL_IMAGE_CATEGORY
	};
};
//=====================================
class LLViewerImage : public LLImageGL
{
        LOG_CLASS(LLViewerImage);

	friend class LLTextureBar; // debug info only
	friend class LLTextureView; // debug info only
	
public:
	static void initClass();
	static void cleanupClass();
	static void updateClass(const F32 velocity, const F32 angular_velocity);

	static LLViewerImage * getImage(const LLUUID &image_id);
		// lightweight wrapper for gImageList.getImage()


	struct Compare
	{
		// lhs < rhs
		bool operator()(const LLPointer<LLViewerImage> &lhs, const LLPointer<LLViewerImage> &rhs) const
		{
			const LLViewerImage* lhsp = (const LLViewerImage*)lhs;
			const LLViewerImage* rhsp = (const LLViewerImage*)rhs;
			// greater priority is "less"
			const F32 lpriority = lhsp->getDecodePriority();
			const F32 rpriority = rhsp->getDecodePriority();
			if (lpriority > rpriority) // higher priority
				return true;
			if (lpriority < rpriority)
				return false;
			return lhsp < rhsp;
		}
	};

	struct CompareByHostAndPriority
	{
		// lhs < rhs
		bool operator()(const LLPointer<LLViewerImage> &lhs, const LLPointer<LLViewerImage> &rhs) const
		{
			const LLViewerImage* lhsp = (const LLViewerImage*)lhs;
			const LLViewerImage* rhsp = (const LLViewerImage*)rhs;
			if (lhsp->mTargetHost != rhsp->mTargetHost)
				return lhsp->mTargetHost < rhsp->mTargetHost;

			const F32 lpriority = lhsp->getDecodePriority();
			const F32 rpriority = rhsp->getDecodePriority();
			if (lpriority != rpriority)
				return lpriority > rpriority; // greater priority is "less"

			return lhsp < rhsp;
		}
	};

	struct CompareForRemoval
	{
		// lhs < rhs
		bool operator()(const LLPointer<LLViewerImage> &lhs, const LLPointer<LLViewerImage> &rhs) const
		{
			const LLViewerImage* lhsp = (const LLViewerImage*)lhs;
			const LLViewerImage* rhsp = (const LLViewerImage*)rhs;
			// compare bind time
			if (lhsp->mLastBindTime < rhsp->mLastBindTime) // older
				return true;
			if (lhsp->mLastBindTime > rhsp->mLastBindTime)
				return false;
			if (lhsp->getDiscardLevel() < rhsp->getDiscardLevel()) // larger
				return true;
			if (lhsp->getDiscardLevel() > rhsp->getDiscardLevel())
				return false;
			return lhsp < rhsp;
		}
	};

	struct CompareForWorstVisibility 
	{
		// lhs < rhs
		bool operator()(const LLPointer<LLViewerImage> &lhs, const LLPointer<LLViewerImage> &rhs) const
		{
			const LLViewerImage* lhsp = (const LLViewerImage*)lhs;
			const LLViewerImage* rhsp = (const LLViewerImage*)rhs;
			F32 lhsvis = ((lhsp->getWidth() * lhsp->getHeight()) / lhsp->mMaxVirtualSize);
			F32 rhsvis = ((rhsp->getWidth() * rhsp->getHeight()) / rhsp->mMaxVirtualSize);
			if (lhsvis > rhsvis) // fewer relative visible pixels
				return true;
			if (rhsvis < lhsvis)
				return false;
			return lhsp < rhsp;
		}
	};
	
	enum
	{
		MAX_IMAGE_SIZE_DEFAULT = 1024,
		INVALID_DISCARD_LEVEL = 0x7fff
	};

protected:
	/*virtual*/ ~LLViewerImage();
	
public:
	LLViewerImage(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE);
	LLViewerImage(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
	LLViewerImage(const U32 width, const U32 height, const U8 components, BOOL usemipmaps);
	LLViewerImage(const LLImageRaw* raw, BOOL usemipmaps);

	/*virtual*/ void dump();	// debug info to llinfos

	/*virtual*/ bool bindError(const S32 stage = 0) const;
	/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
	/*virtual*/ void forceImmediateUpdate() ;
	
	void reinit(BOOL usemipmaps = TRUE);

	const LLUUID& getID() const { return mID; }

	// New methods for determining image quality/priority
	// texel_area_ratio is ("scaled" texel area)/(original texel area), approximately.
	void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
	void resetTextureStats();
	void setAdditionalDecodePriority(F32 priority) ;
	F32  maxAdditionalDecodePriority() ;

	BOOL isLargeImage() ;
	BOOL isUpdateFrozen() ;

	// Process image stats to determine priority/quality requirements.
	void processTextureStats();

	// Set callbacks to get called when the image gets updated with higher 
	// resolution versions.
	void setLoadedCallback(loaded_callback_func cb,
						   S32 discard_level, BOOL keep_imageraw, BOOL needs_aux,
						   void* userdata);

	 // ONLY call from LLViewerImageList
	BOOL createTexture(S32 usename = 0);
	void destroyTexture() ;
	void addToCreateTexture();

	BOOL needsAux() const							{ return mNeedsAux; }

	// setDesiredDiscardLevel is only used by LLViewerImageList
	void setDesiredDiscardLevel(S32 discard) { mDesiredDiscardLevel = discard; }
	S32  getDesiredDiscardLevel()			 { return mDesiredDiscardLevel; }

	void setMinDiscardLevel(S32 discard) 	{ mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
	
	// Host we think might have this image, used for baked av textures.
	void setTargetHost(LLHost host)			{ mTargetHost = host; }
	LLHost getTargetHost() const			{ return mTargetHost; }

	enum
	{
		BOOST_NONE 			= 0,
		BOOST_AVATAR_BAKED	= 1,
		BOOST_AVATAR		= 2,
		BOOST_CLOUDS		= 3,
		BOOST_SCULPTED      = 4,
		
		BOOST_HIGH 			= 10,
		BOOST_TERRAIN		= 11, // has to be high priority for minimap / low detail
		BOOST_SELECTED		= 12,
		BOOST_HUD			= 13,
		BOOST_AVATAR_BAKED_SELF	= 14,
		BOOST_UI			= 15,
		BOOST_PREVIEW		= 16,
		BOOST_MAP			= 17,
		BOOST_MAP_LAYER		= 18,
		BOOST_AVATAR_SELF	= 19, // needed for baking avatar
		BOOST_MAX_LEVEL
	};
	void setBoostLevel(S32 level);
	S32  getBoostLevel() { return mBoostLevel; }
	
	void updateVirtualSize() ;
	F32 getDecodePriority() const { return mDecodePriority; };
	F32 calcDecodePriority();
	static F32 maxDecodePriority();
	
	// Set the decode priority for this image...
	// DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up
	// the priority list, and cause horrible things to happen.
	void setDecodePriority(F32 priority = -1.0f);

	bool updateFetch();
	BOOL hasFetcher() const { return mHasFetcher;}
	// Override the computation of discard levels if we know the exact output
	// size of the image.  Used for UI textures to not decode, even if we have
	// more data.
	void setKnownDrawSize(S32 width, S32 height);

	void setIsMissingAsset();
	BOOL isMissingAsset()	const		{ return mIsMissingAsset; }

	bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; }
	
	bool doLoadedCallbacks();

	// returns dimensions of original image for local files (before power of two scaling)
	// and returns 0 for all asset system images
	S32 getOriginalWidth() { return mOrigWidth; }
	S32 getOriginalHeight() { return mOrigHeight; }

	BOOL        insertToAtlas() ;
	void        resetFaceAtlas() ;
	void		invalidateAtlas(BOOL rebuild_geom = FALSE);

	BOOL isForSculptOnly() const ;
	void setForSculpt();
	
	void        checkCachedRawSculptImage() ;
	LLImageRaw* getRawImage()const { return mRawImage ;}
	S32         getRawImageLevel() const {return mRawDiscardLevel;}
	LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
	S32         getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
	BOOL        isCachedRawImageReady() const {return mCachedRawImageReady ;}
	BOOL        isRawImageValid()const { return mIsRawImageValid ; }
	
	void        forceToSaveRawImage(S32 desired_discard = 0) ;
	void        destroySavedRawImage() ;

	BOOL        isSameTexture(const LLViewerImage* tex) const ;

	void        addFace(LLFace* facep) ;
	void        removeFace(LLFace* facep) ;
	BOOL        isReferenced()const {return mFaceList.size() > 0 ; }

	friend class LocalBitmap; // tag: vaa emerald local_asset_browser

private:
	/*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it)

	void init(bool firstinit);

	// Used to be in LLImageGL
	LLImageRaw* readBackRawImage(S8 discard_level = 0);
	void destroyRawImage();
	void saveRawImage() ;
	BOOL forceFetch() ;

	void scaleDown() ;	
	void switchToCachedImage();
	void setCachedRawImage() ;
public:
	S32 mFullWidth;
	S32 mFullHeight;

	S32 mOrigWidth;
	S32 mOrigHeight;
	std::string mUrl;

	// Data used for calculating required image priority/quality level/decimation
	mutable F32 mMaxVirtualSize;	// The largest virtual size of the image, in pixels - how much data to we need?

	F32 mTexelsPerImage;			// Texels per image.
	F32 mDiscardVirtualSize;		// Virtual size used to calculate desired discard
	
	S8  mInImageList;				// TRUE if image is in list (in which case don't reset priority!)
	S8  mIsMediaTexture;			// TRUE if image is being replaced by media (in which case don't update)

	// Various info regarding image requests
	S32 mRequestedDiscardLevel;
	F32 mRequestedDownloadPriority;
	S32 mFetchState;
	U32 mFetchPriority;
	F32 mDownloadProgress;
	F32 mFetchDeltaTime;
	F32 mRequestDeltaTime;
	S32 mDecodeFrame;
	S32 mVisibleFrame; // decode frame where image was last visible
	
	// Timers
	LLFrameTimer mLastPacketTimer;		// Time since last packet.
	LLFrameTimer mLastReferencedTimer;

private:
	LLUUID mID;

	S8  mDesiredDiscardLevel;			// The discard level we'd LIKE to have - if we have it and there's space
	S8  mMinDesiredDiscardLevel;		// The minimum discard level we'd like to have
	S8  mNeedsCreateTexture;	
	mutable S8  mNeedsGLTexture;
	S8  mNeedsAux;					// We need to decode the auxiliary channels
	S8  mDecodingAux;				// Are we decoding high components
	S8  mIsRawImageValid;
	S8  mHasFetcher;				// We've made a fecth request
	S8  mIsFetching;				// Fetch request is active
	S8  mFullyLoaded;
	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.	

	// Override the computation of discard levels if we know the exact output size of the image.
	// Used for UI textures to not decode, even if we have more data.
	S32 mKnownDrawWidth;
	S32	mKnownDrawHeight;

	F32 mDecodePriority;			// The priority for decoding this image.
	mutable F32 mAdditionalDecodePriority;  // priority add to mDecodePriority.
	S32 mBoostLevel;				// enum describing priority level
	
	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
	callback_list_t mLoadedCallbackList;

	LLPointer<LLImageRaw> mRawImage;
	S32 mRawDiscardLevel;
	S32	mMinDiscardLevel;
	F32 mCalculatedDiscardLevel; // Last calculated discard level
	
	//keep a copy of mRawImage for some special purposes
	//when mForceToSaveRawImage is set.
	BOOL mForceToSaveRawImage ;
	LLPointer<LLImageRaw> mSavedRawImage;
	S32 mSavedRawDiscardLevel;
	S32 mDesiredSavedRawDiscardLevel;

	// Used ONLY for cloth meshes right now.  Make SURE you know what you're 
	// doing if you use it for anything else! - djs
	LLPointer<LLImageRaw> mAuxRawImage;

	//a small version of the copy of the raw image (<= 64 * 64)
	LLPointer<LLImageRaw> mCachedRawImage;
	S32 mCachedRawDiscardLevel;
	BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
	
	LLHost mTargetHost;	// if LLHost::invalid, just request from agent's simulator
	
	BOOL   mForSculpt ; //a flag if the texture is used for a sculpt data.
	mutable BOOL    mNeedsResetMaxVirtualSize ;

	typedef std::list<LLFace*> ll_face_list_t ;
	ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture

	BOOL mInCreationList ;
public:
	static const U32 sCurrentFileVersion;
	// Default textures
	static LLPointer<LLViewerImage> sMissingAssetImagep;	// Texture to show for an image asset that is not in the database
	static LLPointer<LLViewerImage> sWhiteImagep;	// Texture to show NOTHING (whiteness)
	static LLPointer<LLImageGL> sDefaultImagep; // "Default" texture for error cases
	static LLPointer<LLViewerImage> sSmokeImagep; // Old "Default" translucent texture
	static LLPointer<LLImageGL> sNullImagep; // Null texture for non-textured objects.

	static S32 sImageCount;
	static S32 sRawCount;
	static S32 sAuxCount;
	static LLTimer sEvaluationTimer;
	static S8  sCameraMovingDiscardBias;
	static F32 sDesiredDiscardBias;
	static F32 sDesiredDiscardScale;
	static S32 sBoundTextureMemoryInBytes;
	static S32 sTotalTextureMemoryInBytes;
	static S32 sMaxBoundTextureMemInMegaBytes;
	static S32 sMaxTotalTextureMemInMegaBytes;
	static S32 sMaxDesiredTextureMemInBytes ;
	static BOOL sDontLoadVolumeTextures;

	static S32 sMaxSculptRez ;
	static S32 sMinLargeImageSize ;
	static S32 sMaxSmallImageSize ;
	static BOOL sFreezeImageScalingDown ;//do not scale down image res if set.
	static S32 sLLViewerImageCount ;
};

#endif