diff options
Diffstat (limited to 'indra')
70 files changed, 1366 insertions, 442 deletions
| diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 4063cc730b..a6ad6b125c 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -337,11 +337,7 @@ LLMutex::~LLMutex()  void LLMutex::lock()  { -#if LL_DARWIN -	if (mLockingThread == LLThread::currentID()) -#else -	if (mLockingThread == sThreadID) -#endif +	if(isSelfLocked())  	{ //redundant lock  		mCount++;  		return; @@ -398,6 +394,15 @@ bool LLMutex::isLocked()  	}  } +bool LLMutex::isSelfLocked() +{ +#if LL_DARWIN +	return mLockingThread == LLThread::currentID(); +#else +	return mLockingThread == sThreadID; +#endif +} +  U32 LLMutex::lockingThread() const  {  	return mLockingThread; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index f0e0de6173..b52e70ab2e 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -151,6 +151,7 @@ public:  	void lock();		// blocks  	void unlock();  	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free +	bool isSelfLocked(); //return true if locked in a same thread  	U32 lockingThread() const; //get ID of locking thread  protected: diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 99ab053b25..a869c74189 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,8 +28,8 @@  #define LL_LLVERSIONVIEWER_H  const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 2; -const S32 LL_VERSION_PATCH = 8; +const S32 LL_VERSION_MINOR = 3; +const S32 LL_VERSION_PATCH = 0;  const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index f08657a75c..cc9744756f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2078,6 +2078,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge  	mFaceMask = 0x0;  	mDetail = detail;  	mSculptLevel = -2; +	mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims  	mIsMeshAssetLoaded = FALSE;  	mLODScaleBias.setVec(1,1,1);  	mHullPoints = NULL; @@ -3144,6 +3145,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,  		{  			F32 area = sculptGetSurfaceArea(); +			mSurfaceArea = area; +  			const F32 SCULPT_MAX_AREA = 384.f;  			if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index afd1ec5eed..76cf9de613 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -963,6 +963,7 @@ public:  	S32	getNumFaces() const;  	S32 getNumVolumeFaces() const							{ return mVolumeFaces.size(); }  	F32 getDetail() const									{ return mDetail; } +	F32 getSurfaceArea() const								{ return mSurfaceArea; }  	const LLVolumeParams& getParams() const					{ return mParams; }  	LLVolumeParams getCopyOfParams() const					{ return mParams; }  	const LLProfile& getProfile() const						{ return *mProfilep; } @@ -1065,6 +1066,7 @@ public:  	BOOL mUnique;  	F32 mDetail;  	S32 mSculptLevel; +	F32 mSurfaceArea; //unscaled surface area  	BOOL mIsMeshAssetLoaded;  	LLVolumeParams mParams; diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp index 0316797f00..250cace6e9 100644 --- a/indra/llmessage/llbuffer.cpp +++ b/indra/llmessage/llbuffer.cpp @@ -32,6 +32,9 @@  #include "llmath.h"  #include "llmemtype.h"  #include "llstl.h" +#include "llthread.h" + +#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED llassert(!mMutexp || mMutexp->isSelfLocked());  /**    * LLSegment @@ -224,7 +227,8 @@ void LLHeapBuffer::allocate(S32 size)   * LLBufferArray   */  LLBufferArray::LLBufferArray() : -	mNextBaseChannel(0) +	mNextBaseChannel(0), +	mMutexp(NULL)  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  } @@ -233,6 +237,8 @@ LLBufferArray::~LLBufferArray()  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer()); + +	delete mMutexp;  }  // static @@ -243,14 +249,57 @@ LLChannelDescriptors LLBufferArray::makeChannelConsumer(  	return rv;  } +void LLBufferArray::lock() +{ +	if(mMutexp) +	{ +		mMutexp->lock() ; +	} +} + +void LLBufferArray::unlock() +{ +	if(mMutexp) +	{ +		mMutexp->unlock() ; +	} +} + +LLMutex* LLBufferArray::getMutex() +{ +	return mMutexp ; +} + +void LLBufferArray::setThreaded(bool threaded) +{ +	if(threaded) +	{ +		if(!mMutexp) +		{ +			mMutexp = new LLMutex(NULL); +		} +	} +	else +	{ +		if(mMutexp) +		{ +			delete mMutexp ; +			mMutexp = NULL ; +		} +	} +} +  LLChannelDescriptors LLBufferArray::nextChannel()  {  	LLChannelDescriptors rv(mNextBaseChannel++);  	return rv;  } +//mMutexp should be locked before calling this.  S32 LLBufferArray::capacity() const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	S32 total = 0;  	const_buffer_iterator_t iter = mBuffers.begin();  	const_buffer_iterator_t end = mBuffers.end(); @@ -263,6 +312,8 @@ S32 LLBufferArray::capacity() const  bool LLBufferArray::append(S32 channel, const U8* src, S32 len)  { +	LLMutexLock lock(mMutexp) ; +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments;  	if(copyIntoBuffers(channel, src, len, segments)) @@ -273,8 +324,11 @@ bool LLBufferArray::append(S32 channel, const U8* src, S32 len)  	return false;  } +//mMutexp should be locked before calling this.  bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments;  	if(copyIntoBuffers(channel, src, len, segments)) @@ -293,6 +347,8 @@ bool LLBufferArray::insertAfter(  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments; + +	LLMutexLock lock(mMutexp) ;  	if(mSegments.end() != segment)  	{  		++segment; @@ -305,8 +361,11 @@ bool LLBufferArray::insertAfter(  	return false;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	segment_iterator_t end = mSegments.end();  	segment_iterator_t it = getSegment(address); @@ -335,20 +394,26 @@ LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)  	return rv;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	return mSegments.begin();  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::endSegment()  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	return mSegments.end();  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(  	U8* address,  	LLSegment& segment)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	segment_iterator_t rv = mSegments.begin();  	segment_iterator_t end = mSegments.end(); @@ -395,8 +460,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(  	return rv;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	segment_iterator_t end = mSegments.end();  	if(!address)  	{ @@ -414,9 +481,11 @@ LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)  	return end;  } +//mMutexp should be locked before calling this.  LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(  	U8* address) const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	const_segment_iterator_t end = mSegments.end();  	if(!address)  	{ @@ -466,6 +535,8 @@ S32 LLBufferArray::countAfter(S32 channel, U8* start) const  	S32 count = 0;  	S32 offset = 0;  	const_segment_iterator_t it; + +	LLMutexLock lock(mMutexp) ;  	const_segment_iterator_t end = mSegments.end();  	if(start)  	{ @@ -517,6 +588,8 @@ U8* LLBufferArray::readAfter(  	len = 0;  	S32 bytes_to_copy = 0;  	const_segment_iterator_t it; + +	LLMutexLock lock(mMutexp) ;  	const_segment_iterator_t end = mSegments.end();  	if(start)  	{ @@ -568,6 +641,7 @@ U8* LLBufferArray::seek(  	U8* start,  	S32 delta) const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	const_segment_iterator_t it;  	const_segment_iterator_t end = mSegments.end(); @@ -709,9 +783,14 @@ U8* LLBufferArray::seek(  	return rv;  } +//test use only  bool LLBufferArray::takeContents(LLBufferArray& source)  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER); + +	LLMutexLock lock(mMutexp); +	source.lock(); +  	std::copy(  		source.mBuffers.begin(),  		source.mBuffers.end(), @@ -723,13 +802,17 @@ bool LLBufferArray::takeContents(LLBufferArray& source)  		std::back_insert_iterator<segment_list_t>(mSegments));  	source.mSegments.clear();  	source.mNextBaseChannel = 0; +	source.unlock(); +  	return true;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(  	S32 channel,  	S32 len)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	// start at the end of the buffers, because it is the most likely  	// to have free space. @@ -765,8 +848,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(  	return send;  } +//mMutexp should be locked before calling this.  bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	// Find out which buffer contains the segment, and if it is found, @@ -792,13 +877,14 @@ bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)  	return rv;  } - +//mMutexp should be locked before calling this.  bool LLBufferArray::copyIntoBuffers(  	S32 channel,  	const U8* src,  	S32 len,  	std::vector<LLSegment>& segments)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	if(!src || !len) return false;  	S32 copied = 0; diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index 1c42b6fbc6..ccdb9fa7ee 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -39,6 +39,7 @@  #include <list>  #include <vector> +class LLMutex;  /**    * @class LLChannelDescriptors   * @brief A way simple interface to accesss channels inside a buffer @@ -564,6 +565,29 @@ public:  	 * @return Returns true on success.  	 */  	bool eraseSegment(const segment_iterator_t& iter); + +	/** +	* @brief Lock the mutex if it exists +	* This method locks mMutexp to make accessing LLBufferArray thread-safe +	*/ +	void lock(); + +	/** +	* @brief Unlock the mutex if it exists +	*/ +	void unlock(); + +	/** +	* @brief Return mMutexp +	*/ +	LLMutex* getMutex(); + +	/** +	* @brief Set LLBufferArray to be shared across threads or not +	* This method is to create mMutexp if is threaded. +	* @param threaded Indicates this LLBufferArray instance is shared across threads if true. +	*/ +	void setThreaded(bool threaded);  	//@}  protected: @@ -595,6 +619,7 @@ protected:  	S32 mNextBaseChannel;  	buffer_list_t mBuffers;  	segment_list_t mSegments; +	LLMutex* mMutexp;  };  #endif // LL_LLBUFFER_H diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp index 6257983c43..8d8ad05ad5 100644 --- a/indra/llmessage/llbufferstream.cpp +++ b/indra/llmessage/llbufferstream.cpp @@ -31,6 +31,7 @@  #include "llbuffer.h"  #include "llmemtype.h" +#include "llthread.h"  static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4; @@ -62,6 +63,7 @@ int LLBufferStreamBuf::underflow()  		return EOF;  	} +	LLMutexLock lock(mBuffer->getMutex());  	LLBufferArray::segment_iterator_t iter;  	LLBufferArray::segment_iterator_t end = mBuffer->endSegment();  	U8* last_pos = (U8*)gptr(); @@ -149,6 +151,7 @@ int LLBufferStreamBuf::overflow(int c)  	// since we got here, we have a buffer, and we have a character to  	// put on it.  	LLBufferArray::segment_iterator_t it; +	LLMutexLock lock(mBuffer->getMutex());  	it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);  	if(it != mBuffer->endSegment())  	{ @@ -210,6 +213,7 @@ int LLBufferStreamBuf::sync()  	// *NOTE: I bet we could just --address if address is not NULL.  	// Need to think about that. +	LLMutexLock lock(mBuffer->getMutex());  	address = mBuffer->seek(mChannels.out(), address, -1);  	if(address)  	{ @@ -273,6 +277,8 @@ streampos LLBufferStreamBuf::seekoff(  			// NULL is fine  			break;  		} + +		LLMutexLock lock(mBuffer->getMutex());  		address = mBuffer->seek(mChannels.in(), base_addr, off);  		if(address)  		{ @@ -304,6 +310,8 @@ streampos LLBufferStreamBuf::seekoff(  			// NULL is fine  			break;  		} + +		LLMutexLock lock(mBuffer->getMutex());  		address = mBuffer->seek(mChannels.out(), base_addr, off);  		if(address)  		{ diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 344463f036..b93d429feb 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,10 +72,9 @@  static const U32 EASY_HANDLE_POOL_SIZE		= 5;  static const S32 MULTI_PERFORM_CALL_REPEAT	= 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation  static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; -static   // DEBUG //  S32 gCurlEasyCount = 0;  S32 gCurlMultiCount = 0; @@ -87,6 +86,11 @@ std::vector<LLMutex*> LLCurl::sSSLMutex;  std::string LLCurl::sCAPath;  std::string LLCurl::sCAFile;  LLCurlThread* LLCurl::sCurlThread = NULL ; +LLMutex* LLCurl::sHandleMutexp = NULL ; +S32      LLCurl::sTotalHandles = 0 ; +bool     LLCurl::sNotQuitting = true; +F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds +S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined).  void check_curl_code(CURLcode code)  { @@ -224,13 +228,15 @@ LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;  //static  CURL* LLCurl::Easy::allocEasyHandle()  { +	llassert(LLCurl::getCurlThread()) ; +  	CURL* ret = NULL;  	LLMutexLock lock(sHandleMutexp) ;  	if (sFreeHandles.empty())  	{ -		ret = curl_easy_init(); +		ret = LLCurl::newEasyHandle();  	}  	else  	{ @@ -250,19 +256,30 @@ CURL* LLCurl::Easy::allocEasyHandle()  //static  void LLCurl::Easy::releaseEasyHandle(CURL* handle)  { +	static const S32 MAX_NUM_FREE_HANDLES = 32 ; +  	if (!handle)  	{ -		llerrs << "handle cannot be NULL!" << llendl; +		return ; //handle allocation failed. +		//llerrs << "handle cannot be NULL!" << llendl;  	}  	LLMutexLock lock(sHandleMutexp) ;  	if (sActiveHandles.find(handle) != sActiveHandles.end())  	{  		sActiveHandles.erase(handle); + +		if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) +		{  		sFreeHandles.insert(handle);  	}  	else  	{ +			LLCurl::deleteEasyHandle(handle) ; +		} +	} +	else +	{  		llerrs << "Invalid handle." << llendl;  	}  } @@ -302,6 +319,14 @@ LLCurl::Easy::~Easy()  	--gCurlEasyCount;  	curl_slist_free_all(mHeaders);  	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); + +	if (mResponder && LLCurl::sNotQuitting) //aborted +	{	 +		std::string reason("Request timeout, aborted.") ; +		mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort +			reason, mChannels, mOutput);		 +	} +	mResponder = NULL;  }  void LLCurl::Easy::resetState() @@ -474,6 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	LLProxy::getInstance()->applyProxySettings(this);  	mOutput.reset(new LLBufferArray); +	mOutput->setThreaded(true);  	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);  	setopt(CURLOPT_WRITEDATA, (void*)this); @@ -517,8 +543,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  }  //////////////////////////////////////////////////////////////////////////// -LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ; -LLCurl::Multi::Multi() +LLCurl::Multi::Multi(F32 idle_time_out)  	: mQueued(0),  	  mErrorCount(0),  	  mState(STATE_READY), @@ -527,15 +552,17 @@ LLCurl::Multi::Multi()  	  mDeletionMutexp(NULL),  	  mEasyMutexp(NULL)  { -	mCurlMultiHandle = initMulti(); +	mCurlMultiHandle = LLCurl::newMultiHandle();  	if (!mCurlMultiHandle)  	{  		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; -		mCurlMultiHandle = initMulti(); +		mCurlMultiHandle = LLCurl::newMultiHandle();  	} -	llassert_always(mCurlMultiHandle);	 +	//llassert_always(mCurlMultiHandle);	 +	if(mCurlMultiHandle) +	{  	if(LLCurl::getCurlThread()->getThreaded())  	{  		mMutexp = new LLMutex(NULL) ; @@ -544,11 +571,28 @@ LLCurl::Multi::Multi()  	}  	LLCurl::getCurlThread()->addMulti(this) ; +		mIdleTimeOut = idle_time_out ; +		if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) +		{ +			mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; +		} +  	++gCurlMultiCount;  } +}  LLCurl::Multi::~Multi()  { +	cleanup() ;	 +} + +void LLCurl::Multi::cleanup() +{ +	if(!mCurlMultiHandle) +	{ +		return ; //nothing to clean. +	} +  	// Clean up active  	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();  		iter != mEasyActiveList.end(); ++iter) @@ -564,7 +608,8 @@ LLCurl::Multi::~Multi()  	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	  	mEasyFreeList.clear(); -	check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); +	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); +	mCurlMultiHandle = NULL ;  	delete mMutexp ;  	mMutexp = NULL ; @@ -573,14 +618,12 @@ LLCurl::Multi::~Multi()  	delete mEasyMutexp ;  	mEasyMutexp = NULL ; +	mQueued = 0 ; +	mState = STATE_COMPLETED; +	  	--gCurlMultiCount; -} - -CURLM* LLCurl::Multi::initMulti() -{ -	LLMutexLock lock(sMultiInitMutexp) ; -	return curl_multi_init() ; +	return ;  }  void LLCurl::Multi::lock() @@ -604,6 +647,7 @@ void LLCurl::Multi::markDead()  	LLMutexLock lock(mDeletionMutexp) ;  	mDead = TRUE ; +	LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;   }  void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -630,6 +674,11 @@ bool LLCurl::Multi::isCompleted()  bool LLCurl::Multi::waitToComplete()  { +	if(!isValid()) +	{ +		return true ; +	} +  	if(!mMutexp) //not threaded  	{  		doPerform() ; @@ -639,7 +688,7 @@ bool LLCurl::Multi::waitToComplete()  	bool completed = (STATE_COMPLETED == mState) ;  	if(!completed)  	{ -		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; +		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ;  	}  	return completed; @@ -690,6 +739,11 @@ bool LLCurl::Multi::doPerform()  		mQueued = q;	  		setState(STATE_COMPLETED) ; +		mIdleTimer.reset() ; +	} +	else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. +	{ +		dead = true ;  	}  	return dead ; @@ -697,6 +751,11 @@ bool LLCurl::Multi::doPerform()  S32 LLCurl::Multi::process()  { +	if(!isValid()) +	{ +		return 0 ; +	} +  	waitToComplete() ;  	if (getState() != STATE_COMPLETED) @@ -849,32 +908,38 @@ bool LLCurlThread::CurlRequest::processRequest()  	if(mMulti)  	{  		completed = mCurlThread->doMultiPerform(mMulti) ; + +		if(!completed) +		{  		setPriority(LLQueuedThread::PRIORITY_LOW) ;  	} +	}  	return completed ;  }  void LLCurlThread::CurlRequest::finishRequest(bool completed)  { +	if(mMulti->isDead()) +	{  	mCurlThread->deleteMulti(mMulti) ; +	} +	else +	{ +		mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. +	} +  	mMulti = NULL ;  }  LLCurlThread::LLCurlThread(bool threaded) :  	LLQueuedThread("curlthread", threaded)  { -	if(!LLCurl::Multi::sMultiInitMutexp) -	{ -		LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ; -	}  }  //virtual   LLCurlThread::~LLCurlThread()   { -	delete LLCurl::Multi::sMultiInitMutexp ; -	LLCurl::Multi::sMultiInitMutexp = NULL ;  }  S32 LLCurlThread::update(F32 max_time_ms) @@ -896,8 +961,20 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi)  void LLCurlThread::killMulti(LLCurl::Multi* multi)  { +	if(!multi) +	{ +		return ; +	} + +	if(multi->isValid()) +	{  	multi->markDead() ;  } +	else +	{ +		deleteMulti(multi) ; +	} +}  //private  bool LLCurlThread::doMultiPerform(LLCurl::Multi* multi)  @@ -910,6 +987,13 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi)  {  	delete multi ;  } + +//private +void LLCurlThread::cleanupMulti(LLCurl::Multi* multi)  +{ +	multi->cleanup() ; +} +  //------------------------------------------------------------  //static @@ -942,6 +1026,13 @@ LLCurlRequest::~LLCurlRequest()  void LLCurlRequest::addMulti()  {  	LLCurl::Multi* multi = new LLCurl::Multi(); +	if(!multi->isValid()) +	{ +		LLCurl::getCurlThread()->killMulti(multi) ; +		mActiveMulti = NULL ; +		mActiveRequestCount = 0 ; +		return; +	}  	mMultiSet.insert(multi);  	mActiveMulti = multi; @@ -956,7 +1047,12 @@ LLCurl::Easy* LLCurlRequest::allocEasy()  	{  		addMulti();  	} -	llassert_always(mActiveMulti); +	if(!mActiveMulti) +	{ +		return NULL ; +	} + +	//llassert_always(mActiveMulti);  	++mActiveRequestCount;  	LLCurl::Easy* easy = mActiveMulti->allocEasy();  	return easy; @@ -1066,6 +1162,19 @@ S32 LLCurlRequest::process()  	{  		curlmulti_set_t::iterator curiter = iter++;  		LLCurl::Multi* multi = *curiter; + +		if(!multi->isValid()) +		{ +			if(multi == mActiveMulti) +			{				 +				mActiveMulti = NULL ; +				mActiveRequestCount = 0 ; +			} +			mMultiSet.erase(curiter) ; +			LLCurl::getCurlThread()->killMulti(multi) ; +			continue ; +		} +  		S32 tres = multi->process();  		res += tres;  		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) @@ -1086,6 +1195,19 @@ S32 LLCurlRequest::getQueued()  	{  		curlmulti_set_t::iterator curiter = iter++;  		LLCurl::Multi* multi = *curiter; +		 +		if(!multi->isValid()) +		{ +			if(multi == mActiveMulti) +			{				 +				mActiveMulti = NULL ; +				mActiveRequestCount = 0 ; +			} +			LLCurl::getCurlThread()->killMulti(multi); +			mMultiSet.erase(curiter) ; +			continue ; +		} +  		queued += multi->mQueued;  		if (multi->getState() != LLCurl::Multi::STATE_READY)  		{ @@ -1105,6 +1227,8 @@ LLCurlEasyRequest::LLCurlEasyRequest()  {  	mMulti = new LLCurl::Multi(); +	if(mMulti->isValid()) +	{  	mEasy = mMulti->allocEasy();  	if (mEasy)  	{ @@ -1114,6 +1238,13 @@ LLCurlEasyRequest::LLCurlEasyRequest()  		LLProxy::getInstance()->applyProxySettings(mEasy);  	}  } +	else +	{ +		LLCurl::getCurlThread()->killMulti(mMulti) ; +		mEasy = NULL ; +		mMulti = NULL ; +	} +}  LLCurlEasyRequest::~LLCurlEasyRequest()  { @@ -1122,7 +1253,7 @@ LLCurlEasyRequest::~LLCurlEasyRequest()  void LLCurlEasyRequest::setopt(CURLoption option, S32 value)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(option, value);  	} @@ -1130,7 +1261,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value)  void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setoptString(option, value);  	} @@ -1138,7 +1269,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value  void LLCurlEasyRequest::setPost(char* postdata, S32 size)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_POST, 1);  		mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1148,7 +1279,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size)  void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1157,7 +1288,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u  void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1166,7 +1297,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use  void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1175,7 +1306,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd  void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1184,7 +1315,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*  void LLCurlEasyRequest::slist_append(const char* str)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->slist_append(str);  	} @@ -1195,7 +1326,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url)  	llassert_always(!mRequestSent);  	mRequestSent = true;  	lldebugs << url << llendl; -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setHeaders();  		mEasy->setoptString(CURLOPT_URL, url); @@ -1207,7 +1338,7 @@ void LLCurlEasyRequest::requestComplete()  {  	llassert_always(mRequestSent);  	mRequestSent = false; -	if (mEasy) +	if (isValid() && mEasy)  	{  		mMulti->removeEasy(mEasy);  	} @@ -1216,6 +1347,10 @@ void LLCurlEasyRequest::requestComplete()  // Usage: Call getRestult until it returns false (no more messages)  bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)  { +	if(!isValid()) +	{ +		return false ; +	}  	if (!mMulti->isCompleted())  	{ //we're busy, try again later  		return false; @@ -1280,7 +1415,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info)  std::string LLCurlEasyRequest::getErrorString()  { -	return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); +	return isValid() &&  mEasy ? std::string(mEasy->getErrorBuffer()) : std::string();  }  //////////////////////////////////////////////////////////////////////////// @@ -1306,8 +1441,11 @@ unsigned long LLCurl::ssl_thread_id(void)  }  #endif -void LLCurl::initClass(bool multi_threaded) +void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded)  { +	sCurlRequestTimeOut = curl_reuest_timeout ; //seconds +	sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). +  	// Do not change this "unless you are familiar with and mean to control   	// internal operations of libcurl"  	// - http://curl.haxx.se/libcurl/c/curl_global_init.html @@ -1328,12 +1466,15 @@ void LLCurl::initClass(bool multi_threaded)  	sCurlThread = new LLCurlThread(multi_threaded) ;  	if(multi_threaded)  	{ +		sHandleMutexp = new LLMutex(NULL) ;  		Easy::sHandleMutexp = new LLMutex(NULL) ;  	}  }  void LLCurl::cleanupClass()  { +	sNotQuitting = false; //set quitting +  	//shut down curl thread  	while(1)  	{ @@ -1354,7 +1495,7 @@ void LLCurl::cleanupClass()  	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)  	{  		CURL* curl = *iter; -		curl_easy_cleanup(curl); +		LLCurl::deleteEasyHandle(curl);  	}  	Easy::sFreeHandles.clear(); @@ -1362,9 +1503,77 @@ void LLCurl::cleanupClass()  	delete Easy::sHandleMutexp ;  	Easy::sHandleMutexp = NULL ; +	delete sHandleMutexp ; +	sHandleMutexp = NULL ; +  	llassert(Easy::sActiveHandles.empty());  } +//static  +CURLM* LLCurl::newMultiHandle() +{ +	LLMutexLock lock(sHandleMutexp) ; + +	if(sTotalHandles + 1 > sMaxHandles) +	{ +		llwarns << "no more handles available." << llendl ; +		return NULL ; //failed +	} +	sTotalHandles++; + +	CURLM* ret = curl_multi_init() ; +	if(!ret) +	{ +		llwarns << "curl_multi_init failed." << llendl ; +	} + +	return ret ; +} + +//static  +CURLMcode  LLCurl::deleteMultiHandle(CURLM* handle) +{ +	if(handle) +	{ +		LLMutexLock lock(sHandleMutexp) ;		 +		sTotalHandles-- ; +		return curl_multi_cleanup(handle) ; +	} +	return CURLM_OK ; +} + +//static  +CURL*  LLCurl::newEasyHandle() +{ +	LLMutexLock lock(sHandleMutexp) ; + +	if(sTotalHandles + 1 > sMaxHandles) +	{ +		llwarns << "no more handles available." << llendl ; +		return NULL ; //failed +	} +	sTotalHandles++; + +	CURL* ret = curl_easy_init() ; +	if(!ret) +	{ +		llwarns << "curl_easy_init failed." << llendl ; +	} + +	return ret ; +} + +//static  +void  LLCurl::deleteEasyHandle(CURL* handle) +{ +	if(handle) +	{ +		LLMutexLock lock(sHandleMutexp) ; +		curl_easy_cleanup(handle) ; +		sTotalHandles-- ; +	} +} +  const unsigned int LLCurl::MAX_REDIRECTS = 5;  // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 9c2c215c7a..fd664c0fa1 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -43,6 +43,7 @@  #include "llsd.h"  #include "llthread.h"  #include "llqueuedthread.h" +#include "llframetimer.h"  class LLMutex;  class LLCurlThread; @@ -162,7 +163,7 @@ public:  	/**  	 * @ brief Initialize LLCurl class  	 */ -	static void initClass(bool multi_threaded = false); +	static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false);  	/**  	 * @ brief Cleanup LLCurl class @@ -182,11 +183,24 @@ public:  	static unsigned long ssl_thread_id(void);  	static LLCurlThread* getCurlThread() { return sCurlThread ;} + +	static CURLM* newMultiHandle() ; +	static CURLMcode deleteMultiHandle(CURLM* handle) ; +	static CURL*  newEasyHandle() ; +	static void   deleteEasyHandle(CURL* handle) ; +  private:  	static std::string sCAPath;  	static std::string sCAFile;  	static const unsigned int MAX_REDIRECTS;  	static LLCurlThread* sCurlThread; + +	static LLMutex* sHandleMutexp ; +	static S32      sTotalHandles ; +	static S32      sMaxHandles; +public: +	static bool     sNotQuitting; +	static F32      sCurlRequestTimeOut;	  };  class LLCurl::Easy @@ -277,7 +291,7 @@ public:  		STATE_COMPLETED=2  	} ePerformState; -	Multi();	 +	Multi(F32 idle_time_out = 0.f);	  	LLCurl::Easy* allocEasy();  	bool addEasy(LLCurl::Easy* easy);	 @@ -288,7 +302,10 @@ public:  	void setState(ePerformState state) ;  	ePerformState getState() ; +	  	bool isCompleted() ; +	bool isValid() {return mCurlMultiHandle != NULL ;} +	bool isDead() {return mDead;}  	bool waitToComplete() ; @@ -299,9 +316,9 @@ public:  	S32 mQueued;  	S32 mErrorCount; -	static CURLM* initMulti() ;  private:  	void easyFree(LLCurl::Easy*); +	void cleanup() ;  	CURLM* mCurlMultiHandle; @@ -319,8 +336,8 @@ private:  	LLMutex* mMutexp ;  	LLMutex* mDeletionMutexp ;  	LLMutex* mEasyMutexp ; - -	static LLMutex* sMultiInitMutexp ; +	LLFrameTimer mIdleTimer ; +	F32 mIdleTimeOut;  };  class LLCurlThread : public LLQueuedThread @@ -357,6 +374,7 @@ public:  private:  	bool doMultiPerform(LLCurl::Multi* multi) ;  	void deleteMulti(LLCurl::Multi* multi) ; +	void cleanupMulti(LLCurl::Multi* multi) ;  } ;  namespace boost @@ -414,6 +432,7 @@ public:  	std::string getErrorString();  	bool isCompleted() {return mMulti->isCompleted() ;}  	bool wait() { return mMulti->waitToComplete(); } +	bool isValid() {return mMulti && mMulti->isValid(); }  	LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 2bca517e97..612d765969 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -232,7 +232,8 @@ LLSD LLHTTPAssetRequest::getFullDetails() const  void LLHTTPAssetRequest::setupCurlHandle()  {  	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC -	mCurlHandle = curl_easy_init(); +	mCurlHandle = LLCurl::newEasyHandle(); +	llassert_always(mCurlHandle != NULL) ;  	// Apply proxy settings if configured to do so  	LLProxy::getInstance()->applyProxySettings(mCurlHandle); @@ -278,7 +279,7 @@ void LLHTTPAssetRequest::setupCurlHandle()  void LLHTTPAssetRequest::cleanupCurlHandle()  { -	curl_easy_cleanup(mCurlHandle); +	LLCurl::deleteEasyHandle(mCurlHandle);  	if (mAssetStoragep)  	{  		// Terminating a request.  Thus upload or download is no longer pending. @@ -429,12 +430,13 @@ void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& l  	// curl_global_init moved to LLCurl::initClass() -	mCurlMultiHandle = curl_multi_init(); +	mCurlMultiHandle = LLCurl::newMultiHandle() ; +	llassert_always(mCurlMultiHandle != NULL) ;  }  LLHTTPAssetStorage::~LLHTTPAssetStorage()  { -	curl_multi_cleanup(mCurlMultiHandle); +	LLCurl::deleteMultiHandle(mCurlMultiHandle);  	mCurlMultiHandle = NULL;  	// curl_global_cleanup moved to LLCurl::initClass() diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 98983ad28a..0c325a68aa 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -228,6 +228,12 @@ static void request(  	LLPumpIO::chain_t chain;  	LLURLRequest* req = new LLURLRequest(method, url); +	if(!req->isValid())//failed +	{ +		delete req ; +		return ; +	} +  	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); @@ -423,7 +429,9 @@ static LLSD blocking_request(  {  	lldebugs << "blockingRequest of " << url << llendl;  	char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; -	CURL* curlp = curl_easy_init(); +	CURL* curlp = LLCurl::newEasyHandle(); +	llassert_always(curlp != NULL) ; +  	LLHTTPBuffer http_buffer;  	std::string body_str; @@ -517,7 +525,7 @@ static LLSD blocking_request(  	}  	// * Cleanup -	curl_easy_cleanup(curlp); +	LLCurl::deleteEasyHandle(curlp);  	return response;  } diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 73e8a69085..987f386aa3 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -818,6 +818,8 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(    			// Copy everything after mLast read to the out.  			LLBufferArray::segment_iterator_t seg_iter; + +			buffer->lock();  			seg_iter = buffer->splitAfter(mLastRead);  			if(seg_iter != buffer->endSegment())  			{ @@ -838,7 +840,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(  				}  #endif  			} - +			buffer->unlock();  			//  			// *FIX: get rid of extra bytes off the end  			// diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp index 6e4eec74a6..8f827f7a30 100644 --- a/indra/llmessage/lliopipe.cpp +++ b/indra/llmessage/lliopipe.cpp @@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe()  	//lldebugs << "destroying LLIOPipe" << llendl;  } +//virtual  +bool LLIOPipe::isValid()  +{ +	return true ; +} +  // static  std::string LLIOPipe::lookupStatusString(EStatus status)  { diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index 8e656b6da1..cbd17b5a3d 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -231,6 +231,8 @@ public:  	 */  	virtual ~LLIOPipe(); +	virtual bool isValid() ; +  protected:  	/**  	 * @brief Base Constructor. diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 54ceab3422..d5b4d45821 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -445,6 +445,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(  	// efficient - not only because writev() is better, but also  	// because we won't have to do as much work to find the start  	// address. +	buffer->lock();  	LLBufferArray::segment_iterator_t it;  	LLBufferArray::segment_iterator_t end = buffer->endSegment();  	LLSegment segment; @@ -524,6 +525,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(  		}  	} +	buffer->unlock(); +  	PUMP_DEBUG;  	if(done && eos)  	{ diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a8d2a0a224..f3ef4f2684 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -195,7 +195,7 @@ bool LLPumpIO::prime(apr_pool_t* pool)  	return ((pool == NULL) ? false : true);  } -bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) +bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)  {  	LLMemType m1(LLMemType::MTYPE_IO_PUMP);  	if(chain.empty()) return false; @@ -204,8 +204,10 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)  	LLScopedLock lock(mChainsMutex);  #endif  	LLChainInfo info; +	info.mHasCurlRequest = has_curl_request;  	info.setTimeoutSeconds(timeout);  	info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray); +	info.mData->setThreaded(has_curl_request);  	LLLinkInfo link;  #if LL_DEBUG_PIPE_TYPE_IN_PUMP  	lldebugs << "LLPumpIO::addChain() " << chain[0] << " '" @@ -440,6 +442,15 @@ void LLPumpIO::pump()  static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); +LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain)  +{ +	std::for_each( +				(*run_chain).mDescriptors.begin(), +				(*run_chain).mDescriptors.end(), +				ll_delete_apr_pollset_fd_client_data()); +	return mRunningChains.erase(run_chain); +} +  //timeout is in microseconds  void LLPumpIO::pump(const S32& poll_timeout)  { @@ -585,10 +596,16 @@ void LLPumpIO::pump(const S32& poll_timeout)  //						<< (*run_chain).mChainLinks[0].mPipe  //						<< " because we reached the end." << llendl;  #endif -				run_chain = mRunningChains.erase(run_chain); +				run_chain = removeRunningChain(run_chain);  				continue;  			}  		} +		else if(isChainExpired(*run_chain)) +		{ +			run_chain = removeRunningChain(run_chain); +			continue; +		} +  		PUMP_DEBUG;  		if((*run_chain).mLock)  		{ @@ -696,11 +713,7 @@ void LLPumpIO::pump(const S32& poll_timeout)  			PUMP_DEBUG;  			// This chain is done. Clean up any allocated memory and  			// erase the chain info. -			std::for_each( -				(*run_chain).mDescriptors.begin(), -				(*run_chain).mDescriptors.end(), -				ll_delete_apr_pollset_fd_client_data()); -			run_chain = mRunningChains.erase(run_chain); +			run_chain = removeRunningChain(run_chain);  			// *NOTE: may not always need to rebuild the pollset.  			mRebuildPollset = true; @@ -1095,6 +1108,24 @@ void LLPumpIO::processChain(LLChainInfo& chain)  	PUMP_DEBUG;  } +bool LLPumpIO::isChainExpired(LLChainInfo& chain) +{ +	if(!chain.mHasCurlRequest) +	{ +		return false ; +	} + +	for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter) +	{ +		if(!(*iter).mPipe->isValid()) +		{ +			return true ; +		} +	} + +	return false ; +} +  bool LLPumpIO::handleChainError(  	LLChainInfo& chain,  	LLIOPipe::EStatus error) @@ -1136,6 +1167,9 @@ bool LLPumpIO::handleChainError(  #endif  			keep_going = false;  			break; +		case LLIOPipe::STATUS_EXPIRED: +			keep_going = false; +			break ;  		default:  			if(LLIOPipe::isSuccess(error))  			{ @@ -1157,7 +1191,8 @@ bool LLPumpIO::handleChainError(  LLPumpIO::LLChainInfo::LLChainInfo() :  	mInit(false),  	mLock(0), -	mEOS(false) +	mEOS(false), +	mHasCurlRequest(false)  {  	LLMemType m1(LLMemType::MTYPE_IO_PUMP);  	mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 9303c9d7fc..d2c5d37571 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -111,9 +111,10 @@ public:  	 * @param chain The pipes for the chain  	 * @param timeout The number of seconds in the future to  	 * expire. Pass in 0.0f to never expire. +	 * @param has_curl_request The chain contains LLURLRequest if true.  	 * @return Returns true if anything was added to the pump.  	 */ -	bool addChain(const chain_t& chain, F32 timeout); +	bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);  	/**   	 * @brief Struct to associate a pipe with it's buffer io indexes. @@ -356,12 +357,13 @@ protected:  		// basic member data  		bool mInit; +		bool mEOS; +		bool mHasCurlRequest;  		S32 mLock;  		LLFrameTimer mTimer;  		links_t::iterator mHead;  		links_t mChainLinks; -		LLIOPipe::buffer_ptr_t mData; -		bool mEOS; +		LLIOPipe::buffer_ptr_t mData;		  		LLSD mContext;  		// tracking inside the pump @@ -402,7 +404,7 @@ protected:  protected:  	void initialize(apr_pool_t* pool);  	void cleanup(); - +	current_chain_t removeRunningChain(current_chain_t& chain) ;  	/**   	 * @brief Given the internal state of the chains, rebuild the pollset  	 * @see setConditional() @@ -429,6 +431,9 @@ protected:  	 */  	bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error); +	//if the chain is expired, remove it +	bool isChainExpired(LLChainInfo& chain) ; +  public:  	/**   	 * @brief Return number of running chains. diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h index 9fb49a5c33..0cecf4f688 100644 --- a/indra/llmessage/llsdrpcclient.h +++ b/indra/llmessage/llsdrpcclient.h @@ -240,9 +240,16 @@ public:  	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const  	{  		lldebugs << "LLSDRPCClientFactory::build" << llendl; -		LLIOPipe::ptr_t service(new Client); -		chain.push_back(service);  		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); +		if(!http->isValid()) +		{ +			llwarns << "Creating LLURLRequest failed." << llendl ; +			delete http; +			return false; +		} + +		LLIOPipe::ptr_t service(new Client); +		chain.push_back(service);		  		LLIOPipe::ptr_t http_pipe(http);  		http->addHeader("Content-Type: text/llsd");  		if(mURL.empty()) @@ -283,9 +290,16 @@ public:  	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const  	{  		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; -		LLIOPipe::ptr_t service(new Client); -		chain.push_back(service); +  		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); +		if(!http->isValid()) +		{ +			llwarns << "Creating LLURLRequest failed." << llendl ; +			delete http; +			return false ; +		} +		LLIOPipe::ptr_t service(new Client); +		chain.push_back(service);		  		LLIOPipe::ptr_t http_pipe(http);  		http->addHeader("Content-Type: text/xml");  		if(mURL.empty()) diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 261e57e79e..a16f5c7bf0 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -83,6 +83,12 @@ LLURLRequestDetail::LLURLRequestDetail() :  {  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	mCurlRequest = new LLCurlEasyRequest(); +	 +	if(!mCurlRequest->isValid()) //failed. +	{ +		delete mCurlRequest ; +		mCurlRequest = NULL ; +	}  }  LLURLRequestDetail::~LLURLRequestDetail() @@ -250,12 +256,24 @@ void LLURLRequest::allowCookies()  	mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");  } +//virtual  +bool LLURLRequest::isValid()  +{ +	return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid();  +} +  // virtual  LLIOPipe::EStatus LLURLRequest::handleError(  	LLIOPipe::EStatus status,  	LLPumpIO* pump)  {  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); +	 +	if(!isValid()) +	{ +		return STATUS_EXPIRED ; +	} +  	if(mCompletionCallback && pump)  	{  		LLURLRequestComplete* complete = NULL; @@ -441,6 +459,12 @@ void LLURLRequest::initialize()  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	mState = STATE_INITIALIZED;  	mDetail = new LLURLRequestDetail; + +	if(!isValid()) +	{ +		return ; +	} +  	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);  	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index ec5c2c1941..44d358d906 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -188,6 +188,8 @@ public:  	 */  	void allowCookies(); +	/*virtual*/ bool isValid() ; +  public:  	/**   	 * @brief Give this pipe a chance to handle a generated error diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cd827f5091..b0ddacbb05 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -997,7 +997,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction)  		const glh::matrix4f& mat = gGL.getModelviewMatrix();  		mat.mult_matrix_dir(dir); -		mSpotDirection.set(direction); +		mSpotDirection.set(dir.v);  	}  } @@ -1434,6 +1434,8 @@ void LLRender::loadIdentity()  	flush();  	{ +		llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; +  		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();  		mMatHash[mMatrixMode]++;  	} diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 20a450fbfb..eb302392bb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -148,7 +148,7 @@ U32 wpo2(U32 i)  	return r;  } -U8* LLVBOPool::allocate(U32& name, U32 size) +volatile U8* LLVBOPool::allocate(U32& name, U32 size)  {  	llassert(nhpo2(size) == size); @@ -159,20 +159,25 @@ U8* LLVBOPool::allocate(U32& name, U32 size)  		mFreeList.resize(i+1);  	} -	U8* ret = NULL; +	volatile U8* ret = NULL;  	if (mFreeList[i].empty())  	{  		//make a new buffer  		glGenBuffersARB(1, &name);  		glBindBufferARB(mType, name); -		glBufferDataARB(mType, size, 0, mUsage);  		LLVertexBuffer::sAllocatedBytes += size; -		if (LLVertexBuffer::sDisableVBOMapping) +		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)  		{ +			glBufferDataARB(mType, size, 0, mUsage);  			ret = (U8*) ll_aligned_malloc_16(size);  		} +		else +		{ //always use a true hint of static draw when allocating non-client-backed buffers +			glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); +		} +  		glBindBufferARB(mType, 0);  	}  	else @@ -188,7 +193,7 @@ U8* LLVBOPool::allocate(U32& name, U32 size)  	return ret;  } -void LLVBOPool::release(U32 name, U8* buffer, U32 size) +void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)  {  	llassert(nhpo2(size) == size); @@ -201,8 +206,15 @@ void LLVBOPool::release(U32 name, U8* buffer, U32 size)  	rec.mClientData = buffer;  	sBytesPooled += size; - -	mFreeList[i].push_back(rec); +	 +	if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB) +	{ +		glDeleteBuffersARB(1, &rec.mGLName); +	} +	else +	{ +		mFreeList[i].push_back(rec); +	}  }  void LLVBOPool::cleanup() @@ -221,7 +233,7 @@ void LLVBOPool::cleanup()  			if (r.mClientData)  			{ -				ll_aligned_free_16(r.mClientData); +				ll_aligned_free_16((void*) r.mClientData);  			}  			l.pop_front(); @@ -536,7 +548,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of  void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const  {  	validateRange(start, end, count, indices_offset); - +	mMappable = FALSE;  	gGL.syncMatrices();  	llassert(mNumVerts >= 0); @@ -591,7 +603,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi  void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const  {  	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - +	mMappable = FALSE;  	gGL.syncMatrices();  	llassert(mNumIndices >= 0); @@ -637,7 +649,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const  void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const  {  	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); -	 +	mMappable = FALSE;  	gGL.syncMatrices();  	llassert(mNumVerts >= 0); @@ -787,9 +799,26 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :  	if (mUsage && mUsage != GL_STREAM_DRAW_ARB)  	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default -		mUsage = GL_DYNAMIC_DRAW_ARB; +		if (sDisableVBOMapping) +		{ //always use stream draw if VBO mapping is disabled +			mUsage = GL_STREAM_DRAW_ARB; +		} +		else +		{ +			mUsage = GL_DYNAMIC_DRAW_ARB; +		}  	} -		 +	 + +	if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping) +	{ +		mMappable = TRUE; +	} +	else +	{ +		mMappable = FALSE; +	} +  	//zero out offsets  	for (U32 i = 0; i < TYPE_MAX; i++)  	{ @@ -1042,7 +1071,7 @@ void LLVertexBuffer::destroyGLBuffer()  		}  		else  		{ -			FREE_MEM(sPrivatePoolp, mMappedData) ; +			FREE_MEM(sPrivatePoolp, (void*) mMappedData) ;  			mMappedData = NULL;  			mEmpty = TRUE;  		} @@ -1063,7 +1092,7 @@ void LLVertexBuffer::destroyGLIndices()  		}  		else  		{ -			FREE_MEM(sPrivatePoolp, mMappedIndexData) ; +			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ;  			mMappedIndexData = NULL;  			mEmpty = TRUE;  		} @@ -1282,8 +1311,11 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)  	return true;  } +static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range"); +static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map"); +  // Map for data access -U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) +volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)  {  	bindGLBuffer(true);  	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); @@ -1298,7 +1330,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  	if (useVBOs())  	{ -		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) +		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)  		{  			if (count == -1)  			{ @@ -1323,7 +1355,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  			if (!mapped)  			{  				//not already mapped, map new region -				MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count); +				MappedRegion region(type, mMappable && map_range ? -1 : index, count);  				mMappedVertexRegions.push_back(region);  			}  		} @@ -1340,19 +1372,20 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  			sMappedCount++;  			stop_glerror();	 -			if(sDisableVBOMapping) +			if(!mMappable)  			{  				map_range = false;  			}  			else  			{ -				U8* src = NULL; +				volatile U8* src = NULL;  				waitFence();  				if (gGLManager.mHasMapBufferRange)  				{  					if (map_range)  					{  #ifdef GL_ARB_map_buffer_range +						LLFastTimer t(FTM_VBO_MAP_BUFFER_RANGE);  						S32 offset = mOffsets[type] + sTypeSize[type]*index;  						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;  						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length,  @@ -1376,6 +1409,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  							}  						} +						LLFastTimer t(FTM_VBO_MAP_BUFFER);  						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize,   							GL_MAP_WRITE_BIT |   							GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1403,7 +1437,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  				llassert(src != NULL); -				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); +				mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src);  				mAlignedOffset = mMappedData - src;  				stop_glerror(); @@ -1416,7 +1450,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  			//check the availability of memory  			LLMemory::logMemoryInfo(TRUE) ;  -				if(!sDisableVBOMapping) +				if(mMappable)  				{			  					//--------------------  					//print out more debug info before crash @@ -1448,7 +1482,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  		map_range = false;  	} -	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) +	if (map_range && gGLManager.mHasMapBufferRange && mMappable)  	{  		return mMappedData;  	} @@ -1458,7 +1492,11 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran  	}  } -U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) + +static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX_RANGE("IBO Map Range"); +static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map"); + +volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  {  	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);  	bindGLIndices(true); @@ -1473,7 +1511,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  	if (useVBOs())  	{ -		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) +		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)  		{  			if (count == -1)  			{ @@ -1495,7 +1533,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  			if (!mapped)  			{  				//not already mapped, map new region -				MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count); +				MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);  				mMappedIndexRegions.push_back(region);  			}  		} @@ -1524,19 +1562,20 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  				}  			} -			if(sDisableVBOMapping) +			if(!mMappable)  			{  				map_range = false;  			}  			else  			{ -				U8* src = NULL; +				volatile U8* src = NULL;  				waitFence();  				if (gGLManager.mHasMapBufferRange)  				{  					if (map_range)  					{  #ifdef GL_ARB_map_buffer_range +						LLFastTimer t(FTM_VBO_MAP_INDEX_RANGE);  						S32 offset = sizeof(U16)*index;  						S32 length = sizeof(U16)*count;  						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length,  @@ -1548,6 +1587,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  					else  					{  #ifdef GL_ARB_map_buffer_range +						LLFastTimer t(FTM_VBO_MAP_INDEX);  						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices,   							GL_MAP_WRITE_BIT |   							GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1569,6 +1609,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  				}  				else  				{ +					LLFastTimer t(FTM_VBO_MAP_INDEX);  					map_range = false;  					src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);  				} @@ -1587,7 +1628,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  			log_glerror();  			LLMemory::logMemoryInfo(TRUE) ; -			if(!sDisableVBOMapping) +			if(mMappable)  			{  				GLint buff;  				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); @@ -1609,7 +1650,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  		map_range = false;  	} -	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) +	if (map_range && gGLManager.mHasMapBufferRange && mMappable)  	{  		return mMappedIndexData;  	} @@ -1619,6 +1660,13 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  	}  } +static LLFastTimer::DeclareTimer FTM_VBO_UNMAP("VBO Unmap"); +static LLFastTimer::DeclareTimer FTM_VBO_FLUSH_RANGE("Flush VBO Range"); + + +static LLFastTimer::DeclareTimer FTM_IBO_UNMAP("IBO Unmap"); +static LLFastTimer::DeclareTimer FTM_IBO_FLUSH_RANGE("Flush IBO Range"); +  void LLVertexBuffer::unmapBuffer()  {  	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER); @@ -1631,10 +1679,11 @@ void LLVertexBuffer::unmapBuffer()  	if (mMappedData && mVertexLocked)  	{ +		LLFastTimer t(FTM_VBO_UNMAP);  		bindGLBuffer(true);  		updated_all = mIndexLocked; //both vertex and index buffers done updating -		if(sDisableVBOMapping) +		if(!mMappable)  		{  			if (!mMappedVertexRegions.empty())  			{ @@ -1644,7 +1693,7 @@ void LLVertexBuffer::unmapBuffer()  					const MappedRegion& region = mMappedVertexRegions[i];  					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;  					S32 length = sTypeSize[region.mType]*region.mCount; -					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset); +					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset);  					stop_glerror();  				} @@ -1653,7 +1702,7 @@ void LLVertexBuffer::unmapBuffer()  			else  			{  				stop_glerror(); -				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); +				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData);  				stop_glerror();  			}  		} @@ -1671,6 +1720,7 @@ void LLVertexBuffer::unmapBuffer()  						S32 length = sTypeSize[region.mType]*region.mCount;  						if (gGLManager.mHasMapBufferRange)  						{ +							LLFastTimer t(FTM_VBO_FLUSH_RANGE);  #ifdef GL_ARB_map_buffer_range  							glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);  #endif @@ -1698,8 +1748,9 @@ void LLVertexBuffer::unmapBuffer()  	if (mMappedIndexData && mIndexLocked)  	{ +		LLFastTimer t(FTM_IBO_UNMAP);  		bindGLIndices(); -		if(sDisableVBOMapping) +		if(!mMappable)  		{  			if (!mMappedIndexRegions.empty())  			{ @@ -1708,7 +1759,7 @@ void LLVertexBuffer::unmapBuffer()  					const MappedRegion& region = mMappedIndexRegions[i];  					S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;  					S32 length = sizeof(U16)*region.mCount; -					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset); +					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset);  					stop_glerror();  				} @@ -1717,7 +1768,7 @@ void LLVertexBuffer::unmapBuffer()  			else  			{  				stop_glerror(); -				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); +				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData);  				stop_glerror();  			}  		} @@ -1734,6 +1785,7 @@ void LLVertexBuffer::unmapBuffer()  						S32 length = sizeof(U16)*region.mCount;  						if (gGLManager.mHasMapBufferRange)  						{ +							LLFastTimer t(FTM_IBO_FLUSH_RANGE);  #ifdef GL_ARB_map_buffer_range  							glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);  #endif @@ -1778,7 +1830,7 @@ template <class T,S32 type> struct VertexBufferStrider  	{  		if (type == LLVertexBuffer::TYPE_INDEX)  		{ -			U8* ptr = vbo.mapIndexBuffer(index, count, map_range); +			volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range);  			if (ptr == NULL)  			{ @@ -1794,7 +1846,7 @@ template <class T,S32 type> struct VertexBufferStrider  		{  			S32 stride = LLVertexBuffer::sTypeSize[type]; -			U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); +			volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);  			if (ptr == NULL)  			{ @@ -2109,7 +2161,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  {  	LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER);  	stop_glerror(); -	U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; +	volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;  	/*if ((data_mask & mTypeMask) != data_mask)  	{ diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 3e6f6a959a..e1cbfd3b61 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -60,10 +60,10 @@ public:  	U32 mType;  	//size MUST be a power of 2 -	U8* allocate(U32& name, U32 size); +	volatile U8* allocate(U32& name, U32 size);  	//size MUST be the size provided to allocate that returned the given name -	void release(U32 name, U8* buffer, U32 size); +	void release(U32 name, volatile U8* buffer, U32 size);  	//destroy all records in mFreeList  	void cleanup(); @@ -72,7 +72,7 @@ public:  	{  	public:  		U32 mGLName; -		U8* mClientData; +		volatile U8* mClientData;  	};  	typedef std::list<Record> record_list_t; @@ -208,8 +208,8 @@ public:  	LLVertexBuffer(U32 typemask, S32 usage);  	// map for data access -	U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); -	U8*		mapIndexBuffer(S32 index, S32 count, bool map_range); +	volatile U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); +	volatile U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);  	// set for rendering  	virtual void	setBuffer(U32 data_mask); 	// calls  setupVertexBuffer() if data_mask is not 0 @@ -244,16 +244,17 @@ public:  	S32 getNumVerts() const					{ return mNumVerts; }  	S32 getNumIndices() const				{ return mNumIndices; } -	U8* getIndicesPointer() const			{ return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } -	U8* getVerticesPointer() const			{ return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } +	volatile U8* getIndicesPointer() const			{ return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } +	volatile U8* getVerticesPointer() const			{ return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }  	U32 getTypeMask() const					{ return mTypeMask; }  	bool hasDataType(S32 type) const		{ return ((1 << type) & getTypeMask()); }  	S32 getSize() const;  	S32 getIndicesSize() const				{ return mIndicesSize; } -	U8* getMappedData() const				{ return mMappedData; } -	U8* getMappedIndices() const			{ return mMappedIndexData; } +	volatile U8* getMappedData() const				{ return mMappedData; } +	volatile U8* getMappedIndices() const			{ return mMappedIndexData; }  	S32 getOffset(S32 type) const			{ return mOffsets[type]; }  	S32 getUsage() const					{ return mUsage; } +	BOOL isWriteable() const				{ return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; }  	void draw(U32 mode, U32 count, U32 indices_offset) const;  	void drawArrays(U32 mode, U32 offset, U32 count) const; @@ -278,12 +279,13 @@ protected:  	U32		mGLIndices;		// GL IBO handle  	U32		mGLArray;		// GL VAO handle -	U8*		mMappedData;	// pointer to currently mapped data (NULL if unmapped) -	U8*		mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped) +	volatile U8* mMappedData;	// pointer to currently mapped data (NULL if unmapped) +	volatile U8* mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped)  	BOOL	mVertexLocked;			// if TRUE, vertex buffer is being or has been written to in client memory  	BOOL	mIndexLocked;			// if TRUE, index buffer is being or has been written to in client memory  	BOOL	mFinal;			// if TRUE, buffer can not be mapped again  	BOOL	mEmpty;			// if TRUE, client buffer is empty (or NULL). Old values have been discarded.	 +	mutable BOOL	mMappable;     // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)  	S32		mOffsets[TYPE_MAX];  	std::vector<MappedRegion> mMappedVertexRegions; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 62b8052a50..ee8c15752b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1828,6 +1828,28 @@        <key>Value</key>        <integer>0</integer>      </map> +  <key>CurlMaximumNumberOfHandles</key> +  <map> +    <key>Comment</key> +    <string>Maximum number of handles curl can use (requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>S32</string> +    <key>Value</key> +    <integer>256</integer> +  </map> +  <key>CurlRequestTimeOut</key> +  <map> +    <key>Comment</key> +    <string>Max idle time of a curl request before killed (requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>F32</string> +    <key>Value</key> +    <real>120.0</real> +  </map>    <key>CurlUseMultipleThreads</key>    <map>      <key>Comment</key> @@ -9068,6 +9090,28 @@        <key>Value</key>        <integer>1</integer>      </map> +  <key>RenderAutoMuteByteLimit</key> +  <map> +    <key>Comment</key> +    <string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>RenderAutoMuteSurfaceAreaLimit</key> +  <map> +    <key>Comment</key> +    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>F32</string> +    <key>Value</key> +    <integer>0</integer> +  </map>      <key>RenderUseShaderLOD</key>      <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl index 0170ad4b55..40b0cf47ac 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -61,17 +61,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -79,7 +79,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 93b1a114db..8c96d55342 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -70,17 +70,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -88,7 +88,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 @@ -123,7 +123,6 @@ void main()  	col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z);  	vary_pointlight_col = col.rgb*diffuse_color.rgb; -  	col.rgb = vec3(0,0,0);  	// Add windlight lights diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index d7b90978ba..c0edddc40a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -65,17 +65,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -83,7 +83,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl index 5a3955ef00..83815b1786 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -63,21 +63,21 @@ uniform vec3 light_diffuse[8];  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  { -	//get light vector +//get light vector  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -85,7 +85,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 9540ddd2e8..1660f9687e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -69,17 +69,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -87,7 +87,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 9c7a332417..84c27edb26 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -66,17 +66,17 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  	vec3 lv = lp.xyz-v;  	//get distance -	float d = length(lv); +	float d = dot(lv,lv);  	float da = 0.0;  	if (d > 0.0 && la > 0.0 && fa > 0.0)  	{  		//normalize light vector -		lv *= 1.0/d; +		lv = normalize(lv);  		//distance attenuation -		float dist2 = d*d/(la*la); +		float dist2 = d/la;  		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);  		// spotlight coefficient. @@ -84,7 +84,7 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa  		da *= spot*spot; // GL_SPOT_EXPONENT=2  		//angular attenuation -		da *= calcDirectionalLight(n, lv); +		da *= max(dot(n, lv), 0.0);		  	}  	return da;	 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 54ad3cd187..ab9b5ff436 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3314,6 +3314,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *  	}  	llinfos << "Received cached texture response for " << num_results << " textures." << llendl; +	gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");  	gAgentAvatarp->updateMeshTextures(); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index dd7e509e8d..dd02a74a38 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -185,6 +185,7 @@ void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)  {   	if (avatar)  	{ +		avatar->outputRezTiming("Sending wearables request");  		sendAgentWearablesRequest();  	}  } @@ -818,7 +819,7 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index)  		mWearableDatas[type].erase(mWearableDatas[type].begin() + index);  		if (isAgentAvatarValid())  		{ -			gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); +		gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE);  		}  		wearable->setLabelUpdated();  	} @@ -952,6 +953,11 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs  	if (mInitialWearablesUpdateReceived)  		return; +	if (isAgentAvatarValid()) +	{ +		gAgentAvatarp->outputRezTiming("Received initial wearables update"); +	} +  	// notify subscribers that wearables started loading. See EXT-7777  	// *TODO: find more proper place to not be called from deprecated method.  	// Seems such place is found: LLInitialWearablesFetch::processContents() @@ -1622,6 +1628,11 @@ void LLAgentWearables::queryWearableCache()  	//VWR-22113: gAgent.getRegion() can return null if invalid, seen here on logout  	if(gAgent.getRegion())  	{ +		if (isAgentAvatarValid()) +		{ +			gAgentAvatarp->outputRezTiming("Fetching textures from cache"); +		} +  		llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;  		gMessageSystem->sendReliable(gAgent.getRegion()->getHost());  		gAgentQueryManager.mNumPendingQueries++; diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 1edc96e165..8cba54347e 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -87,6 +87,10 @@ public:  LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :  	LLInventoryFetchDescendentsObserver(cof_id)  { +	if (isAgentAvatarValid()) +	{ +		gAgentAvatarp->outputRezTiming("Initial wearables fetch started"); +	}  }  LLInitialWearablesFetch::~LLInitialWearablesFetch() @@ -101,6 +105,10 @@ void LLInitialWearablesFetch::done()  	// idle tick instead.  	gInventory.removeObserver(this);  	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this)); +	if (isAgentAvatarValid()) +	{ +		gAgentAvatarp->outputRezTiming("Initial wearables fetch done"); +	}  }  void LLInitialWearablesFetch::add(InitialWearableData &data) @@ -111,6 +119,12 @@ void LLInitialWearablesFetch::add(InitialWearableData &data)  void LLInitialWearablesFetch::processContents()  { +	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted. +	{ +		delete this; +		return ; +	} +  	// Fetch the wearable items from the Current Outfit Folder  	LLInventoryModel::cat_array_t cat_array;  	LLInventoryModel::item_array_t wearable_array; diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h index 7dafab4a33..bedc445c0e 100644 --- a/indra/newview/llagentwearablesfetch.h +++ b/indra/newview/llagentwearablesfetch.h @@ -40,6 +40,8 @@  //--------------------------------------------------------------------  class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver  { +	LOG_CLASS(LLInitialWearablesFetch); +  public:  	LLInitialWearablesFetch(const LLUUID& cof_id);  	~LLInitialWearablesFetch(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 663257042e..33f5373d7e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -268,6 +268,8 @@ struct LLFoundData  class LLWearableHoldingPattern  { +	LOG_CLASS(LLWearableHoldingPattern); +  public:  	LLWearableHoldingPattern();  	~LLWearableHoldingPattern(); @@ -436,6 +438,11 @@ void LLWearableHoldingPattern::checkMissingWearables()  void LLWearableHoldingPattern::onAllComplete()  { +	if (isAgentAvatarValid()) +	{ +		gAgentAvatarp->outputRezTiming("Agent wearables fetch complete"); +	} +  	if (!isMostRecent())  	{  		llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl; @@ -2363,6 +2370,8 @@ void LLAppearanceMgr::autopopulateOutfits()  // Handler for anything that's deferred until avatar de-clouds.  void LLAppearanceMgr::onFirstFullyVisible()  { +	gAgentAvatarp->outputRezTiming("Avatar fully loaded"); +	gAgentAvatarp->reportAvatarRezTime();  	gAgentAvatarp->debugAvatarVisible();  	// The auto-populate is failing at the point of generating outfits diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a455d359bf..49fbdbf1df 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -722,7 +722,9 @@ bool LLAppViewer::init()      // *NOTE:Mani - LLCurl::initClass is not thread safe.       // Called before threads are created. -    LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads")); +    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"),  +						gSavedSettings.getS32("CurlMaximumNumberOfHandles"),  +						gSavedSettings.getBOOL("CurlUseMultipleThreads"));  	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;      LLMachineID::init(); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index debac9dcbf..21b21c152a 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -1077,6 +1077,7 @@ BOOL LLDrawable::isVisible() const  LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)  : LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB)  { +	mBridge = this;  	mDrawable = root;  	root->setSpatialBridge(this); @@ -1105,6 +1106,15 @@ LLSpatialBridge::~LLSpatialBridge()  	{  		group->mSpatialPartition->remove(this, group);  	} + +	//delete octree here so listeners will still be able to access bridge specific state +	destroyTree(); +} + +void LLSpatialBridge::destroyTree() +{ +	delete mOctree; +	mOctree = NULL;  }  void LLSpatialBridge::updateSpatialExtents() diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 55b314fbb1..b002c11af5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1285,7 +1285,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  		face->setGeomIndex(0);  		face->setIndicesIndex(0); -		if (buffer.isNull() || buffer->getTypeMask() != data_mask) +		if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())  		{ //make a new buffer  			if (sShaderLevel > 0)  			{ @@ -1319,7 +1319,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  		LLMatrix3 mat_normal(mat3);				  		//let getGeometryVolume know if alpha should override shiny -		if (face->getFaceColor().mV[3] < 1.f) +		U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); + +		if (type == LLDrawPool::POOL_ALPHA)  		{  			face->setPoolType(LLDrawPool::POOL_ALPHA);  		} diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 6dbeae6677..cd33a19a2a 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -693,6 +693,49 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of  	tex_coord.mV[1] = t;  } +// Transform the texture coordinates for this face. +static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale)  +{ +	//tex coord is two coords, <s0, t0, s1, t1> +	LLVector4a st; + +	// Texture transforms are done about the center of the face. +	st.setAdd(tex_coord, trans); +	 +	// Handle rotation +	LLVector4a rot_st; +		 +	// <s0 * cosAng, s0*-sinAng, s1*cosAng, s1*-sinAng> +	LLVector4a s0; +	s0.splat(st, 0); +	LLVector4a s1; +	s1.splat(st, 2); +	LLVector4a ss; +	ss.setSelectWithMask(mask, s1, s0); + +	LLVector4a a;  +	a.setMul(rot0, ss); +	 +	// <t0*sinAng, t0*cosAng, t1*sinAng, t1*cosAng> +	LLVector4a t0; +	t0.splat(st, 1); +	LLVector4a t1; +	t1.splat(st, 3); +	LLVector4a tt; +	tt.setSelectWithMask(mask, t1, t0); + +	LLVector4a b; +	b.setMul(rot1, tt); +		 +	st.setAdd(a,b); + +	// Then scale +	st.mul(scale); + +	// Then offset +	tex_coord.setAdd(st, offset); +} +  bool less_than_max_mag(const LLVector4a& vec)  { @@ -1060,6 +1103,16 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail"); +static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos"); +static LLFastTimer::DeclareTimer FTM_FACE_TEXTURE_INDEX_STORE("TexIdx"); +static LLFastTimer::DeclareTimer FTM_FACE_POSITION_PAD("Pad"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); + +static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar");  BOOL LLFace::getGeometryVolume(const LLVolume& volume,  							   const S32 &f, @@ -1078,7 +1131,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		updateRebuildFlags();  	} -	bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange; + +	//don't use map range (generates many redundant unmap calls) +	bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;  	if (mVertexBuffer.notNull())  	{ @@ -1104,16 +1159,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	}  	LLStrider<LLVector3> vert; -	LLVector4a* vertices = NULL;  	LLStrider<LLVector2> tex_coords;  	LLStrider<LLVector2> tex_coords2; -	LLVector4a* normals = NULL;  	LLStrider<LLVector3> norm;  	LLStrider<LLColor4U> colors; -	LLVector4a* binormals = NULL;  	LLStrider<LLVector3> binorm;  	LLStrider<U16> indicesp; -	LLVector4a* weights = NULL;  	LLStrider<LLVector4> wght;  	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); @@ -1202,7 +1253,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		LLFastTimer t(FTM_FACE_GEOM_INDEX);  		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range); -		__m128i* dst = (__m128i*) indicesp.get(); +		volatile __m128i* dst = (__m128i*) indicesp.get();  		__m128i* src = (__m128i*) vf.mIndices;  		__m128i offset = _mm_set1_epi16(index_offset); @@ -1211,12 +1262,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		for (S32 i = 0; i < end; i++)  		{  			__m128i res = _mm_add_epi16(src[i], offset); -			_mm_storeu_si128(dst+i, res); +			_mm_storeu_si128((__m128i*) dst++, res);  		} -		for (S32 i = end*8; i < num_indices; ++i)  		{ -			indicesp[i] = vf.mIndices[i]+index_offset; +			LLFastTimer t(FTM_FACE_GEOM_INDEX_TAIL); +			U16* idx = (U16*) dst; + +			for (S32 i = end*8; i < num_indices; ++i) +			{ +				*idx++ = vf.mIndices[i]+index_offset; +			}  		}  		if (map_range) @@ -1373,19 +1429,48 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)  			{ +				LLFastTimer t(FTM_FACE_TEX_QUICK);  				if (!do_tex_mat)  				{  					if (!do_xform)  					{ +						LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM);  						LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));  					}  					else  					{ -						for (S32 i = 0; i < num_vertices; i++) +						LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); +						F32* dst = (F32*) tex_coords.get(); +						LLVector4a* src = (LLVector4a*) vf.mTexCoords; + +						LLVector4a trans; +						trans.splat(-0.5f); + +						LLVector4a rot0; +						rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + +						LLVector4a rot1; +						rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + +						LLVector4a scale; +						scale.set(ms, mt, ms, mt); + +						LLVector4a offset; +						offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + +						LLVector4Logical mask; +						mask.clear(); +						mask.setElement<2>(); +						mask.setElement<3>(); + +						U32 count = num_vertices/2 + num_vertices%2; + +						for (S32 i = 0; i < count; i++)  						{	 -							LLVector2 tc(vf.mTexCoords[i]); -							xform(tc, cos_ang, sin_ang, os, ot, ms, mt); -							*tex_coords++ = tc;	 +							LLVector4a res = *src++; +							xform4a(res, trans, mask, rot0, rot1, offset, scale); +							res.store4a(dst); +							dst += 4;  						}  					}  				} @@ -1407,6 +1492,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			}  			else  			{ //no bump, no atlas, tex gen planar +				LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR);  				if (do_tex_mat)  				{  					for (S32 i = 0; i < num_vertices; i++) @@ -1451,6 +1537,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		}  		else  		{ //either bump mapped or in atlas, just do the whole expensive loop +			LLFastTimer t(FTM_FACE_TEX_DEFAULT);  			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);  			std::vector<LLVector2> bump_tc; @@ -1642,44 +1729,55 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		llassert(num_vertices > 0);  		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); -		vertices = (LLVector4a*) vert.get(); -	 +			 +  		LLMatrix4a mat_vert;  		mat_vert.loadu(mat_vert_in);  		LLVector4a* src = vf.mPositions; -		LLVector4a* dst = vertices; +		volatile F32* dst = (volatile F32*) vert.get(); -		LLVector4a* end = dst+num_vertices; -		do -		{	 -			mat_vert.affineTransform(*src++, *dst++); -		} -		while(dst < end); +		volatile F32* end = dst+num_vertices*4; +		LLVector4a res; -		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); +		LLVector4a texIdx; +		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);  		llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); -		F32 *index_dst = (F32*) vertices; -		F32 *index_end = (F32*) end; -		index_dst += 3; -		index_end += 3; -		do +		LLVector4Logical mask; +		mask.clear(); +		mask.setElement<3>(); +		 +		texIdx.set(0,0,0,index); +  		{ -			*index_dst = index; -			index_dst += 4; +			LLFastTimer t(FTM_FACE_POSITION_STORE); +			LLVector4a tmp; + +			do +			{	 +				mat_vert.affineTransform(*src++, res); +				tmp.setSelectWithMask(mask, texIdx, res); +				tmp.store4a((F32*) dst); +				dst += 4; +			} +			while(dst < end);  		} -		while (index_dst < index_end); -		 -		S32 aligned_pad_vertices = mGeomCount - num_vertices; -		LLVector4a* last_vec = end - 1; -		while (aligned_pad_vertices > 0) +  		{ -			--aligned_pad_vertices; -			*dst++ = *last_vec; +			LLFastTimer t(FTM_FACE_POSITION_PAD); +			S32 aligned_pad_vertices = mGeomCount - num_vertices; +			res.set(res[0], res[1], res[2], 0.f); + +			while (aligned_pad_vertices > 0) +			{ +				--aligned_pad_vertices; +				res.store4a((F32*) dst); +				dst += 4; +			}  		} -		 +  		if (map_range)  		{  			mVertexBuffer->flush(); @@ -1690,14 +1788,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	{  		LLFastTimer t(FTM_FACE_GEOM_NORMAL);  		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); -		normals = (LLVector4a*) norm.get(); +		F32* normals = (F32*) norm.get();  		for (S32 i = 0; i < num_vertices; i++)  		{	  			LLVector4a normal;  			mat_normal.rotate(vf.mNormals[i], normal);  			normal.normalize3fast(); -			normals[i] = normal; +			normal.store4a(normals); +			normals += 4;  		}  		if (map_range) @@ -1710,14 +1809,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	{  		LLFastTimer t(FTM_FACE_GEOM_BINORMAL);  		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); -		binormals = (LLVector4a*) binorm.get(); +		F32* binormals = (F32*) binorm.get();  		for (S32 i = 0; i < num_vertices; i++)  		{	  			LLVector4a binormal;  			mat_normal.rotate(vf.mBinormals[i], binormal);  			binormal.normalize3fast(); -			binormals[i] = binormal; +			binormal.store4a(binormals); +			binormals += 4;  		}  		if (map_range) @@ -1730,8 +1830,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	{  		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS);  		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); -		weights = (LLVector4a*) wght.get(); -		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); +		F32* weights = (F32*) wght.get(); +		LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));  		if (map_range)  		{  			mVertexBuffer->flush(); @@ -1750,7 +1850,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		src.loadua((F32*) vec); -		LLVector4a* dst = (LLVector4a*) colors.get(); +		F32* dst = (F32*) colors.get();  		S32 num_vecs = num_vertices/4;  		if (num_vertices%4 > 0)  		{ @@ -1759,7 +1859,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		for (S32 i = 0; i < num_vecs; i++)  		{	 -			dst[i] = src; +			src.store4a(dst); +			dst += 4;  		}  		if (map_range) @@ -1789,7 +1890,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		src.loadua((F32*) vec); -		LLVector4a* dst = (LLVector4a*) emissive.get(); +		F32* dst = (F32*) emissive.get();  		S32 num_vecs = num_vertices/4;  		if (num_vertices%4 > 0)  		{ @@ -1798,7 +1899,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		for (S32 i = 0; i < num_vecs; i++)  		{	 -			dst[i] = src; +			src.store4a(dst); +			dst += 4;  		}  		if (map_range) @@ -1821,6 +1923,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		mTexExtents[1][1] *= et ;  	} +  	mLastVertexBuffer = mVertexBuffer;  	mLastGeomCount = mGeomCount;  	mLastGeomIndex = mGeomIndex; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index d8e4aa03f7..95da8ff948 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2474,27 +2474,6 @@ void LLPanelLandAccess::refresh()  				mListBanned->addNameItem(entry.mID, ADD_DEFAULT, TRUE, suffix);  			}  		} -		 -		LLCheckBoxWithTBAcess* maturity_checkbox = (LLCheckBoxWithTBAcess*) getChild<LLCheckBoxCtrl>( "public_access"); -		LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); -		if(region) -		{ -			LLTextBox* maturity_textbox = maturity_checkbox->getTextBox(); -			insert_maturity_into_textbox(maturity_textbox, gFloaterView->getParentFloater(this), getString("allow_public_access")); -			maturity_checkbox->reshape(maturity_checkbox->getRect().getWidth(), maturity_checkbox->getRect().getHeight(), FALSE); -		} -		else -		{ -			std::string maturity_string = getString("allow_public_access"); -			size_t maturity_pos = maturity_string.find(MATURITY); - -			if (maturity_pos != std::string::npos) -			{ -				maturity_string.replace(maturity_pos, MATURITY.length(), std::string("")); -			} - -			maturity_checkbox->setLabel(maturity_string); -		}  		if(parcel->getRegionDenyAnonymousOverride())  		{ diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 64bdcccd9f..9122e5a8f5 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3969,7 +3969,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  				U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();  				if (num_indices > 2)  				{ -					glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f); +					glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*) mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);  				}  				tri_count += num_indices/3;  				stop_gloderror(); @@ -4083,14 +4083,14 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim  				{  					buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true);  					buff->setBuffer(type_mask); -					glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer()); +					glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*) buff->getIndicesPointer());  					stop_gloderror();  				}  				else  				{ //this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0)  					buff->allocateBuffer(1, 3, true); -					memset(buff->getMappedData(), 0, buff->getSize()); -					memset(buff->getIndicesPointer(), 0, buff->getIndicesSize()); +					memset((U8*) buff->getMappedData(), 0, buff->getSize()); +					memset((U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize());  				}  				buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0); @@ -4880,8 +4880,8 @@ void LLModelPreview::addEmptyFace( LLModel* pTarget )  	LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);  	buff->allocateBuffer(1, 3, true); -	memset( buff->getMappedData(), 0, buff->getSize() ); -	memset( buff->getIndicesPointer(), 0, buff->getIndicesSize() ); +	memset( (U8*) buff->getMappedData(), 0, buff->getSize() ); +	memset( (U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize() );  	buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 ); diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index bf6cf52298..a12ec390af 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -60,12 +60,10 @@ public:  private:  	void update(); -	void onNameCache(const LLUUID& id, const std::string& name, bool is_group);  private:  	LLUUID		 mObjectID;  	LLUUID		 mOwnerID; -	std::string  mOwnerLegacyName;  	std::string  mSLurl;  	std::string  mName;  	bool         mGroupOwned; @@ -75,7 +73,6 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :  	LLInspect(LLSD()),  	mObjectID(NULL),  	mOwnerID(NULL), -	mOwnerLegacyName(),  	mSLurl(""),  	mName(""),  	mGroupOwned(false) @@ -111,14 +108,6 @@ void LLInspectRemoteObject::onOpen(const LLSD& data)  	mGroupOwned = data["group_owned"].asBoolean();  	mSLurl      = data["slurl"].asString(); -	// work out the owner's name -	mOwnerLegacyName = ""; -	if (gCacheName) -	{ -		gCacheName->get(mOwnerID, mGroupOwned,  // muting -			boost::bind(&LLInspectRemoteObject::onNameCache, this, _1, _2, _3)); -	} -  	// update the inspector with the current object state  	update(); @@ -144,8 +133,7 @@ void LLInspectRemoteObject::onClickMap()  void LLInspectRemoteObject::onClickBlock()  { -	LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT; -	LLMute mute(mOwnerID, mOwnerLegacyName, mute_type); +	LLMute mute(mObjectID, mName, LLMute::OBJECT);  	LLMuteList::getInstance()->add(mute);  	LLPanelBlockedList::showPanelAndSelect(mute.mID);  	closeFloater(); @@ -156,12 +144,6 @@ void LLInspectRemoteObject::onClickClose()  	closeFloater();  } -void LLInspectRemoteObject::onNameCache(const LLUUID& id, const std::string& name, bool is_group) -{ -	mOwnerLegacyName = name; -	update(); -} -  void LLInspectRemoteObject::update()  {  	// show the object name as the inspector's title @@ -198,8 +180,8 @@ void LLInspectRemoteObject::update()  	// disable the Map button if we don't have a SLurl  	getChild<LLUICtrl>("map_btn")->setEnabled(! mSLurl.empty()); -	// disable the Block button if we don't have the owner ID -	getChild<LLUICtrl>("block_btn")->setEnabled(! mOwnerID.isNull()); +	// disable the Block button if we don't have the object ID (will this ever happen?) +	getChild<LLUICtrl>("block_btn")->setEnabled(! mObjectID.isNull());  }  ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 76576f7b75..257ceed912 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -73,7 +73,7 @@  #include "llwearablelist.h"  // Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	1 +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU	0  #define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0  #define BLOCK_WORN_ITEMS_IN_OUTBOX 1 @@ -3711,9 +3711,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// If an item is being dragged between windows, unselect everything in the active window   			// so that we don't follow the selection to its new location (which is very annoying).  			if (active_panel && (destination_panel != active_panel)) -			{ -				active_panel->unSelectAll(); -			} +				{ +					active_panel->unSelectAll(); +				}  			//--------------------------------------------------------------------------------  			// Destination folder logic diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a97e256c89..b02bf79a28 100644..100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -88,6 +88,9 @@ const S32 MAX_MESH_VERSION = 999;  U32 LLMeshRepository::sBytesReceived = 0;  U32 LLMeshRepository::sHTTPRequestCount = 0;  U32 LLMeshRepository::sHTTPRetryCount = 0; +U32 LLMeshRepository::sLODProcessing = 0; +U32 LLMeshRepository::sLODPending = 0; +  U32 LLMeshRepository::sCacheBytesRead = 0;  U32 LLMeshRepository::sCacheBytesWritten = 0;  U32 LLMeshRepository::sPeakKbps = 0; @@ -205,6 +208,12 @@ public:  	LLMeshHeaderResponder(const LLVolumeParams& mesh_params)  		: mMeshParams(mesh_params)  	{ +		LLMeshRepoThread::sActiveHeaderRequests++; +	} + +	~LLMeshHeaderResponder() +	{ +		LLMeshRepoThread::sActiveHeaderRequests--;  	}  	virtual void completedRaw(U32 status, const std::string& reason, @@ -224,6 +233,12 @@ public:  	LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes)  		: mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes)  	{ +		LLMeshRepoThread::sActiveLODRequests++; +	} + +	~LLMeshLODResponder() +	{ +		LLMeshRepoThread::sActiveLODRequests--;  	}  	virtual void completedRaw(U32 status, const std::string& reason, @@ -497,10 +512,13 @@ void LLMeshRepoThread::run()  					mMutex->lock();  					LODRequest req = mLODReqQ.front();  					mLODReqQ.pop(); +					LLMeshRepository::sLODProcessing--;  					mMutex->unlock(); -					if (fetchMeshLOD(req.mMeshParams, req.mLOD)) +					if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit  					{ -						count++; +						mMutex->lock(); +						mLODReqQ.push(req) ;  +						mMutex->unlock();  					}  				}  			} @@ -512,9 +530,11 @@ void LLMeshRepoThread::run()  					HeaderRequest req = mHeaderReqQ.front();  					mHeaderReqQ.pop();  					mMutex->unlock(); -					if (fetchMeshHeader(req.mMeshParams)) +					if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit  					{ -						count++; +						mMutex->lock(); +						mHeaderReqQ.push(req) ; +						mMutex->unlock();  					}  				}  			} @@ -603,6 +623,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  		{  			LLMutexLock lock(mMutex);  			mLODReqQ.push(req); +			LLMeshRepository::sLODProcessing++;  		}  	}  	else @@ -658,6 +679,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  		return false;  	} +	bool ret = true ;  	U32 header_size = mMeshHeaderSize[mesh_id];  	if (header_size > 0) @@ -673,7 +695,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			//check VFS for mesh skin info  			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);  			if (file.getSize() >= offset+size) -			{ +			{				  				LLMeshRepository::sCacheBytesRead += size;  				file.seek(offset);  				U8* buffer = new U8[size]; @@ -689,7 +711,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  				if (!zero)  				{ //attempt to parse  					if (skinInfoReceived(mesh_id, buffer, size)) -					{ +					{						  						delete[] buffer;  						return true;  					} @@ -704,11 +726,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshSkinInfoResponder(mesh_id, offset, size)); +				if(ret) +				{ +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  	} @@ -718,7 +742,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  }  bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) @@ -732,7 +756,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	}  	U32 header_size = mMeshHeaderSize[mesh_id]; - +	bool ret = true ; +	  	if (header_size > 0)  	{  		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); @@ -748,6 +773,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			if (file.getSize() >= offset+size)  			{  				LLMeshRepository::sCacheBytesRead += size; +  				file.seek(offset);  				U8* buffer = new U8[size];  				file.read(buffer, size); @@ -777,11 +803,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(http_url, headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshDecompositionResponder(mesh_id, offset, size)); +				if(ret) +				{ +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  	} @@ -791,7 +819,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  }  bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) @@ -805,6 +833,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	}  	U32 header_size = mMeshHeaderSize[mesh_id]; +	bool ret = true ;  	if (header_size > 0)  	{ @@ -850,11 +879,14 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(http_url, headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + +				if(ret) +				{ +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  		else @@ -868,13 +900,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  } -bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +//return false if failed to get header +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)  { -	bool retval = false; -  	{  		//look for mesh in asset in vfs  		LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); @@ -889,36 +920,39 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)  			file.read(buffer, bytes);  			if (headerReceived(mesh_params, buffer, bytes))  			{ //did not do an HTTP request, return false -				return false; +				return true;  			}  		}  	} -	//either cache entry doesn't exist or is corrupt, request header from simulator - +	//either cache entry doesn't exist or is corrupt, request header from simulator	 +	bool retval = true ;  	std::vector<std::string> headers;  	headers.push_back("Accept: application/octet-stream");  	std::string http_url = constructUrl(mesh_params.getSculptID());  	if (!http_url.empty())  	{ -		++sActiveHeaderRequests; -		retval = true;  		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits  		//within the first 4KB -		//NOTE -- this will break of headers ever exceed 4KB -		LLMeshRepository::sHTTPRequestCount++; -		mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); +		//NOTE -- this will break of headers ever exceed 4KB		 +		retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); +		if(retval) +		{ +			LLMeshRepository::sHTTPRequestCount++; +		} +		count++;  	}  	return retval;  } -bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +//return false if failed to get mesh lod. +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)  { //protected by mMutex  	mHeaderMutex->lock(); -	bool retval = false; +	bool retval = true;  	LLUUID mesh_id = mesh_params.getSculptID(); @@ -955,7 +989,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  					if (lodReceived(mesh_params, lod, buffer, size))  					{  						delete[] buffer; -						return false; +						return true;  					}  				} @@ -968,12 +1002,15 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				retval = true; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, +			{				 +				retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,  										   new LLMeshLODResponder(mesh_params, lod, offset, size)); + +				if(retval) +				{ +					LLMeshRepository::sHTTPRequestCount++; +				} +				count++;  			}  			else  			{ @@ -1045,6 +1082,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  			{  				LODRequest req(mesh_params, iter->second[i]);  				mLODReqQ.push(req); +				LLMeshRepository::sLODProcessing++;  			}  		}  		mPendingLOD.erase(iter); @@ -1540,8 +1578,17 @@ void LLMeshUploadThread::doWholeModelUpload()  		LLSD body = full_model_data["asset_resources"];  		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));  		LLCurlRequest::headers_t headers; -		mCurlRequest->post(mWholeModelUploadURL, headers, body, -						   new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut); + +		{ +			LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ; + +			while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut)) +			{ +				//sleep for 10ms to prevent eating a whole core +				apr_sleep(10000); +			} +		} +  		do  		{  			mCurlRequest->process(); @@ -1571,8 +1618,15 @@ void LLMeshUploadThread::requestWholeModelFee()  	mPendingUploads++;  	LLCurlRequest::headers_t headers; -	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, -					   new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); + +	{ +		LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ; +		while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut)) +		{ +			//sleep for 10ms to prevent eating a whole core +			apr_sleep(10000); +		} +	}  	do  	{ @@ -1712,7 +1766,6 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,  							  const LLIOPipe::buffer_ptr_t& buffer)  { -	LLMeshRepoThread::sActiveLODRequests--;  	S32 data_size = buffer->countAfter(channels.in(), NULL);  	if (status < 200 || status > 400) @@ -1929,7 +1982,6 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  							  const LLChannelDescriptors& channels,  							  const LLIOPipe::buffer_ptr_t& buffer)  { -	LLMeshRepoThread::sActiveHeaderRequests--;  	if (status < 200 || status > 400)  	{  		//llwarns @@ -2147,6 +2199,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para  			//first request for this mesh  			mLoadingMeshes[detail][mesh_params].insert(vobj->getID());  			mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); +			LLMeshRepository::sLODPending++;  		}  	} @@ -2359,6 +2412,7 @@ void LLMeshRepository::notifyLoadedMeshes()  			LLMeshRepoThread::LODRequest& request = mPendingRequests.front();  			mThread->loadMeshLOD(request.mMeshParams, request.mLOD);  			mPendingRequests.erase(mPendingRequests.begin()); +			LLMeshRepository::sLODPending--;  			push_count--;  		}  	} diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 31b84ea0d9..da81bb057b 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -323,8 +323,8 @@ public:  	virtual void run();  	void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); -	bool fetchMeshHeader(const LLVolumeParams& mesh_params); -	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); +	bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count); +	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count);  	bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);  	bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);  	bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); @@ -441,6 +441,8 @@ public:  	static U32 sBytesReceived;  	static U32 sHTTPRequestCount;  	static U32 sHTTPRetryCount; +	static U32 sLODPending; +	static U32 sLODProcessing;  	static U32 sCacheBytesRead;  	static U32 sCacheBytesWritten;  	static U32 sPeakKbps; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 5d0d1ef9a3..6111255a66 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5556,38 +5556,37 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power)  //helper function for pushing relevant vertices from drawable to GL  void pushWireframe(LLDrawable* drawable)  { -	if (drawable->isState(LLDrawable::RIGGED)) -	{ //render straight from rigged volume if this is a rigged attachment -		LLVOVolume* vobj = drawable->getVOVolume(); -		if (vobj) -		{ -			vobj->updateRiggedVolume(); -			LLRiggedVolume* rigged_volume = vobj->getRiggedVolume(); -			if (rigged_volume) -			{ -				LLVertexBuffer::unbind(); -				gGL.pushMatrix(); -				gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); -				for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i) -				{ -					const LLVolumeFace& face = rigged_volume->getVolumeFace(i); -					LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); -				} -				gGL.popMatrix(); -			} -		} -	} -	else +	LLVOVolume* vobj = drawable->getVOVolume(); +	if (vobj)  	{ -		for (S32 i = 0; i < drawable->getNumFaces(); ++i) +		LLVertexBuffer::unbind(); +		gGL.pushMatrix(); +		gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + +		LLVolume* volume = NULL; + +		if (drawable->isState(LLDrawable::RIGGED)) +		{ +				vobj->updateRiggedVolume(); +				volume = vobj->getRiggedVolume(); +		} +		else +		{ +			volume = vobj->getVolume(); +		} + +		if (volume)  		{ -			LLFace* face = drawable->getFace(i); -			if (face->verify()) +			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)  			{ -				pushVerts(face, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); +				const LLVolumeFace& face = volume->getVolumeFace(i); +				LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices);  			}  		} + +		gGL.popMatrix();  	} +	  }  void LLSelectNode::renderOneWireframe(const LLColor4& color) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 900f126049..5d196a465f 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -264,7 +264,7 @@ static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");  void LLSpatialGroup::buildOcclusion()  { -	if (mOcclusionVerts.isNull()) +	//if (mOcclusionVerts.isNull())  	{  		mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX,   			LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. @@ -726,7 +726,9 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  	if (vertex_count > 0 && index_count > 0)  	{ //create vertex buffer containing volume geometry for this node  		group->mBuilt = 1.f; -		if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) +		if (group->mVertexBuffer.isNull() || +			!group->mVertexBuffer->isWriteable() || +			(group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))  		{  			group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);  			group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); @@ -1185,6 +1187,8 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)  LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :  	mState(0), +	mGeometryBytes(0), +	mSurfaceArea(0.f),  	mBuilt(0.f),  	mOctreeNode(node),  	mSpatialPartition(part), @@ -1410,6 +1414,17 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)  		}  	} +	//clean up avatar attachment stats +	LLSpatialBridge* bridge = mSpatialPartition->asBridge(); +	if (bridge) +	{ +		if (bridge->mAvatar.notNull()) +		{ +			bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes; +			bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea; +		} +	} +  	clearDrawMap();  	mVertexBuffer = NULL;  	mBufferMap.clear(); @@ -1765,7 +1780,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  //==============================================  LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) -: mRenderByGroup(render_by_group) +: mRenderByGroup(render_by_group), mBridge(NULL)  {  	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);  	mOcclusionEnabled = TRUE; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 899547ae4d..6c14ecf452 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -405,6 +405,9 @@ public:  	bridge_list_t mBridgeList;  	buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers +	U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node +	F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node +  	F32 mBuilt;  	OctreeNode* mOctreeNode;  	LLSpatialPartition* mSpatialPartition; @@ -474,8 +477,8 @@ public:  	BOOL isVisible(const LLVector3& v);  	bool isHUDPartition() ; -	virtual LLSpatialBridge* asBridge() { return NULL; } -	virtual BOOL isBridge() { return asBridge() != NULL; } +	LLSpatialBridge* asBridge() { return mBridge; } +	BOOL isBridge() { return asBridge() != NULL; }  	void renderPhysicsShapes();  	void renderDebug(); @@ -487,6 +490,9 @@ public:  public:  	LLSpatialGroup::OctreeNode* mOctree; +	LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this +							// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe +							// to call asBridge() from the destructor  	BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed  	BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane  	U32 mBufferUsage; @@ -511,8 +517,9 @@ public:  	LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); -	virtual BOOL isSpatialBridge() const		{ return TRUE; } +	void destroyTree(); +	virtual BOOL isSpatialBridge() const		{ return TRUE; }  	virtual void updateSpatialExtents();  	virtual void updateBinRadius();  	virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE); @@ -523,11 +530,12 @@ public:  	virtual void shiftPos(const LLVector4a& vec);  	virtual void cleanupReferences();  	virtual LLSpatialPartition* asPartition()		{ return this; } -	virtual LLSpatialBridge* asBridge()				{ return this; } -	 +		  	virtual LLCamera transformCamera(LLCamera& camera);  	LLDrawable* mDrawable; +	LLPointer<LLVOAvatar> mAvatar; +  };  class LLCullResult  diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 85dadb213c..4f43547dae 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -261,6 +261,8 @@ private:  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  class LLTexLayerSetBuffer : public LLViewerDynamicTexture  { +	LOG_CLASS(LLTexLayerSetBuffer); +  public:  	LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);  	virtual ~LLTexLayerSetBuffer(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4a71e6fc8e..12aed8f448 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -947,6 +947,10 @@ U32 info_display_from_string(std::string info_display)  	{  		return LLPipeline::RENDER_DEBUG_COMPOSITION;  	} +	else if ("attachment bytes" == info_display) +	{ +		return LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES; +	}  	else if ("glow" == info_display)  	{  		return LLPipeline::RENDER_DEBUG_GLOW; @@ -2786,8 +2790,31 @@ bool enable_object_mute()  	else  	{  		// Just a regular object -		return LLSelectMgr::getInstance()->getSelection()-> -			contains( object, SELECT_ALL_TES ); +		return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && +			   !LLMuteList::getInstance()->isMuted(object->getID()); +	} +} + +bool enable_object_unmute() +{ +	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +	if (!object) return false; + +	LLVOAvatar* avatar = find_avatar_from_object(object);  +	if (avatar) +	{ +		// It's an avatar +		LLNameValue *lastname = avatar->getNVPair("LastName"); +		bool is_linden = +			lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); +		bool is_self = avatar->isSelf(); +		return !is_linden && !is_self; +	} +	else +	{ +		// Just a regular object +		return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && +			   LLMuteList::getInstance()->isMuted(object->getID());;  	}  } @@ -8302,6 +8329,7 @@ void initialize_menus()  	enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));  	enable.add("Object.EnableMute", boost::bind(&enable_object_mute)); +	enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute));  	enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));  	commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom")); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b8772971aa..37fb77a10a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5520,11 +5520,12 @@ void LLViewerObject::dirtyMesh()  {  	if (mDrawable)  	{ -		LLSpatialGroup* group = mDrawable->getSpatialGroup(); +		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); +		/*LLSpatialGroup* group = mDrawable->getSpatialGroup();  		if (group)  		{  			group->dirtyMesh(); -		} +		}*/  	}  } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 236c828c16..f5a226b781 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -609,7 +609,9 @@ public:  				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,  					LLMeshRepository::sHTTPRetryCount)); +				ypos += y_inc; +				addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing));  				ypos += y_inc;  				addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); @@ -1954,18 +1956,24 @@ void LLViewerWindow::shutdownViews()  	// clean up warning logger  	LLError::removeRecorder(RecordToChatConsole::getInstance()); +	llinfos << "Warning logger is cleaned." << llendl ; +  	delete mDebugText;  	mDebugText = NULL; +	llinfos << "DebugText deleted." << llendl ; +  	// Cleanup global views  	if (gMorphView)  	{  		gMorphView->setVisible(FALSE);  	} +	llinfos << "Global views cleaned." << llendl ;  	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open  	// will crump with LL_ERRS.  	LLModalDialog::shutdownModals(); +	llinfos << "LLModalDialog shut down." << llendl;   	// destroy the nav bar, not currently part of gViewerWindow  	// *TODO: Make LLNavigationBar part of gViewerWindow @@ -1973,14 +1981,17 @@ void LLViewerWindow::shutdownViews()  	{  		delete LLNavigationBar::getInstance();  	} +	llinfos << "LLNavigationBar destroyed." << llendl ;  	// destroy menus after instantiating navbar above, as it needs  	// access to gMenuHolder  	cleanup_menus(); +	llinfos << "menus destroyed." << llendl ;  	// Delete all child views.  	delete mRootView;  	mRootView = NULL; +	llinfos << "RootView deleted." << llendl ;  	// Automatically deleted as children of mRootView.  Fix the globals.  	gStatusBar = NULL; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 68637a7ed9..bc7f5a9744 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -651,6 +651,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	LLViewerObject(id, pcode, regionp),  	mIsDummy(FALSE),  	mSpecialRenderMode(0), +	mAttachmentGeometryBytes(0), +	mAttachmentSurfaceArea(0.f),  	mTurning(FALSE),  	mPelvisToFoot(0.f),  	mLastSkeletonSerialNum( 0 ), @@ -3363,6 +3365,16 @@ void LLVOAvatar::slamPosition()  	mRoot.updateWorldMatrixChildren();  } +bool LLVOAvatar::isVisuallyMuted() +{ +	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); +	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); +	 +	return LLMuteList::getInstance()->isMuted(getID()) || +			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || +			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +} +  //------------------------------------------------------------------------  // updateCharacter()  // called on both your avatar and other avatars @@ -3429,8 +3441,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		size.setSub(ext[1],ext[0]);  		F32 mag = size.getLength3().getF32()*0.5f; +		  		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); -		if (LLMuteList::getInstance()->isMuted(getID())) +		if (isVisuallyMuted())  		{ // muted avatars update at 16 hz  			mUpdatePeriod = 16;  		} @@ -8333,6 +8346,11 @@ void LLVOAvatar::idleUpdateRenderCost()  	static std::set<LLUUID> all_textures; +	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)) +	{ //set debug text to attachment geometry bytes here so render cost will override +		setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea)); +	} +  	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))  	{  		return; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 59796370ae..dd0317f555 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -78,6 +78,8 @@ class LLVOAvatar :  	public LLCharacter,  	public boost::signals2::trackable  { +	LOG_CLASS(LLVOAvatar); +  public:  	friend class LLVOAvatarSelf;  protected: @@ -380,6 +382,8 @@ private:  public:  	U32 		renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); +	bool		isVisuallyMuted(); +  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass);  	F32			getLastSkinTime() { return mLastSkinTime; } @@ -391,6 +395,9 @@ public:  	static void	restoreGL();  	BOOL 		mIsDummy; // for special views  	S32			mSpecialRenderMode; // special lighting +	U32			mAttachmentGeometryBytes; //number of bytes in attached geometry +	F32			mAttachmentSurfaceArea; //estimated surface area of attachments +  private:  	bool		shouldAlphaMask(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 12d08143ee..8be9516ab6 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1574,7 +1574,7 @@ void LLVOAvatarSelf::invalidateAll()  	{  		invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE);  	} -	mDebugSelfLoadTimer.reset(); +	//mDebugSelfLoadTimer.reset();  }  //----------------------------------------------------------------------------- @@ -1896,11 +1896,13 @@ BOOL LLVOAvatarSelf::getIsCloud()  		gAgentWearables.getWearableCount(LLWearableType::WT_EYES) == 0 ||  		gAgentWearables.getWearableCount(LLWearableType::WT_SKIN) == 0)	  	{ +		lldebugs << "No body parts" << llendl;  		return TRUE;  	}  	if (!isTextureDefined(TEX_HAIR, 0))  	{ +		lldebugs << "No hair texture" << llendl;  		return TRUE;  	} @@ -1909,12 +1911,14 @@ BOOL LLVOAvatarSelf::getIsCloud()  		if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) &&  			(!isTextureDefined(TEX_LOWER_BAKED, 0)))  		{ +			lldebugs << "Lower textures not baked" << llendl;  			return TRUE;  		}  		if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) &&  			(!isTextureDefined(TEX_UPPER_BAKED, 0)))  		{ +			lldebugs << "Upper textures not baked" << llendl;  			return TRUE;  		} @@ -1931,10 +1935,12 @@ BOOL LLVOAvatarSelf::getIsCloud()  			const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 );  			if (!baked_img || !baked_img->hasGLTexture())  			{ +				lldebugs << "Texture at index " << i << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << llendl;  				return TRUE;  			}  		} +		lldebugs << "Avatar de-clouded" << llendl;  	}  	return FALSE;  } @@ -2258,6 +2264,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )  	}  } +// FIXME: This is never called. Something may be broken.  void LLVOAvatarSelf::outputRezDiagnostics() const  {  	if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) @@ -2315,6 +2322,18 @@ void LLVOAvatarSelf::outputRezDiagnostics() const  	}  } +void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const +{ +	LL_DEBUGS("Avatar Rez") +		<< llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) +		<< llendl; +} + +void LLVOAvatarSelf::reportAvatarRezTime() const +{ +	// TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow. +} +  //-----------------------------------------------------------------------------  // setCachedBakedTexture()  // A baked texture id was received from a cache query, make it active diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 74ff47a3e4..54dbe81993 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -41,6 +41,7 @@ struct LocalTextureData;  class LLVOAvatarSelf :  	public LLVOAvatar  { +	LOG_CLASS(LLVOAvatarSelf);  /********************************************************************************   **                                                                            ** @@ -358,6 +359,8 @@ public:  	void 					debugWearablesLoaded() { mDebugTimeWearablesLoaded = mDebugSelfLoadTimer.getElapsedTimeF32(); }  	void 					debugAvatarVisible() { mDebugTimeAvatarVisible = mDebugSelfLoadTimer.getElapsedTimeF32(); }  	void 					outputRezDiagnostics() const; +	void					outputRezTiming(const std::string& msg) const; +	void					reportAvatarRezTime() const;  	void 					debugBakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished);  	static void				debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index c3a2e6a712..bf6158eeaf 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -65,7 +65,7 @@ public:  			return;  		} -		U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; +		volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;  		//assume tex coords 2 and 3 are present  		U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 20f8674655..7492a06784 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4097,6 +4097,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); +	LLVOAvatar* pAvatarVO = NULL; + +	LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); +	if (bridge) +	{ +		if (bridge->mAvatar.isNull()) +		{ +			LLViewerObject* vobj = bridge->mDrawable->getVObj(); +			if (vobj) +			{ +				bridge->mAvatar = vobj->getAvatar(); +			} +		} + +		pAvatarVO = bridge->mAvatar; +	} + +	if (pAvatarVO) +	{ +		pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes; +		pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea; +	} + +	group->mGeometryBytes = 0; +	group->mSurfaceArea = 0; +	  	group->clearDrawMap();  	mFaceList.clear(); @@ -4133,12 +4159,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		LLVOVolume* vobj = drawablep->getVOVolume(); +		if (!vobj) +		{ +			continue; +		} +  		if (vobj->isMesh() &&  			(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))  		{  			continue;  		} +		LLVolume* volume = vobj->getVolume(); +		if (volume) +		{ +			const LLVector3& scale = vobj->getScale(); +			group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); +		} +  		llassert_always(vobj);  		vobj->updateTextureVirtualSize(true);  		vobj->preRebuild(); @@ -4183,7 +4221,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  				//Determine if we've received skininfo that contains an  				//alternate bind matrix - if it does then apply the translational component  				//to the joints of the avatar. -				LLVOAvatar* pAvatarVO = vobj->getAvatar();  				bool pelvisGotSet = false;  				if ( pAvatarVO ) @@ -4253,13 +4290,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					if (type == LLDrawPool::POOL_ALPHA)  					{ -						if (te->getFullbright()) +						if (te->getColor().mV[3] > 0.f)  						{ -							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); -						} -						else -						{ -							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); +							if (te->getFullbright()) +							{ +								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); +							} +							else +							{ +								pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); +							}  						}  					}  					else if (te->getShiny()) @@ -4392,8 +4432,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					}  					else  					{ -						drawablep->setState(LLDrawable::HAS_ALPHA); -						alpha_faces.push_back(facep); +						if (te->getColor().mV[3] > 0.f) +						{ +							drawablep->setState(LLDrawable::HAS_ALPHA); +							alpha_faces.push_back(facep); +						}  					}  				}  				else @@ -4510,6 +4553,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	}  	mFaceList.clear(); + +	if (pAvatarVO) +	{ +		pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes; +		pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea; +	}  }  static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); @@ -4806,17 +4855,20 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		//create/delete/resize vertex buffer if needed  		LLVertexBuffer* buffer = NULL; -		LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); + +		{ //try to find a buffer to reuse +			LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); -		if (found_iter != group->mBufferMap[mask].end()) -		{ -			if ((U32) buffer_index < found_iter->second.size()) +			if (found_iter != group->mBufferMap[mask].end())  			{ -				buffer = found_iter->second[buffer_index]; +				if ((U32) buffer_index < found_iter->second.size()) +				{ +					buffer = found_iter->second[buffer_index]; +				}  			}  		} -		if (!buffer) +		if (!buffer || !buffer->isWriteable())  		{ //create new buffer if needed  			buffer = createVertexBuffer(mask, buffer_usage);  			buffer->allocateBuffer(geom_count, index_count, TRUE); @@ -4835,6 +4887,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			}  		} +		group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); + +  		buffer_map[mask][*face_iter].push_back(buffer);  		//add face geometry diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 7df50ec815..315616e8a5 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -167,7 +167,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)  				  indices_per_quad * num_quads);  	LLVertexBuffer* buff = face->getVertexBuffer(); -	if (!buff) +	if (!buff || !buff->isWriteable())  	{  		buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);  		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index f1c5499d84..afd902201b 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -774,7 +774,7 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)  	LLStrider<LLColor4U> colorsp;  	LLStrider<LLVector2> texcoordsp; -	if (mStarsVerts.isNull()) +	if (mStarsVerts.isNull() || !mStarsVerts->isWriteable())  	{  		mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW);  		mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0, TRUE); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 920a9a3752..0da70d398b 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -305,6 +305,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)  	{  		mCurlRequest = new LLCurlEasyRequest();  	} +	if(!mCurlRequest->isValid()) +	{ +		llwarns << "mCurlRequest is invalid." << llendl ; + +		delete mCurlRequest ; +		mCurlRequest = NULL ; +		return ; +	} +  	mErrorCert = NULL;  //	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging @@ -357,10 +366,20 @@ LLXMLRPCTransaction::Impl::~Impl()  	}  	delete mCurlRequest; +	mCurlRequest = NULL ;  }  bool LLXMLRPCTransaction::Impl::process()  { +	if(!mCurlRequest || !mCurlRequest->isValid()) +	{ +		llwarns << "transaction failed." << llendl ; + +		delete mCurlRequest ; +		mCurlRequest = NULL ; +		return true ; //failed, quit. +	} +  	switch(mStatus)  	{  		case LLXMLRPCTransaction::StatusComplete: diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 8449e74fb6..c523a78b22 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1217,10 +1217,12 @@ void LLPipeline::restoreGL()  BOOL LLPipeline::canUseVertexShaders()  { +	static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable"; +  	if (sDisableShaders ||  		!gGLManager.mHasVertexShader ||  		!gGLManager.mHasFragmentShader || -		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") || +		!LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||  		(assertInitialized() && mVertexShadersLoaded != 1) )  	{  		return FALSE; @@ -3765,6 +3767,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)  	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");  	// Initialize lots of GL state to "safe" values +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  	gGL.matrixMode(LLRender::MM_TEXTURE);  	gGL.loadIdentity();  	gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -5296,7 +5299,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)  			light_state->setConstantAttenuation(0.f);  			if (sRenderDeferred)  			{ -				light_state->setLinearAttenuation(light_radius*1.5f); +				F32 size = light_radius*1.5f; +				light_state->setLinearAttenuation(size*size);  				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);  			}  			else @@ -5318,7 +5322,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)  				light_state->setSpotCutoff(90.f);  				light_state->setSpotExponent(2.f); -				light_state->setSpecular(LLColor4::black); +				const LLColor4 specular(0.f, 0.f, 0.f, 0.f); +				light_state->setSpecular(specular);  			}  			else // omnidirectional (point) light  			{ @@ -9419,7 +9424,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  	assertInitialized(); -	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID()); +	bool muted = avatar->isVisuallyMuted();		  	pushRenderTypeMask(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 2815d736e4..9c78048c46 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -432,34 +432,35 @@ public:  	enum LLRenderDebugMask  	{ -		RENDER_DEBUG_COMPOSITION		= 0x0000001, -		RENDER_DEBUG_VERIFY				= 0x0000002, -		RENDER_DEBUG_BBOXES				= 0x0000004, -		RENDER_DEBUG_OCTREE				= 0x0000008, -		RENDER_DEBUG_WIND_VECTORS		= 0x0000010, -		RENDER_DEBUG_OCCLUSION			= 0x0000020, -		RENDER_DEBUG_POINTS				= 0x0000040, -		RENDER_DEBUG_TEXTURE_PRIORITY	= 0x0000080, -		RENDER_DEBUG_TEXTURE_AREA		= 0x0000100, -		RENDER_DEBUG_FACE_AREA			= 0x0000200, -		RENDER_DEBUG_PARTICLES			= 0x0000400, -		RENDER_DEBUG_GLOW				= 0x0000800, -		RENDER_DEBUG_TEXTURE_ANIM		= 0x0001000, -		RENDER_DEBUG_LIGHTS				= 0x0002000, -		RENDER_DEBUG_BATCH_SIZE			= 0x0004000, -		RENDER_DEBUG_ALPHA_BINS			= 0x0008000, -		RENDER_DEBUG_RAYCAST            = 0x0010000, -		RENDER_DEBUG_SHAME				= 0x0020000, -		RENDER_DEBUG_SHADOW_FRUSTA		= 0x0040000, -		RENDER_DEBUG_SCULPTED           = 0x0080000, -		RENDER_DEBUG_AVATAR_VOLUME      = 0x0100000, -		RENDER_DEBUG_BUILD_QUEUE		= 0x0200000, -		RENDER_DEBUG_AGENT_TARGET       = 0x0400000, -		RENDER_DEBUG_UPDATE_TYPE		= 0x0800000, -		RENDER_DEBUG_PHYSICS_SHAPES     = 0x1000000, -		RENDER_DEBUG_NORMALS	        = 0x2000000, -		RENDER_DEBUG_LOD_INFO	        = 0x4000000, -		RENDER_DEBUG_RENDER_COMPLEXITY  = 0x8000000 +		RENDER_DEBUG_COMPOSITION		= 0x00000001, +		RENDER_DEBUG_VERIFY				= 0x00000002, +		RENDER_DEBUG_BBOXES				= 0x00000004, +		RENDER_DEBUG_OCTREE				= 0x00000008, +		RENDER_DEBUG_WIND_VECTORS		= 0x00000010, +		RENDER_DEBUG_OCCLUSION			= 0x00000020, +		RENDER_DEBUG_POINTS				= 0x00000040, +		RENDER_DEBUG_TEXTURE_PRIORITY	= 0x00000080, +		RENDER_DEBUG_TEXTURE_AREA		= 0x00000100, +		RENDER_DEBUG_FACE_AREA			= 0x00000200, +		RENDER_DEBUG_PARTICLES			= 0x00000400, +		RENDER_DEBUG_GLOW				= 0x00000800, +		RENDER_DEBUG_TEXTURE_ANIM		= 0x00001000, +		RENDER_DEBUG_LIGHTS				= 0x00002000, +		RENDER_DEBUG_BATCH_SIZE			= 0x00004000, +		RENDER_DEBUG_ALPHA_BINS			= 0x00008000, +		RENDER_DEBUG_RAYCAST            = 0x00010000, +		RENDER_DEBUG_SHAME				= 0x00020000, +		RENDER_DEBUG_SHADOW_FRUSTA		= 0x00040000, +		RENDER_DEBUG_SCULPTED           = 0x00080000, +		RENDER_DEBUG_AVATAR_VOLUME      = 0x00100000, +		RENDER_DEBUG_BUILD_QUEUE		= 0x00200000, +		RENDER_DEBUG_AGENT_TARGET       = 0x00400000, +		RENDER_DEBUG_UPDATE_TYPE		= 0x00800000, +		RENDER_DEBUG_PHYSICS_SHAPES     = 0x01000000, +		RENDER_DEBUG_NORMALS	        = 0x02000000, +		RENDER_DEBUG_LOD_INFO	        = 0x04000000, +		RENDER_DEBUG_RENDER_COMPLEXITY  = 0x08000000, +		RENDER_DEBUG_ATTACHMENT_BYTES	= 0x10000000,  	};  public: diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index e05b2150a1..2781717f0b 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1952,35 +1952,17 @@ Only large parcels can be listed in search.  				(Defined by the Estate)  			</panel.string>        <panel.string -       name="allow_public_access"> -        Allow Public Access ([MATURITY]) (Note: Unchecking this will create ban lines) -      </panel.string> -            <panel.string               name="estate_override">                  One or more of these options is set at the estate level              </panel.string> -            <text -             type="string" -             length="1" -             follows="left|top" -             height="16" -             layout="topleft" -             left="10" -             name="Limit access to this parcel to:" -             text_color="White" -             top="10" -             width="400"> -                Access To This Parcel -            </text>              <check_box               follows="top|left"               height="16"               layout="topleft" -             left_delta="0" +             left="8"               name="public_access" -             top_pad="5" -             label_text.valign="center" -             label_text.v_pad="-2"  +             label="Allow Public Access (Unchecking this will create ban lines)" +             top_pad="10"                width="278" />              <text               type="string" @@ -1990,28 +1972,28 @@ Only large parcels can be listed in search.               layout="topleft"               left_delta="20"               name="Only Allow" -             top="49" +             top="30"               width="325"> -                Restrict Access to Residents verified by: +                Allow access only to Residents who:              </text>              <check_box               follows="top|left"               height="16" -             label="Payment Information on File [ESTATE_PAYMENT_LIMIT]" +             label="Have payment Information on File [ESTATE_PAYMENT_LIMIT]"               layout="topleft"               left_delta="0"               name="limit_payment" -             tool_tip="Ban unidentified Residents." +             tool_tip="Residents must have payment information on file to access this parcel.  See the [SUPPORT_SITE] for more information."               top_pad="4"               width="278" />              <check_box               follows="top|left"               height="16" -             label="Age Verification [ESTATE_AGE_LIMIT]" +             label="Have been age-verified [ESTATE_AGE_LIMIT]"               layout="topleft"               left_delta="0"               name="limit_age_verified" -             tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information." +             tool_tip="Residents must be age verified to access this parcel. See the [SUPPORT_SITE] for more information."               top_pad="4"               width="278" />              <check_box @@ -2021,7 +2003,7 @@ Only large parcels can be listed in search.               left="8"               name="GroupCheck"               tool_tip="Set group in the General tab." -             top="109" +             top="89"               width="278" />              <check_box               enabled="false" diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml index f818ebe2d7..63e154697b 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml @@ -114,6 +114,15 @@       function="Object.EnableMute" />    </menu_item_call>    <menu_item_call +   label="Unblock" +   layout="topleft" +   name="unblock"> +    <menu_item_call.on_click +     function="Object.Mute" /> +    <menu_item_call.on_visible +     function="Object.EnableUnmute" /> +  </menu_item_call> +  <menu_item_call      label="Zoom In"      layout="topleft"     name="zoom_in"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1f72984166..cd8550b00d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -153,13 +153,6 @@           function="BuyCurrency" />        </menu_item_call>        <menu_item_call -         label="Merchant Outbox..." -         name="MerchantOutbox"> -        <menu_item_call.on_click -         function="Floater.ToggleOrBringToFront" -         parameter="outbox" /> -      </menu_item_call> -      <menu_item_call             label="Account dashboard..."             name="Manage My Account">          <menu_item_call.on_click @@ -2419,6 +2412,16 @@             function="Advanced.ToggleInfoDisplay"             parameter="rendercomplexity" />          </menu_item_check> +        <menu_item_check +         label="Attachment Bytes" +         name="attachment bytes"> +          <menu_item_check.on_check +           function="Advanced.CheckInfoDisplay" +           parameter="attachment bytes" /> +          <menu_item_check.on_click +           function="Advanced.ToggleInfoDisplay" +           parameter="attachment bytes" /> +        </menu_item_check>  		<menu_item_check           label="Sculpt"           name="Sculpt"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 47236c1a48..587c461bee 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -59,7 +59,6 @@       top_pad="30"       width="350" />      <check_box -     enabled_control="EnableVoiceChat"       control_name="VoiceCallsFriendsOnly"       height="16"       label="Only friends and groups can call or IM me" diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml index 6b28639a77..bfd796a62b 100644 --- a/indra/newview/skins/default/xui/en/panel_region_estate.xml +++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml @@ -134,26 +134,26 @@       name="Only Allow"       top_delta="-30"       width="278"> -        Restrict Access to accounts verified by: +        Allow access only to Residents who:      </text>      <check_box       follows="top|left"       height="16" -     label="Payment Information on File" +     label="Have payment information on file"       layout="topleft"       left_delta="0"       name="limit_payment" -     tool_tip="Ban unidentified Residents" +     tool_tip="Residents must have payment information on file to access this estate.  See the [SUPPORT_SITE] for more information."       top_pad="2"       width="278" />      <check_box       follows="top|left"       height="16" -     label="Age Verification" +     label="Have been age-verified"       layout="topleft"       left_delta="0"       name="limit_age_verified" -     tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information." +     tool_tip="Residents must be age verified to access this estate. See the [SUPPORT_SITE] for more information."       top_pad="2"       width="278" /> diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index e88d1bf811..19ac418e9e 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -39,7 +39,7 @@  #include "llsdserialize.h"  #include "llthread.h"  #include "llupdaterservice.h" - +#include "llcurl.h"  class LLUpdateDownloader::Implementation:  	public LLThread @@ -198,13 +198,19 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &  LLUpdateDownloader::Implementation::~Implementation()  { -	if(isDownloading()) { +	if(isDownloading())  +	{  		cancel();  		shutdown(); -	} else { +	}  +	else  +	{  		; // No op.  	} -	if(mCurl) curl_easy_cleanup(mCurl); +	if(mCurl) +	{ +		LLCurl::deleteEasyHandle(mCurl); +	}  } @@ -406,9 +412,12 @@ void LLUpdateDownloader::Implementation::run(void)  void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)  { -	if(mCurl == 0) { -		mCurl = curl_easy_init(); -	} else { +	if(mCurl == 0)  +	{ +		mCurl = LLCurl::newEasyHandle(); +	}  +	else  +	{  		curl_easy_reset(mCurl);  	} | 
