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.cpp240
1 files changed, 231 insertions, 9 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index ec82f62a8b..e3d657068f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -60,6 +60,8 @@
#include "llviewercontrol.h"
#include "pipeline.h"
#include "llappviewer.h"
+#include "lltextureatlas.h"
+#include "lltextureatlasmanager.h"
///////////////////////////////////////////////////////////////////////////////
// statics
@@ -83,6 +85,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
BOOL LLViewerTexture::sDontLoadVolumeTextures = FALSE;
+BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
@@ -244,7 +247,7 @@ void LLViewerTextureManager::init()
LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
#if 1
- LLPointer<LLViewerFetchedTexture> imagep = new LLViewerFetchedTexture(IMG_DEFAULT, TRUE);
+ LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
LLViewerFetchedTexture::sDefaultImagep = imagep;
const S32 dim = 128;
@@ -273,7 +276,6 @@ void LLViewerTextureManager::init()
}
imagep->createGLTexture(0, image_raw);
image_raw = NULL;
- gTextureList.addImage(imagep);
LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
#else
LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
@@ -369,6 +371,7 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
}
}
sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
+ LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
}
//end of static functions
@@ -668,7 +671,7 @@ LLGLuint LLViewerTexture::getTexName() const
return mGLTexturep->getTexName() ;
}
-BOOL LLViewerTexture::hasValidGLTexture() const
+BOOL LLViewerTexture::hasGLTexture() const
{
if(mGLTexturep.notNull())
{
@@ -677,11 +680,6 @@ BOOL LLViewerTexture::hasValidGLTexture() const
return FALSE ;
}
-BOOL LLViewerTexture::hasGLTexture() const
-{
- return mGLTexturep.notNull() ;
-}
-
BOOL LLViewerTexture::getBoundRecently() const
{
if(mGLTexturep.notNull())
@@ -780,6 +778,34 @@ BOOL LLViewerTexture::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool
return mGLTexturep->readBackRaw(discard_level, imageraw, compressed_ok) ;
}
+U32 LLViewerTexture::getTexelsInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInAtlas() ;
+}
+
+U32 LLViewerTexture::getTexelsInGLTexture() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInGLTexture() ;
+}
+
+BOOL LLViewerTexture::isGLTextureCreated() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isGLTextureCreated() ;
+}
+
+S32 LLViewerTexture::getDiscardLevelInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getDiscardLevelInAtlas() ;
+}
+
void LLViewerTexture::destroyGLTexture()
{
if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
@@ -797,6 +823,7 @@ void LLViewerTexture::updateBindStatsForTester()
LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
}
}
+
//----------------------------------------------------------------------------------------------
//end of LLViewerTexture
//----------------------------------------------------------------------------------------------
@@ -1045,7 +1072,11 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
return FALSE;
}
- res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename);
+ if(!(res = insertToAtlas()))
+ {
+ res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename);
+ resetFaceAtlas() ;
+ }
setActive() ;
}
@@ -1742,6 +1773,197 @@ void LLViewerFetchedTexture::destroyRawImage()
mIsRawImageValid = FALSE;
mRawDiscardLevel = INVALID_DISCARD_LEVEL;
}
+
+//----------------------------------------------------------------------------------------------
+//atlasing
+//----------------------------------------------------------------------------------------------
+void LLViewerFetchedTexture::resetFaceAtlas()
+{
+ //Nothing should be done here.
+}
+
+//invalidate all atlas slots for this image.
+void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom)
+{
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ if(*iter)
+ {
+ LLFace* facep = (LLFace*)*iter ;
+ facep->removeAtlas() ;
+ if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup())
+ {
+ facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY);
+ }
+ }
+ }
+}
+
+BOOL LLViewerFetchedTexture::insertToAtlas()
+{
+ if(!LLViewerTexture::sUseTextureAtlas)
+ {
+ return FALSE ;
+ }
+ if(mFaceList.size() < 1)
+ {
+ return FALSE ;
+ }
+ if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas())
+ {
+ return FALSE ;
+ }
+ if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget()))
+ {
+ return FALSE ;
+ }
+
+ BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image.
+ S32 raw_w = mRawImage->getWidth() ;
+ S32 raw_h = mRawImage->getHeight() ;
+ F32 xscale = 1.0f, yscale = 1.0f ;
+ LLPointer<LLTextureAtlasSlot> slot_infop;
+ LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer.
+ LLSpatialGroup* groupp ;
+ LLFace* facep;
+
+ //if the atlas slot pointers for some faces are null, process them later.
+ ll_face_list_t waiting_list ;
+
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ if(*iter)
+ {
+ facep = (LLFace*)*iter ;
+
+ //face can not use atlas.
+ if(!facep->canUseAtlas())
+ {
+ if(facep->getAtlasInfo())
+ {
+ facep->removeAtlas() ;
+ }
+ ret = FALSE ;
+ continue ;
+ }
+
+ //the atlas slot is updated
+ slot_infop = facep->getAtlasInfo() ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ if(slot_infop)
+ {
+ if(slot_infop->getSpatialGroup() != groupp)
+ {
+ if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ else //do not forget to update slot_infop->getSpatialGroup().
+ {
+ LLSpatialGroup* gp = slot_infop->getSpatialGroup() ;
+ gp->setCurUpdatingTime(gFrameCount) ;
+ gp->setCurUpdatingTexture(this) ;
+ gp->setCurUpdatingSlot(slot_infop) ;
+ }
+ }
+ else //same group
+ {
+ if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated
+ {
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ }
+ }
+ else
+ {
+ //if the slot is null, wait to process them later.
+ waiting_list.push_back(facep) ;
+ continue ;
+ }
+
+ //----------
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ //invalidateAtlas();
+ return FALSE ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //update spatial group atlas info
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+ }
+
+ //process the waiting_list
+ for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter)
+ {
+ facep = (LLFace*)*iter ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ //check if this texture already inserted to atlas for this group
+ if((cur_slotp = groupp->getCurUpdatingSlot(this)))
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+
+ //need to reserve a slot from atlas
+ slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ;
+
+ facep->setAtlasInfo(slot_infop) ;
+
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //slot allocation failed.
+ if(!slot_infop || !slot_infop->getAtlas())
+ {
+ ret = FALSE ;
+ facep->setAtlasInUse(FALSE) ;
+ continue ;
+ }
+
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ ret = FALSE ;
+ //invalidateAtlas();
+ break ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+
+ return ret ;
+}
+
//----------------------------------------------------------------------------------------------
//end of LLViewerFetchedTexture
//----------------------------------------------------------------------------------------------