Automated merge with ssh://hg.lindenlab.com/richard/viewer-experience/
commit
bbdb390624
14
.hgtags
14
.hgtags
|
|
@ -228,6 +228,10 @@ c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
|
|||
80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start
|
||||
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
|
||||
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
|
||||
a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release
|
||||
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
|
||||
a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release
|
||||
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release
|
||||
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
|
||||
a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release
|
||||
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
|
||||
|
|
@ -244,5 +248,15 @@ bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
|
|||
3d2d5d244c6398a4214c666d5dd3965b0918709a 3.2.5-beta1
|
||||
65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d DRTVWR-107_3.2.5-beta2
|
||||
65a2c1c8d855b88edfbea4e16ef2f27e7cff8b1d 3.2.5-beta2
|
||||
c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release
|
||||
c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
|
||||
2174ed1c7129562428a5cfe8651ed77b8d26ae18 3.2.6-start
|
||||
286d73ff5c19f6c00e023dc1b60975ed6bbe2872 DRTVWR-109_3.2.6-beta1
|
||||
4891c46a56fed7512c783b9cbe7cb7260727bf0c 3.2.7-start
|
||||
286d73ff5c19f6c00e023dc1b60975ed6bbe2872 3.2.6-beta1
|
||||
c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release
|
||||
c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release
|
||||
3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1
|
||||
3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1
|
||||
89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start
|
||||
37dd400ad721e2a89ee820ffc1e7e433c68f3ca2 3.2.9-start
|
||||
|
|
|
|||
|
|
@ -607,6 +607,9 @@ Jonathan Yap
|
|||
STORM-1737
|
||||
STORM-1733
|
||||
STORM-1790
|
||||
STORM-1788
|
||||
STORM-1799
|
||||
STORM-1796
|
||||
Kadah Coba
|
||||
STORM-1060
|
||||
Jondan Lundquist
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,18 +256,29 @@ 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.
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe()
|
|||
//lldebugs << "destroying LLIOPipe" << llendl;
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLIOPipe::isValid()
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLIOPipe::lookupStatusString(EStatus status)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -231,6 +231,8 @@ public:
|
|||
*/
|
||||
virtual ~LLIOPipe();
|
||||
|
||||
virtual bool isValid() ;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Base Constructor.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ public:
|
|||
*/
|
||||
void allowCookies();
|
||||
|
||||
/*virtual*/ bool isValid() ;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Give this pipe a chance to handle a generated error
|
||||
|
|
|
|||
|
|
@ -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]++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
//--------------------------------------------------------------------
|
||||
class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
|
||||
{
|
||||
LOG_CLASS(LLInitialWearablesFetch);
|
||||
|
||||
public:
|
||||
LLInitialWearablesFetch(const LLUUID& cof_id);
|
||||
~LLInitialWearablesFetch();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
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
|
||||
{
|
||||
*index_dst = index;
|
||||
index_dst += 4;
|
||||
}
|
||||
while (index_dst < index_end);
|
||||
LLVector4Logical mask;
|
||||
mask.clear();
|
||||
mask.setElement<3>();
|
||||
|
||||
S32 aligned_pad_vertices = mGeomCount - num_vertices;
|
||||
LLVector4a* last_vec = end - 1;
|
||||
while (aligned_pad_vertices > 0)
|
||||
texIdx.set(0,0,0,index);
|
||||
|
||||
{
|
||||
--aligned_pad_vertices;
|
||||
*dst++ = *last_vec;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
LLFace* face = drawable->getFace(i);
|
||||
if (face->verify())
|
||||
vobj->updateRiggedVolume();
|
||||
volume = vobj->getRiggedVolume();
|
||||
}
|
||||
else
|
||||
{
|
||||
volume = vobj->getVolume();
|
||||
}
|
||||
|
||||
if (volume)
|
||||
{
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -261,6 +261,8 @@ private:
|
|||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLTexLayerSetBuffer : public LLViewerDynamicTexture
|
||||
{
|
||||
LOG_CLASS(LLTexLayerSetBuffer);
|
||||
|
||||
public:
|
||||
LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
|
||||
virtual ~LLTexLayerSetBuffer();
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -113,6 +113,15 @@
|
|||
<menu_item_call.on_visible
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -152,13 +152,6 @@
|
|||
<menu_item_call.on_click
|
||||
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">
|
||||
|
|
@ -2418,6 +2411,16 @@
|
|||
<menu_item_check.on_click
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue