diff options
author | Jacek Antonelli | 2010-02-09 21:11:42 -0600 |
---|---|---|
committer | Jacek Antonelli | 2010-02-16 18:50:15 -0600 |
commit | e6247fbe78c4d3dacb74f3b2359aba2b6538133b (patch) | |
tree | 10c42d670a2c635b4339f7f68809c221756774f8 /linden/indra/newview/llviewerimage.cpp | |
parent | Ported some cURL and HTTP-related changes from Snowglobe. (diff) | |
download | meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.zip meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.gz meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.bz2 meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.xz |
Ported many texture engine changes from Snowglobe.
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llviewerimage.cpp | 700 |
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; | |||
72 | S32 LLViewerImage::sRawCount = 0; | 74 | S32 LLViewerImage::sRawCount = 0; |
73 | S32 LLViewerImage::sAuxCount = 0; | 75 | S32 LLViewerImage::sAuxCount = 0; |
74 | LLTimer LLViewerImage::sEvaluationTimer; | 76 | LLTimer LLViewerImage::sEvaluationTimer; |
77 | S8 LLViewerImage::sCameraMovingDiscardBias = 0 ; | ||
75 | F32 LLViewerImage::sDesiredDiscardBias = 0.f; | 78 | F32 LLViewerImage::sDesiredDiscardBias = 0.f; |
76 | static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by | 79 | static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by |
77 | static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by | 80 | static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by |
@@ -83,16 +86,26 @@ S32 LLViewerImage::sMaxTotalTextureMemInMegaBytes = 0; | |||
83 | S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ; | 86 | S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ; |
84 | BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE; | 87 | BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE; |
85 | 88 | ||
89 | S32 LLViewerImage::sMaxSculptRez = 128 ; //max sculpt image size | ||
90 | const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; | ||
91 | const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerImage::sMaxSculptRez * LLViewerImage::sMaxSculptRez ; | ||
92 | const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ; | ||
93 | S32 LLViewerImage::sMinLargeImageSize = 65536 ; //256 * 256. | ||
94 | S32 LLViewerImage::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; | ||
95 | BOOL LLViewerImage::sFreezeImageScalingDown = FALSE ; | ||
96 | //debug use | ||
97 | S32 LLViewerImage::sLLViewerImageCount = 0 ; | ||
98 | |||
86 | // static | 99 | // static |
87 | void LLViewerImage::initClass() | 100 | void 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 |
134 | void LLViewerImage::cleanupClass() | 175 | void 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 | ||
199 | const U32 LLViewerImage::sCurrentFileVersion = 1; | 250 | const U32 LLViewerImage::sCurrentFileVersion = 1; |
200 | 251 | ||
201 | LLViewerImage::LLViewerImage(const LLUUID& id, BOOL usemipmaps) | 252 | LLViewerImage::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 | ||
209 | LLViewerImage::LLViewerImage(const std::string& filename, const LLUUID& id, BOOL usemipmaps) | 261 | LLViewerImage::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 | ||
323 | void LLViewerImage::cleanup() | 382 | void 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 | ||
430 | void 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 |
369 | BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) | 488 | BOOL 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 | ||
460 | void LLViewerImage::addTextureStats(F32 virtual_size) const // = 1.0 | 579 | void 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 | ||
468 | void 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 | |||
600 | void LLViewerImage::resetTextureStats() | ||
601 | { | ||
602 | mMaxVirtualSize = 0.0f; | ||
603 | mAdditionalDecodePriority = 0.f ; | ||
604 | mNeedsResetMaxVirtualSize = FALSE ; | ||
605 | } | ||
606 | |||
607 | BOOL LLViewerImage::isUpdateFrozen() | ||
608 | { | ||
609 | return LLViewerImage::sFreezeImageScalingDown && !getDiscardLevel() ; | ||
610 | } | ||
611 | |||
612 | BOOL 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 |
481 | void LLViewerImage::processTextureStats() | 618 | void 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 | } | ||
737 | void 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 | } |
759 | void LLViewerImage::scaleDown() | ||
760 | { | ||
761 | if(getHasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) | ||
762 | { | ||
763 | switchToCachedImage() ; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | //use the mCachedRawImage to (re)generate the gl texture. | ||
768 | void 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 | ||
609 | F32 LLViewerImage::calcDecodePriority() | 790 | F32 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 |
717 | F32 LLViewerImage::maxDecodePriority() | 932 | F32 LLViewerImage::maxDecodePriority() |
718 | { | 933 | { |
719 | return 2000000.f; | 934 | return 6000000.f; |
720 | } | 935 | } |
721 | 936 | ||
722 | void LLViewerImage::setDecodePriority(F32 priority) | 937 | void LLViewerImage::setDecodePriority(F32 priority) |
@@ -725,15 +940,30 @@ void LLViewerImage::setDecodePriority(F32 priority) | |||
725 | mDecodePriority = priority; | 940 | mDecodePriority = priority; |
726 | } | 941 | } |
727 | 942 | ||
728 | void LLViewerImage::setBoostLevel(S32 level) | 943 | F32 LLViewerImage::maxAdditionalDecodePriority() |
944 | { | ||
945 | return 2000000.f; | ||
946 | } | ||
947 | void LLViewerImage::setAdditionalDecodePriority(F32 priority) | ||
729 | { | 948 | { |
949 | priority *= maxAdditionalDecodePriority(); | ||
950 | if(mAdditionalDecodePriority < priority) | ||
951 | { | ||
952 | mAdditionalDecodePriority = priority; | ||
953 | } | ||
954 | } | ||
955 | //------------------------------------------------------------ | ||
956 | |||
957 | void 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 | // | ||
1218 | BOOL 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 | |||
965 | void LLViewerImage::setIsMissingAsset() | 1279 | void 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 | ||
1255 | bool LLViewerImage::bindDefaultImage(S32 stage) const | 1576 | bool 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 |
1278 | void LLViewerImage::forceImmediateUpdate() | 1603 | void 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 | ||
1638 | void 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 | |||
1659 | void LLViewerImage::forceToSaveRawImage(S32 desired_discard) | ||
1660 | { | ||
1661 | mForceToSaveRawImage = TRUE ; | ||
1662 | mDesiredSavedRawDiscardLevel = desired_discard ; | ||
1663 | |||
1664 | forceFetch() ; | ||
1665 | } | ||
1666 | void LLViewerImage::destroySavedRawImage() | ||
1667 | { | ||
1668 | mSavedRawImage = NULL ; | ||
1669 | mForceToSaveRawImage = FALSE ; | ||
1670 | mSavedRawDiscardLevel = -1 ; | ||
1671 | mDesiredSavedRawDiscardLevel = -1 ; | ||
1672 | } | ||
1673 | |||
1314 | void LLViewerImage::destroyRawImage() | 1674 | void 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 | |||
1692 | void 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 | |||
1743 | void 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 | |||
1758 | BOOL LLViewerImage::isForSculptOnly() const | ||
1759 | { | ||
1760 | return mForSculpt && !mNeedsGLTexture ; | ||
1761 | } | ||
1762 | |||
1763 | void 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 | |||
1773 | void LLViewerImage::addFace(LLFace* facep) | ||
1774 | { | ||
1775 | mFaceList.push_back(facep) ; | ||
1776 | } | ||
1777 | void LLViewerImage::removeFace(LLFace* facep) | ||
1778 | { | ||
1779 | mFaceList.remove(facep) ; | ||
1780 | } | ||