aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerimage.h
blob: e2f44e5f35d9fba85b117d547f25e1f7e33accec (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
/** 
 * @file llviewerimage.h
 * @brief Object for managing images and their textures
 *
 * Copyright (c) 2000-2007, Linden Research, Inc.
 * 
 * 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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.
 */

#ifndef LL_LLVIEWERIMAGE_H					
#define LL_LLVIEWERIMAGE_H

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

#include <map>
#include <list>

class LLViewerImage;

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

class LLViewerImage : public LLImageGL
{
// 	friend class LLViewerImageList;
	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 void receiveImage(LLMessageSystem *msg, void **user_data);
	static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
	static BOOL bindTexture(LLImageGL* image, const U32 stage = 0)
	{
		if (image)
		{
			return image->bind(stage);
		}
		else
		{
			return sDefaultImagep->bind(stage);
		}
	}

	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 LLUUID& id, 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 bind(const S32 stage = 0) const;
	
	void reinit(BOOL usemipmaps = TRUE);

	const LLUUID& getID() { return mID; }

	void setFormattedImage(LLImageFormatted* imagep);
	
	// Load an image from the static VFS
	BOOL loadLocalImage(const LLUUID& uuid);

	// Start loading of data from VFS, if any
	BOOL startVFSLoad();
	void startImageDecode();

	// Methods for loading and decoding data
	void setDecodeData(U8 *data, U32 size);
	void decodeImage(const F32 decode_time = 0.0);
	bool isDecoding();

	// Poll the VFS to see if the read is complete.  Returns TRUE if
	// the read is complete (and sets mStreamFile to NULL).
	BOOL loadStreamFile();

	// New methods for determining image quality/priority
	// texel_area_ratio is ("scaled" texel area)/(original texel area), approximately.
	void addTextureStats(F32 pixel_area,
						 F32 texel_area_ratio = 1.0f,
						 F32 cos_center_angle = 1.0f) const;
	void resetTextureStats(BOOL zero = FALSE);

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

	// Checks image data and decodes if ready. Returns true if packets were decoded or are pending
	BOOL checkPacketData();

	// 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,
						   void* userdata);

	BOOL createTexture(S32 usename = 0);
	BOOL destroyTexture();

	BOOL needsAux() const							{ return mNeedsAux; }
	void setNeedsAux(const BOOL needs_aux)			{ mNeedsAux = needs_aux; }
	BOOL needsDecode() const						{ return mNeedsDecode; }
	void setNeedsDecode(const BOOL needs_decode)	{ mNeedsDecode = needs_decode; }

	// 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_TERRAIN		= 1,	
		BOOST_AVATAR_BAKED	= 2,
		BOOST_AVATAR		= 3,
		BOOST_CLOUDS		= 4,
		
		BOOST_HIGH 			= 10,
		BOOST_SELECTED		= 11,
		BOOST_HUD			= 12,
		BOOST_AVATAR_BAKED_SELF	= 13,
		BOOST_UI			= 14,
		BOOST_PREVIEW		= 15,
		BOOST_MAP			= 16,
		BOOST_MAP_LAYER		= 17,
		BOOST_AVATAR_SELF	= 18, // needed for baking avatar
		BOOST_MAX_LEVEL
	};
	void setBoostLevel(S32 level);
	S32  getBoostLevel() { return mBoostLevel; }
	
	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);

	// 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 b)		{ mIsMissingAsset = b; }
	BOOL isMissingAsset()				{ return mIsMissingAsset; }

	BOOL getNeedsCreateTexture() const	{ return mNeedsCreateTexture; }
	
	bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; }
	
	void doLoadedCallbacks();
	S32 getLastPacket() { return mLastPacket; }
	F32 getDecodeProgress(F32 *data_progress_p = 0);

	void abortDecode();
	void destroyRawImage();	// Delete the raw image for this discard level
	
private:
	/*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it)

	void init(bool firstinit);
	void hoseStreamFile();
	void resetPacketData();

	// Used to be in LLImageGL
	LLImageRaw* createRawImage(S8 discard_level = 0, BOOL allocate = FALSE);
	
public:
	S32 mFullWidth;
	S32 mFullHeight;
	LLVFile *mStreamFile;

	// 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?
	mutable F32 mMaxCosAngle;		// The largest cos of the angle between camera X vector and the object

	F32 mTexelsPerImage;			// Texels per image.
	
	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)
	S8  mInStaticVFS;				// Source data in local VFS
	S8  mFormattedFlushed;

	S8  mRequested;					// An image request is currently in process.
	S8  mFullyLoaded;
	
	// Various info regarding image requests
	LLFrameTimer mRequestTime;
	S32 mRequestedDiscardLevel;
	F32 mRequestedDownloadPriority;
	
	// Timers
	LLFrameTimer mLastDecodeTime;		// Time since last decode.
	LLFrameTimer mLastPacketTimer;		// Time since last packet.
	LLFrameTimer mLastReferencedTimer;
	
private:
	LLUUID mID;
	LLPointer<LLImageFormatted> mFormattedImagep;

	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  mGotFirstPacket;
	S8  mNeedsCreateTexture;
	
	S8  mNeedsDecode;				// We have a compressed image that we want to decode, now.
	S8  mNeedsAux;					// We need to decode the auxiliary channels

	S8  mDecodingAux;				// Are we decoding high components
	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.
	
	// Codec of incoming packet data
	U8  mDataCodec;
	S8  mIsRawImageValid;

	typedef std::map<U16, LLViewerImagePacket *> vip_map_t;
	vip_map_t mReceivedPacketMap;
	S32 mLastPacketProcessed;
	U32 mLastBytesProcessed;		// Total bytes including the last packet rec'd

	// Data download/decode info
	U32 mPacketsReceived;
	U32 mTotalBytes;
	S32 mLastPacket;				// Last packet received without a gap.
	U16 mPackets;

	// VFS info
	U8 *mCachedData;
	S32 mCachedSize;
	
	// 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.
	S32  mBoostLevel;				// enum describing priority level
	
	typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
	callback_list_t mLoadedCallbackList;

	LLPointer<LLImageRaw> mRawImage;
	S32					mRawDiscardLevel;
	// 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;

	LLHost mTargetHost;	// if LLHost::invalid, just request from agent's simulator
	
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 LLTimer sEvaluationTimer;
	static F32 sDesiredDiscardBias;
	static F32 sDesiredDiscardScale;
	static S32 sBoundTextureMemory;
	static S32 sTotalTextureMemory;
	static S32 sMaxBoundTextureMem;
	static S32 sMaxTotalTextureMem;
	static BOOL sDontLoadVolumeTextures;
};

#endif