Merge viewer-bear

Tank_Master 2013-09-12 21:15:34 -07:00
commit 52d9b07503
220 changed files with 5763 additions and 5597 deletions

View File

@ -39,6 +39,7 @@ indra/newview/app_settings/static_*.db2
indra/newview/browser_profile
indra/newview/character
indra/newview/fmod.dll
indra/newview/fmod.log
indra/newview/mozilla-theme
indra/newview/mozilla-universal-darwin.tgz
indra/newview/res/ll_icon.*

View File

@ -23,6 +23,7 @@ codeticket_since = 3.3.0-release
# Override build system default toolchain
# Note that this will only affect automated builds.
Linux.distcc_version =
Linux.gcc_version = /usr/bin/gcc-4.6
Linux.cxx_version = /usr/bin/g++-4.6

View File

@ -1700,9 +1700,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>facee34b8bd57ad602157e65a5af1a49</string>
<string>38ea083fe1204ee106b4d44d9811af19</string>
<key>url</key>
<string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/openssl-0.9.8q-darwin-20110211.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/249044/arch/Darwin/installer/openssl-1.0.0g-darwin-20120207.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -1712,9 +1712,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>3d40be8566fa4b9df9a38e2a0f9ea467</string>
<string>7dc5191a3d95074a6ed3bd53f57420e5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/226882/arch/Linux/installer/openssl-1.0.0d-linux-20110418.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/249044/arch/Linux/installer/openssl-1.0.0g-linux-20120207.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>

View File

@ -925,8 +925,11 @@ Nicky Dasmijn
MAINT-873
SUN-72
BUG-2432
STORM-1935
STORM-1936
BUG-3605
CHUIBUG-197
STORM-1937
Nicky Perian
OPEN-1
STORM-1087

View File

@ -177,6 +177,17 @@ if (LINUX)
# Let's actually get a numerical version of gxx's version
STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION})
# Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables
# This is pure rubbish; I wish there was another way.
#
if(${CXX_VERSION_NUMBER} LESS 420)
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}")
endif (${CXX_VERSION_NUMBER} LESS 420)
if(${CXX_VERSION_NUMBER} GREATER 459)
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}")
endif (${CXX_VERSION_NUMBER} GREATER 459)
# gcc 4.3 and above don't like the LL boost and also
# cause warnings due to our use of deprecated headers
if(${CXX_VERSION_NUMBER} GREATER 429)
@ -254,7 +265,7 @@ if (LINUX OR DARWIN)
set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
if (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
# set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
endif (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor")

View File

@ -282,6 +282,7 @@ elseif(LINUX)
libdb-5.1.so
libexpat.so
libexpat.so.1
libfreetype.so.6
libGLOD.so
# libgmock_main.so
# libgmock.so.0

View File

@ -7,7 +7,7 @@ if (STANDALONE)
pkg_check_modules(FREETYPE REQUIRED freetype2)
else (STANDALONE)
use_prebuilt_binary(freetype)
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
set(FREETYPE_LIBRARIES freetype)
endif (STANDALONE)

View File

@ -258,3 +258,4 @@ void LLEditingMotion::onDeactivate()
// End

View File

@ -530,3 +530,4 @@ void LLEyeMotion::onDeactivate()
}
// End

View File

@ -681,15 +681,8 @@ BOOL LLKeyframeMotion::onActivate()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask)
{
// <FS:ND> seems not be to uncommon to enter here with <0.
// forcing time up to zero instead of asserting seems to be
// better to not constantly crash in non release builds.
if(time < 0 )
time = 0;
// llassert(time >= 0.f);
// </FS:ND>
// llassert(time >= 0.f); // This will fire
time = llmax(0.f, time);
if (mJointMotionList->mLoop)
{
@ -2421,3 +2414,4 @@ LLKeyframeMotion::JointConstraint::~JointConstraint()
}
// End

View File

@ -393,3 +393,4 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
return TRUE;
}

View File

@ -169,3 +169,4 @@ BOOL LLMotion::canDeprecate()
}
// End

View File

@ -169,3 +169,4 @@ void LLTargetingMotion::onDeactivate()
// End

View File

@ -122,6 +122,7 @@ set(llcommon_HEADER_FILES
linden_common.h
linked_lists.h
llaccountingcost.h
llalignedarray.h
llallocator.h
llallocator_heap_profile.h
llagentconstants.h
@ -237,6 +238,7 @@ set(llcommon_HEADER_FILES
llstrider.h
llstring.h
llstringtable.h
llstaticstringtable.h
llsys.h
llthread.h
llthreadsafequeue.h

View File

@ -0,0 +1,139 @@
/**
* @file llalignedarray.h
* @brief A static array which obeys alignment restrictions and mimics std::vector accessors.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLALIGNEDARRAY_H
#define LL_LLALIGNEDARRAY_H
#include "llmemory.h"
template <class T, U32 alignment>
class LLAlignedArray
{
public:
T* mArray;
U32 mElementCount;
U32 mCapacity;
LLAlignedArray();
~LLAlignedArray();
void push_back(const T& elem);
U32 size() const { return mElementCount; }
void resize(U32 size);
T* append(S32 N);
T& operator[](int idx);
const T& operator[](int idx) const;
};
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::LLAlignedArray()
{
llassert(alignment >= 16);
mArray = NULL;
mElementCount = 0;
mCapacity = 0;
}
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::~LLAlignedArray()
{
ll_aligned_free(mArray);
mArray = NULL;
mElementCount = 0;
mCapacity = 0;
}
template <class T, U32 alignment>
void LLAlignedArray<T, alignment>::push_back(const T& elem)
{
T* old_buf = NULL;
if (mCapacity <= mElementCount)
{
mCapacity++;
mCapacity *= 2;
T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
}
old_buf = mArray;
mArray = new_buf;
}
mArray[mElementCount++] = elem;
//delete old array here to prevent error on a.push_back(a[0])
ll_aligned_free(old_buf);
}
template <class T, U32 alignment>
void LLAlignedArray<T, alignment>::resize(U32 size)
{
if (mCapacity < size)
{
mCapacity = size+mCapacity*2;
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
ll_aligned_free(mArray);
}
/*for (U32 i = mElementCount; i < mCapacity; ++i)
{
new(new_buf+i) T();
}*/
mArray = new_buf;
}
mElementCount = size;
}
template <class T, U32 alignment>
T& LLAlignedArray<T, alignment>::operator[](int idx)
{
llassert(idx < mElementCount);
return mArray[idx];
}
template <class T, U32 alignment>
const T& LLAlignedArray<T, alignment>::operator[](int idx) const
{
llassert(idx < mElementCount);
return mArray[idx];
}
template <class T, U32 alignment>
T* LLAlignedArray<T, alignment>::append(S32 N)
{
U32 sz = size();
resize(sz+N);
return &((*this)[sz]);
}
#endif

View File

@ -252,7 +252,7 @@ void LLVolatileAPRPool::clearVolatileAPRPool()
llassert_always(mNumActiveRef > 0) ;
}
llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ;
}
BOOL LLVolatileAPRPool::isFull()

View File

@ -164,14 +164,20 @@ public:
~LLAtomic32<Type>() {};
operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
Type CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
private:
apr_uint32_t mData;
volatile apr_uint32_t mData;
};
typedef LLAtomic32<U32> LLAtomicU32;

View File

@ -44,6 +44,7 @@ void LLCommon::initClass()
}
LLTimer::initClass();
LLThreadSafeRefCount::initThreadSafeRefCount();
assert_main_thread(); // Make sure we record the main thread
// LLWorkerThread::initClass();
// LLFrameCallbackManager::initClass();
}

View File

@ -87,3 +87,4 @@ F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache)
return interpolant;
}

View File

@ -47,6 +47,7 @@ class LL_COMMON_API LLEventAPI: public LLDispatchListener,
typedef LLInstanceTracker<LLEventAPI, std::string> ibase;
public:
/**
* @param name LLEventPump name on which this LLEventAPI will listen. This
* also serves as the LLInstanceTracker instance key.

View File

@ -36,6 +36,7 @@
class LL_COMMON_API LLEventTimer : public LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();

View File

@ -113,17 +113,13 @@ class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
{
public:
NamedTimerFactory()
: mTimerRoot(NULL)
{}
/*virtual */ void initSingleton()
: mTimerRoot(new LLFastTimer::NamedTimer("root"))
{
mTimerRoot = new LLFastTimer::NamedTimer("root");
mRootFrameState.setNamedTimer(mTimerRoot);
mTimerRoot->setFrameState(&mRootFrameState);
mTimerRoot->mParent = mTimerRoot;
mTimerRoot->setCollapsed(false);
mRootFrameState.mParent = &mRootFrameState;
mRootFrameState.mParent = &mRootFrameState;
}
~NamedTimerFactory()

View File

@ -139,10 +139,11 @@ public:
// used to statically declare a new named timer
class LL_COMMON_API DeclareTimer
: public LLInstanceTracker<DeclareTimer>
: public LLInstanceTracker< DeclareTimer >
{
friend class LLFastTimer;
public:
DeclareTimer(const std::string& name, bool open);
DeclareTimer(const std::string& name);

View File

@ -1953,7 +1953,7 @@ namespace LLInitParam
class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
{
typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
typedef typename super_t::value_t value_t;
typedef typename super_t::default_value_t default_value_t;

View File

@ -32,19 +32,3 @@
// external library headers
// other Linden headers
//static
void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
{
// typedef std::map<std::string, void *> InstancesMap;
typedef std::map<char const*, void *> InstancesMap; // <ND/> Do not base this in std::string, instead use the char* to avoid string compares.
static InstancesMap instances;
// std::map::insert() is just what we want here. You attempt to insert a
// (key, value) pair. If the specified key doesn't yet exist, it inserts
// the pair and returns a std::pair of (iterator, true). If the specified
// key DOES exist, insert() simply returns (iterator, false). One lookup
// handles both cases.
return instances.insert(InstancesMap::value_type(info.name(),
InstancesMap::mapped_type()))
.first->second;
}

View File

@ -51,21 +51,7 @@
class LL_COMMON_API LLInstanceTrackerBase
{
protected:
/// Get a process-unique void* pointer slot for the specified type_info
static void * & getInstances(std::type_info const & info);
/// Find or create a STATICDATA instance for the specified TRACKED class.
/// STATICDATA must be default-constructible.
template<typename STATICDATA, class TRACKED>
static STATICDATA& getStatic()
{
void *& instances = getInstances(typeid(TRACKED));
if (! instances)
{
instances = new STATICDATA;
}
return *static_cast<STATICDATA*>(instances);
}
/// It's not essential to derive your STATICDATA (for use with
/// getStatic()) from StaticBase; it's just that both known
@ -87,6 +73,8 @@ protected:
};
};
LL_COMMON_API void assert_main_thread();
/// This mix-in class adds support for tracking all instances of the specified class parameter T
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
/// If KEY is not provided, then instances are stored in a simple set
@ -95,14 +83,18 @@ template<typename T, typename KEY = T*>
class LLInstanceTracker : public LLInstanceTrackerBase
{
protected:
typedef LLInstanceTracker<T, KEY> MyT;
typedef LLInstanceTracker<T, KEY> self_t;
typedef typename std::map<KEY, T*> InstanceMap;
struct StaticData: public StaticBase
{
InstanceMap sMap;
};
static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
static InstanceMap& getMap_() { return getStatic().sMap; }
static StaticData& getStatic() { static StaticData sData; return sData;}
static InstanceMap& getMap_()
{
// assert_main_thread(); fwiw this class is not thread safe, and it used by multiple threads. Bad things happen.
return getStatic().sMap;
}
public:
class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
@ -260,7 +252,11 @@ private:
}
void remove_()
{
getMap_().erase(mInstanceKey);
typename InstanceMap::iterator iter = getMap_().find(mInstanceKey);
if (iter != getMap_().end())
{
getMap_().erase(iter);
}
}
private:
@ -273,13 +269,13 @@ template<typename T>
class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
{
protected:
typedef LLInstanceTracker<T, T*> MyT;
typedef LLInstanceTracker<T, T*> self_t;
typedef typename std::set<T*> InstanceSet;
struct StaticData: public StaticBase
{
InstanceSet sSet;
};
static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
static StaticData& getStatic() { static StaticData sData; return sData; }
static InstanceSet& getSet_() { return getStatic().sSet; }
public:

View File

@ -32,6 +32,7 @@
class LL_COMMON_API LLLeap: public LLInstanceTracker<LLLeap>
{
public:
/**
* Pass a brief string description, mostly for logging purposes. The desc
* need not be unique, but obviously the clearer we can make it, the

View File

@ -67,14 +67,20 @@ const S32 LSL_PRIM_TEXGEN = 22;
const S32 LSL_PRIM_POINT_LIGHT = 23;
const S32 LSL_PRIM_CAST_SHADOWS = 24;
const S32 LSL_PRIM_GLOW = 25;
const S32 LSL_PRIM_TEXT = 26;
const S32 LSL_PRIM_NAME = 27;
const S32 LSL_PRIM_DESC = 28;
const S32 LSL_PRIM_TEXT = 26;
const S32 LSL_PRIM_NAME = 27;
const S32 LSL_PRIM_DESC = 28;
const S32 LSL_PRIM_ROT_LOCAL = 29;
const S32 LSL_PRIM_PHYSICS_SHAPE_TYPE = 30;
const S32 LSL_PRIM_PHYSICS_SHAPE_TYPE = 30;
const S32 LSL_PRIM_PHYSICS_MATERIAL = 31;
const S32 LSL_PRIM_OMEGA = 32;
const S32 LSL_PRIM_OMEGA = 32;
const S32 LSL_PRIM_POS_LOCAL = 33;
const S32 LSL_PRIM_LINK_TARGET = 34;
const S32 LSL_PRIM_SLICE = 35;
const S32 LSL_PRIM_PHYSICS_SHAPE_PRIM = 0;
const S32 LSL_PRIM_PHYSICS_SHAPE_NONE = 1;
const S32 LSL_PRIM_PHYSICS_SHAPE_CONVEX = 2;
const S32 LSL_PRIM_TYPE_BOX = 0;
const S32 LSL_PRIM_TYPE_CYLINDER= 1;
@ -191,6 +197,18 @@ const S32 OBJECT_RUNNING_SCRIPT_COUNT = 9;
const S32 OBJECT_TOTAL_SCRIPT_COUNT = 10;
const S32 OBJECT_SCRIPT_MEMORY = 11;
const S32 OBJECT_SCRIPT_TIME = 12;
const S32 OBJECT_PRIM_EQUIVALENCE = 13;
const S32 OBJECT_SERVER_COST = 14;
const S32 OBJECT_STREAMING_COST = 15;
const S32 OBJECT_PHYSICS_COST = 16;
const S32 OBJECT_CHARACTER_TIME = 17;
const S32 OBJECT_ROOT = 18;
const S32 OBJECT_ATTACHED_POINT = 19;
const S32 OBJECT_PATHFINDING_TYPE = 20;
const S32 OBJECT_PHYSICS = 21;
const S32 OBJECT_PHANTOM = 22;
const S32 OBJECT_TEMP_ON_REZ = 23;
const S32 OBJECT_RENDER_WEIGHT = 24;
// llTextBox() magic token string - yes this is a hack. sue me.
char const* const TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";

View File

@ -36,6 +36,44 @@ class LLMutex ;
#define LL_CHECK_MEMORY
#endif
LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#ifdef SHOW_ASSERT
#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
#else
#define ll_assert_aligned(ptr,alignment)
#endif
#include <xmmintrin.h>
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)
{
return reinterpret_cast<T*>(
(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
}
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
{
return reinterpret_cast<T*>(
(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
}
#if LL_LINUX || LL_DARWIN
#define LL_ALIGN_PREFIX(x)
#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x)))
#elif LL_WINDOWS
#define LL_ALIGN_PREFIX(x) __declspec(align(x))
#define LL_ALIGN_POSTFIX(x)
#else
#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined"
#endif
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
// <FS:ND> No tcmalloc
#ifdef ND_NO_TCMALLOC
#include "nd/ndmemory.h"
@ -43,17 +81,28 @@ class LLMutex ;
inline void* ll_aligned_malloc( size_t size, int align )
{
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
void* mem = malloc( size + (align - 1) + sizeof(void*) );
char* aligned = ((char*)mem) + sizeof(void*);
aligned += align - ((uintptr_t)aligned & (align - 1));
((void**)aligned)[-1] = mem;
return aligned;
#endif
}
inline void ll_aligned_free( void* ptr )
{
free( ((void**)ptr)[-1] );
#if defined(LL_WINDOWS)
_aligned_free(ptr);
#else
if (ptr)
{
free( ((void**)ptr)[-1] );
}
#endif
}
#if !LL_USE_TCMALLOC
@ -139,6 +188,78 @@ inline void ll_aligned_free_32(void *p)
}
#endif // </FS:ND> No tcmalloc
// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
// Source and dest must be 16-byte aligned and size must be multiple of 16.
//
inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes)
{
assert(src != NULL);
assert(dst != NULL);
assert(bytes > 0);
assert((bytes % sizeof(F32))== 0);
ll_assert_aligned(src,16);
ll_assert_aligned(dst,16);
assert((src < dst) ? ((src + bytes) < dst) : ((dst + bytes) < src));
assert(bytes%16==0);
char* end = dst + bytes;
if (bytes > 64)
{
// Find start of 64b aligned area within block
//
void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
//at least 64 bytes before the end of the destination, switch to 16 byte copies
void* end_64 = end-64;
// Prefetch the head of the 64b area now
//
_mm_prefetch((char*)begin_64, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
// Copy 16b chunks until we're 64b aligned
//
while (dst < begin_64)
{
_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
dst += 16;
src += 16;
}
// Copy 64b chunks up to your tail
//
// might be good to shmoo the 512b prefetch offset
// (characterize performance for various values)
//
while (dst < end_64)
{
_mm_prefetch((char*)src + 512, _MM_HINT_NTA);
_mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
_mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16)));
_mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32)));
_mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48)));
dst += 64;
src += 64;
}
}
// Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies)
//
while (dst < end)
{
_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
dst += 16;
src += 16;
}
}
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
#endif
@ -556,13 +677,7 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr)
// LLSingleton moved to llsingleton.h
LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#ifdef SHOW_ASSERT
#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
#else
#define ll_assert_aligned(ptr,alignment)
#endif

View File

@ -28,5 +28,4 @@
#include "llsingleton.h"
std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;

View File

@ -30,38 +30,6 @@
#include <typeinfo>
#include <boost/noncopyable.hpp>
/// @brief A global registry of all singletons to prevent duplicate allocations
/// across shared library boundaries
class LL_COMMON_API LLSingletonRegistry {
private:
typedef std::map<std::string, void *> TypeMap;
static TypeMap * sSingletonMap;
static void checkInit()
{
if(sSingletonMap == NULL)
{
sSingletonMap = new TypeMap();
}
}
public:
template<typename T> static void * & get()
{
std::string name(typeid(T).name());
checkInit();
// the first entry of the pair returned by insert will be either the existing
// iterator matching our key, or the newly inserted NULL initialized entry
// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
TypeMap::iterator result =
sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
return result->second;
}
};
// LLSingleton implements the getInstance() method part of the Singleton
// pattern. It can't make the derived class constructors protected, though, so
// you have to do that yourself.
@ -101,20 +69,23 @@ private:
} EInitState;
// stores pointer to singleton instance
// and tracks initialization state of singleton
struct SingletonInstanceData
struct SingletonLifetimeManager
{
EInitState mInitState;
DERIVED_TYPE* mSingletonInstance;
SingletonInstanceData()
: mSingletonInstance(NULL),
mInitState(UNINITIALIZED)
{}
~SingletonInstanceData()
SingletonLifetimeManager()
{
if (mInitState != DELETED)
construct();
}
static void construct()
{
sData.mInitState = CONSTRUCTING;
sData.mInstance = new DERIVED_TYPE();
sData.mInitState = INITIALIZING;
}
~SingletonLifetimeManager()
{
if (sData.mInitState != DELETED)
{
deleteSingleton();
}
@ -124,9 +95,8 @@ private:
public:
virtual ~LLSingleton()
{
SingletonInstanceData& data = getData();
data.mSingletonInstance = NULL;
data.mInitState = DELETED;
sData.mInstance = NULL;
sData.mInitState = DELETED;
}
/**
@ -151,50 +121,46 @@ public:
*/
static void deleteSingleton()
{
delete getData().mSingletonInstance;
getData().mSingletonInstance = NULL;
getData().mInitState = DELETED;
delete sData.mInstance;
sData.mInstance = NULL;
sData.mInitState = DELETED;
}
static SingletonInstanceData& getData()
{
// this is static to cache the lookup results
static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
// *TODO - look into making this threadsafe
if(NULL == registry)
{
static SingletonInstanceData data;
registry = &data;
}
return *static_cast<SingletonInstanceData *>(registry);
}
static DERIVED_TYPE* getInstance()
{
SingletonInstanceData& data = getData();
static SingletonLifetimeManager sLifeTimeMgr;
if (data.mInitState == CONSTRUCTING)
switch (sData.mInitState)
{
case UNINITIALIZED:
// should never be uninitialized at this point
llassert(false);
return NULL;
case CONSTRUCTING:
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
return NULL;
case INITIALIZING:
// go ahead and flag ourselves as initialized so we can be reentrant during initialization
sData.mInitState = INITIALIZED;
sData.mInstance->initSingleton();
return sData.mInstance;
case INITIALIZED:
return sData.mInstance;
case DELETED:
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
SingletonLifetimeManager::construct();
sData.mInitState = INITIALIZED;
sData.mInstance->initSingleton();
return sData.mInstance;
}
if (data.mInitState == DELETED)
{
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
}
if (!data.mSingletonInstance)
{
data.mInitState = CONSTRUCTING;
data.mSingletonInstance = new DERIVED_TYPE();
data.mInitState = INITIALIZING;
data.mSingletonInstance->initSingleton();
data.mInitState = INITIALIZED;
}
return data.mSingletonInstance;
return NULL;
}
static DERIVED_TYPE* getIfExists()
{
return sData.mInstance;
}
// Reference version of getInstance()
@ -208,18 +174,29 @@ public:
// Use this to avoid accessing singletons before the can safely be constructed
static bool instanceExists()
{
return getData().mInitState == INITIALIZED;
return sData.mInitState == INITIALIZED;
}
// Has this singleton already been deleted?
// Use this to avoid accessing singletons from a static object's destructor
static bool destroyed()
{
return getData().mInitState == DELETED;
return sData.mInitState == DELETED;
}
private:
virtual void initSingleton() {}
struct SingletonData
{
EInitState mInitState;
DERIVED_TYPE* mInstance;
};
static SingletonData sData;
};
template<typename T>
typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
#endif

View File

@ -0,0 +1,82 @@
/**
* @file llstringtable.h
* @brief The LLStringTable class provides a _fast_ method for finding
* unique copies of strings.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_STATIC_STRING_TABLE_H
#define LL_STATIC_STRING_TABLE_H
#include "lldefs.h"
#include <boost/unordered_map.hpp>
#include "llstl.h"
class LLStaticHashedString
{
public:
LLStaticHashedString(const std::string& s)
{
string_hash = makehash(s);
string = s;
}
const std::string& String() const { return string; }
size_t Hash() const { return string_hash; }
bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); }
protected:
size_t makehash(const std::string& s)
{
size_t len = s.size();
const char* c = s.c_str();
size_t hashval = 0;
for (size_t i=0; i<len; i++)
{
hashval = ((hashval<<5) + hashval) + *c++;
}
return hashval;
}
std::string string;
size_t string_hash;
};
struct LLStaticStringHasher
{
enum { bucket_size = 8 };
size_t operator()(const LLStaticHashedString& key_value) const { return key_value.Hash(); }
bool operator()(const LLStaticHashedString& left, const LLStaticHashedString& right) const { return left.Hash() < right.Hash(); }
};
template< typename MappedObject >
class LL_COMMON_API LLStaticStringTable
: public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
{
};
#endif

View File

@ -42,14 +42,6 @@
//# define STRING_TABLE_HASH_MAP 1
#endif
#if STRING_TABLE_HASH_MAP
# if LL_WINDOWS
# include <hash_map>
# else
# include <ext/hash_map>
# endif
#endif
const U32 MAX_STRINGS_LENGTH = 256;
class LL_COMMON_API LLStringTableEntry

View File

@ -67,7 +67,8 @@ LL_COMMON_API void assert_main_thread()
static U32 s_thread_id = LLThread::currentID();
if (LLThread::currentID() != s_thread_id)
{
llerrs << "Illegal execution outside main thread." << llendl;
llwarns << "Illegal execution from thread id " << (S32) LLThread::currentID()
<< " outside main thread " << (S32) s_thread_id << llendl;
}
}
@ -507,15 +508,7 @@ LLThreadSafeRefCount::LLThreadSafeRefCount() :
LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
{
if (sMutex)
{
sMutex->lock();
}
mRef = 0;
if (sMutex)
{
sMutex->unlock();
}
}
LLThreadSafeRefCount::~LLThreadSafeRefCount()

View File

@ -242,49 +242,39 @@ public:
LLThreadSafeRefCount(const LLThreadSafeRefCount&);
LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
{
if (sMutex)
{
sMutex->lock();
}
mRef = 0;
if (sMutex)
{
sMutex->unlock();
}
return *this;
}
void ref()
{
if (sMutex) sMutex->lock();
mRef++;
if (sMutex) sMutex->unlock();
}
S32 unref()
void unref()
{
llassert(mRef >= 1);
if (sMutex) sMutex->lock();
S32 res = --mRef;
if (sMutex) sMutex->unlock();
if (0 == res)
{
delete this;
return 0;
if ((--mRef) == 0) // See note in llapr.h on atomic decrement operator return value.
{
// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
// It is technically possible for a vanilla pointer to mess this up, or another thread to
// jump in, find this object, create another smart pointer and end up dangling, but if
// the code is that bad and not thread-safe, it's trouble already.
delete this;
}
return res;
}
}
S32 getNumRefs() const
{
return mRef;
const S32 currentVal = mRef.CurrentValue();
return currentVal;
}
private:
S32 mRef;
LLAtomic32< S32 > mRef;
};
/**
* intrusive pointer support for LLThreadSafeRefCount
* this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
@ -315,4 +305,6 @@ public:
//============================================================================
extern LL_COMMON_API void assert_main_thread();
#endif // LL_LLTHREAD_H

View File

@ -146,9 +146,6 @@ const int HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS = 2;
// Block allocation size (a tuning parameter) is found
// in bufferarray.h.
// Compatibility controls
const bool HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX = true;
} // end namespace LLCore
#endif // _LLCORE_HTTP_INTERNAL_H_

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -186,12 +186,11 @@ void HttpOpRequest::stageFromActive(HttpService * service)
if (mReplyLength)
{
// If non-zero, we received and processed a Content-Range
// header with the response. Verify that what it says
// is consistent with the received data.
// <FS:ND> mReplyBody can be 0
// if (mReplyLength != mReplyBody->size())
if ( !mReplyBody || mReplyLength != mReplyBody->size())
// header with the response. If there is received data
// (and there may not be due to protocol violations,
// HEAD requests, etc., see BUG-2295) Verify that what it
// says is consistent with the received data.
if (mReplyBody && mReplyBody->size() && mReplyLength != mReplyBody->size())
{
// Not as expected, fail the request
mStatus = HttpStatus(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
@ -342,7 +341,6 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
}
}
// Sets all libcurl options and data for a request.
//
// Used both for initial requests and to 'reload' for
@ -384,41 +382,15 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// Get policy options
HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions());
mCurlHandle = curl_easy_init();
curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
mCurlHandle = LLCurl::createStandardCurlHandle();
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
{
// The Linksys WRT54G V5 router has an issue with frequent
// DNS lookups from LAN machines. If they happen too often,
// like for every HTTP request, the router gets annoyed after
// about 700 or so requests and starts issuing TCP RSTs to
// new connections. Reuse the DNS lookups for even a few
// seconds and no RSTs.
curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
}
else
{
// *TODO: Revisit this old DNS timeout setting - may no longer be valid
// I don't think this is valid anymore, the Multi shared DNS
// cache is working well. For the case of naked easy handles,
// consider using a shared DNS object.
curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
}
curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
const std::string * opt_value(NULL);
long opt_long(0L);
@ -697,7 +669,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
std::string safe_line;
std::string tag;
bool logit(false);
len = (std::min)(len, size_t(256)); // Keep things reasonable in all cases
const size_t log_len((std::min)(len, size_t(256))); // Keep things reasonable in all cases
switch (info)
{
@ -705,7 +677,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "TEXT";
escape_libcurl_debug_data(buffer, len, true, safe_line);
escape_libcurl_debug_data(buffer, log_len, true, safe_line);
logit = true;
}
break;
@ -714,7 +686,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "HEADERIN";
escape_libcurl_debug_data(buffer, len, true, safe_line);
escape_libcurl_debug_data(buffer, log_len, true, safe_line);
logit = true;
}
break;
@ -723,7 +695,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "HEADEROUT";
escape_libcurl_debug_data(buffer, 2 * len, true, safe_line); // Goes out as one line
escape_libcurl_debug_data(buffer, log_len, true, safe_line); // Goes out as one line unlike header_in
logit = true;
}
break;
@ -735,7 +707,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
logit = true;
if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
{
escape_libcurl_debug_data(buffer, len, false, safe_line);
escape_libcurl_debug_data(buffer, log_len, false, safe_line);
}
else
{
@ -753,7 +725,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
logit = true;
if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
{
escape_libcurl_debug_data(buffer, len, false, safe_line);
escape_libcurl_debug_data(buffer, log_len, false, safe_line);
}
else
{

View File

@ -60,7 +60,6 @@ class HttpOptions;
/// the information needed to make a working request which can
/// then be enqueued to a request queue.
///
class HttpOpRequest : public HttpOperation
{
public:

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -319,33 +319,13 @@ bool HttpPolicy::cancel(HttpHandle handle)
bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
{
static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
static const HttpStatus cant_res_proxy(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
static const HttpStatus cant_res_host(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
static const HttpStatus send_error(HttpStatus::EXT_CURL_EASY, CURLE_SEND_ERROR);
static const HttpStatus recv_error(HttpStatus::EXT_CURL_EASY, CURLE_RECV_ERROR);
static const HttpStatus upload_failed(HttpStatus::EXT_CURL_EASY, CURLE_UPLOAD_FAILED);
static const HttpStatus op_timedout(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
static const HttpStatus post_error(HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR);
// Retry or finalize
if (! op->mStatus)
{
// If this failed, we might want to retry. Have to inspect
// the status a little more deeply for those reasons worth retrying...
if (op->mPolicyRetries < op->mPolicyRetryLimit &&
((op->mStatus.isHttpStatus() && op->mStatus.mType >= 499 && op->mStatus.mType <= 599) ||
cant_connect == op->mStatus ||
cant_res_proxy == op->mStatus ||
cant_res_host == op->mStatus ||
send_error == op->mStatus ||
recv_error == op->mStatus ||
upload_failed == op->mStatus ||
op_timedout == op->mStatus ||
post_error == op->mStatus))
// If this failed, we might want to retry.
if (op->mPolicyRetries < op->mPolicyRetryLimit && op->mStatus.isRetryable())
{
// Okay, worth a retry. We include 499 in this test as
// it's the old 'who knows?' error from many grid services...
// Okay, worth a retry.
retryOp(op);
return true; // still active/ready
}

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -116,6 +116,7 @@ std::string HttpStatus::toString() const
{ 415, "Unsupported Media Type" },
{ 416, "Requested range not satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Linden Catch-All" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
@ -174,6 +175,37 @@ std::string HttpStatus::toString() const
}
return std::string("Unknown error");
}
// Pass true on statuses that might actually be cleared by a
// retry. Library failures, calling problems, etc. aren't
// going to be fixed by squirting bits all over the Net.
bool HttpStatus::isRetryable() const
{
static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
static const HttpStatus cant_res_proxy(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
static const HttpStatus cant_res_host(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
static const HttpStatus send_error(HttpStatus::EXT_CURL_EASY, CURLE_SEND_ERROR);
static const HttpStatus recv_error(HttpStatus::EXT_CURL_EASY, CURLE_RECV_ERROR);
static const HttpStatus upload_failed(HttpStatus::EXT_CURL_EASY, CURLE_UPLOAD_FAILED);
static const HttpStatus op_timedout(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
static const HttpStatus post_error(HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR);
static const HttpStatus partial_file(HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE);
static const HttpStatus inv_cont_range(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
return ((isHttpStatus() && mType >= 499 && mType <= 599) || // Include special 499 in retryables
*this == cant_connect || // Connection reset/endpoint problems
*this == cant_res_proxy || // DNS problems
*this == cant_res_host || // DNS problems
*this == send_error || // General socket problems
*this == recv_error || // General socket problems
*this == upload_failed || // Transport problem
*this == op_timedout || // Timer expired
*this == post_error || // Transport problem
*this == partial_file || // Data inconsistency in response
*this == inv_cont_range); // Short data read disagrees with content-range
}
} // end namespace LLCore

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -303,6 +303,12 @@ struct HttpStatus
{
return mType >= type_enum_t(100) && mType <= type_enum_t(999);
}
/// Returns true if the status is one that will be retried
/// internally. Provided for external consumption for cases
/// where that logic needs to be replicated. Only applies
/// to failed statuses, successful statuses will return false.
bool isRetryable() const;
}; // end struct HttpStatus

View File

@ -48,8 +48,9 @@ class HttpHeaders;
/// individual pieces of the response.
///
/// Typical usage will have the caller interrogate the object
/// and return from the handler callback. Instances are refcounted
/// and callers can bump the count and retain the object as needed.
/// during the handler callback and then simply returning.
/// But instances are refcounted and and callers can add a
/// reference and hold onto the object after the callback.
///
/// Threading: Not intrinsically thread-safe.
///
@ -119,6 +120,10 @@ public:
/// caller is going to have to make assumptions on receipt of
/// a 206 status. The @full value may also be zero in cases of
/// parsing problems or a wild-carded length response.
///
/// These values will not necessarily agree with the data in
/// the body itself (if present). The BufferArray object
/// is authoritative for actual data length.
void getRange(unsigned int * offset, unsigned int * length, unsigned int * full) const
{
*offset = mReplyOffset;

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -45,6 +45,15 @@
using namespace LLCoreInt;
// spin/sleep waiting times for client/server exchange tests
//
// These are now fairly generous to try to get around timeout
// ('reasonable time') failures during execution on a heavily-
// loaded system where the unit test is in competition with
// other programs.
static const int LOOP_SLEEP_INTERVAL(10000);
static const int LOOP_COUNT_SHORT(500); // 5-second dwell time
static const int LOOP_COUNT_LONG(3000); // 30-second dwell time
namespace
{
@ -294,11 +303,11 @@ void HttpRequestTestObjectType::test<3>()
// Run the notification pump.
int count(0);
int limit(20);
int limit(LOOP_COUNT_SHORT);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -309,21 +318,21 @@ void HttpRequestTestObjectType::test<3>()
// Run the notification pump again
count = 0;
limit = 100;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -392,12 +401,12 @@ void HttpRequestTestObjectType::test<4>()
// Run the notification pump.
int count(0);
int limit(20);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 2)
{
req1->update(1000000);
req2->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 2);
@ -409,22 +418,22 @@ void HttpRequestTestObjectType::test<4>()
// Run the notification pump again
count = 0;
limit = 100;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 3)
{
req1->update(1000000);
req2->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 3);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -493,11 +502,11 @@ void HttpRequestTestObjectType::test<5>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_SHORT);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("NoOp notification received", mHandlerCalls == 1);
@ -569,11 +578,11 @@ void HttpRequestTestObjectType::test<6>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_SHORT);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("No notifications received", mHandlerCalls == 0);
@ -650,11 +659,11 @@ void HttpRequestTestObjectType::test<7>()
// Run the notification pump.
int count(0);
int limit(50); // With one retry, should fail quickish
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -666,21 +675,21 @@ void HttpRequestTestObjectType::test<7>()
// Run the notification pump again
count = 0;
limit = 100;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -766,11 +775,11 @@ void HttpRequestTestObjectType::test<8>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -782,21 +791,21 @@ void HttpRequestTestObjectType::test<8>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -876,11 +885,11 @@ void HttpRequestTestObjectType::test<9>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -892,21 +901,21 @@ void HttpRequestTestObjectType::test<9>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -988,11 +997,11 @@ void HttpRequestTestObjectType::test<10>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1004,21 +1013,21 @@ void HttpRequestTestObjectType::test<10>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1106,11 +1115,11 @@ void HttpRequestTestObjectType::test<11>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1122,21 +1131,21 @@ void HttpRequestTestObjectType::test<11>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1226,11 +1235,11 @@ void HttpRequestTestObjectType::test<12>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1242,21 +1251,21 @@ void HttpRequestTestObjectType::test<12>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1339,8 +1348,8 @@ void HttpRequestTestObjectType::test<13>()
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base,
0,
0,
0,
0,
opts,
NULL,
&handler);
@ -1352,11 +1361,11 @@ void HttpRequestTestObjectType::test<13>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1369,21 +1378,21 @@ void HttpRequestTestObjectType::test<13>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1471,11 +1480,11 @@ void HttpRequestTestObjectType::test<14>()
// Run the notification pump.
int count(0);
int limit(50); // With one retry, should fail quickish
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1487,21 +1496,21 @@ void HttpRequestTestObjectType::test<14>()
// Run the notification pump again
count = 0;
limit = 100;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1594,11 +1603,11 @@ void HttpRequestTestObjectType::test<15>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1611,21 +1620,21 @@ void HttpRequestTestObjectType::test<15>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1724,11 +1733,11 @@ void HttpRequestTestObjectType::test<16>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1764,11 +1773,11 @@ void HttpRequestTestObjectType::test<16>()
// Run the notification pump.
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 2);
@ -1783,21 +1792,21 @@ void HttpRequestTestObjectType::test<16>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 3)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 3);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -1919,11 +1928,11 @@ void HttpRequestTestObjectType::test<17>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -1938,21 +1947,21 @@ void HttpRequestTestObjectType::test<17>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -2079,11 +2088,11 @@ void HttpRequestTestObjectType::test<18>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -2098,21 +2107,21 @@ void HttpRequestTestObjectType::test<18>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -2237,11 +2246,11 @@ void HttpRequestTestObjectType::test<19>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -2255,21 +2264,21 @@ void HttpRequestTestObjectType::test<19>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -2401,11 +2410,11 @@ void HttpRequestTestObjectType::test<20>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -2420,21 +2429,21 @@ void HttpRequestTestObjectType::test<20>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -2569,11 +2578,11 @@ void HttpRequestTestObjectType::test<21>()
// Run the notification pump.
int count(0);
int limit(10);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
@ -2588,21 +2597,21 @@ void HttpRequestTestObjectType::test<21>()
// Run the notification pump again
count = 0;
limit = 10;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000000);
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Second request executed in reasonable time", count < limit);
ensure("Second handler invocation", mHandlerCalls == 2);
// See that we actually shutdown the thread
count = 0;
limit = 10;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(100000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
@ -2650,6 +2659,200 @@ void HttpRequestTestObjectType::test<21>()
}
}
// BUG-2295 Tests - Content-Range header received but no body
template <> template <>
void HttpRequestTestObjectType::test<22>()
{
ScopedCurlInit ready;
std::string url_base(get_base_url());
// std::cerr << "Base: " << url_base << std::endl;
set_test_name("BUG-2295");
// Handler can be stack-allocated *if* there are no dangling
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpOptions * options = NULL;
HttpRequest * req = NULL;
try
{
// options set
options = new HttpOptions();
options->setRetries(1); // Partial_File is retryable and can timeout in here
// Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
// over the test.
HttpRequest::startThread();
// create a new ref counted object with an implicit reference
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
// ======================================
// Issue bug2295 GETs that will get a 206
// ======================================
mStatus = HttpStatus(206);
static const int test_count(3);
for (int i(0); i < test_count; ++i)
{
char buffer[128];
sprintf(buffer, "/bug2295/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base + buffer,
0,
25,
options,
NULL,
&handler);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
// Run the notification pump.
int count(0);
int limit(LOOP_COUNT_LONG);
while (count++ < limit && mHandlerCalls < test_count)
{
req->update(1000000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time - ms1", count < limit);
ensure("One handler invocation for each request - ms1", mHandlerCalls == test_count);
// ======================================
// Issue bug2295 GETs that will get a libcurl 18 (PARTIAL_FILE)
// ======================================
mHandlerCalls = 0;
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE);
static const int test2_count(1);
for (int i(0); i < test2_count; ++i)
{
char buffer[128];
sprintf(buffer, "/bug2295/00000012/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base + buffer,
0,
25,
options,
NULL,
&handler);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
// Run the notification pump.
count = 0;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < test2_count)
{
req->update(1000000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time - ms2", count < limit);
ensure("One handler invocation for each request - ms2", mHandlerCalls == test2_count);
// ======================================
// Issue bug2295 GETs that will get an llcorehttp HE_INV_CONTENT_RANGE_HDR status
// ======================================
mHandlerCalls = 0;
mStatus = HttpStatus(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
static const int test3_count(1);
for (int i(0); i < test3_count; ++i)
{
char buffer[128];
sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base + buffer,
0,
25,
options,
NULL,
&handler);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
// Run the notification pump.
count = 0;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < test3_count)
{
req->update(1000000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Request executed in reasonable time - ms3", count < limit);
ensure("One handler invocation for each request - ms3", mHandlerCalls == test3_count);
// ======================================
// Okay, request a shutdown of the servicing thread
// ======================================
mStatus = HttpStatus();
mHandlerCalls = 0;
HttpHandle handle = req->requestStopThread(&handler);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
count = 0;
limit = LOOP_COUNT_LONG;
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000000);
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Shutdown request executed in reasonable time", count < limit);
ensure("Shutdown handler invocation", mHandlerCalls == 1);
// See that we actually shutdown the thread
count = 0;
limit = LOOP_COUNT_SHORT;
while (count++ < limit && ! HttpService::isStopped())
{
usleep(LOOP_SLEEP_INTERVAL);
}
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
if (options)
{
options->release();
options = NULL;
}
// release the request object
delete req;
req = NULL;
// Shut down service
HttpRequest::destroyService();
#if defined(WIN32)
// Can only do this memory test on Windows. On other platforms,
// the LL logging system holds on to memory and produces what looks
// like memory leaks...
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
#endif
}
catch (...)
{
stop_thread(req);
delete req;
HttpRequest::destroyService();
throw;
}
}
} // end namespace tut

View File

@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
* Copyright (C) 2012-2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -91,9 +91,6 @@ template <> template <>
void HttpStatusTestObjectType::test<2>()
{
set_test_name("HttpStatus memory structure");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
// Require that an HttpStatus object can be trivially
// returned as a function return value in registers.
@ -106,10 +103,7 @@ void HttpStatusTestObjectType::test<2>()
template <> template <>
void HttpStatusTestObjectType::test<3>()
{
set_test_name("HttpStatus valid error string conversion");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
set_test_name("HttpStatus valid status string conversion");
HttpStatus status;
status.mType = HttpStatus::EXT_CURL_EASY;
@ -141,10 +135,7 @@ void HttpStatusTestObjectType::test<3>()
template <> template <>
void HttpStatusTestObjectType::test<4>()
{
set_test_name("HttpStatus invalid error string conversion");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
set_test_name("HttpStatus invalid status string conversion");
HttpStatus status;
status.mType = HttpStatus::EXT_CURL_EASY;
@ -170,9 +161,6 @@ template <> template <>
void HttpStatusTestObjectType::test<5>()
{
set_test_name("HttpStatus equality/inequality testing");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
// Make certain equality/inequality tests do not pass
// through the bool conversion. Distinct successful
@ -193,9 +181,6 @@ template <> template <>
void HttpStatusTestObjectType::test<6>()
{
set_test_name("HttpStatus basic HTTP status encoding");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
HttpStatus status;
status.mType = 200;
@ -242,10 +227,7 @@ void HttpStatusTestObjectType::test<6>()
template <> template <>
void HttpStatusTestObjectType::test<7>()
{
set_test_name("HttpStatus HTTP error text strings");
#if LL_WINDOWS
skip("MAINT-2302: This frequently (though not always) fails on Windows.");
#endif
set_test_name("HttpStatus HTTP status text strings");
HttpStatus status(100, HE_REPLY_ERROR);
std::string msg(status.toString());

View File

@ -9,7 +9,7 @@
$LicenseInfo:firstyear=2008&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2012, Linden Research, Inc.
Copyright (C) 2012-2013, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -35,6 +35,10 @@ import time
import select
import getopt
from threading import Thread
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
@ -47,7 +51,30 @@ from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
LLSD-flavored messages sent by the C++ LLHTTPClient.
Target URLs are fairly free-form and are assembled by
concatinating fragments. Currently defined fragments
are:
- '/reflect/' Request headers are bounced back to caller
after prefixing with 'X-Reflect-'
- '/fail/' Body of request can contain LLSD with
'reason' string and 'status' integer
which will become response header.
- '/bug2295/' 206 response, no data in body:
-- '/bug2295/0/' "Content-Range: bytes 0-75/2983"
-- '/bug2295/1/' "Content-Range: bytes 0-75/*"
-- '/bug2295/2/' "Content-Range: bytes 0-75/2983",
"Content-Length: 0"
-- '/bug2295/00000018/0/' Generates PARTIAL_FILE (18) error in libcurl.
"Content-Range: bytes 0-75/2983",
"Content-Length: 76"
-- '/bug2295/inv_cont_range/0/' Generates HE_INVALID_CONTENT_RANGE error in llcorehttp.
Some combinations make no sense, there's no effort to protect
you from that.
"""
ignore_exceptions = (Exception,)
def read(self):
# The following logic is adapted from the library module
# SimpleXMLRPCServer.py.
@ -87,42 +114,36 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self, withdata=True):
# Of course, don't attempt to read data.
self.answer(dict(reply="success", status=200,
reason="Your GET operation worked"))
try:
self.answer(dict(reply="success", status=200,
reason="Your GET operation worked"))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during GET (ignoring): %s" % str(e)
def do_POST(self):
# Read the provided POST data.
# self.answer(self.read())
self.answer(dict(reply="success", status=200,
reason=self.read()))
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during POST (ignoring): %s" % str(e)
def do_PUT(self):
# Read the provided PUT data.
# self.answer(self.read())
self.answer(dict(reply="success", status=200,
reason=self.read()))
try:
self.answer(dict(reply="success", status=200,
reason=self.read()))
except self.ignore_exceptions, e:
print >> sys.stderr, "Exception during PUT (ignoring): %s" % str(e)
def answer(self, data, withdata=True):
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
if "/sleep/" in self.path:
time.sleep(30)
if "fail" not in self.path:
data = data.copy() # we're going to modify
# Ensure there's a "reply" key in data, even if there wasn't before
data["reply"] = data.get("reply", llsd.LLSD("success"))
response = llsd.format_xml(data)
debug("success: %s", response)
self.send_response(200)
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "application/llsd+xml")
self.send_header("Content-Length", str(len(response)))
self.send_header("X-LL-Special", "Mememememe");
self.end_headers()
if withdata:
self.wfile.write(response)
else: # fail requested
if "fail" in self.path:
status = data.get("status", 500)
# self.responses maps an int status to a (short, long) pair of
# strings. We want the longer string. That's why we pass a string
@ -138,6 +159,57 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
if "/reflect/" in self.path:
self.reflect_headers()
self.end_headers()
elif "/bug2295/" in self.path:
# Test for https://jira.secondlife.com/browse/BUG-2295
#
# Client can receive a header indicating data should
# appear in the body without actually getting the body.
# Library needs to defend against this case.
#
body = None
if "/bug2295/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
elif "/bug2295/1/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/*")
elif "/bug2295/2/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
self.send_header("Content-Length", "0")
elif "/bug2295/00000012/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
self.send_header("Content-Length", "76")
elif "/bug2295/inv_cont_range/0/" in self.path:
self.send_response(206)
self.send_header("Content-Range", "bytes 0-75/2983")
body = "Some text, but not enough."
else:
# Unknown request
self.send_response(400)
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "text/plain")
self.end_headers()
if body:
self.wfile.write(body)
else:
# Normal response path
data = data.copy() # we're going to modify
# Ensure there's a "reply" key in data, even if there wasn't before
data["reply"] = data.get("reply", llsd.LLSD("success"))
response = llsd.format_xml(data)
debug("success: %s", response)
self.send_response(200)
if "/reflect/" in self.path:
self.reflect_headers()
self.send_header("Content-type", "application/llsd+xml")
self.send_header("Content-Length", str(len(response)))
self.send_header("X-LL-Special", "Mememememe");
self.end_headers()
if withdata:
self.wfile.write(response)
def reflect_headers(self):
for name in self.headers.keys():
@ -162,6 +234,17 @@ class Server(ThreadingMixIn, HTTPServer):
# operation of freeport() absolutely depends on it being off.
allow_reuse_address = False
# Override of BaseServer.handle_error(). Not too interested
# in errors and the default handler emits a scary traceback
# to stderr which annoys some. Disable this override to get
# default behavior which *shouldn't* cause the program to return
# a failure status.
def handle_error(self, request, client_address):
print '-'*40
print 'Ignoring exception during processing of request from',
print client_address
print '-'*40
if __name__ == "__main__":
do_valgrind = False
path_search = False
@ -188,3 +271,4 @@ if __name__ == "__main__":
args = ["valgrind", "--log-file=./valgrind.log"] + args
path_search = True
sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), use_path=path_search, *args))

View File

@ -107,15 +107,14 @@ public:
inline void rotate(const LLVector4a& v, LLVector4a& res)
{
res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
res.mul(mMatrix[0]);
LLVector4a y;
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
y.mul(mMatrix[1]);
LLVector4a y,z;
LLVector4a z;
res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
res.mul(mMatrix[0]);
y.mul(mMatrix[1]);
z.mul(mMatrix[2]);
res.add(y);

View File

@ -39,34 +39,6 @@
#include <stdint.h>
#endif
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)
{
return reinterpret_cast<T*>(
(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
}
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
{
return reinterpret_cast<T*>(
(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
}
#if LL_LINUX || LL_DARWIN
#define LL_ALIGN_PREFIX(x)
#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x)))
#elif LL_WINDOWS
#define LL_ALIGN_PREFIX(x) __declspec(align(x))
#define LL_ALIGN_POSTFIX(x)
#else
#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined"
#endif
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
#include <xmmintrin.h>
#include <emmintrin.h>

View File

@ -43,63 +43,7 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F
/*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes)
{
assert(src != NULL);
assert(dst != NULL);
assert(bytes > 0);
assert((bytes % sizeof(F32))== 0);
ll_assert_aligned(src,16);
ll_assert_aligned(dst,16);
assert(bytes%16==0);
F32* end = dst + (bytes / sizeof(F32) );
if (bytes > 64)
{
F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
//at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies
F32* end_64 = end-16;
_mm_prefetch((char*)begin_64, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
while (dst < begin_64)
{
copy4a(dst, src);
dst += 4;
src += 4;
}
while (dst < end_64)
{
_mm_prefetch((char*)src + 512, _MM_HINT_NTA);
_mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
copy4a(dst, src);
copy4a(dst+4, src+4);
copy4a(dst+8, src+8);
copy4a(dst+12, src+12);
dst += 16;
src += 16;
}
}
// <FS:ND> There is no guarantee that the remaining about of bytes left is a number of 16. If that's not the case using copy4a will overwrite and trash memory behind the end of dst
// while (dst < end)
// {
// copy4a(dst, src);
// dst += 4;
// src += 4;
// }
bytes = (U8*)end-(U8*)dst;
if( bytes > 0 )
memcpy( dst, src, bytes );
// </FS:ND>
ll_memcpy_nonaliased_aligned_16((char*)dst, (char*)src, bytes);
}
void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec )

View File

@ -460,16 +460,13 @@ inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs)
mQ = _mm_max_ps(lhs.mQ, rhs.mQ);
}
// Set this to (c * lhs) + rhs * ( 1 - c)
// Set this to lhs + (rhs-lhs)*c
inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c)
{
LLVector4a a = lhs;
a.mul(c);
LLVector4a b = rhs;
b.mul(1.f-c);
setAdd(a, b);
LLVector4a t;
t.setSub(rhs,lhs);
t.mul(c);
setAdd(lhs, t);
}
inline LLBool32 LLVector4a::isFinite3() const

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,6 @@ class LLPath;
template <class T> class LLOctreeNode;
class LLVector4a;
class LLVolumeFace;
class LLVolume;
class LLVolumeTriangle;
@ -50,12 +49,15 @@ class LLVolumeTriangle;
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
#include "llvector4a.h"
#include "llmatrix4a.h"
#include "llquaternion.h"
#include "llstrider.h"
#include "v4coloru.h"
#include "llrefcount.h"
#include "llpointer.h"
#include "llfile.h"
#include "llalignedarray.h"
//============================================================================
@ -711,16 +713,16 @@ public:
LLFaceID mFaceID;
};
std::vector<LLVector3> mProfile;
std::vector<LLVector2> mNormals;
LLAlignedArray<LLVector4a, 64> mProfile;
//LLAlignedArray<LLVector4a, 64> mNormals;
std::vector<Face> mFaces;
std::vector<LLVector3> mEdgeNormals;
std::vector<LLVector3> mEdgeCenters;
//LLAlignedArray<LLVector4a, 64> mEdgeNormals;
//LLAlignedArray<LLVector4a, 64> mEdgeCenters;
friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);
protected:
void genNormals(const LLProfileParams& params);
static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
@ -744,13 +746,29 @@ protected:
class LLPath
{
public:
struct PathPt
class PathPt
{
LLVector3 mPos;
LLVector2 mScale;
LLQuaternion mRot;
public:
LLMatrix4a mRot;
LLVector4a mPos;
LLVector4a mScale;
F32 mTexT;
PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); }
F32 pad[3]; //for alignment
PathPt()
{
mPos.clear();
mTexT = 0;
mScale.clear();
mRot.setRows(LLVector4a(1,0,0,0),
LLVector4a(0,1,0,0),
LLVector4a(0,0,1,0));
//distinguished data in the pad for debugging
pad[0] = 3.14159f;
pad[1] = -3.14159f;
pad[2] = 0.585f;
}
};
public:
@ -782,7 +800,7 @@ public:
friend std::ostream& operator<<(std::ostream &s, const LLPath &path);
public:
std::vector<PathPt> mPath;
LLAlignedArray<PathPt, 64> mPath;
protected:
BOOL mOpen;
@ -915,6 +933,7 @@ public:
LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
S32 mNumVertices;
S32 mNumAllocatedVertices;
S32 mNumIndices;
LLVector4a* mPositions;
@ -936,6 +955,9 @@ public:
LLOctreeNode<LLVolumeTriangle>* mOctree;
//whether or not face has been cache optimized
BOOL mOptimized;
private:
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
@ -950,11 +972,7 @@ protected:
~LLVolume(); // use unref
public:
struct Point
{
LLVector3 mPos;
};
struct FaceParams
{
LLFaceID mFaceID;
@ -977,8 +995,8 @@ public:
const LLProfile& getProfile() const { return *mProfilep; }
LLPath& getPath() const { return *mPathp; }
void resizePath(S32 length);
const std::vector<Point>& getMesh() const { return mMesh; }
const LLVector3& getMeshPt(const U32 i) const { return mMesh[i].mPos; }
const LLAlignedArray<LLVector4a,64>& getMesh() const { return mMesh; }
const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; }
void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
@ -993,10 +1011,7 @@ public:
S32 getSculptLevel() const { return mSculptLevel; }
void setSculptLevel(S32 level) { mSculptLevel = level; }
S32 *getTriangleIndices(U32 &num_indices) const;
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
// <FS:ND> Cache LOD Triangle counts, it is expensive to calculate them each time.
// static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
@ -1071,7 +1086,8 @@ public:
LLVolumeParams mParams;
LLPath *mPathp;
LLProfile *mProfilep;
std::vector<Point> mMesh;
LLAlignedArray<LLVector4a,64> mMesh;
BOOL mGenerateSingleFace;
typedef std::vector<LLVolumeFace> face_list_t;

View File

@ -92,6 +92,7 @@ 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).
CURL* LLCurl::sCurlTemplateStandardHandle = NULL;
void check_curl_code(CURLcode code)
{
@ -1850,10 +1851,10 @@ CURL* LLCurl::newEasyHandle()
}
sTotalHandles++;
CURL* ret = curl_easy_init() ;
CURL* ret = createStandardCurlHandle();
if(!ret)
{
llwarns << "curl_easy_init failed." << llendl ;
llwarns << "failed to create curl handle." << llendl ;
}
return ret ;
@ -1883,3 +1884,47 @@ void LLCurlFF::check_multi_code(CURLMcode code)
{
check_curl_multi_code(code);
}
// Static
CURL* LLCurl::createStandardCurlHandle()
{
if (sCurlTemplateStandardHandle == NULL)
{ // Late creation of the template curl handle
sCurlTemplateStandardHandle = curl_easy_init();
if (sCurlTemplateStandardHandle == NULL)
{
llwarns << "curl error calling curl_easy_init()" << llendl;
}
else
{
CURLcode result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOSIGNAL, 1);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOPROGRESS, 1);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_ENCODING, "");
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_AUTOREFERER, 1);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_FOLLOWLOCATION, 1);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYPEER, 1);
check_curl_code(result);
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYHOST, 0);
check_curl_code(result);
// The Linksys WRT54G V5 router has an issue with frequent
// DNS lookups from LAN machines. If they happen too often,
// like for every HTTP request, the router gets annoyed after
// about 700 or so requests and starts issuing TCP RSTs to
// new connections. Reuse the DNS lookups for even a few
// seconds and no RSTs.
result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
check_curl_code(result);
}
}
return curl_easy_duphandle(sCurlTemplateStandardHandle);
}

View File

@ -45,7 +45,7 @@
#include "llqueuedthread.h"
#include "llframetimer.h"
#include "llpointer.h"
#include "llsingleton.h"
class LLMutex;
class LLCurlThread;
@ -188,6 +188,8 @@ public:
static CURL* newEasyHandle() ;
static void deleteEasyHandle(CURL* handle) ;
static CURL* createStandardCurlHandle();
private:
static std::string sCAPath;
static std::string sCAFile;
@ -197,6 +199,7 @@ private:
static LLMutex* sHandleMutexp ;
static S32 sTotalHandles ;
static S32 sMaxHandles;
static CURL* sCurlTemplateStandardHandle;
public:
static bool sNotQuitting;
static F32 sCurlRequestTimeOut;

View File

@ -37,53 +37,46 @@
const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18
const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86
const S32 PS_PART_DATA_GLOW_SIZE = 2;
const S32 PS_PART_DATA_BLEND_SIZE = 2;
const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
PS_LEGACY_PART_DATA_BLOCK_SIZE +
PS_PART_DATA_BLEND_SIZE +
PS_PART_DATA_GLOW_SIZE+
8; //two S32 size fields
const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND;
const F32 MAX_PART_SCALE = 4.f;
BOOL LLPartData::pack(LLDataPacker &dp)
bool LLPartData::hasGlow() const
{
LLColor4U coloru;
dp.packU32(mFlags, "pdflags");
dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8);
coloru.setVec(mStartColor);
dp.packColor4U(coloru, "pdstartcolor");
coloru.setVec(mEndColor);
dp.packColor4U(coloru, "pdendcolor");
dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5);
dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
return TRUE;
return mStartGlow > 0.f || mEndGlow > 0.f;
}
LLSD LLPartData::asLLSD() const
bool LLPartData::hasBlendFunc() const
{
LLSD sd = LLSD();
sd["pdflags"] = ll_sd_from_U32(mFlags);
sd["pdmaxage"] = mMaxAge;
sd["pdstartcolor"] = ll_sd_from_color4(mStartColor);
sd["pdendcolor"] = ll_sd_from_color4(mEndColor);
sd["pdstartscale"] = ll_sd_from_vector2(mStartScale);
sd["pdendscale"] = ll_sd_from_vector2(mEndScale);
return sd;
return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
}
bool LLPartData::fromLLSD(LLSD& sd)
S32 LLPartData::getSize() const
{
mFlags = ll_U32_from_sd(sd["pdflags"]);
mMaxAge = (F32)sd["pdmaxage"].asReal();
mStartColor = ll_color4_from_sd(sd["pdstartcolor"]);
mEndColor = ll_color4_from_sd(sd["pdendcolor"]);
mStartScale = ll_vector2_from_sd(sd["pdstartscale"]);
mEndScale = ll_vector2_from_sd(sd["pdendscale"]);
return true;
S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
return size;
}
BOOL LLPartData::unpack(LLDataPacker &dp)
BOOL LLPartData::unpackLegacy(LLDataPacker &dp)
{
LLColor4U coloru;
@ -98,9 +91,70 @@ BOOL LLPartData::unpack(LLDataPacker &dp)
dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
mStartGlow = 0.f;
mEndGlow = 0.f;
mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
return TRUE;
}
BOOL LLPartData::unpack(LLDataPacker &dp)
{
S32 size = 0;
dp.unpackS32(size, "partsize");
unpackLegacy(dp);
size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
if (mFlags & LL_PART_DATA_GLOW)
{
if (size < PS_PART_DATA_GLOW_SIZE) return FALSE;
U8 tmp_glow = 0;
dp.unpackU8(tmp_glow,"pdstartglow");
mStartGlow = tmp_glow / 255.f;
dp.unpackU8(tmp_glow,"pdendglow");
mEndGlow = tmp_glow / 255.f;
size -= PS_PART_DATA_GLOW_SIZE;
}
else
{
mStartGlow = 0.f;
mEndGlow = 0.f;
}
if (mFlags & LL_PART_DATA_BLEND)
{
if (size < PS_PART_DATA_BLEND_SIZE) return FALSE;
dp.unpackU8(mBlendFuncSource,"pdblendsource");
dp.unpackU8(mBlendFuncDest,"pdblenddest");
size -= PS_PART_DATA_BLEND_SIZE;
}
else
{
mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
}
if (size > 0)
{ //leftover bytes, unrecognized parameters
U8 feh = 0;
while (size > 0)
{ //read remaining bytes in block
dp.unpackU8(feh, "whippang");
size--;
}
//this particle system won't display properly, better to not show anything
return FALSE;
}
return TRUE;
}
void LLPartData::setFlags(const U32 flags)
{
@ -148,6 +202,18 @@ void LLPartData::setEndAlpha(const F32 alpha)
mEndColor.mV[3] = alpha;
}
// static
bool LLPartData::validBlendFunc(S32 func)
{
if (func >= 0
&& func < LL_PART_BF_COUNT
&& func != UNSUPPORTED_DEST_ALPHA
&& func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
{
return true;
}
return false;
}
LLPartSysData::LLPartSysData()
{
@ -160,6 +226,10 @@ LLPartSysData::LLPartSysData()
mPartData.mStartScale = LLVector2(1.f, 1.f);
mPartData.mEndScale = LLVector2(1.f, 1.f);
mPartData.mMaxAge = 10.0;
mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
mPartData.mStartGlow = 0.f;
mPartData.mEndGlow = 0.f;
mMaxAge = 0.0;
mStartAge = 0.0;
@ -175,38 +245,7 @@ LLPartSysData::LLPartSysData()
mNumParticles = 0;
}
BOOL LLPartSysData::pack(LLDataPacker &dp)
{
dp.packU32(mCRC, "pscrc");
dp.packU32(mFlags, "psflags");
dp.packU8(mPattern, "pspattern");
dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8);
dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8);
dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5);
dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5);
dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8);
dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8);
dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8);
dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8);
dp.packU8(mBurstPartCount, "psburstpartcount");
dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7);
dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7);
dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7);
dp.packUUID(mPartImageID, "psuuid");
dp.packUUID(mTargetUUID, "pstargetuuid");
mPartData.pack(dp);
return TRUE;
}
BOOL LLPartSysData::unpack(LLDataPacker &dp)
BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)
{
dp.unpackU32(mCRC, "pscrc");
dp.unpackU32(mFlags, "psflags");
@ -232,10 +271,48 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)
dp.unpackUUID(mPartImageID, "psuuid");
dp.unpackUUID(mTargetUUID, "pstargetuuid");
mPartData.unpack(dp);
return TRUE;
}
BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp)
{
unpackSystem(dp);
mPartData.unpackLegacy(dp);
return TRUE;
}
BOOL LLPartSysData::unpack(LLDataPacker &dp)
{
// syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
S32 size = 0;
dp.unpackS32(size, "syssize");
if (size != PS_SYS_DATA_BLOCK_SIZE)
{ //unexpected size, this viewer doesn't know how to parse this particle system
//skip to LLPartData block
U8 feh = 0;
for (U32 i = 0; i < size; ++i)
{
dp.unpackU8(feh, "whippang");
}
dp.unpackS32(size, "partsize");
//skip LLPartData block
for (U32 i = 0; i < size; ++i)
{
dp.unpackU8(feh, "whippang");
}
return FALSE;
}
unpackSystem(dp);
return mPartData.unpack(dp);
}
std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
{
s << "Flags: " << std::hex << data.mFlags;
@ -253,7 +330,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
BOOL LLPartSysData::isNullPS(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
U32 crc;
S32 size;
@ -264,14 +341,28 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)
{
return TRUE;
}
else if (size != PS_DATA_BLOCK_SIZE)
if (size > PS_MAX_DATA_BLOCK_SIZE)
{
llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
//size is too big, newer particle version unsupported
return TRUE;
}
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, size);
if (size > PS_LEGACY_DATA_BLOCK_SIZE)
{
// non legacy systems pack a size before the CRC
S32 tmp = 0;
dp.unpackS32(tmp, "syssize");
if (tmp > PS_SYS_DATA_BLOCK_SIZE)
{ //unknown system data block size, don't know how to parse it, treat as NULL
return TRUE;
}
}
dp.unpackU32(crc, "crc");
if (crc == 0)
@ -281,50 +372,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)
return FALSE;
}
//static
BOOL LLPartSysData::packNull()
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0);
return TRUE;
}
BOOL LLPartSysData::packBlock()
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
pack(dp);
// Add to message
gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE);
return TRUE;
}
BOOL LLPartSysData::unpackBlock(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
// Check size of block
S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
if (size != PS_DATA_BLOCK_SIZE)
if (size > PS_MAX_DATA_BLOCK_SIZE)
{
llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
// Larger packets are newer and unsupported
return FALSE;
}
// Get from message
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
unpack(dp);
LLDataPackerBinaryBuffer dp(ps_data_block, size);
return TRUE;
if (size == PS_LEGACY_DATA_BLOCK_SIZE)
{
return unpackLegacy(dp);
}
else
{
return unpack(dp);
}
}
bool LLPartSysData::isLegacyCompatible() const
{
return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
}
void LLPartSysData::clampSourceParticleRate()

View File

@ -70,7 +70,12 @@ enum LLPSScriptFlags
LLPS_SRC_TARGET_UUID,
LLPS_SRC_OMEGA,
LLPS_SRC_ANGLE_BEGIN,
LLPS_SRC_ANGLE_END
LLPS_SRC_ANGLE_END,
LLPS_PART_BLEND_FUNC_SOURCE,
LLPS_PART_BLEND_FUNC_DEST,
LLPS_PART_START_GLOW,
LLPS_PART_END_GLOW
};
@ -83,6 +88,7 @@ public:
mParameter(0.f)
{
}
BOOL unpackLegacy(LLDataPacker &dp);
// <FS:ND> Need virtual dtor so derived classed are properly destroyed.
virtual ~LLPartData()
@ -90,10 +96,11 @@ public:
// </FS:ND>
BOOL unpack(LLDataPacker &dp);
BOOL pack(LLDataPacker &dp);
LLSD asLLSD() const;
operator LLSD() const {return asLLSD(); }
bool fromLLSD(LLSD& sd);
bool hasGlow() const;
bool hasBlendFunc() const;
// Masks for the different particle flags
enum
@ -108,17 +115,39 @@ public:
LL_PART_TARGET_LINEAR_MASK = 0x80, // Particle uses a direct linear interpolation
LL_PART_EMISSIVE_MASK = 0x100, // Particle is "emissive", instead of being lit
LL_PART_BEAM_MASK = 0x200, // Particle is a "beam" connecting source and target
LL_PART_RIBBON_MASK = 0x400, // Particles are joined together into one continuous triangle strip
// Not implemented yet!
//LL_PART_RANDOM_ACCEL_MASK = 0x100, // Particles have random acceleration
//LL_PART_RANDOM_VEL_MASK = 0x200, // Particles have random velocity shifts"
//LL_PART_TRAIL_MASK = 0x400, // Particles have historical "trails"
//sYSTEM SET FLAGS
LL_PART_DATA_GLOW = 0x10000,
LL_PART_DATA_BLEND = 0x20000,
// Viewer side use only!
LL_PART_HUD = 0x40000000,
LL_PART_DEAD_MASK = 0x80000000,
};
enum
{
LL_PART_BF_ONE = 0,
LL_PART_BF_ZERO = 1,
LL_PART_BF_DEST_COLOR = 2,
LL_PART_BF_SOURCE_COLOR = 3,
LL_PART_BF_ONE_MINUS_DEST_COLOR = 4,
LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5,
UNSUPPORTED_DEST_ALPHA = 6,
LL_PART_BF_SOURCE_ALPHA = 7,
UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8,
LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9,
LL_PART_BF_COUNT = 10
};
static bool validBlendFunc(S32 func);
void setFlags(const U32 flags);
void setMaxAge(const F32 max_age);
void setStartScale(const F32 xs, F32 ys);
@ -132,6 +161,9 @@ public:
friend class LLPartSysData;
friend class LLViewerPartSourceScript;
private:
S32 getSize() const;
// These are public because I'm really lazy...
public:
U32 mFlags; // Particle state/interpolators in effect
@ -143,6 +175,12 @@ public:
LLVector3 mPosOffset; // Offset from source if using FOLLOW_SOURCE
F32 mParameter; // A single floating point parameter
F32 mStartGlow;
F32 mEndGlow;
U8 mBlendFuncSource;
U8 mBlendFuncDest;
};
@ -152,18 +190,16 @@ public:
LLPartSysData();
BOOL unpack(LLDataPacker &dp);
BOOL pack(LLDataPacker &dp);
BOOL unpackLegacy(LLDataPacker &dp);
BOOL unpackBlock(const S32 block_num);
BOOL packBlock();
LLSD asLLSD() const;
bool fromLLSD(LLSD& sd);
static BOOL packNull();
static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system)
bool isLegacyCompatible() const;
// Different masks for effects on the source
enum
{
@ -196,7 +232,12 @@ public:
void clampSourceParticleRate();
friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a
S32 getdataBlockSize() const;
private:
BOOL unpackSystem(LLDataPacker &dp);
public:
// Public because I'm lazy....

View File

@ -606,16 +606,21 @@ void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
{
LLUUID *transfer_idp = (LLUUID *)user_data;
if (result)
if (result &&
transfer_idp != NULL)
{
llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
if (tsp)
{
llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
LLTransferSourceChannel *tscp = tsp->mChannelp;
tsp->abortTransfer();
tscp->deleteTransfer(tsp);
}
else
{
llwarns << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << llendl;
}
}
delete transfer_idp;
}
@ -892,22 +897,26 @@ LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &tran
}
BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
{
LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
if (tsp)
{
if (iter->second == tsp)
LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
{
delete tsp;
mTransferSources.mMap.erase(iter);
return TRUE;
if (iter->second == tsp)
{
delete tsp;
mTransferSources.mMap.erase(iter);
return;
}
}
}
llerrs << "Unable to find transfer source to delete!" << llendl;
return FALSE;
llwarns << "Unable to find transfer source id "
<< tsp->getID()
<< " to delete!"
<< llendl;
}
}
@ -1008,21 +1017,26 @@ LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &tran
}
BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
{
tt_iter iter;
for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
if (ttp)
{
if (*iter == ttp)
tt_iter iter;
for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
{
delete ttp;
mTransferTargets.erase(iter);
return TRUE;
if (*iter == ttp)
{
delete ttp;
mTransferTargets.erase(iter);
return;
}
}
}
llerrs << "Unable to find transfer target to delete!" << llendl;
return FALSE;
llwarns << "Unable to find transfer target id "
<< ttp->getID()
<< " to delete!"
<< llendl;
}
}

View File

@ -199,7 +199,7 @@ public:
void addTransferSource(LLTransferSource *sourcep);
LLTransferSource *findTransferSource(const LLUUID &transfer_id);
BOOL deleteTransfer(LLTransferSource *tsp);
void deleteTransfer(LLTransferSource *tsp);
void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; }
@ -232,7 +232,7 @@ public:
const F32 priority);
LLTransferTarget *findTransferTarget(const LLUUID &transfer_id);
BOOL deleteTransfer(LLTransferTarget *ttp);
void deleteTransfer(LLTransferTarget *ttp);
LLTransferChannelType getChannelType() const { return mChannelType; }

View File

@ -38,10 +38,34 @@
namespace tut
{
//bunch of sniffed data that *should* be a valid particle system
static U8 msg[] = {
0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66,
0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e,
0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2,
0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0,
0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc,
0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d,
0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef,
0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,
0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9,
0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55,
0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };
struct partdata_test
{
};
typedef test_group<partdata_test> partdata_test_t;
typedef partdata_test_t::object partdata_test_object_t;
tut::partdata_test_t tut_partdata_test("LLPartData");
@ -49,168 +73,82 @@ namespace tut
template<> template<>
void partdata_test_object_t::test<1>()
{
LLPartData llpdata,llpdata1;
U8 pkbuf[128];
LLPartSysData llpsysdata;
LLDataPackerBinaryBuffer dp1(msg, sizeof(msg));
llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1));
llpdata.setMaxAge(29.3f);
LLVector3 llvec1(1.0f, .5f, .25f);
llpdata.setStartColor(llvec1);
llpdata.setStartAlpha(.7f);
LLVector3 llvec2(.2f, .3f, 1.0f);
llpdata.setEndColor(llvec2);
llpdata.setEndAlpha(1.0f);
llpdata.setStartScale(3.23f, 4.0f);
llpdata.setEndScale(2.4678f, 1.0f);
LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128);
llpdata.pack(dp);
S32 cur_size = dp.getCurrentSize();
//mCRC 1 unsigned int
ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1);
//mFlags 0 unsigned int
ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0);
//mPattern 1 '' unsigned char
ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1);
//mInnerAngle 0.00000000 float
ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8);
//mOuterAngle 0.00000000 float
ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8);
//mAngularVelocity 0,0,0
ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8);
ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8);
ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8);
//mBurstRate 0.097656250 float
ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8);
//mBurstPartCount 1 '' unsigned char
ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1);
//mBurstRadius 0.00000000 float
ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8);
//mBurstSpeedMin 1.0000000 float
ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8);
//mBurstSpeedMax 1.0000000 float
ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8);
//mMaxAge 0.00000000 float
ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8);
//mStartAge 0.00000000 float
ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8);
//mPartAccel <0,0,0>
ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7);
ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7);
ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7);
//mPartData
LLPartData& data = llpsysdata.mPartData;
//mFlags 132354 unsigned int
ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354);
//mMaxAge 10.000000 float
ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8);
//mStartColor <1,1,1,1>
ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8);
ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8);
ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8);
ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8);
//mEndColor <1,1,0,0>
ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8);
ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8);
ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8);
ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8);
//mStartScale <1,1>
ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8);
ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8);
//mEndScale <0,0>
ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8);
ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8);
//mPosOffset <0,0,0>
ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8);
ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8);
ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8);
//mParameter 0.00000000 float
ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8);
LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
llpdata1.unpack(dp1);
ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
}
template<> template<>
void partdata_test_object_t::test<2>()
{
LLPartData llpdata,llpdata1;
llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
llpdata.setMaxAge(29.3f);
LLVector3 llvec1(1.0f, .5f, .25f);
llpdata.setStartColor(llvec1);
llpdata.setStartAlpha(.7f);
LLVector3 llvec2(.2f, .3f, 1.0f);
llpdata.setEndColor(llvec2);
llpdata.setEndAlpha(1.0f);
llpdata.setStartScale(3.23f, 4.0f);
llpdata.setEndScale(2.4678f, 1.0f);
LLSD llsd = llpdata.asLLSD();
llpdata1.fromLLSD(llsd);
ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
}
//*********llpartsysdata***********
template<> template<>
void partdata_test_object_t::test<3>()
{
LLPartSysData llpsysdata, llpsysdata1;
U8 pkbuf[256];
llpsysdata.setBurstSpeedMin(33.33f);
ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin);
llpsysdata.setBurstSpeedMax(44.44f);
ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax);
llpsysdata.setBurstRadius(45.55f);
ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius);
LLVector3 llvec(44.44f, 111.11f, -40.4f);
llpsysdata.setPartAccel(llvec);
llpsysdata.mCRC = 0xFFFFFFFF;
llpsysdata.mFlags = 0x20;
llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY;
llpsysdata.mMaxAge = 99.99f;
llpsysdata.mStartAge = 18.5f;
llpsysdata.mInnerAngle = 4.234f;
llpsysdata.mOuterAngle = 7.123f;
llpsysdata.mBurstRate = 245.53f;
llpsysdata.mBurstPartCount = 0xFF;
llpsysdata.mAngularVelocity = llvec;
llpsysdata.mPartImageID.generate();
llpsysdata.mTargetUUID.generate();
LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256);
llpsysdata.pack(dp);
S32 cur_size = dp.getCurrentSize();
LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
llpsysdata1.unpack(dp1);
ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC);
ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags);
ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern);
ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8);
ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8);
ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5);
ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5);
ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8);
ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount);
ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8);
ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8);
ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7);
ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7);
ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7);
ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7);
ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7);
ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7);
ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID);
ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID);
ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8);
//mStartGlow 0.00000000 float
ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8);
//mEndGlow 0.00000000 float
ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8);
//mBlendFuncSource 2 '' unsigned char
ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2);
//mBlendFuncDest 1 '' unsigned char
ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);
}
}

View File

@ -50,10 +50,17 @@ add_executable(SLPlugin
${SLPlugin_SOURCE_FILES}
)
if (WINDOWS)
set_target_properties(SLPlugin
PROPERTIES
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMTD\""
)
else ()
set_target_properties(SLPlugin
PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist
)
endif ()
if(WINDOWS)
set_target_properties(SLPlugin

View File

@ -186,48 +186,73 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace::VertexMapData::PointMap point_map;
for (U32 i = 0; i < idx.getCount(); i += idx_stride)
U32 index_count = idx.getCount();
U32 vertex_count = pos_source ? v.getCount() : 0;
U32 tc_count = tc_source ? tc.getCount() : 0;
U32 norm_count = norm_source ? n.getCount() : 0;
for (U32 i = 0; i < index_count; i += idx_stride)
{
LLVolumeFace::VertexData cv;
if (pos_source)
{
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( i+pos_offset >= idx.getCount() )
// guard against model data specifiying out of range indices or verts
//
if (((i + pos_offset) > index_count)
|| ((idx[i+pos_offset]*3+2) > vertex_count))
{
return LLModel::BAD_ELEMENT;
if( (idx[i+pos_offset]*3+2) >= v.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
}
cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
v[idx[i+pos_offset]*3+1],
v[idx[i+pos_offset]*3+2]));
if (!cv.getPosition().isFinite3())
{
return LLModel::BAD_ELEMENT;
}
}
if (tc_source)
{
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( i+tc_offset >= idx.getCount() )
// guard against model data specifiying out of range indices or tcs
//
if (((i + tc_offset) > index_count)
|| ((idx[i+pos_offset]*2+1) > tc_count))
{
return LLModel::BAD_ELEMENT;
if( (idx[i+tc_offset]*2+1) >= tc.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
}
cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
tc[idx[i+tc_offset]*2+1]);
if (!cv.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (norm_source)
{
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( i+norm_offset >= idx.getCount() )
// guard against model data specifiying out of range indices or norms
//
if (((i + norm_offset) > index_count)
|| ((idx[i+norm_offset]*3+2) > norm_count))
{
return LLModel::BAD_ELEMENT;
if( (idx[i+norm_offset]*3+2) >= n.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
}
cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
n[idx[i+norm_offset]*3+1],
n[idx[i+norm_offset]*3+2]));
if (!cv.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
BOOL found = FALSE;
@ -282,13 +307,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
@ -313,13 +338,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@ -385,6 +410,11 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace::VertexMapData::PointMap point_map;
U32 index_count = idx.getCount();
U32 vertex_count = pos_source ? v.getCount() : 0;
U32 tc_count = tc_source ? tc.getCount() : 0;
U32 norm_count = norm_source ? n.getCount() : 0;
U32 cur_idx = 0;
for (U32 i = 0; i < vcount.getCount(); ++i)
{ //for each polygon
@ -397,61 +427,65 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (pos_source)
{
// <FS:ND> FIRE-8139/BUG-670; Make sure there is no invalid data in this dae model
if( llisnan( v[idx[cur_idx+pos_offset]*3+0] ) )
// guard against model data specifiying out of range indices or verts
//
if (((i + pos_offset) > index_count)
|| ((idx[i+pos_offset]*3+2) > vertex_count))
{
llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
if( llisnan( v[idx[cur_idx+pos_offset]*3+1] ) )
{
llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
if( llisnan( v[idx[cur_idx+pos_offset]*3+2] ) )
{
llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
// </FS:ND>
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( cur_idx+pos_offset >= idx.getCount() )
return LLModel::BAD_ELEMENT;
if( (idx[cur_idx+pos_offset]*3+2) >= v.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
v[idx[cur_idx+pos_offset]*3+1],
v[idx[cur_idx+pos_offset]*3+2]);
if (!cv.getPosition().isFinite3())
{
llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (tc_source)
{
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( cur_idx+tc_offset >= idx.getCount() )
// guard against model data specifiying out of range indices or tcs
//
if (((i + pos_offset) > index_count)
|| ((idx[cur_idx+tc_offset]*2+1) > tc_count))
{
return LLModel::BAD_ELEMENT;
if( (idx[cur_idx+tc_offset]*2+1) >= tc.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
}
cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
tc[idx[cur_idx+tc_offset]*2+1]);
if (!cv.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (norm_source)
{
// <FS:ND> FIRE-9394; Guard against all kind of out of bounds access
if( cur_idx+norm_offset >= idx.getCount() )
// guard against model data specifiying out of range indices or norms
//
if (((i + pos_offset) > index_count)
|| ((idx[cur_idx+norm_offset]*3+2) > norm_count))
{
return LLModel::BAD_ELEMENT;
if( (idx[cur_idx+norm_offset]*3+2) >= n.getCount() )
return LLModel::BAD_ELEMENT;
// </FS:ND>
}
cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
n[idx[cur_idx+norm_offset]*3+1],
n[idx[cur_idx+norm_offset]*3+2]);
if (!cv.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
cur_idx += idx_stride;
@ -540,13 +574,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
@ -574,13 +608,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@ -692,6 +726,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getPosition().set(v->get(v_idx),
v->get(v_idx+1),
v->get(v_idx+2));
if (!vert.getPosition().isFinite3())
{
llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
//bounds check n and t lookups because some FBX to DAE converters
@ -704,6 +744,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getNormal().set(n->get(n_idx),
n->get(n_idx+1),
n->get(n_idx+2));
if (!vert.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
else
{
@ -717,6 +763,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
vert.mTexCoord.setVec(t->get(t_idx),
t->get(t_idx+1));
if (!vert.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
else
{
@ -790,13 +842,13 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
LLVolumeFace& new_face = *face_list.rbegin();
if (!n)
{
ll_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!t)
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
@ -1070,6 +1122,43 @@ void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& tra
translation_out = mNormalizedTranslation;
}
LLVector3 LLModel::getTransformedCenter(const LLMatrix4& mat)
{
LLVector3 ret;
if (!mVolumeFaces.empty())
{
LLMatrix4a m;
m.loadu(mat);
LLVector4a minv,maxv;
LLVector4a t;
m.affineTransform(mVolumeFaces[0].mPositions[0], t);
minv = maxv = t;
for (S32 i = 0; i < mVolumeFaces.size(); ++i)
{
LLVolumeFace& face = mVolumeFaces[i];
for (U32 j = 0; j < face.mNumVertices; ++j)
{
m.affineTransform(face.mPositions[j],t);
update_min_max(minv, maxv, t);
}
}
minv.add(maxv);
minv.mul(0.5f);
ret.set(minv.getF32ptr());
}
return ret;
}
void LLModel::setNumVolumeFaces(S32 count)
{
mVolumeFaces.resize(count);
@ -1096,7 +1185,7 @@ void LLModel::setVolumeFaceData(
}
else
{
ll_aligned_free_16(face.mNormals);
//ll_aligned_free_16(face.mNormals);
face.mNormals = NULL;
}
@ -1107,7 +1196,7 @@ void LLModel::setVolumeFaceData(
}
else
{
ll_aligned_free_16(face.mTexCoords);
//ll_aligned_free_16(face.mTexCoords);
face.mTexCoords = NULL;
}
@ -1306,7 +1395,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
else
{
ll_aligned_free_16(new_face.mTexCoords);
//ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}

View File

@ -173,13 +173,15 @@ public:
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
LLVector3 getTransformedCenter(const LLMatrix4& mat);
//reorder face list based on mMaterialList in this and reference so
//order matches that of reference (material ordering touchup)
bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
bool isMaterialListSubset( LLModel* ref );
bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
std::vector<std::string> mMaterialList;
//data used for skin weights

View File

@ -545,7 +545,7 @@ S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID)
{
mMaterialUpdatePending = true;
mMaterialID = pMaterialID;
return TEM_CHANGE_NONE;
return TEM_CHANGE_TEXTURE;
}
mMaterialUpdatePending = false;

View File

@ -59,6 +59,7 @@ BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
BOOL gHeadlessClient = FALSE;
BOOL gGLActive = FALSE;
BOOL gGLDebugLoggingEnabled = TRUE;
static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
static const std::string HEADLESS_RENDERER_STRING("Headless");
@ -72,6 +73,7 @@ std::ofstream gFailLog;
#define APIENTRY
#endif
void APIENTRY gl_debug_callback(GLenum source,
GLenum type,
GLuint id,
@ -80,22 +82,25 @@ void APIENTRY gl_debug_callback(GLenum source,
const GLchar* message,
GLvoid* userParam)
{
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
if (gGLDebugLoggingEnabled)
{
llwarns << "----- GL ERROR --------" << llendl;
}
else
{
llwarns << "----- GL WARNING -------" << llendl;
}
llwarns << "Type: " << std::hex << type << llendl;
llwarns << "ID: " << std::hex << id << llendl;
llwarns << "Severity: " << std::hex << severity << llendl;
llwarns << "Message: " << message << llendl;
llwarns << "-----------------------" << llendl;
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
{
llerrs << "Halting on GL Error" << llendl;
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
{
llwarns << "----- GL ERROR --------" << llendl;
}
else
{
llwarns << "----- GL WARNING -------" << llendl;
}
llwarns << "Type: " << std::hex << type << llendl;
llwarns << "ID: " << std::hex << id << llendl;
llwarns << "Severity: " << std::hex << severity << llendl;
llwarns << "Message: " << message << llendl;
llwarns << "-----------------------" << llendl;
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
{
llerrs << "Halting on GL Error" << llendl;
}
}
}
#endif
@ -258,6 +263,7 @@ PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
//GL_ARB_debug_output
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
@ -745,7 +751,7 @@ bool LLGLManager::initGL()
#if LL_WINDOWS
if (mHasDebugOutput && gDebugGL)
{ //setup debug output callback
//glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
@ -1248,6 +1254,7 @@ void LLGLManager::initExtensions()
glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
}
if (mHasDebugOutput)
{
@ -1502,7 +1509,7 @@ void do_assert_glerror()
void assert_glerror()
{
if (!gGLActive)
/* if (!gGLActive)
{
//llwarns << "GL used while not active!" << llendl;
@ -1511,8 +1518,13 @@ void assert_glerror()
//ll_fail("GL used while not active");
}
}
*/
if (gDebugGL)
if (!gDebugGL)
{
//funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often
}
else
{
do_assert_glerror();
}

View File

@ -543,6 +543,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
#elif LL_WINDOWS
@ -787,6 +788,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
//GL_ARB_debug_output
extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;

View File

@ -362,8 +362,8 @@ void LLGLSLShader::unload()
stop_glerror();
}
BOOL LLGLSLShader::createShader(vector<string> * attributes,
vector<string> * uniforms,
BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
std::vector<LLStaticHashedString> * uniforms,
U32 varying_count,
const char** varyings)
{
@ -445,7 +445,8 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
for (S32 i = 0; i < channel_count; i++)
{
uniform1i(llformat("tex%d", i), i);
LLStaticHashedString uniName(llformat("tex%d", i));
uniform1i(uniName, i);
}
S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
@ -502,7 +503,7 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
}
}
BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)
{
//before linking, make sure reserved attributes always have consistent locations
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
@ -539,7 +540,7 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
{
for (U32 i = 0; i < numAttributes; i++)
{
const char* name = (*attributes)[i].c_str();
const char* name = (*attributes)[i].String().c_str();
S32 index = glGetAttribLocationARB(mProgramObject, name);
if (index != -1)
{
@ -555,7 +556,7 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
return FALSE;
}
void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)
{
if (index == -1)
{
@ -625,8 +626,10 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
is_array[0] = 0;
}
mUniformMap[name] = location;
LLStaticHashedString hashedName(name);
mUniformNameMap[location] = name;
mUniformMap[hashedName] = location;
LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
//find the index of this uniform
@ -647,7 +650,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
for (U32 i = 0; i < uniforms->size(); i++)
{
if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
&& ((*uniforms)[i] == name))
&& ((*uniforms)[i].String() == name))
{
//found it
mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
@ -681,7 +684,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
return -1;
}
BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
{
BOOL res = TRUE;
@ -1143,18 +1146,18 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
}
}
GLint LLGLSLShader::getUniformLocation(const string& uniform)
GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
{
GLint ret = -1;
if (mProgramObject > 0)
{
std::map<string, GLint>::iterator iter = mUniformMap.find(uniform);
LLStaticStringTable<GLint>::iterator iter = mUniformMap.find(uniform);
if (iter != mUniformMap.end())
{
if (gDebugGL)
{
stop_glerror();
if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str()))
if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))
{
llerrs << "Uniform does not match." << llendl;
}
@ -1191,10 +1194,10 @@ GLint LLGLSLShader::getAttribLocation(U32 attrib)
}
}
void LLGLSLShader::uniform1i(const string& uniform, GLint v)
void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1207,7 +1210,7 @@ void LLGLSLShader::uniform1i(const string& uniform, GLint v)
}
}
void LLGLSLShader::uniform2i(const string& uniform, GLint i, GLint j)
void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
{
GLint location = getUniformLocation(uniform);
@ -1224,10 +1227,10 @@ void LLGLSLShader::uniform2i(const string& uniform, GLint i, GLint j)
}
void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1240,10 +1243,10 @@ void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
}
}
void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1257,10 +1260,10 @@ void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
}
void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z)
void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1273,23 +1276,7 @@ void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloa
}
}
void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
LLVector4 vec(x,y,z,w);
if (iter == mValue.end() || shouldChange(iter->second,vec))
{
glUniform4fARB(location, x,y,z,w);
mValue[location] = vec;
}
}
}
void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v)
void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@ -1305,10 +1292,10 @@ void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v
}
}
void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v)
void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1321,10 +1308,10 @@ void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v
}
}
void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v)
void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
@ -1337,7 +1324,7 @@ void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v
}
}
void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v)
void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
@ -1355,27 +1342,7 @@ void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v
}
}
void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
glUniformMatrix2fvARB(location, count, transpose, v);
}
}
void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);
if (location >= 0)
{
glUniformMatrix3fvARB(location, count, transpose, v);
}
}
void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
{
GLint location = getUniformLocation(uniform);

View File

@ -29,6 +29,7 @@
#include "llgl.h"
#include "llrender.h"
#include "llstaticstringtable.h"
class LLShaderFeatures
{
@ -90,16 +91,16 @@ public:
void placeProfileQuery();
void readProfileQuery(U32 count, U32 mode);
BOOL createShader(std::vector<std::string> * attributes,
std::vector<std::string> * uniforms,
BOOL createShader(std::vector<LLStaticHashedString> * attributes,
std::vector<LLStaticHashedString> * uniforms,
U32 varying_count = 0,
const char** varyings = NULL);
BOOL attachObject(std::string object);
void attachObject(GLhandleARB object);
void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
BOOL mapAttributes(const std::vector<std::string> * attributes);
BOOL mapUniforms(const std::vector<std::string> * uniforms);
void mapUniform(GLint index, const std::vector<std::string> * uniforms);
BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes);
BOOL mapUniforms(const std::vector<LLStaticHashedString> *);
void mapUniform(GLint index, const std::vector<LLStaticHashedString> *);
void uniform1i(U32 index, GLint i);
void uniform1f(U32 index, GLfloat v);
void uniform2f(U32 index, GLfloat x, GLfloat y);
@ -110,30 +111,27 @@ public:
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
void uniform4fv(U32 index, U32 count, const GLfloat* v);
void uniform1i(const std::string& uniform, GLint i);
void uniform2i(const std::string& uniform, GLint i, GLint j);
void uniform1f(const std::string& uniform, GLfloat v);
void uniform2f(const std::string& uniform, GLfloat x, GLfloat y);
void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1iv(const std::string& uniform, U32 count, const GLint* i);
void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v);
void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v);
void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v);
void uniform4fv(const std::string& uniform, U32 count, const GLfloat* v);
void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix2fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void uniform1i(const LLStaticHashedString& uniform, GLint i);
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void setMinimumAlpha(F32 minimum);
void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(U32 index, GLfloat* v);
GLint getUniformLocation(const std::string& uniform);
//GLint getUniformLocation(const std::string& uniform);
GLint getUniformLocation(const LLStaticHashedString& uniform);
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
@ -170,7 +168,7 @@ public:
std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
std::map<std::string, GLint> mUniformMap; //lookup map of uniform name to uniform location
LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name
std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value
std::vector<GLint> mTexture;

View File

@ -718,9 +718,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
mMipLevels = wpo2(llmax(w, h));
//use legacy mipmap generation mode
//use legacy mipmap generation mode (note: making this condional can cause rendering issues)
glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
w, h,
mFormatPrimary, mFormatType,
@ -1092,6 +1092,16 @@ void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 n
LLFastTimer t(FTM_GENERATE_TEXTURES);
// <FS:ND> user-defined names was deprecated with OpenGL 3.1. Just generate/delete using OpenGL function.
if (LLRender::sGLCoreProfile)
{
switch (format)
{
case GL_LUMINANCE8: format = GL_RGB8; break;
case GL_LUMINANCE8_ALPHA8:
case GL_ALPHA8: format = GL_RGBA8; break;
}
}
// bool empty = true;
//
// dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format);

View File

@ -31,6 +31,21 @@
#include "llsdserialize.h"
#include "llrender.h"
static LLStaticHashedString sRenderTexture("RenderTexture");
static LLStaticHashedString sBrightness("brightness");
static LLStaticHashedString sContrast("contrast");
static LLStaticHashedString sContrastBase("contrastBase");
static LLStaticHashedString sSaturation("saturation");
static LLStaticHashedString sLumWeights("lumWeights");
static LLStaticHashedString sNoiseTexture("NoiseTexture");
static LLStaticHashedString sBrightMult("brightMult");
static LLStaticHashedString sNoiseStrength("noiseStrength");
static LLStaticHashedString sExtractLow("extractLow");
static LLStaticHashedString sExtractHigh("extractHigh");
static LLStaticHashedString sBloomStrength("bloomStrength");
static LLStaticHashedString sTexelSize("texelSize");
static LLStaticHashedString sBlurDirection("blurDirection");
static LLStaticHashedString sBlurWidth("blurWidth");
LLPostProcess * gPostProcess = NULL;
@ -258,12 +273,12 @@ void LLPostProcess::applyColorFilterShader(void)
void LLPostProcess::createColorFilterShader(void)
{
/// Define uniform names
colorFilterUniforms["RenderTexture"] = 0;
colorFilterUniforms["brightness"] = 0;
colorFilterUniforms["contrast"] = 0;
colorFilterUniforms["contrastBase"] = 0;
colorFilterUniforms["saturation"] = 0;
colorFilterUniforms["lumWeights"] = 0;
colorFilterUniforms[sRenderTexture] = 0;
colorFilterUniforms[sBrightness] = 0;
colorFilterUniforms[sContrast] = 0;
colorFilterUniforms[sContrastBase] = 0;
colorFilterUniforms[sSaturation] = 0;
colorFilterUniforms[sLumWeights] = 0;
}
void LLPostProcess::applyNightVisionShader(void)
@ -307,11 +322,11 @@ void LLPostProcess::applyNightVisionShader(void)
void LLPostProcess::createNightVisionShader(void)
{
/// Define uniform names
nightVisionUniforms["RenderTexture"] = 0;
nightVisionUniforms["NoiseTexture"] = 0;
nightVisionUniforms["brightMult"] = 0;
nightVisionUniforms["noiseStrength"] = 0;
nightVisionUniforms["lumWeights"] = 0;
nightVisionUniforms[sRenderTexture] = 0;
nightVisionUniforms[sNoiseTexture] = 0;
nightVisionUniforms[sBrightMult] = 0;
nightVisionUniforms[sNoiseStrength] = 0;
nightVisionUniforms[sLumWeights] = 0;
createNoiseTexture(mNoiseTexture);
}
@ -326,25 +341,25 @@ void LLPostProcess::createBloomShader(void)
createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
/// Create Bloom Extract Shader
bloomExtractUniforms["RenderTexture"] = 0;
bloomExtractUniforms["extractLow"] = 0;
bloomExtractUniforms["extractHigh"] = 0;
bloomExtractUniforms["lumWeights"] = 0;
bloomExtractUniforms[sRenderTexture] = 0;
bloomExtractUniforms[sExtractLow] = 0;
bloomExtractUniforms[sExtractHigh] = 0;
bloomExtractUniforms[sLumWeights] = 0;
/// Create Bloom Blur Shader
bloomBlurUniforms["RenderTexture"] = 0;
bloomBlurUniforms["bloomStrength"] = 0;
bloomBlurUniforms["texelSize"] = 0;
bloomBlurUniforms["blurDirection"] = 0;
bloomBlurUniforms["blurWidth"] = 0;
bloomBlurUniforms[sRenderTexture] = 0;
bloomBlurUniforms[sBloomStrength] = 0;
bloomBlurUniforms[sTexelSize] = 0;
bloomBlurUniforms[sBlurDirection] = 0;
bloomBlurUniforms[sBlurWidth] = 0;
}
void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
{
/// Find uniform locations and insert into map
std::map<const char *, GLuint>::iterator i;
glslUniforms::iterator i;
for (i = uniforms.begin(); i != uniforms.end(); ++i){
i->second = glGetUniformLocationARB(prog, i->first);
i->second = glGetUniformLocationARB(prog, i->first.String().c_str());
}
}

View File

@ -31,6 +31,7 @@
#include <fstream>
#include "llgl.h"
#include "llglheaders.h"
#include "llstaticstringtable.h"
class LLPostProcess
{
@ -44,7 +45,7 @@ public:
} QuadType;
/// GLSL Shader Encapsulation Struct
typedef std::map<const char *, GLuint> glslUniforms;
typedef LLStaticStringTable<GLuint> glslUniforms;
struct PostProcessTweaks : public LLSD {
inline PostProcessTweaks() : LLSD(LLSD::emptyMap())

View File

@ -225,26 +225,15 @@ void LLTexUnit::disable(void)
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
{
stop_glerror();
if (mIndex < 0) return false;
if (mIndex >= 0)
{
gGL.flush();
LLImageGL* gl_tex = NULL ;
if (texture == NULL || !(gl_tex = texture->getGLTexture()))
if (texture != NULL && (gl_tex = texture->getGLTexture()))
{
//llwarns << "NULL LLTexUnit::bind texture" << llendl; //FS:LO Removing possable spammy debug line.
return false;
}
if (!gl_tex->getTexName()) //if texture does not exist
if (gl_tex->getTexName()) //if texture exists
{
//if deleted, will re-generate it immediately
texture->forceImmediateUpdate() ;
gl_tex->forceUpdateBindStats() ;
return texture->bindDefaultImage(mIndex);
}
//in audit, replace the selected texture by the default one.
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
{
@ -265,6 +254,27 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
setTextureFilteringOption(gl_tex->mFilterOption);
}
}
}
else
{
//if deleted, will re-generate it immediately
texture->forceImmediateUpdate() ;
gl_tex->forceUpdateBindStats() ;
return texture->bindDefaultImage(mIndex);
}
}
else
{
llwarns << "NULL LLTexUnit::bind texture" << llendl;
return false;
}
}
else
{ // mIndex < 0
return false;
}
return true;
}
@ -822,8 +832,8 @@ LLLightState::LLLightState(S32 index)
: mIndex(index),
mEnabled(false),
mConstantAtten(1.f),
mLinearAtten(0.f),
mQuadraticAtten(0.f),
mLinearAtten(1.f),
mQuadraticAtten(1.f),
mSpotExponent(0.f),
mSpotCutoff(180.f)
{
@ -1058,6 +1068,16 @@ LLRender::~LLRender()
void LLRender::init()
{
if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
{ //bind a dummy vertex array object so we're core profile compliant
#ifdef GL_ARB_vertex_array_object
U32 ret;
glGenVertexArrays(1, &ret);
glBindVertexArray(ret);
#endif
}
llassert_always(mBuffer.isNull()) ;
stop_glerror();
mBuffer = new LLVertexBuffer(immediate_mask, 0);
@ -1130,7 +1150,7 @@ void LLRender::syncLightState()
position[i] = light->mPosition;
direction[i] = light->mSpotDirection;
attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]);
attenuation[i].set(1.f/light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]);
diffuse[i].set(light->mDiffuse.mV);
}
@ -1870,35 +1890,36 @@ void LLRender::flush()
sUIVerts += mCount;
}
if (gDebugGL)
//store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
U32 count = mCount;
if (mMode == LLRender::QUADS && !sGLCoreProfile)
{
if (mMode == LLRender::QUADS && !sGLCoreProfile)
if (mCount%4 != 0)
{
if (mCount%4 != 0)
{
llerrs << "Incomplete quad rendered." << llendl;
}
}
if (mMode == LLRender::TRIANGLES)
{
if (mCount%3 != 0)
{
llerrs << "Incomplete triangle rendered." << llendl;
}
}
if (mMode == LLRender::LINES)
{
if (mCount%2 != 0)
{
llerrs << "Incomplete line rendered." << llendl;
}
count -= (mCount % 4);
llwarns << "Incomplete quad requested." << llendl;
}
}
//store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
U32 count = mCount;
if (mMode == LLRender::TRIANGLES)
{
if (mCount%3 != 0)
{
count -= (mCount % 3);
llwarns << "Incomplete triangle requested." << llendl;
}
}
if (mMode == LLRender::LINES)
{
if (mCount%2 != 0)
{
count -= (mCount % 2);
llwarns << "Incomplete line requested." << llendl;
}
}
mCount = 0;
if (mBuffer->useVBOs() && !mBuffer->isLocked())
@ -2326,6 +2347,22 @@ void LLRender::diffuseColor4ubv(const U8* c)
}
}
void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
{
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL);
if (shader)
{
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
}
else
{
glColor4ub(r,g,b,a);
}
}
void LLRender::debugTexUnits(void)
{
LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;

View File

@ -396,6 +396,7 @@ public:
void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
void diffuseColor4fv(const F32* c);
void diffuseColor4ubv(const U8* c);
void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);

View File

@ -473,6 +473,12 @@ U32 LLRenderTarget::getTexture(U32 attachment) const
return mTex[attachment];
}
U32 LLRenderTarget::getNumTextures() const
{
return mTex.size();
}
void LLRenderTarget::bindTexture(U32 index, S32 channel)
{
gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));

View File

@ -115,6 +115,7 @@ public:
LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
U32 getTexture(U32 attachment = 0) const;
U32 getNumTextures() const;
U32 getDepth(void) const { return mDepth; }
bool hasStencil() const { return mStencil; }

View File

@ -1033,7 +1033,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_matrix1");
mReservedUniforms.push_back("texture_matrix2");
mReservedUniforms.push_back("texture_matrix3");
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_MATRIX3+1);
mReservedUniforms.push_back("object_plane_s");
mReservedUniforms.push_back("object_plane_t");
llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);
mReservedUniforms.push_back("viewport");
@ -1187,6 +1189,45 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("exo_screen");
// </FS:CR> Import Vignette from Exodus
mReservedUniforms.push_back("matrixPalette");
mReservedUniforms.push_back("screenTex");
mReservedUniforms.push_back("screenDepth");
mReservedUniforms.push_back("refTex");
mReservedUniforms.push_back("eyeVec");
mReservedUniforms.push_back("time");
mReservedUniforms.push_back("d1");
mReservedUniforms.push_back("d2");
mReservedUniforms.push_back("lightDir");
mReservedUniforms.push_back("specular");
mReservedUniforms.push_back("lightExp");
mReservedUniforms.push_back("waterFogColor");
mReservedUniforms.push_back("waterFogDensity");
mReservedUniforms.push_back("waterFogKS");
mReservedUniforms.push_back("refScale");
mReservedUniforms.push_back("waterHeight");
mReservedUniforms.push_back("waterPlane");
mReservedUniforms.push_back("normScale");
mReservedUniforms.push_back("fresnelScale");
mReservedUniforms.push_back("fresnelOffset");
mReservedUniforms.push_back("blurMultiplier");
mReservedUniforms.push_back("sunAngle");
mReservedUniforms.push_back("scaledAngle");
mReservedUniforms.push_back("sunAngle2");
mReservedUniforms.push_back("camPosLocal");
mReservedUniforms.push_back("gWindDir");
mReservedUniforms.push_back("gSinWaveParams");
mReservedUniforms.push_back("gGravity");
mReservedUniforms.push_back("detail_0");
mReservedUniforms.push_back("detail_1");
mReservedUniforms.push_back("detail_2");
mReservedUniforms.push_back("detail_3");
mReservedUniforms.push_back("alpha_ramp");
mReservedUniforms.push_back("origin");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);

View File

@ -47,6 +47,8 @@ public:
TEXTURE_MATRIX1,
TEXTURE_MATRIX2,
TEXTURE_MATRIX3,
OBJECT_PLANE_S,
OBJECT_PLANE_T,
VIEWPORT,
LIGHT_POSITION,
LIGHT_DIRECTION,
@ -176,7 +178,48 @@ public:
EXO_RENDER_SCREEN,
// </FS:CR> Import Vignette from Exodus
AVATAR_MATRIX,
WATER_SCREENTEX,
WATER_SCREENDEPTH,
WATER_REFTEX,
WATER_EYEVEC,
WATER_TIME,
WATER_WAVE_DIR1,
WATER_WAVE_DIR2,
WATER_LIGHT_DIR,
WATER_SPECULAR,
WATER_SPECULAR_EXP,
WATER_FOGCOLOR,
WATER_FOGDENSITY,
WATER_FOGKS,
WATER_REFSCALE,
WATER_WATERHEIGHT,
WATER_WATERPLANE,
WATER_NORM_SCALE,
WATER_FRESNEL_SCALE,
WATER_FRESNEL_OFFSET,
WATER_BLUR_MULTIPLIER,
WATER_SUN_ANGLE,
WATER_SCALED_ANGLE,
WATER_SUN_ANGLE2,
WL_CAMPOSLOCAL,
AVATAR_WIND,
AVATAR_SINWAVE,
AVATAR_GRAVITY,
TERRAIN_DETAIL0,
TERRAIN_DETAIL1,
TERRAIN_DETAIL2,
TERRAIN_DETAIL3,
TERRAIN_ALPHARAMP,
SHINY_ORIGIN,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
// singleton pattern implementation

View File

@ -85,6 +85,7 @@ const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
//static
LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_ARB, GL_ARRAY_BUFFER_ARB);
LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
@ -273,7 +274,10 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
{
glBufferDataARB(mType, size, 0, mUsage);
ret = (U8*) ll_aligned_malloc_16(size);
if (mUsage != GL_DYNAMIC_COPY_ARB)
{ //data will be provided by application
ret = (U8*) ll_aligned_malloc(size, 64);
}
}
else
{
@ -293,9 +297,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
llassert(vbo_block_size(size) == size);
deleteBuffer(name);
if ( LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
ll_aligned_free_16((U8*) buffer);
ll_aligned_free((U8*) buffer);
if (mType == GL_ARRAY_BUFFER_ARB)
{
@ -355,7 +357,7 @@ void LLVBOPool::cleanup()
//
// if (r.mClientData)
// {
// ll_aligned_free_16((void*) r.mClientData);
// ll_aligned_free((void*) r.mClientData);
// }
//
// l.pop_front();
@ -461,6 +463,7 @@ void LLVertexBuffer::seedPools()
{
sStreamVBOPool.seedPool();
sDynamicVBOPool.seedPool();
sDynamicCopyVBOPool.seedPool();
sStreamIBOPool.seedPool();
sDynamicIBOPool.seedPool();
}
@ -962,6 +965,7 @@ void LLVertexBuffer::cleanupClass()
sDynamicIBOPool.cleanup();
sStreamVBOPool.cleanup();
sDynamicVBOPool.cleanup();
sDynamicCopyVBOPool.cleanup();
if(sPrivatePoolp)
{
@ -998,13 +1002,16 @@ S32 LLVertexBuffer::determineUsage(S32 usage)
if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
if (sDisableVBOMapping)
{ //always use stream draw if VBO mapping is disabled
ret_usage = GL_STREAM_DRAW_ARB;
}
else
if (ret_usage != GL_DYNAMIC_COPY_ARB)
{
ret_usage = GL_DYNAMIC_DRAW_ARB;
if (sDisableVBOMapping)
{ //always use stream draw if VBO mapping is disabled
ret_usage = GL_STREAM_DRAW_ARB;
}
else
{
ret_usage = GL_DYNAMIC_DRAW_ARB;
}
}
}
@ -1154,10 +1161,15 @@ void LLVertexBuffer::genBuffer(U32 size)
{
mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
}
else
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
}
else
{
mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
}
sGLCount++;
}
@ -1386,7 +1398,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
//actually allocate space for the vertex buffer if using VBO mapping
flush();
if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))
if (gGLManager.mHasVertexArrayObject && useVBOs() && (sUseVAO))
{
#if GL_ARB_vertex_array_object
mGLArray = getVAOName();
@ -1543,21 +1555,18 @@ bool LLVertexBuffer::useVBOs() const
//----------------------------------------------------------------------------
bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
bool expand_region(LLVertexBuffer::MappedRegion& region, S32 start, S32 end)
{
S32 end = index+count;
S32 region_end = region.mIndex+region.mCount;
if (end < region.mIndex ||
index > region_end)
start > region.mEnd)
{ //gap exists, do not merge
return false;
}
S32 new_end = llmax(end, region_end);
S32 new_index = llmin(index, region.mIndex);
region.mIndex = new_index;
region.mCount = new_end-new_index;
region.mEnd = llmax(end, region.mEnd);
region.mIndex = llmin(start, region.mIndex);
region.mCount = region.mEnd-region.mIndex;
return true;
}
@ -1567,7 +1576,6 @@ static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map");
// Map for data access
volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
{
bindGLBuffer(true);
if (mFinal)
{
llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl;
@ -1588,23 +1596,23 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
S32 start_index = mOffsets[type]+index*sTypeSize[type];
S32 end_index = start_index+count*sTypeSize[type];
for (std::vector<MappedRegion>::iterator iter = mMappedVertexRegions.begin(), end = mMappedVertexRegions.end(); iter != end; ++iter)
{
MappedRegion& region = mMappedVertexRegions[i];
if (region.mType == type)
MappedRegion& region = *iter;
if (expand_region(region, index, end_index))
{
if (expand_region(region, index, count))
{
mapped = true;
break;
}
mapped = true;
break;
}
}
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(type, mMappable && map_range ? -1 : index, count);
MappedRegion region(mMappable && map_range ? -1 : start_index, end_index-start_index);
mMappedVertexRegions.push_back(region);
}
}
@ -1628,6 +1636,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
{
volatile U8* src = NULL;
waitFence();
bindGLBuffer();
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
@ -1750,7 +1759,6 @@ static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map");
volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
{
bindGLIndices(true);
if (mFinal)
{
llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl;
@ -1769,12 +1777,14 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
count = mNumIndices-index;
}
S32 end = index+count;
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
MappedRegion& region = mMappedIndexRegions[i];
if (expand_region(region, index, count))
if (expand_region(region, index, end))
{
mapped = true;
break;
@ -1784,7 +1794,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);
MappedRegion region(mMappable && map_range ? -1 : index, count);
mMappedIndexRegions.push_back(region);
}
}
@ -1800,23 +1810,23 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
sMappedCount++;
stop_glerror();
if (gDebugGL && useVBOs())
{
GLint elem = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
if (elem != mGLIndices)
{
llerrs << "Wrong index buffer bound!" << llendl;
}
}
if(!mMappable)
{
map_range = false;
}
else
{
bindGLIndices();
if (gDebugGL && useVBOs())
{
GLint elem = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
if (elem != mGLIndices)
{
llerrs << "Wrong index buffer bound!" << llendl;
}
}
volatile U8* src = NULL;
waitFence();
if (gGLManager.mHasMapBufferRange)
@ -1932,9 +1942,11 @@ void LLVertexBuffer::unmapBuffer()
if (mMappedData && mVertexLocked)
{
llassert(mUsage != GL_DYNAMIC_COPY_ARB);
// <FS:ND/> Fast timers can have measurable impact in frequent places. A better all around solution would be to disable all fast timers until the fast timer view is open. But we're not there yet.
// LLFastTimer t(FTM_VBO_UNMAP);
bindGLBuffer(true);
bindGLBuffer();
updated_all = mIndexLocked; //both vertex and index buffers done updating
if(!mMappable)
@ -1945,8 +1957,8 @@ void LLVertexBuffer::unmapBuffer()
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
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;
S32 offset = region.mIndex;
S32 length = region.mCount;
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset);
stop_glerror();
}
@ -1970,8 +1982,8 @@ void LLVertexBuffer::unmapBuffer()
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
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;
S32 offset = region.mIndex;
S32 length = region.mCount;
if (gGLManager.mHasMapBufferRange)
{
// <FS:ND/> Fast timers can have measurable impact in frequent places. A better all around solution would be to disable all fast timers until the fast timer view is open. But we're not there yet.
@ -2208,8 +2220,6 @@ bool LLVertexBuffer::bindGLArray()
if (mGLArray && sGLRenderArray != mGLArray)
{
{
// <FS:ND/> Fast timers can have measurable impact in frequent places. A better all around solution would be to disable all fast timers until the fast timer view is open. But we're not there yet.
// LLFastTimer t(FTM_BIND_GL_ARRAY);
#if GL_ARB_vertex_array_object
glBindVertexArray(mGLArray);
#endif
@ -2236,23 +2246,15 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
{
// <FS:ND/> Fast timers can have measurable impact in frequent places. A better all around solution would be to disable all fast timers until the fast timer view is open. But we're not there yet.
// LLFastTimer t(FTM_BIND_GL_BUFFER);
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
}*/
//LLFastTimer t(FTM_BIND_GL_BUFFER); <-- this timer is showing up as a hotspot (irony)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
sBindCount++;
sVBOActive = true;
if (mGLArray)
{
llassert(sGLRenderArray == mGLArray);
//mCachedRenderBuffer = mGLBuffer;
}
llassert(!mGLArray || sGLRenderArray == mGLArray);
ret = true;
}
@ -2503,7 +2505,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
if (data_mask & MAP_COLOR)
{
S32 loc = TYPE_COLOR;
void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
//bind emissive instead of color pointer if emissive is present
void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
}
if (data_mask & MAP_EMISSIVE)
@ -2511,6 +2514,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
S32 loc = TYPE_EMISSIVE;
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
if (!(data_mask & MAP_COLOR))
{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
loc = TYPE_COLOR;
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
}
}
if (data_mask & MAP_WEIGHT)
{
@ -2593,11 +2602,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
llglassertok();
}
LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
: mType(type), mIndex(index), mCount(count)
LLVertexBuffer::MappedRegion::MappedRegion(S32 index, S32 count)
: mIndex(index), mCount(count)
{
llassert(mType == LLVertexBuffer::TYPE_INDEX ||
mType < LLVertexBuffer::TYPE_TEXTURE_INDEX);
mEnd = mIndex+mCount;
}

View File

@ -109,11 +109,11 @@ public:
class MappedRegion
{
public:
S32 mType;
S32 mIndex;
S32 mCount;
S32 mEnd;
MappedRegion(S32 type, S32 index, S32 count);
MappedRegion(S32 index, S32 count);
};
LLVertexBuffer(const LLVertexBuffer& rhs)
@ -130,9 +130,10 @@ public:
static LLVBOPool sStreamVBOPool;
static LLVBOPool sDynamicVBOPool;
static LLVBOPool sDynamicCopyVBOPool;
static LLVBOPool sStreamIBOPool;
static LLVBOPool sDynamicIBOPool;
static std::list<U32> sAvailableVAOName;
static U32 sCurVAOName;

View File

@ -381,7 +381,6 @@ void LLConsole::clear()
void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)
{
LLSD paragraph_color_segments;
paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);
LLSD color_sd = color.getValue();
paragraph_color_segments[0]["color"]=color_sd;

View File

@ -37,6 +37,7 @@ class LLSD;
class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker<LLConsole>
{
public:
typedef enum e_font_size
{
MONOSPACE = -1,

View File

@ -112,6 +112,8 @@ struct LLCoordFloater : LLCoord<LL_COORD_FLOATER>
bool operator!=(const LLCoordFloater& other) const { return !(*this == other); }
void setFloater(LLFloater& floater);
};
class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
@ -121,6 +123,7 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
friend class LLMultiFloater;
public:
struct KeyCompare
{
// static bool compare(const LLSD& a, const LLSD& b);

View File

@ -521,7 +521,6 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
const llwchar* base = wtext.c_str();
const llwchar* cur = base;
while( *cur )
{
if( *cur == '\n' || cur == base )

View File

@ -38,6 +38,7 @@ class LLLayoutPanel;
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
typedef enum e_layout_orientation
{
HORIZONTAL,

View File

@ -40,7 +40,7 @@ class LLModalDialog : public LLFloater
{
public:
LLModalDialog( const LLSD& key, BOOL modal = true );
/*virtual*/ ~LLModalDialog();
virtual ~LLModalDialog();
/*virtual*/ BOOL postBuild();

View File

@ -1133,7 +1133,7 @@ LLNotificationChannel::LLNotificationChannel(const Params& p)
mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString())
{
BOOST_FOREACH(const std::string& source, p.sources)
{
{
connectToChannel(source);
}
}
@ -1217,6 +1217,10 @@ LLNotifications::LLNotifications()
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
}
void LLNotifications::clear()
{
mDefaultChannels.clear();
}
// The expiration channel gets all notifications that are cancelled
bool LLNotifications::expirationFilter(LLNotificationPtr pNotification)

View File

@ -138,6 +138,7 @@ typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegi
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
{
public:
LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
{
}
@ -878,6 +879,13 @@ class LLNotifications :
friend class LLSingleton<LLNotifications>;
public:
// Needed to clear up RefCounted things prior to actual destruction
// as the singleton nature of the class makes them do "bad things"
// on at least Mac, if not all 3 platforms
//
void clear();
// load all notification descriptions from file
// calling more than once will overwrite existing templates
// but never delete a template

View File

@ -2521,7 +2521,6 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
{
// Figure out which line we're nearest to.
LLRect doc_rect = mDocumentView->getRect();
S32 doc_y = local_y - doc_rect.mBottom;
// binary search for line that starts before local_y

View File

@ -42,6 +42,7 @@ class LLWindowCallbacks;
class LLWindow : public LLInstanceTracker<LLWindow>
{
public:
struct LLWindowResolution
{
S32 mWidth;

View File

@ -79,8 +79,8 @@ void parse_string();
#define yyfree indra_free
int yylex( void );
int yyparse( void );
int yylex( void );
int yyerror(const char *fmt, ...);
%}
@ -161,6 +161,7 @@ int yyerror(const char *fmt, ...);
"STATUS_DIE_AT_EDGE" { count(); yylval.ival = 0x80; return(INTEGER_CONSTANT); }
"STATUS_RETURN_AT_EDGE" { count(); yylval.ival = 0x100; return(INTEGER_CONSTANT); }
"STATUS_CAST_SHADOWS" { count(); yylval.ival = 0x200; return(INTEGER_CONSTANT); }
"STATUS_BLOCK_GRAB_OBJECT" { count(); yylval.ival = 0x400; return(INTEGER_CONSTANT); }
"AGENT_FLYING" { count(); yylval.ival = AGENT_FLYING; return(INTEGER_CONSTANT); }
"AGENT_ATTACHMENTS" { count(); yylval.ival = AGENT_ATTACHMENTS; return(INTEGER_CONSTANT); }
@ -235,6 +236,8 @@ int yyerror(const char *fmt, ...);
"PERMISSION_TRACK_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA]; return(INTEGER_CONSTANT); }
"PERMISSION_CONTROL_CAMERA" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); }
"PERMISSION_TELEPORT" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TELEPORT]; return(INTEGER_CONSTANT); }
"PERMISSION_SILENT_ESTATE_MANAGEMENT" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT]; return(INTEGER_CONSTANT); }
"PERMISSION_OVERRIDE_ANIMATIONS" { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS]; return(INTEGER_CONSTANT); }
"INVENTORY_TEXTURE" { count(); yylval.ival = LLAssetType::AT_TEXTURE; return(INTEGER_CONSTANT); }
"INVENTORY_SOUND" { count(); yylval.ival = LLAssetType::AT_SOUND; return(INTEGER_CONSTANT); }
@ -271,6 +274,22 @@ int yyerror(const char *fmt, ...);
"OBJECT_OWNER" { count(); yylval.ival = OBJECT_OWNER; return(INTEGER_CONSTANT); }
"OBJECT_GROUP" { count(); yylval.ival = OBJECT_GROUP; return(INTEGER_CONSTANT); }
"OBJECT_CREATOR" { count(); yylval.ival = OBJECT_CREATOR; return(INTEGER_CONSTANT); }
"OBJECT_RUNNING_SCRIPT_COUNT" { count(); yylval.ival = OBJECT_RUNNING_SCRIPT_COUNT; return(INTEGER_CONSTANT); }
"OBJECT_TOTAL_SCRIPT_COUNT" { count(); yylval.ival = OBJECT_TOTAL_SCRIPT_COUNT; return(INTEGER_CONSTANT); }
"OBJECT_SCRIPT_MEMORY" { count(); yylval.ival = OBJECT_SCRIPT_MEMORY; return(INTEGER_CONSTANT); }
"OBJECT_SCRIPT_TIME" { count(); yylval.ival = OBJECT_SCRIPT_TIME; return(INTEGER_CONSTANT); }
"OBJECT_PRIM_EQUIVALENCE" { count(); yylval.ival = OBJECT_PRIM_EQUIVALENCE; return(INTEGER_CONSTANT); }
"OBJECT_SERVER_COST" { count(); yylval.ival = OBJECT_SERVER_COST; return(INTEGER_CONSTANT); }
"OBJECT_STREAMING_COST" { count(); yylval.ival = OBJECT_STREAMING_COST; return(INTEGER_CONSTANT); }
"OBJECT_PHYSICS_COST" { count(); yylval.ival = OBJECT_PHYSICS_COST; return(INTEGER_CONSTANT); }
"OBJECT_CHARACTER_TIME" { count(); yylval.ival = OBJECT_CHARACTER_TIME; return(INTEGER_CONSTANT); }
"OBJECT_ROOT" { count(); yylval.ival = OBJECT_ROOT; return(INTEGER_CONSTANT); }
"OBJECT_ATTACHED_POINT" { count(); yylval.ival = OBJECT_ATTACHED_POINT; return(INTEGER_CONSTANT); }
"OBJECT_PATHFINDING_TYPE" { count(); yylval.ival = OBJECT_PATHFINDING_TYPE; return(INTEGER_CONSTANT); }
"OBJECT_PHYSICS" { count(); yylval.ival = OBJECT_PHYSICS; return(INTEGER_CONSTANT); }
"OBJECT_PHANTOM" { count(); yylval.ival = OBJECT_PHANTOM; return(INTEGER_CONSTANT); }
"OBJECT_TEMP_ON_REZ" { count(); yylval.ival = OBJECT_TEMP_ON_REZ; return(INTEGER_CONSTANT); }
"OBJECT_RENDER_WEIGHT" { count(); yylval.ival = OBJECT_RENDER_WEIGHT; return(INTEGER_CONSTANT); }
"TYPE_INTEGER" { count(); yylval.ival = LST_INTEGER; return(INTEGER_CONSTANT); }
"TYPE_FLOAT" { count(); yylval.ival = LST_FLOATINGPOINT; return(INTEGER_CONSTANT); }
@ -377,6 +396,10 @@ int yyerror(const char *fmt, ...);
"PSYS_PART_END_SCALE" { count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }
"PSYS_PART_MAX_AGE" { count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); }
"PSYS_PART_BLEND_FUNC_SOURCE" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); }
"PSYS_PART_BLEND_FUNC_DEST" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); }
"PSYS_PART_START_GLOW" { count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); }
"PSYS_PART_END_GLOW" { count(); yylval.ival = LLPS_PART_END_GLOW; return (INTEGER_CONSTANT); }
"PSYS_PART_WIND_MASK" { count(); yylval.ival = LLPartData::LL_PART_WIND_MASK; return(INTEGER_CONSTANT); }
"PSYS_PART_INTERP_COLOR_MASK" { count(); yylval.ival = LLPartData::LL_PART_INTERP_COLOR_MASK; return(INTEGER_CONSTANT); }
@ -387,6 +410,16 @@ int yyerror(const char *fmt, ...);
"PSYS_PART_TARGET_POS_MASK" { count(); yylval.ival = LLPartData::LL_PART_TARGET_POS_MASK; return(INTEGER_CONSTANT); }
"PSYS_PART_EMISSIVE_MASK" { count(); yylval.ival = LLPartData::LL_PART_EMISSIVE_MASK; return(INTEGER_CONSTANT); }
"PSYS_PART_TARGET_LINEAR_MASK" { count(); yylval.ival = LLPartData::LL_PART_TARGET_LINEAR_MASK; return(INTEGER_CONSTANT); }
"PSYS_PART_RIBBON_MASK" { count(); yylval.ival = LLPartData::LL_PART_RIBBON_MASK; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ONE" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ZERO" { count(); yylval.ival = LLPartData::LL_PART_BF_ZERO; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_DEST_COLOR" { count(); yylval.ival = LLPartData::LL_PART_BF_DEST_COLOR; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_SOURCE_COLOR" { count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_COLOR; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ONE_MINUS_DEST_COLOR" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
"PSYS_SRC_MAX_AGE" { count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); }
@ -482,7 +515,17 @@ int yyerror(const char *fmt, ...);
"PRIM_BUMP_SHINY" { count(); yylval.ival = LSL_PRIM_BUMP_SHINY; return(INTEGER_CONSTANT); }
"PRIM_FULLBRIGHT" { count(); yylval.ival = LSL_PRIM_FULLBRIGHT; return(INTEGER_CONSTANT); }
"PRIM_TEXGEN" { count(); yylval.ival = LSL_PRIM_TEXGEN; return(INTEGER_CONSTANT); }
"PRIM_GLOW" { count(); yylval.ival = LSL_PRIM_GLOW; return(INTEGER_CONSTANT); }
"PRIM_GLOW" { count(); yylval.ival = LSL_PRIM_GLOW; return(INTEGER_CONSTANT); }
"PRIM_TEXT" { count(); yylval.ival = LSL_PRIM_TEXT; return(INTEGER_CONSTANT); }
"PRIM_NAME" { count(); yylval.ival = LSL_PRIM_NAME; return(INTEGER_CONSTANT); }
"PRIM_DESC" { count(); yylval.ival = LSL_PRIM_DESC; return(INTEGER_CONSTANT); }
"PRIM_OMEGA" { count(); yylval.ival = LSL_PRIM_OMEGA; return(INTEGER_CONSTANT); }
"PRIM_LINK_TARGET" { count(); yylval.ival = LSL_PRIM_LINK_TARGET; return(INTEGER_CONSTANT); }
"PRIM_SLICE" { count(); yylval.ival = LSL_PRIM_SLICE; return(INTEGER_CONSTANT); }
"PRIM_PHYSICS_SHAPE_PRIM" { count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_PRIM; return(INTEGER_CONSTANT); }
"PRIM_PHYSICS_SHAPE_NONE" { count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_NONE; return(INTEGER_CONSTANT); }
"PRIM_PHYSICS_SHAPE_CONVEX" { count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_CONVEX; return(INTEGER_CONSTANT); }
"PRIM_TYPE_BOX" { count(); yylval.ival = LSL_PRIM_TYPE_BOX; return(INTEGER_CONSTANT); }
"PRIM_TYPE_CYLINDER" { count(); yylval.ival = LSL_PRIM_TYPE_CYLINDER; return(INTEGER_CONSTANT); }

View File

@ -145,7 +145,6 @@ void LLScriptLSOParse::printGlobals(LLFILE *fp)
// get offset to skip past name
varoffset = global_v_offset;
bytestream2integer(mRawData, global_v_offset);
// get typeexport
type = *(mRawData + global_v_offset++);
@ -347,6 +346,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp)
S32 temp_end;
opcode_end = worst_case_opcode_end;
(void)opcode_end;
for (k = LSTT_STATE_BEGIN; k < LSTT_STATE_END; k++)
{

View File

@ -211,6 +211,7 @@ set(viewer_SOURCE_FILES
llavatariconctrl.cpp
llavatarlist.cpp
llavatarlistitem.cpp
llavatarrenderinfoaccountant.cpp
llavatarpropertiesprocessor.cpp
llblockedlistitem.cpp
llblocklist.cpp
@ -903,6 +904,7 @@ set(viewer_HEADER_FILES
llavatarlist.h
llavatarlistitem.h
llavatarpropertiesprocessor.h
llavatarrenderinfoaccountant.h
llblockedlistitem.h
llblocklist.h
llbox.h

View File

@ -65,10 +65,12 @@ STATUS_ROTATE_X Passed in the llSetStatus library function. If FALSE, object do
STATUS_ROTATE_Y Passed in the llSetStatus library function. If FALSE, object doesn't rotate around local Y axis
STATUS_ROTATE_Z Passed in the llSetStatus library function. If FALSE, object doesn't rotate around local Z axis
STATUS_SANDBOX Passed in the llSetStatus library function. If TRUE, object can't cross region boundaries or move more than 10 meters from its start location
STATUS_BLOCK_GRAB Passed in the llSetStatus library function. If TRUE, object can't be grabbed and physically dragged
STATUS_BLOCK_GRAB Passed in the llSetStatus library function. If TRUE, root prim of linkset (or unlinked prim) can't be grabbed and physically dragged
STATUS_DIE_AT_EDGE Passed in the llSetStatus library function. If TRUE, objects that reach the edge of the world just die:rather than teleporting back to the owner
STATUS_RETURN_AT_EDGE Passed in the llSetStatus library function. If TRUE, script rezzed objects that reach the edge of the world:are returned rather than killed:STATUS_RETURN_AT_EDGE trumps STATUS_DIE_AT_EDGE if both are set
STATUS_CAST_SHADOWS Passed in the llSetStatus library function. If TRUE, object casts shadows on other objects
STATUS_BLOCK_GRAB_OBJECT Passed in the llSetStatus library function. If TRUE, no prims in linkset can be grabbed or physically dragged
AGENT Passed in llSensor library function to look for other Agents
ACTIVE Passed in llSensor library function to look for moving objects
PASSIVE Passed in llSensor library function to look for objects that aren't moving
@ -95,7 +97,7 @@ PERMISSION_CHANGE_LINKS Passed to llRequestPermissions library function to req
PERMISSION_TRACK_CAMERA Passed to llRequestPermissions library function to request permission to track agent's camera
PERMISSION_CONTROL_CAMERA Passed to llRequestPermissions library function to request permission to change agent's camera
PERMISSION_TELEPORT Passed to llRequestPermissions library function to request permission to teleport agent
SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT Passed to llRequestPermissions library function to request permission to silently modify estate access lists
PERMISSION_SILENT_ESTATE_MANAGEMENT Passed to llRequestPermissions library function to request permission to silently modify estate access lists
PERMISSION_OVERRIDE_ANIMATIONS Passed to llRequestPermissions library function to request permission to override animations on agent
PERMISSION_RETURN_OBJECTS Passed to llRequestPermissions library function to request permission to return objects
@ -135,6 +137,7 @@ PSYS_PART_FOLLOW_VELOCITY_MASK
PSYS_PART_TARGET_POS_MASK
PSYS_PART_EMISSIVE_MASK
PSYS_PART_TARGET_LINEAR_MASK
PSYS_PART_RIBBON_MASK
PSYS_SRC_PATTERN
PSYS_SRC_INNERANGLE Deprecated -- Use PSYS_SRC_ANGLE_BEGIN
@ -151,12 +154,24 @@ PSYS_SRC_ACCEL
PSYS_SRC_TEXTURE
PSYS_SRC_TARGET_KEY
PSYS_SRC_OMEGA
PSYS_PART_BLEND_FUNC_SOURCE
PSYS_PART_BLEND_FUNC_DEST
PSYS_PART_START_GLOW
PSYS_PART_END_GLOW
PSYS_SRC_PATTERN_DROP
PSYS_SRC_PATTERN_EXPLODE
PSYS_SRC_PATTERN_ANGLE
PSYS_SRC_PATTERN_ANGLE_CONE
PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
PSYS_PART_BF_ONE
PSYS_PART_BF_ZERO
PSYS_PART_BF_DEST_COLOR
PSYS_PART_BF_SOURCE_COLOR
PSYS_PART_BF_ONE_MINUS_DEST_COLOR
PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR
PSYS_PART_BF_SOURCE_ALPHA
PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA
OBJECT_UNKNOWN_DETAIL Returned by llGetObjectDetails when passed an invalid object parameter type
OBJECT_NAME Used with llGetObjectDetails to get an object's name
@ -167,6 +182,23 @@ OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity
OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned
OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key
OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key
OBJECT_RUNNING_SCRIPT_COUNT Used with llGetObjectDetails to get the number of running scripts in an object
OBJECT_TOTAL_SCRIPT_COUNT Used with llGetObjectDetails to get the total number of scripts in an object
OBJECT_SCRIPT_MEMORY Used with llGetObjectDetails to get the total amount of script memory in an object
OBJECT_SCRIPT_TIME Used with llGetObjectDetails to get the average script time used by an object
OBJECT_PRIM_EQUIVALENCE Used with llGetObjectDetails to get the prim equivalence of an object
OBJECT_SERVER_COST Used with llGetObjectDetails to get the server cost of an object
OBJECT_STREAMING_COST Used with llGetObjectDetails to get the streaming (download) cost of an object
OBJECT_PHYSICS_COST Used with llGetObjectDetails to get the physics cost of an object
OBJECT_CHARACTER_TIME Used with llGetObjectDetails to get the pathfinding time (seconds) for an object
OBJECT_ROOT Used with llGetObjectDetails to get root ID of an object
OBJECT_ATTACHED_POINT Used with llGetObjectDetails to get attachent point where an object is attached
OBJECT_PATHFINDING_TYPE Used with llGetObjectDetails to get the pathfinding setting of an object
OBJECT_PHYSICS Used with llGetObjectDetails to determine if the object is physical or not
OBJECT_PHANTOM Used with llGetObjectDetails to determine if the object is phantom or not
OBJECT_TEMP_ON_REZ Used with llGetObjectDetails to determine if the object is temporary or not
OBJECT_RENDER_WEIGHT Used with llGetObjectDetails to return an avatar's rendering weight
# some vehicle params
VEHICLE_TYPE_NONE
@ -349,7 +381,7 @@ PRIM_MATERIAL Followed by PRIM_MATERIAL_STONE, PRIM_MATERIAL_METAL, PRIM_MATERI
PRIM_PHYSICS Sets physics to TRUE or FALSE
PRIM_FLEXIBLE Followed by TRUE or FALSE, integer softness, float gravity, float friction, float wind, float tension, and vector force
PRIM_POINT_LIGHT Followed by TRUE or FALSE, vector color, float intensity, float radius, float falloff
PRIM_TEMP_ON_REZ Sets temporay on rez to TRUE or FALSE
PRIM_TEMP_ON_REZ Sets temporary on rez to TRUE or FALSE
PRIM_PHANTOM Sets phantom to TRUE or FALSE
PRIM_CAST_SHADOWS DEPRECATED. Takes 1 parameter, an integer, but has no effect when set and always returns 0 if used in llGetPrimitiveParams
PRIM_POSITION Sets primitive position to a vector position
@ -361,6 +393,19 @@ PRIM_BUMP_SHINY Followed by an integer face, one of PRIM_SHINY_NONE, PRIM_SHINY
PRIM_FULLBRIGHT Followed by an integer face, and TRUE or FALSE
PRIM_TEXGEN Followed by an integer face, and one of PRIM_TEXGEN_DEFAULT or PRIM_TEXGEN_PLANAR
PRIM_GLOW Followed by an integer face, and a float from 0.0 to 1.0 specifying glow amount
PRIM_TEXT Followed by string text, vector color, and float alpha
PRIM_NAME Followed by string name
PRIM_DESC Followed by string description
PRIM_ROT_LOCAL Followed by rotation rot
PRIM_PHYSICS_SHAPE_TYPE Followed by PRIM_PHYSICS_SHAPE_PRIM, PRIM_PHYSICS_SHAPE_NONE, or PRIM_PHYSICS_SHAPE_CONVEX
PRIM_OMEGA Followed by vector axis, float spinrate, and float gain
PRIM_POS_LOCAL Followed by vector position
PRIM_LINK_TARGET Followed by integer link_target, then additional prim parameter flags
PRIM_SLICE Followed by vector slice
PRIM_PHYSICS_SHAPE_PRIM Use the default physics shape
PRIM_PHYSICS_SHAPE_CONVEX Use the convex hull of the prim shape for physics
PRIM_PHYSICS_SHAPE_NONE Ignore this prim in the physics shape
PRIM_TYPE_BOX Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear
PRIM_TYPE_CYLINDER Followed by integer hole shape, vector cut, float hollow, vector twist,:vector top size, and vector top shear

View File

@ -3982,6 +3982,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>DebugShowAvatarRenderInfo</key>
<map>
<key>Comment</key>
<string>Show avatar render cost information</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DebugShowColor</key>
<map>
<key>Comment</key>
@ -12223,7 +12234,18 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
<string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string>
<string>Maximum bytes of attachments before an avatar is rendered as a simple imposter (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>RenderAutoMuteRenderCostLimit</key>
<map>
<key>Comment</key>
<string>Maximum render weight before an avatar is rendered as a simple imposter (0 to not use this limit).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -12236,7 +12258,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<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>
<string>Maximum surface area of attachments before an avatar is rendered as a simple imposter (0 to not use this limit).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -12246,7 +12268,28 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Backup</key>
<integer>0</integer>
</map>
<key>RenderAutoMuteThreshold</key>
<map>
<key>Comment</key>
<string>Threshold on the Avatar Detail slider where simple imposter mode is enabled. (less than 0 is always on, greather than 1 always off)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.25</real>
</map>
<key>RenderAutoMuteLogging</key>
<map>
<key>Comment</key>
<string>Show extra information in viewer logs about avatar rendering costs</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAutoHideSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@ -12408,6 +12451,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>RevokePermsOnStopAnimation</key>
<map>
<key>Comment</key>
<string>Clear animation permssions when choosing "Stop Animating Me"</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RotateRight</key>
<map>
<key>Comment</key>
@ -19487,6 +19541,18 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>VersionChannelName</key>
<map>
<key>Comment</key>
<string>Version information generated by running the viewer</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string />
</map>
<key>FSShowServerVersionChangeNotice</key>
<map>
<key>Comment</key>
@ -21300,3 +21366,4 @@ Change of this parameter will affect the layout of buttons in notification toast
</map>
</map>
</llsd>

View File

@ -61,6 +61,7 @@ VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_position;
VARYING vec3 vary_pointlight_col;
VARYING vec3 vary_pointlight_col_linear;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_norm;
@ -82,7 +83,7 @@ vec3 calcDirectionalLight(vec3 n, vec3 l)
return vec3(a,a,a);
}
vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
@ -92,16 +93,16 @@ vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
//if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
lv /= d;
//distance attenuation
float dist = d/la;
da = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
float dist = d*la;
da = clamp(1.0-(dist+fa-1.0)/fa, 0.0, 1.0);
da *= da;
da *= 1.4;
da *= 2.0;
// spotlight coefficient.
@ -112,7 +113,7 @@ vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float
da *= max(dot(n, lv), 0.0);
}
return vec3(da,da,da);
return da;
}
#if HAS_SHADOW
@ -138,6 +139,25 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
void main()
{
#ifdef USE_INDEXED_TEX
vec4 diff = diffuseLookup(vary_texcoord0.xy);
#else
vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
#endif
#ifdef USE_VERTEX_COLOR
float vertex_color_alpha = vertex_color.a;
#else
float vertex_color_alpha = 1.0;
#endif
float alpha = vertex_color_alpha*diff.a;
vec4 gamma_diff = diff;
diff.rgb = pow(diff.rgb, vec3(2.2f, 2.2f, 2.2f));
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
@ -210,21 +230,6 @@ void main()
}
#endif
#ifdef USE_INDEXED_TEX
vec4 diff = diffuseLookup(vary_texcoord0.xy);
#else
vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
#endif
vec4 gamma_diff = diff;
diff.rgb = pow(diff.rgb, vec3(2.2f, 2.2f, 2.2f));
#ifdef USE_VERTEX_COLOR
float vertex_color_alpha = vertex_color.a;
#else
float vertex_color_alpha = 1.0;
#endif
vec3 normal = vary_norm;
vec3 l = light_position[0].xyz;
@ -243,6 +248,7 @@ void main()
color.rgb = scaleSoftClip(color.rgb);
//convert to linear space
color.rgb = pow(color.rgb, vec3(2.2));
col = vec4(0,0,0,0);
@ -257,8 +263,9 @@ void main()
LIGHT_LOOP(6)
LIGHT_LOOP(7)
color.rgb += diff.rgb * pow(vary_pointlight_col, vec3(2.2)) * col.rgb;
color.rgb += diff.rgb * vary_pointlight_col_linear * col.rgb;
//convert to gamma space
color.rgb = pow(color.rgb, vec3(1.0/2.2));
frag_color = color;

View File

@ -1,150 +0,0 @@
/**
* @file alphaF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2DRect depthMap;
uniform sampler2D diffuseMap;
uniform vec2 screen_res;
vec3 atmosLighting(vec3 light);
vec3 scaleSoftClip(vec3 light);
VARYING vec3 vary_ambient;
VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_position;
VARYING vec3 vary_pointlight_col;
VARYING vec2 vary_texcoord0;
VARYING vec4 vertex_color;
VARYING vec3 vary_norm;
uniform mat4 inv_proj;
uniform vec4 light_position[8];
uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
vec3 calcDirectionalLight(vec3 n, vec3 l)
{
float a = pow(max(dot(n,l),0.0), 0.7);
return vec3(a,a,a);
}
vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = dot(lv,lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
//distance attenuation
float dist2 = d/la;
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= max(pow(dot(n, lv), 0.7), 0.0);
}
return vec3(da,da,da);
}
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
vec4 pos = vec4(vary_position, 1.0);
vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy);
vec3 n = vary_norm;
vec3 l = light_position[0].xyz;
vec3 dlight = calcDirectionalLight(n, l);
dlight = dlight * vary_directional.rgb * vary_pointlight_col;
vec4 col = vec4(vary_ambient + dlight, vertex_color.a);
vec4 color = diff * col;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
vec3 light_col = vec3(0,0,0);
#define LIGHT_LOOP(i) \
light_col += light_diffuse[i].rgb * calcPointLightOrSpotLight(pos.xyz, vary_norm, light_position[i], light_direction[i], light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z);
LIGHT_LOOP(1)
LIGHT_LOOP(2)
LIGHT_LOOP(3)
LIGHT_LOOP(4)
LIGHT_LOOP(5)
LIGHT_LOOP(6)
LIGHT_LOOP(7)
color.rgb += diff.rgb * vary_pointlight_col * light_col;
color.rgb = pow(color.rgb, vec3(1.0/2.2));
frag_color = color;
//frag_color = vec4(1,0,1,1);
//frag_color = vec4(1,0,1,1)*shadow;
}

View File

@ -1,92 +0,0 @@
/**
* @file alphaNonIndexedNoColorF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform float minimum_alpha;
uniform sampler2DRect depthMap;
uniform sampler2D diffuseMap;
uniform vec2 screen_res;
vec3 atmosLighting(vec3 light);
vec3 scaleSoftClip(vec3 light);
VARYING vec3 vary_ambient;
VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_position;
VARYING vec3 vary_pointlight_col;
VARYING vec2 vary_texcoord0;
uniform mat4 inv_proj;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
vec4 pos = vec4(vary_position, 1.0);
vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy);
if (diff.a < minimum_alpha)
{
discard;
}
vec4 col = vec4(vary_ambient + vary_directional.rgb, 1.0);
vec4 color = diff * col;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
color.rgb += diff.rgb * vary_pointlight_col.rgb;
frag_color = color;
}

View File

@ -1,136 +0,0 @@
/**
* @file alphaSkinnedV.glsl
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec4 diffuse_color;
ATTRIBUTE vec2 texcoord0;
mat4 getObjectSkinnedTransform();
void calcAtmospherics(vec3 inPositionEye);
float calcDirectionalLight(vec3 n, vec3 l);
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
VARYING vec3 vary_position;
VARYING vec3 vary_ambient;
VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_pointlight_col;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_norm;
uniform float near_clip;
uniform vec4 light_position[8];
uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
float calcDirectionalLight(vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = dot(lv,lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
//distance attenuation
float dist2 = d/la;
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= max(dot(n, lv), 0.0);
}
return da;
}
void main()
{
vary_texcoord0 = texcoord0;
vec4 pos;
vec3 norm;
mat4 trans = getObjectSkinnedTransform();
trans = modelview_matrix * trans;
pos = trans * vec4(position.xyz, 1.0);
norm = position.xyz + normal.xyz;
norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz);
vary_norm = norm;
vec4 frag_pos = projection_matrix * pos;
gl_Position = frag_pos;
vary_position = pos.xyz;
calcAtmospherics(pos.xyz);
//vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.));
vec4 col = vec4(0.0, 0.0, 0.0, diffuse_color.a);
vary_pointlight_col = diffuse_color.rgb;
col.rgb = vec3(0,0,0);
// Add windlight lights
col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*diffuse_color.rgb;
vary_directional.rgb = atmosAffectDirectionalLight(1);
col.rgb = col.rgb*diffuse_color.rgb;
vertex_color = col;
vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
}

View File

@ -68,6 +68,7 @@ VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_position;
VARYING vec3 vary_pointlight_col;
VARYING vec3 vary_pointlight_col_linear;
#ifdef USE_VERTEX_COLOR
VARYING vec4 vertex_color;
@ -79,43 +80,8 @@ VARYING vec3 vary_norm;
uniform float near_clip;
uniform vec4 light_position[8];
uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
uniform vec3 sun_dir;
vec3 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = dot(lv,lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
//distance attenuation
float dist2 = d/la;
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= max(dot(n, lv), 0.0);
}
return vec3(da,da,da);
}
void main()
{
vec4 pos;
@ -181,6 +147,7 @@ void main()
vary_pointlight_col = diff;
vary_pointlight_col_linear = pow(diff, vec3(2.2));
col.rgb = vec3(0,0,0);

View File

@ -71,18 +71,18 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
vec3 lv = lp.xyz-v;
//get distance
float d = dot(lv,lv);
float d = length(lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
//if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
lv /= d;
//distance attenuation
float dist2 = d/la;
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
float dist = d*la;
da = clamp(1.0-(dist-1.0+fa)/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);

View File

@ -1,153 +0,0 @@
/**
* @file avatarAlphaV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat4 projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0;
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
void calcAtmospherics(vec3 inPositionEye);
float calcDirectionalLight(vec3 n, vec3 l);
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
VARYING vec3 vary_position;
VARYING vec3 vary_ambient;
VARYING vec3 vary_directional;
VARYING vec3 vary_fragcoord;
VARYING vec3 vary_pointlight_col;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
uniform float near_clip;
uniform vec4 color;
uniform vec4 light_position[8];
uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
float calcDirectionalLight(vec3 n, vec3 l)
{
float a = max(dot(n,l),0.0);
return a;
}
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = dot(lv,lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv = normalize(lv);
//distance attenuation
float dist2 = d/la;
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= max(dot(n, lv), 0.0);
}
return da;
}
void main()
{
vary_texcoord0 = texcoord0;
vec4 pos;
vec3 norm;
mat4 trans = getSkinnedTransform();
vec4 pos_in = vec4(position.xyz, 1.0);
pos.x = dot(trans[0], pos_in);
pos.y = dot(trans[1], pos_in);
pos.z = dot(trans[2], pos_in);
pos.w = 1.0;
norm.x = dot(trans[0].xyz, normal);
norm.y = dot(trans[1].xyz, normal);
norm.z = dot(trans[2].xyz, normal);
norm = normalize(norm);
vec4 frag_pos = projection_matrix * pos;
gl_Position = frag_pos;
vary_position = pos.xyz;
calcAtmospherics(pos.xyz);
vec4 col = vec4(0.0, 0.0, 0.0, 1.0);
// Collect normal lights
col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z);
col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z);
col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z);
col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z);
col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z);
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*color.rgb;
col.rgb = vec3(0,0,0);
// Add windlight lights
col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*color.rgb;
vary_directional = color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0));
col.rgb = col.rgb * color.rgb;
vertex_color = col;
vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
}

View File

@ -31,6 +31,8 @@ out vec4 frag_data[3];
uniform sampler2D diffuseMap;
uniform float minimum_alpha;
VARYING vec3 vary_normal;
VARYING vec2 vary_texcoord0;
@ -44,7 +46,7 @@ void main()
{
vec4 diff = texture2D(diffuseMap, vary_texcoord0.xy);
if (diff.a < 0.2)
if (diff.a < minimum_alpha)
{
discard;
}

Some files were not shown because too many files have changed in this diff Show More