summaryrefslogtreecommitdiff
path: root/indra/newview/llviewertexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewertexture.cpp')
-rw-r--r--indra/newview/llviewertexture.cpp247
1 files changed, 201 insertions, 46 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 4da0f80a00..e1eb54bd24 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -66,6 +66,8 @@
// statics
LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
+LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL;
+LLPointer<LLViewerTexture> LLViewerTexture::sCheckerBoardImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
@@ -86,6 +88,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ;
+F32 LLViewerTexture::sCameraMovingBias = 0.0f ;
S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ;
@@ -95,6 +98,9 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
F32 LLViewerTexture::sCurrentTime = 0.0f ;
BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
+F32 LLViewerTexture::sTexelPixelRatio = 1.0f;
+
+LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by
@@ -174,7 +180,12 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id)
}
return tex ;
}
-
+
+LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id)
+{
+ return gTextureList.findImage(id);
+}
+
LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
{
return LLViewerMediaTexture::findMediaTexture(media_id) ;
@@ -295,17 +306,23 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const
void LLViewerTextureManager::init()
{
- LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
- raw->clear(0x77, 0x77, 0x77, 0xFF);
- LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
-
-#if 1
- LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
- LLViewerFetchedTexture::sDefaultImagep = imagep;
+ {
+ LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
+ raw->clear(0x77, 0x77, 0x77, 0xFF);
+ LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
+ }
const S32 dim = 128;
LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
U8* data = image_raw->getData();
+
+ memset(data, 0, dim * dim * 3) ;
+ LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ;
+
+#if 1
+ LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
+ LLViewerFetchedTexture::sDefaultImagep = imagep;
+
for (S32 i = 0; i<dim; i++)
{
for (S32 j = 0; j<dim; j++)
@@ -340,6 +357,21 @@ void LLViewerTextureManager::init()
LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
+ image_raw = new LLImageRaw(32,32,3);
+ data = image_raw->getData();
+
+ for (S32 i = 0; i < (32*32*3); i+=3)
+ {
+ S32 x = (i % (32*3)) / (3*16);
+ S32 y = i / (32*3*16);
+ U8 color = ((x + y) % 2) * 255;
+ data[i] = color;
+ data[i+1] = color;
+ data[i+2] = color;
+ }
+
+ LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE);
+
LLViewerTexture::initClass() ;
if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
@@ -359,6 +391,8 @@ void LLViewerTextureManager::cleanup()
LLImageGL::sDefaultGLTexture = NULL ;
LLViewerTexture::sNullImagep = NULL;
+ LLViewerTexture::sBlackImagep = NULL;
+ LLViewerTexture::sCheckerBoardImagep = NULL;
LLViewerFetchedTexture::sDefaultImagep = NULL;
LLViewerFetchedTexture::sSmokeImagep = NULL;
LLViewerFetchedTexture::sMissingAssetImagep = NULL;
@@ -375,11 +409,7 @@ void LLViewerTextureManager::cleanup()
void LLViewerTexture::initClass()
{
LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
-
- if(gAuditTexture)
- {
- LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ;
- }
+ sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
}
// static
@@ -409,6 +439,64 @@ const S32 min_non_tex_system_mem = (128<<20); // 128 MB
F32 texmem_lower_bound_scale = 0.85f;
F32 texmem_middle_bound_scale = 0.925f;
+static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check");
+
+//static
+bool LLViewerTexture::isMemoryForTextureLow()
+{
+ const F32 WAIT_TIME = 1.0f ; //second
+ static LLFrameTimer timer ;
+
+ if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second.
+ {
+ return false;
+ }
+ timer.reset() ;
+
+ LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
+
+ const S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
+ const S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB
+
+ bool low_mem = false ;
+ if (gGLManager.mHasATIMemInfo)
+ {
+ S32 meminfo[4];
+ glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
+
+ if(meminfo[0] / 1024 < MIN_FREE_TEXTURE_MEMORY)
+ {
+ low_mem = true ;
+ }
+
+ if(!low_mem) //check main memory, only works for windows.
+ {
+ LLMemory::updateMemoryInfo() ;
+ if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
+ {
+ low_mem = true ;
+ }
+ }
+ }
+#if 0 //ignore nVidia cards
+ else if (gGLManager.mHasNVXMemInfo)
+ {
+ S32 free_memory;
+ glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
+
+ if(free_memory / 1024 < MIN_FREE_TEXTURE_MEMORY)
+ {
+ low_mem = true ;
+ }
+ }
+#endif
+
+ return low_mem ;
+}
+
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_MEDIA("Media");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_TEST("Test");
+
//static
void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
{
@@ -417,9 +505,14 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
if (tester)
{
+ LLFastTimer t(FTM_TEXTURE_UPDATE_TEST);
tester->update() ;
}
- LLViewerMediaTexture::updateClass() ;
+
+ {
+ LLFastTimer t(FTM_TEXTURE_UPDATE_MEDIA);
+ LLViewerMediaTexture::updateClass() ;
+ }
sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
@@ -441,6 +534,11 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
sEvaluationTimer.reset();
}
}
+ else if(sEvaluationTimer.getElapsedTimeF32() > discard_delta_time && isMemoryForTextureLow())
+ {
+ sDesiredDiscardBias += discard_bias_delta;
+ sEvaluationTimer.reset();
+ }
else if (sDesiredDiscardBias > 0.0f &&
BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
@@ -458,7 +556,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
- sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
+ sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1);
+ sCameraMovingDiscardBias = (S8)(sCameraMovingBias);
LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
(BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
@@ -579,10 +678,6 @@ void LLViewerTexture::setBoostLevel(S32 level)
{
setNoDelete() ;
}
- if(gAuditTexture)
- {
- setCategory(mBoostLevel);
- }
}
}
@@ -599,7 +694,7 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
}
if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep))
{
- res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ;
+ res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep);
}
if (!res)
{
@@ -636,6 +731,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co
mNeedsGLTexture = TRUE ;
}
+ virtual_size *= sTexelPixelRatio;
if(!mMaxVirtualSizeResetCounter)
{
//flag to reset the values because the old values are used.
@@ -1211,6 +1307,7 @@ void LLViewerFetchedTexture::cleanup()
mCachedRawDiscardLevel = -1 ;
mCachedRawImageReady = FALSE ;
mSavedRawImage = NULL ;
+ mSavedRawDiscardLevel = -1;
}
void LLViewerFetchedTexture::setForSculpt()
@@ -1301,10 +1398,10 @@ void LLViewerFetchedTexture::dump()
// ONLY called from LLViewerFetchedTextureList
void LLViewerFetchedTexture::destroyTexture()
{
- if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
- {
- return ;
- }
+ //if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
+ //{
+ // return ;
+ //}
if (mNeedsCreateTexture)//return if in the process of generating a new texture.
{
return ;
@@ -1804,6 +1901,8 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
bool LLViewerFetchedTexture::updateFetch()
{
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
+ static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold");
+ static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost");
if(textures_decode_disabled)
{
return false ;
@@ -1966,18 +2065,24 @@ bool LLViewerFetchedTexture::updateFetch()
// make_request = false;
//}
- if(make_request)
+ if (make_request)
{
- //load the texture progressively.
+ // Load the texture progressively: we try not to rush to the desired discard too fast.
+ // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps
+ // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around
S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ;
- if(current_discard < 0)
+ if (current_discard < 0)
{
desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level);
}
- else
+ else if (LLViewerTexture::sCameraMovingBias < sCameraMotionThreshold)
{
- desired_discard = llmax(desired_discard, current_discard - delta_level);
+ desired_discard = llmax(desired_discard, current_discard - sCameraMotionBoost);
}
+ else
+ {
+ desired_discard = llmax(desired_discard, current_discard - delta_level);
+ }
if (mIsFetching)
{
@@ -2045,6 +2150,30 @@ bool LLViewerFetchedTexture::updateFetch()
return mIsFetching ? true : false;
}
+void LLViewerFetchedTexture::clearFetchedResults()
+{
+ llassert_always(!mNeedsCreateTexture && !mIsFetching);
+
+ cleanup();
+ destroyGLTexture();
+
+ if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate
+ {
+ mGLTexturep->forceToInvalidateGLTexture();
+ }
+}
+
+void LLViewerFetchedTexture::forceToDeleteRequest()
+{
+ if (mHasFetcher)
+ {
+ LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+ mHasFetcher = FALSE;
+ mIsFetching = FALSE ;
+ resetTextureStats();
+ }
+}
+
void LLViewerFetchedTexture::setIsMissingAsset()
{
if (mUrl.empty())
@@ -2053,7 +2182,8 @@ void LLViewerFetchedTexture::setIsMissingAsset()
}
else
{
- llwarns << mUrl << ": Marking image as missing" << llendl;
+ //it is normal no map tile on an empty region.
+ //llwarns << mUrl << ": Marking image as missing" << llendl;
}
if (mHasFetcher)
{
@@ -2214,6 +2344,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
}
}
mPauseLoadedCallBacks = FALSE ;
+ mLastCallBackActiveTime = sCurrentTime ;
if(need_raw)
{
mSaveRawImage = TRUE ;
@@ -2253,13 +2384,18 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
bool LLViewerFetchedTexture::doLoadedCallbacks()
{
- static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
+ static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds
if (mNeedsCreateTexture)
{
return false;
}
- if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME)
+ if(mPauseLoadedCallBacks)
+ {
+ destroyRawImage();
+ return false; //paused
+ }
+ if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching)
{
clearCallbackEntryList() ; //remove all callbacks.
return false ;
@@ -2282,12 +2418,8 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
// Remove ourself from the global list of textures with callbacks
gTextureList.mCallbackList.erase(this);
- }
- if(mPauseLoadedCallBacks)
- {
- destroyRawImage();
- return res; //paused
- }
+ return false ;
+ }
S32 gl_discard = getDiscardLevel();
@@ -2549,7 +2681,11 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
void LLViewerFetchedTexture::destroyRawImage()
{
- if (mAuxRawImage.notNull()) sAuxCount--;
+ if (mAuxRawImage.notNull())
+ {
+ sAuxCount--;
+ mAuxRawImage = NULL;
+ }
if (mRawImage.notNull())
{
@@ -2563,12 +2699,12 @@ void LLViewerFetchedTexture::destroyRawImage()
}
setCachedRawImage() ;
}
+
+ mRawImage = NULL;
+
+ mIsRawImageValid = FALSE;
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL;
}
-
- mRawImage = NULL;
- mAuxRawImage = NULL;
- mIsRawImageValid = FALSE;
- mRawDiscardLevel = INVALID_DISCARD_LEVEL;
}
//use the mCachedRawImage to (re)generate the gl texture.
@@ -3081,8 +3217,13 @@ void LLViewerLODTexture::processTextureStats()
S32 current_discard = getDiscardLevel();
if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0)
{
+ if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage)
+ {
+ //needs to release texture memory urgently
+ scaleDown() ;
+ }
// Limit the amount of GL memory bound each frame
- if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
+ else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
{
scaleDown() ;
@@ -3101,9 +3242,16 @@ void LLViewerLODTexture::processTextureStats()
{
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ;
}
+ else if(LLPipeline::sMemAllocationThrottled)//release memory of large textures by decrease their resolutions.
+ {
+ if(scaleDown())
+ {
+ mDesiredDiscardLevel = mCachedRawDiscardLevel ;
+ }
+ }
}
-void LLViewerLODTexture::scaleDown()
+bool LLViewerLODTexture::scaleDown()
{
if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
{
@@ -3114,7 +3262,10 @@ void LLViewerLODTexture::scaleDown()
{
tester->setStablizingTime() ;
}
+
+ return true ;
}
+ return false ;
}
//----------------------------------------------------------------------------------------------
//end of LLViewerLODTexture
@@ -3193,10 +3344,14 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
sMediaMap.insert(std::make_pair(id, this));
mGLTexturep = gl_image ;
+
if(mGLTexturep.isNull())
{
generateGLTexture() ;
}
+
+ mGLTexturep->setAllowCompression(false);
+
mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
mIsPlaying = FALSE ;