diff options
24 files changed, 243 insertions, 58 deletions
| diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 66b3c2bd25..0d0b85ba60 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -214,8 +214,10 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)  	target = target * target_dist;  	if (!target.isFinite())  	{ -		llerrs << "Non finite target in editing motion with target distance of " << target_dist <<  +		// Don't error out here, set a fail-safe target vector +		llwarns << "Non finite target in editing motion with target distance of " << target_dist <<   			" and focus point " << focus_pt << llendl; +		target.setVec(1.f, 1.f, 1.f);  	}  	mTarget.setPosition( target + mParentJoint.getPosition()); diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index fa0eb9f72c..0c32679744 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -47,7 +47,8 @@ std::string ll_safe_string(const char* in)  std::string ll_safe_string(const char* in, S32 maxlen)  { -	if(in) return std::string(in, maxlen); +	if(in && maxlen > 0 ) return std::string(in, maxlen); +  	return std::string();  } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 964495a3ab..d70e764769 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -424,6 +424,10 @@ const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000;  //1 ms  class LLGLFence  {  public: +	virtual ~LLGLFence() +	{ +	} +  	virtual void placeFence() = 0;  	virtual bool isCompleted() = 0;  	virtual void wait() = 0; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index cc5c232380..846311a8d0 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -163,10 +163,19 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  	}  	U32 offset = mTex.size(); -	if (offset >= 4 || -		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) + +	if( offset >= 4 )  	{ -		llerrs << "Too many color attachments!" << llendl; +		llwarns << "Too many color attachments" << llendl; +		llassert( offset < 4 ); +		return false; +	} +	if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) ) +	{ +		llwarns << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << llendl; +		llassert(  mFBO != 0 ); +		llassert( gGLManager.mHasDrawBuffers ); +		return false;  	}  	U32 tex; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index eadef93c89..2fe0aa0b72 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -555,8 +555,21 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con  	gGL.syncMatrices();  	U32 count = pos.size(); -	llassert_always(norm.size() >= pos.size()); -	llassert_always(count > 0); +	 +	llassert(norm.size() >= pos.size()); +	llassert(count > 0); + +	if( count == 0 ) +	{ +		llwarns << "Called drawArrays with 0 vertices" << llendl; +		return; +	} + +	if( norm.size() < pos.size() ) +	{ +		llwarns << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << llendl; +		return; +	}  	unbind(); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 447836910d..11fa50b51a 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4045,6 +4045,12 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)  void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)  {  	LLViewerRegion* regionp = getRegion(); + +	if (!regionp) +	{ +		return; +	} +  	U64 handle = to_region_handle(pos_global);  	LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);  	if(regionp && info) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6d67e098a6..06a9892c7e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -52,7 +52,8 @@  std::string self_av_string()  { -	return gAgentAvatarp->avString(); +	// On logout gAgentAvatarp can already be invalid +	return isAgentAvatarValid() ? gAgentAvatarp->avString() : "";  }  // RAII thingy to guarantee that a variable gets reset when the Setter diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index c9543988a6..ea0b8f00a4 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -62,6 +62,12 @@ void LLAttachmentsMgr::onIdle(void *)  void LLAttachmentsMgr::onIdle()  { +	// Make sure we got a region before trying anything else +	if( !gAgent.getRegion() ) +	{ +		return; +	} +  	S32 obj_count = mPendingAttachments.size();  	if (obj_count == 0)  	{ diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index caf15fe1cb..b5faff7968 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -192,14 +192,18 @@ void LLDrawPoolWLSky::renderStars(void) const  	bool error;  	LLColor4 star_alpha(LLColor4::black);  	star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f; -	llassert_always(!error); + +	// If start_brightness is not set, exit +	if( error ) +	{ +		llwarns << "star_brightness missing in mCurParams" << llendl; +		return; +	}  	gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex());  	gGL.pushMatrix();  	gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); -	// gl_FragColor.rgb = gl_Color.rgb; -	// gl_FragColor.a = gl_Color.a * star_alpha.a;  	if (LLGLSLShader::sNoFixedFunction)  	{  		gCustomAlphaProgram.bind(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 188f943f13..605cb81c10 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1062,7 +1062,11 @@ bool LLFace::canRenderAsMask()  	}  	const LLTextureEntry* te = getTextureEntry(); - +	if( !te || !getViewerObject() || !getTexture() ) +	{ +		return false; +	} +	  	if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha  		(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask  		getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index fa0ad20fdb..62848586cd 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -422,13 +422,14 @@ void LLFloaterBvhPreview::resetMotion()  	LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();  	BOOL paused = avatarp->areAnimationsPaused(); -	// *TODO: Fix awful casting hack -	LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); -	 -	// Set emotion -	std::string emote = getChild<LLUICtrl>("emote_combo")->getValue().asString(); -	motionp->setEmote(mIDList[emote]); -	 +	LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*>(avatarp->findMotion(mMotionID)); +	if( motionp ) +	{ +		// Set emotion +		std::string emote = getChild<LLUICtrl>("emote_combo")->getValue().asString(); +		motionp->setEmote(mIDList[emote]); +	} +  	LLUUID base_id = mIDList[getChild<LLUICtrl>("preview_base_anim")->getValue().asString()];  	avatarp->deactivateAllMotions();  	avatarp->startMotion(mMotionID, 0.0f); @@ -438,8 +439,12 @@ void LLFloaterBvhPreview::resetMotion()  	// Set pose  	std::string handpose = getChild<LLUICtrl>("hand_pose_combo")->getValue().asString();  	avatarp->startMotion( ANIM_AGENT_HAND_MOTION, 0.0f ); -	motionp->setHandPose(LLHandMotion::getHandPose(handpose)); +	if( motionp ) +	{ +		motionp->setHandPose(LLHandMotion::getHandPose(handpose)); +	} +	  	if (paused)  	{  		mPauseRequest = avatarp->requestPause(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fce0b7c9c9..14a228df1c 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2577,14 +2577,23 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)  		LLInventoryModel::item_array_t* item_array;  		gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array); -		S32 item_count = item_array->count(); -		S32 cat_count = cat_array->count(); -	 +		S32 item_count(0); +		if( item_array ) +		{			 +			item_count = item_array->count(); +		} +		 +		S32 cat_count(0); +		if( cat_array ) +		{			 +			cat_count = cat_array->count(); +		} +  		// Move to next if current folder empty  		if ((item_count == 0) && (cat_count == 0)) -	{ +		{  			continue; -	} +		}  		uuid_vec_t ids;  		LLRightClickInventoryFetchObserver* outfit = NULL; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index bc7f522848..ba0a590910 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1097,11 +1097,13 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  			mMeshHeader[mesh_id] = header;  			} + +		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. +  		//check for pending requests  		pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);  		if (iter != mPendingLOD.end())  		{ -			LLMutexLock lock(mMutex);  			for (U32 i = 0; i < iter->second.size(); ++i)  			{  				LODRequest req(mesh_params, iter->second[i]); @@ -1796,7 +1798,12 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { - +	// thread could have already be destroyed during logout +	if( !gMeshRepo.mThread ) +	{ +		return; +	} +	  	S32 data_size = buffer->countAfter(channels.in(), NULL);  	if (status < 200 || status > 400) @@ -1851,6 +1858,12 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { +	// thread could have already be destroyed during logout +	if( !gMeshRepo.mThread ) +	{ +		return; +	} +  	S32 data_size = buffer->countAfter(channels.in(), NULL);  	if (status < 200 || status > 400) @@ -1905,6 +1918,11 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { +	if( !gMeshRepo.mThread ) +	{ +		return; +	} +  	S32 data_size = buffer->countAfter(channels.in(), NULL);  	if (status < 200 || status > 400) @@ -1959,6 +1977,12 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { +	// thread could have already be destroyed during logout +	if( !gMeshRepo.mThread ) +	{ +		return; +	} +  	S32 data_size = buffer->countAfter(channels.in(), NULL);  	if (status < 200 || status > 400) @@ -2013,6 +2037,12 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { +	// thread could have already be destroyed during logout +	if( !gMeshRepo.mThread ) +	{ +		return; +	} +  	if (status < 200 || status > 400)  	{  		//llwarns diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index f792f53ac5..3d8150eed3 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -97,6 +97,13 @@ bool LLNotificationManager::onNotification(const LLSD& notify)  {  	LLSysHandler* handle = NULL; +	// Don't bother if we're going down. +	// Otherwise we might crash when trying to use handlers that are already dead. +	if( LLApp::isExiting() ) +	{ +		return false; +	} +  	if (LLNotifications::destroyed())  		return false; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index d58d6d536c..d42056ef9d 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -835,11 +835,11 @@ BOOL LLPanelEditWearable::isDirty() const          BOOL isDirty = FALSE;          if (mWearablePtr)          { -                if (mWearablePtr->isDirty() || -                        mWearableItem->getName().compare(mNameEditor->getText()) != 0) -                { -                        isDirty = TRUE; -                } +			if (mWearablePtr->isDirty() || +				( mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0 )) +			{ +				isDirty = TRUE; +			}          }          return isDirty;  } diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 18626e3273..04934b13f1 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -464,7 +464,9 @@ LLMultiPreview::LLMultiPreview()  void LLMultiPreview::onOpen(const LLSD& key)  { -	LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); +	// Floater could be something else than LLPreview, eg LLFloaterProfile. +	LLPreview* frontmost_preview = dynamic_cast<LLPreview*>(mTabContainer->getCurrentPanel()); +  	if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)  	{  		frontmost_preview->loadAsset(); @@ -477,8 +479,13 @@ void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)  {  	if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())  	{ -		LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); -		if (frontmost_preview) frontmost_preview->userResized(); +		// Floater could be something else than LLPreview, eg LLFloaterProfile. +		LLPreview* frontmost_preview = dynamic_cast<LLPreview*>(mTabContainer->getCurrentPanel()); + +		if (frontmost_preview) +		{ +			frontmost_preview->userResized(); +		}  	}  	LLFloater::handleReshape(new_rect, by_user);  } @@ -486,7 +493,9 @@ void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)  void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)  { -	LLPreview* opened_preview = (LLPreview*)opened_floater; +	// Floater could be something else than LLPreview, eg LLFloaterProfile. +	LLPreview* opened_preview = dynamic_cast<LLPreview*>(opened_floater); +  	if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)  	{  		opened_preview->loadAsset(); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d340b304ca..d2280ea089 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -571,9 +571,13 @@ void LLScreenChannel::showToastsBottom()  	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); -	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) +	// Use a local variable instead of mToastList. +	// mToastList can be modified during recursive calls and then all iteratos will be invalidated. +	std::vector<ToastElem> vToastList( mToastList ); + +	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)  	{ -		if(it != mToastList.rbegin()) +		if(it != vToastList.rbegin())  		{  			LLToast* toast = (it-1)->getToast();  			if (!toast) @@ -601,7 +605,7 @@ void LLScreenChannel::showToastsBottom()  		if(floater && floater->overlapsScreenChannel())  		{ -			if(it == mToastList.rbegin()) +			if(it == vToastList.rbegin())  			{  				// move first toast above docked floater  				S32 shift = floater->getRect().getHeight(); @@ -624,7 +628,7 @@ void LLScreenChannel::showToastsBottom()  		if(!stop_showing_toasts)  		{ -			if( it != mToastList.rend()-1) +			if( it != vToastList.rend()-1)  			{  				S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap");  				stop_showing_toasts = toast_top > getRect().mTop; @@ -632,7 +636,8 @@ void LLScreenChannel::showToastsBottom()  		}   		// at least one toast should be visible -		if(it == mToastList.rbegin()) + +		if(it == vToastList.rbegin())  		{  			stop_showing_toasts = false;  		} @@ -655,10 +660,11 @@ void LLScreenChannel::showToastsBottom()  	}  	// Dismiss toasts we don't have space for (STORM-391). -	if(it != mToastList.rend()) +	if(it != vToastList.rend())  	{  		mHiddenToastsNum = 0; -		for(; it != mToastList.rend(); it++) + +		for(; it != vToastList.rend(); it++)  		{  			LLToast* toast = it->getToast();  			if (toast) @@ -714,9 +720,13 @@ void LLScreenChannel::showToastsTop()  	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); -	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) +	// Use a local variable instead of mToastList. +	// mToastList can be modified during recursive calls and then all iteratos will be invalidated. +	std::vector<ToastElem> vToastList( mToastList ); + +	for(it = vToastList.rbegin(); it != vToastList.rend(); ++it)  	{ -		if(it != mToastList.rbegin()) +		if(it != vToastList.rbegin())  		{  			LLToast* toast = (it-1)->getToast();  			if (!toast) @@ -744,7 +754,7 @@ void LLScreenChannel::showToastsTop()  		if(floater && floater->overlapsScreenChannel())  		{ -			if(it == mToastList.rbegin()) +			if(it == vToastList.rbegin())  			{  				// move first toast above docked floater  				S32 shift = -floater->getRect().getHeight(); @@ -767,7 +777,7 @@ void LLScreenChannel::showToastsTop()  		if(!stop_showing_toasts)  		{ -			if( it != mToastList.rend()-1) +			if( it != vToastList.rend()-1)  			{  				S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");  				stop_showing_toasts = toast_bottom < channel_rect.mBottom; @@ -775,7 +785,7 @@ void LLScreenChannel::showToastsTop()  		}   		// at least one toast should be visible -		if(it == mToastList.rbegin()) +		if(it == vToastList.rbegin())  		{  			stop_showing_toasts = false;  		} @@ -799,10 +809,12 @@ void LLScreenChannel::showToastsTop()  	// Dismiss toasts we don't have space for (STORM-391).  	std::vector<LLToast*> toasts_to_hide; -	if(it != mToastList.rend()) + +	if(it != vToastList.rend())  	{  		mHiddenToastsNum = 0; -		for(; it != mToastList.rend(); it++) + +		for(; it != vToastList.rend(); it++)  		{  			LLToast* toast = it->getToast();  			if (toast) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8eb8717de2..32cf8cc1b3 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1904,7 +1904,7 @@ void LLViewerFetchedTexture::updateVirtualSize()  	for(U32 i = 0 ; i < mNumFaces ; i++)  	{				  		LLFace* facep = mFaceList[i] ; -		if(facep->getDrawable()->isRecentlyVisible()) +		if( facep && facep->getDrawable() && facep->getDrawable()->isRecentlyVisible())  		{  			addTextureStats(facep->getVirtualSize()) ;  			setAdditionalDecodePriority(facep->getImportanceToCamera()) ; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 366b6004be..627238b0f5 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4421,7 +4421,9 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)  		}  		// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)  		// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); -		if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha) + +		if ( getImage(TEX_HAIR_BAKED, 0) +			&& getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)  		{  			num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);  			first_pass = FALSE; @@ -4565,7 +4567,20 @@ void LLVOAvatar::updateTextures()  		LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index);  		U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);  		const LLTextureEntry *te = getTE(texture_index); -		const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); + +		// getTE can return 0. +		// Not sure yet why it does, but of course it crashes when te->mScale? gets used. +		// Put safeguard in place so this corner case get better handling and does not result in a crash. +		F32 texel_area_ratio = 1.0f; +		if( te ) +		{ +			texel_area_ratio = fabs(te->mScaleS * te->mScaleT); +		} +		else +		{ +			llwarns << "getTE( " << texture_index << " ) returned 0" <<llendl; +		} +  		LLViewerFetchedTexture *imagep = NULL;  		for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)  		{ @@ -8705,6 +8720,12 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index  		return FALSE;  	} +	if( !getImage( te, index ) ) +	{ +		llwarns << "getImage( " << te << ", " << index << " ) returned 0" << llendl; +		return FALSE; +	} +  	return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR &&   			getImage(te, index)->getID() != IMG_DEFAULT);  } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e99898a83c..5d1c335078 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1227,6 +1227,13 @@ BOOL LLVOVolume::calcLOD()  	if (mDrawable->isState(LLDrawable::RIGGED))  	{  		LLVOAvatar* avatar = getAvatar();  +		 +		// Not sure how this can really happen, but alas it does. Better exit here than crashing. +		if( !avatar || !avatar->mDrawable ) +		{ +			return FALSE; +		} +  		distance = avatar->mDrawable->mDistanceWRTCamera;  		radius = avatar->getBinRadius();  	} @@ -1335,7 +1342,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)  void LLVOVolume::updateFaceFlags()  { -	for (S32 i = 0; i < getVolume()->getNumFaces(); i++) +	// There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() +	for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++)  	{  		LLFace *face = mDrawable->getFace(i);  		if (face) @@ -1436,7 +1444,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)  		volume = getVolume();  	} -	for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++) +	// There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() +	for (S32 i = 0; +		 i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); +		 i++)  	{  		LLFace *face = mDrawable->getFace(i);  		if (!face) @@ -1737,6 +1748,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  void LLVOVolume::updateFaceSize(S32 idx)  { +	if( mDrawable->getNumFaces() <= idx ) +	{ +		return; +	} +  	LLFace* facep = mDrawable->getFace(idx);  	if (facep)  	{ @@ -2427,7 +2443,12 @@ void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index)  	//add the face to show the media if it is in playing  	if(mDrawable)  	{ -		LLFace* facep = mDrawable->getFace(texture_index) ; +		LLFace* facep(NULL); +		if( texture_index < mDrawable->getNumFaces() ) +		{ +			facep = mDrawable->getFace(texture_index) ; +		} +  		if(facep)  		{  			LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; @@ -3826,6 +3847,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  			LLVector4a* pos = dst_face.mPositions; +			if( pos && weight && dst_face.mExtents )  			{  				LLFastTimer t(FTM_SKIN_RIGGED); diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 2425b96678..be3e3ff30e 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -105,10 +105,16 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()  		return;  	} -	if (unvalidated_content[0]["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) +	LLUUID regionId; +	if( gAgent.getRegion() ) +	{ +		regionId = gAgent.getRegion()->getRegionID(); +	} +	 +	if (unvalidated_content[0]["regionID"].asUUID() != regionId )  	{  		LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting " -			<< gAgent.getRegion()->getRegionID() << " but got " << unvalidated_content[0]["regionID"].asUUID() +			<< regionId << " but got " << unvalidated_content[0]["regionID"].asUUID()  			<< ") - ignoring..." << LL_ENDL;  		return;  	} diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 678898797f..91dd441319 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2011,6 +2011,7 @@ void LLPipeline::grabReferences(LLCullResult& result)  void LLPipeline::clearReferences()  {  	sCull = NULL; +	mGroupSaveQ1.clear();  }  void check_references(LLSpatialGroup* group, LLDrawable* drawable) @@ -2619,6 +2620,7 @@ void LLPipeline::rebuildPriorityGroups()  		group->clearState(LLSpatialGroup::IN_BUILD_Q1);  	} +	mGroupSaveQ1 = mGroupQ1;  	mGroupQ1.clear();  	mGroupQ1Locked = false; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fd2a1e06cd..7a0ca86231 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -668,6 +668,8 @@ protected:  	LLSpatialGroup::sg_vector_t		mGroupQ1; //priority  	LLSpatialGroup::sg_vector_t		mGroupQ2; // non-priority +	LLSpatialGroup::sg_vector_t		mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref +  	LLSpatialGroup::sg_vector_t		mMeshDirtyGroup; //groups that need rebuildMesh called  	U32 mMeshDirtyQueryObject; diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index d480b63094..bdcb068200 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -271,6 +271,16 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para              }              return;             // Done!          } + +		/* Sometimes we end with "Started" here. Slightly slow server? +		 * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below. +		 */ +		if( status == "Started") +		{ +			LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL; +			continue; +		} +          // If we don't recognize status at all, trouble          if (! (status == "CURLError"                 || status == "XMLRPCError" | 
