summaryrefslogtreecommitdiff
path: root/indra/newview/llviewertexture.h
blob: dc9182bf1be9ef5225f91c65b6a890e74fafdf57 (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
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
/**
 * @file llviewertexture.h
 * @brief Object for managing images and their textures
 *
 * $LicenseInfo:firstyear=2000&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_LLVIEWERTEXTURE_H
#define LL_LLVIEWERTEXTURE_H

#include "llatomic.h"
#include "llgltexture.h"
#include "lltimer.h"
#include "llframetimer.h"
#include "llhost.h"
#include "llgltypes.h"
#include "llrender.h"
#include "llmetricperformancetester.h"
#include "httpcommon.h"
#include "workqueue.h"

#include <map>
#include <list>

extern const S32Megabytes gMinVideoRam;
extern const S32Megabytes gMaxVideoRam;

class LLFace;
class LLImageGL ;
class LLImageRaw;
class LLViewerObject;
class LLViewerTexture;
class LLViewerFetchedTexture ;
class LLViewerMediaTexture ;
class LLTexturePipelineTester ;


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

class LLFileSystem;
class LLMessageSystem;
class LLViewerMediaImpl ;
class LLVOVolume ;
struct LLTextureKey;

class LLLoadedCallbackEntry
{
public:
    typedef std::set< LLTextureKey > source_callback_list_t;

public:
    LLLoadedCallbackEntry(loaded_callback_func cb,
                          S32 discard_level,
                          bool need_imageraw, // Needs image raw for the callback
                          void* userdata,
                          source_callback_list_t* src_callback_list,
                          LLViewerFetchedTexture* target,
                          bool pause);
    ~LLLoadedCallbackEntry();
    void removeTexture(LLViewerFetchedTexture* tex) ;

    loaded_callback_func    mCallback;
    S32                     mLastUsedDiscard;
    S32                     mDesiredDiscard;
    bool                    mNeedsImageRaw;
    bool                    mPaused;
    void*                   mUserData;
    source_callback_list_t* mSourceCallbackList;

public:
    static void cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) ;
};

class LLTextureBar;

class LLViewerTexture : public LLGLTexture
{
public:
    enum
    {
        LOCAL_TEXTURE,
        MEDIA_TEXTURE,
        DYNAMIC_TEXTURE,
        FETCHED_TEXTURE,
        LOD_TEXTURE,
        ATLAS_TEXTURE,
        INVALID_TEXTURE_TYPE
    };

    typedef std::vector<class LLFace*> ll_face_list_t;
    typedef std::vector<LLVOVolume*> ll_volume_list_t;


protected:
    virtual ~LLViewerTexture();
    LOG_CLASS(LLViewerTexture);

public:
    static void initClass();
    static void updateClass();

    LLViewerTexture(bool usemipmaps = true);
    LLViewerTexture(const LLUUID& id, bool usemipmaps) ;
    LLViewerTexture(const LLImageRaw* raw, bool usemipmaps) ;
    LLViewerTexture(const U32 width, const U32 height, const U8 components, bool usemipmaps) ;

    virtual S8 getType() const;
    virtual bool isMissingAsset() const ;
    virtual void dump();    // debug info to LL_INFOS()

    virtual bool isViewerMediaTexture() const { return false; }

    /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
    /*virtual*/ bool bindDebugImage(const S32 stage = 0) ;
    /*virtual*/ void forceImmediateUpdate() ;
    /*virtual*/ bool isActiveFetching();

    /*virtual*/ const LLUUID& getID() const { return mID; }
    virtual void setBoostLevel(S32 level);
    S32  getBoostLevel() { return mBoostLevel; }
    void setTextureListType(S32 tex_type) { mTextureListType = tex_type; }
    S32 getTextureListType() { return mTextureListType; }

    void addTextureStats(F32 virtual_size, bool needs_gltexture = true) const;
    void resetTextureStats();
    void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;}
    void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;}
    S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; }

    virtual F32  getMaxVirtualSize() ;

    LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}

    S32 getFullWidth() const { return mFullWidth; }
    S32 getFullHeight() const { return mFullHeight; }
    /*virtual*/ void setKnownDrawSize(S32 width, S32 height);

    virtual void addFace(U32 channel, LLFace* facep) ;
    virtual void removeFace(U32 channel, LLFace* facep) ;
    S32 getTotalNumFaces() const;
    S32 getNumFaces(U32 ch) const;
    const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];}

    virtual void addVolume(U32 channel, LLVOVolume* volumep);
    virtual void removeVolume(U32 channel, LLVOVolume* volumep);
    S32 getNumVolumes(U32 channel) const;
    const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; }


    virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
    bool isLargeImage() ;

    void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
    bool hasParcelMedia() const { return mParcelMedia != NULL;}
    LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}

    /*virtual*/ void updateBindStatsForTester() ;
protected:
    void cleanup() ;
    void init(bool firstinit) ;
    void reorganizeFaceList() ;
    void reorganizeVolumeList();

private:
    friend class LLBumpImageList;
    friend class LLUIImageList;

    virtual void switchToCachedImage();

protected:
    friend class LLViewerTextureList;
    LLUUID mID;
    S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList

    mutable F32 mMaxVirtualSize = 0.f;  // The largest virtual size of the image, in pixels - how much data to we need?
    mutable S32  mMaxVirtualSizeResetCounter;
    mutable S32  mMaxVirtualSizeResetInterval;
    LLFrameTimer mLastReferencedTimer;

    ll_face_list_t    mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture
    U32               mNumFaces[LLRender::NUM_TEXTURE_CHANNELS];
    LLFrameTimer      mLastFaceListUpdateTimer ;

    ll_volume_list_t  mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
    U32                 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
    LLFrameTimer      mLastVolumeListUpdateTimer;

    //do not use LLPointer here.
    LLViewerMediaTexture* mParcelMedia ;

    LL::WorkQueue::weak_t mMainQueue;
    LL::WorkQueue::weak_t mImageQueue;

public:
    static const U32 sCurrentFileVersion;
    static S32 sImageCount;
    static S32 sRawCount;
    static S32 sAuxCount;
    static LLFrameTimer sEvaluationTimer;
    static F32 sDesiredDiscardBias;
    static F32 sDesiredDiscardScale;
    static S32 sMaxSculptRez ;
    static U32 sMinLargeImageSize ;
    static U32 sMaxSmallImageSize ;
    static bool sFreezeImageUpdates;
    static F32  sCurrentTime ;

    // estimated free memory for textures, by bias calculation
    static F32 sFreeVRAMMegabytes;

    enum EDebugTexels
    {
        DEBUG_TEXELS_OFF,
        DEBUG_TEXELS_CURRENT,
        DEBUG_TEXELS_DESIRED,
        DEBUG_TEXELS_FULL
    };

    static EDebugTexels sDebugTexelsMode;

    static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
    static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black)
    static LLPointer<LLViewerTexture> sCheckerBoardImagep;  // Texture to show NOTHING (pure black)
};


enum FTType
{
    FTT_UNKNOWN = -1,
    FTT_DEFAULT = 0, // standard texture fetched by id.
    FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there.
    FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host.
    FTT_MAP_TILE, // tiles are fetched from map server directly.
    FTT_LOCAL_FILE // fetch directly from a local file.
};

const std::string& fttype_to_string(const FTType& fttype);

//
//textures are managed in gTextureList.
//raw image data is fetched from remote or local cache
//but the raw image this texture pointing to is fixed.
//
class LLViewerFetchedTexture : public LLViewerTexture
{
    friend class LLTextureBar; // debug info only
    friend class LLTextureView; // debug info only

protected:
    /*virtual*/ ~LLViewerFetchedTexture();
public:
    LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), bool usemipmaps = true);
    LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, bool usemipmaps);
    LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, bool usemipmaps = true);

public:

    struct Compare
    {
        // lhs < rhs
        bool operator()(const LLPointer<LLViewerFetchedTexture> &lhs, const LLPointer<LLViewerFetchedTexture> &rhs) const
        {
            const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs;
            const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs;

            // greater priority is "less"
            const F32 lpriority = lhsp->mMaxVirtualSize;
            const F32 rpriority = rhsp->mMaxVirtualSize;
            if (lpriority > rpriority) // higher priority
                return true;
            if (lpriority < rpriority)
                return false;
            return lhsp < rhsp;
        }
    };

public:
    /*virtual*/ S8 getType() const override;
    FTType getFTType() const;
    /*virtual*/ void forceImmediateUpdate() override;
    /*virtual*/ void dump() override;

    // 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, LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, bool pause = false);
    bool hasCallbacks() { return !mLoadedCallbackList.empty(); }
    void pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
    void unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
    bool doLoadedCallbacks();
    void deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
    void clearCallbackEntryList() ;

    void addToCreateTexture();

    //call to determine if createTexture is necessary
    bool preCreateTexture(S32 usename = 0);
     // ONLY call from LLViewerTextureList or ImageGL background thread
    bool createTexture(S32 usename = 0);
    void postCreateTexture();
    void scheduleCreateTexture();

    void destroyTexture() ;

    virtual void processTextureStats() ;

    bool needsAux() const { return mNeedsAux; }

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

    void updateVirtualSize() ;

    S32  getDesiredDiscardLevel()            { return mDesiredDiscardLevel; }
    void setMinDiscardLevel(S32 discard)    { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }

    void setBoostLevel(S32 level) override;
    bool updateFetch();
    bool setDebugFetching(S32 debug_level);
    bool isInDebug() const { return mInDebug; }

    void setUnremovable(bool value) { mUnremovable = value; }
    bool isUnremovable() const { return mUnremovable; }

    void clearFetchedResults(); //clear all fetched results, for debug use.

    // 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.
    /*virtual*/ void setKnownDrawSize(S32 width, S32 height) override;

    // Set the debug text of all Viewer Objects associated with this texture
    // to the specified text
    void setDebugText(const std::string& text);

    void setIsMissingAsset(bool is_missing = true);
    /*virtual*/ bool isMissingAsset() const override { return mIsMissingAsset; }

    // 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 isInImageList() const {return mInImageList ;}
    void setInImageList(bool flag) {mInImageList = flag ;}

    LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;}

    U32 getFetchPriority() const { return mFetchPriority ;}
    F32 getDownloadProgress() const {return mDownloadProgress ;}

    LLImageRaw* reloadRawImage(S8 discard_level) ;
    void destroyRawImage();
    bool needsToSaveRawImage();

    const std::string& getUrl() const {return mUrl;}
    //---------------
    bool isDeleted() ;
    bool isInactive() ;
    bool isDeletionCandidate();
    void setDeletionCandidate() ;
    void setInactive() ;
    bool getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
    //---------------

    void setForSculpt();
    bool forSculpt() const {return mForSculpt;}
    bool isForSculptOnly() const;

    //raw image management
    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, F32 kept_time = 0.f) ;
    /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;
    void        destroySavedRawImage() ;
    LLImageRaw* getSavedRawImage() ;
    bool        hasSavedRawImage() const ;
    F32         getElapsedLastReferencedSavedRawImageTime() const ;
    bool        isFullyLoaded() const;

    bool        hasFetcher() const { return mHasFetcher;}
    bool        isFetching() const { return mIsFetching;}
    void        setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}

    void        forceToDeleteRequest();
    void        loadFromFastCache();
    void        setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }
    bool        isInFastCacheList() { return mInFastCacheList; }

    /*virtual*/bool  isActiveFetching() override; //is actively in fetching by the fetching pipeline.

protected:
    /*virtual*/ void switchToCachedImage() override;
    S32 getCurrentDiscardLevelForFetching() ;
    void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);

private:
    void init(bool firstinit) ;
    void cleanup() ;

    void saveRawImage() ;
    void setCachedRawImage() ;

    //for atlas
    void resetFaceAtlas() ;
    void invalidateAtlas(bool rebuild_geom) ;
    bool insertToAtlas() ;

private:
    bool  mFullyLoaded;
    bool  mInDebug;
    bool  mUnremovable;
    bool  mInFastCacheList;
    bool  mForceCallbackFetch;

protected:
    S32 mOrigWidth;
    S32 mOrigHeight;

    // 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;
    bool mKnownDrawSizeChanged ;
    std::string mUrl;

    S32 mRequestedDiscardLevel;
    F32 mRequestedDownloadPriority;
    S32 mFetchState;
    S32 mLastFetchState = -1; // DEBUG
    U32 mFetchPriority;
    F32 mDownloadProgress;
    F32 mFetchDeltaTime;
    F32 mRequestDeltaTime;
    S32 mMinDiscardLevel;
    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

    bool mNeedsAux;                 // We need to decode the auxiliary channels
    bool mHasAux;                    // We have aux channels
    bool mDecodingAux;              // Are we decoding high components
    bool mIsRawImageValid;
    bool mHasFetcher;               // We've made a fecth request
    bool mIsFetching;               // Fetch request is active
    bool mCanUseHTTP;              //This texture can be fetched through http if true.
    LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture.

    FTType mFTType; // What category of image is this - map tile, server bake, etc?
    mutable bool mIsMissingAsset;       // True if we know that there is no image asset with this image id in the database.

    typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
    S8              mLoadedCallbackDesiredDiscardLevel;
    bool            mPauseLoadedCallBacks;
    callback_list_t mLoadedCallbackList;
    F32             mLastCallBackActiveTime;

    LLPointer<LLImageRaw> mRawImage;
    S32 mRawDiscardLevel = -1;

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

    //keep a copy of mRawImage for some special purposes
    //when mForceToSaveRawImage is set.
    bool mForceToSaveRawImage ;
    bool mSaveRawImage;
    LLPointer<LLImageRaw> mSavedRawImage;
    S32 mSavedRawDiscardLevel;
    S32 mDesiredSavedRawDiscardLevel;
    F32 mLastReferencedSavedRawImageTime ;
    F32 mKeptSavedRawImageTime ;

    //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 invalid, just request from agent's simulator

    // Timers
    LLFrameTimer mLastPacketTimer;      // Time since last packet.
    LLFrameTimer mStopFetchingTimer;    // Time since mDecodePriority == 0.f.

    bool  mInImageList;             // true if image is in list (in which case don't reset priority!)
    // This needs to be atomic, since it is written both in the main thread
    // and in the GL image worker thread... HB
    LLAtomicBool  mNeedsCreateTexture;

    bool   mForSculpt ; //a flag if the texture is used as sculpt data.
    bool   mIsFetched ; //is loaded from remote or from cache, not generated locally.

public:
    static F32 sMaxVirtualSize; //maximum possible value of mMaxVirtualSize
    static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep;   // Texture to show for an image asset that is not in the database
    static LLPointer<LLViewerFetchedTexture> sWhiteImagep;  // Texture to show NOTHING (whiteness)
    static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
    static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
    static LLPointer<LLViewerFetchedTexture> sDefaultIrradiancePBRp; // PBR: irradiance

    // not sure why, but something is iffy about the loading of this particular texture, use the accessor instead of accessing directly
    static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
    static LLViewerFetchedTexture* getSmokeImage();
};

//
//the image data is fetched from remote or from local cache
//the resolution of the texture is adjustable: depends on the view-dependent parameters.
//
class LLViewerLODTexture : public LLViewerFetchedTexture
{
protected:
    /*virtual*/ ~LLViewerLODTexture(){}

public:
    LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), bool usemipmaps = true);
    LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, bool usemipmaps = true);

    /*virtual*/ S8 getType() const;
    // Process image stats to determine priority/quality requirements.
    /*virtual*/ void processTextureStats();
    bool isUpdateFrozen() ;

private:
    void init(bool firstinit) ;
    bool scaleDown() ;

private:
    F32 mDiscardVirtualSize;        // Virtual size used to calculate desired discard
    F32 mCalculatedDiscardLevel;    // Last calculated discard level
};

//
//the image data is fetched from the media pipeline periodically
//the resolution of the texture is also adjusted by the media pipeline
//
class LLViewerMediaTexture : public LLViewerTexture
{
protected:
    /*virtual*/ ~LLViewerMediaTexture() ;

public:
    LLViewerMediaTexture(const LLUUID& id, bool usemipmaps = true, LLImageGL* gl_image = NULL) ;

    /*virtual*/ S8 getType() const;
    void reinit(bool usemipmaps = true);

    bool  getUseMipMaps() {return mUseMipMaps ; }
    void  setUseMipMaps(bool mipmap) ;

    void setPlaying(bool playing) ;
    bool isPlaying() const {return mIsPlaying;}
    void setMediaImpl() ;

    virtual bool isViewerMediaTexture() const { return true; }

    void initVirtualSize() ;
    void invalidateMediaImpl() ;

    void addMediaToFace(LLFace* facep) ;
    void removeMediaFromFace(LLFace* facep) ;

    /*virtual*/ void addFace(U32 ch, LLFace* facep) ;
    /*virtual*/ void removeFace(U32 ch, LLFace* facep) ;

    /*virtual*/ F32  getMaxVirtualSize() ;
private:
    void switchTexture(U32 ch, LLFace* facep) ;
    bool findFaces() ;
    void stopPlaying() ;

private:
    //
    //an instant list, recording all faces referencing or can reference to this media texture.
    //NOTE: it is NOT thread safe.
    //
    std::list< LLFace* > mMediaFaceList ;

    //an instant list keeping all textures which are replaced by the current media texture,
    //is only used to avoid the removal of those textures from memory.
    std::list< LLPointer<LLViewerTexture> > mTextureList ;

    LLViewerMediaImpl* mMediaImplp ;
    bool mIsPlaying ;
    U32  mUpdateVirtualSizeTime ;

public:
    static void updateClass() ;
    static void cleanUpClass() ;

    static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ;
    static void removeMediaImplFromTexture(const LLUUID& media_id) ;

private:
    typedef std::map< LLUUID, LLPointer<LLViewerMediaTexture> > media_map_t ;
    static media_map_t sMediaMap ;
};

//just an interface class, do not create instance from this class.
class LLViewerTextureManager
{
private:
    //make the constructor private to preclude creating instances from this class.
    LLViewerTextureManager(){}

public:
    //texture pipeline tester
    static LLTexturePipelineTester* sTesterp ;

    //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
    static LLViewerFetchedTexture*    staticCastToFetchedTexture(LLTexture* tex, bool report_error = false) ;

    //
    //"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
    //
    static void                       findFetchedTextures(const LLUUID& id, std::vector<LLViewerFetchedTexture*> &output);
    static void                       findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output);
    static LLViewerFetchedTexture*    findFetchedTexture(const LLUUID& id, S32 tex_type);
    static LLViewerMediaTexture*      findMediaTexture(const LLUUID& id) ;

    static LLViewerMediaTexture*      createMediaTexture(const LLUUID& id, bool usemipmaps = true, LLImageGL* gl_image = NULL) ;

    //
    //"get-texture" will create a new texture if the texture does not exist.
    //
    static LLViewerMediaTexture*      getMediaTexture(const LLUUID& id, bool usemipmaps = true, LLImageGL* gl_image = NULL) ;

    static LLPointer<LLViewerTexture> getLocalTexture(bool usemipmaps = true, bool generate_gl_tex = true);
    static LLPointer<LLViewerTexture> getLocalTexture(const LLUUID& id, bool usemipmaps, bool generate_gl_tex = true) ;
    static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, bool usemipmaps) ;
    static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, bool usemipmaps, bool generate_gl_tex = true) ;

    static LLViewerFetchedTexture* getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps);

    static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
                                     FTType f_type = FTT_DEFAULT,
                                     bool usemipmap = true,
                                     LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE,     // Get the requested level immediately upon creation.
                                     S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
                                     LLGLint internal_format = 0,
                                     LLGLenum primary_format = 0,
                                     LLHost request_from_host = LLHost()
                                     );

    static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename,
                                     FTType f_type = FTT_LOCAL_FILE,
                                     bool usemipmap = true,
                                     LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE,
                                     S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
                                     LLGLint internal_format = 0,
                                     LLGLenum primary_format = 0,
                                     const LLUUID& force_id = LLUUID::null
                                     );

    static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url,
                                     FTType f_type,
                                     bool usemipmap = true,
                                     LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE,
                                     S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
                                     LLGLint internal_format = 0,
                                     LLGLenum primary_format = 0,
                                     const LLUUID& force_id = LLUUID::null
                                     );

    static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ;

    // decode a given image data according to given mime type
    // WARNING: caller is responsible for deleting the returned raw image
    static LLImageRaw* getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype);

    // decode given image data according to given mime type
    // WARNING: caller is responsible for deleting the returned image
    static LLViewerFetchedTexture* getFetchedTextureFromMemory(const U8* data, U32 size, std::string_view mimetype);

    static void init() ;
    static void cleanup() ;
};
//
//this class is used for test/debug only
//it tracks the activities of the texture pipeline
//records them, and outputs them to log files
//
class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession
{
    enum
    {
        MIN_LARGE_IMAGE_AREA = 262144  //512 * 512
    };
public:
    LLTexturePipelineTester() ;
    ~LLTexturePipelineTester() ;

    void update();
    void updateTextureBindingStats(const LLViewerTexture* imagep) ;
    void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, bool from_cache) ;
    void updateGrayTextureBinding() ;
    void setStablizingTime() ;

private:
    void reset() ;
    void updateStablizingTime() ;

    /*virtual*/ void outputTestRecord(LLSD* sd) ;

private:
    bool mPause ;
private:
    bool mUsingDefaultTexture;            //if set, some textures are still gray.

    U32Bytes mTotalBytesUsed ;                     //total bytes of textures bound/used for the current frame.
    U32Bytes mTotalBytesUsedForLargeImage ;        //total bytes of textures bound/used for the current frame for images larger than 256 * 256.
    U32Bytes mLastTotalBytesUsed ;                 //total bytes of textures bound/used for the previous frame.
    U32Bytes mLastTotalBytesUsedForLargeImage ;    //total bytes of textures bound/used for the previous frame for images larger than 256 * 256.

    //
    //data size
    //
    U32Bytes mTotalBytesLoaded ;               //total bytes fetched by texture pipeline
    U32Bytes mTotalBytesLoadedFromCache ;      //total bytes fetched by texture pipeline from local cache
    U32Bytes mTotalBytesLoadedForLargeImage ;  //total bytes fetched by texture pipeline for images larger than 256 * 256.
    U32Bytes mTotalBytesLoadedForSculpties ;   //total bytes fetched by texture pipeline for sculpties

    //
    //time
    //NOTE: the error tolerances of the following timers is one frame time.
    //
    F32 mStartFetchingTime ;
    F32 mTotalGrayTime ;                  //total loading time when no gray textures.
    F32 mTotalStablizingTime ;            //total stablizing time when texture memory overflows
    F32 mStartTimeLoadingSculpties ;      //the start moment of loading sculpty images.
    F32 mEndTimeLoadingSculpties ;        //the end moment of loading sculpty images.
    F32 mStartStablizingTime ;
    F32 mEndStablizingTime ;

private:
    //
    //The following members are used for performance analyzing
    //
    class LLTextureTestSession : public LLTestSession
    {
    public:
        LLTextureTestSession() ;
        /*virtual*/ ~LLTextureTestSession() ;

        void reset() ;

        F32 mTotalGrayTime ;
        F32 mTotalStablizingTime ;
        F32 mStartTimeLoadingSculpties ;
        F32 mTotalTimeLoadingSculpties ;

        S32 mTotalBytesLoaded ;
        S32 mTotalBytesLoadedFromCache ;
        S32 mTotalBytesLoadedForLargeImage ;
        S32 mTotalBytesLoadedForSculpties ;

        typedef struct _texture_instant_preformance_t
        {
            S32 mAverageBytesUsedPerSecond ;
            S32 mAverageBytesUsedForLargeImagePerSecond ;
            F32 mAveragePercentageBytesUsedPerSecond ;
            F32 mTime ;
        }texture_instant_preformance_t ;
        std::vector<texture_instant_preformance_t> mInstantPerformanceList ;
        S32 mInstantPerformanceListCounter ;
    };

    /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ;
    /*virtual*/ void compareTestSessions(llofstream* os) ;
};

#endif