From 8431725c0bf08da2b909cefe2f3ecfb43a2aecad Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Mon, 4 Apr 2011 23:01:06 -0700 Subject: Ported the GPL version of Zwagoth Klaar's fix for sculpty crashers. This has two major side effects: 1. instead of crashing on bad sculpt data, the viewer freezes for a time. 2. Sculpties can be slow to build --- linden/indra/llmath/llvolume.h | 4 +- linden/indra/newview/llhudtext.cpp | 15 +++++++ linden/indra/newview/llhudtext.h | 1 + linden/indra/newview/llviewerobject.cpp | 13 +++++- linden/indra/newview/llviewerobject.h | 2 + linden/indra/newview/llvovolume.cpp | 77 +++++++++++++++------------------ linden/indra/newview/llvovolume.h | 2 +- linden/indra/newview/pipeline.cpp | 5 ++- linden/indra/newview/pipeline.h | 2 + 9 files changed, 73 insertions(+), 48 deletions(-) diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h index 0b9002f..77af2c4 100644 --- a/linden/indra/llmath/llvolume.h +++ b/linden/indra/llmath/llvolume.h @@ -949,9 +949,11 @@ public: LLVector3 mLODScaleBias; // vector for biasing LOD based on scale void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); + + F32 sculptGetSurfaceArea(); + private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); - F32 sculptGetSurfaceArea(); void sculptGeneratePlaceholder(); void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t); diff --git a/linden/indra/newview/llhudtext.cpp b/linden/indra/newview/llhudtext.cpp index 7c0c469..457249f 100644 --- a/linden/indra/newview/llhudtext.cpp +++ b/linden/indra/newview/llhudtext.cpp @@ -723,6 +723,21 @@ void LLHUDText::setDoFade(const BOOL do_fade) mDoFade = do_fade; } +std::string LLHUDText::getStringUTF8() +{ + std::string out(""); + int t = mTextSegments.size(); + int i = 0; + for (std::vector::iterator segment_iter = mTextSegments.begin(); + segment_iter != mTextSegments.end(); ++segment_iter ) + { + out.append(wstring_to_utf8str((*segment_iter).getText())); + i++; + if(i < t) out.append("\n"); + } + return out; +} + void LLHUDText::updateVisibility() { if (mSourceObject) diff --git a/linden/indra/newview/llhudtext.h b/linden/indra/newview/llhudtext.h index 297e4d5..fbe984f 100644 --- a/linden/indra/newview/llhudtext.h +++ b/linden/indra/newview/llhudtext.h @@ -103,6 +103,7 @@ public: void setZCompare(const BOOL zcompare); void setDoFade(const BOOL do_fade); void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; } + std::string getStringUTF8(); // mMaxLines of -1 means unlimited lines. void setMaxLines(S32 max_lines) { mMaxLines = max_lines; } diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index 58b8490..e622a7f 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -207,7 +207,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mJointInfo(NULL), mState(0), mMedia(NULL), - mClickAction(0) + mClickAction(0), + mSculptSurfaceArea(0.0) { if(!is_global) { @@ -4014,7 +4015,7 @@ LLBBox LLViewerObject::getBoundingBoxAgent() const LLQuaternion rot; LLViewerObject* root_edit = (LLViewerObject*)getRootEdit(); LLViewerObject* avatar_parent = (LLViewerObject*)root_edit->getParent(); - if (avatar_parent && avatar_parent->isAvatar() && root_edit->mDrawable.notNull()) + if (avatar_parent && avatar_parent->isAvatar() && root_edit && root_edit->mDrawable.notNull()) { LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent(); position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); @@ -4112,6 +4113,14 @@ void LLViewerObject::setDebugText(const std::string &utf8text) mText->setDoFade(FALSE); updateText(); } +std::string LLViewerObject::getDebugText() +{ + if(mText) + { + return mText->getStringUTF8(); + } + return ""; +} void LLViewerObject::setIcon(LLViewerImage* icon_image) { diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index 33e8da2..9b05470 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h @@ -353,6 +353,7 @@ public: void setCanSelect(BOOL canSelect); void setDebugText(const std::string &utf8text); + std::string getDebugText(); void setIcon(LLViewerImage* icon_image); void clearIcon(); @@ -552,6 +553,7 @@ public: LLPointer mIcon; static BOOL sUseSharedDrawables; + F32 mSculptSurfaceArea; protected: // delete an item in the inventory, but don't tell the diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 7aaf845..8666e4a 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -72,6 +72,10 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; +static const F32 sSculptSAThresh = 1750.f; // Surface area at which sculpts are considered for not being rendered +static const F32 sSculptSAMax = 50000.f; // The maximum combined surface area of sculpts(per frame) that are above the + // threshold before they stop being rendered + BOOL gAnimateTextures = TRUE; extern BOOL gHideSelectedObjects; @@ -89,6 +93,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXformInvTrans.setIdentity(); mLOD = MIN_LOD; + mSculptLevel = -2; mTextureAnimp = NULL; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; @@ -502,8 +507,9 @@ void LLVOVolume::updateTextureVirtualSize() if (isSculpted()) { - updateSculptTexture(); - + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + mSculptTexture = gImageList.getImage(id); if (mSculptTexture.notNull()) { mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), @@ -526,22 +532,22 @@ void LLVOVolume::updateTextureVirtualSize() } } - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture - S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture + S32 current_discard = mSculptLevel; if (texture_discard >= 0 && //texture has some data available (texture_discard < current_discard || //texture has more data than last rebuild current_discard < 0)) //no previous rebuild { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + markForUpdate(FALSE); mSculptChanged = TRUE; } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) { - setDebugText(llformat("T%d C%d V%d\n%dx%d", + setDebugText(llformat("T%d C%d V%d\n%dx%d SA%f", texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); + mSculptTexture->getHeight(), mSculptTexture->getWidth(), mSculptSurfaceArea)); } } } @@ -681,50 +687,25 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail mVolumeImpl->onSetVolume(volume_params, detail); } - updateSculptTexture(); - if (isSculpted()) { + mSculptTexture = gImageList.getImage(volume_params.getSculptID()); if (mSculptTexture.notNull()) { sculpt(); + mSculptLevel = getVolume()->getSculptLevel(); + mSculptSurfaceArea = getVolume()->sculptGetSurfaceArea(); } } - - return TRUE; - } - return FALSE; -} - -void LLVOVolume::updateSculptTexture() -{ - LLPointer old_sculpt = mSculptTexture; - - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) + else { - mSculptTexture = gImageList.getImage(id); + mSculptTexture = NULL; + mSculptSurfaceArea = 0.0; } - } - else - { - mSculptTexture = NULL; - } - if (mSculptTexture != old_sculpt) - { - if (old_sculpt.notNull()) - { - old_sculpt->removeVolume(this); - } - if (mSculptTexture.notNull()) - { - mSculptTexture->addVolume(this); - } + return TRUE; } + return FALSE; } // sculpt replaces generate() for sculpted surfaces @@ -737,7 +718,7 @@ void LLVOVolume::sculpt() S8 sculpt_components = 0; const U8* sculpt_data = NULL; - S32 discard_level = mSculptTexture->getDiscardLevel(); + S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; S32 max_discard = mSculptTexture->getMaxDiscardLevel(); @@ -781,7 +762,7 @@ void LLVOVolume::sculpt() } getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); - //notify rebuild any other VOVolumes that reference this sculpty volume + /*//notify rebuild any other VOVolumes that reference this sculpty volume for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) { LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i]; @@ -789,7 +770,7 @@ void LLVOVolume::sculpt() { gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); } - } + }*/ } } @@ -2298,6 +2279,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } LLVOVolume* vobj = drawablep->getVOVolume(); + + if (vobj->mSculptSurfaceArea > sSculptSAThresh) + { + LLPipeline::sSculptSurfaceAreaFrame += vobj->mSculptSurfaceArea; + if(LLPipeline::sSculptSurfaceAreaFrame > sSculptSAMax) + { + continue; + } + } + llassert_always(vobj); vobj->updateTextureVirtualSize(); vobj->preRebuild(); diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index 7c8a68d..7fba28c 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h @@ -171,7 +171,6 @@ public: void setTexture(const S32 face); S32 getIndexInTex() const {return mIndexInTex ;} /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); - void updateSculptTexture(); void setIndexInTex(S32 index) { mIndexInTex = index ;} void sculpt(); void updateRelativeXform(); @@ -233,6 +232,7 @@ private: LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; + S32 mSculptLevel; BOOL mSculptChanged; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index 5458af5..ae0e605 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp @@ -257,7 +257,8 @@ BOOL LLPipeline::sRenderFrameTest = FALSE; BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; BOOL LLPipeline::sRenderDeferred = FALSE; -S32 LLPipeline::sVisibleLightCount = 0; +S32 LLPipeline::sVisibleLightCount = 0; +F32 LLPipeline::sSculptSurfaceAreaFrame = 0.0; static LLCullResult* sCull = NULL; @@ -2198,6 +2199,8 @@ void LLPipeline::postSort(LLCamera& camera) LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT); assertInitialized(); + + sSculptSurfaceAreaFrame = 0.0; //rebuild drawable geometry for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) diff --git a/linden/indra/newview/pipeline.h b/linden/indra/newview/pipeline.h index 1ecb56e..2252fbd 100644 --- a/linden/indra/newview/pipeline.h +++ b/linden/indra/newview/pipeline.h @@ -579,6 +579,8 @@ protected: public: static BOOL sRenderBeacons; static BOOL sRenderHighlight; + static F32 sSculptSurfaceAreaFrame; + }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.1