aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerimage.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llviewerimage.cpp700
1 files changed, 579 insertions, 121 deletions
diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp
index 272fcb5..3a14bf0 100644
--- a/linden/indra/newview/llviewerimage.cpp
+++ b/linden/indra/newview/llviewerimage.cpp
@@ -59,6 +59,8 @@
59#include "llviewercontrol.h" 59#include "llviewercontrol.h"
60#include "pipeline.h" 60#include "pipeline.h"
61#include "llappviewer.h" 61#include "llappviewer.h"
62#include "llface.h"
63#include "llviewercamera.h"
62/////////////////////////////////////////////////////////////////////////////// 64///////////////////////////////////////////////////////////////////////////////
63 65
64// statics 66// statics
@@ -72,6 +74,7 @@ S32 LLViewerImage::sImageCount = 0;
72S32 LLViewerImage::sRawCount = 0; 74S32 LLViewerImage::sRawCount = 0;
73S32 LLViewerImage::sAuxCount = 0; 75S32 LLViewerImage::sAuxCount = 0;
74LLTimer LLViewerImage::sEvaluationTimer; 76LLTimer LLViewerImage::sEvaluationTimer;
77S8 LLViewerImage::sCameraMovingDiscardBias = 0 ;
75F32 LLViewerImage::sDesiredDiscardBias = 0.f; 78F32 LLViewerImage::sDesiredDiscardBias = 0.f;
76static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by 79static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by
77static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by 80static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by
@@ -83,16 +86,26 @@ S32 LLViewerImage::sMaxTotalTextureMemInMegaBytes = 0;
83S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ; 86S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ;
84BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE; 87BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE;
85 88
89S32 LLViewerImage::sMaxSculptRez = 128 ; //max sculpt image size
90const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
91const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerImage::sMaxSculptRez * LLViewerImage::sMaxSculptRez ;
92const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ;
93S32 LLViewerImage::sMinLargeImageSize = 65536 ; //256 * 256.
94S32 LLViewerImage::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
95BOOL LLViewerImage::sFreezeImageScalingDown = FALSE ;
96//debug use
97S32 LLViewerImage::sLLViewerImageCount = 0 ;
98
86// static 99// static
87void LLViewerImage::initClass() 100void LLViewerImage::initClass()
88{ 101{
89 sNullImagep = new LLImageGL(1,1,3,TRUE); 102 sNullImagep = new LLImageGL(1,1,3,TRUE);
90 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); 103 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
91 raw->clear(0x77, 0x77, 0x77, 0xFF); 104 raw->clear(0x77, 0x77, 0x77, 0xFF);
92 sNullImagep->createGLTexture(0, raw); 105 sNullImagep->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER);
93 106
94#if 1 107#if 1
95 LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT, TRUE); 108 LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT);
96 sDefaultImagep = imagep; 109 sDefaultImagep = imagep;
97 const S32 dim = 128; 110 const S32 dim = 128;
98 LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); 111 LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
@@ -118,7 +131,7 @@ void LLViewerImage::initClass()
118 } 131 }
119 } 132 }
120 } 133 }
121 imagep->createGLTexture(0, image_raw); 134 imagep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER);
122 image_raw = NULL; 135 image_raw = NULL;
123 gImageList.addImage(imagep); 136 gImageList.addImage(imagep);
124 imagep->dontDiscard(); 137 imagep->dontDiscard();
@@ -128,17 +141,48 @@ void LLViewerImage::initClass()
128 sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); 141 sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE);
129 sSmokeImagep->setNoDelete() ; 142 sSmokeImagep->setNoDelete() ;
130 143
144 if(gAuditTexture)
145 {
146 sDefaultTexturep = new LLImageGL() ;
147 image_raw = new LLImageRaw(dim,dim,3);
148 data = image_raw->getData();
149 for (S32 i = 0; i<dim; i++)
150 {
151 for (S32 j = 0; j<dim; j++)
152 {
153 const S32 border = 2;
154 if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
155 {
156 *data++ = 0xff;
157 *data++ = 0xff;
158 *data++ = 0xff;
159 }
160 else
161 {
162 *data++ = 0xff;
163 *data++ = 0xff;
164 *data++ = 0x00;
165 }
166 }
167 }
168 sDefaultTexturep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER);
169 image_raw = NULL;
170 sDefaultTexturep->dontDiscard();
171 }
131} 172}
132 173
133// static 174// static
134void LLViewerImage::cleanupClass() 175void LLViewerImage::cleanupClass()
135{ 176{
136 stop_glerror(); 177 stop_glerror();
178 LLImageGL::cleanupClass() ;
179
137 sNullImagep = NULL; 180 sNullImagep = NULL;
138 sDefaultImagep = NULL; 181 sDefaultImagep = NULL;
139 sSmokeImagep = NULL; 182 sSmokeImagep = NULL;
140 sMissingAssetImagep = NULL; 183 sMissingAssetImagep = NULL;
141 sWhiteImagep = NULL; 184 sWhiteImagep = NULL;
185 sDefaultTexturep = NULL ;
142} 186}
143 187
144// tuning params 188// tuning params
@@ -186,6 +230,13 @@ void LLViewerImage::updateClass(const F32 velocity, const F32 angular_velocity)
186 } 230 }
187 } 231 }
188 sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); 232 sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax);
233
234 F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
235 F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
236 sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
237
238 LLViewerImage::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
239 (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
189} 240}
190 241
191// static 242// static
@@ -198,18 +249,19 @@ LLViewerImage* LLViewerImage::getImage(const LLUUID& image_id)
198 249
199const U32 LLViewerImage::sCurrentFileVersion = 1; 250const U32 LLViewerImage::sCurrentFileVersion = 1;
200 251
201LLViewerImage::LLViewerImage(const LLUUID& id, BOOL usemipmaps) 252LLViewerImage::LLViewerImage(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
202 : LLImageGL(usemipmaps), 253 : LLImageGL(usemipmaps),
203 mID(id) 254 mID(id),
255 mTargetHost(host)
204{ 256{
205 init(true); 257 init(true);
206 sImageCount++; 258 sImageCount++;
207} 259}
208 260
209LLViewerImage::LLViewerImage(const std::string& filename, const LLUUID& id, BOOL usemipmaps) 261LLViewerImage::LLViewerImage(const std::string& url, const LLUUID& id, BOOL usemipmaps)
210 : LLImageGL(usemipmaps), 262 : LLImageGL(usemipmaps),
211 mID(id), 263 mID(id),
212 mLocalFileName(filename) 264 mUrl(url)
213{ 265{
214 init(true); 266 init(true);
215 sImageCount++; 267 sImageCount++;
@@ -265,7 +317,7 @@ void LLViewerImage::init(bool firstinit)
265 } 317 }
266 mIsMediaTexture = FALSE; 318 mIsMediaTexture = FALSE;
267 319
268 mBoostLevel = LLViewerImage::BOOST_NONE; 320 mBoostLevel = LLViewerImageBoostLevel::BOOST_NONE;
269 321
270 // Only set mIsMissingAsset true when we know for certain that the database 322 // Only set mIsMissingAsset true when we know for certain that the database
271 // does not contain this image. 323 // does not contain this image.
@@ -277,8 +329,6 @@ void LLViewerImage::init(bool firstinit)
277 mRawDiscardLevel = INVALID_DISCARD_LEVEL; 329 mRawDiscardLevel = INVALID_DISCARD_LEVEL;
278 mMinDiscardLevel = 0; 330 mMinDiscardLevel = 0;
279 331
280 mTargetHost = LLHost::invalid;
281
282 mHasFetcher = FALSE; 332 mHasFetcher = FALSE;
283 mIsFetching = FALSE; 333 mIsFetching = FALSE;
284 mFetchState = 0; 334 mFetchState = 0;
@@ -287,6 +337,15 @@ void LLViewerImage::init(bool firstinit)
287 mFetchDeltaTime = 999999.f; 337 mFetchDeltaTime = 999999.f;
288 mDecodeFrame = 0; 338 mDecodeFrame = 0;
289 mVisibleFrame = 0; 339 mVisibleFrame = 0;
340 mForSculpt = FALSE ;
341 mCachedRawImage = NULL ;
342 mCachedRawDiscardLevel = -1 ;
343 mCachedRawImageReady = FALSE ;
344 mNeedsResetMaxVirtualSize = FALSE ;
345
346 mForceToSaveRawImage = FALSE ;
347 mSavedRawDiscardLevel = -1 ;
348 mDesiredSavedRawDiscardLevel = -1 ;
290} 349}
291 350
292// virtual 351// virtual
@@ -322,6 +381,7 @@ LLViewerImage::~LLViewerImage()
322 381
323void LLViewerImage::cleanup() 382void LLViewerImage::cleanup()
324{ 383{
384 mFaceList.clear() ;
325 for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); 385 for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
326 iter != mLoadedCallbackList.end(); ) 386 iter != mLoadedCallbackList.end(); )
327 { 387 {
@@ -336,7 +396,9 @@ void LLViewerImage::cleanup()
336 396
337 // Clean up image data 397 // Clean up image data
338 destroyRawImage(); 398 destroyRawImage();
339 399 mCachedRawImage = NULL ;
400 mCachedRawDiscardLevel = -1 ;
401 mCachedRawImageReady = FALSE ;
340 // LLImageGL::cleanup will get called more than once when this is used in the destructor. 402 // LLImageGL::cleanup will get called more than once when this is used in the destructor.
341 LLImageGL::cleanup(); 403 LLImageGL::cleanup();
342} 404}
@@ -365,6 +427,63 @@ void LLViewerImage::destroyTexture()
365 destroyGLTexture() ; 427 destroyGLTexture() ;
366} 428}
367 429
430void LLViewerImage::addToCreateTexture()
431{
432 if(isForSculptOnly())
433 {
434 //just update some variables, not to create a real GL texture.
435 createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ;
436 mNeedsCreateTexture = FALSE ;
437 destroyRawImage();
438 }
439 else
440 {
441#if 1
442 //
443 //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up,
444 //so do not scale down the over qualified image.
445 //Note: scaling down image is expensensive. Do it only when very necessary.
446 //
447 if(mRequestedDiscardLevel <= mDesiredDiscardLevel)
448 {
449 S32 w = mFullWidth >> mRawDiscardLevel;
450 S32 h = mFullHeight >> mRawDiscardLevel;
451
452 //if big image, do not load extra data
453 //scale it down to size >= LLViewerImage::sMinLargeImageSize
454 if(w * h > LLViewerImage::sMinLargeImageSize)
455 {
456 S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ;
457
458 if(d_level > 0)
459 {
460 S32 i = 0 ;
461 while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerImage::sMinLargeImageSize))
462 {
463 i++;
464 d_level--;
465 }
466 if(i > 0)
467 {
468 mRawDiscardLevel += i ;
469 if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0)
470 {
471 mNeedsCreateTexture = FALSE ;
472 destroyRawImage();
473 return ;
474 }
475 mRawImage->scale(w >> i, h >> i) ;
476 }
477 }
478 }
479 }
480#endif
481 mNeedsCreateTexture = TRUE;
482 gImageList.mCreateTextureList.insert(this);
483 }
484 return ;
485}
486
368// ONLY called from LLViewerImageList 487// ONLY called from LLViewerImageList
369BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) 488BOOL LLViewerImage::createTexture(S32 usename/*= 0*/)
370{ 489{
@@ -386,7 +505,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/)
386 if (!gNoRender) 505 if (!gNoRender)
387 { 506 {
388 // store original size only for locally-sourced images 507 // store original size only for locally-sourced images
389 if (!mLocalFileName.empty()) 508 if (mUrl.compare(0, 7, "file://") == 0)
390 { 509 {
391 mOrigWidth = mRawImage->getWidth(); 510 mOrigWidth = mRawImage->getWidth();
392 mOrigHeight = mRawImage->getHeight(); 511 mOrigHeight = mRawImage->getHeight();
@@ -457,29 +576,54 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/)
457 576
458//============================================================================ 577//============================================================================
459 578
460void LLViewerImage::addTextureStats(F32 virtual_size) const // = 1.0 579void LLViewerImage::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const
461{ 580{
462 if (virtual_size > mMaxVirtualSize) 581 if(needs_gltexture)
463 { 582 {
464 mMaxVirtualSize = virtual_size; 583 mNeedsGLTexture = TRUE ;
465 } 584 }
466}
467 585
468void LLViewerImage::resetTextureStats(BOOL zero) 586 if(mNeedsResetMaxVirtualSize)
469{
470 if (zero)
471 { 587 {
472 mMaxVirtualSize = 0.0f; 588 //flag to reset the values because the old values are used.
589 mNeedsResetMaxVirtualSize = FALSE ;
590 mMaxVirtualSize = virtual_size;
591 mAdditionalDecodePriority = 0.f ;
592 mNeedsGLTexture = needs_gltexture ;
473 } 593 }
474 else 594 else if (virtual_size > mMaxVirtualSize)
475 { 595 {
476 mMaxVirtualSize -= mMaxVirtualSize * .10f; // decay by 5%/update 596 mMaxVirtualSize = virtual_size;
477 } 597 }
598}
599
600void LLViewerImage::resetTextureStats()
601{
602 mMaxVirtualSize = 0.0f;
603 mAdditionalDecodePriority = 0.f ;
604 mNeedsResetMaxVirtualSize = FALSE ;
605}
606
607BOOL LLViewerImage::isUpdateFrozen()
608{
609 return LLViewerImage::sFreezeImageScalingDown && !getDiscardLevel() ;
610}
611
612BOOL LLViewerImage::isLargeImage()
613{
614 return mTexelsPerImage > LLViewerImage::sMinLargeImageSize ;
478} 615}
479 616
480// This is gauranteed to get called periodically for every texture 617// This is gauranteed to get called periodically for every texture
481void LLViewerImage::processTextureStats() 618void LLViewerImage::processTextureStats()
482{ 619{
620 //no need to update if the texture reaches its highest res and the memory is sufficient.
621 //if(isUpdateFrozen())
622 //{
623 // return ;
624 //}
625
626 updateVirtualSize() ;
483 // Generate the request priority and render priority 627 // Generate the request priority and render priority
484 if (mDontDiscard || !getUseMipMaps()) 628 if (mDontDiscard || !getUseMipMaps())
485 { 629 {
@@ -487,7 +631,7 @@ void LLViewerImage::processTextureStats()
487 if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) 631 if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
488 mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 632 mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
489 } 633 }
490 else if (mBoostLevel < LLViewerImage::BOOST_HIGH && mMaxVirtualSize <= 10.f) 634 else if (mBoostLevel < LLViewerImageBoostLevel::BOOST_HIGH && mMaxVirtualSize <= 10.f)
491 { 635 {
492 // If the image has not been significantly visible in a while, we don't want it 636 // If the image has not been significantly visible in a while, we don't want it
493 mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); 637 mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1));
@@ -504,15 +648,14 @@ void LLViewerImage::processTextureStats()
504 S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); 648 S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
505 S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); 649 S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
506 mTexelsPerImage = (F32)fullwidth * fullheight; 650 mTexelsPerImage = (F32)fullwidth * fullheight;
507
508 F32 discard_level = 0.f; 651 F32 discard_level = 0.f;
509 652
510 // If we know the output width and height, we can force the discard 653 // If we know the output width and height, we can force the discard
511 // level to the correct value, and thus not decode more texture 654 // level to the correct value, and thus not decode more texture
512 // data than we need to. 655 // data than we need to.
513 if (mBoostLevel == LLViewerImage::BOOST_UI || 656 if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI ||
514 mBoostLevel == LLViewerImage::BOOST_PREVIEW || 657 mBoostLevel == LLViewerImageBoostLevel::BOOST_PREVIEW ||
515 mBoostLevel == LLViewerImage::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? 658 mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF?
516 { 659 {
517 discard_level = 0; // full res 660 discard_level = 0; // full res
518 } 661 }
@@ -527,6 +670,12 @@ void LLViewerImage::processTextureStats()
527 } 670 }
528 else 671 else
529 { 672 {
673 if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f)
674 {
675 //if is a big image and not being used recently, nor close to the view point, do not load hi-res data.
676 mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerImage::sMinLargeImageSize) ;
677 }
678
530 if ((mCalculatedDiscardLevel >= 0.f) && 679 if ((mCalculatedDiscardLevel >= 0.f) &&
531 (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) 680 (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f))
532 { 681 {
@@ -541,15 +690,14 @@ void LLViewerImage::processTextureStats()
541 mCalculatedDiscardLevel = discard_level; 690 mCalculatedDiscardLevel = discard_level;
542 } 691 }
543 } 692 }
544 if (mBoostLevel < LLViewerImage::BOOST_HIGH) 693 if (mBoostLevel < LLViewerImageBoostLevel::BOOST_HIGH)
545 { 694 {
546 static const F32 discard_bias = -.5f; // Must be < 1 or highest discard will never load!
547 discard_level += discard_bias;
548 discard_level += sDesiredDiscardBias; 695 discard_level += sDesiredDiscardBias;
549 discard_level *= sDesiredDiscardScale; // scale 696 discard_level *= sDesiredDiscardScale; // scale
697
698 discard_level += sCameraMovingDiscardBias ;
550 } 699 }
551 discard_level = floorf(discard_level); 700 discard_level = floorf(discard_level);
552// discard_level -= (gImageList.mVideoMemorySetting>>1); // more video ram = higher detail
553 701
554 F32 min_discard = 0.f; 702 F32 min_discard = 0.f;
555 if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) 703 if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
@@ -567,43 +715,76 @@ void LLViewerImage::processTextureStats()
567 // if possible. Now we check to see if we have it, and take the 715 // if possible. Now we check to see if we have it, and take the
568 // proper action if we don't. 716 // proper action if we don't.
569 // 717 //
570
571 BOOL increase_discard = FALSE;
572 S32 current_discard = getDiscardLevel(); 718 S32 current_discard = getDiscardLevel();
573 if ((sDesiredDiscardBias > 0.0f) && 719 if ((sDesiredDiscardBias > 0.0f) &&
574 (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) 720 (current_discard >= 0 && mDesiredDiscardLevel >= current_discard))
575 { 721 {
576 if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) 722 // Limit the amount of GL memory bound each frame
723 if ( (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
724 (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
577 { 725 {
578 // Limit the amount of GL memory bound each frame 726 scaleDown() ;
579 if (mDesiredDiscardLevel > current_discard)
580 {
581 increase_discard = TRUE;
582 }
583 } 727 }
584 if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) 728 // Only allow GL to have 2x the video card memory
729 else if ( (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) &&
730 (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
585 { 731 {
586 // Only allow GL to have 2x the video card memory 732 scaleDown() ;
587 if (!getBoundRecently())
588 {
589 increase_discard = TRUE;
590 }
591 } 733 }
592 if (increase_discard) 734 }
735 }
736}
737void LLViewerImage::updateVirtualSize()
738{
739#if 1
740 if(mNeedsResetMaxVirtualSize)
741 {
742 addTextureStats(0.f, FALSE) ;//reset
743 }
744 if(mFaceList.size() > 0)
745 {
746 for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
747 {
748 LLFace* facep = *iter ;
749 if(facep->getDrawable()->isRecentlyVisible())
593 { 750 {
594 // llinfos << "DISCARDED: " << mID << " Discard: " << current_discard << llendl; 751 addTextureStats(facep->getVirtualSize()) ;
595 sBoundTextureMemoryInBytes -= mTextureMemory; 752 setAdditionalDecodePriority(facep->getImportanceToCamera()) ;
596 sTotalTextureMemoryInBytes -= mTextureMemory;
597 // Increase the discard level (reduce the texture res)
598 S32 new_discard = current_discard+1;
599 setDiscardLevel(new_discard);
600 sBoundTextureMemoryInBytes += mTextureMemory;
601 sTotalTextureMemoryInBytes += mTextureMemory;
602 } 753 }
603 } 754 }
604 } 755 }
756 mNeedsResetMaxVirtualSize = TRUE ;
757#endif
605} 758}
759void LLViewerImage::scaleDown()
760{
761 if(getHasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
762 {
763 switchToCachedImage() ;
764 }
765}
766
767//use the mCachedRawImage to (re)generate the gl texture.
768void LLViewerImage::switchToCachedImage()
769{
770 if(mCachedRawImage.notNull())
771 {
772 mRawImage = mCachedRawImage ;
773
774 if (getComponents() != mRawImage->getComponents())
775 {
776 // We've changed the number of components, so we need to move any
777 // objects using this pool to a different pool.
778 mComponents = mRawImage->getComponents();
779 gImageList.dirtyImage(this);
780 }
606 781
782 mIsRawImageValid = TRUE;
783 mRawDiscardLevel = mCachedRawDiscardLevel ;
784 gImageList.mCreateTextureList.insert(this);
785 mNeedsCreateTexture = TRUE;
786 }
787}
607//============================================================================ 788//============================================================================
608 789
609F32 LLViewerImage::calcDecodePriority() 790F32 LLViewerImage::calcDecodePriority()
@@ -619,9 +800,19 @@ F32 LLViewerImage::calcDecodePriority()
619 { 800 {
620 return mDecodePriority; // no change while waiting to create 801 return mDecodePriority; // no change while waiting to create
621 } 802 }
803 if(mForceToSaveRawImage)
804 {
805 return maxDecodePriority() ;
806 }
622 807
623 F32 priority;
624 S32 cur_discard = getDiscardLevel(); 808 S32 cur_discard = getDiscardLevel();
809
810 //no need to update if the texture reaches its highest res and the memory is sufficient.
811 //if(LLViewerImage::sFreezeImageScalingDown && !cur_discard)
812 //{
813 // return -5.0f ;
814 //}
815
625 bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); 816 bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
626 F32 pixel_priority = fsqrtf(mMaxVirtualSize); 817 F32 pixel_priority = fsqrtf(mMaxVirtualSize);
627 const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame 818 const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame
@@ -631,23 +822,36 @@ F32 LLViewerImage::calcDecodePriority()
631 mVisibleFrame = mDecodeFrame; 822 mVisibleFrame = mDecodeFrame;
632 } 823 }
633 824
825 F32 priority = 0.f;
634 if (mIsMissingAsset) 826 if (mIsMissingAsset)
635 { 827 {
636 priority = 0.0f; 828 priority = 0.0f;
829 }
830 else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1)
831 {
832 priority = -1.0f ;
833 }
834 else if (!isJustBound() && mCachedRawImageReady)
835 {
836 priority = -1.0f;
837 }
838 else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel)
839 {
840 priority = -1.0f;
637 } 841 }
638 else if (mDesiredDiscardLevel > mMaxDiscardLevel) 842 else if (mDesiredDiscardLevel > mMaxDiscardLevel)
639 { 843 {
640 // Don't decode anything we don't need 844 // Don't decode anything we don't need
641 priority = -1.0f; 845 priority = -1.0f;
642 } 846 }
643 else if (mBoostLevel == LLViewerImage::BOOST_UI && !have_all_data) 847 else if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI && !have_all_data)
644 { 848 {
645 priority = 1.f; 849 priority = 1.f;
646 } 850 }
647 else if (pixel_priority <= 0.f && !have_all_data) 851 else if (pixel_priority <= 0.f && !have_all_data)
648 { 852 {
649 // Not on screen but we might want some data 853 // Not on screen but we might want some data
650 if (mBoostLevel > BOOST_HIGH) 854 if (mBoostLevel > LLViewerImageBoostLevel::BOOST_HIGH)
651 { 855 {
652 // Always want high boosted images 856 // Always want high boosted images
653 priority = 1.f; 857 priority = 1.f;
@@ -695,12 +899,16 @@ F32 LLViewerImage::calcDecodePriority()
695 ddiscard-=2; 899 ddiscard-=2;
696 } 900 }
697 ddiscard = llclamp(ddiscard, 0, 4); 901 ddiscard = llclamp(ddiscard, 0, 4);
902
698 priority = ddiscard*100000.f; 903 priority = ddiscard*100000.f;
699 } 904 }
700 if (priority > 0.0f) 905 if (priority > 0.0f)
701 { 906 {
702 pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); // priority range = 100000-900000 907 // priority range = 100000-900000
703 if ( mBoostLevel > BOOST_HIGH) 908 pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f);
909
910 // priority range = [100000.f, 2000000.f]
911 if ( mBoostLevel > LLViewerImageBoostLevel::BOOST_HIGH)
704 { 912 {
705 priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel; 913 priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel;
706 } 914 }
@@ -708,7 +916,14 @@ F32 LLViewerImage::calcDecodePriority()
708 { 916 {
709 priority += 0.f + pixel_priority + 1000.f * mBoostLevel; 917 priority += 0.f + pixel_priority + 1000.f * mBoostLevel;
710 } 918 }
919
920 // priority range = [2100000.f, 5000000.f] if mAdditionalDecodePriority > 1.0
921 if(mAdditionalDecodePriority > 1.0f)
922 {
923 priority += 2000000.f + mAdditionalDecodePriority ;
924 }
711 } 925 }
926
712 return priority; 927 return priority;
713} 928}
714 929
@@ -716,7 +931,7 @@ F32 LLViewerImage::calcDecodePriority()
716//static 931//static
717F32 LLViewerImage::maxDecodePriority() 932F32 LLViewerImage::maxDecodePriority()
718{ 933{
719 return 2000000.f; 934 return 6000000.f;
720} 935}
721 936
722void LLViewerImage::setDecodePriority(F32 priority) 937void LLViewerImage::setDecodePriority(F32 priority)
@@ -725,15 +940,30 @@ void LLViewerImage::setDecodePriority(F32 priority)
725 mDecodePriority = priority; 940 mDecodePriority = priority;
726} 941}
727 942
728void LLViewerImage::setBoostLevel(S32 level) 943F32 LLViewerImage::maxAdditionalDecodePriority()
944{
945 return 2000000.f;
946}
947void LLViewerImage::setAdditionalDecodePriority(F32 priority)
729{ 948{
949 priority *= maxAdditionalDecodePriority();
950 if(mAdditionalDecodePriority < priority)
951 {
952 mAdditionalDecodePriority = priority;
953 }
954}
955//------------------------------------------------------------
956
957void LLViewerImage::setBoostLevel(S32 level)
958{
730 mBoostLevel = level; 959 mBoostLevel = level;
731 if (level >= LLViewerImage::BOOST_HIGH) 960
961 if(gAuditTexture)
732 { 962 {
733 processTextureStats(); 963 setCategory(mBoostLevel);
734 } 964 }
735 965
736 if(mBoostLevel != LLViewerImage::BOOST_NONE) 966 if(mBoostLevel != LLViewerImageBoostLevel::BOOST_NONE)
737 { 967 {
738 setNoDelete() ; 968 setNoDelete() ;
739 } 969 }
@@ -785,11 +1015,20 @@ bool LLViewerImage::updateFetch()
785 S32 desired_discard = getDesiredDiscardLevel(); 1015 S32 desired_discard = getDesiredDiscardLevel();
786 F32 decode_priority = getDecodePriority(); 1016 F32 decode_priority = getDecodePriority();
787 decode_priority = llmax(decode_priority, 0.0f); 1017 decode_priority = llmax(decode_priority, 0.0f);
1018 decode_priority = llmin(decode_priority, maxDecodePriority());
788 1019
789 if (mIsFetching) 1020 if (mIsFetching)
790 { 1021 {
791 // Sets mRawDiscardLevel, mRawImage, mAuxRawImage 1022 // Sets mRawDiscardLevel, mRawImage, mAuxRawImage
792 S32 fetch_discard = current_discard; 1023 S32 fetch_discard = current_discard;
1024 if(mForceToSaveRawImage)
1025 {
1026 if(fetch_discard >= 0)
1027 {
1028 fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ;
1029 }
1030 }
1031
793 if (mRawImage.notNull()) sRawCount--; 1032 if (mRawImage.notNull()) sRawCount--;
794 if (mAuxRawImage.notNull()) sAuxCount--; 1033 if (mAuxRawImage.notNull()) sAuxCount--;
795 bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); 1034 bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
@@ -809,6 +1048,7 @@ bool LLViewerImage::updateFetch()
809 if (mRawImage.notNull()) 1048 if (mRawImage.notNull())
810 { 1049 {
811 mRawDiscardLevel = fetch_discard; 1050 mRawDiscardLevel = fetch_discard;
1051
812 if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && 1052 if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
813 (current_discard < 0 || mRawDiscardLevel < current_discard)) 1053 (current_discard < 0 || mRawDiscardLevel < current_discard))
814 { 1054 {
@@ -819,11 +1059,25 @@ bool LLViewerImage::updateFetch()
819 mComponents = mRawImage->getComponents(); 1059 mComponents = mRawImage->getComponents();
820 gImageList.dirtyImage(this); 1060 gImageList.dirtyImage(this);
821 } 1061 }
822 mIsRawImageValid = TRUE; 1062
823 gImageList.mCreateTextureList.insert(this);
824 mNeedsCreateTexture = TRUE;
825 mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; 1063 mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
826 mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; 1064 mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
1065
1066 if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
1067 {
1068 //discard all oversized textures.
1069 destroyRawImage();
1070 setIsMissingAsset();
1071 mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
1072 mIsFetching = FALSE ;
1073 }
1074 else
1075 {
1076 mIsRawImageValid = TRUE;
1077 addToCreateTexture() ;
1078 }
1079
1080 return TRUE ;
827 } 1081 }
828 else 1082 else
829 { 1083 {
@@ -846,7 +1100,7 @@ bool LLViewerImage::updateFetch()
846 } 1100 }
847 else 1101 else
848 { 1102 {
849 llwarns << mID << ": Setting min discard to " << current_discard << llendl; 1103 //llwarns << mID << ": Setting min discard to " << current_discard << llendl;
850 mMinDiscardLevel = current_discard; 1104 mMinDiscardLevel = current_discard;
851 desired_discard = current_discard; 1105 desired_discard = current_discard;
852 } 1106 }
@@ -865,8 +1119,19 @@ bool LLViewerImage::updateFetch()
865 } 1119 }
866 } 1120 }
867 1121
868 bool make_request = true; 1122 if (!mDontDiscard)
869 1123 {
1124 if (mBoostLevel == 0)
1125 {
1126 desired_discard = llmax(desired_discard, current_discard-1);
1127 }
1128 else
1129 {
1130 desired_discard = llmax(desired_discard, current_discard-2);
1131 }
1132 }
1133
1134 bool make_request = true;
870 if (decode_priority <= 0) 1135 if (decode_priority <= 0)
871 { 1136 {
872 make_request = false; 1137 make_request = false;
@@ -879,6 +1144,10 @@ bool LLViewerImage::updateFetch()
879 { 1144 {
880 make_request = false; 1145 make_request = false;
881 } 1146 }
1147 else if (!isJustBound() && mCachedRawImageReady)
1148 {
1149 make_request = false;
1150 }
882 else 1151 else
883 { 1152 {
884 if (mIsFetching) 1153 if (mIsFetching)
@@ -906,41 +1175,21 @@ bool LLViewerImage::updateFetch()
906 h = getHeight(0); 1175 h = getHeight(0);
907 c = getComponents(); 1176 c = getComponents();
908 } 1177 }
909 if (!mDontDiscard) 1178
910 {
911 if (mBoostLevel == 0)
912 {
913 desired_discard = llmax(desired_discard, current_discard-1);
914 }
915 else
916 {
917 desired_discard = llmax(desired_discard, current_discard-2);
918 }
919 }
920
921 // bypass texturefetch directly by pulling from LLTextureCache 1179 // bypass texturefetch directly by pulling from LLTextureCache
922 bool fetch_request_created = false; 1180 bool fetch_request_created = false;
923 if (mLocalFileName.empty()) 1181 fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority,
924 { 1182 w, h, c, desired_discard, needsAux());
925 fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(getID(), getTargetHost(), decode_priority,
926 w, h, c, desired_discard,
927 needsAux());
928 }
929 else
930 {
931 fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mLocalFileName, getID(),getTargetHost(), decode_priority,
932 w, h, c, desired_discard,
933 needsAux());
934 }
935 1183
936 if (fetch_request_created) 1184 if (fetch_request_created)
937 { 1185 {
938 mHasFetcher = TRUE; 1186 mHasFetcher = TRUE;
939 mIsFetching = TRUE; 1187 mIsFetching = TRUE;
940 mRequestedDiscardLevel = desired_discard; 1188 mRequestedDiscardLevel = desired_discard;
1189
941 mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, 1190 mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
942 mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); 1191 mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
943 } 1192 }
944 1193
945 // if createRequest() failed, we're finishing up a request for this UUID, 1194 // if createRequest() failed, we're finishing up a request for this UUID,
946 // wait for it to complete 1195 // wait for it to complete
@@ -962,9 +1211,81 @@ bool LLViewerImage::updateFetch()
962 return mIsFetching ? true : false; 1211 return mIsFetching ? true : false;
963} 1212}
964 1213
1214//
1215//force to fetch a new raw image for this texture
1216//this function is to replace readBackRaw().
1217//
1218BOOL LLViewerImage::forceFetch()
1219{
1220 if(!mForceToSaveRawImage)
1221 {
1222 return false ;
1223 }
1224 if (mIsMediaTexture)
1225 {
1226 mForceToSaveRawImage = false ;
1227 llassert_always(!mHasFetcher);
1228 return false; // skip
1229 }
1230 if (mIsMissingAsset)
1231 {
1232 mForceToSaveRawImage = false ;
1233 llassert_always(!mHasFetcher);
1234 return false; // skip
1235 }
1236 if (!mLoadedCallbackList.empty() && mRawImage.notNull())
1237 {
1238 return false; // process any raw image data in callbacks before replacing
1239 }
1240 if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
1241 {
1242 return false ; // mRawImage is enough
1243 }
1244 if(mIsFetching)
1245 {
1246 return false ;
1247 }
1248
1249 S32 desired_discard = mDesiredSavedRawDiscardLevel ;
1250 S32 current_discard = getDiscardLevel();
1251
1252 bool fetch_request_created = false;
1253 S32 w=0, h=0, c=0;
1254 if (current_discard >= 0)
1255 {
1256 w = getWidth(0);
1257 h = getHeight(0);
1258 c = getComponents();
1259 }
1260 fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), maxDecodePriority(),
1261 w, h, c, desired_discard, needsAux());
1262
1263 if (fetch_request_created)
1264 {
1265 mHasFetcher = TRUE;
1266 mIsFetching = TRUE;
1267 // Set the image's decode priority to maxDecodePriority() too, or updateFetch() will set
1268 // the request priority to 0 and terminate the fetch before we even started (SNOW-203).
1269 gImageList.bumpToMaxDecodePriority(this);
1270 mRequestedDiscardLevel = desired_discard ;
1271
1272 mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
1273 mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
1274 }
1275
1276 return mIsFetching ? true : false;
1277}
1278
965void LLViewerImage::setIsMissingAsset() 1279void LLViewerImage::setIsMissingAsset()
966{ 1280{
967 llwarns << mLocalFileName << " " << mID << ": Marking image as missing" << llendl; 1281 if (mUrl.empty())
1282 {
1283 llwarns << mID << ": Marking image as missing" << llendl;
1284 }
1285 else
1286 {
1287 llwarns << mUrl << ": Marking image as missing" << llendl;
1288 }
968 if (mHasFetcher) 1289 if (mHasFetcher)
969 { 1290 {
970 LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); 1291 LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
@@ -1252,7 +1573,7 @@ bool LLViewerImage::bindError(S32 stage) const
1252 return res; 1573 return res;
1253} 1574}
1254 1575
1255bool LLViewerImage::bindDefaultImage(S32 stage) const 1576bool LLViewerImage::bindDefaultImage(S32 stage)
1256{ 1577{
1257 if (stage < 0) return false; 1578 if (stage < 0) return false;
1258 1579
@@ -1271,24 +1592,17 @@ bool LLViewerImage::bindDefaultImage(S32 stage) const
1271 llwarns << "LLViewerImage::bindError failed." << llendl; 1592 llwarns << "LLViewerImage::bindError failed." << llendl;
1272 } 1593 }
1273 stop_glerror(); 1594 stop_glerror();
1595
1596 //check if there is cached raw image and switch to it if possible
1597 switchToCachedImage() ;
1598
1274 return res; 1599 return res;
1275} 1600}
1276 1601
1277//virtual 1602//virtual
1278void LLViewerImage::forceImmediateUpdate() 1603void LLViewerImage::forceImmediateUpdate()
1279{ 1604{
1280 //only immediately update a deleted texture which is now being re-used. 1605 gImageList.bumpToMaxDecodePriority(this) ;
1281 if(!isDeleted())
1282 {
1283 return ;
1284 }
1285 //if already called forceImmediateUpdate()
1286 if(mInImageList && mDecodePriority == LLViewerImage::maxDecodePriority())
1287 {
1288 return ;
1289 }
1290
1291 gImageList.forceImmediateUpdate(this) ;
1292 return ; 1606 return ;
1293} 1607}
1294 1608
@@ -1302,21 +1616,165 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level)
1302 llerrs << "called with existing mRawImage" << llendl; 1616 llerrs << "called with existing mRawImage" << llendl;
1303 mRawImage = NULL; 1617 mRawImage = NULL;
1304 } 1618 }
1305 mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), mComponents);
1306 sRawCount++;
1307 mRawDiscardLevel = discard_level;
1308 readBackRaw(mRawDiscardLevel, mRawImage, false);
1309 mIsRawImageValid = TRUE;
1310 1619
1620 if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
1621 {
1622 mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
1623 mRawImage->copy(mSavedRawImage) ;
1624 mRawDiscardLevel = discard_level ;
1625 }
1626 else
1627 {
1628 mRawImage = mCachedRawImage ;
1629 mRawDiscardLevel = mCachedRawDiscardLevel;
1630 }
1631
1632 sRawCount++;
1633 mIsRawImageValid = TRUE;
1634
1311 return mRawImage; 1635 return mRawImage;
1312} 1636}
1313 1637
1638void LLViewerImage::saveRawImage()
1639{
1640 if(mRawImage.isNull() || mRawDiscardLevel > mDesiredSavedRawDiscardLevel)
1641 {
1642 forceFetch() ;
1643 }
1644
1645 if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel)
1646 {
1647 return ;
1648 }
1649
1650 mSavedRawDiscardLevel = mRawDiscardLevel ;
1651 mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ;
1652
1653 if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
1654 {
1655 mForceToSaveRawImage = FALSE ;
1656 }
1657}
1658
1659void LLViewerImage::forceToSaveRawImage(S32 desired_discard)
1660{
1661 mForceToSaveRawImage = TRUE ;
1662 mDesiredSavedRawDiscardLevel = desired_discard ;
1663
1664 forceFetch() ;
1665}
1666void LLViewerImage::destroySavedRawImage()
1667{
1668 mSavedRawImage = NULL ;
1669 mForceToSaveRawImage = FALSE ;
1670 mSavedRawDiscardLevel = -1 ;
1671 mDesiredSavedRawDiscardLevel = -1 ;
1672}
1673
1314void LLViewerImage::destroyRawImage() 1674void LLViewerImage::destroyRawImage()
1315{ 1675{
1316 if (mRawImage.notNull()) sRawCount--; 1676 if (mRawImage.notNull()) sRawCount--;
1317 if (mAuxRawImage.notNull()) sAuxCount--; 1677 if (mAuxRawImage.notNull()) sAuxCount--;
1678
1679 if(mForceToSaveRawImage)
1680 {
1681 saveRawImage() ;
1682 }
1683
1684 setCachedRawImage() ;
1685
1318 mRawImage = NULL; 1686 mRawImage = NULL;
1319 mAuxRawImage = NULL; 1687 mAuxRawImage = NULL;
1320 mIsRawImageValid = FALSE; 1688 mIsRawImageValid = FALSE;
1321 mRawDiscardLevel = INVALID_DISCARD_LEVEL; 1689 mRawDiscardLevel = INVALID_DISCARD_LEVEL;
1322} 1690}
1691
1692void LLViewerImage::setCachedRawImage()
1693{
1694 if(mRawImage == mCachedRawImage)
1695 {
1696 return ;
1697 }
1698 if(!mIsRawImageValid)
1699 {
1700 return ;
1701 }
1702
1703 if(mCachedRawImageReady)
1704 {
1705 return ;
1706 }
1707
1708 if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel)
1709 {
1710 S32 i = 0 ;
1711 S32 w = mRawImage->getWidth() ;
1712 S32 h = mRawImage->getHeight() ;
1713
1714 S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ;
1715 if(LLViewerImageBoostLevel::BOOST_TERRAIN == mBoostLevel)
1716 {
1717 max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ;
1718 }
1719 if(mForSculpt)
1720 {
1721 max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ;
1722 }
1723
1724 while(((w >> i) * (h >> i)) > max_size)
1725 {
1726 ++i ;
1727 }
1728 mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ;
1729
1730 if(i)
1731 {
1732 if(!(w >> i) || !(h >> i))
1733 {
1734 --i ;
1735 }
1736 mRawImage->scale(w >> i, h >> i) ;
1737 }
1738 mCachedRawImage = mRawImage ;
1739 mCachedRawDiscardLevel = mRawDiscardLevel + i ;
1740 }
1741}
1742
1743void LLViewerImage::checkCachedRawSculptImage()
1744{
1745 if(mCachedRawImageReady && mCachedRawDiscardLevel > 0)
1746 {
1747 if(mCachedRawImage->getWidth() * mCachedRawImage->getHeight() < MAX_CACHED_RAW_SCULPT_IMAGE_AREA)
1748 {
1749 mCachedRawImageReady = FALSE ;
1750 }
1751 else if(isForSculptOnly())
1752 {
1753 resetTextureStats() ; //do not update this image any more.
1754 }
1755 }
1756}
1757
1758BOOL LLViewerImage::isForSculptOnly() const
1759{
1760 return mForSculpt && !mNeedsGLTexture ;
1761}
1762
1763void LLViewerImage::setForSculpt()
1764{
1765 mForSculpt = TRUE ;
1766 if(isForSculptOnly() && !getBoundRecently())
1767 {
1768 destroyGLTexture() ; //sculpt image does not need gl texture.
1769 }
1770 checkCachedRawSculptImage() ;
1771}
1772
1773void LLViewerImage::addFace(LLFace* facep)
1774{
1775 mFaceList.push_back(facep) ;
1776}
1777void LLViewerImage::removeFace(LLFace* facep)
1778{
1779 mFaceList.remove(facep) ;
1780}