summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorruslantproductengine <ruslantproductengine@lindenlab.com>2017-01-24 15:56:25 +0200
committerruslantproductengine <ruslantproductengine@lindenlab.com>2017-01-24 15:56:25 +0200
commit6770c27321cf674af57c45ffee6faf09db788a6d (patch)
tree7fe838baabaea1da6cb188e9a7b933e527154cfb /indra/newview
parent65161e6b393a6df6fa0a932aeb940fb7ac7ea084 (diff)
MAINT-6645 - Improvement - Agents that render as jelly dolls should have their attachments render at 0 LoD to prevent loading higher LoD complexity in memory thus deterring crashes.
Comments: - Fix based on "RenderAutoMuteByteLimit" setting. - File indra/llxml/llcontrol.h - add all signals to 0 group. It garanty that handlers (in indra/newview/llviewercontrol.cpp) will be called last.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml4
-rw-r--r--indra/newview/lldrawable.cpp23
-rw-r--r--indra/newview/lldrawable.h3
-rw-r--r--indra/newview/llface.cpp15
-rw-r--r--indra/newview/llmeshrepository.cpp2
-rw-r--r--indra/newview/llspatialpartition.h2
-rw-r--r--indra/newview/llviewercontrol.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp8
-rw-r--r--indra/newview/llviewerobject.h1
-rw-r--r--indra/newview/llvovolume.cpp215
-rw-r--r--indra/newview/llvovolume.h92
-rw-r--r--indra/newview/pipeline.cpp6
12 files changed, 352 insertions, 23 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 63fa93df02..7c3867bdfb 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10169,9 +10169,9 @@
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
- <string>OBSOLETE and UNUSED.</string>
+ <string>If avatar attachment size exceed this value (in bytes) attachment will not be rendered. Excludes attachments worn by own avatar.</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 3bb2c45a24..aa67ea2524 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -50,6 +50,7 @@
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llvocache.h"
+#include "lldrawpoolavatar.h"
const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;
const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
@@ -143,6 +144,28 @@ void LLDrawable::init(bool new_entry)
initVisible(sCurVisible - 2);//invisible for the current frame and the last frame.
}
+void LLDrawable::unload()
+{
+ LLVOVolume *pVVol = getVOVolume();
+ pVVol->setNoLOD();
+
+ for (S32 i = 0; i < getNumFaces(); i++)
+ {
+ LLFace* facep = getFace(i);
+ if (facep->isState(LLFace::RIGGED))
+ {
+ LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool();
+ if (pool) {
+ pool->removeRiggedFace(facep);
+ }
+ facep->setVertexBuffer(NULL);
+ }
+ facep->clearState(LLFace::RIGGED);
+ }
+
+ pVVol->markForUpdate(TRUE);
+}
+
// static
void LLDrawable::initClass()
{
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index a3461d4c01..14d782d6f2 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -84,6 +84,7 @@ public:
void markDead(); // Mark this drawable as dead
BOOL isDead() const { return isState(DEAD); }
BOOL isNew() const { return !isState(BUILT); }
+ BOOL isUnload() const { return isState(FOR_UNLOAD); }
BOOL isLight() const;
@@ -141,6 +142,7 @@ public:
void mergeFaces(LLDrawable* src);
void init(bool new_entry);
+ void unload();
void destroy();
void update();
@@ -282,6 +284,7 @@ public:
PARTITION_MOVE = 0x10000000,
ANIMATED_CHILD = 0x20000000,
ACTIVE_CHILD = 0x40000000,
+ FOR_UNLOAD = 0x80000000, //should be unload from memory
} EDrawableFlags;
public:
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 50a4925c37..51bb2e3087 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -2650,12 +2650,27 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const
void LLFace::setVertexBuffer(LLVertexBuffer* buffer)
{
+ if (buffer)
+ {
+ LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize());
+ }
+
+ if (mVertexBuffer)
+ {
+ LLSculptIDSize::instance().dec(mDrawablep);
+ }
+
mVertexBuffer = buffer;
llassert(verify());
}
void LLFace::clearVertexBuffer()
{
+ if (mVertexBuffer)
+ {
+ LLSculptIDSize::instance().dec(mDrawablep);
+ }
+
mVertexBuffer = NULL;
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index df708013fc..9edffea1c1 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -3945,7 +3945,7 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
{
- if (mThread && mesh_id.notNull())
+ if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod)
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 7633e46200..f7bcce6daf 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -646,7 +646,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
virtual void rebuildGeom(LLSpatialGroup* group);
virtual void rebuildMesh(LLSpatialGroup* group);
virtual void getGeometry(LLSpatialGroup* group);
- void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
+ U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
private:
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index d9d66ef254..3280aa718d 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -582,6 +582,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)
return true;
}
+void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value);
////////////////////////////////////////////////////////////////////////////
void settings_setup_listeners()
@@ -734,7 +735,8 @@ void settings_setup_listeners()
gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));
gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));
gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged));
- gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2));
+ gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2));
+ gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2));
}
#if TEST_CACHED_CONTROL
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 6c2d4d7fea..293df89bf0 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5868,6 +5868,14 @@ void LLViewerObject::markForUpdate(BOOL priority)
}
}
+void LLViewerObject::markForUnload(BOOL priority)
+{
+ if (mDrawable.notNull())
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::FOR_UNLOAD, priority);
+ }
+}
+
bool LLViewerObject::isPermanentEnforced() const
{
return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike();
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 7a490f6957..e4224a79d1 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -412,6 +412,7 @@ public:
void clearIcon();
void markForUpdate(BOOL priority);
+ void markForUnload(BOOL priority);
void updateVolume(const LLVolumeParams& volume_params);
virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max);
virtual F32 getBinRadius();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 9c77a76683..5292eb7067 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -249,6 +249,8 @@ void LLVOVolume::markDead()
{
if (!mDead)
{
+ LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID());
+
if(getMDCImplCount() > 0)
{
LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
@@ -951,13 +953,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
// if it's a mesh
if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{ //meshes might not have all LODs, get the force detail to best existing LOD
- LLUUID mesh_id = volume_params.getSculptID();
-
- lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
- if (lod == -1)
+ if (NO_LOD != lod)
{
- is404 = TRUE;
- lod = 0;
+ lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
+ if (lod == -1)
+ {
+ is404 = TRUE;
+ lod = 0;
+ }
}
}
}
@@ -4652,10 +4655,79 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)
return NULL;
}
-void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
+void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
{
-
+ static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
+
+ if (0 != render_auto_mute_byte_limit)
+ {
+ //for unload
+ LLSculptIDSize::container_BY_SIZE_view::iterator
+ itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().lower_bound(render_auto_mute_byte_limit),
+ itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end();
+
+ for (; itL != itU; ++itL)
+ {
+ const LLSculptIDSize::Info &nfo = *itL;
+ LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+ if (pVVol
+ && !pVVol->isDead()
+ && pVVol->isAttachment()
+ && !pVVol->getAvatar()->isSelf()
+ && LLVOVolume::NO_LOD != pVVol->getLOD()
+ )
+ {
+ //postponed
+ pVVol->markForUnload();
+ }
+ }
+
+ //for load if it was unload
+ itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin();
+ itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().upper_bound(render_auto_mute_byte_limit);
+
+ for (; itL != itU; ++itL)
+ {
+ const LLSculptIDSize::Info &nfo = *itL;
+ LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+ if (pVVol
+ && !pVVol->isDead()
+ && pVVol->isAttachment()
+ && !pVVol->getAvatar()->isSelf()
+ && LLVOVolume::NO_LOD == pVVol->getLOD()
+ )
+ {
+ pVVol->updateLOD();
+ pVVol->markForUpdate(TRUE);
+ }
+ }
+ }
+ else
+ {
+ LLSculptIDSize::container_BY_SIZE_view::iterator
+ itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(),
+ itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end();
+
+ for (; itL != itU; ++itL)
+ {
+ const LLSculptIDSize::Info &nfo = *itL;
+ LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume();
+ if (pVVol
+ && !pVVol->isDead()
+ && pVVol->isAttachment()
+ && !pVVol->getAvatar()->isSelf()
+ && LLVOVolume::NO_LOD == pVVol->getLOD()
+ )
+ {
+ pVVol->updateLOD();
+ pVVol->markForUpdate(TRUE);
+ }
+ }
+ }
+}
+void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
+{
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -5216,13 +5288,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
}
- genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
- genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
- genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
- genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
- genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
- genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
- genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
+ group->mGeometryBytes = 0;
+
+ U32 geometryBytes = 0;
+
+ geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
+ geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
+ geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
+ geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
+
+ group->mGeometryBytes = geometryBytes;
if (!LLPipeline::sDelayVBUpdate)
{
@@ -5412,10 +5490,11 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB");
-void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
+U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
{
LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO);
+ U32 geometryBytes = 0;
U32 buffer_usage = group->mBufferUsage;
static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
@@ -5665,7 +5744,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
if (buffer)
{
- group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize();
+ geometryBytes += buffer->getSize() + buffer->getIndicesSize();
buffer_map[mask][*face_iter].push_back(buffer);
}
@@ -6021,6 +6100,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
{
group->mBufferMap[mask][i->first] = i->second;
}
+
+ return geometryBytes;
}
void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
@@ -6088,3 +6169,103 @@ void LLHUDPartition::shift(const LLVector4a &offset)
//HUD objects don't shift with region crossing. That would be silly.
}
+
+//...........
+
+void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ }
+
+void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz)
+{
+ llassert(sz >= 0);
+
+ if (!pdrawable) return;
+ LLVOVolume* vvol = pdrawable->getVOVolume();
+ if (!vvol) return;
+ if (!vvol->isAttachment()) return;
+ if (!vvol->getAvatar()) return;
+ if (vvol->getAvatar()->isSelf()) return;
+ LLVolume *vol = vvol->getVolume();
+ if (!vol) return;
+
+ const LLUUID &sculptId = vol->getParams().getSculptID();
+
+ unsigned int total_size = 0;
+
+ typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t;
+
+ pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
+ if (itLU.first == itLU.second)
+ { //register
+ llassert(m_size_info.get<tag_BY_DRAWABLE>().end() == m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable));
+ m_size_info.get<tag_BY_DRAWABLE>().insert(Info( pdrawable, sz, boost::make_shared<SizeInfo>(sz), sculptId ));
+ total_size = sz;
+ }
+ else
+ { //update + register
+ Info &nfo = const_cast<Info &>(*itLU.first);
+ //calc new size
+ total_size = nfo.getTotalSize() + sz;
+ nfo.m_p_size_info->m_size = total_size;
+ nfo.m_size = sz;
+ //update size for all LLDrwable in range of sculptId
+ for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it)
+ {
+ m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
+ }
+
+ //trying insert the LLDrawable
+ m_size_info.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.m_p_size_info, sculptId));
+ }
+
+ static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
+
+ if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit)
+ {
+ pair_iter_iter_t it_eqr = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
+ for (; it_eqr.first != it_eqr.second; ++it_eqr.first)
+ {
+ const Info &i = *it_eqr.first;
+ LLVOVolume *pVVol = i.m_p_drawable->getVOVolume();
+ if (pVVol
+ && !pVVol->isDead()
+ && pVVol->isAttachment()
+ && !pVVol->getAvatar()->isSelf()
+ && LLVOVolume::NO_LOD != pVVol->getLOD()
+ )
+ {
+ //immediately
+ const_cast<LLDrawable*>(i.m_p_drawable)->unload();
+ }
+ }
+ }
+}
+
+void LLSculptIDSize::dec(const LLDrawable *pdrawable)
+{
+ container_BY_DRAWABLE_view::iterator it = m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable);
+ if (m_size_info.get<tag_BY_DRAWABLE>().end() == it) return;
+
+ unsigned int size = it->getTotalSize() - it->getSize();
+
+ if (0 == size)
+ {
+ m_size_info.get<tag_BY_SCULPT_ID>().erase(it->getSculptId());
+ }
+ else
+ {
+ Info &nfo = const_cast<Info &>(*it);
+ nfo.m_size = 0;
+ typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t;
+ pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId());
+ it->m_p_size_info->m_size = size;
+ for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it)
+ {
+ m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
+ }
+ }
+}
+
+void LLSculptIDSize::rem(LLUUID sculptId)
+{
+ m_size_info.get<tag_BY_SCULPT_ID>().erase(sculptId);
+}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 3b68d61ee9..3ae9ac5325 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -35,6 +35,12 @@
#include "m3math.h" // LLMatrix3
#include "m4math.h" // LLMatrix4
#include <map>
+#include <set>
+//boost
+#include "boost/multi_index_container.hpp"
+#include "boost/multi_index/ordered_index.hpp"
+#include "boost/multi_index/mem_fun.hpp"
+
class LLViewerTextureAnim;
class LLDrawPool;
@@ -125,7 +131,8 @@ public:
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
/*virtual*/ BOOL setParent(LLViewerObject* parent);
- S32 getLOD() const { return mLOD; }
+ S32 getLOD() const { return mLOD; }
+ void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; }
const LLVector3 getPivotPositionAgent() const;
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
@@ -160,6 +167,7 @@ public:
const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
void markForUpdate(BOOL priority) { LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; }
+ void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; }
void faceMappingChanged() { mFaceMappingChanged=TRUE; };
/*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts
@@ -410,5 +418,87 @@ private:
};
+//...........
+
+class LLSculptIDSize
+{
+public:
+ struct SizeInfo
+ {
+ SizeInfo(int size) : m_size(size) {}
+ unsigned int m_size;
+ };
+
+ struct Info
+ {
+ typedef boost::shared_ptr<SizeInfo> PtrSizeInfo;
+
+ Info(const LLDrawable *pdrawable, int size, PtrSizeInfo psize_info, LLUUID sculpt_id)
+ : m_p_drawable(pdrawable)
+ , m_size(size)
+ , m_p_size_info(psize_info)
+ , m_sculpt_id(sculpt_id)
+ {}
+
+ const LLDrawable *m_p_drawable;
+ unsigned int m_size;
+ PtrSizeInfo m_p_size_info;
+ LLUUID m_sculpt_id;
+
+ inline const LLDrawable* getPtrLLDrawable() const { return m_p_drawable; }
+ inline unsigned int getSize() const { return m_size; }
+ inline unsigned int getTotalSize() const { return m_p_size_info->m_size; }
+ inline LLUUID getSculptId() const { return m_sculpt_id; }
+ PtrSizeInfo getSizeInfo() { return m_p_size_info; }
+ };
+
+public:
+ //tags
+ struct tag_BY_DRAWABLE {};
+ struct tag_BY_SCULPT_ID {};
+ struct tag_BY_SIZE {};
+
+ //container
+ typedef boost::multi_index_container <
+ Info,
+ boost::multi_index::indexed_by <
+ boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE>
+ , boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable>
+ >
+ , boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID>
+ , boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId>
+ >
+ , boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SIZE>
+ , boost::multi_index::const_mem_fun<Info, unsigned int, &Info::getTotalSize>
+ >
+ >
+ > container;
+
+ //views
+ typedef container::template index<tag_BY_DRAWABLE>::type container_BY_DRAWABLE_view;
+ typedef container::template index<tag_BY_SCULPT_ID>::type container_BY_SCULPT_ID_view;
+ typedef container::template index<tag_BY_SIZE>::type container_BY_SIZE_view;
+
+private:
+ LLSculptIDSize()
+ {}
+
+public:
+ static LLSculptIDSize & instance() {
+ static LLSculptIDSize inst;
+ return inst;
+ }
+
+public:
+ void inc(const LLDrawable *pdrawable, int sz);
+ void dec(const LLDrawable *pdrawable);
+ void rem(LLUUID sculptId);
+
+ const container & getSizeInfo() const { return m_size_info; }
+
+private:
+ container m_size_info;
+};
+
#endif // LL_LLVOVOLUME_H
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 1777fcc0f2..205585b34e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3031,6 +3031,12 @@ void LLPipeline::updateGeom(F32 max_dtime)
}
}
+ if (drawablep->isUnload())
+ {
+ drawablep->unload();
+ drawablep->clearState(LLDrawable::FOR_UNLOAD);
+ }
+
if (updateDrawableGeom(drawablep, TRUE))
{
drawablep->clearState(LLDrawable::IN_REBUILD_Q1);