diff options
141 files changed, 5380 insertions, 2576 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 98eeed09b3..00baf626d2 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -69,6 +69,7 @@ if (WINDOWS) /Oy- /Zc:wchar_t- /arch:SSE2 + /fp:fast ) # Are we using the crummy Visual Studio KDU build workaround? diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index c9fb8534f1..0a6a8f9fa6 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -189,6 +189,7 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation"); static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); +static LLFastTimer::DeclareTimer FTM_UPDATE_MOTIONS("Update Motions"); void LLCharacter::updateMotions(e_update_t update_type) { @@ -206,7 +207,10 @@ void LLCharacter::updateMotions(e_update_t update_type) mMotionController.unpauseAllMotions(); } bool force_update = (update_type == FORCE_UPDATE); - mMotionController.updateMotions(force_update); + { + LLFastTimer t(FTM_UPDATE_MOTIONS); + mMotionController.updateMotions(force_update); + } } } diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index bb892f4a7f..4f6351709e 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -542,6 +542,8 @@ void LLMotionController::updateIdleActiveMotions() //----------------------------------------------------------------------------- // updateMotionsByType() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_MOTION_ON_UPDATE("Motion onUpdate"); + void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { BOOL update_result = TRUE; @@ -699,7 +701,10 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty } // perform motion update - update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); + { + LLFastTimer t(FTM_MOTION_ON_UPDATE); + update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); + } } //********************** @@ -810,7 +815,7 @@ void LLMotionController::updateMotions(bool force_update) // Always cap the number of loaded motions purgeExcessMotions(); - + // Update timing info for this time step. if (!mPaused) { @@ -832,6 +837,7 @@ void LLMotionController::updateMotions(bool force_update) } updateLoadingMotions(); + return; } @@ -850,7 +856,7 @@ void LLMotionController::updateMotions(bool force_update) } updateLoadingMotions(); - + resetJointSignatures(); if (mPaused && !force_update) @@ -861,11 +867,12 @@ void LLMotionController::updateMotions(bool force_update) { // update additive motions updateAdditiveMotions(); + resetJointSignatures(); - + // update all regular motions updateRegularMotions(); - + if (use_quantum) { mPoseBlender.blendAndCache(TRUE); diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index e295e3c621..8276ec836a 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -269,6 +269,7 @@ namespace virtual LLSD::UUID asUUID() const { return LLUUID(mValue); } virtual LLSD::Date asDate() const { return LLDate(mValue); } virtual LLSD::URI asURI() const { return LLURI(mValue); } + virtual int size() const { return mValue.size(); } }; LLSD::Integer ImplString::asInteger() const diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index f4c43bac61..ed9284d2c5 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -44,6 +44,15 @@ public: const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + LLStrider<Object> operator+(const S32& index) + { + LLStrider<Object> ret; + ret.mBytep = mBytep + mSkip*index; + ret.mSkip = mSkip; + + return ret; + } + void skip(const U32 index) { mBytep += mSkip*index;} U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } @@ -51,6 +60,7 @@ public: Object& operator *() { return *mObjectp; } Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } + Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } }; diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 1b11e83b4a..6c768863a6 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -31,7 +31,6 @@ #include "v3math.h" #include "llvector4a.h" #include <vector> -#include <set> #define OCT_ERRS LL_WARNS("OctreeErrors") @@ -79,11 +78,13 @@ public: typedef LLOctreeTraveler<T> oct_traveler; typedef LLTreeTraveler<T> tree_traveler; - typedef typename std::set<LLPointer<T> > element_list; - typedef typename element_list::iterator element_iter; - typedef typename element_list::const_iterator const_element_iter; + typedef LLPointer<T>* element_list; + typedef LLPointer<T>* element_iter; + typedef const LLPointer<T>* const_element_iter; typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; - typedef typename std::vector<LLOctreeNode<T>* > child_list; + typedef LLOctreeNode<T>** child_list; + typedef LLOctreeNode<T>** child_iter; + typedef LLTreeNode<T> BaseType; typedef LLOctreeNode<T> oct_node; typedef LLOctreeListener<T> oct_listener; @@ -105,6 +106,9 @@ public: : mParent((oct_node*)parent), mOctant(octant) { + mData = NULL; + mDataEnd = NULL; + mCenter = center; mSize = size; @@ -123,6 +127,16 @@ public: { BaseType::destroyListeners(); + for (U32 i = 0; i < mElementCount; ++i) + { + mData[i]->setBinIndex(-1); + mData[i] = NULL; + } + + free(mData); + mData = NULL; + mDataEnd = NULL; + for (U32 i = 0; i < getChildCount(); i++) { delete getChild(i); @@ -219,12 +233,17 @@ public: } void accept(oct_traveler* visitor) { visitor->visit(this); } - virtual bool isLeaf() const { return mChild.empty(); } + virtual bool isLeaf() const { return mChildCount == 0; } U32 getElementCount() const { return mElementCount; } + bool isEmpty() const { return mElementCount == 0; } element_list& getData() { return mData; } const element_list& getData() const { return mData; } - + element_iter getDataBegin() { return mData; } + element_iter getDataEnd() { return mDataEnd; } + const_element_iter getDataBegin() const { return mData; } + const_element_iter getDataEnd() const { return mDataEnd; } + U32 getChildCount() const { return mChildCount; } oct_node* getChild(U32 index) { return mChild[index]; } const oct_node* getChild(U32 index) const { return mChild[index]; } @@ -289,7 +308,7 @@ public: virtual bool insert(T* data) { - if (data == NULL) + if (data == NULL || data->getBinIndex() != -1) { OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; return false; @@ -302,13 +321,16 @@ public: if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here - //if this is a redundant insertion, error out (should never happen) - llassert(mData.find(data) == mData.end()); + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); - mData.insert(data); - BaseType::insert(data); + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>)); - mElementCount = mData.size(); + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); + BaseType::insert(data); return true; } else @@ -342,10 +364,16 @@ public: if( lt == 0x7 ) { - mData.insert(data); - BaseType::insert(data); + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); + + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>)); - mElementCount = mData.size(); + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); + BaseType::insert(data); return true; } @@ -394,23 +422,59 @@ public: return false; } + void _remove(T* data, S32 i) + { //precondition -- mElementCount > 0, idx is in range [0, mElementCount) + + mElementCount--; + data->setBinIndex(-1); + + if (mElementCount > 0) + { + if (mElementCount != i) + { + mData[i] = mData[mElementCount]; //might unref data, do not access data after this point + mData[i]->setBinIndex(i); + } + + mData[mElementCount] = NULL; //needed for unref + mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount); + mDataEnd = mData+mElementCount; + } + else + { + mData[0] = NULL; //needed for unref + free(mData); + mData = NULL; + mDataEnd = NULL; + } + + notifyRemoval(data); + checkAlive(); + } + bool remove(T* data) { - if (mData.find(data) != mData.end()) - { //we have data - mData.erase(data); - mElementCount = mData.size(); - notifyRemoval(data); - checkAlive(); - return true; - } - else if (isInside(data)) + S32 i = data->getBinIndex(); + + if (i >= 0 && i < mElementCount) + { + if (mData[i] == data) + { //found it + _remove(data, i); + llassert(data->getBinIndex() == -1); + return true; + } + } + + if (isInside(data)) { oct_node* dest = getNodeAt(data); if (dest != this) { - return dest->remove(data); + bool ret = dest->remove(data); + llassert(data->getBinIndex() == -1); + return ret; } } @@ -429,19 +493,20 @@ public: //node is now root llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl; node->removeByAddress(data); + llassert(data->getBinIndex() == -1); return true; } void removeByAddress(T* data) { - if (mData.find(data) != mData.end()) + for (U32 i = 0; i < mElementCount; ++i) { - mData.erase(data); - mElementCount = mData.size(); - notifyRemoval(data); - llwarns << "FOUND!" << llendl; - checkAlive(); - return; + if (mData[i] == data) + { //we have data + _remove(data, i); + llwarns << "FOUND!" << llendl; + return; + } } for (U32 i = 0; i < getChildCount(); i++) @@ -453,8 +518,8 @@ public: void clearChildren() { - mChild.clear(); mChildCount = 0; + U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; } @@ -516,7 +581,7 @@ public: mChildMap[child->getOctant()] = mChildCount; - mChild.push_back(child); + mChild[mChildCount] = child; ++mChildCount; child->setParent(this); @@ -543,9 +608,12 @@ public: mChild[index]->destroy(); delete mChild[index]; } - mChild.erase(mChild.begin() + index); + --mChildCount; + mChild[index] = mChild[mChildCount]; + + //rebuild child map U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; @@ -601,11 +669,12 @@ protected: oct_node* mParent; U8 mOctant; - child_list mChild; + LLOctreeNode<T>* mChild[8]; U8 mChildMap[8]; U32 mChildCount; element_list mData; + element_iter mDataEnd; U32 mElementCount; }; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index cc9744756f..06ac0aa1f6 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -328,16 +328,16 @@ public: LLVector4a& min = node->mExtents[0]; LLVector4a& max = node->mExtents[1]; - if (!branch->getData().empty()) + if (!branch->isEmpty()) { //node has data, find AABB that binds data set - const LLVolumeTriangle* tri = *(branch->getData().begin()); + const LLVolumeTriangle* tri = *(branch->getDataBegin()); //initialize min/max to first available vertex min = *(tri->mV[0]); max = *(tri->mV[0]); for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - branch->getData().begin(); iter != branch->getData().end(); ++iter) + branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) { //for each triangle in node //stretch by triangles in node @@ -352,7 +352,7 @@ public: max.setMax(max, *tri->mV[2]); } } - else if (!branch->getChildren().empty()) + else if (!branch->isLeaf()) { //no data, but child nodes exist LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 76cf9de613..2e6f9e2f71 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -54,6 +54,7 @@ class LLVolumeTriangle; #include "llstrider.h" #include "v4coloru.h" #include "llrefcount.h" +#include "llpointer.h" #include "llfile.h" //============================================================================ @@ -919,6 +920,10 @@ public: LLVector2* mTexCoords; U16* mIndices; + //vertex buffer filled in by LLFace to cache this volume face geometry in vram + // (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer) + mutable LLPointer<LLRefCount> mVertexBuffer; + std::vector<S32> mEdge; //list of skin weights for rigged volumes diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index b5a935c2b5..cc83cb7235 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -131,7 +131,7 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle> void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* node) { for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = - node->getData().begin(); iter != node->getData().end(); ++iter) + node->getDataBegin(); iter != node->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -236,8 +236,8 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch) } //children fit, check data - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); ++iter) + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 688d91dc40..ed54fe0835 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -39,7 +39,7 @@ class LLVolumeTriangle : public LLRefCount public: LLVolumeTriangle() { - + mBinIndex = -1; } LLVolumeTriangle(const LLVolumeTriangle& rhs) @@ -64,9 +64,16 @@ public: U16 mIndex[3]; F32 mRadius; + mutable S32 mBinIndex; + virtual const LLVector4a& getPositionGroup() const; virtual const F32& getBinRadius() const; + + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 idx) const { mBinIndex = idx; } + + }; class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index 3d8ca2ad9f..a6fccd2a56 100644 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -276,7 +276,7 @@ S32 getElementSize(const LLSD& llsd) case LLSD::TypeReal: return sizeof(F64); case LLSD::TypeString: - return llsd.asString().size(); + return llsd.size(); case LLSD::TypeUUID: return sizeof(LLUUID); case LLSD::TypeDate: diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 45a3b18179..362452d837 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -81,7 +81,7 @@ void LLCubeMap::initGL() { U32 texname = 0; - LLImageGL::generateTextures(1, &texname); + LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname); for (int i = 0; i < 6; i++) { diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 628a8d6131..0b56b3889c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -249,6 +249,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL; PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL; PFNGLSAMPLEMASKIPROC glSampleMaski = NULL; +//transform feedback (4.0 core) +PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL; +PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; + //GL_ARB_debug_output PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL; @@ -421,6 +427,7 @@ LLGLManager::LLGLManager() : mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), mHasTextureMultisample(FALSE), + mHasTransformFeedback(FALSE), mMaxSampleMaskWords(0), mMaxColorTextureSamples(0), mMaxDepthTextureSamples(0), @@ -558,7 +565,8 @@ bool LLGLManager::initGL() parse_gl_version( &mDriverVersionMajor, &mDriverVersionMinor, &mDriverVersionRelease, - &mDriverVersionVendorString ); + &mDriverVersionVendorString, + &mGLVersionString); mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; @@ -938,7 +946,6 @@ void LLGLManager::initExtensions() mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); - mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); glh_init_extensions("GL_ARB_texture_cube_map"); @@ -963,11 +970,14 @@ void LLGLManager::initExtensions() ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); #endif + mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f; + mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); + mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -1207,7 +1217,14 @@ void LLGLManager::initExtensions() glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample"); glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv"); glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); - } + } + if (mHasTransformFeedback) + { + glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback"); + glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback"); + glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings"); + glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); + } if (mHasDebugOutput) { glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); @@ -1964,6 +1981,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) : case GL_COLOR_MATERIAL: case GL_FOG: case GL_LINE_STIPPLE: + case GL_POLYGON_STIPPLE: mState = 0; break; } @@ -2052,7 +2070,7 @@ void LLGLManager::initGLStates() //////////////////////////////////////////////////////////////////////////////// -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ) +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ) { // GL_VERSION returns a null-terminated string with the format: // <major>.<minor>[.<release>] [<vendor specific>] @@ -2068,6 +2086,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor return; } + version_string->assign(version); + std::string ver_copy( version ); S32 len = (S32)strlen( version ); /* Flawfinder: ignore */ S32 i = 0; @@ -2429,3 +2449,65 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip() gGL.matrixMode(LLRender::MM_MODELVIEW); } + + +LLGLSyncFence::LLGLSyncFence() +{ +#ifdef GL_ARB_sync + mSync = 0; +#endif +} + +LLGLSyncFence::~LLGLSyncFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif +} + +void LLGLSyncFence::placeFence() +{ +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif +} + +bool LLGLSyncFence::isCompleted() +{ + bool ret = true; +#ifdef GL_ARB_sync + if (mSync) + { + GLenum status = glClientWaitSync(mSync, 0, 1); + if (status == GL_TIMEOUT_EXPIRED) + { + ret = false; + } + } +#endif + return ret; +} + +void LLGLSyncFence::wait() +{ +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif +} + + + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 5a33c98708..964495a3ab 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -104,6 +104,7 @@ public: BOOL mHasDepthClamp; BOOL mHasTextureRectangle; BOOL mHasTextureMultisample; + BOOL mHasTransformFeedback; S32 mMaxSampleMaskWords; S32 mMaxColorTextureSamples; S32 mMaxDepthTextureSamples; @@ -141,6 +142,7 @@ public: S32 mGLSLVersionMajor; S32 mGLSLVersionMinor; std::string mDriverVersionVendorString; + std::string mGLVersionString; S32 mVRAM; // VRAM in MB S32 mGLMaxVertexRange; @@ -417,13 +419,38 @@ public: virtual void updateGL() = 0; }; +const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms + +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual bool isCompleted() = 0; + virtual void wait() = 0; +}; + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence(); + virtual ~LLGLSyncFence(); + + void placeFence(); + bool isCompleted(); + void wait(); +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" void init_glstates(); -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ); +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string ); extern BOOL gClothRipple; extern BOOL gHeadlessClient; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index d61ec707f0..a0727b8686 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -528,6 +528,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + + #elif LL_WINDOWS //---------------------------------------------------------------------------- // LL_WINDOWS @@ -759,6 +766,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + //GL_ARB_debug_output extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4b7e639aed..7cbf39096e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -129,7 +129,9 @@ void LLGLSLShader::unload() } BOOL LLGLSLShader::createShader(vector<string> * attributes, - vector<string> * uniforms) + vector<string> * uniforms, + U32 varying_count, + const char** varyings) { //reloading, reset matrix hash values for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) @@ -172,6 +174,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } +#ifdef GL_INTERLEAVED_ATTRIBS + if (varying_count > 0 && varyings) + { + glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + } +#endif + // Map attributes and uniforms if (success) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7873fe3c4e..5c68cb46eb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -76,7 +76,9 @@ public: void unload(); BOOL createShader(std::vector<std::string> * attributes, - std::vector<std::string> * uniforms); + std::vector<std::string> * 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); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c04a3f6b41..a842211764 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,6 +42,10 @@ //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; +//which power of 2 is i? +//assumes i is a power of 2 > 0 +U32 wpo2(U32 i); + //statics U32 LLImageGL::sUniqueCount = 0; @@ -50,7 +54,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; -std::list<U32> LLImageGL::sDeadTextureList; +LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; +U32 LLImageGL::sCurTexName = 1; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; @@ -232,9 +237,11 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) //---------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats"); // static void LLImageGL::updateStats(F32 current_time) { + LLFastTimer t(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; @@ -416,6 +423,7 @@ void LLImageGL::init(BOOL usemipmaps) mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mHasMipMaps = false; + mMipLevels = -1; mIsResident = 0; @@ -606,8 +614,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) is_compressed = true; } + + + if (mUseMipMaps) + { + //set has mip maps to true before binding image so tex parameters get set properly + gGL.getTexUnit(0)->unbind(mBindTarget); + mHasMipMaps = true; + mTexOptionsDirty = true; + setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mHasMipMaps = false; + } + llverify(gGL.getTexUnit(0)->bind(this)); + if (mUseMipMaps) { if (data_hasmips) @@ -620,6 +644,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(d); S32 h = getHeight(d); S32 gl_level = d-mCurrentDiscardLevel; + + mMipLevels = llmax(mMipLevels, gl_level); + if (d > mCurrentDiscardLevel) { data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment @@ -662,10 +689,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { if (mAutoGenMips) { - if (!gGLManager.mHasFramebufferObject) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); - } stop_glerror(); { // LLFastTimer t2(FTM_TEMP4); @@ -679,6 +702,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); + mMipLevels = wpo2(llmax(w, h)); + + //use legacy mipmap generation mode + glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, @@ -694,16 +722,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } } - - if (gGLManager.mHasFramebufferObject) - { - glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget)); - } } else { // Create mips by hand - // about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800 // ~4x faster than gluBuild2DMipmaps S32 width = getWidth(mCurrentDiscardLevel); S32 height = getHeight(mCurrentDiscardLevel); @@ -713,6 +735,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) const U8* cur_mip_data = 0; S32 prev_mip_size = 0; S32 cur_mip_size = 0; + + mMipLevels = nummips; + for (int m=0; m<nummips; m++) { if (m==0) @@ -777,10 +802,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; } - mHasMipMaps = true; } else { + mMipLevels = 0; S32 w = getWidth(); S32 h = getHeight(); if (is_compressed) @@ -812,7 +837,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } } - mHasMipMaps = false; } stop_glerror(); mGLTextureCreated = true; @@ -1025,23 +1049,65 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } // static -void LLImageGL::generateTextures(S32 numTextures, U32 *textures) +void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures) { - glGenTextures(numTextures, (GLuint*)textures); + bool empty = true; + + dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format); + + if (iter != sDeadTextureList[type].end()) + { + empty = iter->second.empty(); + } + + for (S32 i = 0; i < numTextures; ++i) + { + if (!empty) + { + textures[i] = iter->second.front(); + iter->second.pop_front(); + empty = iter->second.empty(); + } + else + { + textures[i] = sCurTexName++; + } + } } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) +void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate) { - for (S32 i = 0; i < numTextures; i++) + if (gGLManager.mInited) { - sDeadTextureList.push_back(textures[i]); - } + if (format == 0 || type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1) + { //unknown internal format or unknown number of mip levels, not safe to reuse + glDeleteTextures(numTextures, textures); + } + else + { + for (S32 i = 0; i < numTextures; ++i) + { //remove texture from VRAM by setting its size to zero + for (S32 j = 0; j <= mip_levels; j++) + { + gGL.getTexUnit(0)->bindManual(type, textures[i]); + + glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } + + llassert(std::find(sDeadTextureList[type][format].begin(), + sDeadTextureList[type][format].end(), textures[i]) == + sDeadTextureList[type][format].end()); - if (immediate) + sDeadTextureList[type][format].push_back(textures[i]); + } + } + } + + /*if (immediate) { LLImageGL::deleteDeadTextures(); - } + }*/ } // static @@ -1166,10 +1232,11 @@ BOOL LLImageGL::createGLTexture() if(mTexName) { - glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast<GLuint*>(&mTexName))) ; } - glGenTextures(1, (GLuint*)&mTexName); + + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); if (!mTexName) { @@ -1282,7 +1349,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } else { - LLImageGL::generateTextures(1, &mTexName); + LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName); stop_glerror(); { llverify(gGL.getTexUnit(0)->bind(this)); @@ -1327,7 +1394,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ { sGlobalTextureMemoryInBytes -= mTextureMemory; - LLImageGL::deleteTextures(1, &old_name); + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name); stop_glerror(); } @@ -1456,7 +1523,7 @@ void LLImageGL::deleteDeadTextures() { bool reset = false; - while (!sDeadTextureList.empty()) + /*while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); sDeadTextureList.pop_front(); @@ -1478,7 +1545,7 @@ void LLImageGL::deleteDeadTextures() glDeleteTextures(1, &tex); stop_glerror(); - } + }*/ if (reset) { @@ -1496,7 +1563,7 @@ void LLImageGL::destroyGLTexture() mTextureMemory = 0; } - LLImageGL::deleteTextures(1, &mTexName); + LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &mTexName); mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f34b9fa91a..e118c28c1b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -45,8 +45,16 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; public: - static std::list<U32> sDeadTextureList; + static U32 sCurTexName; + //previously used but now available texture names + // sDeadTextureList[<usage>][<internal format>] + typedef std::map<U32, std::list<U32> > dead_texturelist_t; + static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE]; + + // These 2 functions replace glGenTextures() and glDeleteTextures() + static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures); + static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false); static void deleteDeadTextures(); // Size calculation @@ -96,10 +104,6 @@ public: void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setAllowCompression(bool allow) { mAllowCompression = allow; } - // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() - // for tracking purposes and will be deprecated in the future - static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false); static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); BOOL createGLTexture() ; @@ -217,7 +221,8 @@ protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) bool mHasMipMaps; - + S32 mMipLevels; + LLGLboolean mIsResident; S8 mComponents; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 93bac4c779..348c1eb1b7 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -408,12 +408,14 @@ void LLTexUnit::unbind(eTextureType type) if (mIndex < 0) return; + //always flush and activate for consistency + // some code paths assume unbind always flushes and sets the active texture + gGL.flush(); + activate(); + // Disabled caching of binding state. if (mCurrTexType == type) { - gGL.flush(); - - activate(); mCurrTexture = 0; if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) { @@ -464,11 +466,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio } else if (option >= TFO_BILINEAR) { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } } else { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } } if (gGLManager.mHasAnisotropic) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 780f1dc484..cc5c232380 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -55,7 +55,6 @@ bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), - mTex(0), mFBO(0), mDepth(0), mStencil(0), @@ -70,6 +69,42 @@ LLRenderTarget::~LLRenderTarget() release(); } +void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) +{ + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; + + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + sBytesAllocated += pix_diff*4; + } + + if (mDepth) + { //resize depth attachment + if (mStencil) + { + //use render buffers where stencil buffers are in play + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + else + { + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + } + + sBytesAllocated += pix_diff*4; + } +} + + bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); @@ -135,7 +170,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } U32 tex; - LLImageGL::generateTextures(1, &tex); + LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); @@ -193,6 +228,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } mTex.push_back(tex); + mInternalFormat.push_back(color_fmt); if (gDebugGL) { //bind and unbind to validate target @@ -217,7 +253,7 @@ bool LLRenderTarget::allocateDepth() } else { - LLImageGL::generateTextures(1, &mDepth); + LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); @@ -294,7 +330,7 @@ void LLRenderTarget::release() } else { - LLImageGL::deleteTextures(1, &mDepth, true); + LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true); stop_glerror(); } mDepth = 0; @@ -326,8 +362,9 @@ void LLRenderTarget::release() if (mTex.size() > 0) { sBytesAllocated -= mResX*mResY*4*mTex.size(); - LLImageGL::deleteTextures(mTex.size(), &mTex[0], true); + LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true); mTex.clear(); + mInternalFormat.clear(); } mResX = mResY = 0; diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 2735ab21c5..e1a51304f1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -57,8 +57,6 @@ */ -class LLMultisampleBuffer; - class LLRenderTarget { public: @@ -74,6 +72,12 @@ public: //multiple calls will release previously allocated resources bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + //resize existing attachments to use new resolution and color format + // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined + // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded + // DO use for render targets that resize often and aren't likely to ruin someone's day if they break + void resize(U32 resx, U32 resy, U32 color_fmt); + //add color buffer attachment //limit of 4 color attachments per render target bool addColorAttachment(U32 color_fmt); @@ -142,6 +146,7 @@ protected: U32 mResX; U32 mResY; std::vector<U32> mTex; + std::vector<U32> mInternalFormat; U32 mFBO; U32 mDepth; bool mStencil; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5a6e6cab3e..d3b2d9fa74 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1026,6 +1026,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("size"); mReservedUniforms.push_back("falloff"); + mReservedUniforms.push_back("box_center"); + mReservedUniforms.push_back("box_size"); + mReservedUniforms.push_back("minLuminance"); mReservedUniforms.push_back("maxExtractAlpha"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index f792faa8f0..7a16b7c20f 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -97,6 +97,8 @@ public: LIGHT_CENTER, LIGHT_SIZE, LIGHT_FALLOFF, + BOX_CENTER, + BOX_SIZE, GLOW_MIN_LUMINANCE, GLOW_MAX_EXTRACT_ALPHA, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 823c6b9dc5..0092df6587 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -38,12 +38,6 @@ #include "llglslshader.h" #include "llmemory.h" -#if LL_DARWIN -#define LL_VBO_POOLING 1 -#else -#define LL_VBO_POOLING 0 -#endif - //Next Highest Power Of Two //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2 U32 nhpo2(U32 v) @@ -71,6 +65,7 @@ U32 wpo2(U32 i) const U32 LL_VBO_BLOCK_SIZE = 2048; +const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024; U32 vbo_block_size(U32 size) { //what block size will fit size? @@ -83,6 +78,7 @@ U32 vbo_block_index(U32 size) return vbo_block_size(size)/LL_VBO_BLOCK_SIZE; } +const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE); //============================================================================ @@ -95,6 +91,11 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_ U32 LLVBOPool::sBytesPooled = 0; U32 LLVBOPool::sIndexBytesPooled = 0; +U32 LLVBOPool::sCurGLName = 1; + +std::list<U32> LLVertexBuffer::sAvailableVAOName; +U32 LLVertexBuffer::sCurVAOName = 1; + U32 LLVertexBuffer::sAllocatedIndexBytes = 0; U32 LLVertexBuffer::sIndexCount = 0; @@ -119,69 +120,55 @@ bool LLVertexBuffer::sUseStreamDraw = true; bool LLVertexBuffer::sUseVAO = false; bool LLVertexBuffer::sPreferStreamDraw = false; -const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms -class LLGLSyncFence : public LLGLFence +U32 LLVBOPool::genBuffer() { -public: -#ifdef GL_ARB_sync - GLsync mSync; -#endif - - LLGLSyncFence() - { -#ifdef GL_ARB_sync - mSync = 0; -#endif - } + U32 ret = 0; - virtual ~LLGLSyncFence() + if (mGLNamePool.empty()) { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } -#endif + ret = sCurGLName++; } - - void placeFence() + else { -#ifdef GL_ARB_sync - if (mSync) - { - glDeleteSync(mSync); - } - mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -#endif + ret = mGLNamePool.front(); + mGLNamePool.pop_front(); } - void wait() + return ret; +} + +void LLVBOPool::deleteBuffer(U32 name) +{ + if (gGLManager.mInited) { -#ifdef GL_ARB_sync - if (mSync) - { - while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) - { //track the number of times we've waited here - static S32 waits = 0; - waits++; - } - } -#endif - } + LLVertexBuffer::unbind(); + glBindBufferARB(mType, name); + glBufferDataARB(mType, 0, NULL, mUsage); -}; + llassert(std::find(mGLNamePool.begin(), mGLNamePool.end(), name) == mGLNamePool.end()); + + mGLNamePool.push_back(name); + + glBindBufferARB(mType, 0); + } +} -volatile U8* LLVBOPool::allocate(U32& name, U32 size) +LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) +: mUsage(vboUsage), mType(vboType) +{ + mMissCount.resize(LL_VBO_POOL_SEED_COUNT); + std::fill(mMissCount.begin(), mMissCount.end(), 0); +} + +volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) { llassert(vbo_block_size(size) == size); volatile U8* ret = NULL; -#if LL_VBO_POOLING - U32 i = vbo_block_index(size); if (mFreeList.size() <= i) @@ -189,12 +176,18 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList.resize(i+1); } - if (mFreeList[i].empty()) + if (mFreeList[i].empty() || for_seed) { //make a new buffer - glGenBuffersARB(1, &name); + name = genBuffer(); + glBindBufferARB(mType, name); + if (!for_seed && i < LL_VBO_POOL_SEED_COUNT) + { //record this miss + mMissCount[i]++; + } + if (mType == GL_ARRAY_BUFFER_ARB) { LLVertexBuffer::sAllocatedBytes += size; @@ -215,6 +208,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) } glBindBufferARB(mType, 0); + + if (for_seed) + { //put into pool for future use + llassert(mFreeList.size() > i); + + Record rec; + rec.mGLName = name; + rec.mClientData = ret; + + if (mType == GL_ARRAY_BUFFER_ARB) + { + sBytesPooled += size; + } + else + { + sIndexBytesPooled += size; + } + mFreeList[i].push_back(rec); + } } else { @@ -232,33 +244,6 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList[i].pop_front(); } -#else //no pooling - - glGenBuffersARB(1, &name); - glBindBufferARB(mType, name); - - if (mType == GL_ARRAY_BUFFER_ARB) - { - LLVertexBuffer::sAllocatedBytes += size; - } - else - { - LLVertexBuffer::sAllocatedIndexBytes += size; - } - - if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) - { - glBufferDataARB(mType, size, 0, mUsage); - ret = (U8*) ll_aligned_malloc_16(size); - } - else - { //always use a true hint of static draw when allocating non-client-backed buffers - glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); - } - - glBindBufferARB(mType, 0); - -#endif return ret; } @@ -267,50 +252,47 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) { llassert(vbo_block_size(size) == size); -#if LL_VBO_POOLING - - U32 i = vbo_block_index(size); - - llassert(mFreeList.size() > i); + deleteBuffer(name); + ll_aligned_free_16((U8*) buffer); - Record rec; - rec.mGLName = name; - rec.mClientData = buffer; - - if (buffer == NULL) + if (mType == GL_ARRAY_BUFFER_ARB) { - glDeleteBuffersARB(1, &rec.mGLName); + LLVertexBuffer::sAllocatedBytes -= size; } else { - if (mType == GL_ARRAY_BUFFER_ARB) - { - sBytesPooled += size; - } - else - { - sIndexBytesPooled += size; - } - mFreeList[i].push_back(rec); + LLVertexBuffer::sAllocatedIndexBytes -= size; } -#else //no pooling - glDeleteBuffersARB(1, &name); - ll_aligned_free_16((U8*) buffer); +} - if (mType == GL_ARRAY_BUFFER_ARB) +void LLVBOPool::seedPool() +{ + U32 dummy_name = 0; + + if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT) { - LLVertexBuffer::sAllocatedBytes -= size; + mFreeList.resize(LL_VBO_POOL_SEED_COUNT); } - else + + for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++) { - LLVertexBuffer::sAllocatedIndexBytes -= size; + if (mMissCount[i] > mFreeList[i].size()) + { + U32 size = i*LL_VBO_BLOCK_SIZE; + + S32 count = mMissCount[i] - mFreeList[i].size(); + for (U32 j = 0; j < count; ++j) + { + allocate(dummy_name, size, true); + } + } } -#endif } + void LLVBOPool::cleanup() { - U32 size = 1; + U32 size = LL_VBO_BLOCK_SIZE; for (U32 i = 0; i < mFreeList.size(); ++i) { @@ -320,8 +302,8 @@ void LLVBOPool::cleanup() { Record& r = l.front(); - glDeleteBuffersARB(1, &r.mGLName); - + deleteBuffer(r.mGLName); + if (r.mClientData) { ll_aligned_free_16((void*) r.mClientData); @@ -341,8 +323,11 @@ void LLVBOPool::cleanup() } } - size *= 2; + size += LL_VBO_BLOCK_SIZE; } + + //reset miss counts + std::fill(mMissCount.begin(), mMissCount.end(), 0); } @@ -376,6 +361,41 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = GL_LINE_LOOP, }; +//static +U32 LLVertexBuffer::getVAOName() +{ + U32 ret = 0; + + if (!sAvailableVAOName.empty()) + { + ret = sAvailableVAOName.front(); + sAvailableVAOName.pop_front(); + } + else + { +#ifdef GL_ARB_vertex_array_object + glGenVertexArrays(1, &ret); +#endif + } + + return ret; +} + +//static +void LLVertexBuffer::releaseVAOName(U32 name) +{ + sAvailableVAOName.push_back(name); +} + + +//static +void LLVertexBuffer::seedPools() +{ + sStreamVBOPool.seedPool(); + sDynamicVBOPool.seedPool(); + sStreamIBOPool.seedPool(); + sDynamicIBOPool.seedPool(); +} //static void LLVertexBuffer::setupClientArrays(U32 data_mask) @@ -985,7 +1005,7 @@ LLVertexBuffer::~LLVertexBuffer() if (mGLArray) { #if GL_ARB_vertex_array_object - glDeleteVertexArrays(1, &mGLArray); + releaseVAOName(mGLArray); #endif } @@ -1211,10 +1231,10 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) llassert(nverts >= 0); - if (nverts >= 65535) + if (nverts > 65536) { llwarns << "Vertex buffer overflow!" << llendl; - nverts = 65535; + nverts = 65536; } U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); @@ -1270,7 +1290,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO)) { #if GL_ARB_vertex_array_object - glGenVertexArrays(1, &mGLArray); + mGLArray = getVAOName(); #endif setupVertexArray(); } @@ -2140,6 +2160,16 @@ void LLVertexBuffer::flush() } } +// bind for transform feedback (quick 'n dirty) +void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count) +{ +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER + U32 offset = mOffsets[type] + sTypeSize[type]*index; + U32 size= (sTypeSize[type]*count); + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size); +#endif +} + // Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { @@ -2291,10 +2321,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) stop_glerror(); volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - /*if ((data_mask & mTypeMask) != data_mask) + if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; - }*/ + } if (LLGLSLShader::sNoFixedFunction) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 7477dec3ad..11fa4ab6a0 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -57,23 +57,28 @@ public: static U32 sBytesPooled; static U32 sIndexBytesPooled; - LLVBOPool(U32 vboUsage, U32 vboType) - : mUsage(vboUsage) - , mType(vboType) - {} + static U32 sCurGLName; + LLVBOPool(U32 vboUsage, U32 vboType); + const U32 mUsage; const U32 mType; //size MUST be a power of 2 - volatile U8* allocate(U32& name, U32 size); + volatile U8* allocate(U32& name, U32 size, bool for_seed = false); //size MUST be the size provided to allocate that returned the given name void release(U32 name, volatile U8* buffer, U32 size); + //batch allocate buffers to be provided to the application on demand + void seedPool(); + //destroy all records in mFreeList void cleanup(); + U32 genBuffer(); + void deleteBuffer(U32 name); + class Record { public: @@ -81,17 +86,15 @@ public: volatile U8* mClientData; }; + std::list<U32> mGLNamePool; + typedef std::list<Record> record_list_t; std::vector<record_list_t> mFreeList; -}; + std::vector<U32> mMissCount; -class LLGLFence -{ -public: - virtual void placeFence() = 0; - virtual void wait() = 0; }; + //============================================================================ // base class class LLPrivateMemoryPool; @@ -125,13 +128,22 @@ public: static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; + static std::list<U32> sAvailableVAOName; + static U32 sCurVAOName; + static bool sUseStreamDraw; static bool sUseVAO; static bool sPreferStreamDraw; + static void seedPools(); + + static U32 getVAOName(); + static void releaseVAOName(U32 name); + static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); + static void pushPositions(U32 mode, const LLVector4a* pos, U32 count); static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); @@ -208,7 +220,6 @@ protected: void destroyGLIndices(); void updateNumVerts(S32 nverts); void updateNumIndices(S32 nindices); - bool useVBOs() const; void unmapBuffer(); public: @@ -218,6 +229,8 @@ public: volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); + // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 void flush(); //flush pending data to GL memory @@ -240,12 +253,14 @@ public: bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool useVBOs() const; bool isEmpty() const { return mEmpty; } bool isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 7aeeae298f..104481cbfc 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -280,12 +280,23 @@ bool LLTextBase::truncate() if (getLength() >= S32(mMaxTextByteLength / 4)) { // Have to check actual byte size - LLWString text(getWText()); - S32 utf8_byte_size = wstring_utf8_length(text); + S32 utf8_byte_size = 0; + LLSD value = getViewModel()->getValue(); + if (value.type() == LLSD::TypeString) + { + // save a copy for strings. + utf8_byte_size = value.size(); + } + else + { + // non string LLSDs need explicit conversion to string + utf8_byte_size = value.asString().size(); + } + if ( utf8_byte_size > mMaxTextByteLength ) { // Truncate safely in UTF-8 - std::string temp_utf8_text = wstring_to_utf8str(text); + std::string temp_utf8_text = value.asString(); temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength ); LLWString text = utf8str_to_wstring( temp_utf8_text ); // remove extra bit of current string, to preserve formatting, etc. @@ -592,8 +603,7 @@ void LLTextBase::drawText() S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments ) { - LLWString text(getWText()); - S32 old_len = text.length(); // length() returns character length + S32 old_len = getLength(); // length() returns character length S32 insert_len = wstr.length(); pos = getEditableIndex(pos, true); @@ -653,8 +663,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } } - text.insert(pos, wstr); - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay().insert(pos, wstr); if ( truncate() ) { @@ -669,7 +678,6 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) { - LLWString text(getWText()); segment_set_t::iterator seg_iter = getSegIterContaining(pos); while(seg_iter != mSegments.end()) { @@ -715,8 +723,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) ++seg_iter; } - text.erase(pos, length); - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay().erase(pos, length); // recreate default segment in case we erased everything createDefaultSegment(); @@ -733,9 +740,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc) { return 0; } - LLWString text(getWText()); - text[pos] = wc; - getViewModel()->setDisplay(text); + getViewModel()->getEditableDisplay()[pos] = wc; onValueChange(pos, pos + 1); needsReflow(pos); @@ -1685,6 +1690,8 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name) } } +static LLFastTimer::DeclareTimer FTM_PARSE_HTML("Parse HTML"); + void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) { LLStyle::Params style_params(input_params); @@ -1693,6 +1700,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para S32 part = (S32)LLTextParser::WHOLE; if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). { + LLFastTimer _(FTM_PARSE_HTML); S32 start=0,end=0; LLUrlMatch match; std::string text = new_text; @@ -1760,8 +1768,11 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } } +static LLFastTimer::DeclareTimer FTM_APPEND_TEXT("Append Text"); + void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) { + LLFastTimer _(FTM_APPEND_TEXT); if (new_text.empty()) return; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 6a905b7ec0..11cfa1d263 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -150,7 +150,7 @@ S32 LLTextBox::getTextPixelHeight() LLSD LLTextBox::getValue() const { - return LLSD(getText()); + return getViewModel()->getValue(); } BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text ) diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b5e27616b7..87bf518aa1 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -831,7 +831,11 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL gGL.flush(); glLineWidth(2.5f); - glLineStipple(2, 0x3333 << shift); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(2, 0x3333 << shift); + } gGL.begin(LLRender::LINES); { diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 763af5d8a2..ef2e314799 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -102,6 +102,7 @@ public: // New functions /// Get the stored value in string form const LLWString& getDisplay() const { return mDisplay; } + LLWString& getEditableDisplay() { mDirty = true; mUpdateFromDisplay = true; return mDisplay; } /** * Set the display string directly (see LLTextEditor). What the user is diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e07fbddb94..6f0d90be06 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -367,6 +367,10 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags) { + + //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways + LoadLibrary(L"opengl32.dll"); + mFSAASamples = fsaa_samples; mIconResource = gIconResource; mOverrideAspectRatio = 0.f; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c9b4de0140..1928e53699 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -148,7 +148,7 @@ <key>Value</key> <integer>1</integer> </map> - <key>ApplyTextureImmediately</key> + <key>TextureLivePreview</key> <map> <key>Comment</key> <string>Preview selections in texture picker immediately</string> @@ -7274,7 +7274,7 @@ <key>WebContentWindowLimit</key> <map> <key>Comment</key> - <string>Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit)</string> + <string>Maximum number of web browser windows that can be open at once in the Web content floater (0 for no limit)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -8093,6 +8093,18 @@ <real>0</real> </map> + <key>RenderDepthPrePass</key> + <map> + <key>Comment</key> + <string>EXPERIMENTAL: Prime the depth buffer with simple prim geometry before rendering with textures.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDepthOfField</key> <map> <key>Comment</key> @@ -9172,7 +9184,7 @@ <key>RenderUseVAO</key> <map> <key>Comment</key> - <string>Use GL Vertex Array Objects</string> + <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -9180,7 +9192,19 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderVBOMappingDisable</key> + <key>RenderUseTransformFeedback</key> + <map> + <key>Comment</key> + <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderVBOMappingDisable</key> <map> <key>Comment</key> <string>Disable VBO glMapBufferARB</string> @@ -12227,6 +12251,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderSynchronousOcclusion</key> + <map> + <key>Comment</key> + <string>Don't let occlusion queries get more than one frame behind (block until they complete).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderDelayVBUpdate</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl index cb87b754b4..1113a9845b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif +uniform float minimum_alpha; + uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; @@ -70,9 +72,15 @@ void main() 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); diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 75de47614c..bff87cb6aa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -55,8 +55,6 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; uniform vec3 center; uniform vec3 color; @@ -143,7 +141,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0, norm.z); norm = normalize(norm); float l_dist = -dot(lv, proj_n); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 19800a8b8e..f671d5b750 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -42,12 +42,13 @@ uniform sampler2DRect depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; -uniform vec3 center; uniform vec3 color; uniform float falloff; uniform float size; VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; + uniform vec2 screen_res; uniform mat4 inv_proj; @@ -74,7 +75,7 @@ void main() frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = center.xyz-pos; + vec3 lv = trans_center.xyz-pos; float dist2 = dot(lv,lv); dist2 /= size; if (dist2 > 1.0) diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index cb14e6d4e8..9491421236 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -24,16 +24,22 @@ */ uniform mat4 modelview_projection_matrix; +uniform mat4 modelview_matrix; ATTRIBUTE vec3 position; +uniform vec3 center; +uniform float size; + VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; void main() { //transform vertex - vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0); + vec3 p = position*sqrt(size)+center; + vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0); vary_fragcoord = pos; - + trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz; gl_Position = pos; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl new file mode 100644 index 0000000000..6195e2f1ec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl @@ -0,0 +1,44 @@ +/** + * @file shadowCubeV.glsl + * + * $LicenseInfo:firstyear=2011&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 modelview_projection_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec4 post_pos; + +uniform vec3 box_center; +uniform vec3 box_size; + +void main() +{ + //transform vertex + vec3 p = position*box_size+box_center; + vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0); + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 7ed8ed3370..cca63872de 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -24,18 +24,21 @@ */ -#extension GL_ARB_texture_rectangle : enable - #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else #define frag_color gl_FragColor #endif +//class 1 -- no shadows + +#extension GL_ARB_texture_rectangle : enable + uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; uniform sampler2D noiseMap; uniform sampler2D projectionMap; @@ -46,6 +49,7 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; @@ -53,19 +57,66 @@ uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; -uniform vec3 center; uniform vec3 color; uniform float falloff; uniform float size; VARYING vec4 vary_fragcoord; +VARYING vec3 trans_center; + uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -84,16 +135,16 @@ void main() frag.xy *= screen_res; vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = center.xyz-pos.xyz; + vec3 lv = trans_center.xyz-pos.xyz; float dist2 = dot(lv,lv); dist2 /= size; if (dist2 > 1.0) { discard; } - + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + norm = vec3((norm.xy-0.5)*2.0, norm.z); norm = normalize(norm); float l_dist = -dot(lv, proj_n); @@ -107,7 +158,11 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = falloff+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -125,32 +180,32 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex; + amb_da += (da*0.5)*proj_ambiance; } - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - + col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -168,18 +223,22 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb; } } diff --git a/indra/newview/app_settings/shaders/class1/interface/clipF.glsl b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl new file mode 100644 index 0000000000..ac2bc8703b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipF.glsl @@ -0,0 +1,46 @@ +/** + * @file debugF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform vec4 color; +uniform vec4 clip_plane; + +VARYING vec3 vary_position; + + +void main() +{ + if (dot(vary_position,clip_plane.xyz)+clip_plane.w < 0.0) + { + discard; + } + + frag_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/interface/clipV.glsl b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl new file mode 100644 index 0000000000..e376b25a71 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/clipV.glsl @@ -0,0 +1,38 @@ +/** + * @file debugV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 modelview_projection_matrix; +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_position; + +void main() +{ + vary_position = (modelview_matrix*vec4(position.xyz,1.0)).xyz; + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl new file mode 100644 index 0000000000..5c479d27a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl @@ -0,0 +1,38 @@ +/** + * @file occlusionCubeV.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 modelview_projection_matrix; + +ATTRIBUTE vec3 position; + +uniform vec3 box_center; +uniform vec3 box_size; + +void main() +{ + vec3 p = position*box_size+box_center; + gl_Position = modelview_projection_matrix * vec4(p.xyz, 1.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl new file mode 100644 index 0000000000..44f1aa34a0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/binormalV.glsl @@ -0,0 +1,36 @@ +/** + * @file binormalV.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 mat3 normal_matrix; + +ATTRIBUTE vec3 binormal; + +VARYING vec4 binormal_out; + +void main() +{ + binormal_out = vec4(normal_matrix * binormal, 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/colorV.glsl b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl new file mode 100644 index 0000000000..59c4a7d895 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/colorV.glsl @@ -0,0 +1,36 @@ +/** + * @file colorV.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 int color_in; + +ATTRIBUTE vec3 position; + +VARYING int color_out; + +void main() +{ + color_out = color_in; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/normalV.glsl b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl new file mode 100644 index 0000000000..a213aa0ae8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/normalV.glsl @@ -0,0 +1,36 @@ +/** + * @file normalV.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 mat3 normal_matrix; + +ATTRIBUTE vec3 normal; + +VARYING vec4 normal_out; + +void main() +{ + normal_out = vec4(normalize(normal_matrix * normal), 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/positionV.glsl b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl new file mode 100644 index 0000000000..01eed18de4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl @@ -0,0 +1,40 @@ +/** + * @file positionV.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 modelview_matrix; + +uniform int texture_index_in; + +ATTRIBUTE vec3 position; + +VARYING vec3 position_out; +VARYING int texture_index_out; + +void main() +{ + texture_index_out = texture_index_in; + position_out = (modelview_matrix*vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl new file mode 100644 index 0000000000..0e074f3cec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/transform/texcoordV.glsl @@ -0,0 +1,35 @@ +/** + * @file texcoordV.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$ + */ + + +ATTRIBUTE vec2 texcoord0; + +VARYING vec2 texcoord_out; + +void main() +{ + texcoord_out = texcoord0; +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index ba6f3ace53..2093fc37dc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -31,6 +31,8 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif +uniform float minimum_alpha; + uniform sampler2DRectShadow shadowMap0; uniform sampler2DRectShadow shadowMap1; uniform sampler2DRectShadow shadowMap2; @@ -97,6 +99,13 @@ void main() float shadow = 0.0; vec4 pos = vec4(vary_position, 1.0); + vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); + + if (diff.a < minimum_alpha) + { + discard; + } + vec4 spos = pos; if (spos.z > -shadow_clip.w) @@ -164,8 +173,6 @@ void main() shadow = 1.0; } - vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy); - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, 1.0); vec4 color = diff * col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 99a277fbfc..ab077d9e02 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -31,8 +31,6 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -VARYING vec4 vertex_color; - uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; @@ -49,6 +47,7 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; @@ -58,16 +57,65 @@ uniform float sun_wash; uniform int proj_shadow_idx; uniform float shadow_fade; -VARYING vec4 vary_light; +uniform float size; +uniform vec3 color; +uniform float falloff; +VARYING vec3 trans_center; VARYING vec4 vary_fragcoord; uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -85,6 +133,15 @@ void main() frag.xyz = frag.xyz*0.5+0.5; frag.xy *= screen_res; + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = trans_center.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= size; + if (dist2 > 1.0) + { + discard; + } + float shadow = 1.0; if (proj_shadow_idx >= 0) @@ -96,15 +153,6 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm @@ -119,8 +167,12 @@ void main() proj_tc.xyz /= proj_tc.w; - float fa = vertex_color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float fa = falloff+1.0; + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -138,37 +190,33 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); - vec3 lcol = vertex_color.rgb * plcol.rgb * plcol.a; + vec3 lcol = color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex*shadow; - } - - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - if (da > 0.0) - { amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; } + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - - col += amb_da*vertex_color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + + col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -185,19 +233,23 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*vertex_color.rgb*scol.a*spec.rgb*shadow; + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow; } } } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index e8a109e661..eeb632acaf 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -520,6 +520,7 @@ Disregard128DefaultDrawDistance 1 0 list ATIOldDriver RenderAvatarVP 0 0 RenderAvatarCloth 0 0 +RenderVBOEnable 1 0 // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index 398a64378e..a945f7a693 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -517,6 +517,7 @@ Disregard128DefaultDrawDistance 1 0 list ATIOldDriver RenderAvatarVP 0 0 RenderAvatarCloth 0 0 +RenderVBOEnable 1 0 // ATI cards generally perform better when not using VBOs for streaming data diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ed04b5bf38..062551a3e8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -89,6 +89,7 @@ #include "lllogininstance.h" #include "llprogressview.h" #include "llvocache.h" +#include "llvopartgroup.h" #include "llweb.h" #include "llsecondlifeurls.h" #include "llupdaterservice.h" @@ -675,6 +676,9 @@ bool LLAppViewer::init() // initialize SSE options LLVector4a::initClass(); + //initialize particle index pool + LLVOPartGroup::initClass(); + // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -1162,6 +1166,8 @@ void LLAppViewer::checkMemory() static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); +static LLFastTimer::DeclareTimer FTM_YIELD("Yield"); + static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache"); static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode"); static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread"); @@ -1347,6 +1353,7 @@ bool LLAppViewer::mainLoop() // yield some time to the os based on command line option if(mYieldTime >= 0) { + LLFastTimer t(FTM_YIELD); ms_sleep(mYieldTime); } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f530d10ddc..84e73e96fa 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -495,7 +495,7 @@ protected: void showInfoCtrl() { - if (mAvatarID.isNull() || mFrom.empty() || SYSTEM_FROM == mFrom) return; + if (mAvatarID.isNull() || mFrom.empty() || CHAT_SOURCE_SYSTEM == mSourceType) return; if (!sInfoCtrl) { @@ -689,8 +689,11 @@ void LLChatHistory::clear() mLastFromID = LLUUID::null; } +static LLFastTimer::DeclareTimer FTM_APPEND_MESSAGE("Append Chat Message"); + void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params) { + LLFastTimer _(FTM_APPEND_MESSAGE); bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); llassert(mEditor); @@ -783,7 +786,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL timestamp_style.color(timestamp_color); timestamp_style.readonly_color(timestamp_color); } - mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); + mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getLength() != 0, timestamp_style); if (utf8str_trim(chat.mFromName).size() != 0) { @@ -842,7 +845,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL else { view = getHeader(chat, style_params, args); - if (mEditor->getText().size() == 0) + if (mEditor->getLength() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 21b21c152a..563b9b9cab 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -57,6 +57,8 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +extern bool gShiftFrame; + //////////////////////// // @@ -108,6 +110,8 @@ void LLDrawable::init() mGeneration = -1; mBinRadius = 1.f; + mBinIndex = -1; + mSpatialBridge = NULL; } @@ -450,7 +454,7 @@ void LLDrawable::makeStatic(BOOL warning_enabled) { if (isState(ACTIVE)) { - clearState(ACTIVE); + clearState(ACTIVE | ANIMATED_CHILD); if (mParent.notNull() && mParent->isActive() && warning_enabled) { @@ -538,9 +542,9 @@ F32 LLDrawable::updateXform(BOOL undamped) target_rot = new_rot; target_scale = new_scale; } - else + else if (mVObjp->getAngularVelocity().isExactlyZero()) { - // snap to final position + // snap to final position (only if no target omega is applied) dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild @@ -549,15 +553,25 @@ F32 LLDrawable::updateXform(BOOL undamped) } } - if ((mCurrentScale != target_scale) || - (!isRoot() && - (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || - !mVObjp->getAngularVelocity().isExactlyZero() || - target_pos != mXform.getPosition() || - target_rot != mXform.getRotation()))) - { //child prim moving or scale change requires immediate rebuild + LLVector3 vec = mCurrentScale-target_scale; + + if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) + { //scale change requires immediate rebuild + mCurrentScale = target_scale; gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } + else if (!isRoot() && + (!mVObjp->getAngularVelocity().isExactlyZero() || + dist_squared > 0.f)) + { //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild + dist_squared = 1.f; //keep this object on the move list + if (!isState(LLDrawable::ANIMATED_CHILD)) + { + setState(LLDrawable::ANIMATED_CHILD); + gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); + mVObjp->dirtySpatialGroup(); + } + } else if (!getVOVolume() && !isAvatar()) { movePartition(); @@ -568,9 +582,7 @@ F32 LLDrawable::updateXform(BOOL undamped) mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); - - mCurrentScale = target_scale; - + if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); @@ -596,7 +608,11 @@ void LLDrawable::moveUpdatePipeline(BOOL moved) // Update the face centers. for (S32 i = 0; i < getNumFaces(); i++) { - getFace(i)->updateCenterAgent(); + LLFace* face = getFace(i); + if (face) + { + face->updateCenterAgent(); + } } } @@ -651,7 +667,6 @@ BOOL LLDrawable::updateMoveUndamped() } mVObjp->clearChanged(LLXform::MOVED); - return TRUE; } @@ -703,6 +718,11 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) return; } + if (gShiftFrame) + { + return; + } + //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); @@ -727,7 +747,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); - if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) + if (facep && + (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)) { LLVector4a box; box.setSub(facep->mExtents[1], facep->mExtents[0]); @@ -811,14 +832,19 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) mXform.setPosition(mVObjp->getPositionAgent()); } - mXform.setRotation(mVObjp->getRotation()); - mXform.setScale(1,1,1); mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); - if (!volume) + + bool rebuild = (!volume && + getRenderType() != LLPipeline::RENDER_TYPE_TREE && + getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN && + getRenderType() != LLPipeline::RENDER_TYPE_SKY && + getRenderType() != LLPipeline::RENDER_TYPE_GROUND); + + if (rebuild) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } @@ -826,13 +852,16 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); - facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); - facep->mExtents[0].add(shift_vector); - facep->mExtents[1].add(shift_vector); - - if (!volume && facep->hasGeometry()) + if (facep) { - facep->clearVertexBuffer(); + facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); + facep->mExtents[0].add(shift_vector); + facep->mExtents[1].add(shift_vector); + + if (rebuild && facep->hasGeometry()) + { + facep->clearVertexBuffer(); + } } } @@ -940,6 +969,12 @@ void LLDrawable::updateUVMinMax() { } +LLSpatialGroup* LLDrawable::getSpatialGroup() const +{ + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); + return mSpatialGroupp; +} + void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) @@ -954,11 +989,16 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) for (S32 i = 0; i < getNumFaces(); ++i) { LLFace* facep = getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } mSpatialGroupp = groupp; + + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1081,6 +1121,8 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat mDrawable = root; root->setSpatialBridge(this); + mBinIndex = -1; + mRenderType = mDrawable->mRenderType; mDrawableType = mDrawable->mRenderType; @@ -1384,6 +1426,11 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) markDead(); return; } + + if (gShiftFrame) + { + return; + } if (mDrawable->getVObj()) { @@ -1462,7 +1509,13 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - mDrawable->setSpatialGroup(NULL); + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(mDrawable); + mDrawable->setSpatialGroup(NULL); + } + if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1473,7 +1526,12 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(drawable); + drawable->setSpatialGroup(NULL); + } } } } @@ -1529,10 +1587,10 @@ BOOL LLDrawable::isAnimating() const return TRUE; } - if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) - { + /*if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) + { //target omega return TRUE; - } + }*/ return FALSE; } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index e268640a21..bc4b301ebb 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -109,6 +109,9 @@ public: F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } F32 getBinRadius() const { return mBinRadius; } + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 index) const { mBinIndex = index; } + void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } LLXformMatrix* getXform() { return &mXform; } @@ -194,7 +197,7 @@ public: S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... void setSpatialGroup(LLSpatialGroup *groupp); - LLSpatialGroup *getSpatialGroup() const { return mSpatialGroupp; } + LLSpatialGroup *getSpatialGroup() const; LLSpatialPartition* getSpatialPartition(); // Statics @@ -277,6 +280,7 @@ public: HAS_ALPHA = 0x04000000, RIGGED = 0x08000000, PARTITION_MOVE = 0x10000000, + ANIMATED_CHILD = 0x20000000, } EDrawableFlags; private: //aligned members @@ -314,6 +318,7 @@ private: mutable U32 mVisible; F32 mRadius; F32 mBinRadius; + mutable S32 mBinIndex; S32 mGeneration; LLVector3 mCurrentScale; @@ -333,12 +338,14 @@ inline LLFace* LLDrawable::getFace(const S32 i) const if ((U32) i >= mFaces.size()) { - llerrs << "Invalid face index." << llendl; + llwarns << "Invalid face index." << llendl; + return NULL; } if (!mFaces[i]) { - llerrs << "Null face found." << llendl; + llwarns << "Null face found." << llendl; + return NULL; } return mFaces[i]; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 35f8a85796..6c0be0a5c2 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -253,48 +253,6 @@ void LLFacePool::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures { } -// static -S32 LLFacePool::drawLoop(face_array_t& face_list) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector<LLFace*>::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - res += facep->renderIndexed(); - } - } - return res; -} - -// static -S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector<LLFace*>::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ; - gGL.getTexUnit(0)->activate(); - res += facep->renderIndexed(); - } - } - return res; -} - -void LLFacePool::drawLoop() -{ - if (!mDrawFace.empty()) - { - drawLoop(mDrawFace); - } -} - void LLFacePool::enqueue(LLFace* facep) { mDrawFace.push_back(facep); @@ -442,7 +400,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask) void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { - for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 64774d06df..e0f2da41d7 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -186,10 +186,6 @@ public: void buildEdges(); - static S32 drawLoop(face_array_t& face_list); - static S32 drawLoopSetTex(face_array_t& face_list, S32 stage); - void drawLoop(); - void addFaceReference(LLFace *facep); void removeFaceReference(LLFace *facep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b62dbc560..313b310e1e 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -348,7 +348,7 @@ void LLDrawPoolAlpha::render(S32 pass) void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; if (group->mSpatialPartition->mRenderByGroup && @@ -385,7 +385,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) BOOL use_shaders = gPipeline.canUseVertexShaders(); - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; llassert(group); @@ -405,6 +405,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { LLDrawInfo& params = **k; + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + llwarns << "Missing required components, skipping render batch." << llendl; + continue; + } + LLRenderPass::applyModelMatrix(params); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 0103373fd2..730ad1a364 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -261,7 +261,9 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() sRenderingSkinned = TRUE; gPipeline.bindDeferredShader(*sVertexProgram); - + + sVertexProgram->setMinimumAlpha(0.2f); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } @@ -1034,9 +1036,13 @@ void LLDrawPoolAvatar::endDeferredSkinned() gGL.getTexUnit(0)->activate(); } +static LLFastTimer::DeclareTimer FTM_RENDER_AVATARS("renderAvatars"); + void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { + LLFastTimer t(FTM_RENDER_AVATARS); + if (pass == -1) { for (S32 i = 1; i < getNumPasses(); i++) @@ -1193,15 +1199,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass >= 7 && pass < 9) { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - if (pass == 7) { renderRiggedAlpha(avatarp); @@ -1217,20 +1214,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 9) { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - renderRiggedGlow(avatarp); - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; } @@ -1428,7 +1413,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled()) + if (avatar->isSelf() && !gAgent.needsRenderAvatar()) { return; } @@ -1557,8 +1542,12 @@ void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) renderRigged(avatar, RIGGED_DEFERRED_BUMP); } +static LLFastTimer::DeclareTimer FTM_RIGGED_VBO("Rigged VBO"); + void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) { + LLFastTimer t(FTM_RIGGED_VBO); + //update rigged vertex buffers for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type) { @@ -1630,17 +1619,56 @@ void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_ALPHA); + if (!mRiggedFace[RIGGED_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_GLOW, true); + if (!mRiggedFace[RIGGED_GLOW].empty()) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRigged(avatar, RIGGED_GLOW, true); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6f71e6ebc8..a264eae302 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -847,12 +847,12 @@ void LLDrawPoolBump::renderDeferred(S32 pass) LLFastTimer ftm(FTM_RENDER_BUMP); U32 type = LLRenderPass::PASS_BUMP; - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; @@ -1448,10 +1448,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI void LLDrawPoolBump::renderBump(U32 type, U32 mask) { - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b95d8296fa..7fc78fb382 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -294,6 +294,34 @@ void LLDrawPoolTerrain::renderShadow(S32 pass) //glCullFace(GL_BACK); } + +void LLDrawPoolTerrain::drawLoop() +{ + if (!mDrawFace.empty()) + { + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; + + LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + + facep->renderIndexed(); + } + } +} + void LLDrawPoolTerrain::renderFullShader() { // Hack! Get the region that this draw pool is rendering from! diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 283ed87f1a..2163d087e1 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -83,6 +83,7 @@ protected: void renderFull2TU(); void renderFull4TU(); void renderFullShader(); + void drawLoop(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 3165a3516c..83f04e45a8 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -37,6 +37,7 @@ #include "llviewershadermgr.h" #include "llrender.h" #include "llviewercontrol.h" +#include "llviewerregion.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -104,8 +105,22 @@ void LLDrawPoolTree::render(S32 pass) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); + if(buff) { + LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 64eb11fc9b..885cae1737 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -155,6 +155,7 @@ LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : mAvatarp(avatarp), mWearablep(NULL) { + mDefaultVec.clear(); } LLDriverParam::LLDriverParam(LLWearable *wearablep) : @@ -162,6 +163,7 @@ LLDriverParam::LLDriverParam(LLWearable *wearablep) : mAvatarp(NULL), mWearablep(wearablep) { + mDefaultVec.clear(); } LLDriverParam::~LLDriverParam() @@ -341,18 +343,19 @@ F32 LLDriverParam::getTotalDistortion() return sum; } -const LLVector3 &LLDriverParam::getAvgDistortion() +const LLVector4a &LLDriverParam::getAvgDistortion() { // It's not actually correct to take the average of averages, but it good enough here. - LLVector3 sum; + LLVector4a sum; + sum.clear(); S32 count = 0; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getAvgDistortion(); + sum.add(driven->mParam->getAvgDistortion()); count++; } - sum /= (F32)count; + sum.mul( 1.f/(F32)count); mDefaultVec = sum; return mDefaultVec; @@ -375,21 +378,22 @@ F32 LLDriverParam::getMaxDistortion() } -LLVector3 LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) +LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { - LLVector3 sum; + LLVector4a sum; + sum.clear(); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getVertexDistortion( index, poly_mesh ); + sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); } return sum; } -const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { mCurrentDistortionParam = NULL; - const LLVector3* v = NULL; + const LLVector4a* v = NULL; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); @@ -404,7 +408,7 @@ const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly return v; }; -const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { llassert( mCurrentDistortionParam ); if( !mCurrentDistortionParam ) @@ -432,7 +436,7 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ } // We're already in the middle of a param's distortions, so get the next one. - const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh ); + const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); if( (!v) && (iter != mDriven.end()) ) { // This param is finished, so start the next param. It might not have any diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index fb1b44458c..7a4d711d4e 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -105,18 +105,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); - LLVector3 mDefaultVec; // temp holder + LLVector4a mDefaultVec; // temp holder typedef std::vector<LLDrivenEntry> entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4108d69e82..f5b217d539 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -44,11 +44,14 @@ #include "llsky.h" #include "llviewercamera.h" #include "llviewertexturelist.h" +#include "llvopartgroup.h" #include "llvosky.h" #include "llvovolume.h" #include "pipeline.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llviewershadermgr.h" + #define LL_MAX_INDICES_COUNT 1000000 @@ -56,7 +59,6 @@ BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) - /* For each vertex, given: B - binormal @@ -161,7 +163,10 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomCount = 0; mGeomIndex = 0; mIndicesCount = 0; - mIndicesIndex = 0; + + //special value to indicate uninitialized position + mIndicesIndex = 0xFFFFFFFF; + mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; @@ -177,12 +182,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mFaceColor = LLColor4(1,0,0,1); - mLastVertexBuffer = mVertexBuffer; - mLastGeomCount = mGeomCount; - mLastGeomIndex = mGeomIndex; - mLastIndicesCount = mIndicesCount; - mLastIndicesIndex = mIndicesIndex; - mImportanceToCamera = 0.f ; mBoundingSphereRadius = 0.0f ; @@ -203,6 +202,12 @@ void LLFace::destroy() mTexture->removeFace(this) ; } + if (isState(LLFace::PARTICLE)) + { + LLVOPartGroup::freeVBSlot(getGeomIndex()/4); + clearState(LLFace::PARTICLE); + } + if (mDrawPoolp) { if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) @@ -372,7 +377,6 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align) mGeomCount = num_vertices; mIndicesCount = num_indices; mVertexBuffer = NULL; - mLastVertexBuffer = NULL; } llassert(verify()); @@ -765,12 +769,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, LLMatrix4a mat_normal; mat_normal.loadu(mat_normal_in); - //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - //{ //vertex buffer no longer valid - // mVertexBuffer = NULL; - // mLastVertexBuffer = NULL; - //} - //VECTORIZE THIS LLVector4a min,max; @@ -1032,30 +1030,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs void LLFace::updateRebuildFlags() { - if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - BOOL moved = TRUE; - if (mLastVertexBuffer == mVertexBuffer && - !mVertexBuffer->isEmpty()) - { //this face really doesn't need to be regenerated, try real hard not to do so - if (mLastGeomCount == mGeomCount && - mLastGeomIndex == mGeomIndex && - mLastIndicesCount == mIndicesCount && - mLastIndicesIndex == mIndicesIndex) - { //data is in same location in vertex buffer - moved = FALSE; - } - } - mLastMoveTime = gFrameTimeSeconds; - - if (moved) - { - mDrawablep->setState(LLDrawable::REBUILD_VOLUME); - } + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { //this rebuild is zero overhead (direct consequence of some change that affects this face) + mLastUpdateTime = gFrameTimeSeconds; } else - { - mLastUpdateTime = gFrameTimeSeconds; + { //this rebuild is overhead (side effect of some change that does not affect this face) + mLastMoveTime = gFrameTimeSeconds; } } @@ -1094,6 +1075,73 @@ bool LLFace::canRenderAsMask() } +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_VOLUME("Volume VB Cache"); + +//static +void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) +{ + LLFastTimer t(FTM_FACE_GEOM_VOLUME); + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL; + + if (vf.mWeights) + { + mask |= LLVertexBuffer::MAP_WEIGHT4; + } + + LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW_ARB); + vf.mVertexBuffer = buff; + + buff->allocateBuffer(vf.mNumVertices, 0, true); + + LLStrider<LLVector4a> f_vert; + LLStrider<LLVector3> f_binorm; + LLStrider<LLVector3> f_norm; + LLStrider<LLVector2> f_tc; + + buff->getBinormalStrider(f_binorm); + buff->getVertexStrider(f_vert); + buff->getNormalStrider(f_norm); + buff->getTexCoord0Strider(f_tc); + + for (U32 i = 0; i < vf.mNumVertices; ++i) + { + *f_vert++ = vf.mPositions[i]; + (*f_binorm++).set(vf.mBinormals[i].getF32ptr()); + *f_tc++ = vf.mTexCoords[i]; + (*f_norm++).set(vf.mNormals[i].getF32ptr()); + } + + if (vf.mWeights) + { + LLStrider<LLVector4> f_wght; + buff->getWeight4Strider(f_wght); + for (U32 i = 0; i < vf.mNumVertices; ++i) + { + (*f_wght++).set(vf.mWeights[i].getF32ptr()); + } + } + + buff->flush(); +} + +//helper function for pushing primitives for transform shaders and cleaning up +//uninitialized data on the tail, plus tracking number of expected primitives +void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) +{ + if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping + { + //push source primitives + buff->drawArrays(LLRender::POINTS, 0, source_count); + U32 tail = dest_count-source_count; + for (U32 i = 0; i < tail; ++i) + { //copy last source primitive into each element in tail + buff->drawArrays(LLRender::POINTS, source_count-1, 1); + } + gPipeline.mTransformFeedbackPrimitives += dest_count; + } +} + static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position"); static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal"); @@ -1111,7 +1159,6 @@ static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); - static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); BOOL LLFace::getGeometryVolume(const LLVolume& volume, @@ -1139,21 +1186,25 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { - llwarns << "Index buffer overflow!" << llendl; - llwarns << "Indices Count: " << mIndicesCount - << " VF Num Indices: " << num_indices - << " Indices Index: " << mIndicesIndex - << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; - llwarns << "Last Indices Count: " << mLastIndicesCount - << " Last Indices Index: " << mLastIndicesIndex - << " Face Index: " << f - << " Pool Type: " << mPoolType << llendl; + if (gDebugGL) + { + llwarns << "Index buffer overflow!" << llendl; + llwarns << "Indices Count: " << mIndicesCount + << " VF Num Indices: " << num_indices + << " Indices Index: " << mIndicesIndex + << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; + llwarns << " Face Index: " << f + << " Pool Type: " << mPoolType << llendl; + } return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { - llwarns << "Vertex buffer overflow!" << llendl; + if (gDebugGL) + { + llwarns << "Vertex buffer overflow!" << llendl; + } return FALSE; } } @@ -1284,17 +1335,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLMatrix4a mat_normal; mat_normal.loadu(mat_norm_in); - //if it's not fullbright and has no normals, bake sunlight based on face normal - //bool bake_sunlight = !getTextureEntry()->getFullbright() && - // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; - + bool do_xform = false; if (rebuild_tcoord) { - LLFastTimer t(FTM_FACE_GEOM_TEXTURE); - bool do_xform; - if (tep) { r = tep->getRotation(); @@ -1323,599 +1367,759 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { do_xform = false; } + } + + static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER + if (use_transform_feedback && + gTransformPositionProgram.mProgramObject && //transform shaders are loaded + mVertexBuffer->useVBOs() && //target buffer is in VRAM + !rebuild_weights && //TODO: add support for weights + !volume.isUnique()) //source volume is NOT flexi + { //use transform feedback to pack vertex buffer + + LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + + if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) + { + mVObjp->getVolume()->genBinormals(f); + LLFace::cacheFaceInVRAM(vf); + buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + } + + LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr; + + gGL.pushMatrix(); + gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix); + + if (rebuild_pos) + { + LLFastTimer t(FTM_FACE_GEOM_POSITION); + gTransformPositionProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); + + U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + + S32 val = 0; + U8* vp = (U8*) &val; + vp[0] = index; + vp[1] = 0; + vp[2] = 0; + vp[3] = 0; + + gTransformPositionProgram.uniform1i("texture_index_in", val); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + + push_for_transform(buff, vf.mNumVertices, mGeomCount); + + glEndTransformFeedback(); + } + + if (rebuild_color) + { + LLFastTimer t(FTM_FACE_GEOM_COLOR); + gTransformColorProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); + + S32 val = *((S32*) color.mV); + + gTransformColorProgram.uniform1i("color_in", val); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } + + if (rebuild_emissive) + { + LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); + gTransformColorProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); + + U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + + S32 glow32 = glow | + (glow << 8) | + (glow << 16) | + (glow << 24); + + gTransformColorProgram.uniform1i("color_in", glow32); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } + + if (rebuild_normal) + { + LLFastTimer t(FTM_FACE_GEOM_NORMAL); + gTransformNormalProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); - //bump setup - LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); - LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); - LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_NORMAL); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } - LLQuaternion bump_quat; - if (mDrawablep->isActive()) + if (rebuild_binormal) { - bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); + LLFastTimer t(FTM_FACE_GEOM_BINORMAL); + gTransformBinormalProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); + + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_BINORMAL); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); } - - if (bump_code) + + if (rebuild_tcoord) { - mVObjp->getVolume()->genBinormals(f); - F32 offset_multiple; - switch( bump_code ) - { - case BE_NO_BUMP: - offset_multiple = 0.f; - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - if( mTexture.notNull() && mTexture->hasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture->getDiscardLevel(); - S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; + LLFastTimer t(FTM_FACE_GEOM_TEXTURE); + gTransformTexCoordProgram.bind(); + + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); + + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); - default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) + if (do_bump) { - tep->getScale( &s_scale, &t_scale ); - } - // Use the nudged south when coming from above sun angle, such - // that emboss mapping always shows up on the upward faces of cubes when - // it's noon (since a lot of builders build with the sun forced to noon). - LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; - LLVector3 moon_ray = gSky.getMoonDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - - bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); - bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); + mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount); + glBeginTransformFeedback(GL_POINTS); + buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); + push_for_transform(buff, vf.mNumVertices, mGeomCount); + glEndTransformFeedback(); + } } - U8 texgen = getTextureEntry()->getTexGen(); - if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { //planar texgen needs binormals - mVObjp->getVolume()->genBinormals(f); + glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + + gGL.popMatrix(); + + if (cur_shader) + { + cur_shader->bind(); } + } + else +#endif + { + //if it's not fullbright and has no normals, bake sunlight based on face normal + //bool bake_sunlight = !getTextureEntry()->getFullbright() && + // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - U8 tex_mode = 0; - - if (isState(TEXTURE_ANIM)) + if (rebuild_tcoord) { - LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; - tex_mode = vobj->mTexAnimMode; + LLFastTimer t(FTM_FACE_GEOM_TEXTURE); + + //bump setup + LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); + LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); + LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); - if (!tex_mode) + LLQuaternion bump_quat; + if (mDrawablep->isActive()) { - clearState(TEXTURE_ANIM); + bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); } - else + + if (bump_code) { - os = ot = 0.f; - r = 0.f; - cos_ang = 1.f; - sin_ang = 0.f; - ms = mt = 1.f; + mVObjp->getVolume()->genBinormals(f); + F32 offset_multiple; + switch( bump_code ) + { + case BE_NO_BUMP: + offset_multiple = 0.f; + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + if( mTexture.notNull() && mTexture->hasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture->getDiscardLevel(); + S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; + } + else + { + offset_multiple = 1.f/256; + } + break; - do_xform = false; + default: // Standard bumpmap textures. Assumed to be 256x256 + offset_multiple = 1.f / 256; + break; + } + + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if( tep ) + { + tep->getScale( &s_scale, &t_scale ); + } + // Use the nudged south when coming from above sun angle, such + // that emboss mapping always shows up on the upward faces of cubes when + // it's noon (since a lot of builders build with the sun forced to noon). + LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; + LLVector3 moon_ray = gSky.getMoonDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + + bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); + bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) - { //don't override texture transform during tc bake - tex_mode = 0; + U8 texgen = getTextureEntry()->getTexGen(); + if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { //planar texgen needs binormals + mVObjp->getVolume()->genBinormals(f); } - } - LLVector4a scalea; - scalea.load3(scale.mV); + U8 tex_mode = 0; + + if (isState(TEXTURE_ANIM)) + { + LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; + tex_mode = vobj->mTexAnimMode; + + if (!tex_mode) + { + clearState(TEXTURE_ANIM); + } + else + { + os = ot = 0.f; + r = 0.f; + cos_ang = 1.f; + sin_ang = 0.f; + ms = mt = 1.f; + + do_xform = false; + } - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - bool do_tex_mat = tex_mode && mTextureMatrix; + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + { //don't override texture transform during tc bake + tex_mode = 0; + } + } - if (!in_atlas && !do_bump) - { //not in atlas or not bump mapped, might be able to do a cheap update - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + LLVector4a scalea; + scalea.load3(scale.mV); - if (texgen != LLTextureEntry::TEX_GEN_PLANAR) - { - LLFastTimer t(FTM_FACE_TEX_QUICK); - if (!do_tex_mat) + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); + bool do_tex_mat = tex_mode && mTextureMatrix; + + if (!in_atlas && !do_bump) + { //not in atlas or not bump mapped, might be able to do a cheap update + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + + if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { - if (!do_xform) - { - LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); - } - else + LLFastTimer t(FTM_FACE_TEX_QUICK); + if (!do_tex_mat) { - LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); - F32* dst = (F32*) tex_coords.get(); - LLVector4a* src = (LLVector4a*) vf.mTexCoords; + if (!do_xform) + { + LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + } + else + { + LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); + F32* dst = (F32*) tex_coords.get(); + LLVector4a* src = (LLVector4a*) vf.mTexCoords; - LLVector4a trans; - trans.splat(-0.5f); + LLVector4a trans; + trans.splat(-0.5f); - LLVector4a rot0; - rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + LLVector4a rot0; + rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); - LLVector4a rot1; - rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + LLVector4a rot1; + rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); - LLVector4a scale; - scale.set(ms, mt, ms, mt); + LLVector4a scale; + scale.set(ms, mt, ms, mt); - LLVector4a offset; - offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + LLVector4a offset; + offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); - LLVector4Logical mask; - mask.clear(); - mask.setElement<2>(); - mask.setElement<3>(); + LLVector4Logical mask; + mask.clear(); + mask.setElement<2>(); + mask.setElement<3>(); - U32 count = num_vertices/2 + num_vertices%2; + U32 count = num_vertices/2 + num_vertices%2; - for (S32 i = 0; i < count; i++) + for (S32 i = 0; i < count; i++) + { + LLVector4a res = *src++; + xform4a(res, trans, mask, rot0, rot1, offset, scale); + res.store4a(dst); + dst += 4; + } + } + } + else + { //do tex mat, no texgen, no atlas, no bump + for (S32 i = 0; i < num_vertices; i++) { - LLVector4a res = *src++; - xform4a(res, trans, mask, rot0, rot1, offset, scale); - res.store4a(dst); - dst += 4; + LLVector2 tc(vf.mTexCoords[i]); + //LLVector4a& norm = vf.mNormals[i]; + //LLVector4a& center = *(vf.mCenter); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + *tex_coords++ = tc; } } } else - { //do tex mat, no texgen, no atlas, no bump - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - //LLVector4a& norm = vf.mNormals[i]; - //LLVector4a& center = *(vf.mCenter); - - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; - *tex_coords++ = tc; - } - } - } - else - { //no bump, no atlas, tex gen planar - LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); - if (do_tex_mat) - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); + { //no bump, no atlas, tex gen planar + LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); + if (do_tex_mat) + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; - *tex_coords++ = tc; + *tex_coords++ = tc; + } } - } - else - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - *tex_coords++ = tc; + *tex_coords++ = tc; + } } } - } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - else - { //either bump mapped or in atlas, just do the whole expensive loop - LLFastTimer t(FTM_FACE_TEX_DEFAULT); - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); + else + { //either bump mapped or in atlas, just do the whole expensive loop + LLFastTimer t(FTM_FACE_TEX_DEFAULT); + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); - std::vector<LLVector2> bump_tc; + std::vector<LLVector2> bump_tc; - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; + LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); + LLVector4a& center = *(vf.mCenter); - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector4a vec = vf.mPositions[i]; + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); + vec.mul(scalea); - switch (texgen) + switch (texgen) + { + case LLTextureEntry::TEX_GEN_PLANAR: + planarProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_SPHERICAL: + sphericalProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_CYLINDRICAL: + cylindricalProjection(tc, norm, center, vec); + break; + default: + break; + } + } + + if (tex_mode && mTextureMatrix) { - case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, norm, center, vec); + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + if(in_atlas) + { + // + //manually calculate tex-coord per vertex for varying address modes. + //should be removed if shader can handle this. + // + + S32 int_part = 0 ; + switch(mTexture->getAddressMode()) + { + case LLTexUnit::TAM_CLAMP: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 0.f ; + } + else if(tc.mV[0] > 1.f) + { + tc.mV[0] = 1.f; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 0.f ; + } + else if(tc.mV[1] > 1.f) + { + tc.mV[1] = 1.f; + } break; - case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, norm, center, vec); + case LLTexUnit::TAM_MIRROR: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = -tc.mV[0] ; + } + int_part = (S32)tc.mV[0] ; + if(int_part & 1) //odd number + { + tc.mV[0] = int_part + 1 - tc.mV[0] ; + } + else //even number + { + tc.mV[0] -= int_part ; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = -tc.mV[1] ; + } + int_part = (S32)tc.mV[1] ; + if(int_part & 1) //odd number + { + tc.mV[1] = int_part + 1 - tc.mV[1] ; + } + else //even number + { + tc.mV[1] -= int_part ; + } break; - case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, norm, center, vec); + case LLTexUnit::TAM_WRAP: + if(tc.mV[0] > 1.f) + tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; + else if(tc.mV[0] < -1.f) + tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; + + if(tc.mV[1] > 1.f) + tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; + else if(tc.mV[1] < -1.f) + tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; + + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 1.0f + tc.mV[0] ; + } + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 1.0f + tc.mV[1] ; + } break; default: break; - } - } + } + + tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; + tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; + } + - if (tex_mode && mTextureMatrix) - { - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + *tex_coords++ = tc; + if (do_bump) + { + bump_tc.push_back(tc); + } } - else + + if (map_range) { - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + mVertexBuffer->flush(); } - if(in_atlas) + if (do_bump) { - // - //manually calculate tex-coord per vertex for varying address modes. - //should be removed if shader can handle this. - // - - S32 int_part = 0 ; - switch(mTexture->getAddressMode()) + mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); + + for (S32 i = 0; i < num_vertices; i++) { - case LLTexUnit::TAM_CLAMP: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 0.f ; - } - else if(tc.mV[0] > 1.f) - { - tc.mV[0] = 1.f; - } - - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 0.f ; - } - else if(tc.mV[1] > 1.f) - { - tc.mV[1] = 1.f; - } - break; - case LLTexUnit::TAM_MIRROR: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = -tc.mV[0] ; - } - int_part = (S32)tc.mV[0] ; - if(int_part & 1) //odd number - { - tc.mV[0] = int_part + 1 - tc.mV[0] ; - } - else //even number + LLVector4a tangent; + tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); + + LLMatrix4a tangent_to_object; + tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); + LLVector4a t; + tangent_to_object.rotate(binormal_dir, t); + LLVector4a binormal; + mat_normal.rotate(t, binormal); + + //VECTORIZE THIS + if (mDrawablep->isActive()) { - tc.mV[0] -= int_part ; + LLVector3 t; + t.set(binormal.getF32ptr()); + t *= bump_quat; + binormal.load3(t.mV); } - if(tc.mV[1] < 0.f) - { - tc.mV[1] = -tc.mV[1] ; - } - int_part = (S32)tc.mV[1] ; - if(int_part & 1) //odd number - { - tc.mV[1] = int_part + 1 - tc.mV[1] ; - } - else //even number - { - tc.mV[1] -= int_part ; - } - break; - case LLTexUnit::TAM_WRAP: - if(tc.mV[0] > 1.f) - tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; - else if(tc.mV[0] < -1.f) - tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; - - if(tc.mV[1] > 1.f) - tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; - else if(tc.mV[1] < -1.f) - tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; - - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 1.0f + tc.mV[0] ; - } - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 1.0f + tc.mV[1] ; - } - break; - default: - break; + binormal.normalize3fast(); + LLVector2 tc = bump_tc[i]; + tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); + + *tex_coords2++ = tc; } - - tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; - tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; - } - - *tex_coords++ = tc; - if (do_bump) - { - bump_tc.push_back(tc); - } - } - - if (map_range) - { - mVertexBuffer->flush(); - } - - if (do_bump) - { - mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); - - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a tangent; - tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); - - LLMatrix4a tangent_to_object; - tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); - LLVector4a t; - tangent_to_object.rotate(binormal_dir, t); - LLVector4a binormal; - mat_normal.rotate(t, binormal); - - //VECTORIZE THIS - if (mDrawablep->isActive()) + if (map_range) { - LLVector3 t; - t.set(binormal.getF32ptr()); - t *= bump_quat; - binormal.load3(t.mV); + mVertexBuffer->flush(); } - - binormal.normalize3fast(); - LLVector2 tc = bump_tc[i]; - tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); - - *tex_coords2++ = tc; - } - - if (map_range) - { - mVertexBuffer->flush(); } } } - } - if (rebuild_pos) - { - LLFastTimer t(FTM_FACE_GEOM_POSITION); - llassert(num_vertices > 0); + if (rebuild_pos) + { + LLFastTimer t(FTM_FACE_GEOM_POSITION); + llassert(num_vertices > 0); - mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); + mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - LLMatrix4a mat_vert; - mat_vert.loadu(mat_vert_in); + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); - LLVector4a* src = vf.mPositions; - volatile F32* dst = (volatile F32*) vert.get(); + LLVector4a* src = vf.mPositions; + volatile F32* dst = (volatile F32*) vert.get(); - volatile F32* end = dst+num_vertices*4; - LLVector4a res; + volatile F32* end = dst+num_vertices*4; + LLVector4a res; - LLVector4a texIdx; + LLVector4a texIdx; - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + U8 index = mTextureIndex < 255 ? mTextureIndex : 0; - F32 val = 0.f; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; + F32 val = 0.f; + U8* vp = (U8*) &val; + vp[0] = index; + vp[1] = 0; + vp[2] = 0; + vp[3] = 0; - llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); + llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); - texIdx.set(0,0,0,val); + texIdx.set(0,0,0,val); - { - LLFastTimer t(FTM_FACE_POSITION_STORE); - LLVector4a tmp; - - do - { - mat_vert.affineTransform(*src++, res); - tmp.setSelectWithMask(mask, texIdx, res); - tmp.store4a((F32*) dst); - dst += 4; + { + LLFastTimer t(FTM_FACE_POSITION_STORE); + LLVector4a tmp; + + do + { + mat_vert.affineTransform(*src++, res); + tmp.setSelectWithMask(mask, texIdx, res); + tmp.store4a((F32*) dst); + dst += 4; + } + while(dst < end); } - while(dst < end); - } - { - LLFastTimer t(FTM_FACE_POSITION_PAD); - S32 aligned_pad_vertices = mGeomCount - num_vertices; - res.set(res[0], res[1], res[2], 0.f); + { + LLFastTimer t(FTM_FACE_POSITION_PAD); + S32 aligned_pad_vertices = mGeomCount - num_vertices; + res.set(res[0], res[1], res[2], 0.f); - while (aligned_pad_vertices > 0) + while (aligned_pad_vertices > 0) + { + --aligned_pad_vertices; + res.store4a((F32*) dst); + dst += 4; + } + } + + if (map_range) { - --aligned_pad_vertices; - res.store4a((F32*) dst); - dst += 4; + mVertexBuffer->flush(); } } - if (map_range) - { - mVertexBuffer->flush(); - } - } - if (rebuild_normal) - { - LLFastTimer t(FTM_FACE_GEOM_NORMAL); - mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); - F32* normals = (F32*) norm.get(); + if (rebuild_normal) + { + LLFastTimer t(FTM_FACE_GEOM_NORMAL); + mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); + F32* normals = (F32*) norm.get(); - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a normal; - mat_normal.rotate(vf.mNormals[i], normal); - normal.normalize3fast(); - normal.store4a(normals); - normals += 4; - } + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a normal; + mat_normal.rotate(vf.mNormals[i], normal); + normal.normalize3fast(); + normal.store4a(normals); + normals += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_binormal) - { - LLFastTimer t(FTM_FACE_GEOM_BINORMAL); - mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); - F32* binormals = (F32*) binorm.get(); + if (rebuild_binormal) + { + LLFastTimer t(FTM_FACE_GEOM_BINORMAL); + mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); + F32* binormals = (F32*) binorm.get(); - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a binormal; - mat_normal.rotate(vf.mBinormals[i], binormal); - binormal.normalize3fast(); - binormal.store4a(binormals); - binormals += 4; - } + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a binormal; + mat_normal.rotate(vf.mBinormals[i], binormal); + binormal.normalize3fast(); + binormal.store4a(binormals); + binormals += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_weights && vf.mWeights) - { - LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); - mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); - F32* weights = (F32*) wght.get(); - LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); - if (map_range) + if (rebuild_weights && vf.mWeights) { - mVertexBuffer->flush(); + LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); + mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); + F32* weights = (F32*) wght.get(); + LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) - { - LLFastTimer t(FTM_FACE_GEOM_COLOR); - mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); + if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) + { + LLFastTimer t(FTM_FACE_GEOM_COLOR); + mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); - LLVector4a src; + LLVector4a src; - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; - src.loadua((F32*) vec); + src.loadua((F32*) vec); - F32* dst = (F32*) colors.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } + F32* dst = (F32*) colors.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } - } - if (rebuild_emissive) - { - LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); - LLStrider<LLColor4U> emissive; - mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); + if (rebuild_emissive) + { + LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); + LLStrider<LLColor4U> emissive; + mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); - LLVector4a src; + LLVector4a src; - U32 glow32 = glow | - (glow << 8) | - (glow << 16) | - (glow << 24); + U32 glow32 = glow | + (glow << 8) | + (glow << 16) | + (glow << 24); - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = glow32; + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = glow32; - src.loadua((F32*) vec); + src.loadua((F32*) vec); - F32* dst = (F32*) emissive.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } + F32* dst = (F32*) emissive.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } - if (map_range) - { - mVertexBuffer->flush(); + if (map_range) + { + mVertexBuffer->flush(); + } } } + if (rebuild_tcoord) { mTexExtents[0].setVec(0,0); @@ -1932,12 +2136,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } - mLastVertexBuffer = mVertexBuffer; - mLastGeomCount = mGeomCount; - mLastGeomIndex = mGeomIndex; - mLastIndicesCount = mIndicesCount; - mLastIndicesIndex = mIndicesIndex; - return TRUE; } @@ -2516,7 +2714,6 @@ void LLFace::setVertexBuffer(LLVertexBuffer* buffer) void LLFace::clearVertexBuffer() { mVertexBuffer = NULL; - mLastVertexBuffer = NULL; } //static diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 82e4ab61b7..3babc13c2e 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -79,10 +79,13 @@ public: USE_FACE_COLOR = 0x0010, TEXTURE_ANIM = 0x0020, RIGGED = 0x0040, + PARTICLE = 0x0080, }; static void initClass(); + static void cacheFaceInVRAM(const LLVolumeFace& vf); + public: LLFace(LLDrawable* drawablep, LLViewerObject* objp) { init(drawablep, objp); } ~LLFace() { destroy(); } @@ -222,7 +225,7 @@ public: //vertex buffer tracking void setVertexBuffer(LLVertexBuffer* buffer); - void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL + void clearVertexBuffer(); //sets mVertexBuffer to NULL LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } U32 getRiggedVertexBufferDataMask() const; S32 getRiggedIndex(U32 type) const; @@ -255,8 +258,7 @@ public: private: LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mLastVertexBuffer; - + U32 mState; LLFacePool* mDrawPoolp; U32 mPoolType; @@ -269,12 +271,6 @@ private: U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) S32 mIndexInTex ; - //previous rebuild's geometry info - U16 mLastGeomCount; - U16 mLastGeomIndex; - U32 mLastIndicesCount; - U32 mLastIndicesIndex; - LLXformMatrix* mXform; LLPointer<LLViewerTexture> mTexture; LLPointer<LLDrawable> mDrawablep; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 575b613ccf..4cbc9cab4a 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1191,7 +1191,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) } else if (action == "paste") { - pastFromClipboard(); + pasteFromClipboard(); } else if (action == "delete") { @@ -1239,7 +1239,7 @@ BOOL LLFavoritesBarCtrl::isClipboardPasteable() const return TRUE; } -void LLFavoritesBarCtrl::pastFromClipboard() const +void LLFavoritesBarCtrl::pasteFromClipboard() const { LLInventoryModel* model = &gInventory; if(model && isClipboardPasteable()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2f75b3bb0e..447d30f1f4 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -90,7 +90,7 @@ protected: bool enableSelected(const LLSD& userdata); void doToSelected(const LLSD& userdata); BOOL isClipboardPasteable() const; - void pastFromClipboard() const; + void pasteFromClipboard() const; void showDropDownMenu(); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 32a533570a..c4dca4cb79 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -65,7 +65,7 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD mFrameNum = 0; mCollisionSphereRadius = 0.f; mRenderRes = 1; - + if(mVO->mDrawable.notNull()) { mVO->mDrawable->makeActive() ; @@ -255,50 +255,28 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons { } -//--------------------------------------------------------------------------------- -// This calculates the physics of the flexible object. Note that it has to be 0 -// updated every time step. In the future, perhaps there could be an -// optimization similar to what Havok does for objects that are stationary. -//--------------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); -BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - if (mVO->mDrawable.isNull()) - { - // Don't do anything until we have a drawable - return FALSE; // (we are not initialized or updated) - } - - BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; - //flexible objects never go static - mVO->mDrawable->mQuietCount = 0; - if (!mVO->mDrawable->isRoot()) - { - LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); - parent->mDrawable->mQuietCount = 0; - } +void LLVolumeImplFlexible::updateRenderRes() +{ + LLDrawable* drawablep = mVO->mDrawable; - LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - S32 new_res = mAttributes->getSimulateLOD(); - //number of segments only cares about z axis - F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); +#if 1 //optimal approximation of previous behavior that doesn't rely on atan2 + F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera; // Rendering sections increases with visible angle on the screen - mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView()); - if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS) - { - mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS; - } - + mRenderRes = (S32) (12.f*app_angle); +#else //legacy behavior + //number of segments only cares about z axis + F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - // Bottom cap at 1/4 the original number of sections - if (mRenderRes < mAttributes->getSimulateLOD()-1) - { - mRenderRes = mAttributes->getSimulateLOD()-1; - } + // Rendering sections increases with visible angle on the screen + mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView()); +#endif + + mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS); + // Throttle back simulation of segments we're not rendering if (mRenderRes < new_res) { @@ -311,43 +289,65 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 setAttributesOfAllSections(); mInitialized = TRUE; } - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) - { - return FALSE; // (we are not initialized or updated) - } - - bool visible = mVO->mDrawable->isVisible(); +} +//--------------------------------------------------------------------------------- +// This calculates the physics of the flexible object. Note that it has to be 0 +// updated every time step. In the future, perhaps there could be an +// optimization similar to what Havok does for objects that are stationary. +//--------------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); +void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + LLDrawable* drawablep = mVO->mDrawable; - if (force_update && visible) + if (drawablep) { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); - } - else if (visible && - !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) && - mVO->getPixelArea() > 256.f) - { - U32 id; - F32 pixel_area = mVO->getPixelArea(); + //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - if (mVO->isRootEdit()) + //flexible objects never go static + drawablep->mQuietCount = 0; + if (!drawablep->isRoot()) { - id = mID; + LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); + parent->mDrawable->mQuietCount = 0; } - else + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { - LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); - id = parent->getVolumeInterfaceID(); - } + bool visible = drawablep->isVisible(); - U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + if ((mSimulateRes == 0) && visible) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + else if (visible && + !drawablep->isState(LLDrawable::IN_REBUILD_Q1) && + mVO->getPixelArea() > 256.f) + { + U32 id; + F32 pixel_area = mVO->getPixelArea(); - if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) - { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); + if (mVO->isRootEdit()) + { + id = mID; + } + else + { + LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); + id = parent->getVolumeInterfaceID(); + } + + U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + + if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + } } } - - return force_update; } inline S32 log2(S32 x) @@ -368,8 +368,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - mVO->markForUpdate(TRUE); - if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0)) + //mVO->markForUpdate(TRUE); + doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0); + + if (mSimulateRes == 0) { return; // we did not get updated or initialized, proceeding without can be dangerous } @@ -729,7 +731,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) else if (!mUpdated || rotated) { volume->mDrawable->setState(LLDrawable::REBUILD_POSITION); - volume->dirtyMesh(); + LLSpatialGroup* group = volume->mDrawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } volume->genBBoxes(isVolumeGlobal()); } @@ -814,15 +820,17 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation() }//------------------------------------------------------------------ -void LLVolumeImplFlexible::updateRelativeXform() +void LLVolumeImplFlexible::updateRelativeXform(bool force_identity) { LLQuaternion delta_rot; LLVector3 delta_pos, delta_scale; LLVOVolume* vo = (LLVOVolume*) mVO; + bool use_identity = vo->mDrawable->isSpatialRoot() || force_identity; + //matrix from local space to parent relative/global space - delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation(); - delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); + delta_rot = use_identity ? LLQuaternion() : vo->mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); delta_scale = LLVector3(1,1,1); // Vertex transform (4x4) diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index fef43d464d..56d579d86f 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -78,7 +78,8 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVector3 getFramePosition() const; LLQuaternion getFrameRotation() const; LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; } - BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void updateRenderRes(); + void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); BOOL doUpdateGeometry(LLDrawable *drawable); LLVector3 getPivotPosition() const; void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); @@ -89,7 +90,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface bool isVolumeGlobal() const { return true; } bool isActive() const { return true; } const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; - void updateRelativeXform(); + void updateRelativeXform(bool force_identity); void doFlexibleUpdate(); // Called to update the simulation void doFlexibleRebuild(); // Called to rebuild the geometry void preRebuild(); @@ -128,7 +129,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVector3 mCollisionSpherePosition; F32 mCollisionSphereRadius; U32 mID; - + //-------------------------------------- // private methods //-------------------------------------- diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index bca4b5e447..809d344d01 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -211,8 +211,8 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, BOOL item_is_multi = FALSE; if ((inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED - || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) - && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) + || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) + && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) { item_is_multi = TRUE; } diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index ac33a05f42..fa0ad20fdb 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1124,9 +1124,13 @@ BOOL LLPreviewAnimation::render() LLVertexBuffer::unbind(); LLGLDepthTest gls_depth(GL_TRUE); - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - avatarp->dirtyMesh(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar + LLFace* face = avatarp->mDrawable->getFace(0); + if (face) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); + avatarp->dirtyMesh(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } } gGL.color4f(1,1,1,1); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 92ee8ddac6..6b2492d927 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -704,9 +704,13 @@ BOOL LLImagePreviewAvatar::render() // make sure alpha=0 shows avatar material color LLGLDisable no_blend(GL_BLEND); - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - gPipeline.enableLightsPreview(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar + LLFace* face = avatarp->mDrawable->getFace(0); + if (face) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); + gPipeline.enableLightsPreview(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } } gGL.popUIMatrix(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index ee18c95b34..cc7c9a5bda 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1901,6 +1901,7 @@ BOOL LLPanelLandOptions::postBuild() mSnapshotCtrl->setCommitCallback( onCommitAny, this ); mSnapshotCtrl->setAllowNoTexture ( TRUE ); mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mSnapshotCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); } else @@ -2226,8 +2227,8 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) BOOL allow_damage = !self->mCheckSafe->get(); BOOL allow_fly = self->mCheckFly->get(); BOOL allow_landmark = TRUE; // cannot restrict landmark creation - BOOL allow_group_scripts = self->mCheckGroupScripts->get() || self->mCheckOtherScripts->get(); BOOL allow_other_scripts = self->mCheckOtherScripts->get(); + BOOL allow_group_scripts = self->mCheckGroupScripts->get() || allow_other_scripts; BOOL allow_publish = FALSE; BOOL mature_publish = self->mMatureCtrl->get(); BOOL push_restriction = self->mPushRestrictionCtrl->get(); @@ -2240,11 +2241,16 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerRegion* region; region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (!allow_other_scripts && region && region->getAllowDamage()) - { - - LLNotificationsUtil::add("UnableToDisableOutsideScripts"); - return; + if (region && region->getAllowDamage()) + { // Damage is allowed on the region - server will always allow scripts + if ( (!allow_other_scripts && parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)) || + (!allow_group_scripts && parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)) ) + { // Don't allow turning off "Run Scripts" if damage is allowed in the region + self->mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)); // Restore UI to actual settings + self->mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)); + LLNotificationsUtil::add("UnableToDisableOutsideScripts"); + return; + } } // Push data into current parcel diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7448f2bb2a..40d2157e28 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -396,7 +396,6 @@ mCalculateBtn(NULL) sInstance = this; mLastMouseX = 0; mLastMouseY = 0; - mGLName = 0; mStatusLock = new LLMutex(NULL); mModelPreview = NULL; @@ -538,11 +537,6 @@ LLFloaterModelPreview::~LLFloaterModelPreview() delete mModelPreview; } - if (mGLName) - { - LLImageGL::deleteTextures(1, &mGLName ); - } - delete mStatusLock; mStatusLock = NULL; } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 64324854a5..981f9b0f72 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -256,7 +256,6 @@ protected: S32 mLastMouseX; S32 mLastMouseY; LLRect mPreviewRect; - U32 mGLName; static S32 sUploadAmount; std::set<LLPointer<DecompRequest> > mCurRequest; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1fa194ab19..0965b7b533 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -2236,12 +2236,16 @@ void LLFolderView::doIdle() arrangeAll(); } + mNeedsAutoSelect = mFilter->hasFilterString() && + !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); + + if (mFilter->isModified() && mFilter->isNotDefault()) { mNeedsAutoSelect = TRUE; } mFilter->clearModified(); - + // filter to determine visibility before arranging filterFromRoot(); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 8092f3bf36..6e23d7c701 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -822,6 +822,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) { parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); new_item->setParent(parent_id); + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate new_folder(parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + } item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 3a88fbd96d..f8088d04b4 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -60,6 +60,7 @@ #include "llworld.h" #include "llui.h" #include "pipeline.h" +#include "llviewershadermgr.h" const S32 NUM_AXES = 3; const S32 MOUSE_DRAG_SLOP = 2; // pixels @@ -1580,7 +1581,11 @@ void LLManipTranslate::renderSnapGuides() LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); LLGLEnable stipple(GL_LINE_STIPPLE); gGL.flush(); - glLineStipple(1, 0x3333); + + if (!LLGLSLShader::sNoFixedFunction) + { + glLineStipple(1, 0x3333); + } switch (mManipPart) { @@ -1645,17 +1650,28 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, LLQuaternion grid_rotation, LLColor4 inner_color) { - if (!gSavedSettings.getBOOL("GridCrossSections")) + if (!gSavedSettings.getBOOL("GridCrossSections") || !LLGLSLShader::sNoFixedFunction) { return; } + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; U32 num_types = LL_ARRAY_SIZE(types); GLuint stencil_mask = 0xFFFFFFFF; //stencil in volumes + gGL.flush(); + + if (shader) + { + gClipProgram.bind(); + } + { glStencilMask(stencil_mask); glClearStencil(1); @@ -1666,6 +1682,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, glStencilFunc(GL_ALWAYS, 0, stencil_mask); gGL.setColorMask(false, false); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.diffuseColor4f(1,1,1,1); //setup clip plane @@ -1675,10 +1692,12 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, normal = -normal; } F32 d = -(selection_center * normal); - F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d }; - LLGLEnable clip(GL_CLIP_PLANE0); - glClipPlane(GL_CLIP_PLANE0, plane); + glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); + + gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); + gClipProgram.uniform4fv("clip_plane", 1, plane.v); + BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); @@ -1729,6 +1748,11 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, F32 sz = mGridSizeMeters; F32 tiles = sz; + if (shader) + { + shader->bind(); + } + //draw volume/plane intersections { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index c899e8991e..bc7f522848 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1659,7 +1659,7 @@ void LLMeshUploadThread::requestWholeModelFee() mCurlRequest->process(); //sleep for 10ms to prevent eating a whole core apr_sleep(10000); - } while (mCurlRequest->getQueued() > 0); + } while (!LLApp::isQuitting() && mCurlRequest->getQueued() > 0); delete mCurlRequest; mCurlRequest = NULL; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 03404e816b..d58d6d536c 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -574,6 +574,7 @@ static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const L texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture); // Don't allow (no copy) or (notransfer) textures to be selected. texture_ctrl->setImmediateFilterPermMask(PERM_NONE); + texture_ctrl->setDnDFilterPermMask(PERM_NONE); texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7301b305b2..3e29805446 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@ #include "llfontgl.h" // project includes +#include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" @@ -46,6 +47,7 @@ #include "llface.h" #include "lllineeditor.h" #include "llmediaentry.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llspinctrl.h" @@ -104,27 +106,11 @@ BOOL LLPanelFace::postBuild() mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) ); mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) ); mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); + mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); mTextureCtrl->setFollowsTop(); mTextureCtrl->setFollowsLeft(); - // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode - mTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - // Allow any texture to be used during non-immediate mode. - mTextureCtrl->setNonImmediateFilterPermMask(PERM_NONE); - LLAggregatePermissions texture_perms; - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - mTextureCtrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - mTextureCtrl->setCanApplyImmediately(FALSE); - } + mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); } mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); @@ -595,28 +581,6 @@ void LLPanelFace::getState() } - LLAggregatePermissions texture_perms; - if(texture_ctrl) - { -// texture_ctrl->setValid( editable ); - - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - texture_ctrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - texture_ctrl->setCanApplyImmediately(FALSE); - } - } - - // planar align bool align_planar = false; bool identical_planar_aligned = false; @@ -1190,3 +1154,35 @@ void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) self->sendTextureInfo(); } +void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) +{ + LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control"); + if (texture_ctrl) + { + LLUUID obj_owner_id; + std::string obj_owner_name; + LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name); + + LLSaleInfo sale_info; + LLSelectMgr::instance().selectGetSaleInfo(sale_info); + + bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture? + bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture? + bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent? + bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale? + + if (can_copy && can_transfer) + { + texture_ctrl->setCanApply(true, true); + return; + } + + // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale + texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale); + + if (gSavedSettings.getBOOL("TextureLivePreview")) + { + LLNotificationsUtil::add("LivePreviewUnavailable"); + } + } +} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 42be9b257f..3b5a9b1398 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -91,6 +91,15 @@ protected: static void onClickAutoFix(void*); static F32 valueGlow(LLViewerObject* object, S32 face); +private: + + /* + * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. + * If agent selects texture which is not allowed to be applied for the currently selected object, + * all controls of the floater texture picker which allow to apply the texture will be disabled. + */ + void onTextureSelectionChanged(LLInventoryItem* itemp); + }; #endif diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index b3adfac8a2..26cd3ff1c1 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -85,6 +85,7 @@ BOOL LLPanelLandMedia::postBuild() mMediaTextureCtrl->setCommitCallback( onCommitAny, this ); mMediaTextureCtrl->setAllowNoTexture ( TRUE ); mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mMediaTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); mMediaAutoScaleCheck = getChild<LLCheckBoxCtrl>("media_auto_scale"); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1f77e7a602..7dfe529b73 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -245,6 +245,7 @@ BOOL LLPanelObject::postBuild() mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 )); // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); // Allow any texture to be used during non-immediate mode. mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE); LLAggregatePermissions texture_perms; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index e124916c48..cb6989c9dd 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -67,6 +67,19 @@ inline F64 llsgn(const F64 a) class LLPhysicsMotion { public: + typedef enum + { + SMOOTHING = 0, + MASS, + GRAVITY, + SPRING, + GAIN, + DAMPING, + DRAG, + MAX_EFFECT, + NUM_PARAMS + } eParamName; + /* param_driver_name: The param that controls the params that are being affected by the physics. joint_name: The joint that the body part is attached to. The joint is @@ -98,6 +111,11 @@ public: mPositionLastUpdate_local(0) { mJointState = new LLJointState; + + for (U32 i = 0; i < NUM_PARAMS; ++i) + { + mParamCache[i] = NULL; + } } BOOL initialize(); @@ -111,16 +129,43 @@ public: return mJointState; } protected: - F32 getParamValue(const std::string& controller_key) - { - const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key); + + F32 getParamValue(eParamName param) + { + static std::string controller_key[] = + { + "Smoothing", + "Mass", + "Gravity", + "Spring", + "Gain", + "Damping", + "Drag", + "MaxEffect" + }; + + if (!mParamCache[param]) + { + const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key[param]); if (entry == mParamControllers.end()) { - return sDefaultController[controller_key]; + return sDefaultController[controller_key[param]]; } const std::string& param_name = (*entry).second.c_str(); - return mCharacter->getVisualParamWeight(param_name.c_str()); - } + mParamCache[param] = mCharacter->getVisualParam(param_name.c_str()); + } + + if (mParamCache[param]) + { + return mParamCache[param]->getWeight(); + } + else + { + return sDefaultController[controller_key[param]]; + } + } + + void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, F32 behavior_maxeffect); @@ -150,6 +195,8 @@ private: F32 mLastTime; + LLVisualParam* mParamCache[NUM_PARAMS]; + static default_controller_map_t sDefaultController; }; @@ -427,7 +474,6 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) return TRUE; } - // Return TRUE if character has to update visual params. BOOL LLPhysicsMotion::onUpdate(F32 time) { @@ -471,15 +517,16 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) LLJoint *joint = mJointState->getJoint(); - const F32 behavior_mass = getParamValue("Mass"); - const F32 behavior_gravity = getParamValue("Gravity"); - const F32 behavior_spring = getParamValue("Spring"); - const F32 behavior_gain = getParamValue("Gain"); - const F32 behavior_damping = getParamValue("Damping"); - const F32 behavior_drag = getParamValue("Drag"); - const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. + const F32 behavior_mass = getParamValue(MASS); + const F32 behavior_gravity = getParamValue(GRAVITY); + const F32 behavior_spring = getParamValue(SPRING); + const F32 behavior_gain = getParamValue(GAIN); + const F32 behavior_damping = getParamValue(DAMPING); + const F32 behavior_drag = getParamValue(DRAG); + F32 behavior_maxeffect = getParamValue(MAX_EFFECT); + + const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. - F32 behavior_maxeffect = getParamValue("MaxEffect"); if (physics_test) behavior_maxeffect = 1.0f; diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 450f9b2be7..3baa1eccc8 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -229,15 +229,18 @@ U32 LLPolyMeshSharedData::getNumKB() BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; - mBaseCoords = new LLVector3[ numVertices ]; - mBaseNormals = new LLVector3[ numVertices ]; - mBaseBinormals = new LLVector3[ numVertices ]; + mBaseCoords = new LLVector4a[ numVertices ]; + mBaseNormals = new LLVector4a[ numVertices ]; + mBaseBinormals = new LLVector4a[ numVertices ]; mTexCoords = new LLVector2[ numVertices ]; mDetailTexCoords = new LLVector2[ numVertices ]; mWeights = new F32[ numVertices ]; for (i = 0; i < numVertices; i++) { - mWeights[i] = 0.f; + mBaseCoords[i].clear(); + mBaseNormals[i].clear(); + mBaseBinormals[i].clear(); + mWeights[i] = 0.f; } mNumVertices = numVertices; return TRUE; @@ -408,39 +411,47 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) allocateVertexData( numVertices ); - //---------------------------------------------------------------- - // Coords - //---------------------------------------------------------------- - numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << "can't read Coordinates from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // Normals - //---------------------------------------------------------------- - numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Normals from " << fileName << llendl; - return FALSE; - } - - //---------------------------------------------------------------- - // Binormals - //---------------------------------------------------------------- - numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Binormals from " << fileName << llendl; - return FALSE; - } - + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseCoords[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseNormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; + } + } //---------------------------------------------------------------- // TexCoords @@ -767,21 +778,28 @@ LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_ { // Allocate memory without initializing every vector // NOTE: This makes asusmptions about the size of LLVector[234] - int nverts = mSharedData->mNumVertices; - int nfloats = nverts * (2*4 + 3*3 + 2 + 4); + S32 nverts = mSharedData->mNumVertices; + //make sure it's an even number of verts for alignment + nverts += nverts%2; + S32 nfloats = nverts * ( + 4 + //coords + 4 + //normals + 4 + //weights + 2 + //coords + 4 + //scaled normals + 4 + //binormals + 4); //scaled binormals + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); - int offset = 0; - mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - - // these members don't need to be 16-byte aligned, but the first one might be - // read during an aligned memcpy of mTexCoords - mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + S32 offset = 0; + mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; initializeForMorph(); } } @@ -906,7 +924,7 @@ void LLPolyMesh::dumpDiagInfo() //----------------------------------------------------------------------------- // getWritableCoords() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableCoords() +LLVector4a *LLPolyMesh::getWritableCoords() { return mCoords; } @@ -914,7 +932,7 @@ LLVector4 *LLPolyMesh::getWritableCoords() //----------------------------------------------------------------------------- // getWritableNormals() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableNormals() +LLVector4a *LLPolyMesh::getWritableNormals() { return mNormals; } @@ -922,7 +940,7 @@ LLVector4 *LLPolyMesh::getWritableNormals() //----------------------------------------------------------------------------- // getWritableBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getWritableBinormals() +LLVector4a *LLPolyMesh::getWritableBinormals() { return mBinormals; } @@ -931,7 +949,7 @@ LLVector3 *LLPolyMesh::getWritableBinormals() //----------------------------------------------------------------------------- // getWritableClothingWeights() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableClothingWeights() +LLVector4a *LLPolyMesh::getWritableClothingWeights() { return mClothingWeights; } @@ -947,7 +965,7 @@ LLVector2 *LLPolyMesh::getWritableTexCoords() //----------------------------------------------------------------------------- // getScaledNormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledNormals() +LLVector4a *LLPolyMesh::getScaledNormals() { return mScaledNormals; } @@ -955,7 +973,7 @@ LLVector3 *LLPolyMesh::getScaledNormals() //----------------------------------------------------------------------------- // getScaledBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledBinormals() +LLVector4a *LLPolyMesh::getScaledBinormals() { return mScaledBinormals; } @@ -966,17 +984,17 @@ LLVector3 *LLPolyMesh::getScaledBinormals() //----------------------------------------------------------------------------- void LLPolyMesh::initializeForMorph() { - for (U32 i = 0; i < mSharedData->mNumVertices; ++i) + LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + + for (U32 i = 0; i < mSharedData->mNumVertices; ++i) { - mCoords[i] = LLVector4(mSharedData->mBaseCoords[i]); - mNormals[i] = LLVector4(mSharedData->mBaseNormals[i]); + mClothingWeights[i].clear(); } - - memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); } //----------------------------------------------------------------------------- @@ -1098,7 +1116,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp) { mAvatar = avatarp; - mDefaultVec.setVec(0.001f, 0.001f, 0.001f); + mDefaultVec.splat(0.001f); } //----------------------------------------------------------------------------- @@ -1171,8 +1189,12 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); + void LLPolySkeletalDistortion::apply( ESex avatar_sex ) { + LLFastTimer t(FTM_POLYSKELETAL_DISTORTION_APPLY); + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); LLJoint* joint; @@ -1228,11 +1250,14 @@ LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, { LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) { - cloned_morph_data->mCoords[v] = direction; - cloned_morph_data->mNormals[v] = LLVector3(0,0,0); - cloned_morph_data->mBinormals[v] = LLVector3(0,0,0); + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); } return cloned_morph_data; } @@ -1243,17 +1268,27 @@ LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, { LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]*scale; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]*scale; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]*scale; - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v][1] *= -1; - cloned_morph_data->mNormals[v][1] *= -1; - cloned_morph_data->mBinormals[v][1] *= -1; - } + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } } return cloned_morph_data; } diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index ba2bf85570..ffb11a3f7e 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -73,9 +73,9 @@ private: // vertex data S32 mNumVertices; - LLVector3 *mBaseCoords; - LLVector3 *mBaseNormals; - LLVector3 *mBaseBinormals; + LLVector4a *mBaseCoords; + LLVector4a *mBaseNormals; + LLVector4a *mBaseBinormals; LLVector2 *mTexCoords; LLVector2 *mDetailTexCoords; F32 *mWeights; @@ -217,41 +217,41 @@ public: } // Get coords - const LLVector4 *getCoords() const{ + const LLVector4a *getCoords() const{ return mCoords; } // non const version - LLVector4 *getWritableCoords(); + LLVector4a *getWritableCoords(); // Get normals - const LLVector4 *getNormals() const{ + const LLVector4a *getNormals() const{ return mNormals; } // Get normals - const LLVector3 *getBinormals() const{ + const LLVector4a *getBinormals() const{ return mBinormals; } // Get base mesh normals - const LLVector3 *getBaseNormals() const{ + const LLVector4a *getBaseNormals() const{ llassert(mSharedData); return mSharedData->mBaseNormals; } // Get base mesh normals - const LLVector3 *getBaseBinormals() const{ + const LLVector4a *getBaseBinormals() const{ llassert(mSharedData); return mSharedData->mBaseBinormals; } // intermediate morphed normals and output normals - LLVector4 *getWritableNormals(); - LLVector3 *getScaledNormals(); + LLVector4a *getWritableNormals(); + LLVector4a *getScaledNormals(); - LLVector3 *getWritableBinormals(); - LLVector3 *getScaledBinormals(); + LLVector4a *getWritableBinormals(); + LLVector4a *getScaledBinormals(); // Get texCoords const LLVector2 *getTexCoords() const { @@ -275,9 +275,9 @@ public: F32 *getWritableWeights() const; - LLVector4 *getWritableClothingWeights(); + LLVector4a *getWritableClothingWeights(); - const LLVector4 *getClothingWeights() + const LLVector4a *getClothingWeights() { return mClothingWeights; } @@ -341,17 +341,17 @@ protected: // Single array of floats for allocation / deletion F32 *mVertexData; // deformed vertices (resulting from application of morph targets) - LLVector4 *mCoords; + LLVector4a *mCoords; // deformed normals (resulting from application of morph targets) - LLVector3 *mScaledNormals; + LLVector4a *mScaledNormals; // output normals (after normalization) - LLVector4 *mNormals; + LLVector4a *mNormals; // deformed binormals (resulting from application of morph targets) - LLVector3 *mScaledBinormals; + LLVector4a *mScaledBinormals; // output binormals (after normalization) - LLVector3 *mBinormals; + LLVector4a *mBinormals; // weight values that mark verts as clothing/skin - LLVector4 *mClothingWeights; + LLVector4a *mClothingWeights; // output texture coordinates LLVector2 *mTexCoords; @@ -419,17 +419,17 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector3(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; protected: typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; joint_vec_map_t mJointScales; joint_vec_map_t mJointOffsets; - LLVector3 mDefaultVec; + LLVector4a mDefaultVec; // Backlink only; don't make this an LLPointer. LLVOAvatar *mAvatar; }; diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index cefd7df3fe..d25d1420ee 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -48,7 +48,7 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) mNumIndices = 0; mCurrentIndex = 0; mTotalDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMaxDistortion = 0.f; mVertexIndices = NULL; mCoords = NULL; @@ -73,9 +73,9 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : { const S32 numVertices = mNumIndices; - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; mVertexIndices = new U32[numVertices]; @@ -121,16 +121,16 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) //------------------------------------------------------------------------- // allocate vertices //------------------------------------------------------------------------- - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; // Actually, we are allocating more space than we need for the skiplist mVertexIndices = new U32[numVertices]; mNumIndices = 0; mTotalDistortion = 0.f; mMaxDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMesh = mesh; //------------------------------------------------------------------------- @@ -152,36 +152,36 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) } - numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target vertex coordinates" << llendl; return FALSE; } - F32 magnitude = mCoords[v].magVec(); + F32 magnitude = mCoords[v].getLength3().getF32(); mTotalDistortion += magnitude; - mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]); - mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]); - mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]); + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); if (magnitude > mMaxDistortion) { mMaxDistortion = magnitude; } - numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target normal" << llendl; return FALSE; } - numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target binormal" << llendl; @@ -200,8 +200,8 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) mNumIndices++; } - mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices); - mAvgDistortion.normVec(); + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); return TRUE; } @@ -367,9 +367,9 @@ BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // getVertexDistortion() //----------------------------------------------------------------------------- -LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) { - if (!mMorphData || mMesh != mesh) return LLVector3::zero; + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); for(U32 index = 0; index < mMorphData->mNumIndices; index++) { @@ -379,17 +379,17 @@ LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh } } - return LLVector3::zero; + return LLVector4a::getZero(); } //----------------------------------------------------------------------------- // getFirstDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex = 0; if (mMorphData->mNumIndices) { @@ -411,11 +411,11 @@ const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh ** //----------------------------------------------------------------------------- // getNextDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex++; if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) { @@ -451,7 +451,7 @@ F32 LLPolyMorphTarget::getTotalDistortion() //----------------------------------------------------------------------------- // getAvgDistortion() //----------------------------------------------------------------------------- -const LLVector3& LLPolyMorphTarget::getAvgDistortion() +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() { if (mMorphData) { @@ -459,7 +459,7 @@ const LLVector3& LLPolyMorphTarget::getAvgDistortion() } else { - return LLVector3::zero; + return LLVector4a::getZero(); } } @@ -481,6 +481,8 @@ F32 LLPolyMorphTarget::getMaxDistortion() //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_APPLY_MORPH_TARGET("Apply Morph"); + void LLPolyMorphTarget::apply( ESex avatar_sex ) { if (!mMorphData || mNumMorphMasksPending > 0) @@ -488,6 +490,8 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) return; } + LLFastTimer t(FTM_APPLY_MORPH_TARGET); + mLastSex = avatar_sex; // Check for NaN condition (NaN is detected if a variable doesn't equal itself. @@ -508,15 +512,15 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) if (delta_weight != 0.f) { llassert(!mMesh->isLOD()); - LLVector4 *coords = mMesh->getWritableCoords(); + LLVector4a *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector4 *normals = mMesh->getWritableNormals(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); - LLVector3 *binormals = mMesh->getWritableBinormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); - LLVector4 *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; @@ -531,31 +535,38 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) maskWeight = maskWeightArray[vert_index_morph]; } - coords[vert_index_mesh] += LLVector4(mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight); + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); if (getInfo()->mIsClothingMorph && clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight; - LLVector4* clothing_weight = &clothing_weights[vert_index_mesh]; - clothing_weight->mV[VX] += clothing_offset.mV[VX]; - clothing_weight->mV[VY] += clothing_offset.mV[VY]; - clothing_weight->mV[VZ] += clothing_offset.mV[VZ]; - clothing_weight->mV[VW] = maskWeight; + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; } // calculate new normals based on half angles - scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 normalized_normal = scaled_normals[vert_index_mesh]; - normalized_normal.normVec(); - normals[vert_index_mesh] = LLVector4(normalized_normal); + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + norm.normalize3fast(); + normals[vert_index_mesh] = norm; // calculate new binormals - scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal; - LLVector3 normalized_binormal = normalized_normal % tangent; - normalized_binormal.normVec(); - binormals[vert_index_mesh] = normalized_binormal; - + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; } @@ -582,7 +593,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) { - LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; if (!mVertMask) { @@ -596,29 +607,47 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 if (maskWeights) { - LLVector4 *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) { F32 lastMaskWeight = mLastWeight * maskWeights[vert]; S32 out_vert = mMorphData->mVertexIndices[vert]; // remove effect of existing masked morph - coords[out_vert] -= LLVector4(mMorphData->mCoords[vert]) * lastMaskWeight; - scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; - scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; if (clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight; - LLVector4* clothing_weight = &clothing_weights[out_vert]; - clothing_weight->mV[VX] -= clothing_offset.mV[VX]; - clothing_weight->mV[VY] -= clothing_offset.mV[VY]; - clothing_weight->mV[VZ] -= clothing_offset.mV[VZ]; + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); } } } @@ -654,7 +683,7 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights) +void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) // BOOL debugImg = FALSE; @@ -698,7 +727,7 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, if (clothing_weights) { - clothing_weights[vertIndex].mV[VW] = mWeights[index]; + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; } } mWeightsGenerated = TRUE; diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index 8a024f2e9e..46e23b7792 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -58,14 +58,14 @@ public: U32 mNumIndices; U32* mVertexIndices; U32 mCurrentIndex; - LLVector3* mCoords; - LLVector3* mNormals; - LLVector3* mBinormals; + LLVector4a* mCoords; + LLVector4a* mNormals; + LLVector4a* mBinormals; LLVector2* mTexCoords; F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LLVector3 mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; }; @@ -78,7 +78,7 @@ public: LLPolyVertexMask(LLPolyMorphData* morph_data); ~LLPolyVertexMask(); - void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights); + void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); F32* getMorphMaskWeights(); @@ -157,11 +157,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index eec2c0a521..a55565909f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1508,6 +1508,49 @@ struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor } }; +void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) +{ + if (!item) + { + return; + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID()); + + for (iterator iter = begin(); iter != end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = (*iter)->getObject(); + if (!object) + { + continue; + } + + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); + bool texture_copied = false; + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + //(no-copy) textures must be moved to the object's inventory only once + // without making any copies + if (!texture_copied) + { + LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); + texture_copied = true; + } + + // apply texture for the selected faces + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + object->setTEImage(te, image); + dialog_refresh_all(); + + // send the update to the simulator + object->sendTEUpdate(); + } + } + } +} + //----------------------------------------------------------------------------- // selectionSetImage() //----------------------------------------------------------------------------- @@ -1559,8 +1602,18 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) } return true; } - } setfunc(item, imageid); - getSelection()->applyToTEs(&setfunc); + }; + + if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) + { + getSelection()->applyNoCopyTextureToTEs(item); + } + else + { + f setfunc(item, imageid); + getSelection()->applyToTEs(&setfunc); + } + struct g : public LLSelectedObjectFunctor { @@ -5583,7 +5636,7 @@ void pushWireframe(LLDrawable* drawable) for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); } } @@ -5610,7 +5663,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) if (shader) { - gHighlightProgram.bind(); + gDebugProgram.bind(); } gGL.matrixMode(LLRender::MM_MODELVIEW); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 87ada5ac6b..94606b9fba 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -307,6 +307,15 @@ public: bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false); bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); + /* + * Used to apply (no-copy) textures to the selected object or + * selected face/faces of the object. + * This method moves (no-copy) texture to the object's inventory + * and doesn't make copy of the texture for each face. + * Then this only texture is used for all selected faces. + */ + void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); + ESelectType getSelectType() const { return mSelectType; } private: diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 1ce05da849..92c2863ffd 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -352,7 +352,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) getChildView("BtnCreator")->setEnabled(FALSE); getChildView("LabelCreatorTitle")->setEnabled(FALSE); getChildView("LabelCreatorName")->setEnabled(FALSE); - getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown")); + getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown_multiple")); } //////////////// diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 8e62b79d7f..bd335576ba 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -68,6 +68,7 @@ const F32 SG_OCCLUSION_FUDGE = 0.25f; #define assert_states_valid(x) #endif +extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; @@ -85,12 +86,32 @@ static F32 sCurMaxTexPriority = 1.f; class LLOcclusionQueryPool : public LLGLNamePool { +public: + LLOcclusionQueryPool() + { + mCurQuery = 1; + } + protected: + + std::list<GLuint> mAvailableName; + GLuint mCurQuery; + virtual GLuint allocateName() { - GLuint name; - glGenQueriesARB(1, &name); - return name; + GLuint ret = 0; + + if (!mAvailableName.empty()) + { + ret = mAvailableName.front(); + mAvailableName.pop_front(); + } + else + { + ret = mCurQuery++; + } + + return ret; } virtual void releaseName(GLuint name) @@ -98,7 +119,8 @@ protected: #if LL_TRACK_PENDING_OCCLUSION_QUERIES LLSpatialGroup::sPendingQueries.erase(name); #endif - glDeleteQueriesARB(1, &name); + llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); + mAvailableName.push_back(name); } }; @@ -259,79 +281,39 @@ U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) return (U8*) (sOcclusionIndices+cypher*8); } - -static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); - -void LLSpatialGroup::buildOcclusion() +//create a vertex buffer for efficiently rendering cubes +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) { - //if (mOcclusionVerts.isNull()) - { - mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, - LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. - mOcclusionVerts->allocateBuffer(8, 64, true); - - LLStrider<U16> idx; - mOcclusionVerts->getIndexStrider(idx); - for (U32 i = 0; i < 64; i++) - { - *idx++ = sOcclusionIndices[i]; - } - } + LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); - LLVector4a fudge; - fudge.splat(SG_OCCLUSION_FUDGE); - - LLVector4a r; - r.setAdd(mBounds[1], fudge); + ret->allocateBuffer(8, 64, true); LLStrider<LLVector3> pos; - - { - LLFastTimer t(FTM_BUILD_OCCLUSION); - mOcclusionVerts->getVertexStrider(pos); - } + LLStrider<U16> idx; - { - LLVector4a* v = (LLVector4a*) pos.get(); + ret->getVertexStrider(pos); + ret->getIndexStrider(idx); - const LLVector4a& c = mBounds[0]; - const LLVector4a& s = r; - - static const LLVector4a octant[] = - { - LLVector4a(-1.f, -1.f, -1.f), - LLVector4a(-1.f, -1.f, 1.f), - LLVector4a(-1.f, 1.f, -1.f), - LLVector4a(-1.f, 1.f, 1.f), - - LLVector4a(1.f, -1.f, -1.f), - LLVector4a(1.f, -1.f, 1.f), - LLVector4a(1.f, 1.f, -1.f), - LLVector4a(1.f, 1.f, 1.f), - }; - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - - for (S32 i = 0; i < 8; ++i) - { - LLVector4a p; - p.setMul(s, octant[i]); - p.add(c); - v[i] = p; - } - } - + pos[0] = LLVector3(-1,-1,-1); + pos[1] = LLVector3(-1,-1, 1); + pos[2] = LLVector3(-1, 1,-1); + pos[3] = LLVector3(-1, 1, 1); + pos[4] = LLVector3( 1,-1,-1); + pos[5] = LLVector3( 1,-1, 1); + pos[6] = LLVector3( 1, 1,-1); + pos[7] = LLVector3( 1, 1, 1); + + for (U32 i = 0; i < 64; i++) { - mOcclusionVerts->flush(); - LLVertexBuffer::unbind(); + idx[i] = sOcclusionIndices[i]; } - clearState(LLSpatialGroup::OCCLUSION_DIRTY); + ret->flush(); + + return ret; } +static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); @@ -394,8 +376,6 @@ LLSpatialGroup::~LLSpatialGroup() } } - mOcclusionVerts = NULL; - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); clearAtlasList() ; @@ -562,7 +542,7 @@ void LLSpatialGroup::validate() validateDrawMap(); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; sg_assert(drawable->getSpatialGroup() == this); @@ -687,6 +667,11 @@ void LLSpatialGroup::rebuildGeom() if (!isDead()) { mSpatialPartition->rebuildGeom(this); + + if (isState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } } } @@ -699,6 +684,9 @@ void LLSpatialGroup::rebuildMesh() } static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLFastTimer::DeclareTimer FTM_CREATE_VB("Create VB"); +static LLFastTimer::DeclareTimer FTM_GET_GEOMETRY("Get Geometry"); void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { @@ -720,27 +708,36 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) //get geometry count U32 index_count = 0; U32 vertex_count = 0; - - addGeometryCount(group, vertex_count, index_count); + + { + LLFastTimer t(FTM_ADD_GEOMETRY_COUNT); + addGeometryCount(group, vertex_count, index_count); + } if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node - group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || - !group->mVertexBuffer->isWriteable() || - (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) { - group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); - group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); - stop_glerror(); + LLFastTimer t(FTM_CREATE_VB); + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + { + group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); + group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); + stop_glerror(); + } + else + { + group->mVertexBuffer->resizeBuffer(vertex_count, index_count); + stop_glerror(); + } } - else + { - group->mVertexBuffer->resizeBuffer(vertex_count, index_count); - stop_glerror(); + LLFastTimer t(FTM_GET_GEOMETRY); + getGeometry(group); } - - getGeometry(group); } else { @@ -762,7 +759,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma { const OctreeNode* node = mOctreeNode; - if (node->getData().empty()) + if (node->isEmpty()) { //don't do anything if there are no objects if (empty && mOctreeNode->getParent()) { //only root is allowed to be empty @@ -779,14 +776,14 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma clearState(OBJECT_DIRTY); //initialize bounding box to first element - OctreeNode::const_element_iter i = node->getData().begin(); + OctreeNode::const_element_iter i = node->getDataBegin(); LLDrawable* drawablep = *i; const LLVector4a* minMax = drawablep->getSpatialExtents(); newMin = minMax[0]; newMax = minMax[1]; - for (++i; i != node->getData().end(); ++i) + for (++i; i != node->getDataEnd(); ++i) { drawablep = *i; minMax = drawablep->getSpatialExtents(); @@ -927,16 +924,14 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - //if (!mSpatialPartition->mRenderByGroup) + if (!mSpatialPartition->mRenderByGroup && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); } - - if (mOcclusionVerts.notNull()) - { - setState(OCCLUSION_DIRTY); - } } class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -1235,8 +1230,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mVisible[i] = 0; } - mOcclusionVerts = NULL; - mRadius = 1; mPixelArea = 1024.f; } @@ -1249,13 +1242,18 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) return; } + if (gShiftFrame) + { + return; + } + #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { llerrs << "Spatial group dirty on distance update." << llendl; } #endif - if (!getData().empty()) + if (!isEmpty()) { mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : (F32) mOctreeNode->getSize().getLength3().getF32(); @@ -1406,7 +1404,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); setState(DEAD); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getSpatialGroup() == this) @@ -1465,10 +1463,14 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo unbound(); } -void LLSpatialGroup::destroyGL() +void LLSpatialGroup::destroyGL(bool keep_occlusion) { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - gPipeline.markRebuild(this, TRUE); + + if (!keep_occlusion) + { //going to need a rebuild + gPipeline.markRebuild(this, TRUE); + } mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; @@ -1476,24 +1478,29 @@ void LLSpatialGroup::destroyGL() clearDrawMap(); - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + if (!keep_occlusion) { - if (mOcclusionQuery[i]) + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) { - sQueryPool.release(mOcclusionQuery[i]); - mOcclusionQuery[i] = 0; + if (mOcclusionQuery[i]) + { + sQueryPool.release(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } } } - mOcclusionVerts = NULL; - for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) + for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* facep = drawable->getFace(j); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } } @@ -1556,15 +1563,13 @@ BOOL LLSpatialGroup::rebound() mBounds[1].mul(0.5f); } - setState(OCCLUSION_DIRTY); - clearState(DIRTY); return TRUE; } static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait"); void LLSpatialGroup::checkOcclusion() { @@ -1584,7 +1589,9 @@ void LLSpatialGroup::checkOcclusion() { glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) + static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); + + if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) { //query was issued last frame, wait until it's available S32 max_loop = 1024; LLFastTimer t(FTM_OCCLUSION_WAIT); @@ -1635,7 +1642,9 @@ void LLSpatialGroup::checkOcclusion() else { assert_states_valid(this); + setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); } @@ -1690,12 +1699,6 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); } - if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY)) - { - LLFastTimer t(FTM_OCCLUSION_BUILD); - buildOcclusion(); - } - // Depth clamp all water to avoid it being culled as a result of being // behind the far clip plane, and in the case of edge water to avoid // it being culled while still visible. @@ -1726,10 +1729,13 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); } - { - LLFastTimer t(FTM_OCCLUSION_SET_BUFFER); - mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - } + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + + shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); + shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE, + mBounds[1][1]+SG_OCCLUSION_FUDGE, + mBounds[1][2]+SG_OCCLUSION_FUDGE); if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) { @@ -1738,12 +1744,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) LLGLSquashToFarClip squash(glh_get_current_projection(), 1); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } else @@ -1751,12 +1757,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) LLFastTimer t(FTM_OCCLUSION_DRAW); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } @@ -1841,12 +1847,14 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - drawablep->setSpatialGroup(NULL); - if (!curp->removeObject(drawablep)) { OCT_ERRS << "Failed to remove drawable from octree!" << llendl; } + else + { + drawablep->setSpatialGroup(NULL); + } assert_octree_valid(mOctree); @@ -2117,7 +2125,7 @@ public: virtual void processGroup(LLSpatialGroup* group) { - llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty()) + llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->isEmpty()) if (mRes < 2) { @@ -2184,7 +2192,7 @@ public: { LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2308,7 +2316,7 @@ public: LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup) @@ -2480,18 +2488,21 @@ void pushVerts(LLSpatialGroup* group, U32 mask) void pushVerts(LLFace* face, U32 mask) { - llassert(face->verify()); + if (face) + { + llassert(face->verify()); - LLVertexBuffer* buffer = face->getVertexBuffer(); + LLVertexBuffer* buffer = face->getVertexBuffer(); - if (buffer && (face->getGeomCount() >= 3)) - { - buffer->setBuffer(mask); - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - U32 count = face->getIndicesCount(); - U16 offset = face->getIndicesStart(); - buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + if (buffer && (face->getGeomCount() >= 3)) + { + buffer->setBuffer(mask); + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + U32 count = face->getIndicesCount(); + U16 offset = face->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } } } @@ -2615,7 +2626,7 @@ void renderOctree(LLSpatialGroup* group) gGL.flush(); glLineWidth(1.f); gGL.flush(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (!group->mSpatialPartition->isBridge()) @@ -2628,7 +2639,7 @@ void renderOctree(LLSpatialGroup* group) for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* face = drawable->getFace(j); - if (face->getVertexBuffer()) + if (face && face->getVertexBuffer()) { if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) { @@ -2661,7 +2672,7 @@ void renderOctree(LLSpatialGroup* group) } else { - if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() && group->mSpatialPartition->mRenderByGroup) { col.setVec(0.8f, 0.4f, 0.1f, 0.1f); @@ -2729,7 +2740,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->getData().empty(); + !group->isEmpty(); if (render_objects) { @@ -2757,19 +2768,6 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } - /*else if (camera && group->mOcclusionVerts.notNull()) - { - LLVertexBuffer::unbind(); - group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - - gGL.diffuseColor4f(1.0f, 0.f, 0.f, 0.5f); - group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4f(1.0f, 1.f, 1.f, 1.0f); - group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0])); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - }*/ } } @@ -2999,15 +2997,17 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; - ext = facep->mExtents; - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - drawBoxOutline(pos,size); + drawBoxOutline(pos,size); + } } //render drawable bounding box @@ -3471,7 +3471,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) void renderPhysicsShapes(LLSpatialGroup* group) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; LLVOVolume* volume = drawable->getVOVolume(); @@ -3499,18 +3499,21 @@ void renderPhysicsShapes(LLSpatialGroup* group) for (S32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* face = drawable->getFace(i); - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) + if (face) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - gGL.diffuseColor3f(0.2f, 1.f, 0.3f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + gGL.diffuseColor3f(0.2f, 1.f, 0.3f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + } } } } @@ -3534,6 +3537,7 @@ void renderTexturePriority(LLDrawable* drawable) //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) + if (facep) { //F32 vsize = imagep->mMaxVirtualSize; @@ -3586,7 +3590,11 @@ void renderPoints(LLDrawable* drawablep) gGL.diffuseColor3f(1,1,1); for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + LLFace * face = drawablep->getFace(i); + if (face) + { + gGL.vertex3fv(face->mCenterLocal.mV); + } } gGL.end(); } @@ -3767,7 +3775,11 @@ void renderLights(LLDrawable* drawablep) for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + LLFace * face = drawablep->getFace(i); + if (face) + { + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } } const LLVector4a* ext = drawablep->getSpatialExtents(); @@ -3808,7 +3820,7 @@ public: LLVector3 center, size; - if (branch->getData().empty()) + if (branch->isEmpty()) { gGL.diffuseColor3f(1.f,0.2f,0.f); center.set(branch->getCenter().getF32ptr()); @@ -3844,8 +3856,8 @@ public: } gGL.begin(LLRender::TRIANGLES); - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -4082,7 +4094,7 @@ public: if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { - if (!group->getData().empty()) + if (!group->isEmpty()) { gGL.diffuseColor3f(0,0,1); drawBoxOutline(group->mObjectBounds[0], @@ -4090,7 +4102,7 @@ public: } } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4169,18 +4181,21 @@ public: for (U32 i = 0; i < drawable->getNumFaces(); ++i) { LLFace* facep = drawable->getFace(i); - U8 index = facep->getTextureIndex(); - if (facep->mDrawInfo) + if (facep) { - if (index < 255) + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) { - if (facep->mDrawInfo->mTextureList.size() <= index) - { - llerrs << "Face texture index out of bounds." << llendl; - } - else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + if (index < 255) { - llerrs << "Face texture index incorrect." << llendl; + if (facep->mDrawInfo->mTextureList.size()<= index) + { + llerrs << "Face texture index out of bounds." << llendl; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + llerrs << "Face texture index incorrect." << llendl; + } } } } @@ -4276,7 +4291,7 @@ public: return; } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4500,7 +4515,7 @@ public: virtual void visit(const LLSpatialGroup::OctreeNode* branch) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); } @@ -4686,28 +4701,62 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) LLCullResult::LLCullResult() { + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups = NULL; + mVisibleGroupsEnd = NULL; + mAlphaGroups = NULL; + mAlphaGroupsEnd = NULL; + mOcclusionGroups = NULL; + mOcclusionGroupsEnd = NULL; + mDrawableGroups = NULL; + mDrawableGroupsEnd = NULL; + mVisibleList = NULL; + mVisibleListEnd = NULL; + mVisibleBridge = NULL; + mVisibleBridgeEnd = NULL; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i] = NULL; + mRenderMapEnd[i] = NULL; + mRenderMapAllocated[i] = 0; + } + clear(); } +void LLCullResult::pushBack(void**& head, U32& count, void* val) +{ + count++; + head = (void**) realloc((void*) head, sizeof(void*) * count); + head[count-1] = val; +} + void LLCullResult::clear() { mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups.begin(); + mVisibleGroupsEnd = mVisibleGroups; mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups.begin(); + mAlphaGroupsEnd = mAlphaGroups; mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mOcclusionGroupsEnd = mOcclusionGroups; mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups.begin(); + mDrawableGroupsEnd = mDrawableGroups; mVisibleListSize = 0; - mVisibleListEnd = mVisibleList.begin(); + mVisibleListEnd = mVisibleList; mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge.begin(); + mVisibleBridgeEnd = mVisibleBridge; for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) @@ -4717,176 +4766,176 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i].begin(); + mRenderMapEnd[i] = mRenderMap[i]; } } -LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() +LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return mVisibleGroups.begin(); + return mVisibleGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() +LLCullResult::sg_iterator LLCullResult::endVisibleGroups() { return mVisibleGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() +LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return mAlphaGroups.begin(); + return mAlphaGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() +LLCullResult::sg_iterator LLCullResult::endAlphaGroups() { return mAlphaGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return mOcclusionGroups.begin(); + return mOcclusionGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() { return mOcclusionGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() +LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return mDrawableGroups.begin(); + return mDrawableGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() +LLCullResult::sg_iterator LLCullResult::endDrawableGroups() { return mDrawableGroupsEnd; } -LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() +LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return mVisibleList.begin(); + return mVisibleList; } -LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() +LLCullResult::drawable_iterator LLCullResult::endVisibleList() { return mVisibleListEnd; } -LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return mVisibleBridge.begin(); + return mVisibleBridge; } -LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() { return mVisibleBridgeEnd; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return mRenderMap[type].begin(); + return mRenderMap[type]; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) { return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) { - if (mVisibleGroupsSize < mVisibleGroups.size()) + if (mVisibleGroupsSize < mVisibleGroupsAllocated) { mVisibleGroups[mVisibleGroupsSize] = group; } else { - mVisibleGroups.push_back(group); + pushBack((void**&) mVisibleGroups, mVisibleGroupsAllocated, (void*) group); } ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) { - if (mAlphaGroupsSize < mAlphaGroups.size()) + if (mAlphaGroupsSize < mAlphaGroupsAllocated) { mAlphaGroups[mAlphaGroupsSize] = group; } else { - mAlphaGroups.push_back(group); + pushBack((void**&) mAlphaGroups, mAlphaGroupsAllocated, (void*) group); } ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { - if (mOcclusionGroupsSize < mOcclusionGroups.size()) + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) { mOcclusionGroups[mOcclusionGroupsSize] = group; } else { - mOcclusionGroups.push_back(group); + pushBack((void**&) mOcclusionGroups, mOcclusionGroupsAllocated, (void*) group); } ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) { - if (mDrawableGroupsSize < mDrawableGroups.size()) + if (mDrawableGroupsSize < mDrawableGroupsAllocated) { mDrawableGroups[mDrawableGroupsSize] = group; } else { - mDrawableGroups.push_back(group); + pushBack((void**&) mDrawableGroups, mDrawableGroupsAllocated, (void*) group); } ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) { - if (mVisibleListSize < mVisibleList.size()) + if (mVisibleListSize < mVisibleListAllocated) { mVisibleList[mVisibleListSize] = drawable; } else { - mVisibleList.push_back(drawable); + pushBack((void**&) mVisibleList, mVisibleListAllocated, (void*) drawable); } ++mVisibleListSize; - mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; + mVisibleListEnd = mVisibleList+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) { - if (mVisibleBridgeSize < mVisibleBridge.size()) + if (mVisibleBridgeSize < mVisibleBridgeAllocated) { mVisibleBridge[mVisibleBridgeSize] = bridge; } else { - mVisibleBridge.push_back(bridge); + pushBack((void**&) mVisibleBridge, mVisibleBridgeAllocated, (void*) bridge); } ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; + mVisibleBridgeEnd = mVisibleBridge+mVisibleBridgeSize; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) { - if (mRenderMapSize[type] < mRenderMap[type].size()) + if (mRenderMapSize[type] < mRenderMapAllocated[type]) { mRenderMap[type][mRenderMapSize[type]] = draw_info; } else { - mRenderMap[type].push_back(draw_info); + pushBack((void**&) mRenderMap[type], mRenderMapAllocated[type], (void*) draw_info); } ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; + mRenderMapEnd[type] = mRenderMap[type] + mRenderMapSize[type]; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 1a93145cc5..e82c50b92b 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -263,11 +263,10 @@ public: SKIP_FRUSTUM_CHECK = 0x00000020, IN_IMAGE_QUEUE = 0x00000040, IMAGE_DIRTY = 0x00000080, - OCCLUSION_DIRTY = 0x00000100, - MESH_DIRTY = 0x00000200, - NEW_DRAWINFO = 0x00000400, - IN_BUILD_Q1 = 0x00000800, - IN_BUILD_Q2 = 0x00001000, + MESH_DIRTY = 0x00000100, + NEW_DRAWINFO = 0x00000200, + IN_BUILD_Q1 = 0x00000400, + IN_BUILD_Q2 = 0x00000800, STATE_MASK = 0x0000FFFF, } eSpatialState; @@ -313,10 +312,9 @@ public: BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax); void unbound(); BOOL rebound(); - void buildOcclusion(); //rebuild mOcclusionVerts void checkOcclusion(); //read back last occlusion query (if any) void doOcclusion(LLCamera* camera); //issue occlusion query - void destroyGL(); + void destroyGL(bool keep_occlusion = false); void updateDistance(LLCamera& camera); BOOL needsUpdate(); @@ -327,8 +325,13 @@ public: void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } + + //octree wrappers to make code more readable element_list& getData() { return mOctreeNode->getData(); } + element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } + element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } + bool isEmpty() const { return mOctreeNode->isEmpty(); } void drawObjectBox(LLColor4 col); @@ -415,7 +418,6 @@ public: LLSpatialPartition* mSpatialPartition; LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLVertexBuffer> mOcclusionVerts; GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; U32 mBufferUsage; @@ -545,34 +547,39 @@ class LLCullResult public: LLCullResult(); - typedef std::vector<LLSpatialGroup*> sg_list_t; - typedef std::vector<LLDrawable*> drawable_list_t; - typedef std::vector<LLSpatialBridge*> bridge_list_t; - typedef std::vector<LLDrawInfo*> drawinfo_list_t; + typedef LLSpatialGroup** sg_list_t; + typedef LLDrawable** drawable_list_t; + typedef LLSpatialBridge** bridge_list_t; + typedef LLDrawInfo** drawinfo_list_t; + + typedef LLSpatialGroup** sg_iterator; + typedef LLSpatialBridge** bridge_iterator; + typedef LLDrawInfo** drawinfo_iterator; + typedef LLDrawable** drawable_iterator; void clear(); - sg_list_t::iterator beginVisibleGroups(); - sg_list_t::iterator endVisibleGroups(); + sg_iterator beginVisibleGroups(); + sg_iterator endVisibleGroups(); - sg_list_t::iterator beginAlphaGroups(); - sg_list_t::iterator endAlphaGroups(); + sg_iterator beginAlphaGroups(); + sg_iterator endAlphaGroups(); bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } - sg_list_t::iterator beginOcclusionGroups(); - sg_list_t::iterator endOcclusionGroups(); + sg_iterator beginOcclusionGroups(); + sg_iterator endOcclusionGroups(); - sg_list_t::iterator beginDrawableGroups(); - sg_list_t::iterator endDrawableGroups(); + sg_iterator beginDrawableGroups(); + sg_iterator endDrawableGroups(); - drawable_list_t::iterator beginVisibleList(); - drawable_list_t::iterator endVisibleList(); + drawable_iterator beginVisibleList(); + drawable_iterator endVisibleList(); - bridge_list_t::iterator beginVisibleBridge(); - bridge_list_t::iterator endVisibleBridge(); + bridge_iterator beginVisibleBridge(); + bridge_iterator endVisibleBridge(); - drawinfo_list_t::iterator beginRenderMap(U32 type); - drawinfo_list_t::iterator endRenderMap(U32 type); + drawinfo_iterator beginRenderMap(U32 type); + drawinfo_iterator endRenderMap(U32 type); void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); @@ -592,28 +599,41 @@ public: void assertDrawMapsEmpty(); private: + + void pushBack(void** &head, U32& count, void* val); + U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; U32 mVisibleBridgeSize; + + U32 mVisibleGroupsAllocated; + U32 mAlphaGroupsAllocated; + U32 mOcclusionGroupsAllocated; + U32 mDrawableGroupsAllocated; + U32 mVisibleListAllocated; + U32 mVisibleBridgeAllocated; + U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; - sg_list_t::iterator mVisibleGroupsEnd; + sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; - sg_list_t::iterator mAlphaGroupsEnd; + sg_iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; - sg_list_t::iterator mOcclusionGroupsEnd; + sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; - sg_list_t::iterator mDrawableGroupsEnd; + sg_iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; - drawable_list_t::iterator mVisibleListEnd; + drawable_iterator mVisibleListEnd; bridge_list_t mVisibleBridge; - bridge_list_t::iterator mVisibleBridgeEnd; + bridge_iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; - drawinfo_list_t::iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + U32 mRenderMapAllocated[LLRenderPass::NUM_RENDER_TYPES]; + drawinfo_iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + }; @@ -657,6 +677,7 @@ class LLParticlePartition : public LLSpatialPartition { public: LLParticlePartition(); + virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); @@ -671,10 +692,14 @@ public: }; //spatial partition for grass (implemented in LLVOGrass.cpp) -class LLGrassPartition : public LLParticlePartition +class LLGrassPartition : public LLSpatialPartition { public: LLGrassPartition(); + virtual void getGeometry(LLSpatialGroup* group); + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); +protected: + U32 mRenderPass; }; //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 66df7dae3e..230e871b49 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -56,6 +56,7 @@ #include "lldrawable.h" extern LLPipeline gPipeline; +extern bool gShiftFrame; LLColor4U MAX_WATER_COLOR(0, 48, 96, 240); @@ -294,7 +295,7 @@ void LLSurface::initTextures() mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); - water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); + water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); // region doesn't have a valid water height yet mWaterObjp->setPositionGlobal(water_pos_global); } } @@ -608,6 +609,11 @@ void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta) void LLSurface::updatePatchVisibilities(LLAgent &agent) { + if (gShiftFrame) + { + return; + } + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); LLSurfacePatch *patchp; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5077c2c7e1..a9ba2bce9c 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -43,6 +43,7 @@ #include "lldrawpool.h" #include "noise.h" +extern bool gShiftFrame; extern U64 gFrameTime; extern LLPipeline gPipeline; @@ -218,7 +219,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); pos_agent.mV[VZ] = *(mDataZ + point_offset); - *vertex = pos_agent; + *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); LLVector3 tex_pos = rel_pos * (1.f/surface_stride); @@ -366,10 +367,13 @@ void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { if (LLPipeline::sDynamicLOD) { - LLVector3 dv = pos_region; - dv -= mCenterRegion; - mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ - llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + if (!gShiftFrame) + { + LLVector3 dv = pos_region; + dv -= mCenterRegion; + mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ + llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + } } else { diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 74c22b0cdf..2c0da60b48 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -76,11 +76,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions BOOL render( S32 x, S32 y, S32 width, S32 height ); @@ -94,7 +94,7 @@ private: LLPointer<LLImageRaw> mStaticImageRaw; BOOL mNeedsCreateTexture; BOOL mStaticImageInvalid; - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; F32 mCachedEffectiveWeight; public: @@ -155,18 +155,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions LLColor4 getNetColor() const; protected: virtual void onGlobalColorChanged(bool upload_bake) {} private: - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; }; class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp index d2e4b01732..f8c1bca8ae 100644 --- a/indra/newview/lltextureatlas.cpp +++ b/indra/newview/lltextureatlas.cpp @@ -116,7 +116,6 @@ LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_ return 0 ; } - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE); glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h, mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData()); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ed9faa0706..6703ef4a41 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -97,6 +97,7 @@ public: LLTextureCtrl* owner, const std::string& label, PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, BOOL can_apply_immediately, LLUIImagePtr fallback_image_name); @@ -134,6 +135,9 @@ public: void onFilterEdit(const std::string& search_string ); + void setCanApply(bool can_preview, bool can_apply); + void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} + static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); static void onBtnCancel( void* userdata ); @@ -175,6 +179,7 @@ protected: LLFilterEditor* mFilterEdit; LLInventoryPanel* mInventoryPanel; PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; PermissionMask mNonImmediateFilterPermMask; BOOL mCanApplyImmediately; BOOL mNoCopyTextureSelected; @@ -184,12 +189,18 @@ protected: LLRadioGroup* mModeSelector; LLScrollListCtrl* mLocalScrollCtrl; + +private: + bool mCanApply; + bool mCanPreview; + texture_selected_callback mTextureSelectedCallback; }; LLFloaterTexturePicker::LLFloaterTexturePicker( LLTextureCtrl* owner, const std::string& label, PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, PermissionMask non_immediate_filter_perm_mask, BOOL can_apply_immediately, LLUIImagePtr fallback_image) @@ -205,9 +216,12 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mActive( TRUE ), mFilterEdit(NULL), mImmediateFilterPermMask(immediate_filter_perm_mask), + mDnDFilterPermMask(dnd_filter_perm_mask), mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), mContextConeOpacity(0.f), - mSelectedItemPinned( FALSE ) + mSelectedItemPinned( FALSE ), + mCanApply(true), + mCanPreview(true) { buildFromFile("floater_texture_ctrl.xml"); mCanApplyImmediately = can_apply_immediately; @@ -319,7 +333,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( if (xfer) item_perm_mask |= PERM_TRANSFER; //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss. - PermissionMask filter_perm_mask = mImmediateFilterPermMask; + PermissionMask filter_perm_mask = mDnDFilterPermMask; if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) { if (drop) @@ -464,7 +478,7 @@ BOOL LLFloaterTexturePicker::postBuild() mNoCopyTextureSelected = FALSE; - getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("ApplyTextureImmediately")); + getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview")); childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); if (!mCanApplyImmediately) @@ -546,7 +560,7 @@ void LLFloaterTexturePicker::draw() // if we're inactive, gray out "apply immediate" checkbox getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); - getChildView("Select")->setEnabled(mActive); + getChildView("Select")->setEnabled(mActive && mCanApply); getChildView("Pipette")->setEnabled(mActive); getChild<LLUICtrl>("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); @@ -702,8 +716,7 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask() void LLFloaterTexturePicker::commitIfImmediateSet() { - bool apply_immediate = getChild<LLUICtrl>("apply_immediate_check")->getValue().asBoolean(); - if (!mNoCopyTextureSelected && apply_immediate && mOwner) + if (!mNoCopyTextureSelected && mOwner && mCanApply) { mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); } @@ -713,6 +726,7 @@ void LLFloaterTexturePicker::commitIfImmediateSet() void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); if (self->mOwner) { self->setImageID( self->mOwner->getDefaultImageAssetID() ); @@ -724,6 +738,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) void LLFloaterTexturePicker::onBtnWhite(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID( self->mWhiteImageAssetID ); self->commitIfImmediateSet(); } @@ -804,13 +819,14 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem mNoCopyTextureSelected = FALSE; if (itemp) { + mTextureSelectedCallback(itemp); if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { mNoCopyTextureSelected = TRUE; } mImageAssetID = itemp->getAssetUUID(); mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - if (user_action) + if (user_action && mCanPreview) { // only commit intentional selections, not implicit ones commitIfImmediateSet(); @@ -947,7 +963,7 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; - gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get()); + gSavedSettings.setBOOL("TextureLivePreview", check_box->get()); picker->updateFilterPermMask(); picker->commitIfImmediateSet(); @@ -958,6 +974,16 @@ void LLFloaterTexturePicker::updateFilterPermMask() //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } +void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) +{ + getChildRef<LLUICtrl>("Select").setEnabled(can_apply); + getChildRef<LLUICtrl>("preview_disabled").setVisible(!can_preview); + getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview); + + mCanApply = can_apply; + mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false; +} + void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { std::string upper_case_search_string = search_string; @@ -1108,6 +1134,15 @@ void LLTextureCtrl::setCanApplyImmediately(BOOL b) } } +void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) +{ + LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); + if( floaterp ) + { + floaterp->setCanApply(can_preview, can_apply); + } +} + void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) @@ -1188,12 +1223,19 @@ void LLTextureCtrl::showPicker(BOOL take_focus) this, mLabel, mImmediateFilterPermMask, + mDnDFilterPermMask, mNonImmediateFilterPermMask, mCanApplyImmediately, mFallbackImage); mFloaterHandle = floaterp->getHandle(); + LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp); + if (texture_floaterp && mOnTextureSelectedCallback) + { + texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); + } + LLFloater* root_floater = gFloaterView->getParentFloater(this); if (root_floater) root_floater->addDependentFloater(floaterp); @@ -1318,6 +1360,16 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) } } +void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) +{ + mOnTextureSelectedCallback = cb; + LLFloaterTexturePicker* floaterp = dynamic_cast<LLFloaterTexturePicker*>(mFloaterHandle.get()); + if (floaterp) + { + floaterp->setTextureSelectedCallback(cb); + } +} + void LLTextureCtrl::setImageAssetName(const std::string& name) { LLPointer<LLUIImage> imagep = LLUI::getUIImage(name); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 3abe84dcc3..599d9c70c5 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -43,6 +43,7 @@ class LLViewerFetchedTexture; // used for setting drag & drop callbacks. typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; +typedef boost::function<void (LLInventoryItem*)> texture_selected_callback; ////////////////////////////////////////////////////////////////////////////////////////// @@ -147,8 +148,12 @@ public: void setCaption(const std::string& caption); void setCanApplyImmediately(BOOL b); + void setCanApply(bool can_preview, bool can_apply); + void setImmediateFilterPermMask(PermissionMask mask) { mImmediateFilterPermMask = mask; } + void setDnDFilterPermMask(PermissionMask mask) + { mDnDFilterPermMask = mask; } void setNonImmediateFilterPermMask(PermissionMask mask) { mNonImmediateFilterPermMask = mask; } PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } @@ -172,6 +177,11 @@ public: void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + /* + * callback for changing texture selection in inventory list of texture floater + */ + void setOnTextureSelectedCallback(texture_selected_callback cb); + void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); LLViewerFetchedTexture* getTexture() { return mTexturep; } @@ -185,6 +195,7 @@ private: drag_n_drop_callback mDropCallback; commit_callback_t mOnCancelCallback; commit_callback_t mOnSelectCallback; + texture_selected_callback mOnTextureSelectedCallback; LLPointer<LLViewerFetchedTexture> mTexturep; LLUIColor mBorderColor; LLUUID mImageItemID; @@ -198,6 +209,7 @@ private: std::string mLabel; BOOL mAllowNoTexture; // If true, the user can select "none" as an option PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; PermissionMask mNonImmediateFilterPermMask; BOOL mCanApplyImmediately; BOOL mCommitOnSelection; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 245c2a23e6..41aee484db 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -93,6 +93,13 @@ public: static S32 getOperationId() { return sOperationId; } + // deal with permissions of object, etc. returns TRUE if drop can + // proceed, otherwise FALSE. + static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id); + protected: enum EDropTarget { @@ -219,13 +226,6 @@ protected: // inventory items to determine if a drop would be ok. static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item); - // deal with permissions of object, etc. returns TRUE if drop can - // proceed, otherwise FALSE. - static BOOL handleDropTextureProtections(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id); - public: // helper functions static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 718201e381..0d5daf129f 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -225,7 +225,8 @@ BOOL LLVisualParamHint::render() LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - if (gAgentAvatarp->mDrawable.notNull()) + if (gAgentAvatarp->mDrawable.notNull() && + gAgentAvatarp->mDrawable->getFace(0)) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index f2712e7590..0d361a2646 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -325,7 +325,7 @@ static bool handleJoystickChanged(const LLSD& newvalue) static bool handleUseOcclusionChanged(const LLSD& newvalue) { - LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery + LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0; return true; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0adb187dd2..0ad2a6eb9b 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -79,6 +79,7 @@ #include "llpostprocess.h" extern LLPointer<LLViewerTexture> gStartTexture; +extern bool gShiftFrame; LLPointer<LLViewerTexture> gDisconnectedImagep = NULL; @@ -162,8 +163,11 @@ void display_startup() glClear(GL_DEPTH_BUFFER_BIT); } +static LLFastTimer::DeclareTimer FTM_UPDATE_CAMERA("Update Camera"); + void display_update_camera() { + LLFastTimer t(FTM_UPDATE_CAMERA); LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA); // TODO: cut draw distance down if customizing avatar? // TODO: cut draw distance on per-parcel basis? @@ -217,6 +221,11 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete"); +static LLFastTimer::DeclareTimer FTM_RESIZE_WINDOW("Resize Window"); +static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("HUD Update"); +static LLFastTimer::DeclareTimer FTM_DISPLAY_UPDATE_GEOM("Update Geom"); +static LLFastTimer::DeclareTimer FTM_TEXTURE_UNBIND("Texture Unbind"); +static LLFastTimer::DeclareTimer FTM_TELEPORT_DISPLAY("Teleport Display"); // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) @@ -226,6 +235,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gWindowResized) { //skip render on frames where window has been resized + LLFastTimer t(FTM_RESIZE_WINDOW); gGL.flush(); glClear(GL_COLOR_BUFFER_BIT); gViewerWindow->getWindow()->swapBuffers(); @@ -362,6 +372,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gTeleportDisplay) { + LLFastTimer t(FTM_TELEPORT_DISPLAY); LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. @@ -581,6 +592,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // *TODO: merge these two methods { + LLFastTimer t(FTM_HUD_UPDATE); LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD); LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); @@ -588,6 +600,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } { + LLFastTimer t(FTM_DISPLAY_UPDATE_GEOM); LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); @@ -597,6 +610,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gPipeline.updateGL(); + stop_glerror(); S32 water_clip = 0; @@ -622,11 +636,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLSpatialGroup::sNoDelete = TRUE; LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); - /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) - { //force occlusion on for all render types if doing deferred render (tighter shadow frustum) - LLPipeline::sUseOcclusion = 3; - }*/ - S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state @@ -755,12 +764,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gTextureList.updateImages(max_image_decode_time); } - { + /*{ LLFastTimer t(FTM_IMAGE_UPDATE_DELETE); //remove dead textures from GL LLImageGL::deleteDeadTextures(); stop_glerror(); - } + }*/ } LLGLState::checkStates(); @@ -889,6 +898,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM); + + if (gSavedSettings.getBOOL("RenderDepthPrePass") && LLGLSLShader::sNoFixedFunction) + { + gGL.setColorMask(false, false); + + U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY + }; + + U32 num_types = LL_ARRAY_SIZE(types); + gOcclusionProgram.bind(); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + gOcclusionProgram.unbind(); + } + + gGL.setColorMask(true, false); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { @@ -911,14 +942,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); } - for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) - { //dummy cleanup of any currently bound textures - if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) - { - gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); - gGL.getTexUnit(i)->disable(); + { + LLFastTimer t(FTM_TEXTURE_UNBIND); + for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } } } + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) @@ -984,6 +1019,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); + + gShiftFrame = false; } void render_hud_attachments() diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 4e14824e69..3a04bbed4f 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -127,7 +127,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { - object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); + LLFace *face = object->mDrawable->getFace(face_num); + if (face) + { + face->setState(LLFace::HUD_RENDER); + } } } @@ -146,7 +150,11 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { - childp->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER); + LLFace * face = childp->mDrawable->getFace(face_num); + if (face) + { + face->setState(LLFace::HUD_RENDER); + } } } } @@ -254,7 +262,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) { - object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); + LLFace * face = object->mDrawable->getFace(face_num); + if (face) + { + face->clearState(LLFace::HUD_RENDER); + } } } } @@ -272,7 +284,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) { - childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER); + LLFace * face = childp->mDrawable->getFace(face_num); + if (face) + { + face->clearState(LLFace::HUD_RENDER); + } } } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a9bff67f40..d790fbc31d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -132,6 +132,7 @@ static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds extern BOOL gDebugClicks; +extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); @@ -2770,7 +2771,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mSourceType = CHAT_SOURCE_OBJECT; - if(SYSTEM_FROM == name) + // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not + // enough to check only from name (i.e. fromName = "Second Life"). For example + // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. + bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); + if(chat_from_system) { // System's UUID is NULL (fixes EXT-4766) chat.mFromID = LLUUID::null; @@ -2795,7 +2800,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); - if(SYSTEM_FROM != name && nearby_chat) + if(!chat_from_system && nearby_chat) { chat.mOwnerID = from_id; LLSD args; @@ -2814,7 +2819,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) //Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590) - if (SYSTEM_FROM != name) break; + if (!chat_from_system) break; LLSD substitutions; substitutions["NAME"] = name; @@ -3734,6 +3739,7 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + gShiftFrame = true; gAgentMovementCompleted = true; LLUUID agent_id; @@ -4064,6 +4070,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) head_rot_chg = dot(last_head_rot, head_rotation); + //static S32 msg_number = 0; // Used for diagnostic log messages + if (force_send || (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) || (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) || @@ -4072,19 +4080,20 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) control_flag_change != 0 || flag_change != 0) { -/* + /* Diagnotics to show why we send the AgentUpdate message. Also un-commment the msg_number code above and below this block + msg_number += 1; if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) { - //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; - LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL; + //LL_INFOS("Messaging") << " head rot " << head_rotation << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL; } if (cam_rot_chg.magVec() > ROTATION_THRESHOLD) { - LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam rot " << cam_rot_chg.magVec() << LL_ENDL; } if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) { - LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam center " << cam_center_chg.magVec() << LL_ENDL; } // if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD) // { @@ -4092,9 +4101,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // } if (control_flag_change) { - LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL; } -*/ + */ duplicate_count = 0; } @@ -4129,6 +4138,26 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) if (duplicate_count < DUP_MSGS && !gDisconnected) { + /* More diagnostics to count AgentUpdate messages + static S32 update_sec = 0; + static S32 update_count = 0; + static S32 max_update_count = 0; + S32 cur_sec = lltrunc( LLTimer::getTotalSeconds() ); + update_count += 1; + if (cur_sec != update_sec) + { + if (update_sec != 0) + { + update_sec = cur_sec; + //msg_number = 0; + max_update_count = llmax(max_update_count, update_count); + llinfos << "Sent " << update_count << " AgentUpdate messages per second, max is " << max_update_count << llendl; + } + update_sec = cur_sec; + update_count = 0; + } + */ + LLFastTimer t(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); @@ -4297,8 +4326,6 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL; } - LLSelectMgr::getInstance()->removeObjectFromSelections(id); - // ...don't kill the avatar if (!(id == gAgentID)) { @@ -4321,6 +4348,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) gObjectList.mNumUnknownKills++; } } + + // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, + // which is using the object, release the mouse capture correctly when the object dies. + // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). + LLSelectMgr::getInstance()->removeObjectFromSelections(id); + } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index cd300accb7..af007743bf 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -199,6 +199,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mID(id), mLocalID(0), mTotalCRC(0), + mListIndex(-1), mTEImages(NULL), mGLName(0), mbCanSelect(TRUE), @@ -432,7 +433,9 @@ void LLViewerObject::dump() const llinfos << "PositionAgent: " << getPositionAgent() << llendl; llinfos << "PositionGlobal: " << getPositionGlobal() << llendl; llinfos << "Velocity: " << getVelocity() << llendl; - if (mDrawable.notNull() && mDrawable->getNumFaces()) + if (mDrawable.notNull() && + mDrawable->getNumFaces() && + mDrawable->getFace(0)) { LLFacePool *poolp = mDrawable->getFace(0)->getPool(); if (poolp) @@ -2169,8 +2172,8 @@ BOOL LLViewerObject::isActive() const BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - static LLFastTimer::DeclareTimer ftm("Viewer Object"); - LLFastTimer t(ftm); + //static LLFastTimer::DeclareTimer ftm("Viewer Object"); + //LLFastTimer t(ftm); if (mDead) { @@ -2798,6 +2801,23 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS (object = gObjectList.findObject(ft->mTaskID))) { object->loadTaskInvFile(ft->mFilename); + + LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); + std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; + + for (; it != end && pending_lst.size(); ++it) + { + LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); + if(item && item->getType() != LLAssetType::AT_CATEGORY) + { + std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + if (id_it != pending_lst.end()) + { + pending_lst.erase(id_it); + } + } + } } else { @@ -2910,7 +2930,22 @@ void LLViewerObject::updateInventory( bool is_new) { LLMemType mt(LLMemType::MTYPE_OBJECT); - + + std::list<LLUUID>::iterator begin = mPendingInventoryItemsIDs.begin(); + std::list<LLUUID>::iterator end = mPendingInventoryItemsIDs.end(); + + bool is_fetching = std::find(begin, end, item->getAssetUUID()) != end; + bool is_fetched = getInventoryItemByAsset(item->getAssetUUID()) != NULL; + + if (is_fetched || is_fetching) + { + return; + } + else + { + mPendingInventoryItemsIDs.push_back(item->getAssetUUID()); + } + // This slices the object into what we're concerned about on the // viewer. The simulator will take the permissions and transfer // ownership. @@ -4477,7 +4512,11 @@ U32 LLViewerObject::getNumVertices() const num_faces = mDrawable->getNumFaces(); for (i = 0; i < num_faces; i++) { - num_vertices += mDrawable->getFace(i)->getGeomCount(); + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_vertices += facep->getGeomCount(); + } } } return num_vertices; @@ -4492,7 +4531,11 @@ U32 LLViewerObject::getNumIndices() const num_faces = mDrawable->getNumFaces(); for (i = 0; i < num_faces; i++) { - num_indices += mDrawable->getFace(i)->getIndicesCount(); + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_indices += facep->getIndicesCount(); + } } } return num_indices; @@ -4769,9 +4812,11 @@ void LLViewerObject::deleteParticleSource() // virtual void LLViewerObject::updateDrawable(BOOL force_damped) { - if (mDrawable.notNull() && - !mDrawable->isState(LLDrawable::ON_MOVE_LIST) && - isChanged(MOVED)) + if (!isChanged(MOVED)) + { //most common case, having an empty if case here makes for better branch prediction + } + else if (mDrawable.notNull() && + !mDrawable->isState(LLDrawable::ON_MOVE_LIST)) { BOOL damped_motion = !isChanged(SHIFTED) && // not shifted between regions this frame and... diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index c8152e1539..30c3d03635 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -229,6 +229,8 @@ public: const LLUUID &getID() const { return mID; } U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mTotalCRC; } + S32 getListIndex() const { return mListIndex; } + void setListIndex(S32 idx) { mListIndex = idx; } virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } @@ -589,6 +591,9 @@ public: // Last total CRC received from sim, used for caching U32 mTotalCRC; + // index into LLViewerObjectList::mActiveObjects or -1 if not in list + S32 mListIndex; + LLPointer<LLViewerTexture> *mTEImages; // Selection, picking and rendering variables @@ -684,6 +689,10 @@ protected: F32 mAppAngle; // Apparent visual arc in degrees F32 mPixelArea; // Apparent area in pixels + // IDs of of all items in the object's content which are added to the object's content, + // but not updated on the server yet. After item was updated, its ID will be removed from this list. + std::list<LLUUID> mPendingInventoryItemsIDs; + // This is the object's inventory from the viewer's perspective. LLInventoryObject::object_list_t* mInventory; class LLInventoryCallbackInfo diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 54ccfb9aae..2fd8c87fc2 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -931,21 +931,30 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) LLViewerObject *objectp = NULL; // Make a copy of the list in case something in idleUpdate() messes with it - std::vector<LLViewerObject*> idle_list; - + static std::vector<LLViewerObject*> idle_list; + + U32 idle_count = 0; + static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); { LLFastTimer t(idle_copy); - idle_list.reserve( mActiveObjects.size() ); - - for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); + + for (std::vector<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) { objectp = *active_iter; if (objectp) { - idle_list.push_back( objectp ); + if (idle_count >= idle_list.size()) + { + idle_list.push_back( objectp ); + } + else + { + idle_list[idle_count] = objectp; + } + ++idle_count; } else { // There shouldn't be any NULL pointers in the list, but they have caused @@ -955,10 +964,13 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } } + std::vector<LLViewerObject*>::iterator idle_end = idle_list.begin()+idle_count; + if (gSavedSettings.getBOOL("FreezeTime")) { + for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin(); - iter != idle_list.end(); iter++) + iter != idle_end; iter++) { objectp = *iter; if (objectp->isAvatar()) @@ -970,17 +982,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) else { for (std::vector<LLViewerObject*>::iterator idle_iter = idle_list.begin(); - idle_iter != idle_list.end(); idle_iter++) + idle_iter != idle_end; idle_iter++) { objectp = *idle_iter; - if (!objectp->idleUpdate(agent, world, frame_time)) + if (objectp->idleUpdate(agent, world, frame_time)) { - // If Idle Update returns false, kill object! - kill_list.push_back(objectp); + num_active_objects++; } else { - num_active_objects++; + // If Idle Update returns false, kill object! + kill_list.push_back(objectp); } } for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin(); @@ -1218,7 +1230,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl; objectp->setOnActiveList(FALSE); - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); } if (objectp->isOnMap()) @@ -1395,6 +1407,26 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) mNumDeadObjects = 0; } +void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) +{ + S32 idx = objectp->getListIndex(); + if (idx != -1) + { //remove by moving last element to this object's position + llassert(mActiveObjects[idx] == objectp); + + objectp->setListIndex(-1); + + S32 last_index = mActiveObjects.size()-1; + + if (idx != last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + mActiveObjects.pop_back(); + } + } +} + void LLViewerObjectList::updateActive(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -1409,13 +1441,29 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (active) { //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl; - mActiveObjects.insert(objectp); - objectp->setOnActiveList(TRUE); + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(TRUE); + } + else + { + llassert(idx < mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); + + if (idx >= mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + llwarns << "Invalid object list index detected!" << llendl; + } + } } else { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl; - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); objectp->setOnActiveList(FALSE); } } @@ -1489,6 +1537,10 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) mPendingPhysicsFlags.erase(object_id); } +static LLFastTimer::DeclareTimer FTM_SHIFT_OBJECTS("Shift Objects"); +static LLFastTimer::DeclareTimer FTM_PIPELINE_SHIFT("Pipeline Shift"); +static LLFastTimer::DeclareTimer FTM_REGION_SHIFT("Region Shift"); + void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { // This is called when we shift our origin when we cross region boundaries... @@ -1500,6 +1552,8 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) return; } + LLFastTimer t(FTM_SHIFT_OBJECTS); + LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { @@ -1516,8 +1570,15 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) } } - gPipeline.shiftObjects(offset); - LLWorld::getInstance()->shiftRegions(offset); + { + LLFastTimer t(FTM_PIPELINE_SHIFT); + gPipeline.shiftObjects(offset); + } + + { + LLFastTimer t(FTM_REGION_SHIFT); + LLWorld::getInstance()->shiftRegions(offset); + } } void LLViewerObjectList::repartitionObjects() @@ -1721,7 +1782,10 @@ void LLViewerObjectList::generatePickList(LLCamera &camera) LLViewerObject* last_objectp = NULL; for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++) { - LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject(); + LLFace * facep = drawablep->getFace(face_num); + if (!facep) continue; + + LLViewerObject* objectp = facep->getViewerObject(); if (objectp && objectp != last_objectp) { diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 64925f46ae..9936432a71 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -118,7 +118,9 @@ public: void dirtyAllObjectInventory(); + void removeFromActiveList(LLViewerObject* objectp); void updateActive(LLViewerObject *objectp); + void updateAvatarVisibility(); // Selection related stuff @@ -197,7 +199,7 @@ protected: typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; vobj_list_t mObjects; - std::set<LLPointer<LLViewerObject> > mActiveObjects; + std::vector<LLPointer<LLViewerObject> > mActiveObjects; vobj_list_t mMapObjects; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 6b3e04348a..345023dbfa 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -476,7 +476,7 @@ void LLViewerPartSim::checkParticleCount(U32 size) LLViewerPartSim::LLViewerPartSim() { LLMemType mt(LLMemType::MTYPE_PARTICLES); - sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); static U32 id_seed = 0; mID = ++id_seed; } diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 3e20f999c0..c9959c63ec 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -39,6 +39,8 @@ class LLViewerRegion; class LLViewerTexture; class LLVOPartGroup; +#define LL_MAX_PARTICLE_COUNT 8192 + typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt); /////////////////// diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e3cb985ddb..e4108e2cd1 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1461,7 +1461,8 @@ void LLViewerRegion::unpackRegionHandshake() // all of our terrain stuff, by if (compp->getParamsReady()) { - getLand().dirtyAllPatches(); + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); } else { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 10c61c01d5..a6c564a6a1 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,8 +63,16 @@ bool LLViewerShaderMgr::sSkipReload = false; LLVector4 gShinyOrigin; +//transform shaders +LLGLSLShader gTransformPositionProgram; +LLGLSLShader gTransformTexCoordProgram; +LLGLSLShader gTransformNormalProgram; +LLGLSLShader gTransformColorProgram; +LLGLSLShader gTransformBinormalProgram; + //utility shaders LLGLSLShader gOcclusionProgram; +LLGLSLShader gOcclusionCubeProgram; LLGLSLShader gCustomAlphaProgram; LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; @@ -72,6 +80,7 @@ LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gOneTextureNoColorProgram; LLGLSLShader gDebugProgram; +LLGLSLShader gClipProgram; LLGLSLShader gAlphaMaskProgram; //object shaders @@ -178,6 +187,7 @@ LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredShadowCubeProgram; LLGLSLShader gDeferredShadowAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAttachmentShadowProgram; @@ -437,7 +447,8 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; - + S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP") && @@ -475,6 +486,7 @@ void LLViewerShaderMgr::setShaders() gSky.mVOSkyp->forceSkyUpdate(); } + // Load lighting shaders mVertexShaderLevel[SHADER_LIGHTING] = light_class; mVertexShaderLevel[SHADER_INTERFACE] = light_class; @@ -484,6 +496,7 @@ void LLViewerShaderMgr::setShaders() mVertexShaderLevel[SHADER_EFFECT] = effect_class; mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class; mVertexShaderLevel[SHADER_DEFERRED] = deferred_class; + mVertexShaderLevel[SHADER_TRANSFORM] = transform_class; BOOL loaded = loadBasicShaders(); @@ -493,65 +506,109 @@ void LLViewerShaderMgr::setShaders() gPipeline.mVertexShadersLoaded = 1; // Load all shaders to set max levels - loadShadersEnvironment(); - loadShadersWater(); - loadShadersWindLight(); - loadShadersEffects(); - loadShadersInterface(); + loaded = loadShadersEnvironment(); + + if (loaded) + { + loaded = loadShadersWater(); + } + + if (loaded) + { + loaded = loadShadersWindLight(); + } + + if (loaded) + { + loaded = loadShadersEffects(); + } + + if (loaded) + { + loaded = loadShadersInterface(); + } - // Load max avatar shaders to set the max level - mVertexShaderLevel[SHADER_AVATAR] = 3; - mMaxAvatarShaderLevel = 3; - - if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) - { //hardware skinning is enabled and rigged attachment shaders loaded correctly - BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); - S32 avatar_class = 1; - - // cloth is a class3 shader - if(avatar_cloth) - { - avatar_class = 3; - } + if (loaded) + { + loaded = loadTransformShaders(); + } - // Set the actual level - mVertexShaderLevel[SHADER_AVATAR] = avatar_class; - loadShadersAvatar(); - if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) - { - if (mVertexShaderLevel[SHADER_AVATAR] == 0) + if (loaded) + { + // Load max avatar shaders to set the max level + mVertexShaderLevel[SHADER_AVATAR] = 3; + mMaxAvatarShaderLevel = 3; + + if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) + { //hardware skinning is enabled and rigged attachment shaders loaded correctly + BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); + S32 avatar_class = 1; + + // cloth is a class3 shader + if(avatar_cloth) { - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + avatar_class = 3; } - if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + + // Set the actual level + mVertexShaderLevel[SHADER_AVATAR] = avatar_class; + loadShadersAvatar(); + if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) { - avatar_cloth = true; + if (mVertexShaderLevel[SHADER_AVATAR] == 0) + { + gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + } + if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3) + { + avatar_cloth = true; + } + else + { + avatar_cloth = false; + } + gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); } - else + } + else + { //hardware skinning not possible, neither is deferred rendering + mVertexShaderLevel[SHADER_AVATAR] = 0; + mVertexShaderLevel[SHADER_DEFERRED] = 0; + + if (gSavedSettings.getBOOL("RenderAvatarVP")) { - avatar_cloth = false; + gSavedSettings.setBOOL("RenderDeferred", FALSE); + gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); + gSavedSettings.setBOOL("RenderAvatarVP", FALSE); } - gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); + + loadShadersAvatar(); // unloads + + loaded = loadShadersObject(); } } - else - { //hardware skinning not possible, neither is deferred rendering - mVertexShaderLevel[SHADER_AVATAR] = 0; - mVertexShaderLevel[SHADER_DEFERRED] = 0; - - if (gSavedSettings.getBOOL("RenderAvatarVP")) - { - gSavedSettings.setBOOL("RenderDeferred", FALSE); - gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + + if (!loaded) + { //some shader absolutely could not load, try to fall back to a simpler setting + if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) + { //disable windlight and try again + gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); + reentrance = false; + setShaders(); + return; } - loadShadersAvatar(); // unloads - loadShadersObject(); - } + if (gSavedSettings.getBOOL("VertexShaderEnable")) + { //disable shaders outright and try again + gSavedSettings.setBOOL("VertexShaderEnable", FALSE); + reentrance = false; + setShaders(); + return; + } + } - if (!loadShadersDeferred()) - { + if (loaded && !loadShadersDeferred()) + { //everything else succeeded but deferred failed, disable deferred and try again gSavedSettings.setBOOL("RenderDeferred", FALSE); reentrance = false; setShaders(); @@ -600,7 +657,9 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { gOcclusionProgram.unload(); + gOcclusionCubeProgram.unload(); gDebugProgram.unload(); + gClipProgram.unload(); gAlphaMaskProgram.unload(); gUIProgram.unload(); gCustomAlphaProgram.unload(); @@ -692,6 +751,12 @@ void LLViewerShaderMgr::unloadShaders() gDeferredSkinnedBumpProgram.unload(); gDeferredSkinnedAlphaProgram.unload(); + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformBinormalProgram.unload(); + mVertexShaderLevel[SHADER_LIGHTING] = 0; mVertexShaderLevel[SHADER_OBJECT] = 0; mVertexShaderLevel[SHADER_AVATAR] = 0; @@ -700,6 +765,7 @@ void LLViewerShaderMgr::unloadShaders() mVertexShaderLevel[SHADER_INTERFACE] = 0; mVertexShaderLevel[SHADER_EFFECT] = 0; mVertexShaderLevel[SHADER_WINDLIGHT] = 0; + mVertexShaderLevel[SHADER_TRANSFORM] = 0; gPipeline.mVertexShadersLoaded = 0; } @@ -828,7 +894,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment() if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0) { gTerrainProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -868,7 +934,7 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterProgram.unload(); gUnderWaterProgram.unload(); gTerrainWaterProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -953,7 +1019,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gGlowExtractProgram.unload(); gPostColorFilterProgram.unload(); gPostNightVisionProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -1013,6 +1079,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); gDeferredShadowProgram.unload(); + gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAttachmentShadowProgram.unload(); @@ -1200,7 +1267,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; gDeferredSpotLightProgram.mShaderFiles.clear(); gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSpotLightProgram.createShader(NULL, NULL); } @@ -1209,7 +1276,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; gDeferredMultiSpotLightProgram.mShaderFiles.clear(); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); @@ -1368,6 +1435,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; + gDeferredShadowCubeProgram.mShaderFiles.clear(); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowCubeProgram.createShader(NULL, NULL); + } + + if (success) + { gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); @@ -2410,7 +2487,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.unload(); gAvatarEyeballProgram.unload(); gAvatarPickProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2504,7 +2581,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (mVertexShaderLevel[SHADER_INTERFACE] == 0) { gHighlightProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2647,6 +2724,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (success) { + gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; + gOcclusionCubeProgram.mShaderFiles.clear(); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOcclusionCubeProgram.createShader(NULL, NULL); + } + + if (success) + { gDebugProgram.mName = "Debug Shader"; gDebugProgram.mShaderFiles.clear(); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2657,6 +2744,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (success) { + gClipProgram.mName = "Clip Shader"; + gClipProgram.mShaderFiles.clear(); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB)); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB)); + gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gClipProgram.createShader(NULL, NULL); + } + + if (success) + { gAlphaMaskProgram.mName = "Alpha Mask Shader"; gAlphaMaskProgram.mShaderFiles.clear(); gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2682,7 +2779,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() { gWLSkyProgram.unload(); gWLCloudProgram.unload(); - return FALSE; + return TRUE; } if (success) @@ -2712,6 +2809,95 @@ BOOL LLViewerShaderMgr::loadShadersWindLight() return success; } +BOOL LLViewerShaderMgr::loadTransformShaders() +{ + BOOL success = TRUE; + + if (mVertexShaderLevel[SHADER_TRANSFORM] < 1) + { + gTransformPositionProgram.unload(); + gTransformTexCoordProgram.unload(); + gTransformNormalProgram.unload(); + gTransformColorProgram.unload(); + gTransformBinormalProgram.unload(); + return TRUE; + } + + if (success) + { + gTransformPositionProgram.mName = "Position Transform Shader"; + gTransformPositionProgram.mShaderFiles.clear(); + gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "position_out", + "texture_index_out", + }; + + success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); + } + + if (success) + { + gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; + gTransformTexCoordProgram.mShaderFiles.clear(); + gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "texcoord_out", + }; + + success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformNormalProgram.mName = "Normal Transform Shader"; + gTransformNormalProgram.mShaderFiles.clear(); + gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "normal_out", + }; + + success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformColorProgram.mName = "Color Transform Shader"; + gTransformColorProgram.mShaderFiles.clear(); + gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "color_out", + }; + + success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); + } + + if (success) + { + gTransformBinormalProgram.mName = "Binormal Transform Shader"; + gTransformBinormalProgram.mShaderFiles.clear(); + gTransformBinormalProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); + gTransformBinormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + + const char* varyings[] = { + "binormal_out", + }; + + success = gTransformBinormalProgram.createShader(NULL, NULL, 1, varyings); + } + + + return success; +} + std::string LLViewerShaderMgr::getShaderDirPrefix(void) { return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 95eb551bf1..8f7ff8dd2f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -54,6 +54,7 @@ public: BOOL loadShadersWater(); BOOL loadShadersInterface(); BOOL loadShadersWindLight(); + BOOL loadTransformShaders(); std::vector<S32> mVertexShaderLevel; S32 mMaxAvatarShaderLevel; @@ -69,6 +70,7 @@ public: SHADER_WINDLIGHT, SHADER_WATER, SHADER_DEFERRED, + SHADER_TRANSFORM, SHADER_COUNT }; @@ -209,13 +211,24 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade extern LLVector4 gShinyOrigin; +//transform shaders +extern LLGLSLShader gTransformPositionProgram; +extern LLGLSLShader gTransformTexCoordProgram; +extern LLGLSLShader gTransformNormalProgram; +extern LLGLSLShader gTransformColorProgram; +extern LLGLSLShader gTransformBinormalProgram; + + + //utility shaders extern LLGLSLShader gOcclusionProgram; +extern LLGLSLShader gOcclusionCubeProgram; extern LLGLSLShader gCustomAlphaProgram; extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; +extern LLGLSLShader gClipProgram; extern LLGLSLShader gAlphaMaskProgram; //output tex0[tc0] + tex1[tc1] @@ -328,6 +341,7 @@ extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredShadowCubeProgram; extern LLGLSLShader gDeferredShadowAlphaMaskProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredCoFProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 497e95c5e3..28f4ec72f3 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -789,6 +789,24 @@ void send_stats() system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass(); system["gpu_vendor"] = gGLManager.mGLVendorShort; system["gpu_version"] = gGLManager.mDriverVersionVendorString; + system["opengl_version"] = gGLManager.mGLVersionString; + + S32 shader_level = 0; + if (LLPipeline::sRenderDeferred) + { + shader_level = 3; + } + else if (gPipeline.canUseWindLightShadersOnObjects()) + { + shader_level = 2; + } + else if (gPipeline.canUseVertexShaders()) + { + shader_level = 1; + } + + + system["shader_level"] = shader_level; LLSD &download = body["downloads"]; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d844aeb12a..7f638a24bf 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1398,10 +1398,10 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { - if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. - { - return ; - } + //if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory. + //{ + // return ; + //} if (mNeedsCreateTexture)//return if in the process of generating a new texture. { return ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 528e0080b7..9a6c0569a9 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -705,7 +705,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() // Flush formatted images using a lazy flush // const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding - const F32 MAX_INACTIVE_TIME = 50.f; // actually delete + const F32 MAX_INACTIVE_TIME = 20.f; // actually delete S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference S32 num_refs = imagep->getNumRefs(); diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index dd7751acd7..3bc95cbfbf 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -83,11 +83,11 @@ public: // New Virtual functions virtual F32 getTotalDistortion() = 0; - virtual const LLVector3& getAvgDistortion() = 0; + virtual const LLVector4a& getAvgDistortion() = 0; virtual F32 getMaxDistortion() = 0; - virtual LLVector3 getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; - virtual const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; - virtual const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; + virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; // interface methods F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 39e330ad66..862d53c613 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -175,6 +175,7 @@ #include "llviewershadermgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" +#include "llvopartgroup.h" #include "llvovolume.h" #include "llworld.h" #include "llworldmapview.h" @@ -4660,6 +4661,8 @@ void LLViewerWindow::stopGL(BOOL save_state) LLVOAvatar::destroyGL(); stop_glerror(); + LLVOPartGroup::destroyGL(); + LLViewerDynamicTexture::destroyGL(); stop_glerror(); @@ -4713,7 +4716,8 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gBumpImageList.restoreGL(); LLViewerDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - + LLVOPartGroup::restoreGL(); + gResizeScreenTexture = TRUE; gWindowResized = TRUE; @@ -4759,8 +4763,11 @@ void LLViewerWindow::requestResolutionUpdate() mResDirty = true; } +static LLFastTimer::DeclareTimer FTM_WINDOW_CHECK_SETTINGS("Window Settings"); + void LLViewerWindow::checkSettings() { + LLFastTimer t(FTM_WINDOW_CHECK_SETTINGS); if (mStatesDirty) { gGL.refreshState(); @@ -5196,8 +5203,10 @@ void LLPickInfo::getSurfaceInfo() if (objectp->mDrawable.notNull() && mObjectFace > -1) { LLFace* facep = objectp->mDrawable->getFace(mObjectFace); - - mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + if (facep) + { + mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + } } // and XY coords: diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index eada77156e..28a25f744b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -817,6 +817,7 @@ LLVOAvatar::~LLVOAvatar() lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); + mJointMap.clear(); deleteAndClearArray(mSkeleton); deleteAndClearArray(mCollisionVolumes); @@ -961,7 +962,7 @@ void LLVOAvatar::deleteLayerSetCaches(bool clearAll) } if (mBakedTextureDatas[i].mMaskTexName) { - glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); mBakedTextureDatas[i].mMaskTexName = 0 ; } } @@ -1459,8 +1460,6 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector) const LLVector3& shift = reinterpret_cast<const LLVector3&>(shift_vector); mLastAnimExtents[0] += shift; mLastAnimExtents[1] += shift; - mNeedsImpostorUpdate = TRUE; - mNeedsAnimUpdate = TRUE; } void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) @@ -1934,6 +1933,7 @@ void LLVOAvatar::buildCharacter() // remove all of mRoot's children //------------------------------------------------------------------------- mRoot.removeAllChildren(); + mJointMap.clear(); mIsBuilt = FALSE; //------------------------------------------------------------------------- @@ -2094,11 +2094,17 @@ void LLVOAvatar::releaseMeshData() if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); - facep->setSize(0, 0); - for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) + if (facep) { - facep = mDrawable->getFace(i); facep->setSize(0, 0); + for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) + { + facep = mDrawable->getFace(i); + if (facep) + { + facep->setSize(0, 0); + } + } } } @@ -2183,15 +2189,20 @@ void LLVOAvatar::updateMeshData() part_index-- ; } - LLFace* facep ; + LLFace* facep = NULL; if(f_num < mDrawable->getNumFaces()) { facep = mDrawable->getFace(f_num); } else { - facep = mDrawable->addFace(mDrawable->getFace(0)->getPool(), mDrawable->getFace(0)->getTexture()) ; + facep = mDrawable->getFace(0); + if (facep) + { + facep = mDrawable->addFace(facep->getPool(), facep->getTexture()) ; + } } + if (!facep) continue; // resize immediately facep->setSize(num_vertices, num_indices); @@ -2379,7 +2390,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) } } -static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Update Avatar"); +static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Avatar Update"); static LLFastTimer::DeclareTimer FTM_JOINT_UPDATE("Update Joints"); //------------------------------------------------------------------------ @@ -4236,10 +4247,14 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mNeedsSkin = FALSE; mLastSkinTime = gFrameTimeSeconds; - LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); - if (vb) + LLFace * face = mDrawable->getFace(0); + if (face) { - vb->flush(); + LLVertexBuffer* vb = face->getVertexBuffer(); + if (vb) + { + vb->flush(); + } } } } @@ -5122,7 +5137,20 @@ const LLUUID& LLVOAvatar::getID() const // RN: avatar joints are multi-rooted to include screen-based attachments LLJoint *LLVOAvatar::getJoint( const std::string &name ) { - LLJoint* jointp = mRoot.findJoint(name); + joint_map_t::iterator iter = mJointMap.find(name); + + LLJoint* jointp = NULL; + + if (iter == mJointMap.end() || iter->second == NULL) + { //search for joint and cache found joint in lookup table + jointp = mRoot.findJoint(name); + mJointMap[name] = jointp; + } + else + { //return cached pointer + jointp = iter->second; + } + return jointp; } @@ -7492,7 +7520,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture } U32 gl_name; - LLImageGL::generateTextures(1, &gl_name ); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_ALPHA8, 1, &gl_name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); @@ -7529,7 +7557,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture maskData->mLastDiscardLevel = discard_level; if (self->mBakedTextureDatas[baked_index].mMaskTexName) { - LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); } self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; found_texture_id = true; @@ -8395,7 +8423,7 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (!facep->getVertexBuffer()) + if (!facep || !facep->getVertexBuffer()) { dirtyMesh(2); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6fb56a4c0b..fab15c200d 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -356,6 +356,10 @@ public: LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; + + typedef std::map<std::string, LLJoint*> joint_map_t; + joint_map_t mJointMap; + protected: static BOOL parseSkeletonFile(const std::string& filename); void buildCharacter(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index d2609e5587..98f7245f8d 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2751,7 +2751,7 @@ void LLVOAvatarSelf::deleteScratchTextures() namep; namep = sScratchTexNames.getNextData() ) { - LLImageGL::deleteTextures(1, (U32 *)namep ); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 0, -1, 1, (U32 *)namep ); stop_glerror(); } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 8a79d564d3..5ad9ccc9af 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -34,6 +34,7 @@ #include "llagentcamera.h" #include "llnotificationsutil.h" #include "lldrawable.h" +#include "lldrawpoolalpha.h" #include "llface.h" #include "llsky.h" #include "llsurface.h" @@ -380,8 +381,10 @@ BOOL LLVOGrass::updateLOD() { mNumBlades <<= 1; } - - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (num_blades <= (mNumBlades >> 1)) @@ -391,7 +394,10 @@ BOOL LLVOGrass::updateLOD() mNumBlades >>=1; } - face->setSize(mNumBlades*8, mNumBlades*12); + if (face) + { + face->setSize(mNumBlades*8, mNumBlades*12); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); return TRUE; } @@ -449,14 +455,16 @@ void LLVOGrass::plantBlades() } LLFace *face = mDrawable->getFace(0); + if (face) + { + face->setTexture(getTEImage(0)); + face->setState(LLFace::GLOBAL); + face->setSize(mNumBlades * 8, mNumBlades * 12); + face->setVertexBuffer(NULL); + face->setTEOffset(0); + face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); + } - face->setTexture(getTEImage(0)); - face->setState(LLFace::GLOBAL); - face->setSize(mNumBlades * 8, mNumBlades * 12); - face->setVertexBuffer(NULL); - face->setTEOffset(0); - face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); - mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis(); mDrawable->setPosition(face->mCenterLocal); mDrawable->movePartition(); @@ -486,6 +494,8 @@ void LLVOGrass::getGeometry(S32 idx, LLColor4U color(255,255,255,255); LLFace *face = mDrawable->getFace(idx); + if (!face) + return; F32 width = sSpeciesTable[mSpecies]->mBladeSizeX; F32 height = sSpeciesTable[mSpecies]->mBladeSizeY; @@ -594,6 +604,7 @@ U32 LLVOGrass::getPartitionType() const } LLGrassPartition::LLGrassPartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -604,6 +615,143 @@ LLGrassPartition::LLGrassPartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } +void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ + group->mBufferUsage = mBufferUsage; + + mFaceList.clear(); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawablep = *i; + + if (drawablep->isDead()) + { + continue; + } + + LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); + obj->mDepth = 0.f; + + if (drawablep->isAnimating()) + { + group->mBufferUsage = GL_STREAM_DRAW_ARB; + } + + U32 count = 0; + for (S32 j = 0; j < drawablep->getNumFaces(); ++j) + { + drawablep->updateFaceSize(j); + + LLFace* facep = drawablep->getFace(j); + if ( !facep || !facep->hasGeometry()) + { + continue; + } + + if ((facep->getGeomCount() + vertex_count) <= 65536) + { + count++; + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); + obj->mDepth += facep->mDistance; + + mFaceList.push_back(facep); + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); + } + else + { + facep->clearVertexBuffer(); + } + } + + obj->mDepth /= count; + } +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); + +void LLGrassPartition::getGeometry(LLSpatialGroup* group) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + + U32 index_count = 0; + U32 vertex_count = 0; + + group->clearDrawMap(); + + LLVertexBuffer* buffer = group->mVertexBuffer; + + LLStrider<U16> indicesp; + LLStrider<LLVector4a> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texcoordsp; + LLStrider<LLColor4U> colorsp; + + buffer->getVertexStrider(verticesp); + buffer->getNormalStrider(normalsp); + buffer->getColorStrider(colorsp); + buffer->getTexCoord0Strider(texcoordsp); + buffer->getIndexStrider(indicesp); + + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; + + for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); + facep->setGeomIndex(vertex_count); + facep->setIndicesIndex(index_count); + facep->setVertexBuffer(buffer); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + F32 vsize = facep->getVirtualSize(); + + if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == facep->getTexture() && + (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && + //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && + draw_vec[idx]->mFullbright == fullbright) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + //facep->getTexture(), + buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; + info->mVSize = vsize; + draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); + } + } + + buffer->flush(); + mFaceList.clear(); +} + // virtual void LLVOGrass::updateDrawable(BOOL force_damped) { diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 0060f81ab5..6da54435e3 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -82,6 +82,7 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline) return mDrawable; } +// TO DO - this always returns TRUE, BOOL LLVOGround::updateGeometry(LLDrawable *drawable) { LLStrider<LLVector3> verticesp; @@ -96,6 +97,8 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) if (drawable->getNumFaces() < 1) drawable->addFace(poolp, NULL); face = drawable->getFace(0); + if (!face) + return TRUE; if (!face->getVertexBuffer()) { diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 5c10a80b07..9cce68fff6 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -48,6 +48,120 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; +LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +void LLVOPartGroup::initClass() +{ + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + + sVBSlotCursor = sVBSlotFree; +} + +//static +void LLVOPartGroup::restoreGL() +{ + sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + U32 count = LL_MAX_PARTICLE_COUNT; + sVB->allocateBuffer(count*4, count*6, true); + + //indices and texcoords are always the same, set once + LLStrider<U16> indicesp; + + LLStrider<LLVector4a> verticesp; + + sVB->getIndexStrider(indicesp); + sVB->getVertexStrider(verticesp); + + LLVector4a v; + v.set(0,0,0,0); + + + U16 vert_offset = 0; + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *indicesp++ = vert_offset + 0; + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 2; + + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 3; + *indicesp++ = vert_offset + 2; + + *verticesp++ = v; + + vert_offset += 4; + } + + LLStrider<LLVector2> texcoordsp; + sVB->getTexCoord0Strider(texcoordsp); + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *texcoordsp++ = LLVector2(0.f, 1.f); + *texcoordsp++ = LLVector2(0.f, 0.f); + *texcoordsp++ = LLVector2(1.f, 1.f); + *texcoordsp++ = LLVector2(1.f, 0.f); + } + + sVB->flush(); + +} + +//static +void LLVOPartGroup::destroyGL() +{ + sVB = NULL; +} + +//static +S32 LLVOPartGroup::findAvailableVBSlot() +{ + if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) + { //no more available slots + return -1; + } + + S32 ret = *sVBSlotCursor; + sVBSlotCursor++; + + return ret; +} + +bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) +{ + while (start < end) + { + if (*start == idx) + { //not allocated (in free list) + return false; + } + ++start; + } + + //allocated (not in free list) + return true; +} + +//static +void LLVOPartGroup::freeVBSlot(S32 idx) +{ + llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); + llassert(sVBSlotCursor > sVBSlotFree); + llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); + + if (sVBSlotCursor > sVBSlotFree) + { + sVBSlotCursor--; + *sVBSlotCursor = idx; + } +} + LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp), mViewerPartGroupp(NULL) @@ -62,7 +176,6 @@ LLVOPartGroup::~LLVOPartGroup() { } - BOOL LLVOPartGroup::isActive() const { return FALSE; @@ -287,9 +400,6 @@ void LLVOPartGroup::getGeometry(S32 idx, const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); - U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); - - LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; @@ -361,33 +471,18 @@ void LLVOPartGroup::getGeometry(S32 idx, verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; - //*verticesp++ = part_pos_agent + up - right; - //*verticesp++ = part_pos_agent - up - right; - //*verticesp++ = part_pos_agent + up + right; - //*verticesp++ = part_pos_agent - up + right; - *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; - *texcoordsp++ = LLVector2(0.f, 1.f); - *texcoordsp++ = LLVector2(0.f, 0.f); - *texcoordsp++ = LLVector2(1.f, 1.f); - *texcoordsp++ = LLVector2(1.f, 0.f); - - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - - *indicesp++ = vert_offset + 0; - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 2; - - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 3; - *indicesp++ = vert_offset + 2; + if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) + { //not fullbright, needs normal + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + } } U32 LLVOPartGroup::getPartitionType() const @@ -412,6 +507,49 @@ LLHUDParticlePartition::LLHUDParticlePartition() : mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); + +void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO); + + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; + + addGeometryCount(group, vertex_count, index_count); + + + if (vertex_count > 0 && index_count > 0) + { + group->mBuilt = 1.f; + //use one vertex buffer for all groups + group->mVertexBuffer = LLVOPartGroup::sVB; + getGeometry(group); + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); +} + void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) { group->mBufferUsage = mBufferUsage; @@ -419,7 +557,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; @@ -431,11 +569,6 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); obj->mDepth = 0.f; - if (drawablep->isAnimating()) - { - group->mBufferUsage = GL_STREAM_DRAW_ARB; - } - U32 count = 0; for (S32 j = 0; j < drawablep->getNumFaces(); ++j) { @@ -447,13 +580,14 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co continue; } + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + count++; facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); obj->mDepth += facep->mDistance; mFaceList.push_back(facep); - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); llassert(facep->getIndicesCount() < 65536); } @@ -461,15 +595,13 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? - FTM_REBUILD_GRASS_VB : - FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -489,21 +621,45 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoord0Strider(texcoordsp); - buffer->getIndexStrider(indicesp); - + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - facep->setGeomIndex(vertex_count); - facep->setIndicesIndex(index_count); - facep->setVertexBuffer(buffer); - facep->setPoolType(LLDrawPool::POOL_ALPHA); - object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + if (!facep->isState(LLFace::PARTICLE)) + { //set the indices of this face + S32 idx = LLVOPartGroup::findAvailableVBSlot(); + if (idx >= 0) + { + facep->setGeomIndex(idx*4); + facep->setIndicesIndex(idx*6); + facep->setVertexBuffer(LLVOPartGroup::sVB); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + facep->setState(LLFace::PARTICLE); + } + else + { + continue; //out of space in particle buffer + } + } + + S32 geom_idx = (S32) facep->getGeomIndex(); + + LLStrider<U16> cur_idx = indicesp + facep->getIndicesStart(); + LLStrider<LLVector4a> cur_vert = verticesp + geom_idx; + LLStrider<LLVector3> cur_norm = normalsp + geom_idx; + LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx; + LLStrider<LLColor4U> cur_col = colorsp + geom_idx; + + object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); + llassert(facep->getGeomCount() == 4); + llassert(facep->getIndicesCount() == 6); + + vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); @@ -512,18 +668,31 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); - if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + bool batched = false; + + if (idx >= 0 && draw_vec[idx]->mTexture == facep->getTexture() && - (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && - //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mStart -= facep->getGeomCount(); + draw_vec[idx]->mOffset = facep->getIndicesStart(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } } - else + + + if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; @@ -541,7 +710,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) } } - buffer->flush(); mFaceList.clear(); } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index e58fed86d9..43b2844f07 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -31,18 +31,33 @@ #include "v3math.h" #include "v3color.h" #include "llframetimer.h" +#include "llviewerpartsim.h" +#include "llvertexbuffer.h" class LLViewerPartGroup; class LLVOPartGroup : public LLAlphaObject { public: + + //vertex buffer for holding all particles + static LLPointer<LLVertexBuffer> sVB; + static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; + static S32* sVBSlotCursor; + + static void initClass(); + static void restoreGL(); + static void destroyGL(); + static S32 findAvailableVBSlot(); + static void freeVBSlot(S32 idx); + enum { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_COLOR) + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TEXTURE_INDEX }; LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index bf6158eeaf..94a3111f4c 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -296,18 +296,20 @@ void LLVOSurfacePatch::updateFaceSize(S32 idx) } LLFace* facep = mDrawable->getFace(idx); - - S32 num_vertices = 0; - S32 num_indices = 0; - - if (mLastStride) + if (facep) { - getGeomSizesMain(mLastStride, num_vertices, num_indices); - getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); - getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); - } + S32 num_vertices = 0; + S32 num_indices = 0; + + if (mLastStride) + { + getGeomSizesMain(mLastStride, num_vertices, num_indices); + getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); + getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); + } - facep->setSize(num_vertices, num_indices); + facep->setSize(num_vertices, num_indices); + } } BOOL LLVOSurfacePatch::updateLOD() @@ -322,30 +324,32 @@ void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp, LLStrider<U16> &indicesp) { LLFace* facep = mDrawable->getFace(0); + if (facep) + { + U32 index_offset = facep->getGeomIndex(); - U32 index_offset = facep->getGeomIndex(); - - updateMainGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateNorthGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateEastGeometry(facep, + updateMainGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, index_offset); + updateNorthGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + updateEastGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + } } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -864,7 +868,11 @@ void LLVOSurfacePatch::dirtyGeom() if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace* facep = mDrawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } mDrawable->movePartition(); } } diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4564207da4..337ddfb24d 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -374,7 +374,7 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. - const LLVector3 &this_position = getPositionAgent(); + const LLVector3 &this_position = getPositionRegion(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); @@ -490,11 +490,16 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. { mReferenceBuffer = NULL ; - mDrawable->getFace(0)->setVertexBuffer(NULL); + LLFace * facep = drawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } return TRUE ; } - if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()) + if (mDrawable->getFace(0) && + (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())) { const F32 SRR3 = 0.577350269f; // sqrt(1/3) const F32 SRR2 = 0.707106781f; // sqrt(1/2) @@ -507,6 +512,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) S32 lod; LLFace *face = drawable->getFace(0); + if (!face) return TRUE; face->mCenterAgent = getPositionAgent(); face->mCenterLocal = face->mCenterAgent; @@ -837,10 +843,10 @@ void LLVOTree::updateMesh() LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_agent = getPositionAgent(); + const LLVector3 &pos_region = getPositionRegion(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; - trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind @@ -879,6 +885,7 @@ void LLVOTree::updateMesh() calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); + if (!facep) return; LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); buff->allocateBuffer(vert_count, index_count, TRUE); facep->setVertexBuffer(buff); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 080d1f774a..082818b112 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -520,6 +520,7 @@ void LLVOVolume::animateTextures() for (S32 i = start; i <= end; i++) { LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; const LLTextureEntry* te = facep->getTextureEntry(); @@ -638,8 +639,8 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLViewerObject::idleUpdate(agent, world, time); - static LLFastTimer::DeclareTimer ftm("Volume"); - LLFastTimer t(ftm); + //static LLFastTimer::DeclareTimer ftm("Volume Idle"); + //LLFastTimer t(ftm); if (mDead || mDrawable.isNull()) { @@ -682,7 +683,21 @@ void LLVOVolume::updateTextures() const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { - updateTextureVirtualSize(); + updateTextureVirtualSize(); + + if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + { //delete vertex buffer to free up some VRAM + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->destroyGL(true); + + //flag the group as having changed geometry so it gets a rebuild next time + //it becomes visible + group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } + } } @@ -715,7 +730,18 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if(!forced) { if(!isVisible()) - { + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } + return ; } @@ -743,6 +769,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) for (S32 i = 0; i < num_faces; i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); if (!imagep || !te || @@ -1062,9 +1089,33 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } + + static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + + bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && + (!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + + if (cache_in_vram) + { //this volume might be used as source data for a transform object, put it in vram + LLVolume* volume = getVolume(); + for (S32 i = 0; i < volume->getNumFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + if (face.mVertexBuffer.notNull()) + { //already cached + break; + } + volume->genBinormals(i); + LLFace::cacheFaceInVRAM(face); + } + } + + return TRUE; } + + return FALSE; } @@ -1246,7 +1297,8 @@ BOOL LLVOVolume::calcLOD() llround(radius, 0.01f)); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) { //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); @@ -1325,25 +1377,23 @@ void LLVOVolume::updateFaceFlags() for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); - if (!face) + if (face) { - return; - } + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } } } } @@ -1380,6 +1430,8 @@ void LLVOVolume::regenFaces() for (S32 i = 0; i < mNumFaces; i++) { LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; + facep->setTEOffset(i); facep->setTexture(getTEImage(i)); facep->setViewerObject(this); @@ -1416,7 +1468,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); -// bool rigged = false; + // bool rigged = false; LLVolume* volume = mRiggedVolume; if (!volume) { @@ -1471,11 +1523,11 @@ void LLVOVolume::preRebuild() } } -void LLVOVolume::updateRelativeXform() +void LLVOVolume::updateRelativeXform(bool force_identity) { if (mVolumeImpl) { - mVolumeImpl->updateRelativeXform(); + mVolumeImpl->updateRelativeXform(force_identity); return; } @@ -1495,15 +1547,16 @@ void LLVOVolume::updateRelativeXform() mRelativeXform.invert(); mRelativeXformInvTrans.transpose(); } - else if (drawable->isActive()) + else if (drawable->isActive() || force_identity) { // setup relative transforms LLQuaternion delta_rot; LLVector3 delta_pos, delta_scale; //matrix from local space to parent relative/global space - delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition(); + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); delta_scale = mDrawable->getScale(); // Vertex transform (4x4) @@ -1604,7 +1657,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return res; } - dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->dirtyMesh(); + } BOOL compiled = FALSE; @@ -1617,6 +1674,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) if (mVolumeChanged || mFaceMappingChanged ) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + compiled = TRUE; if (mVolumeChanged) @@ -1635,6 +1694,8 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) } else if ((mLODChanged) || (mSculptChanged)) { + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + LLVolume *old_volumep, *new_volumep; F32 old_lod, new_lod; S32 old_num_faces, new_num_faces ; @@ -1716,16 +1777,19 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) void LLVOVolume::updateFaceSize(S32 idx) { LLFace* facep = mDrawable->getFace(idx); - if (idx >= getVolume()->getNumVolumeFaces()) + if (facep) { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + } } } @@ -3098,6 +3162,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const for (S32 i = 0; i < num_faces; ++i) { const LLFace* face = drawablep->getFace(i); + if (!face) continue; const LLTextureEntry* te = face->getTextureEntry(); const LLViewerTexture* img = face->getTexture(); @@ -3369,6 +3434,7 @@ F32 LLVOVolume::getBinRadius() for (S32 i = 0; i < mDrawable->getNumFaces(); i++) { LLFace* face = mDrawable->getFace(i); + if (!face) continue; if (face->getPoolType() == LLDrawPool::POOL_ALPHA && !face->canRenderAsMask()) { @@ -3450,9 +3516,12 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { LLVector3 ret = pos - getRenderPosition(); ret = ret * ~getRenderRotation(); - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + } return ret; } @@ -3470,8 +3539,12 @@ LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } + ret = ret * getRenderRotation(); ret += getRenderPosition(); @@ -3592,7 +3665,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e { LLFace* face = mDrawable->getFace(face_hit); - if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) + if (face && + (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))) { v_end = p; if (face_hitp != NULL) @@ -3902,8 +3976,11 @@ bool can_batch_texture(LLFace* facep) return true; } +static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); + void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { + LLFastTimer t(FTM_REGISTER_FACE); LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) @@ -3935,9 +4012,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, const LLMatrix4* model_mat = NULL; LLDrawable* drawable = facep->getDrawable(); - if (drawable->isActive()) + + if (drawable->isState(LLDrawable::ANIMATED_CHILD)) { - model_mat = &(drawable->getRenderMatrix()); + model_mat = &drawable->getWorldMatrix(); + } + else if (drawable->isActive()) + { + model_mat = &drawable->getRenderMatrix(); } else { @@ -3948,6 +4030,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } } + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); @@ -4041,8 +4125,9 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } -static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume"); -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume VB"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); +static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) { @@ -4073,6 +4158,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { + + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -4084,19 +4171,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - LLFastTimer ftm(FTM_REBUILD_VBO); - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); - rebuildMesh(group); } return; } - group->mBuilt = 1.f; - LLFastTimer ftm(FTM_REBUILD_VBO); - - LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB); + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + group->mBuilt = 1.f; + LLVOAvatar* pAvatarVO = NULL; LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); @@ -4145,359 +4228,375 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool emissive = false; - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); + + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - continue; - } + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + { + continue; + } - if (drawablep->isAnimating()) - { //fall back to stream draw for animating verts - useage = GL_STREAM_DRAW_ARB; - } + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } - LLVOVolume* vobj = drawablep->getVOVolume(); + LLVOVolume* vobj = drawablep->getVOVolume(); - if (!vobj) - { - continue; - } + if (!vobj) + { + continue; + } - if (vobj->isMesh() && - (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) - { - continue; - } + if (vobj->isMesh() && + (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) + { + continue; + } - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); - drawablep->clearState(LLDrawable::HAS_ALPHA); + drawablep->clearState(LLDrawable::HAS_ALPHA); - bool rigged = vobj->isAttachment() && - vobj->isMesh() && - gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); - bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); + bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); - bool is_rigged = false; + bool is_rigged = false; - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) + { + continue; + } - //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render - // batch, it will recover its vertex buffer reference from the spatial group - facep->setVertexBuffer(NULL); + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); - //sum up face verts and indices - drawablep->updateFaceSize(i); + //sum up face verts and indices + drawablep->updateFaceSize(i); - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } - facep->setState(LLFace::RIGGED); - is_rigged = true; + facep->setState(LLFace::RIGGED); + is_rigged = true; - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - bool pelvisGotSet = false; + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. + bool pelvisGotSet = false; - if ( pAvatarVO ) - { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - - if ( pSkinData ) + if ( pAvatarVO ) { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; i<jointCnt; ++i ) + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + bool fullRig = (jointCnt>=20) ? true : false; + if ( fullRig ) { - std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); - //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; - LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { + for ( int i=0; i<jointCnt; ++i ) + { + std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); + //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; + LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pJoint->storeCurrentXform( jointPos ); + if ( !pAvatarVO->hasPelvisOffset() ) + { + pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); + //Trigger to rebuild viewer AV + pelvisGotSet = true; + } } - } + } } - } - } + } + } } } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) - { - pAvatarVO->postPelvisSetRecalc(); - } - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + //If we've set the pelvis to a new position we need to also rebuild some information that the + //viewer does at launch (e.g. body size etc.) + if ( pelvisGotSet ) { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + pAvatarVO->postPelvisSetRecalc(); } - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - if (type == LLDrawPool::POOL_ALPHA) + if (pool) { - if (te->getColor().mV[3] > 0.f) + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getColor().mV[3] > 0.f) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + } + else if (te->getShiny()) { if (te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } } } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } else { - if (LLPipeline::sRenderDeferred) + if (te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); } else { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); } } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else + + if (te->getGlow()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); } - } - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + if (LLPipeline::sRenderDeferred) { - if (te->getBumpmap()) + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } } } } - } - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); } - facep->clearState(LLFace::RIGGED); } - } - - - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } - - cur_total += facep->getGeomCount(); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); - if (te->getGlow() >= 1.f/255.f) + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { - emissive = true; + facep->clearVertexBuffer(); + continue; } - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } + cur_total += facep->getGeomCount(); - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - if (type != LLDrawPool::POOL_ALPHA && force_simple) + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); - if (vobj->isHUDAttachment()) - { - facep->setState(LLFace::FULLBRIGHT); - } + if (te->getGlow() >= 1.f/255.f) + { + emissive = true; + } - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) + if (facep->isState(LLFace::TEXTURE_ANIM)) { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) + if (!vobj->mTexAnimMode) { - drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); + facep->clearState(LLFace::TEXTURE_ANIM); } } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) { - drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); + type = LLDrawPool::POOL_SIMPLE; } - } + facep->setPoolType(type); - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask - simple_faces.push_back(facep); - } - else + if (vobj->isHUDAttachment()) { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - alpha_faces.push_back(facep); + facep->setState(LLFace::FULLBRIGHT); } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) { - facep->mLastUpdateTime = gFrameTimeSeconds; + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } } - if (gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump) + if (type == LLDrawPool::POOL_ALPHA) { - if (te->getBumpmap()) - { //needs normal + binormal - bump_faces.push_back(facep); - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal + if (facep->canRenderAsMask()) + { //can be treated as alpha mask simple_faces.push_back(facep); } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getColor().mV[3] > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + } + alpha_faces.push_back(facep); } } else { - if (te->getBumpmap() && LLPipeline::sRenderBump) - { //needs normal + binormal - bump_faces.push_back(facep); + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; } - else if ((te->getShiny() && LLPipeline::sRenderBump) || - !(te->getFullbright() || bake_sunlight)) - { //needs normal - simple_faces.push_back(facep); + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); - fullbright_faces.push_back(facep); + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if ((te->getShiny() && LLPipeline::sRenderBump) || + !(te->getFullbright() || bake_sunlight)) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); + fullbright_faces.push_back(facep); + } } } } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - if (is_rigged) - { - drawablep->setState(LLDrawable::RIGGED); - } - else - { - drawablep->clearState(LLDrawable::RIGGED); + if (is_rigged) + { + drawablep->setState(LLDrawable::RIGGED); + } + else + { + drawablep->clearState(LLDrawable::RIGGED); + } } } @@ -4539,7 +4638,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (!LLPipeline::sDelayVBUpdate) { //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; drawablep->clearState(LLDrawable::REBUILD_ALL); @@ -4564,31 +4663,35 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry"); -static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM_PARTIAL("Terse Rebuild"); void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { llassert(group); if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) { - LLFastTimer tm(FTM_VOLUME_GEOM); + LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; group->mBuilt = 1.f; std::set<LLVertexBuffer*> mapped_buffers; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL); LLDrawable* drawablep = *drawable_iter; - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) + if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { LLVOVolume* vobj = drawablep->getVOVolume(); vobj->preRebuild(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + LLVolume* volume = vobj->getVolume(); for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { @@ -4598,8 +4701,15 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + llassert(!face->isState(LLFace::RIGGED)); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + if (buff->isLocked()) { @@ -4608,6 +4718,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } + drawablep->clearState(LLDrawable::REBUILD_ALL); } @@ -4630,16 +4746,19 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) { llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - LLVertexBuffer* buff = face->getVertexBuffer(); - if (face && buff && buff->isLocked()) + if (face) { - buff->flush(); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } } } } @@ -4648,7 +4767,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } - llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); +// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } struct CompareBatchBreakerModified @@ -4674,8 +4793,20 @@ struct CompareBatchBreakerModified } }; +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); +static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); + + + + + void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) { + LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + U32 buffer_usage = group->mBufferUsage; #if LL_DARWIN @@ -4693,15 +4824,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); - } - else { - //sort faces by distance - std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + LLFastTimer t(FTM_GEN_DRAW_INFO_SORT); + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } } bool hud_group = group->isHUDGroup() ; @@ -4766,57 +4900,86 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::vector<LLViewerTexture*> texture_list; - if (batch_textures) { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - texture_list.push_back(tex); - - //if (can_batch_texture(facep)) + LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); + if (batch_textures) { - while (i != faces.end()) + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + texture_list.push_back(tex); + + //if (can_batch_texture(facep)) { - facep = *i; - if (facep->getTexture() != tex) + while (i != faces.end()) { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) + facep = *i; + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) { - cur_tex = tex_idx; - found = true; - break; + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } } - } - if (!found) + if (!found) + { + cur_tex = texture_list.size(); + } + } + else { - cur_tex = texture_list.size(); + cur_tex++; } - } - else - { - cur_tex++; - } - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - break; + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + break; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + texture_list.push_back(tex); } - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big break; } - tex = facep->getTexture(); + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - texture_list.push_back(tex); + facep->setTextureIndex(cur_tex); } + } + + tex = texture_list[0]; + } + else + { + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); if (geom_count + facep->getGeomCount() > max_vertices) { //cut batches on geom count too big @@ -4826,69 +4989,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: ++i; index_count += facep->getIndicesCount(); geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); } } - - tex = texture_list[0]; } - else - { - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) - { - facep = *i; - - - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(255); - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - } - } - - //create/delete/resize vertex buffer if needed + //create vertex buffer LLVertexBuffer* buffer = NULL; - { //try to find a buffer to reuse - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); - - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) - { - buffer = found_iter->second[buffer_index]; - } - } - } - - if (!buffer || !buffer->isWriteable()) - { //create new buffer if needed + { + LLFastTimer t(FTM_GEN_DRAW_INFO_ALLOCATE); buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); } - else - { //resize pre-existing buffer - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != buffer_usage || - buffer->getTypeMask() != mask) - { - buffer = createVertexBuffer(mask, buffer_usage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } - } group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); @@ -4922,10 +5034,25 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + U32 te_idx = facep->getTEOffset(); - facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); + llassert(!facep->isState(LLFace::RIGGED)); + + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + llwarns << "Failed to get geometry for face!" << llendl; + } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } } } @@ -5089,7 +5216,8 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun mFaceList.clear(); //for each drawable - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -5109,17 +5237,21 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + if (facep) { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - llassert(facep->getIndicesCount() < 65536); - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } } } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 3cf434dc26..5a0960204c 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -68,7 +68,7 @@ class LLVolumeInterface public: virtual ~LLVolumeInterface() { } virtual LLVolumeInterfaceType getInterfaceType() const = 0; - virtual BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; + virtual void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; virtual LLVector3 getPivotPosition() const = 0; virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; @@ -79,7 +79,7 @@ public: virtual bool isVolumeGlobal() const = 0; // Are we in global space? virtual bool isActive() const = 0; // Is this object currently active? virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; - virtual void updateRelativeXform() = 0; + virtual void updateRelativeXform(bool force_identity = false) = 0; virtual U32 getID() const = 0; virtual void preRebuild() = 0; }; @@ -203,7 +203,7 @@ public: LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); - void updateRelativeXform(); + void updateRelativeXform(bool force_identity = false); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index cd78157944..942eff6171 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -146,6 +146,10 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) drawable->addFace(poolp, NULL); } face = drawable->getFace(0); + if (!face) + { + return TRUE; + } // LLVector2 uvs[4]; // LLVector3 vtx[4]; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index b061c90d98..78ee3e4fd9 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -657,7 +657,10 @@ void LLWorld::updateRegions(F32 max_update_time) if (did_one && max_time <= 0.f) break; max_time = llmin(max_time, max_update_time*.1f); - did_one |= regionp->idleUpdate(max_update_time); + if (regionp->idleUpdate(max_update_time)) + { + did_one = TRUE; + } } } @@ -837,6 +840,9 @@ void LLWorld::updateWaterObjects() } mHoleWaterObjects.clear(); + // Use the water height of the region we're on for areas where there is no region + F32 water_height = gAgent.getRegion()->getWaterHeight(); + // Now, get a list of the holes S32 x, y; for (x = min_x; x <= max_x; x += rwidth) @@ -845,12 +851,12 @@ void LLWorld::updateWaterObjects() { U64 region_handle = to_region_handle(x, y); if (!getRegionFromHandle(region_handle)) - { + { // No region at that area, so make water LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); waterp->setUseTexture(FALSE); waterp->setPositionGlobal(LLVector3d(x + rwidth/2, y + rwidth/2, - 256.f+DEFAULT_WATER_HEIGHT)); + 256.f + water_height)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); @@ -907,7 +913,7 @@ void LLWorld::updateWaterObjects() } waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, 256.f+DEFAULT_WATER_HEIGHT) ; + LLVector3d water_pos(water_center_x, water_center_y, 256.f + water_height) ; LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); //stretch out to horizon diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ed636a40b2..cfa47b3ba3 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -51,6 +51,10 @@ // newview includes #include "llagent.h" #include "llagentcamera.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h" #include "lldrawable.h" #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" @@ -113,6 +117,8 @@ //#define DEBUG_INDICES #endif +bool gShiftFrame = false; + //cached settings BOOL LLPipeline::RenderAvatarVP; BOOL LLPipeline::VertexShaderEnable; @@ -210,7 +216,7 @@ BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; -LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry"); +LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Render Geometry"); LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass"); LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible"); LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion"); @@ -227,8 +233,13 @@ LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump"); LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright"); LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow"); LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update"); +LLFastTimer::DeclareTimer FTM_PIPELINE_CREATE("Pipeline Create"); LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool"); LLFastTimer::DeclareTimer FTM_POOLS("Pools"); +LLFastTimer::DeclareTimer FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); +LLFastTimer::DeclareTimer FTM_DEFERRED_POOLS("Pools (Deferred)"); +LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); +LLFastTimer::DeclareTimer FTM_POST_DEFERRED_POOLS("Pools (Post)"); LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO"); LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State"); LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline"); @@ -264,6 +275,7 @@ std::string gPoolNames[] = void drawBox(const LLVector3& c, const LLVector3& r); void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v); +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); glh::matrix4f glh_copy_matrix(F32* src) { @@ -403,9 +415,11 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), + mTransformFeedbackPrimitives(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), + mMeshDirtyQueryObject(0), mGroupQ1Locked(false), mGroupQ2Locked(false), mResetVertexBuffers(false), @@ -504,6 +518,11 @@ void LLPipeline::init() mSpotLightFade[i] = 1.f; } + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); mDeferredVB->allocateBuffer(8, 0, true); setLightingDetail(-1); @@ -693,6 +712,12 @@ void LLPipeline::destroyGL() { LLVertexBuffer::sEnableVBOs = FALSE; } + + if (mMeshDirtyQueryObject) + { + glDeleteQueriesARB(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; + } } static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -942,6 +967,7 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseOcclusion = (!gUseWireframe + && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; @@ -1030,13 +1056,13 @@ void LLPipeline::releaseGLBuffers() if (mNoiseMap) { - LLImageGL::deleteTextures(1, &mNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mNoiseMap); mNoiseMap = 0; } if (mTrueNoiseMap) { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 0, 1, &mTrueNoiseMap); mTrueNoiseMap = 0; } @@ -1060,7 +1086,7 @@ void LLPipeline::releaseLUTBuffers() { if (mLightFunc) { - LLImageGL::deleteTextures(1, &mLightFunc); + LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, GL_R8, 0, 1, &mLightFunc); mLightFunc = 0; } } @@ -1138,7 +1164,7 @@ void LLPipeline::createGLBuffers() noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; } - LLImageGL::generateTextures(1, &mNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); @@ -1154,7 +1180,7 @@ void LLPipeline::createGLBuffers() noise[i] = ll_frand()*2.0-1.0; } - LLImageGL::generateTextures(1, &mTrueNoiseMap); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_RGB16F_ARB, 1, &mTrueNoiseMap); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -1210,7 +1236,7 @@ void LLPipeline::createLUTBuffers() } } - LLImageGL::generateTextures(1, &mLightFunc); + LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -1349,7 +1375,7 @@ public: { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty()) + if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1658,7 +1684,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LLFastTimer ftm(FTM_GEO_UPDATE); + LLFastTimer ftm(FTM_PIPELINE_CREATE); LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS); LLTimer update_timer; @@ -1820,6 +1846,16 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) if (done) { drawablep->clearState(LLDrawable::ON_MOVE_LIST); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { //will likely not receive any future world matrix updates + // -- this keeps attachments from getting stuck in space and falling off your avatar + drawablep->clearState(LLDrawable::ANIMATED_CHILD); + markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, TRUE); + if (drawablep->getVObj()) + { + drawablep->getVObj()->dirtySpatialGroup(TRUE); + } + } iter = moved_list.erase(curiter); } } @@ -1944,7 +1980,7 @@ void LLPipeline::clearReferences() void check_references(LLSpatialGroup* group, LLDrawable* drawable) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { if (drawable == *i) { @@ -1966,7 +2002,7 @@ void check_references(LLDrawable* drawable, LLFace* face) void check_references(LLSpatialGroup* group, LLFace* face) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; check_references(drawable, face); @@ -1978,25 +2014,25 @@ void LLPipeline::checkReferences(LLFace* face) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable* drawable = *iter; check_references(drawable, face); @@ -2010,25 +2046,25 @@ void LLPipeline::checkReferences(LLDrawable* drawable) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { if (drawable == *iter) { @@ -2061,19 +2097,19 @@ void LLPipeline::checkReferences(LLDrawInfo* draw_info) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); @@ -2087,7 +2123,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { if (group == *iter) { @@ -2095,7 +2131,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { if (group == *iter) { @@ -2103,7 +2139,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { if (group == *iter) { @@ -2214,8 +2250,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl gGLLastMatrix = NULL; gGL.loadMatrix(gGLLastModelView); - - LLVertexBuffer::unbind(); LLGLDisable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -2259,7 +2293,16 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can // (shadow render uses a special shader that clamps to clip planes) bound_shader = true; - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); + } + + if (sUseOcclusion > 1) + { + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); } for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -2291,7 +2334,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl if (bound_shader) { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } camera.disableUserClipPlane(); @@ -2335,7 +2378,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) { - if (group->getData().empty()) + if (group->isEmpty()) { return; } @@ -2424,15 +2467,21 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } else { - gOcclusionProgram.bind(); + gOcclusionCubeProgram.bind(); } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; group->doOcclusion(&camera); @@ -2443,11 +2492,11 @@ void LLPipeline::doOcclusion(LLCamera& camera) { if (LLPipeline::sShadowRender) { - gDeferredShadowProgram.unbind(); + gDeferredShadowCubeProgram.unbind(); } else { - gOcclusionProgram.unbind(); + gOcclusionCubeProgram.unbind(); } } @@ -2466,22 +2515,36 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +static LLFastTimer::DeclareTimer FTM_SEED_VBO_POOLS("Seed VBO Pool"); + +static LLFastTimer::DeclareTimer FTM_UPDATE_GL("Update GL"); + void LLPipeline::updateGL() { - while (!LLGLUpdate::sGLQ.empty()) { - LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); - glu->updateGL(); - glu->mInQ = FALSE; - LLGLUpdate::sGLQ.pop_front(); + LLFastTimer t(FTM_UPDATE_GL); + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } + } + + { //seed VBO Pools + LLFastTimer t(FTM_SEED_VBO_POOLS); + LLVertexBuffer::seedPools(); } } +static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); + void LLPipeline::rebuildPriorityGroups() { + LLFastTimer t(FTM_REBUILD_PRIORITY_GROUPS); LLTimer update_timer; LLMemType mt(LLMemType::MTYPE_PIPELINE); - assertInitialized(); gMeshRepo.notifyLoadedMeshes(); @@ -2500,7 +2563,9 @@ void LLPipeline::rebuildPriorityGroups() mGroupQ1Locked = false; } - + +static LLFastTimer::DeclareTimer FTM_REBUILD_GROUPS("Rebuild Groups"); + void LLPipeline::rebuildGroups() { if (mGroupQ2.empty()) @@ -2508,6 +2573,7 @@ void LLPipeline::rebuildGroups() return; } + LLFastTimer t(FTM_REBUILD_GROUPS); mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); @@ -2749,6 +2815,10 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } +static LLFastTimer::DeclareTimer FTM_SHIFT_DRAWABLE("Shift Drawable"); +static LLFastTimer::DeclareTimer FTM_SHIFT_OCTREE("Shift Octree"); +static LLFastTimer::DeclareTimer FTM_SHIFT_HUD("Shift HUD"); + void LLPipeline::shiftObjects(const LLVector3 &offset) { LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS); @@ -2761,35 +2831,46 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) LLVector4a offseta; offseta.load3(offset.mV); - for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); - iter != mShiftList.end(); iter++) { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) + LLFastTimer t(FTM_SHIFT_DRAWABLE); + + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); iter++) { - continue; - } - drawablep->shiftPos(offseta); - drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + LLDrawable *drawablep = *iter; + if (drawablep->isDead()) + { + continue; + } + drawablep->shiftPos(offseta); + drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + } + mShiftList.resize(0); } - mShiftList.resize(0); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + LLFastTimer t(FTM_SHIFT_OCTREE); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { - part->shift(offseta); + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->shift(offseta); + } } } } - LLHUDText::shiftAll(offset); - LLHUDNameTag::shiftAll(offset); + { + LLFastTimer t(FTM_SHIFT_HUD); + LLHUDText::shiftAll(offset); + LLHUDNameTag::shiftAll(offset); + } display_update_camera(); } @@ -2822,8 +2903,10 @@ void LLPipeline::markPartitionMove(LLDrawable* drawable) } } +static LLFastTimer::DeclareTimer FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { + LLFastTimer t(FTM_PROCESS_PARTITIONQ); for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) { LLDrawable* drawable = *iter; @@ -2838,6 +2921,11 @@ void LLPipeline::processPartitionQ() mPartitionQ.clear(); } +void LLPipeline::markMeshDirty(LLSpatialGroup* group) +{ + mMeshDirtyGroup.push_back(group); +} + void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -2934,7 +3022,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) //LLVertexBuffer::unbind(); grabReferences(result); - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -2945,7 +3033,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) else { group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { markVisible(*i, camera); } @@ -2960,9 +3048,9 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { LLSpatialGroup* last_group = NULL; - for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { - LLCullResult::bridge_list_t::iterator cur_iter = i; + LLCullResult::bridge_iterator cur_iter = i; LLSpatialBridge* bridge = *cur_iter; LLSpatialGroup* group = bridge->getSpatialGroup(); @@ -2992,7 +3080,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -3014,7 +3102,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { LLFastTimer ftm(FTM_STATESORT_DRAWABLE); - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable *drawablep = *iter; @@ -3033,7 +3121,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT); if (group->changeLOD()) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; stateSort(drawablep, camera); @@ -3150,13 +3238,13 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } -void forAllDrawables(LLCullResult::sg_list_t::iterator begin, - LLCullResult::sg_list_t::iterator end, +void forAllDrawables(LLCullResult::sg_iterator begin, + LLCullResult::sg_iterator end, void (*func)(LLDrawable*)) { - for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { - for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j) + for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { func(*j); } @@ -3189,7 +3277,11 @@ void renderScriptedBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3215,7 +3307,11 @@ void renderScriptedTouchBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3240,7 +3336,11 @@ void renderPhysicalBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3276,7 +3376,11 @@ void renderMOAPBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3301,7 +3405,11 @@ void renderParticleBeacons(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3319,7 +3427,11 @@ void renderSoundHighlights(LLDrawable* drawablep) S32 count = drawablep->getNumFaces(); for (face_id = 0; face_id < count; face_id++) { - gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } } } } @@ -3334,7 +3446,7 @@ void LLPipeline::postSort(LLCamera& camera) llpushcallstacks ; //rebuild drawable geometry - for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) { LLSpatialGroup* group = *i; if (!sUseOcclusion || @@ -3350,23 +3462,9 @@ void LLPipeline::postSort(LLCamera& camera) rebuildPriorityGroups(); llpushcallstacks ; - const S32 bin_count = 1024*8; - - static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; - static U32 bin_size[bin_count]; - - //clear one bin per frame to avoid memory bloat - static S32 clear_idx = 0; - clear_idx = (1+clear_idx)%bin_count; - alpha_bins[clear_idx].clear(); - - for (U32 j = 0; j < bin_count; j++) - { - bin_size[j] = 0; - } - + //build render map - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (sUseOcclusion && @@ -3436,11 +3534,43 @@ void LLPipeline::postSort(LLCamera& camera) } } } + + //flush particle VB + LLVOPartGroup::sVB->flush(); + + /*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + + if (use_transform_feedback) + { //place a query around potential transform feedback code for synchronization + mTransformFeedbackPrimitives = 0; + + if (!mMeshDirtyQueryObject) + { + glGenQueriesARB(1, &mMeshDirtyQueryObject); + } + + glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); + }*/ + + //pack vertex buffers for groups that chose to delay their updates + for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) + { + (*iter)->rebuildMesh(); + } + + /*if (use_transform_feedback) + { + glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + }*/ + + mMeshDirtyGroup.clear(); + if (!sShadowRender) { std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } + llpushcallstacks ; // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) @@ -3514,7 +3644,11 @@ void LLPipeline::postSort(LLCamera& camera) { if (object->mDrawable) { - gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + LLFace * facep = object->mDrawable->getFace(te); + if (facep) + { + gPipeline.mSelectedFaces.push_back(facep); + } } return true; } @@ -3523,6 +3657,33 @@ void LLPipeline::postSort(LLCamera& camera) } } + /*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); + static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); + if (use_transform_feedback) + { //using transform feedback, wait for transform feedback to complete + LLFastTimer t(FTM_TRANSFORM_WAIT); + + S32 done = 0; + //glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); + + glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); + + while (!done) + { + { + LLFastTimer t(FTM_TRANSFORM_DO_WORK); + F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); + //do some useful work while we wait + LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread + LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread + LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread + } + glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); + } + + mTransformFeedbackPrimitives = 0; + }*/ + //LLSpatialGroup::sNoDelete = FALSE; llpushcallstacks ; } @@ -4005,7 +4166,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED); LLFastTimer t(FTM_RENDER_GEOMETRY); - LLFastTimer t2(FTM_POOLS); + LLFastTimer t2(FTM_DEFERRED_POOLS); LLGLEnable cull(GL_CULL_FACE); @@ -4047,7 +4208,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LLFastTimer t(FTM_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4100,7 +4261,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF); - LLFastTimer t(FTM_POOLS); + LLFastTimer t(FTM_POST_DEFERRED_POOLS); U32 cur_type = 0; LLGLEnable cull(GL_CULL_FACE); @@ -4134,7 +4295,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) pool_set_t::iterator iter2 = iter1; if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) { - LLFastTimer t(FTM_POOLRENDER); + LLFastTimer t(FTM_POST_DEFERRED_POOLRENDER); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); @@ -4324,7 +4485,7 @@ void LLPipeline::renderPhysicsDisplay() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -4419,7 +4580,7 @@ void LLPipeline::renderDebug() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -4671,8 +4832,11 @@ void LLPipeline::renderDebug() } } +static LLFastTimer::DeclareTimer FTM_REBUILD_POOLS("Rebuild Pools"); + void LLPipeline::rebuildPools() { + LLFastTimer t(FTM_REBUILD_POOLS); LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS); assertInitialized(); @@ -6219,7 +6383,10 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); - facep->clearVertexBuffer(); + if (facep) + { + facep->clearVertexBuffer(); + } } } @@ -6228,15 +6395,20 @@ void LLPipeline::resetVertexBuffers() mResetVertexBuffers = true; } +static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); + void LLPipeline::doResetVertexBuffers() { if (!mResetVertexBuffers) { return; } - + + LLFastTimer t(FTM_RESET_VB); mResetVertexBuffers = false; + mCubeVB = NULL; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -6255,11 +6427,15 @@ void LLPipeline::doResetVertexBuffers() gSky.resetVertexBuffers(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); + + if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6279,6 +6455,8 @@ void LLPipeline::doResetVertexBuffers() LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + + LLVOPartGroup::restoreGL(); } void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) @@ -7466,12 +7644,17 @@ void LLPipeline::renderDeferredLighting() std::list<LLVector4> light_colors; LLVertexBuffer::unbind(); - LLVector4a* v = (LLVector4a*) vert.get(); { bindDeferredShader(gDeferredLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); + } + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { @@ -7517,25 +7700,7 @@ void LLPipeline::renderDeferredLighting() } sVisibleLightCount++; - - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - + if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || camera->getOrigin().mV[0] < c[0] - s - 0.2f || camera->getOrigin().mV[1] > c[1] + s + 0.2f || @@ -7553,16 +7718,13 @@ void LLPipeline::renderDeferredLighting() } LLFastTimer ftm(FTM_LOCAL_LIGHTS); - //glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); - //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); stop_glerror(); } } @@ -7575,6 +7737,9 @@ void LLPipeline::renderDeferredLighting() continue; } + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } @@ -7587,7 +7752,7 @@ void LLPipeline::renderDeferredLighting() LLGLDepthTest depth(GL_TRUE, GL_FALSE); bindDeferredShader(gDeferredSpotLightProgram); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); @@ -7605,36 +7770,17 @@ void LLPipeline::renderDeferredLighting() sVisibleLightCount++; - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - setupSpotLight(gDeferredSpotLightProgram, drawablep); LLColor3 col = volume->getLightColor(); - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - mDeferredVB->getVertexStrider(vert); - v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000 - v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001 - v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010 - v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011 - - v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100 - v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101 - v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110 - v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111 - - gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v); + gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s); gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f); gGL.syncMatrices(); - mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center)); + + mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center)); } gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION); unbindDeferredShader(gDeferredSpotLightProgram); @@ -7666,8 +7812,6 @@ void LLPipeline::renderDeferredLighting() LLVector4 light[max_count]; LLVector4 col[max_count]; -// glVertexPointer(2, GL_FLOAT, 0, vert); - F32 far_z = 0.f; while (!fullscreen_lights.empty()) @@ -8324,7 +8468,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera if (use_shader) { - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); } updateCull(shadow_cam, result); @@ -8341,17 +8485,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera stop_glerror(); gGLLastMatrix = NULL; - { - //LLGLDepthTest depth(GL_TRUE); - //glClear(GL_DEPTH_BUFFER_BIT); - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); - //glCullFace(GL_FRONT); - LLVertexBuffer::unbind(); { @@ -8359,6 +8496,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { //occlusion program is general purpose depth-only no-textures gOcclusionProgram.bind(); } + else + { + gDeferredShadowProgram.bind(); + } gGL.diffuseColor4f(1,1,1,1); gGL.setColorMask(false, false); @@ -8408,7 +8549,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera //glCullFace(GL_BACK); - gDeferredShadowProgram.bind(); + gDeferredShadowCubeProgram.bind(); gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); doOcclusion(shadow_cam); @@ -8683,6 +8824,8 @@ void LLPipeline::generateHighlight(LLCamera& camera) } +static LLFastTimer::DeclareTimer FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); + void LLPipeline::generateSunShadow(LLCamera& camera) { if (!sRenderDeferred || RenderShadowDetail <= 0) @@ -8690,6 +8833,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) return; } + LLFastTimer t(FTM_GEN_SUN_SHADOW); + BOOL skip_avatar_update = FALSE; if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) { @@ -9439,7 +9584,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) { - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (!group->isDead() && @@ -9452,6 +9597,12 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu } } +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_SETUP("Impostor Setup"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_BACKGROUND("Impostor Background"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); +static LLFastTimer::DeclareTimer FTM_IMPOSTOR_RESIZE("Impostor Resize"); + void LLPipeline::generateImpostor(LLVOAvatar* avatar) { LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR); @@ -9507,101 +9658,114 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sImpostorRender = TRUE; LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); - markVisible(avatar->mDrawable, *viewer_camera); - LLVOAvatar::sUseImpostors = FALSE; - LLVOAvatar::attachment_map_t::iterator iter; - for (iter = avatar->mAttachmentPoints.begin(); - iter != avatar->mAttachmentPoints.end(); - ++iter) { - LLViewerJointAttachment *attachment = iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + LLFastTimer t(FTM_IMPOSTOR_MARK_VISIBLE); + markVisible(avatar->mDrawable, *viewer_camera); + LLVOAvatar::sUseImpostors = FALSE; + + LLVOAvatar::attachment_map_t::iterator iter; + for (iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); + ++iter) { - if (LLViewerObject* attached_object = (*attachment_iter)) + LLViewerJointAttachment *attachment = iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + if (LLViewerObject* attached_object = (*attachment_iter)) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + } } } } stateSort(*LLViewerCamera::getInstance(), result); - const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); - LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLCamera camera = *viewer_camera; - - camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); - LLVector2 tdim; + U32 resY = 0; + U32 resX = 0; + { + LLFastTimer t(FTM_IMPOSTOR_SETUP); + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); + LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLVector4a half_height; - half_height.setSub(ext[1], ext[0]); - half_height.mul(0.5f); + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); + + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); - LLVector4a left; - left.load3(camera.getLeftAxis().mV); - left.mul(left); - left.normalize3fast(); + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + left.normalize3fast(); - LLVector4a up; - up.load3(camera.getUpAxis().mV); - up.mul(up); - up.normalize3fast(); + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + up.normalize3fast(); - tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); - tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); - F32 distance = (pos-camera.getOrigin()).length(); - F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; - glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); - glh_set_current_projection(persp); - gGL.loadMatrix(persp.m); + F32 distance = (pos-camera.getOrigin()).length(); + F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; + F32 aspect = tdim.mV[0]/tdim.mV[1]; + glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); + glh_set_current_projection(persp); + gGL.loadMatrix(persp.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - glh::matrix4f mat; - camera.getOpenGLTransform(mat.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + glh::matrix4f mat; + camera.getOpenGLTransform(mat.m); - mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; - gGL.loadMatrix(mat.m); - glh_set_current_modelview(mat); + gGL.loadMatrix(mat.m); + glh_set_current_modelview(mat); - glClearColor(0.0f,0.0f,0.0f,0.0f); - gGL.setColorMask(true, true); + glClearColor(0.0f,0.0f,0.0f,0.0f); + gGL.setColorMask(true, true); - // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + // get the number of pixels per angle + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); - //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) - U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); - U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) + resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); + resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); - if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || - resY != avatar->mImpostor.getHeight()) - { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + if (!avatar->mImpostor.isComplete()) + { + LLFastTimer t(FTM_IMPOSTOR_ALLOCATE); + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + + if (LLPipeline::sRenderDeferred) + { + addDeferredAttachments(avatar->mImpostor); + } - if (LLPipeline::sRenderDeferred) + gGL.getTexUnit(0)->bind(&avatar->mImpostor); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else if(resX != avatar->mImpostor.getWidth() || + resY != avatar->mImpostor.getHeight()) { - addDeferredAttachments(avatar->mImpostor); + LLFastTimer t(FTM_IMPOSTOR_RESIZE); + avatar->mImpostor.resize(resX,resY,GL_RGBA); } - - gGL.getTexUnit(0)->bind(&avatar->mImpostor); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - avatar->mImpostor.bindTarget(); + avatar->mImpostor.bindTarget(); + } if (LLPipeline::sRenderDeferred) { @@ -9618,6 +9782,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } { //create alpha mask based on depth buffer (grey out if muted) + LLFastTimer t(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0; @@ -9703,22 +9868,22 @@ BOOL LLPipeline::hasRenderBatches(const U32 type) const return sCull->getRenderMapSize(type) > 0; } -LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) { return sCull->beginRenderMap(type); } -LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) { return sCull->endRenderMap(type); } -LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups() +LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() { return sCull->beginAlphaGroups(); } -LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() +LLCullResult::sg_iterator LLPipeline::endAlphaGroups() { return sCull->endAlphaGroups(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5c623fc9f2..efc94315d7 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -163,6 +163,7 @@ public: void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); void markPartitionMove(LLDrawable* drawablep); + void markMeshDirty(LLSpatialGroup* group); //get the object between start and end that's closest to start. LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, @@ -293,10 +294,10 @@ public: void setLight(LLDrawable *drawablep, BOOL is_light); BOOL hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_list_t::iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); - LLCullResult::sg_list_t::iterator beginAlphaGroups(); - LLCullResult::sg_list_t::iterator endAlphaGroups(); + LLCullResult::drawinfo_iterator beginRenderMap(U32 type); + LLCullResult::drawinfo_iterator endRenderMap(U32 type); + LLCullResult::sg_iterator beginAlphaGroups(); + LLCullResult::sg_iterator endAlphaGroups(); void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); @@ -544,6 +545,9 @@ public: //utility buffer for rendering post effects, gets abused by renderDeferredLighting LLPointer<LLVertexBuffer> mDeferredVB; + //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] + LLPointer<LLVertexBuffer> mCubeVB; + //sun shadow map LLRenderTarget mShadow[6]; std::vector<LLVector3> mShadowFrustPoints[4]; @@ -595,6 +599,7 @@ public: BOOL mVertexShadersEnabled; S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed + U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: BOOL mRenderTypeEnabled[NUM_RENDER_TYPES]; std::stack<std::string> mRenderTypeEnableStack; @@ -652,6 +657,9 @@ protected: LLSpatialGroup::sg_vector_t mGroupQ1; //priority LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called + U32 mMeshDirtyQueryObject; + LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius bool mGroupQ2Locked; diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index d011c7295c..c875b8c652 100644 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -21,7 +21,6 @@ <menu_item_call label="Beschäftigt" name="Set Busy"/> </menu> <menu_item_call label="L$ kaufen..." name="Buy and Sell L$"/> - <menu_item_call label="Händler-Outbox..." name="MerchantOutbox"/> <menu_item_call label="Kontoübersicht..." name="Manage My Account"> <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/> </menu_item_call> diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml index 184f296255..ea44fd493e 100644 --- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml @@ -6,7 +6,7 @@ height="570" help_topic="sidebar_inventory" min_width="333" - min_height="440" + min_height="560" name="floater_my_inventory" save_rect="true" save_visibility="true" diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index ffb8b842f0..2e29c61cb2 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -134,6 +134,26 @@ top_delta="-25" name="Pipette" width="28" /> + <check_box + follows="left|bottom" + height="20" + initial_value="true" + label="Live Preview" + layout="topleft" + left="4" + name="apply_immediate_check" + top="262" + width="120" /> + <text + follows="left|bottom" + height="20" + layout="topleft" + left="8" + name="preview_disabled" + top="266" + value="Preview Disabled" + visible="false" + width="120" /> <filter_editor follows="left|top|right" height="23" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a26c5bb344..e806a40951 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7197,6 +7197,18 @@ You locally updated a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] <notification icon="alertmodal.tga" + name="LivePreviewUnavailable" + type="alert"> + +We cannot display a preview of this texture because it is no-copy and/or no-transfer. + <usetemplate + ignoretext="Warn me that Live Preview mode is not available for no-copy and/or no-transfer textures" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="ConfirmLeaveCall" type="alert"> Are you sure you want to leave this call? diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index 54a312bd59..c5dfb703e5 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -11,6 +11,10 @@ name="unknown"> (unknown) </panel.string> + <panel.string + name="unknown_multiple"> + (unknown / multiple) + </panel.string> <panel.string name="public"> (public) |