diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 7bb64a15a..5b54db867 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -31,10 +31,6 @@ if (WINDOWS) # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) - if (MSVC10) - set(MSVC100 TRUE) - endif (MSVC10) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd" CACHE STRING "C++ compiler debug options" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO @@ -69,10 +65,9 @@ if (WINDOWS) /Zc:forScope /nologo /Oy- - /Zc:wchar_t- ) - if(MSVC80 OR MSVC90 OR MSVC100) + if(MSVC80 OR MSVC90 OR MSVC10) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" CACHE STRING "C++ compiler release options" FORCE) @@ -82,7 +77,10 @@ if (WINDOWS) set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" CACHE STRING "C compiler release-SSE2 options" FORCE) - endif (MSVC80 OR MSVC90 OR MSVC100) + add_definitions( + /Zc:wchar_t- + ) + endif (MSVC80 OR MSVC90 OR MSVC10) # Are we using the crummy Visual Studio KDU build workaround? if (NOT VS_DISABLE_FATAL_WARNINGS) diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 9aa4b857e..780ed9830 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -426,7 +426,16 @@ protected: template class LLSingleton { + static bool &needsInit() + { + static bool needs_init = true; + return needs_init; + } public: + static bool instanceExists() + { + return !needsInit(); + } virtual ~LLSingleton() {} #ifdef LL_MSVC7 // workaround for VC7 compiler bug @@ -445,7 +454,7 @@ public: #endif { static T instance; - static bool needs_init = true; + bool &needs_init = needsInit(); if (needs_init) { needs_init = false; diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index 369b06b48..44ea80a36 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -51,7 +51,7 @@ public: void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} void skip(const U32 index) { mBytep += mSkip*index;} - + U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } Object* operator->() { return mObjectp; } Object& operator *() { return *mObjectp; } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1263ac83c..1106c3ced 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -59,11 +59,13 @@ BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; +BOOL gGLActive = FALSE; LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 LLGLNamePool::pool_list_t LLGLNamePool::sInstances; +std::list LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS // ATI prototypes diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 27116e088..1f1d8c3c4 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -361,6 +361,35 @@ protected: virtual void releaseName(GLuint name) = 0; }; +/* + Interface for objects that need periodic GL updates applied to them. + Used to synchronize GL updates with GL thread. +*/ +class LLGLUpdate +{ +public: + + static std::list sGLQ; + + BOOL mInQ; + LLGLUpdate() + : mInQ(FALSE) + { + } + virtual ~LLGLUpdate() + { + if (mInQ) + { + std::list::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this); + if (iter != sGLQ.end()) + { + sGLQ.erase(iter); + } + } + } + virtual void updateGL() = 0; +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" @@ -379,4 +408,6 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gNoRender; +extern BOOL gGLActive; + #endif // LL_LLGL_H diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index ffa25b425..60c3582d8 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -352,8 +352,21 @@ void LLImageGL::restoreGL() } } +//static +void LLImageGL::dirtyTexOptions() +{ + for (std::set::iterator iter = sImageList.begin(); + iter != sImageList.end(); iter++) + { + LLImageGL* glimage = *iter; + glimage->mTexOptionsDirty = true; + stop_glerror(); + } + +} //---------------------------------------------------------------------------- +//for server side use only. //static BOOL LLImageGL::create(LLPointer& dest, BOOL usemipmaps) { @@ -361,12 +374,14 @@ BOOL LLImageGL::create(LLPointer& dest, BOOL usemipmaps) return TRUE; } +//for server side use only. BOOL LLImageGL::create(LLPointer& dest, U32 width, U32 height, U8 components, BOOL usemipmaps) { dest = new LLImageGL(width, height, components, usemipmaps); return TRUE; } +//for server side use only. BOOL LLImageGL::create(LLPointer& dest, const LLImageRaw* imageraw, BOOL usemipmaps) { dest = new LLImageGL(imageraw, usemipmaps); diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 478d74cb1..6cb9dd314 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -68,6 +68,7 @@ public: // Save off / restore GL textures static void destroyGL(BOOL save_state = TRUE); static void restoreGL(); + static void dirtyTexOptions(); // Sometimes called externally for textures not using LLImageGL (should go away...) static S32 updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) ; @@ -137,6 +138,7 @@ public: BOOL getBoundRecently() const; BOOL isJustBound() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } + LLGLenum getFormatType() const { return mFormatType; } BOOL getHasGLTexture() const { return mTexName != 0; } LLGLuint getTexName() const { return mTexName; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 756603a32..8d927ada5 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -56,6 +56,7 @@ U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; S32 LLVertexBuffer::sGLCount = 0; S32 LLVertexBuffer::sMappedCount = 0; +BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ; BOOL LLVertexBuffer::sEnableVBOs = TRUE; U32 LLVertexBuffer::sGLRenderBuffer = 0; U32 LLVertexBuffer::sGLRenderIndices = 0; @@ -287,9 +288,21 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const } //static -void LLVertexBuffer::initClass(bool use_vbo) +void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { - sEnableVBOs = use_vbo; + sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ; + if(sEnableVBOs) + { + //llassert_always(glBindBufferARB) ; //double check the extention for VBO is loaded. + + llinfos << "VBO is enabled." << llendl ; + } + else + { + llinfos << "VBO is disabled." << llendl ; + } + + sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; LLGLNamePool::registerPool(&sDynamicVBOPool); LLGLNamePool::registerPool(&sDynamicIBOPool); LLGLNamePool::registerPool(&sStreamVBOPool); @@ -346,7 +359,9 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mGLBuffer(0), mGLIndices(0), mMappedData(NULL), - mMappedIndexData(NULL), mLocked(FALSE), + mMappedIndexData(NULL), + mVertexLocked(FALSE), + mIndexLocked(FALSE), mFinal(FALSE), mFilthy(FALSE), mEmpty(TRUE), @@ -544,6 +559,8 @@ void LLVertexBuffer::destroyGLBuffer() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped!" << llendl; @@ -571,6 +588,8 @@ void LLVertexBuffer::destroyGLIndices() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped." << llendl; @@ -768,6 +787,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) if (mResized && useVBOs()) { + freeClientBuffer() ; setBuffer(0); } } @@ -782,104 +802,228 @@ BOOL LLVertexBuffer::useVBOs() const } //---------------------------------------------------------------------------- +void LLVertexBuffer::freeClientBuffer() +{ + if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) + { + delete[] mMappedData ; + delete[] mMappedIndexData ; + mMappedData = NULL ; + mMappedIndexData = NULL ; + } +} + +void LLVertexBuffer::allocateClientVertexBuffer() +{ + if(!mMappedData) + { + U32 size = getSize() ; + mMappedData = new U8[size]; + memset((void*)mMappedData, 0, size); + } +} + +void LLVertexBuffer::allocateClientIndexBuffer() +{ + if(!mMappedIndexData) + { + U32 size = getIndicesSize(); + mMappedIndexData = new U8[size]; + memset((void*)mMappedIndexData, 0, size); + } +} // Map for data access -volatile U8* LLVertexBuffer::mapBuffer(S32 access) +volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { - llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; + llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { - llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; + llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl; } - if (!mLocked && useVBOs()) + if (!mVertexLocked && useVBOs()) { - setBuffer(0); - mLocked = TRUE; - stop_glerror(); - mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - stop_glerror(); - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - stop_glerror(); + { + setBuffer(0, type); + mVertexLocked = TRUE; + stop_glerror(); + if(sDisableVBOMapping) + { + allocateClientVertexBuffer() ; + } + else + { + mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + stop_glerror(); + } + if (!mMappedData) { - //-------------------- - //print out more debug info before crash - llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; - GLint size ; - glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; - llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; - //-------------------- - - GLint buff; - glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLBuffer) + if(!sDisableVBOMapping) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + //-------------------- + //print out more debug info before crash + llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; + GLint size ; + glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; + llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; + //-------------------- + + GLint buff; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); + if ((GLuint)buff != mGLBuffer) + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } + + + llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; } - - - llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; - } - - if (!mMappedIndexData) - { - GLint buff; - glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLIndices) + else { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + llerrs << "memory allocation for vertex data failed." << llendl ; } - - llerrs << "glMapBuffer returned NULL (no index data)" << llendl; } - sMappedCount++; } return mMappedData; } -void LLVertexBuffer::unmapBuffer() +volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); - if (mMappedData || mMappedIndexData) + if (mFinal) { - if (useVBOs() && mLocked) + llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl; + } + if (!useVBOs() && !mMappedData && !mMappedIndexData) + { + llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl; + } + + if (!mIndexLocked && useVBOs()) + { + { + + setBuffer(0, TYPE_INDEX); + mIndexLocked = TRUE; + stop_glerror(); + + if(sDisableVBOMapping) + { + allocateClientIndexBuffer() ; + } + else + { + mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + stop_glerror(); + } + + if (!mMappedIndexData) + { + + if(!sDisableVBOMapping) + { + GLint buff; + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); + if ((GLuint)buff != mGLIndices) + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } + + llerrs << "glMapBuffer returned NULL (no index data)" << llendl; + } + else + { + llerrs << "memory allocation for Index data failed. " << llendl ; + } + } + + sMappedCount++; + } + + return mMappedIndexData ; +} + +void LLVertexBuffer::unmapBuffer(S32 type) +{ + LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + if (!useVBOs()) + { + return ; //nothing to unmap + } + + bool updated_all = false ; + if (mMappedData && mVertexLocked && type != TYPE_INDEX) + { + updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating + + if(sDisableVBOMapping) + { + stop_glerror(); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (void*)mMappedData); + stop_glerror(); + } + else { stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); + + mMappedData = NULL; + } + + mVertexLocked = FALSE ; + sMappedCount--; + } + + if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX)) + { + if(sDisableVBOMapping) + { + stop_glerror(); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (void*)mMappedIndexData); + stop_glerror(); + } + else + { + stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); - /*if (!sMapped) - { - llerrs << "Redundantly unmapped VBO!" << llendl; - } - sMapped = FALSE;*/ - sMappedCount--; + mMappedIndexData = NULL ; + } - if (mUsage == GL_STATIC_DRAW_ARB) - { //static draw buffers can only be mapped a single time - //throw out client data (we won't be using it again) - mEmpty = TRUE; - mFinal = TRUE; - } - else - { - mEmpty = FALSE; - } + mIndexLocked = FALSE ; + sMappedCount--; + } - mMappedIndexData = NULL; - mMappedData = NULL; - - mLocked = FALSE; + if(updated_all) + { + if(mUsage == GL_STATIC_DRAW_ARB) + { + //static draw buffers can only be mapped a single time + //throw out client data (we won't be using it again) + mEmpty = TRUE; + mFinal = TRUE; + + if(sDisableVBOMapping) + { + freeClientBuffer() ; + } + } + else + { + mEmpty = FALSE; } } } @@ -893,15 +1037,16 @@ template struct VertexBufferStrider strider_t& strider, S32 index) { - if (vbo.mapBuffer() == NULL) - { - llwarns << "mapBuffer failed!" << llendl; - return FALSE; - } - if (type == LLVertexBuffer::TYPE_INDEX) { S32 stride = sizeof(T); + + if (vbo.mapIndexBuffer() == NULL) + { + llwarns << "mapIndexBuffer failed!" << llendl; + return FALSE; + } + strider = (T*)(vbo.getMappedIndices() + index*stride); strider.setStride(0); return TRUE; @@ -909,6 +1054,13 @@ template struct VertexBufferStrider else if (vbo.hasDataType(type)) { S32 stride = vbo.getStride(); + + if (vbo.mapVertexBuffer(type) == NULL) + { + llwarns << "mapVertexBuffer failed!" << llendl; + return FALSE; + } + strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); strider.setStride(stride); return TRUE; @@ -989,7 +1141,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride) //---------------------------------------------------------------------------- // Set for rendering -void LLVertexBuffer::setBuffer(U32 data_mask) +void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); //set up pointers if the data mask is different ... @@ -1023,6 +1175,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) sIBOActive = TRUE; } + BOOL error = FALSE; if (gDebugGL) { GLint buff; @@ -1085,7 +1238,11 @@ void LLVertexBuffer::setBuffer(U32 data_mask) } } - unmapBuffer(); + if (error) + { + llerrs << "LLVertexBuffer::mapBuffer failed" << llendl; + } + unmapBuffer(type); } else { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 4cd8087c3..c7984e615 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -88,7 +88,7 @@ public: static BOOL sUseStreamDraw; static BOOL sOmitBlank; - static void initClass(bool use_vbo); + static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void clientCopy(F64 max_time = 0.005); //copy data from client to GL @@ -147,15 +147,20 @@ protected: void updateNumVerts(S32 nverts); void updateNumIndices(S32 nindices); virtual BOOL useVBOs() const; - void unmapBuffer(); + void unmapBuffer(S32 type); + void freeClientBuffer() ; + void allocateClientVertexBuffer() ; + void allocateClientIndexBuffer() ; public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - volatile U8* mapBuffer(S32 access = -1); + volatile U8* mapVertexBuffer(S32 type = -1, S32 access = -1); + volatile U8* mapIndexBuffer(S32 access = -1); + // set for rendering - virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 + virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0 // allocate buffer void allocateBuffer(S32 nverts, S32 nindices, bool create); virtual void resizeBuffer(S32 newnverts, S32 newnindices); @@ -178,7 +183,7 @@ public: bool getClothWeightStrider(LLStrider& strider, S32 index=0); BOOL isEmpty() const { return mEmpty; } - BOOL isLocked() const { return mLocked; } + BOOL isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } S32 getRequestedVerts() const { return mRequestedNumVerts; } @@ -217,13 +222,14 @@ protected: U32 mGLIndices; // GL IBO handle volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) - BOOL mLocked; // if TRUE, buffer is being or has been written to in client memory + BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory + BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory BOOL mFinal; // if TRUE, buffer can not be mapped again BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags) - BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. - S32 mOffsets[TYPE_MAX]; + BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) + S32 mOffsets[TYPE_MAX]; class DirtyRegion { @@ -248,13 +254,14 @@ public: static std::vector sDeleteList; typedef std::list buffer_list_t; + static BOOL sDisableVBOMapping; //disable glMapBufferARB static BOOL sEnableVBOs; + static BOOL sVBOActive; + static BOOL sIBOActive; static S32 sTypeOffsets[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; - static U32 sGLRenderIndices; - static BOOL sVBOActive; - static BOOL sIBOActive; + static U32 sGLRenderIndices; static U32 sLastMask; static U32 sAllocatedBytes; static U32 sBindCount; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ca1deb3e7..2057d827c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9832,6 +9832,17 @@ Value 1 + RenderVBOMappingDisable + + Comment + Disable VBO glMapBufferARB + Persist + 1 + Type + Boolean + Value + 1 + RenderVolumeLODFactor Comment @@ -12789,6 +12800,17 @@ Value 1 + SkipReflectOcclusionUpdates + + Comment + Enable optimization that prevents occlusion updates for refelction pass + Persist + 1 + Type + Boolean + Value + 1 + UseOutfitFolders Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index a91e9fa15..7c8d238d2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -71,14 +71,14 @@ void main() color.rgb = scaleSoftClip(color.rgb); - if (samp_pos.z != 0.0) + /*if (samp_pos.z != 0.0) { float dist_factor = alpha_soften; float a = gl_Color.a; a *= a; dist_factor *= 1.0/(1.0-a); color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } + }*/ //gl_FragColor = gl_Color; gl_FragColor = color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index b496bd674..9f130ee42 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -37,8 +37,8 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Add windlight lights col.rgb = atmosAmbient(vec3(0.)); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 58aa5a9cb..b5daef03e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -12,7 +12,14 @@ varying vec4 vary_position; void main() { - gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 diff = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); + + if (diff.a < 0.2) + { + discard; + } + + gl_FragData[0] = vec4(diff.rgb, 0.0); gl_FragData[1] = vec4(0,0,0,0); gl_FragData[2] = vec4(normalize(vary_normal), 0.0); gl_FragData[3] = vary_position; diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 20a3f3df5..4e3e635f1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -13,7 +13,8 @@ varying vec4 vary_position; void main() { - gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = vec4(col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z); gl_FragData[3] = vary_position; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 3689d1284..c8248b294 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -77,6 +77,12 @@ void main() //attenuate point light contribution by SSAO component out_col *= texture2DRect(lightMap, frag.xy).g; + + + if (dot(out_col, out_col) <= 0.0) + { + discard; + } gl_FragColor.rgb = out_col; gl_FragColor.a = 0.0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 52bad1f34..68f376d69 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -69,6 +69,11 @@ void main() //attenuate point light contribution by SSAO component col *= texture2DRect(lightMap, frag.xy).g; + if (dot(col, col) <= 0.0) + { + discard; + } + gl_FragColor.rgb = col; gl_FragColor.a = 0.0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index bc2c9816d..ea70eabf5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -13,7 +13,7 @@ varying vec4 vary_position; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); - gl_FragData[0] = gl_Color*col; + gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); gl_FragData[2] = vec4(normalize(vary_normal), 0.0); gl_FragData[3] = vary_position; diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 0a1f019e3..83959101e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#extension GL_ARB_texture_rectangle : enable vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); @@ -32,6 +33,7 @@ uniform vec3 normScale; uniform float fresnelScale; uniform float fresnelOffset; uniform float blurMultiplier; +uniform mat4 norm_mat; //region space to screen space //bigWave is (refCoord.w, view.w); @@ -88,7 +90,7 @@ void main() refcol *= df1 * 0.333; vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - wavef.z *= max(-viewVec.z, 0.1); +// wavef.z *= max(-viewVec.z, 0.1); wavef = normalize(wavef); float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; @@ -101,10 +103,10 @@ void main() refcol = mix(baseCol*df2, refcol, dweight); //get specular component - float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); +// float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); //harden specular - spec = pow(spec, 128.0); +// spec = pow(spec, 128.0); //figure out distortion vector (ripply) vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); @@ -118,13 +120,13 @@ void main() float shadow = 1.0; vec4 pos = vary_position; - vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - if (pos.z > -shadow_clip.w) - { +// if (pos.z > -shadow_clip.w) +// { vec4 spos = pos; - if (pos.z < -shadow_clip.z) +/* if (pos.z < -shadow_clip.z) { vec4 lpos = (shadow_matrix[3]*spos); shadow = shadow2DProj(shadowMap3, lpos).x; @@ -144,14 +146,19 @@ void main() vec4 lpos = (shadow_matrix[0]*spos); shadow = shadow2DProj(shadowMap0, lpos).x; } - } + }*/ - spec *= shadow; - color.rgb += spec * specular; +// spec *= shadow; +// color.rgb += spec * specular; - color.rgb = atmosTransport(color.rgb); - color.rgb = scaleSoftClip(color.rgb); - color.a = spec * sunAngle2; +// color.rgb = atmosTransport(color.rgb); +// color.rgb = scaleSoftClip(color.rgb); +// color.a = spec * sunAngle2; - gl_FragColor = color; +// gl_FragColor = color; + vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; + + gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse + gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec + gl_FragData[2] = vec4(screenspacewavef, 0.0); // normalxyz, displace } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2fc5e99bd..e465f338b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -180,6 +180,7 @@ #include "llinventoryview.h" #include "llcommandlineparser.h" +#include "llprogressview.h" // [RLVa:KB] #include "rlvhandler.h" @@ -734,6 +735,7 @@ bool LLAppViewer::init() // // Initialize the window // + gGLActive = TRUE; initWindow(); // call all self-registered classes @@ -875,7 +877,8 @@ bool LLAppViewer::mainLoop() { LLFastTimer t(LLFastTimer::FTM_FRAME); pingMainloopTimeout("Main:MiscNativeWindowEvents"); - + + if (gViewerWindow) { LLFastTimer t2(LLFastTimer::FTM_MESSAGES); gViewerWindow->mWindow->processMiscNativeEvents(); @@ -883,6 +886,7 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:GatherInput"); + if (gViewerWindow) { LLFastTimer t2(LLFastTimer::FTM_MESSAGES); if (!restoreErrorTrap()) @@ -958,11 +962,12 @@ bool LLAppViewer::mainLoop() if (!LLApp::isExiting()) { pingMainloopTimeout("Main:Display"); + gGLActive = TRUE; display(); pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots - + gGLActive = FALSE; #if LL_LCD_COMPILE // update LCD Screen pingMainloopTimeout("Main:LCD"); @@ -989,7 +994,7 @@ bool LLAppViewer::mainLoop() // yield cooperatively when not running as foreground window if ( gNoRender - || !gViewerWindow->mWindow->getVisible() + || (gViewerWindow && !gViewerWindow->mWindow->getVisible()) || !gFocusMgr.getAppHasFocus()) { // Sleep if we're not rendering, or the window is minimized. @@ -1141,11 +1146,14 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; // Must clean up texture references before viewer window is destroyed. - LLHUDManager::getInstance()->updateEffects(); - LLHUDObject::updateAll(); - LLHUDManager::getInstance()->cleanupEffects(); - LLHUDObject::cleanupHUDObjects(); - llinfos << "HUD Objects cleaned up" << llendflush; + if(LLHUDManager::instanceExists()) + { + LLHUDManager::getInstance()->updateEffects(); + LLHUDObject::updateAll(); + LLHUDManager::getInstance()->cleanupEffects(); + LLHUDObject::cleanupHUDObjects(); + llinfos << "HUD Objects cleaned up" << llendflush; + } LLKeyframeDataCache::clear(); @@ -1157,8 +1165,10 @@ bool LLAppViewer::cleanup() // Note: this is where gWorldMap used to be deleted. // Note: this is where gHUDManager used to be deleted. - LLHUDManager::getInstance()->shutdownClass(); - + if(LLHUDManager::instanceExists()) + { + LLHUDManager::getInstance()->shutdownClass(); + } delete gAssetStorage; gAssetStorage = NULL; @@ -1247,21 +1257,25 @@ bool LLAppViewer::cleanup() llinfos << "Shutting down." << llendflush; // Destroy the UI - gViewerWindow->shutdownViews(); + if( gViewerWindow) + gViewerWindow->shutdownViews(); // Clean up selection managers after UI is destroyed, as UI may be observing them. // Clean up before GL is shut down because we might be holding on to objects with texture references LLSelectMgr::cleanupGlobals(); // Shut down OpenGL - gViewerWindow->shutdownGL(); + if( gViewerWindow) + { + gViewerWindow->shutdownGL(); - // Destroy window, and make sure we're not fullscreen - // This may generate window reshape and activation events. - // Therefore must do this before destroying the message system. - delete gViewerWindow; - gViewerWindow = NULL; - llinfos << "ViewerWindow deleted" << llendflush; + // Destroy window, and make sure we're not fullscreen + // This may generate window reshape and activation events. + // Therefore must do this before destroying the message system. + delete gViewerWindow; + gViewerWindow = NULL; + llinfos << "ViewerWindow deleted" << llendflush; + } // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; @@ -1369,6 +1383,9 @@ bool LLAppViewer::cleanup() writeDebugInfo(); + // Stop the plugin read thread if it's running. + LLPluginProcessParent::setUseReadThread(false); + // Let threads finish LLTimer idleTimer; idleTimer.reset(); @@ -1394,8 +1411,8 @@ bool LLAppViewer::cleanup() // Delete workers first // shotdown all worker threads before deleting them in case of co-dependencies - sTextureCache->shutdown(); sTextureFetch->shutdown(); + sTextureCache->shutdown(); sImageDecodeThread->shutdown(); sTextureFetch->shutDownTextureCacheThread(); sTextureFetch->shutDownImageDecodeThread(); @@ -1424,7 +1441,10 @@ bool LLAppViewer::cleanup() #ifndef LL_RELEASE_FOR_DOWNLOAD llinfos << "Auditing VFS" << llendl; - gVFS->audit(); + if(gVFS) + { + gVFS->audit(); + } #endif // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up. @@ -2525,7 +2545,7 @@ void LLAppViewer::handleViewerCrash() gMessageSystem->stopLogging(); } - LLWorld::getInstance()->getInfo(gDebugInfo); + if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo); // Close the debug file pApp->writeDebugInfo(); @@ -2692,6 +2712,13 @@ void LLAppViewer::requestQuit() if( (LLStartUp::getStartupState() < STATE_STARTED) || !region ) { + // If we have a region, make some attempt to send a logout request first. + // This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes. + if(region) + { + sendLogoutRequest(); + } + // Quit immediately forceQuit(); return; @@ -2731,6 +2758,11 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q void LLAppViewer::userQuit() { + if (gDisconnected || gViewerWindow->getProgressView()->getVisible()) + { + requestQuit(); + } + else LLNotifications::instance().add("ConfirmQuit"); } @@ -3311,10 +3343,13 @@ void LLAppViewer::idle() if (LLStartUp::getStartupState() < STATE_STARTED) { // Skip rest if idle startup returns false (essentially, no world yet) + gGLActive = TRUE; if (!idle_startup()) { + gGLActive = FALSE; return; } + gGLActive = FALSE; } @@ -3641,6 +3676,7 @@ void LLAppViewer::idle() // forcibly quit if it has taken too long if (mQuitRequested) { + gGLActive = TRUE; idleShutdown(); } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 2ae30f9da..a425e30de 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -384,8 +384,6 @@ void LLDrawable::makeActive() mParent->makeActive(); } - gPipeline.setActive(this, TRUE); - //all child objects must also be active llassert_always(mVObjp); @@ -432,7 +430,6 @@ void LLDrawable::makeStatic(BOOL warning_enabled) if (isState(ACTIVE)) { clearState(ACTIVE); - gPipeline.setActive(this, FALSE); if (mParent.notNull() && mParent->isActive() && warning_enabled) { @@ -676,6 +673,11 @@ BOOL LLDrawable::updateMoveDamped() void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { + if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + llerrs << "WTF?" << llendl; + } + //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); @@ -953,11 +955,31 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() return retval; } +const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one. +//static +S32 LLDrawable::getMinVisFrameRange() +{ + return MIN_VIS_FRAME_RANGE ; +} + BOOL LLDrawable::isRecentlyVisible() const { //currently visible or visible in the previous frame. - return isVisible() || (mVisible == sCurVisible - 1) ; + BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ; + + if(!vis) + { + LLSpatialGroup* group = getSpatialGroup(); + if (group && group->isRecentlyVisible()) + { + mVisible = sCurVisible; + vis = TRUE ; + } + } + + return vis ; } + BOOL LLDrawable::isVisible() const { if (mVisible == sCurVisible) @@ -1007,8 +1029,8 @@ BOOL LLDrawable::isVisible() const // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask) -: LLSpatialPartition(data_mask, FALSE) +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) +: LLSpatialPartition(data_mask, render_by_group, FALSE) { mDrawable = root; root->setSpatialBridge(this); @@ -1019,8 +1041,12 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask) mPartitionType = LLViewerRegion::PARTITION_VOLUME; mOctree->balance(); + LLSpatialPartition *part = mDrawable->getRegion()->getSpatialPartition(mPartitionType); - mDrawable->getRegion()->getSpatialPartition(mPartitionType)->put(this); + if (part) + { + part->put(this); + } } LLSpatialBridge::~LLSpatialBridge() @@ -1334,8 +1360,13 @@ void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL imm BOOL LLSpatialBridge::updateMove() { + LLSpatialPartition* part = mDrawable->getRegion()->getSpatialPartition(mPartitionType); + llassert_always(part); mOctree->balance(); - mDrawable->getRegion()->getSpatialPartition(mPartitionType)->move(this, getSpatialGroup(), TRUE); + if (part) + { + part->move(this, getSpatialGroup(), TRUE); + } return TRUE; } @@ -1439,9 +1470,8 @@ void LLDrawable::updateFaceSize(S32 idx) } LLBridgePartition::LLBridgePartition() -: LLSpatialPartition(0, TRUE) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; mLODPeriod = 16; diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 2d693b6d2..47bbcf1c1 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -281,6 +281,7 @@ public: S32 mQuietCount; static S32 getCurrentFrame() { return sCurVisible; } + static S32 getMinVisFrameRange(); void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 342173159..243c51eb9 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -482,7 +482,8 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { if (params.mTexture.notNull()) { - gGL.getTexUnit(0)->bind(params.mTexture.get(), TRUE); + params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; if (params.mTextureMatrix) { glMatrixMode(GL_TEXTURE); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 4b552acd5..c93f64c0a 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -61,7 +61,9 @@ static BOOL deferred_render = FALSE; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), - simple_shader(NULL), fullbright_shader(NULL) + simple_shader(NULL), fullbright_shader(NULL), + mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), + mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) { } @@ -88,22 +90,23 @@ void LLDrawPoolAlpha::beginDeferredPass(S32 pass) void LLDrawPoolAlpha::endDeferredPass(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); + +} + +void LLDrawPoolAlpha::renderDeferred(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); gDeferredTreeProgram.bind(); LLGLEnable test(GL_ALPHA_TEST); //render alpha masked objects LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + gDeferredTreeProgram.unbind(); } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } -void LLDrawPoolAlpha::renderDeferred(S32 pass) -{ - -} - S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { @@ -178,8 +181,15 @@ void LLDrawPoolAlpha::render(S32 pass) LLGLSPipelineAlpha gls_pipeline_alpha; + gGL.setColorMask(true, true); if (LLPipeline::sFastAlpha && !deferred_render) { + mColorSFactor = LLRender::BF_ONE; // } + mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow + mAlphaSFactor = LLRender::BF_ZERO; + mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); if (mVertexShaderLevel > 0) { @@ -203,8 +213,17 @@ void LLDrawPoolAlpha::render(S32 pass) } LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); + + mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend + mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression + mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + renderAlpha(getVertexDataMask()); + gGL.setColorMask(true, false); + if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); @@ -283,6 +302,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (group->mSpatialPartition->mRenderByGroup && !group->isDead()) { + bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. + // All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress. + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD && + group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) @@ -291,88 +316,115 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLRenderPass::applyModelMatrix(params); - if (params.mTexture.notNull()) { - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(params.mTexture.get()); - - if (params.mTextureMatrix) + if (params.mFullbright) { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + // Turn off lighting if it hasn't already been so. + if (light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = fullbright_shader; + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + light_enabled = FALSE; + } } - } - - if (params.mFullbright) - { - // Turn off lighting if it hasn't already been so. - if (light_enabled || !initialized_lighting) + // Turn on lighting if it isn't already. + else if (!light_enabled || !initialized_lighting) { initialized_lighting = TRUE; if (use_shaders) { - target_shader = fullbright_shader; + target_shader = simple_shader; } else { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + gPipeline.enableLightsDynamic(); } - light_enabled = FALSE; + light_enabled = TRUE; } - } - // Turn on lighting if it isn't already. - else if (!light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } - light_enabled = TRUE; - } - // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) - { - llassert(target_shader != NULL); - if (deferred_render && current_shader != NULL) + // If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + if(use_shaders && (current_shader != target_shader)) { - gPipeline.unbindDeferredShader(*current_shader); + llassert(target_shader != NULL); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + } + current_shader = target_shader; + if (deferred_render) + { + gPipeline.bindDeferredShader(*current_shader); + } + else + { + current_shader->bind(); + } } - current_shader = target_shader; - if (deferred_render) + else if (!use_shaders && current_shader != NULL) { - gPipeline.bindDeferredShader(*current_shader); + + if (deferred_render) + { + gPipeline.unbindDeferredShader(*current_shader); + } + LLGLSLShader::bindNoShader(); + current_shader = NULL; } - else - { - current_shader->bind(); - } - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - if (deferred_render) - { - gPipeline.unbindDeferredShader(*current_shader); - } - current_shader = NULL; - } - if (params.mGroup) - { - params.mGroup->rebuildMesh(); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + + + if (params.mTexture.notNull()) + { + gGL.getTexUnit(0)->bind(params.mTexture.get()); + if(params.mTexture.notNull()) + { + params.mTexture->addTextureStats(params.mVSize); + } + if (params.mTextureMatrix) + { + gGL.getTexUnit(0)->activate(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); + + // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. + if (draw_glow_for_this_partition && + params.mGlowColor.mV[3] > 0) + { + // install glow-accumulating blend mode + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color + LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) + // glow doesn't use vertex colors from the mesh data + params.mVertexBuffer->setBuffer(mask & ~LLVertexBuffer::MAP_COLOR); + glColor4ubv(params.mGlowColor.mV); + + // do the actual drawing, again + params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount/3); + + // restore our alpha blend mode + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + } + if (params.mTextureMatrix && params.mTexture.notNull()) { gGL.getTexUnit(0)->activate(); @@ -383,6 +435,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + if (!light_enabled) { gPipeline.enableLightsDynamic(); diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index 3aa752f72..c3aca964d 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -83,6 +83,12 @@ private: LLGLSLShader* target_shader; LLGLSLShader* simple_shader; LLGLSLShader* fullbright_shader; + + // our 'normal' alpha blend function for this pass + LLRender::eBlendFactor mColorSFactor; + LLRender::eBlendFactor mColorDFactor; + LLRender::eBlendFactor mAlphaSFactor; + LLRender::eBlendFactor mAlphaDFactor; }; class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 38996e624..97daff8aa 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -158,8 +158,8 @@ S32 LLDrawPoolAvatar::getNumDeferredPasses() void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); - + sSkipTransparent = TRUE; + if (LLPipeline::sImpostorRender) { beginDeferredSkinned(); @@ -182,7 +182,7 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) void LLDrawPoolAvatar::endDeferredPass(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + sSkipTransparent = FALSE; if (LLPipeline::sImpostorRender) { @@ -317,6 +317,10 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } @@ -353,7 +357,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) switch (pass) { case 0: - beginFootShadow(); + beginImpostor(); break; case 1: beginRigid(); @@ -377,7 +381,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) switch (pass) { case 0: - endFootShadow(); + endImpostor(); break; case 1: endRigid(); @@ -387,7 +391,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) } } -void LLDrawPoolAvatar::beginFootShadow() +void LLDrawPoolAvatar::beginImpostor() { if (!LLPipeline::sReflectionRender) { @@ -398,7 +402,7 @@ void LLDrawPoolAvatar::beginFootShadow() gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); } -void LLDrawPoolAvatar::endFootShadow() +void LLDrawPoolAvatar::endImpostor() { gPipeline.enableLightsDynamic(); } @@ -568,7 +572,6 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginDeferredSkinned() { - sSkipTransparent = TRUE; sShaderLevel = mVertexShaderLevel; sVertexProgram = &gDeferredAvatarProgram; @@ -583,7 +586,6 @@ void LLDrawPoolAvatar::beginDeferredSkinned() void LLDrawPoolAvatar::endDeferredSkinned() { - sSkipTransparent = FALSE; // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 1e2630e1f..e12f5081f 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -90,11 +90,11 @@ public: /*virtual*/ void renderShadow(S32 pass); void beginRigid(); - void beginFootShadow(); + void beginImpostor(); void beginSkinned(); void endRigid(); - void endFootShadow(); + void endImpostor(); void endSkinned(); void beginDeferredImpostor(); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 14931024e..7ca763a18 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -263,7 +263,7 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass) void LLDrawPoolGrass::renderDeferred(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index bed103047..63e24ec8a 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -49,8 +49,11 @@ #include "pipeline.h" #include "llviewershadermgr.h" -LLDrawPoolSky::LLDrawPoolSky() : - LLFacePool(POOL_SKY), mShader(NULL) +LLDrawPoolSky::LLDrawPoolSky() +: LLFacePool(POOL_SKY), + + mSkyTex(NULL), + mShader(NULL) { } diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 019d1328e..833c74873 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -73,19 +73,19 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); - gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); + //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c", TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); - gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); + //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } LLDrawPoolTerrain::~LLDrawPoolTerrain() diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 2f3833dd6..f08e22569 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -52,7 +52,6 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : LLFacePool(POOL_TREE), mTexturep(texturep) { - gGL.getTexUnit(0)->bind(mTexturep.get()); mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } @@ -142,8 +141,8 @@ void LLDrawPoolTree::endRenderPass(S32 pass) void LLDrawPoolTree::beginDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); + shader = &gDeferredTreeProgram; shader->bind(); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 6fa1d5894..4b9f55946 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -137,6 +137,19 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass) deferred_render = FALSE; } +//=============================== +//DEFERRED IMPLEMENTATION +//=============================== +void LLDrawPoolWater::renderDeferred(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_WATER); + deferred_render = TRUE; + shade(); + deferred_render = FALSE; +} + +//========================================= + void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); @@ -338,7 +351,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face) void LLDrawPoolWater::shade() { - gGL.setColorMask(true, true); + if (!deferred_render) + { + gGL.setColorMask(true, true); + } LLVOSky *voskyp = gSky.mVOSkyp; @@ -354,7 +370,7 @@ void LLDrawPoolWater::shade() LLVector3 light_dir; LLColor3 light_color; - if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) { light_dir = gSky.getSunDirection(); light_dir.normVec(); @@ -401,6 +417,15 @@ void LLDrawPoolWater::shade() shader = &gWaterProgram; } + if (deferred_render) + { + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); + } + sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); @@ -436,15 +461,6 @@ void LLDrawPoolWater::shade() S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX); - if (deferred_render) - { - gPipeline.bindDeferredShader(*shader); - } - else - { - shader->bind(); - } - if (screentex > -1) { shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); @@ -545,7 +561,7 @@ void LLDrawPoolWater::shade() sNeedsDistortionUpdate = TRUE; face->renderIndexed(); } - else if (gGLManager.mHasDepthClamp) + else if (gGLManager.mHasDepthClamp || deferred_render) { face->renderIndexed(); } @@ -575,7 +591,10 @@ void LLDrawPoolWater::shade() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.setColorMask(true, false); + if (!deferred_render) + { + gGL.setColorMask(true, false); + } } diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index 635104114..90db2ed29 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -71,10 +71,12 @@ public: /*virtual*/ LLDrawPool *instancePool(); static void restoreGL(); - /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); } /*virtual*/ void beginPostDeferredPass(S32 pass); /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void renderDeferred(S32 pass = 0); /*virtual*/ S32 getNumPasses(); /*virtual*/ void render(S32 pass = 0); diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index c32ee428c..3f5754007 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -160,14 +160,14 @@ void LLDrawPoolWLSky::renderStars(void) const // *NOTE: have to have bound the cloud noise texture already since register // combiners blending below requires something to be bound // and we might as well only bind once. - //gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gPipeline.disableLights(); - if (!LLPipeline::sReflectionRender) + /*if (!LLPipeline::sReflectionRender) { glPointSize(2.f); - } + }*/ // *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid // clamping and allow the star_alpha param to brighten the stars. @@ -175,17 +175,26 @@ void LLDrawPoolWLSky::renderStars(void) const LLColor4 star_alpha(LLColor4::black); star_alpha.mV[3] = LLWLParamManager::instance()->mCurParams.getFloat("star_brightness", error) / 2.f; llassert_always(!error); - + // gl_FragColor.rgb = gl_Color.rgb; // gl_FragColor.a = gl_Color.a * star_alpha.a; - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_PREV_ALPHA, LLTexUnit::TBS_CONST_ALPHA); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); + //New + gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex()); + gGL.pushMatrix(); + glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); + /*//Old + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_PREV_ALPHA, LLTexUnit::TBS_CONST_ALPHA); */ + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); + gSky.mVOWLSkyp->drawStars(); - glPointSize(1.f); - + gGL.popMatrix(); //New + //glPointSize(1.f); + // and disable the combiner states gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } @@ -284,9 +293,10 @@ void LLDrawPoolWLSky::render(S32 pass) LLImageGL * tex = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture(); gGL.getTexUnit(0)->bind(tex); + renderHeavenlyBodies(); + renderStars(); - renderHeavenlyBodies(); glPopMatrix(); diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index c7a1f3fe2..0e2220e7f 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -43,7 +43,7 @@ public: static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0; static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_COLOR; + LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; LLDrawPoolWLSky(void); /*virtual*/ ~LLDrawPoolWLSky(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 5ce007d1e..14df6a742 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -157,6 +157,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomIndex = 0; mIndicesCount = 0; mIndicesIndex = 0; + mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; @@ -205,6 +206,7 @@ void LLFace::destroy() if (group) { group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); } } } @@ -272,12 +274,36 @@ void LLFace::setTexture(LLViewerImage* tex) mTexture->removeFace(this) ; } - mTexture = tex ; - - if(mTexture.notNull()) + if(tex) { - mTexture->addFace(this) ; - } + tex->addFace(this) ; + } + + mTexture = tex ; +} + +void LLFace::dirtyTexture() +{ + gPipeline.markTextured(getDrawable()); +} + +void LLFace::switchTexture(LLViewerImage* new_texture) +{ + if(mTexture == new_texture) + { + return ; + } + + if(!new_texture) + { + llerrs << "Can not switch to a null texture." << llendl; + return; + } + new_texture->addTextureStats(mTexture->mMaxVirtualSize) ; + + getViewerObject()->changeTEImage(mTEOffset, new_texture) ; + setTexture(new_texture) ; + dirtyTexture(); } void LLFace::setTEOffset(const S32 te_offset) @@ -453,8 +479,15 @@ void LLFace::renderForSelect(U32 data_mask) void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) { - if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL || - mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY)) + if (mDrawablep->getSpatialGroup() == NULL) + { + return; + } + + mDrawablep->getSpatialGroup()->rebuildGeom(); + mDrawablep->getSpatialGroup()->rebuildMesh(); + + if(mDrawablep.isNull() || mVertexBuffer.isNull()) { return; } @@ -473,17 +506,13 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); } - setFaceColor(color); - renderSetColor(); - + glColor4fv(color.mV); mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #if !LL_RELEASE_FOR_DOWNLOAD LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #endif mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - unsetFaceColor(); - unsetFaceColor(); gGL.popMatrix(); } } @@ -805,6 +834,7 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, // by planarProjection(). This is needed to match planar texgen parameters. void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const { + const LLMatrix4& vol_mat = getWorldMatrix(); const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); LLVector3 normal = vf.mVertices[0].mNormal; LLVector3 binormal = vf.mVertices[0].mBinormal; @@ -819,8 +849,8 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang; binormal.rotVec(ang, normal); LLQuaternion local_rot( binormal % normal, binormal, normal ); - *face_rot = local_rot * mXform->getWorldRotation(); - *face_pos = mXform->getWorldPosition(); + *face_rot = local_rot * vol_mat.quaternion(); + *face_pos = vol_mat.getTranslation(); } // Returns the necessary texture transform to align this face's TE to align_to's TE @@ -1089,7 +1119,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); - for (U16 i = 0; i < num_indices; i++) + for (U32 i = 0; i < (U32) num_indices; i++) { *indicesp++ = vf.mIndices[i] + index_offset; } @@ -1256,6 +1286,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mTexExtents[1].setVec(1,1); xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); + + F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; + F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; + mTexExtents[0][0] *= es ; + mTexExtents[1][0] *= es ; + mTexExtents[0][1] *= et ; + mTexExtents[1][1] *= et ; } mLastVertexBuffer = mVertexBuffer; @@ -1305,13 +1342,13 @@ F32 LLFace::getTextureVirtualSize() } face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area); - if (mImportanceToCamera < 1.0f && face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + if (/*mImportanceToCamera < 1.0f && */face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. { if (mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture.notNull() && mTexture->isLargeImage()) { face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius); } - } + } setVirtualSize(face_area); @@ -1413,8 +1450,9 @@ F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) { - F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; - F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + LLViewerCamera* camera = LLViewerCamera::getInstance(); + F32 camera_moving_speed = camera->getAverageSpeed() ; + F32 camera_angular_speed = camera->getAverageAngularSpeed(); if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) { diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 90edf9de1..c23cf2586 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -87,8 +87,9 @@ public: U16 getGeomCount() const { return mGeomCount; } // vertex count for this face U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool U16 getGeomStart() const { return mGeomIndex; } // index into draw pool - LLViewerImage* getTexture() const { return mTexture; } void setTexture(LLViewerImage* tex) ; + void switchTexture(LLViewerImage* new_texture); + void dirtyTexture(); LLXformMatrix* getXform() const { return mXform; } BOOL hasGeometry() const { return mGeomCount > 0; } LLVector3 getPositionAgent() const; @@ -126,8 +127,8 @@ public: LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } void setPoolType(U32 type) { mPoolType = type; } S32 getTEOffset() { return mTEOffset; } - LLViewerImage* getTexture() { return mTexture; } - + LLViewerImage* getTexture() const { return mTexture; } + void setViewerObject(LLViewerObject* object); void setPool(LLFacePool *pool, LLViewerImage *texturep); @@ -262,7 +263,7 @@ public: { bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) { - return lhs->mDistance > rhs->mDistance; // farthest = first + return !lhs || (rhs && (lhs->mDistance > rhs->mDistance)); // farthest = first } }; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index daf5d2a0f..b9032107a 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -705,7 +705,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) } if (volume->mLODChanged || volume->mFaceMappingChanged || - volume->mVolumeChanged) + volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL)) { volume->regenFaces(); volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME); diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index e10acfe0e..3b721c6ba 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -193,7 +193,8 @@ void LLFloaterHardwareSettings::apply() } else if (old_anisotropic != LLImageGL::sGlobalUseAnisotropic) { - gViewerWindow->restartDisplay(logged_in); + LLImageGL::dirtyTexOptions(); + gViewerWindow->restartDisplay(logged_in); } refresh(); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index f68bc28fb..089d9beaa 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1056,7 +1056,8 @@ void LLViewerObjectList::renderObjectBeacons() S32 last_line_width = -1; // gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width) - + + BOOL flush = FALSE; for (S32 i = 0; i < mDebugBeacons.count(); i++) { const LLDebugBeacon &debug_beacon = mDebugBeacons[i]; @@ -1065,11 +1066,12 @@ void LLViewerObjectList::renderObjectBeacons() S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { - if (i > 0) + if (flush) { gGL.end(); - gGL.flush(); } + flush = TRUE; + gGL.flush(); glLineWidth( (F32)line_width ); last_line_width = line_width; gGL.begin(LLRender::LINES); @@ -1095,7 +1097,8 @@ void LLViewerObjectList::renderObjectBeacons() S32 last_line_width = -1; // gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width) - + + BOOL flush = FALSE; for (S32 i = 0; i < mDebugBeacons.count(); i++) { const LLDebugBeacon &debug_beacon = mDebugBeacons[i]; @@ -1103,11 +1106,12 @@ void LLViewerObjectList::renderObjectBeacons() S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { - if (i > 0) + if (flush) { gGL.end(); - gGL.flush(); } + flush = TRUE; + gGL.flush(); glLineWidth( (F32)line_width ); last_line_width = line_width; gGL.begin(LLRender::LINES); diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 2a4e6ccf8..3e3b83eab 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -647,6 +647,8 @@ bool LLHUDEffectLookAt::calcTargetPosition() } LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; + if (!source_avatar->isBuilt()) + return false; if (target_obj && target_obj->mDrawable.notNull()) { diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 20732d9e2..328efbd91 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -608,9 +608,11 @@ void LLPanelFace::getState() } } + // planar align bool align_planar = false; bool identical_planar_aligned = false; + bool is_planar = false; { LLCheckBoxCtrl* cb_planar_align = getChild("checkbox planar align"); align_planar = (cb_planar_align && cb_planar_align->get()); @@ -621,13 +623,12 @@ void LLPanelFace::getState() return (object->getTE(face)->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR); } } func; - - bool is_planar; + bool texgens_identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, is_planar ); bool enabled = (editable && texgens_identical && is_planar); childSetValue("checkbox planar align", align_planar && enabled); childSetEnabled("checkbox planar align", enabled); - + if (align_planar && enabled) { struct f2 : public LLSelectedTEGetFunctor diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index ba8ef3eff..3e22474a7 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -110,6 +110,7 @@ const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constan const S32 MAX_ACTION_QUEUE_SIZE = 20; const S32 MAX_SILS_PER_FRAME = 50; const S32 MAX_OBJECTS_PER_PACKET = 254; +const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF; // // Globals @@ -219,6 +220,9 @@ LLSelectMgr::LLSelectMgr() mSelectedObjects = new LLObjectSelection(); mHoverObjects = new LLObjectSelection(); mHighlightedObjects = new LLObjectSelection(); + + mForceSelection = FALSE; + mShowSelection = FALSE; } @@ -551,7 +555,7 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) object_found = TRUE; break; // must break here, may have removed multiple objects from list } - else if (object->isAvatar()) + else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id) { // It's possible the item being removed has an avatar sitting on it // So remove the avatar that is sitting on the object. @@ -787,41 +791,53 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face) { - // Always blitz hover list when setting - mHoverObjects->deleteAllNodes(); - if (!objectp) { + mHoverObjects->deleteAllNodes(); return NULL; } // Can't select yourself if (objectp->mID == gAgentID) { + mHoverObjects->deleteAllNodes(); return NULL; } // Can't select land if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) { + mHoverObjects->deleteAllNodes(); return NULL; } - // Collect all of the objects - LLDynamicArray objects; - objectp = objectp->getRootEdit(); - objectp->addThisAndNonJointChildren(objects); + mHoverObjects->mPrimaryObject = objectp; - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) + objectp = objectp->getRootEdit(); + + // is the requested object the same as the existing hover object root? + // NOTE: there is only ever one linked set in mHoverObjects + if (mHoverObjects->getFirstRootObject() != objectp) { - LLViewerObject* cur_objectp = *iter; - LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); - nodep->selectTE(face, TRUE); - mHoverObjects->addNodeAtEnd(nodep); + + // Collect all of the objects + LLDynamicArray objects; + objectp = objectp->getRootEdit(); + objectp->addThisAndNonJointChildren(objects); + + mHoverObjects->deleteAllNodes(); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* cur_objectp = *iter; + LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); + nodep->selectTE(face, TRUE); + mHoverObjects->addNodeAtEnd(nodep); + } + + requestObjectPropertiesFamily(objectp); } - requestObjectPropertiesFamily(objectp); return mHoverObjects; } @@ -5059,6 +5075,7 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep) mName = nodep.mName; mDescription = nodep.mDescription; mCategory = nodep.mCategory; + mInventorySerial = 0; mSavedPositionLocal = nodep.mSavedPositionLocal; mSavedPositionGlobal = nodep.mSavedPositionGlobal; mSavedScale = nodep.mSavedScale; @@ -5097,7 +5114,7 @@ LLSelectNode::~LLSelectNode() void LLSelectNode::selectAllTEs(BOOL b) { - mTESelectMask = b ? 0xFFFFFFFF : 0x0; + mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0; mLastTESelected = 0; } @@ -5732,8 +5749,22 @@ void LLSelectMgr::redo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDoDelete() const { + bool can_delete = false; + // This function is "logically const" - it does not change state in + // a way visible outside the selection manager. + LLSelectMgr* self = const_cast(this); + LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject(); // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) - return const_cast(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG + if (obj!= NULL) + { + // all the faces needs to be selected + if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES )) + { + can_delete = true; + } + } + + return can_delete; } //----------------------------------------------------------------------------- @@ -6136,8 +6167,14 @@ BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te) LLSelectNode* nodep = *iter; if (nodep->getObject() == object) { + // Optimization + if (nodep->getTESelectMask() == TE_SELECT_MASK_ALL) + { + return TRUE; + } + BOOL all_selected = TRUE; - for (S32 i = 0; i < SELECT_MAX_TES; i++) + for (S32 i = 0; i < object->getNumTEs(); i++) { all_selected = all_selected && nodep->isTESelected(i); } diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index ac7e865de..b6f4dedbd 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -67,6 +67,9 @@ F32 elevation_from_vector(const LLVector3 &v); LLSky gSky; // ---------------- LLSky ---------------- +const F32 LLSky::NIGHTTIME_ELEVATION = -8.0f; // degrees +const F32 LLSky::NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD); + ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h index abd4205e6..d7796dea8 100644 --- a/indra/newview/llsky.h +++ b/indra/newview/llsky.h @@ -42,9 +42,6 @@ #include "llvosky.h" #include "llvoground.h" -const F32 NIGHTTIME_ELEVATION = -8.0f; // degrees -const F32 NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD); - class LLViewerCamera; class LLVOWLSky; @@ -111,6 +108,9 @@ public: // Legacy stuff LLVector3 mSunDefaultPosition; + static const F32 NIGHTTIME_ELEVATION; // degrees + static const F32 NIGHTTIME_ELEVATION_COS; + protected: BOOL mOverrideSimSunPosition; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 1c81d4cdb..63784107b 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -86,7 +86,7 @@ protected: static LLOcclusionQueryPool sQueryPool; -BOOL LLSpatialPartition::sFreezeState = FALSE; +//BOOL LLSpatialPartition::sFreezeState = FALSE; //static counter for frame to switch LOD on @@ -281,10 +281,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3 LLSpatialGroup::~LLSpatialGroup() { - if (sNoDelete) + /*if (sNoDelete) { llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; - } + }*/ if (isState(DEAD)) { @@ -293,12 +293,13 @@ LLSpatialGroup::~LLSpatialGroup() sNodeCount--; - if (gGLManager.mHasOcclusionQuery && mOcclusionQuery) + if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - sQueryPool.release(mOcclusionQuery); + sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); } delete [] mOcclusionVerts; + mOcclusionVerts = NULL; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); @@ -309,17 +310,19 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } +BOOL LLSpatialGroup::isRecentlyVisible() const +{ + return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; +} + BOOL LLSpatialGroup::isVisible() const { - return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE; + return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE; } void LLSpatialGroup::setVisible() { - if (!LLSpatialPartition::sFreezeState) - { - mVisible = LLDrawable::getCurrentFrame(); - } + mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame(); } void LLSpatialGroup::validate() @@ -378,63 +381,6 @@ void LLSpatialGroup::validate() #endif } - - -class LLOctreeStateCheck : public LLOctreeTraveler -{ -public: - U32 mInheritedMask; - - LLOctreeStateCheck(): mInheritedMask(0) { } - - virtual void traverse(const LLSpatialGroup::OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - node->accept(this); - - U32 temp = mInheritedMask; - mInheritedMask |= group->getState() & - (LLSpatialGroup::OCCLUDED); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - - mInheritedMask = temp; - } - - virtual void visit(const LLOctreeNode* state) - { - LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); - - if (mInheritedMask && !group->isState(mInheritedMask)) - { - llerrs << "Spatial group failed inherited mask test." << llendl; - } - - if (group->isState(LLSpatialGroup::DIRTY)) - { - assert_parent_state(group, LLSpatialGroup::DIRTY); - } - } - - void assert_parent_state(LLSpatialGroup* group, U32 state) - { - LLSpatialGroup* parent = group->getParent(); - while (parent) - { - if (!parent->isState(state)) - { - llerrs << "Spatial group failed parent state check." << llendl; - } - parent = parent->getParent(); - } - } -}; - - void LLSpatialGroup::checkStates() { #if LL_OCTREE_PARANOIA_CHECK @@ -468,17 +414,17 @@ void validate_draw_info(LLDrawInfo& params) } //bad indices - U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer(); + U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer(); if (indicesp) { for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++) { - if (indicesp[i] < params.mStart) + if (indicesp[i] < (U16)params.mStart) { llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; } - if (indicesp[i] > params.mEnd) + if (indicesp[i] > (U16)params.mEnd) { llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; } @@ -539,7 +485,9 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc { drawablep->setSpatialGroup(this); validate_drawable(drawablep); - setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY); + setState(OBJECT_DIRTY | GEOM_DIRTY); + setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); + gPipeline.markRebuild(this, TRUE); if (drawablep->isSpatialBridge()) { mBridgeList.push_back((LLSpatialBridge*) drawablep); @@ -572,9 +520,18 @@ void LLSpatialGroup::rebuildMesh() void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - if (!gPipeline.hasRenderType(mDrawableType)) + /*if (!gPipeline.hasRenderType(mDrawableType)) { return; + }*/ + + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup) + { + llerrs << "WTF?" << llendl; + }*/ + return; } if (!LLPipeline::sSkipUpdate && group->changeLOD()) @@ -582,12 +539,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateDistance = group->mDistance; group->mLastUpdateViewAngle = group->mViewAngle; } - - if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) - { - return; - } - + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); group->clearDrawMap(); @@ -663,8 +615,11 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO drawablep = *i; minMax = drawablep->getSpatialExtents(); + update_min_max(newMin, newMax, minMax[0]); + update_min_max(newMin, newMax, minMax[1]); + //bin up the object - for (U32 i = 0; i < 3; i++) + /*for (U32 i = 0; i < 3; i++) { if (minMax[0].mV[i] < newMin.mV[i]) { @@ -674,7 +629,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO { newMax.mV[i] = minMax[1].mV[i]; } - } + }*/ } mObjectBounds[0] = (newMin + newMax) * 0.5f; @@ -738,6 +693,10 @@ LLSpatialGroup* LLSpatialGroup::getParent() return NULL; } + if(!mOctreeNode) + { + return NULL; + } OctreeNode* parent = mOctreeNode->getOctParent(); if (parent) @@ -763,6 +722,8 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { drawablep->setSpatialGroup(NULL); setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); + if (drawablep->isSpatialBridge()) { for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) @@ -799,6 +760,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset) //if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); } if (mOcclusionVerts) @@ -816,15 +778,15 @@ void LLSpatialGroup::shift(const LLVector3 &offset) class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler { public: - U32 mState; - LLSpatialSetState(U32 state) : mState(state) { } + LLSpatialGroup::eSpatialState mState; + LLSpatialSetState(LLSpatialGroup::eSpatialState state) : mState(state) { } virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } }; class LLSpatialSetStateDiff : public LLSpatialSetState { public: - LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } + LLSpatialSetStateDiff(LLSpatialGroup::eSpatialState state) : LLSpatialSetState(state) { } virtual void traverse(const LLSpatialGroup::OctreeNode* n) { @@ -837,20 +799,27 @@ public: } }; -void LLSpatialGroup::setState(U32 state) +void LLSpatialGroup::setState(eSpatialState state) { - if (!LLSpatialPartition::sFreezeState) +// if (LLSpatialPartition::sFreezeState) +// return; + mState |= state; + + if (state > LLSpatialGroup::STATE_MASK) { - mState |= state; - } + llerrs << "WTF?" << llendl; + } } -void LLSpatialGroup::setState(U32 state, S32 mode) +void LLSpatialGroup::setState(eSpatialState state, S32 mode) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - if (LLSpatialPartition::sFreezeState) +// if (LLSpatialPartition::sFreezeState) +// return; + + if (state > LLSpatialGroup::STATE_MASK) { - return; + llerrs << "WTF?" << llendl; } if (mode > STATE_MODE_SINGLE) @@ -875,15 +844,15 @@ void LLSpatialGroup::setState(U32 state, S32 mode) class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler { public: - U32 mState; - LLSpatialClearState(U32 state) : mState(state) { } + LLSpatialGroup::eSpatialState mState; + LLSpatialClearState(LLSpatialGroup::eSpatialState state) : mState(state) { } virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } }; class LLSpatialClearStateDiff : public LLSpatialClearState { public: - LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } + LLSpatialClearStateDiff(LLSpatialGroup::eSpatialState state) : LLSpatialClearState(state) { } virtual void traverse(const LLSpatialGroup::OctreeNode* n) { @@ -896,22 +865,30 @@ public: } }; -void LLSpatialGroup::clearState(U32 state) +void LLSpatialGroup::clearState(eSpatialState state) { - if (!LLSpatialPartition::sFreezeState) +// if (LLSpatialPartition::sFreezeState) +// return; + if (state > LLSpatialGroup::STATE_MASK) { - mState &= ~state; + llerrs << "WTF?" << llendl; } + + mState &= ~state; } -void LLSpatialGroup::clearState(U32 state, S32 mode) +void LLSpatialGroup::clearState(eSpatialState state, S32 mode) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - if (LLSpatialPartition::sFreezeState) + +// if (LLSpatialPartition::sFreezeState) +// return; + if (state > LLSpatialGroup::STATE_MASK) { - return; + llerrs << "WTF?" << llendl; } + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -931,6 +908,128 @@ void LLSpatialGroup::clearState(U32 state, S32 mode) } } +BOOL LLSpatialGroup::isState(eSpatialState state) const +{ + if (state > LLSpatialGroup::STATE_MASK) + { + llerrs << "LLSpatialGroup::isState passed invalid state '" << state << "'" << llendl; + } + + return mState & state ? TRUE : FALSE; +} + +//===================================== +// Occlusion State Set/Clear +//===================================== +class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler +{ +public: + LLSpatialGroup::eOcclusionState mState; + LLSpatialSetOcclusionState(LLSpatialGroup::eOcclusionState state) : mState(state) { } + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); } +}; + +class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState +{ +public: + LLSpatialSetOcclusionStateDiff(LLSpatialGroup::eOcclusionState state) : LLSpatialSetOcclusionState(state) { } + + virtual void traverse(const LLSpatialGroup::OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (!group->isOcclusionState(mState)) + { + LLSpatialGroup::OctreeTraveler::traverse(n); + } + } +}; + + +void LLSpatialGroup::setOcclusionState(eOcclusionState state, S32 mode) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialSetOcclusionStateDiff setter(state); + setter.traverse(mOctreeNode); + } + else if (mode == STATE_MODE_BRANCH) + { + LLSpatialSetOcclusionState setter(state); + setter.traverse(mOctreeNode); + } + else + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] |= state; + } + } + } + else + { + mOcclusionState[LLViewerCamera::sCurCameraID] |= state; + } +} + +class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler +{ +public: + LLSpatialGroup::eOcclusionState mState; + + LLSpatialClearOcclusionState(LLSpatialGroup::eOcclusionState state) : mState(state) { } + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); } +}; + +class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState +{ +public: + LLSpatialClearOcclusionStateDiff(LLSpatialGroup::eOcclusionState state) : LLSpatialClearOcclusionState(state) { } + + virtual void traverse(const LLSpatialGroup::OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (group->isOcclusionState(mState)) + { + LLSpatialGroup::OctreeTraveler::traverse(n); + } + } +}; + +void LLSpatialGroup::clearOcclusionState(eOcclusionState state, S32 mode) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialClearOcclusionStateDiff clearer(state); + clearer.traverse(mOctreeNode); + } + else if (mode == STATE_MODE_BRANCH) + { + LLSpatialClearOcclusionState clearer(state); + clearer.traverse(mOctreeNode); + } + else + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] &= ~state; + } + } + } + else + { + mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state; + } +} //====================================== // Octree Listener Implementation //====================================== @@ -942,7 +1041,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mSpatialPartition(part), mVertexBuffer(NULL), mBufferUsage(GL_STATIC_DRAW_ARB), - mVisible(0), mDistance(0.f), mDepth(0.f), mLastUpdateDistance(-1.f), @@ -956,6 +1054,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sg_assert(mOctreeNode->getListenerCount() == 0); mOctreeNode->addListener(this); setState(SG_INITIAL_STATE_MASK); + gPipeline.markRebuild(this, TRUE); mBounds[0] = LLVector3(node->getCenter()); mBounds[1] = LLVector3(node->getSize()); @@ -963,7 +1062,16 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; mLODHash = part->mLODSeed; - mOcclusionQuery = 0; + OctreeNode* oct_parent = node->getOctParent(); + + LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL; + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionQuery[i] = 0; + mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0; + mVisible[i] = 0; + } mOcclusionVerts = NULL; mRadius = 1; @@ -972,13 +1080,18 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : void LLSpatialGroup::updateDistance(LLCamera &camera) { + if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + llerrs << "WTF?" << llendl; + } + #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { llerrs << "Spatial group dirty on distance update." << llendl; } #endif - if (!getData().empty() && !LLSpatialPartition::sFreezeState) + if (!getData().empty() /*&& !LLSpatialPartition::sFreezeState*/) { mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : (F32) mOctreeNode->getSize().magVec(); @@ -1014,6 +1127,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, //not setting this node to dirty would be a very good thing group->setState(LLSpatialGroup::ALPHA_DIRTY); + gPipeline.markRebuild(group, FALSE); } } } @@ -1050,6 +1164,18 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } +F32 LLSpatialGroup::getUpdateUrgency() const +{ + if (!isVisible()) + { + return 0.f; + } + else + { + return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; + } +} + BOOL LLSpatialGroup::needsUpdate() { return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; @@ -1136,8 +1262,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); if (child->getListenerCount() == 0) { - LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition); - group->setState(mState & SG_STATE_INHERIT_MASK); + new LLSpatialGroup(child, mSpatialPartition); } else { @@ -1157,16 +1282,20 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo void LLSpatialGroup::destroyGL() { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); + gPipeline.markRebuild(this, TRUE); mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; mBufferMap.clear(); clearDrawMap(); - if (mOcclusionQuery) + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) { - sQueryPool.release(mOcclusionQuery); - mOcclusionQuery = 0; + if (mOcclusionQuery[i]) + { + sQueryPool.release(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } } delete [] mOcclusionVerts; @@ -1260,39 +1389,44 @@ void LLSpatialGroup::checkOcclusion() { if (LLPipeline::sUseOcclusion > 1) { + LLFastTimer t( LLFastTimer::FTM_OCCLUSION_READBACK); LLSpatialGroup* parent = getParent(); - if (parent && parent->isState(LLSpatialGroup::OCCLUDED)) + if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) { //if the parent has been marked as occluded, the child is implicitly occluded - clearState(QUERY_PENDING | DISCARD_QUERY); + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); } - else if (isState(QUERY_PENDING)) + else if (isOcclusionState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back - LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); GLuint res = 1; - if (!isState(DISCARD_QUERY) && mOcclusionQuery) + if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res); + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); + } + + if (isOcclusionState(DISCARD_QUERY)) + { + res = 2; } if (res > 0) { assert_states_valid(this); - clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); } else { assert_states_valid(this); - setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); } - clearState(QUERY_PENDING | DISCARD_QUERY); + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); } - else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED)) + else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED)) { //check occlusion has been issued for occluded node that has not had a query issued assert_states_valid(this); - clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); } } @@ -1302,15 +1436,14 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) { - static const LLCachedControl render_water_void_culling("RenderWaterVoidCulling", TRUE); + //static const LLCachedControl render_water_void_culling("RenderWaterVoidCulling", TRUE); // Don't cull hole/edge water, unless RenderWaterVoidCulling is set and we have the GL_ARB_depth_clamp extension. - if ((mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER && - !(render_water_void_culling && gGLManager.mHasDepthClamp)) || - earlyFail(camera, this)) + if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || + earlyFail(camera, this)) { - setState(LLSpatialGroup::DISCARD_QUERY); + setOcclusionState(LLSpatialGroup::DISCARD_QUERY); assert_states_valid(this); - clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); } else @@ -1318,9 +1451,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); - if (!mOcclusionQuery) + if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - mOcclusionQuery = sQueryPool.allocate(); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); } if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) @@ -1331,19 +1464,28 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) // 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. - bool const use_depth_clamp = - gGLManager.mHasDepthClamp && - (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER || - mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER); + bool const use_depth_clamp = gGLManager.mHasDepthClamp && + (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || + mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); if (use_depth_clamp) { glEnable(GL_DEPTH_CLAMP); } - - glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery); + + glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]); glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); + if (camera->getOrigin().isExactlyZero()) + { //origin is invalid, draw entire box + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); + } + else + { + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); + } glEndQueryARB(GL_SAMPLES_PASSED_ARB); if (use_depth_clamp) @@ -1352,15 +1494,16 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) } } - setState(LLSpatialGroup::QUERY_PENDING); - clearState(LLSpatialGroup::DISCARD_QUERY); + setOcclusionState(LLSpatialGroup::QUERY_PENDING); + clearOcclusionState(LLSpatialGroup::DISCARD_QUERY); } } } //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) +: mRenderByGroup(render_by_group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); mOcclusionEnabled = TRUE; @@ -1372,7 +1515,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) mBufferUsage = buffer_usage; mDepthMask = FALSE; mSlopRatio = 0.25f; - mRenderByGroup = TRUE; mInfiniteFarClip = FALSE; LLGLNamePool::registerPool(&sQueryPool); @@ -1409,9 +1551,9 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) LLSpatialGroup* group = drawablep->getSpatialGroup(); - if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING)) + if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) { - group->setState(LLSpatialGroup::DISCARD_QUERY); + group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); } return group; @@ -1510,7 +1652,7 @@ public: if (group->mOctreeNode->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { gPipeline.markOccluder(group); return true; @@ -1592,7 +1734,7 @@ public: virtual void processGroup(LLSpatialGroup* group) { if (group->needsUpdate() || - group->mVisible < LLDrawable::getCurrentFrame() - 1) + group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1) { group->doOcclusion(mCamera); } @@ -1660,7 +1802,7 @@ public: { if (group->mOctreeNode->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { return true; } @@ -1668,13 +1810,54 @@ public: return false; } + virtual void traverse(const LLSpatialGroup::OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (earlyFail(group)) + { + return; + } + + if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + mRes == 2) + { //don't need to do frustum check + LLSpatialGroup::OctreeTraveler::traverse(n); + } + else + { + mRes = frustumCheck(group); + + if (mRes) + { //at least partially in, run on down + LLSpatialGroup::OctreeTraveler::traverse(n); + } + + mRes = 0; + } + } + virtual void processGroup(LLSpatialGroup* group) { - if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) - { //megaprims and water edge patches be damned! + if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty()) + { + llerrs << "WTF?" << llendl; + } + + if (mRes < 2) + { + if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0) + { + mEmpty = FALSE; + update_min_max(mMin, mMax, group->mObjectExtents[0]); + update_min_max(mMin, mMax, group->mObjectExtents[1]); + } + } + else + { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mObjectExtents[0]); - update_min_max(mMin, mMax, group->mObjectExtents[1]); + update_min_max(mMin, mMax, group->mExtents[0]); + update_min_max(mMin, mMax, group->mExtents[1]); } } @@ -1693,8 +1876,8 @@ public: { if (mResult || //already found a node, don't check any more (group->mOctreeNode->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isState(LLSpatialGroup::OCCLUDED))) + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED))) { return true; } @@ -1873,6 +2056,11 @@ BOOL LLSpatialPartition::isOcclusionEnabled() BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { + { + LLFastTimer ftm( LLFastTimer::FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } LLOctreeCullVisExtents vis(&camera, visMin, visMax); vis.traverse(mOctree); return vis.mEmpty; @@ -1892,12 +2080,12 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif { - BOOL temp = sFreezeState; - sFreezeState = FALSE; + //BOOL temp = sFreezeState; + //sFreezeState = FALSE; LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); - sFreezeState = temp; + //sFreezeState = temp; } #if LL_OCTREE_PARANOIA_CHECK @@ -1934,6 +2122,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) { + if (camera->getOrigin().isExactlyZero()) + { + return FALSE; + } + const F32 vel = SG_OCCLUSION_FUDGE*2.f; LLVector3 c = group->mBounds[0]; LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel); @@ -2161,7 +2354,6 @@ void renderOctree(LLSpatialGroup* group) gGL.color4fv(col.mV); drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); - glDepthMask(GL_TRUE); gGL.setSceneBlendType(LLRender::BT_ALPHA); if (group->mBuilt <= 0.f) @@ -2211,7 +2403,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) LLGLEnable cull(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && !group->getData().empty(); if (render_objects) { @@ -2270,6 +2462,49 @@ void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) gGL.end(); } +void renderUpdateType(LLDrawable* drawablep) +{ + LLViewerObject* vobj = drawablep->getVObj(); + if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) + { + return; + } + LLGLEnable blend(GL_BLEND); + switch (vobj->getLastUpdateType()) + { + case OUT_FULL: + glColor4f(0,1,0,0.5f); + break; + case OUT_TERSE_IMPROVED: + glColor4f(0,1,1,0.5f); + break; + case OUT_FULL_COMPRESSED: + if (vobj->getLastUpdateCached()) + { + glColor4f(1,0,0,0.5f); + } + else + { + glColor4f(1,1,0,0.5f); + } + break; + case OUT_FULL_CACHED: + glColor4f(0,0,1,0.5f); + break; + default: + llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl; + break; + }; + S32 num_faces = drawablep->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } +} + void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { @@ -2310,6 +2545,7 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) break; case LL_PCODE_LEGACY_TREE: gGL.color4f(0,0.5f,0,1); + break; default: gGL.color4f(1,0,1,1); break; @@ -2587,6 +2823,9 @@ public: //draw tight fit bounding boxes for spatial group if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) { + group->rebuildGeom(); + group->rebuildMesh(); + renderOctree(group); stop_glerror(); } @@ -2594,6 +2833,9 @@ public: //render visibility wireframe if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { + group->rebuildGeom(); + group->rebuildMesh(); + gGL.flush(); glPushMatrix(); gGLLastMatrix = NULL; @@ -2619,6 +2861,19 @@ public: LLVector3 nodeCenter = group->mBounds[0]; LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); + group->rebuildGeom(); + group->rebuildMesh(); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + if (!group->getData().empty()) + { + gGL.color3f(0,0,1); + drawBoxOutline(group->mObjectBounds[0], + group->mObjectBounds[1]); + } + } + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; @@ -2726,6 +2981,79 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) pusher.traverse(mOctree); } +class LLOctreeStateCheck : public LLOctreeTraveler +{ +public: + U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; + + LLOctreeStateCheck() + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mInheritedMask[i] = 0; + } + } + + virtual void traverse(const LLSpatialGroup::OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + node->accept(this); + + + U32 temp[LLViewerCamera::NUM_CAMERAS]; + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + temp[i] = mInheritedMask[i]; + mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED; + } + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mInheritedMask[i] = temp[i]; + } + } + + + virtual void visit(const LLOctreeNode* state) + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) + { + llerrs << "Spatial group failed inherited mask test." << llendl; + } + } + + if (group->isState(LLSpatialGroup::DIRTY)) + { + assert_parent_state(group, LLSpatialGroup::DIRTY); + } + } + + void assert_parent_state(LLSpatialGroup* group, LLSpatialGroup::eSpatialState state) + { + LLSpatialGroup* parent = group->getParent(); + while (parent) + { + if (!parent->isState(state)) + { + llerrs << "Spatial group failed parent state check." << llendl; + } + parent = parent->getParent(); + } + } +}; + + void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | @@ -2773,6 +3101,12 @@ void LLSpatialPartition::renderDebug() render_debug.traverse(mOctree); } +void LLSpatialGroup::drawObjectBox(LLColor4 col) +{ + gGL.color4fv(col.mV); + drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); +} + BOOL LLSpatialPartition::isVisible(const LLVector3& v) { @@ -2953,10 +3287,10 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLDrawInfo::~LLDrawInfo() { - if (LLSpatialGroup::sNoDelete) + /*if (LLSpatialGroup::sNoDelete) { llerrs << "LLDrawInfo deleted illegally!" << llendl; - } + }*/ if (mFace) { @@ -2977,11 +3311,22 @@ LLCullResult::LLCullResult() void LLCullResult::clear() { mVisibleGroupsSize = 0; + mVisibleGroupsEnd = mVisibleGroups.begin(); + mAlphaGroupsSize = 0; + mAlphaGroupsEnd = mAlphaGroups.begin(); + mOcclusionGroupsSize = 0; + mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mDrawableGroupsSize = 0; + mDrawableGroupsEnd = mDrawableGroups.begin(); + mVisibleListSize = 0; + mVisibleListEnd = mVisibleList.begin(); + mVisibleBridgeSize = 0; + mVisibleBridgeEnd = mVisibleBridge.begin(); for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { @@ -2990,6 +3335,7 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; + mRenderMapEnd[i] = mRenderMap[i].begin(); } } @@ -3000,7 +3346,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() { - return mVisibleGroups.begin() + mVisibleGroupsSize; + return mVisibleGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() @@ -3010,7 +3356,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() { - return mAlphaGroups.begin() + mAlphaGroupsSize; + return mAlphaGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() @@ -3020,7 +3366,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() { - return mOcclusionGroups.begin() + mOcclusionGroupsSize; + return mOcclusionGroupsEnd; } LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() @@ -3030,7 +3376,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() { - return mDrawableGroups.begin() + mDrawableGroupsSize; + return mDrawableGroupsEnd; } LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() @@ -3040,7 +3386,7 @@ LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() { - return mVisibleList.begin() + mVisibleListSize; + return mVisibleListEnd; } LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() @@ -3050,7 +3396,7 @@ LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() { - return mVisibleBridge.begin() + mVisibleBridgeSize; + return mVisibleBridgeEnd; } LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) @@ -3060,7 +3406,7 @@ LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) { - return mRenderMap[type].begin() + mRenderMapSize[type]; + return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) @@ -3074,6 +3420,7 @@ void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) mVisibleGroups.push_back(group); } ++mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) @@ -3087,6 +3434,7 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) mAlphaGroups.push_back(group); } ++mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) @@ -3100,6 +3448,7 @@ void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) mOcclusionGroups.push_back(group); } ++mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) @@ -3113,6 +3462,7 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) mDrawableGroups.push_back(group); } ++mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) @@ -3126,6 +3476,7 @@ void LLCullResult::pushDrawable(LLDrawable* drawable) mVisibleList.push_back(drawable); } ++mVisibleListSize; + mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) @@ -3139,6 +3490,7 @@ void LLCullResult::pushBridge(LLSpatialBridge* bridge) mVisibleBridge.push_back(bridge); } ++mVisibleBridgeSize; + mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) @@ -3152,6 +3504,7 @@ void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) mRenderMap[type].push_back(draw_info); } ++mRenderMapSize[type]; + mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index be0163b2b..ebab60e49 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -43,6 +43,7 @@ #include "llcubemap.h" #include "lldrawpool.h" #include "llface.h" +#include "llviewercamera.h" #include @@ -153,12 +154,12 @@ public: class LLSpatialGroup : public LLOctreeListener { friend class LLSpatialPartition; + friend class LLOctreeStateCheck; public: static U32 sNodeCount; static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE typedef std::vector > sg_vector_t; - typedef std::set > sg_set_t; typedef std::vector > bridge_list_t; typedef std::vector > drawmap_elem_t; typedef std::map draw_map_t; @@ -183,6 +184,14 @@ public: } }; + struct CompareUpdateUrgency + { + bool operator()(const LLPointer lhs, const LLPointer rhs) + { + return lhs->getUpdateUrgency() > rhs->getUpdateUrgency(); + } + }; + struct CompareDepthGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) @@ -193,53 +202,67 @@ public: typedef enum { - OCCLUDED = 0x00000001, - IN_QUEUE = 0x00000002, - QUERY_PENDING = 0x00000004, - ACTIVE_OCCLUSION = 0x00000008, - DISCARD_QUERY = 0x00000010, - DEAD = 0x00000020, - EARLY_FAIL = 0x00000040, - DIRTY = 0x00000080, - OBJECT_DIRTY = 0x00000100, - GEOM_DIRTY = 0x00000200, - ALPHA_DIRTY = 0x00000800, - SKIP_FRUSTUM_CHECK = 0x00001000, - IN_IMAGE_QUEUE = 0x00002000, - IMAGE_DIRTY = 0x00004000, - OCCLUSION_DIRTY = 0x00008000, - MESH_DIRTY = 0x00010000, + OCCLUDED = 0x00010000, + QUERY_PENDING = 0x00020000, + ACTIVE_OCCLUSION = 0x00040000, + DISCARD_QUERY = 0x00080000, + EARLY_FAIL = 0x00100000, + } eOcclusionState; + + typedef enum + { + DEAD = 0x00000001, + DIRTY = 0x00000002, + OBJECT_DIRTY = 0x00000004, + GEOM_DIRTY = 0x00000008, + ALPHA_DIRTY = 0x00000010, + 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, + STATE_MASK = 0x0000FFFF, } eSpatialState; typedef enum { STATE_MODE_SINGLE = 0, //set one node STATE_MODE_BRANCH, //set entire branch - STATE_MODE_DIFF //set entire branch as long as current state is different + STATE_MODE_DIFF, //set entire branch as long as current state is different + STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras } eSetStateMode; LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); BOOL isDead() { return isState(DEAD); } - BOOL isState(U32 state) const { return mState & state ? TRUE : FALSE; } + BOOL isState(eSpatialState state) const; //Using enum type here and below to force type-safeness. + BOOL isOcclusionState(eOcclusionState state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } U32 getState() { return mState; } - void setState(U32 state); - void clearState(U32 state); + void setState(eSpatialState state); + void clearState(eSpatialState state); void clearDrawMap(); void validate(); void checkStates(); void validateDrawMap(); - void setState(U32 state, S32 mode); + void setState(eSpatialState state, S32 mode); + void clearState(eSpatialState state, S32 mode); + + void setOcclusionState(eOcclusionState state, S32 mode = STATE_MODE_SINGLE); + void clearOcclusionState(eOcclusionState state, S32 mode = STATE_MODE_SINGLE); LLSpatialGroup* getParent(); - void clearState(U32 state, S32 mode); + BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE); BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group BOOL isVisible() const; + BOOL isRecentlyVisible() const; void setVisible(); void shift(const LLVector3 &offset); BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax); @@ -252,6 +275,7 @@ public: void updateDistance(LLCamera& camera); BOOL needsUpdate(); + F32 getUpdateUrgency() const; BOOL changeLOD(); void rebuildGeom(); void rebuildMesh(); @@ -261,6 +285,8 @@ public: element_list& getData() { return mOctreeNode->getData(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } + void drawObjectBox(LLColor4 col); + //LISTENER FUNCTIONS virtual void handleInsertion(const TreeNode* node, LLDrawable* face); virtual void handleRemoval(const TreeNode* node, LLDrawable* face); @@ -273,6 +299,7 @@ protected: virtual ~LLSpatialGroup(); U32 mState; + U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS]; S32 mLODHash; static S32 sLODSeed; @@ -291,12 +318,12 @@ public: LLPointer mVertexBuffer; F32* mOcclusionVerts; - GLuint mOcclusionQuery; + GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; U32 mBufferUsage; draw_map_t mDrawMap; - S32 mVisible; + S32 mVisible[LLViewerCamera::NUM_CAMERAS]; F32 mDistance; F32 mDepth; F32 mLastUpdateDistance; @@ -309,6 +336,15 @@ public: F32 mRadius; }; +inline LLSpatialGroup::eOcclusionState operator|(const LLSpatialGroup::eOcclusionState &a, const LLSpatialGroup::eOcclusionState &b) +{ + return LLSpatialGroup::eOcclusionState(+a | +b); +} +inline LLSpatialGroup::eSpatialState operator|(const LLSpatialGroup::eSpatialState &a, const LLSpatialGroup::eSpatialState &b) +{ + return LLSpatialGroup::eSpatialState(+a | +b); +} + class LLGeometryManager { public: @@ -325,9 +361,8 @@ public: class LLSpatialPartition: public LLGeometryManager { public: - static BOOL sFreezeState; //if true, no spatialgroup state updates will be made - - LLSpatialPartition(U32 data_mask, U32 mBufferUsage = GL_STATIC_DRAW_ARB); + //static BOOL sFreezeState; //if true, no spatialgroup state updates will be made + LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); @@ -392,7 +427,7 @@ protected: public: typedef std::vector > bridge_vector_t; - LLSpatialBridge(LLDrawable* root, U32 data_mask); + LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); virtual BOOL isSpatialBridge() const { return TRUE; } @@ -473,14 +508,22 @@ private: U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; + sg_list_t::iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; + sg_list_t::iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; + sg_list_t::iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; + sg_list_t::iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; + drawable_list_t::iterator mVisibleListEnd; bridge_list_t mVisibleBridge; + bridge_list_t::iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; + drawinfo_list_t::iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; }; + //spatial partition for water (implemented in LLVOWater.cpp) class LLWaterPartition : public LLSpatialPartition { diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index caaba056d..f8cf9e57e 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -160,6 +160,7 @@ void LLSurface::initClasses() void LLSurface::setRegion(LLViewerRegion *regionp) { mRegionp = regionp; + mWaterObjp = NULL; // depends on regionp, needs recreating } // Assumes that arguments are powers of 2, and that @@ -1282,6 +1283,10 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, } } + if (!mWaterTexturep->getHasGLTexture()) + { + mWaterTexturep->createGLTexture(0, raw); + } mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin); return TRUE; } diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5fac5fd1e..b8b4e4f91 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -60,6 +60,7 @@ LLSurfacePatch::LLSurfacePatch() : mHeightsGenerated(FALSE), mDataOffset(0), mDataZ(NULL), + mDataNorm(NULL), mVObjp(NULL), mOriginRegion(0.f, 0.f, 0.f), mCenterRegion(0.f, 0.f, 0.f), @@ -712,17 +713,7 @@ BOOL LLSurfacePatch::updateTexture() if (mVObjp) { mVObjp->dirtyGeom(); - } - updateCompositionStats(); - F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; - if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], - tex_patch_size, tex_patch_size)) - { - mSTexUpdate = FALSE; - - // Also generate the water texture - mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], - tex_patch_size, tex_patch_size); + gPipeline.markGLRebuild(mVObjp); return TRUE; } } @@ -735,6 +726,28 @@ BOOL LLSurfacePatch::updateTexture() } } +void LLSurfacePatch::updateGL() +{ + F32 meters_per_grid = getSurface()->getMetersPerGrid(); + F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); + + LLViewerRegion *regionp = getSurface()->getRegion(); + LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); + + LLVLComposition* comp = regionp->getComposition(); + + updateCompositionStats(); + F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; + if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], + tex_patch_size, tex_patch_size)) + { + mSTexUpdate = FALSE; + + // Also generate the water texture + mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], + tex_patch_size, tex_patch_size); + } +} void LLSurfacePatch::dirtyZ() { diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index 7e84f7f6c..1f9658d4a 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -90,6 +90,7 @@ public: void updateCameraDistanceRegion( const LLVector3 &pos_region); void updateVisibility(); + void updateGL(); void dirtyZ(); // Dirty the z values of this patch void setHasReceivedData(); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 8ccd47066..8873821ef 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1420,22 +1420,21 @@ void LLTextureCache::readHeaderCache() } } } - if (num_entries > sCacheMaxEntries) + if (num_entries - empty_entries > sCacheMaxEntries) { // Special case: cache size was reduced, need to remove entries // Note: After we prune entries, we will call this again and create the LRU U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; - if (entries_to_purge > 0) + // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have: + // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge + // So, it's certain that iter will never reach lru.end() first. + std::set::iterator iter = lru.begin(); + while (purge_list.size() < entries_to_purge) { - for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) - { - purge_list.insert(iter->second); - if (purge_list.size() >= entries_to_purge) - break; - } + purge_list.insert(iter->second); + ++iter; } - llassert_always(purge_list.size() >= entries_to_purge); } else { diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index d7577ac67..150a75ea8 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -302,7 +302,10 @@ public: const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + static LLCachedControl log_to_viewer_log("LogTextureDownloadsToViewerLog",false); + static LLCachedControl log_to_sim("LogTextureDownloadsToSimulator",false); + + if (log_to_viewer_log || log_to_sim) { mFetcher->mTextureInfo.setRequestStartTime(mID, mStartTime); U64 timeNow = LLTimer::getTotalTime(); @@ -2127,7 +2130,9 @@ void LLTextureFetch::sendRequestListToSimulators() // llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard // << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; - if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + static LLCachedControl log_to_viewer_log("LogTextureDownloadsToViewerLog",false); + static LLCachedControl log_to_sim("LogTextureDownloadsToSimulator",false); + if (log_to_viewer_log || log_to_sim) { mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); mTextureInfo.setRequestOffset(req->mID, 0); @@ -2347,7 +2352,10 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 if(packet_num >= (worker->mTotalPackets - 1)) { - if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + static LLCachedControl log_to_viewer_log("LogTextureDownloadsToViewerLog",false); + static LLCachedControl log_to_sim("LogTextureDownloadsToSimulator",false); + + if (log_to_viewer_log || log_to_sim) { U64 timeNow = LLTimer::getTotalTime(); mTextureInfo.setRequestSize(id, worker->mFileSize); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index dade65f1a..260c6e253 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -51,6 +51,8 @@ #include "lltoolmgr.h" #include "llviewerjoystick.h" +U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + //glu pick matrix implementation borrowed from Mesa3D glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport) { diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index d25d063a5..1fcda6362 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -54,6 +54,24 @@ const BOOL NOT_FOR_SELECTION = FALSE; class LLViewerCamera : public LLCamera, public LLSingleton { public: + + typedef enum + { + CAMERA_WORLD = 0, + CAMERA_SHADOW0, + CAMERA_SHADOW1, + CAMERA_SHADOW2, + CAMERA_SHADOW3, + CAMERA_SHADOW4, + CAMERA_SHADOW5, + CAMERA_WATER0, + CAMERA_WATER1, + CAMERA_GI_SOURCE, + NUM_CAMERAS + } eCameraID; + + static U32 sCurCameraID; + LLViewerCamera(); void updateCameraLocation(const LLVector3 ¢er, diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index b201fb877..089f52af8 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -356,6 +356,15 @@ static bool handleRenderUseVBOChanged(const LLSD& newvalue) return true; } +static bool handleRenderUseVBOMappingChanged(const LLSD& newvalue) +{ + if (gPipeline.isInit()) + { + gPipeline.setDisableVBOMapping(newvalue.asBoolean()); + } + return true; +} + static bool handleWLSkyDetailChanged(const LLSD&) { if (gSky.mVOWLSkyp.notNull()) @@ -602,6 +611,7 @@ void settings_setup_listeners() gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _1)); + gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleRenderUseVBOMappingChanged, _1)); gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _1)); gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _1)); gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _1)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0f8efb23b..765329cdc 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -131,6 +131,7 @@ void display_startup() return; } + gPipeline.updateGL(); LLGLSDefault gls_default; // Required for HTML update in login screen @@ -241,6 +242,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(LLFastTimer::FTM_RENDER); + if (LLPipeline::sRenderDeferred) + { //hack to make sky show up in deferred snapshots + for_snapshot = FALSE; + } + if (LLPipeline::sRenderFrameTest) { send_agent_pause(); @@ -614,6 +620,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); gPipeline.updateGeom(max_geom_update_time); + gPipeline.updateGL(); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_CULL); @@ -666,6 +673,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLGLState::checkClientArrays(); static LLCullResult result; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); @@ -706,6 +714,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); } + LLVertexBuffer::unbind(); + LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); @@ -781,7 +791,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gFrameStats.start(LLFrameStats::STATE_SORT); + gPipeline.sAllowRebuildPriorityGroup = TRUE ; gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); @@ -866,6 +878,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.bindTarget(); + glClearColor(0,0,0,0); gPipeline.mDeferredScreen.clear(); } else @@ -882,7 +895,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL) { - + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gGL.setColorMask(true, false); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { @@ -932,6 +945,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) render_ui(); } + gPipeline.rebuildGroups(); + LLSpatialGroup::sNoDelete = FALSE; } @@ -980,9 +995,10 @@ void render_hud_attachments() bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); //only render hud objects - U32 mask = gPipeline.getRenderTypeMask(); + gPipeline.pushRenderTypeMask(); + // turn off everything - gPipeline.setRenderTypeMask(0); + gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); // turn on HUD gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); // turn on HUD particles @@ -1009,6 +1025,7 @@ void render_hud_attachments() static LLCullResult result; LLSpatialGroup::sNoDelete = TRUE; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gPipeline.updateCull(hud_cam, result); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); @@ -1016,6 +1033,15 @@ void render_hud_attachments() gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); gPipeline.stateSort(hud_cam, result); @@ -1024,8 +1050,10 @@ void render_hud_attachments() LLSpatialGroup::sNoDelete = FALSE; render_hud_elements(); + //restore type mask - gPipeline.setRenderTypeMask(mask); + gPipeline.popRenderTypeMask(); + if (has_ui) { gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); @@ -1056,7 +1084,6 @@ BOOL setup_hud_matrices() S32 tile_height = llround((F32)gViewerWindow->getWindowHeight() / zoom_factor); int tile_y = sub_region / num_horizontal_tiles; int tile_x = sub_region - (tile_y * num_horizontal_tiles); - glh::matrix4f mat; whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height); } @@ -1158,6 +1185,10 @@ void render_ui(F32 zoom_factor, int subfield) render_ui_3d(); LLGLState::checkStates(); } + else + { + render_disconnected_background(); + } render_ui_2d(); LLGLState::checkStates(); @@ -1343,6 +1374,12 @@ void render_disconnected_background() gGL.color4f(1,1,1,1); if (!gDisconnectedImagep && gDisconnected) { + //Default black image. + gDisconnectedImagep = new LLImageGL( FALSE ); + LLPointer raw = new LLImageRaw(1,1,3); + raw->clear(); + gDisconnectedImagep->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + llinfos << "Loading last bitmap..." << llendl; std::string temp_str; @@ -1355,8 +1392,6 @@ void render_disconnected_background() return; } - gDisconnectedImagep = new LLImageGL( FALSE ); - LLPointer raw = new LLImageRaw; if (!image_bmp->decode(raw, 0.0f)) { llinfos << "Bitmap decode failed" << llendl; diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index c2591ac8d..8f2006b43 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -59,13 +59,9 @@ BOOL LLViewerJoint::sDisableLOD = FALSE; // Class Constructor //----------------------------------------------------------------------------- LLViewerJoint::LLViewerJoint() + : LLJoint() { - mUpdateXform = TRUE; - mValid = FALSE; - mComponents = SC_JOINT | SC_BONE | SC_AXES; - mMinPixelArea = DEFAULT_LOD; - mPickName = PN_DEFAULT; - mVisible = TRUE; + init(); } @@ -73,13 +69,21 @@ LLViewerJoint::LLViewerJoint() // LLViewerJoint() // Class Constructor //----------------------------------------------------------------------------- -LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) : - LLJoint(name, parent) +LLViewerJoint::LLViewerJoint(const std::string &name, LLJoint *parent) + : LLJoint(name, parent) +{ + init(); +} + + +void LLViewerJoint::init() { mValid = FALSE; mComponents = SC_JOINT | SC_BONE | SC_AXES; mMinPixelArea = DEFAULT_LOD; mPickName = PN_DEFAULT; + mVisible = TRUE; + mMeshID = 0; } @@ -436,13 +440,13 @@ void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pix } } -void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) +void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { LLViewerJoint* joint = (LLViewerJoint*)(*iter); - joint->updateFaceData(face, pixel_area, damp_wind); + joint->updateFaceData(face, pixel_area, damp_wind, terse_update); } } diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 0e993a2eb..ccfa99dd3 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -127,7 +127,7 @@ public: PickName getPickName() { return mPickName; } virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); + virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); virtual BOOL updateLOD(F32 pixel_area, BOOL activate); virtual void updateJointGeometry(); virtual void dump(); @@ -143,6 +143,8 @@ public: void setMeshID( S32 id ) {mMeshID = id;} protected: + void init(); + BOOL mValid; U32 mComponents; F32 mMinPixelArea; diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 608be31ec..b89e1eeaa 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -116,7 +116,7 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) object->mDrawable->makeActive(); LLVector3 current_pos = object->getRenderPosition(); LLQuaternion current_rot = object->getRenderRotation(); - LLQuaternion attachment_pt_inv_rot = ~getWorldRotation(); + LLQuaternion attachment_pt_inv_rot = ~(getWorldRotation()); current_pos -= getWorldPosition(); current_pos.rotVec(attachment_pt_inv_rot); @@ -173,10 +173,22 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object) // Pass through anyway to let setupDrawable() // re-connect object to the joint correctly } + + // Two instances of the same inventory item attached -- + // Request detach, and kill the object in the meantime. + if (getAttachedObject(object->getAttachmentItemID())) + { + llinfos << "(same object re-attached)" << llendl; + object->markDead(); + + // If this happens to be attached to self, then detach. + LLVOAvatar::detachAttachmentIntoInventory(object->getAttachmentItemID()); + return FALSE; + } mAttachedObjects.push_back(object); setupDrawable(object); - + if (mIsHUDAttachment) { if (object->mText.notNull()) diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 747016376..5e5a98d0b 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -148,6 +148,7 @@ LLViewerJointMesh::LLViewerJointMesh() mTexture( NULL ), mLayerSet( NULL ), mTestImageName( 0 ), + mFaceIndexCount(0), mIsTransparent(FALSE) { @@ -573,7 +574,10 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else if ( !is_dummy && mTexture.notNull() ) { - old_mode = mTexture->getAddressMode(); + if(mTexture->getHasGLTexture()) + { + old_mode = mTexture->getAddressMode(); + } gGL.getTexUnit(0)->bind(mTexture.get()); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } @@ -663,7 +667,8 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 //----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- -void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) + +void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { mFace = face; @@ -690,29 +695,98 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w face->mVertexBuffer->getIndexStrider(indicesp); stop_glerror(); - for (U16 i = 0; i < mMesh->getNumVertices(); i++) + verticesp += mMesh->mFaceVertexOffset; + tex_coordsp += mMesh->mFaceVertexOffset; + normalsp += mMesh->mFaceVertexOffset; + vertex_weightsp += mMesh->mFaceVertexOffset; + clothing_weightsp += mMesh->mFaceVertexOffset; + + const U32* __restrict coords = (U32*) mMesh->getCoords(); + const U32* __restrict tex_coords = (U32*) mMesh->getTexCoords(); + const U32* __restrict normals = (U32*) mMesh->getNormals(); + const U32* __restrict weights = (U32*) mMesh->getWeights(); + const U32* __restrict cloth_weights = (U32*) mMesh->getClothingWeights(); + + const U32 num_verts = mMesh->getNumVertices(); + + U32 i = 0; + + const U32 skip = verticesp.getSkip()/sizeof(U32); + + U32* __restrict v = (U32*) verticesp.get(); + U32* __restrict n = (U32*) normalsp.get(); + + if (terse_update) { - verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i); - tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i); - normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i); - vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i); - if (damp_wind) + for (S32 i = num_verts; i > 0; --i) { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0); + //morph target application only, only update positions and normals + v[0] = coords[0]; + v[1] = coords[1]; + v[2] = coords[2]; + coords += 3; + v += skip; } - else + + for (S32 i = num_verts; i > 0; --i) { - clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i)); + n[0] = normals[0]; + n[1] = normals[1]; + n[2] = normals[2]; + normals += 3; + n += skip; } } - - for (S32 i = 0; i < mMesh->getNumFaces(); i++) - { - for (U32 j = 0; j < 3; j++) + else { - U32 k = i*3+j+mMesh->mFaceIndexOffset; - indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset; + + U32* __restrict tc = (U32*) tex_coordsp.get(); + U32* __restrict vw = (U32*) vertex_weightsp.get(); + U32* __restrict cw = (U32*) clothing_weightsp.get(); + + do + { + v[0] = *(coords++); + v[1] = *(coords++); + v[2] = *(coords++); + v += skip; + + tc[0] = *(tex_coords++); + tc[1] = *(tex_coords++); + tc += skip; + + n[0] = *(normals++); + n[1] = *(normals++); + n[2] = *(normals++); + n += skip; + + vw[0] = *(weights++); + vw += skip; + + cw[0] = *(cloth_weights++); + cw[1] = *(cloth_weights++); + cw[2] = *(cloth_weights++); + cw[3] = *(cloth_weights++); + cw += skip; } + while (++i < num_verts); + + const U32 idx_count = mMesh->getNumFaces()*3; + + indicesp += mMesh->mFaceIndexOffset; + + U16* __restrict idx = indicesp.get(); + S32* __restrict src_idx = (S32*) mMesh->getFaces(); + + i = 0; + + const S32 offset = (S32) mMesh->mFaceVertexOffset; + + do + { + *(idx++) = *(src_idx++)+offset; + } + while (++i < idx_count); } } } diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h index ee019f659..721c3f1dd 100644 --- a/indra/newview/llviewerjointmesh.h +++ b/indra/newview/llviewerjointmesh.h @@ -141,7 +141,7 @@ public: /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ); /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); + /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); /*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate); /*virtual*/ void updateJointGeometry(); /*virtual*/ void dump(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8729d5714..f5f3513d8 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1365,10 +1365,12 @@ void init_debug_rendering_menu(LLMenuGL* menu) &LLPipeline::toggleRenderTypeControl, NULL, &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_GRASS, '0', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); + //NOTE: Using a static variable, as an unsigned long long cannot fit in the space of a pointer. Pass pointer to callbacks + static U64 cloud_flags = (1ULL<append(new LLMenuItemCheckGL("Clouds", //This clobbers skyuseclassicclouds, but.. big deal. &LLPipeline::toggleRenderPairedTypeControl, NULL, &LLPipeline::hasRenderPairedTypeControl, - (void*)(1<append(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderTypeControl, NULL, &LLPipeline::hasRenderTypeControl, diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6a754665c..1b33b6515 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -208,7 +208,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mState(0), mMedia(NULL), mClickAction(0), - mAttachmentItemID(LLUUID::null) + mAttachmentItemID(LLUUID::null), + mLastUpdateType(OUT_UNKNOWN), + mLastUpdateCached(FALSE) { if(!is_global) { @@ -454,7 +456,6 @@ void LLViewerObject::initVOClasses() llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl; LLVOGrass::initClass(); LLVOWater::initClass(); - LLVOSky::initClass(); LLVOVolume::initClass(); } @@ -2860,6 +2861,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) return TRUE; } +void LLViewerObject::updateGL() +{ + +} + void LLViewerObject::updateFaceSize(S32 idx) { @@ -3786,6 +3792,15 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos } +void LLViewerObject::changeTEImage(S32 index, LLViewerImage* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTEImages[index] = new_image ; +} + S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim @@ -4651,7 +4666,7 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin) { ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param->in_use != in_use) + if (param && param->in_use != in_use) { param->in_use = in_use; parameterChanged(param_type, param->data, in_use, local_origin); @@ -5071,7 +5086,7 @@ U32 LLViewerObject::getPartitionType() const return LLViewerRegion::PARTITION_NONE; } -void LLViewerObject::dirtySpatialGroup() const +void LLViewerObject::dirtySpatialGroup(BOOL priority) const { if (mDrawable) { @@ -5079,6 +5094,7 @@ void LLViewerObject::dirtySpatialGroup() const if (group) { group->dirtyGeom(); + gPipeline.markRebuild(group, priority); } } } @@ -5266,7 +5282,25 @@ std::string LLViewerObject::getAttachmentPointName() return llformat("unsupported point %d", point); } // +EObjectUpdateType LLViewerObject::getLastUpdateType() const +{ + return mLastUpdateType; +} +void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) +{ + mLastUpdateType = last_update_type; +} + +BOOL LLViewerObject::getLastUpdateCached() const +{ + return mLastUpdateCached; +} + +void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) +{ + mLastUpdateCached = last_update_cached; +} const LLUUID &LLViewerObject::extractAttachmentItemID() { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 2eb8819dd..a0e790d3e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -81,6 +81,7 @@ typedef enum e_object_update_type OUT_TERSE_IMPROVED, OUT_FULL_COMPRESSED, OUT_FULL_CACHED, + OUT_UNKNOWN, } EObjectUpdateType; @@ -116,7 +117,7 @@ public: //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount +class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate { protected: ~LLViewerObject(); // use unref() @@ -194,6 +195,7 @@ public: virtual LLDrawable* createDrawable(LLPipeline *pipeline); virtual BOOL updateGeometry(LLDrawable *drawable); + virtual void updateGL(); virtual void updateFaceSize(S32 idx); virtual BOOL updateLOD(); virtual BOOL setDrawableParent(LLDrawable* parentp); @@ -312,6 +314,7 @@ public: /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ BOOL setMaterial(const U8 material); virtual void setTEImage(const U8 te, LLViewerImage *imagep); // Not derived from LLPrimitive + void changeTEImage(S32 index, LLViewerImage* new_image) ; LLViewerImage *getTEImage(const U8 te) const; void fitFaceTexture(const U8 face); @@ -450,6 +453,7 @@ public: inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); } inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); } inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } + inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } bool getIncludeInSearch() const; void setIncludeInSearch(bool include_in_search); @@ -474,7 +478,7 @@ public: virtual S32 getLOD() const { return 3; } virtual U32 getPartitionType() const; - virtual void dirtySpatialGroup() const; + virtual void dirtySpatialGroup(BOOL priority = FALSE) const; virtual void dirtyMesh(); virtual LLNetworkData* getParameterEntry(U16 param_type) const; @@ -673,8 +677,14 @@ public: const LLUUID &getAttachmentItemID() const { return mAttachmentItemID; } void setAttachmentItemID(const LLUUID &id) { mAttachmentItemID = id; } const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object + EObjectUpdateType getLastUpdateType() const; + void setLastUpdateType(EObjectUpdateType last_update_type); + BOOL getLastUpdateCached() const; + void setLastUpdateCached(BOOL last_update_cached); private: LLUUID mAttachmentItemID; // ItemID when item is in user inventory. + EObjectUpdateType mLastUpdateType; + BOOL mLastUpdateCached; }; typedef std::vector llvo_vec_t; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 3d6471ab5..4f50fec6e 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -570,6 +570,9 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } } // + + objectp->setLastUpdateType(update_type); + objectp->setLastUpdateCached(cached); } LLVOAvatar::cullAvatarsByPixelArea(); @@ -842,13 +845,14 @@ void LLViewerObjectList::clearDebugText() void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); - if (mDeadObjects.count(objectp->mID)) + if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) { llinfos << "Object " << objectp->mID << " already on dead list, ignoring cleanup!" << llendl; - return; } - - mDeadObjects.insert(std::pair >(objectp->mID, objectp)); + else + { + mDeadObjects.insert(std::pair >(objectp->mID, objectp)); + } // Cleanup any references we have to this object // Remove from object map so noone can look it up. @@ -1064,7 +1068,7 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { objectp = getObject(i); // There could be dead objects on the object list, so don't update stuff if the object is dead. - if (objectp) + if (objectp && !objectp->isDead()) { objectp->updatePositionCaches(); @@ -1097,7 +1101,7 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) for (S32 i = 0; i < mMapObjects.count(); i++) { LLViewerObject* objectp = mMapObjects[i]; - if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment()) + if (objectp->isDead() || !objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment()) { continue; } diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 5cea9c2ae..d005bd010 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -97,8 +97,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ mOwnership[i] = PARCEL_PUBLIC; } - // Make sure the texture matches the ownership information. - updateOverlayTexture(); + gPipeline.markGLRebuild(this); } @@ -711,6 +710,11 @@ void LLViewerParcelOverlay::setDirty() mDirty = TRUE; } +void LLViewerParcelOverlay::updateGL() +{ + updateOverlayTexture(); +} + void LLViewerParcelOverlay::idleUpdate(bool force_update) { if (gGLManager.mIsDisabled) @@ -720,7 +724,7 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update) if (mOverlayTextureIdx >= 0 && (!(mDirty && force_update))) { // We are in the middle of updating the overlay texture - updateOverlayTexture(); + gPipeline.markGLRebuild(this); return; } // Only if we're dirty and it's been a while since the last update. diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 9bed1dde3..1ab83a20a 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -40,13 +40,14 @@ #include "llframetimer.h" #include "lluuid.h" #include "llviewerimage.h" +#include "llgl.h" class LLViewerRegion; class LLVector3; class LLColor4U; class LLVector2; -class LLViewerParcelOverlay +class LLViewerParcelOverlay : public LLGLUpdate { public: LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters); @@ -76,6 +77,7 @@ public: void setDirty(); void idleUpdate(bool update_now = false); + void updateGL(); private: // This is in parcel rows and columns, not grid rows and columns diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index b74f9e9f2..d5c28fb67 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -81,6 +81,7 @@ F32 calc_desired_size(LLVector3 pos, LLVector2 scale) LLViewerPart::LLViewerPart() : mPartID(0), mLastUpdateTime(0.f), + mSkipOffset(0.f), mVPCallback(NULL), mImagep(NULL) { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 98fe69549..8ef475a24 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -127,7 +127,8 @@ LLGLSLShader gDeferredFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); / GLint gAvatarMatrixParam; LLViewerShaderMgr::LLViewerShaderMgr() : - mVertexShaderLevel(SHADER_COUNT, 0) + mVertexShaderLevel(SHADER_COUNT, 0), + mMaxAvatarShaderLevel(0) {} LLViewerShaderMgr::~LLViewerShaderMgr() @@ -253,10 +254,15 @@ S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type) void LLViewerShaderMgr::setShaders() { - if (!gPipeline.mInitialized || !sInitialized) + //setShaders might be called redundantly by gSavedSettings, so return on reentrance + static bool reentrance = false; + + if (!gPipeline.mInitialized || !sInitialized || reentrance) { return; } + + reentrance = true; initAttribsAndUniforms(); gPipeline.releaseGLBuffers(); @@ -269,8 +275,8 @@ void LLViewerShaderMgr::setShaders() } else { - LLPipeline::sRenderGlow = - LLPipeline::sWaterReflections = FALSE; + LLPipeline::sRenderGlow = FALSE; + LLPipeline::sWaterReflections = FALSE; } //hack to reset buffers that change behavior with shaders @@ -302,6 +308,21 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; + + if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + gSavedSettings.getBOOL("RenderDeferred")) + { + deferred_class = 1; + + //make sure framebuffer objects are enabled + gSavedSettings.setBOOL("RenderUseFBO", TRUE); + + //make sure hardware skinning is enabled + gSavedSettings.setBOOL("RenderAvatarVP", TRUE); + + //make sure atmospheric shaders are enabled + gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE); + } if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) { @@ -310,11 +331,6 @@ void LLViewerShaderMgr::setShaders() wl_class = 1; } - if (LLPipeline::sRenderDeferred) - { - deferred_class = 1; - } - if(!gSavedSettings.getBOOL("EnableRippleWater")) { water_class = 0; @@ -428,6 +444,7 @@ void LLViewerShaderMgr::setShaders() gViewerWindow->setCursor(UI_CURSOR_ARROW); } gPipeline.createGLBuffers(); + reentrance = false; } void LLViewerShaderMgr::unloadShaders() diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 674b412c4..501126abd 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1544,7 +1544,7 @@ LLViewerWindow::LLViewerWindow( { gSavedSettings.setBOOL("RenderVBOEnable", FALSE); } - LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable")); + LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable")); if (LLFeatureManager::getInstance()->isSafe() || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) @@ -2065,6 +2065,9 @@ LLViewerWindow::~LLViewerWindow() { llinfos << "Destroying Window" << llendl; destroyWindow(); + + delete mDebugText; + mDebugText = NULL; } @@ -5395,11 +5398,15 @@ void LLPickInfo::fetchResults() // put global position into land_pos LLVector3d land_pos; - if (gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos)) + if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos)) { - // Fudge the land focus a little bit above ground. - mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; + // The selected point is beyond the draw distance or is otherwise + // not selectable. Return before calling mPickCallback(). + return; } + + // Fudge the land focus a little bit above ground. + mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; } else { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 14e796e6e..fcbc65a11 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -830,7 +830,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } - mDirtyMesh = TRUE; // Dirty geometry, need to regenerate. + mDirtyMesh = 2; // Dirty geometry, need to regenerate. + mMeshTexturesDirty = FALSE; mShadow0Facep = NULL; mShadow1Facep = NULL; mHeadp = NULL; @@ -2461,7 +2462,7 @@ void LLVOAvatar::updateMeshData() } if(num_vertices < 1)//skip empty meshes { - break ; + continue ; } if(last_v_num > 0)//put the last inserted part into next vertex buffer. { @@ -2483,6 +2484,8 @@ void LLVOAvatar::updateMeshData() // resize immediately facep->setSize(num_vertices, num_indices); + bool terse_update = false; + if(facep->mVertexBuffer.isNull()) { facep->mVertexBuffer = new LLVertexBufferAvatar(); @@ -2490,7 +2493,15 @@ void LLVOAvatar::updateMeshData() } else { - facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ; + if (facep->mVertexBuffer->getRequestedIndices() == num_indices && + facep->mVertexBuffer->getRequestedVerts() == num_vertices) + { + terse_update = true; + } + else + { + facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ; + } } facep->setGeomIndex(0); @@ -2505,7 +2516,7 @@ void LLVOAvatar::updateMeshData() for(S32 k = j ; k < part_index ; k++) { - mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR); + mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update); } stop_glerror(); @@ -4903,13 +4914,20 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } - if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + LLFace* face = mDrawable->getFace(0); + + bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); + + if (needs_rebuild || mDirtyMesh) { //LOD changed or new mesh created, allocate new vertex buffer if needed + if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) + { updateMeshData(); - mDirtyMesh = FALSE; + mDirtyMesh = 0; mNeedsSkin = TRUE; mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } + } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) { @@ -6693,7 +6711,7 @@ BOOL LLVOAvatar::updateJointLODs() if (res) { sNumLODChangesThisFrame++; - dirtyMesh(); + dirtyMesh(2); return TRUE; } } @@ -6728,11 +6746,20 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) mNumInitFaces = mDrawable->getNumFaces() ; - dirtyMesh(); + dirtyMesh(2); return mDrawable; } +void LLVOAvatar::updateGL() +{ + if (mMeshTexturesDirty) + { + updateMeshTextures(); + mMeshTexturesDirty = FALSE; + } +} + //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- @@ -6874,9 +6901,12 @@ void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user ) //----------------------------------------------------------------------------- void LLVOAvatar::dirtyMesh() { - mDirtyMesh = TRUE; + dirtyMesh(1); +} +void LLVOAvatar::dirtyMesh(S32 priority) +{ + mDirtyMesh = llmax(mDirtyMesh, priority); } - //----------------------------------------------------------------------------- // hideSkirt() //----------------------------------------------------------------------------- @@ -9142,7 +9172,8 @@ void LLVOAvatar::onFirstTEMessageReceived() } } - updateMeshTextures(); + mMeshTexturesDirty = TRUE; + gPipeline.markGLRebuild(this); } } @@ -9227,6 +9258,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } setCompositeUpdatesEnabled( FALSE ); + mMeshTexturesDirty = TRUE; + gPipeline.markGLRebuild(this); if (!mIsSelf) { @@ -10437,21 +10470,22 @@ void LLVOAvatar::updateFreezeCounter(S32 counter) BOOL LLVOAvatar::updateLOD() { + if (isImpostor()) + { + return TRUE; + } BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (facep->mVertexBuffer.isNull() || - (LLVertexBuffer::sEnableVBOs && - ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != - (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))) + if (facep->mVertexBuffer.isNull()) { - mDirtyMesh = TRUE; + dirtyMesh(2); } - if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) { //LOD changed or new mesh created, allocate new vertex buffer if needed updateMeshData(); - mDirtyMesh = FALSE; + mDirtyMesh = 0; mNeedsSkin = TRUE; mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index ac5906a44..5b4149bdf 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -103,6 +103,7 @@ public: // LLViewerObject interface //-------------------------------------------------------------------- public: + virtual void updateGL(); static void initClass(); // Initialize data that's only init'd once per class. static void cleanupClass(); // Cleanup data that's only init'd once per class. static BOOL parseSkeletonFile(const std::string& filename); @@ -246,7 +247,7 @@ public: BOOL isVisible(); BOOL isSelf() const { return mIsSelf; } BOOL isCulled() const { return mCulled; } - + bool isBuilt() const { return mIsBuilt; } public: static void cullAvatarsByPixelArea(); void setVisibilityRank(U32 rank); @@ -295,7 +296,6 @@ public: void processAvatarAppearance( LLMessageSystem* mesgsys ); void onFirstTEMessageReceived(); void updateSexDependentLayerSets( BOOL set_by_user ); - void dirtyMesh(); // Dirty the avatar mesh void hideSkirt(); @@ -660,7 +660,6 @@ private: BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients // LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations - BOOL mDirtyMesh; BOOL mTurning; // controls hysteresis on avatar rotation F32 mSpeed; // misc. animation repeated state @@ -673,7 +672,7 @@ private: BOOL mMeshValid; BOOL mVisible; LLFrameTimer mMeshInvisibleTime; - + // Lip synch morph stuff bool mLipSyncActive; // we're morphing for lip sync LLVisualParam* mOohMorph; // cached pointers morphs for lip sync @@ -878,6 +877,13 @@ private: static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; static LLVOAvatarXmlInfo* sAvatarXmlInfo; +public: + void dirtyMesh(); +private: + void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD + BOOL mMeshTexturesDirty; + //----------------------------------------------------------------------------------------------- // Diagnostics //----------------------------------------------------------------------------------------------- diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 3f1c132e7..4f4330b17 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -104,7 +104,10 @@ LLVOCacheEntry::LLVOCacheEntry(LLFILE *fp) LLVOCacheEntry::~LLVOCacheEntry() { - delete [] mBuffer; + if(mBuffer) + { + delete [] mBuffer; + } } diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index ee195af09..a24054b4f 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -123,7 +123,10 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) return TRUE; } - dirtySpatialGroup(); + if (drawable->isVisible()) + { + dirtySpatialGroup(TRUE); + } LLFace *facep; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 0923483c2..f5c4e9d3c 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -45,6 +45,7 @@ #include "llsurface.h" #include "llsurfacepatch.h" #include "llvosky.h" +#include "llvotree.h" #include "llviewercamera.h" #include "llviewerimagelist.h" #include "llviewerregion.h" @@ -304,6 +305,22 @@ BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } + if(LLVOTree::isTreeRenderingStopped()) //stop rendering grass + { + if(mNumBlades) + { + mNumBlades = 0 ; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + return TRUE ; + } + else if(!mNumBlades)//restart grass rendering + { + mNumBlades = GRASS_MAX_BLADES ; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + + return TRUE ; + } if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime())) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); @@ -350,7 +367,20 @@ BOOL LLVOGrass::updateLOD() { return FALSE; } - + if(LLVOTree::isTreeRenderingStopped()) + { + if(mNumBlades) + { + mNumBlades = 0 ; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + return TRUE ; + } + if(!mNumBlades) + { + mNumBlades = GRASS_MAX_BLADES; + } + LLFace* face = mDrawable->getFace(0); F32 tan_angle = 0.f; @@ -396,7 +426,22 @@ BOOL LLVOGrass::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_GRASS); dirtySpatialGroup(); - plantBlades(); + + if(!mNumBlades)//stop rendering grass + { + if (mDrawable->getNumFaces() > 0) + { + LLFace* facep = mDrawable->getFace(0); + if(facep) + { + facep->setSize(0, 0); + } + } + } + else + { + plantBlades(); + } return TRUE; } @@ -437,6 +482,11 @@ void LLVOGrass::getGeometry(S32 idx, LLStrider& colorsp, LLStrider& indicesp) { + if(!mNumBlades)//stop rendering grass + { + return ; + } + mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); if (mPatch) mLastPatchUpdateTime = mPatch->getLastUpdateTime(); diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index a0f80689e..b6ba7e50f 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -154,6 +154,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) group = drawable->getSpatialGroup(); } + if (group && group->isVisible()) + { + dirtySpatialGroup(TRUE); + } + if (!num_parts) { if (group && drawable->getNumFaces()) @@ -352,12 +357,11 @@ U32 LLVOPartGroup::getPartitionType() const } LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; mPartitionType = LLViewerRegion::PARTITION_PARTICLE; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; mSlopRatio = 0.f; mLODPeriod = 1; } @@ -375,6 +379,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) { LLDrawable* drawablep = *i; @@ -404,7 +409,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } count++; - facep->mDistance = (facep->mCenterLocal - LLViewerCamera::getInstance()->getOrigin()) * LLViewerCamera::getInstance()->getAtAxis(); + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); obj->mDepth += facep->mDistance; mFaceList.push_back(facep); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index ff6bba3b3..0443aaaca 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -78,16 +78,9 @@ static const LLVector2 TEX01 = LLVector2(0.f, 1.f); static const LLVector2 TEX10 = LLVector2(1.f, 0.f); static const LLVector2 TEX11 = LLVector2(1.f, 1.f); -// Exported global semi-constants. +// Exported globals LLUUID gSunTextureID = IMG_SUN; LLUUID gMoonTextureID = IMG_MOON; -// Exported global constants. -LLColor3 const gAirScaSeaLevel = calc_air_sca_sea_level(); -F32 const AIR_SCA_INTENS = color_intens(gAirScaSeaLevel); -F32 const AIR_SCA_AVG = AIR_SCA_INTENS / 3.f; - -//static -LLColor3 LLHaze::sAirScaSeaLevel; class LLFastLn { @@ -191,6 +184,23 @@ inline void color_gamma_correct(LLColor3 &col) } } +static LLColor3 calc_air_sca_sea_level() +{ + static LLColor3 WAVE_LEN(675, 520, 445); + static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN); + static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1); + static LLColor3 n4 = n21 * n21; + static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f; + static LLColor3 wl4 = wl2 * wl2; + static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4; + static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2); + return dens_div_N * color_div ( mult_const, wl4 ); +} + +// static constants. +LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level(); +F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel); +F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f; /*************************************** @@ -389,22 +399,21 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mHeavenlyBodyUpdated = FALSE ; + + mDrawRefl = 0; + mHazeConcentration = 0.f; + mInterpVal = 0.f; } LLVOSky::~LLVOSky() { - // Don't delete images - it'll get deleted by gImageList on shutdown + // Don't delete images - it'll get deleted by gTextureList on shutdown // This needs to be done for each texture mCubeMap = NULL; } -void LLVOSky::initClass() -{ - LLHaze::initClass(); -} - void LLVOSky::init() { @@ -969,7 +978,7 @@ void LLVOSky::calcAtmospherics(void) // and vary_sunlight will work properly with moon light F32 lighty = unclamped_lightnorm[1]; - if(lighty < NIGHTTIME_ELEVATION_COS) + if(lighty < LLSky::NIGHTTIME_ELEVATION_COS) { lighty = -lighty; } @@ -1080,10 +1089,10 @@ BOOL LLVOSky::updateSky() ++next_frame; next_frame = next_frame % cycle_frame_no; - sInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no; + mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no; // sInterpVal = (F32)next_frame / cycle_frame_no; - LLSkyTex::setInterpVal( sInterpVal ); - LLHeavenBody::setInterpVal( sInterpVal ); + LLSkyTex::setInterpVal( mInterpVal ); + LLHeavenBody::setInterpVal( mInterpVal ); calcAtmospherics(); if (mForceUpdate || total_no_tiles == frame) @@ -2151,17 +2160,8 @@ void LLVOSky::updateFog(const F32 distance) stop_glerror(); } -// static -void LLHaze::initClass() -{ - sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel(); -} - - // Functions used a lot. - - F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply) { F32 mv = color_max(col); diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 137082481..19dd1443d 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -147,8 +147,8 @@ protected: static S32 getResolution() { return sResolution; } static S32 getCurrent() { return sCurrent; } - static S32 stepCurrent() { sCurrent++; sCurrent&=1; return sCurrent; } - static S32 getNext() { return ((sCurrent+1) % 2); } + static S32 stepCurrent() { sCurrent++; sCurrent &= 1; return sCurrent; } + static S32 getNext() { return ((sCurrent+1) & 1); } static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); } void initEmpty(const S32 tex); @@ -298,24 +298,6 @@ LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length) } -LL_FORCE_INLINE LLColor3 calc_air_sca_sea_level() -{ - const static LLColor3 WAVE_LEN(675, 520, 445); - const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN); - const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1); - const static LLColor3 n4 = n21 * n21; - const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f; - const static LLColor3 wl4 = wl2 * wl2; - const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4; - const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2); - return dens_div_N * color_div ( mult_const, wl4 ); -} - -// Non-POD constants. -extern LLColor3 const gAirScaSeaLevel; -extern F32 const AIR_SCA_INTENS; -extern F32 const AIR_SCA_AVG; - class LLHaze { public: @@ -323,18 +305,15 @@ public: LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2.f) : mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0.f) { - mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS; + mAbsCoef = color_intens(mSigSca) / sAirScaIntense; } LLHaze(const F32 g, const F32 sca, const F32 fo = 2.f) : mG(g), mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo) { - mAbsCoef = 0.01f * sca / AIR_SCA_AVG; + mAbsCoef = 0.01f * sca / sAirScaAvg; } - static void initClass(); - - F32 getG() const { return mG; } void setG(const F32 g) @@ -350,12 +329,12 @@ public: void setSigSca(const LLColor3& s) { mSigSca = s; - mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS; + mAbsCoef = 0.01f * color_intens(mSigSca) / sAirScaIntense; } void setSigSca(const F32 s0, const F32 s1, const F32 s2) { - mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2); + mSigSca = sAirScaAvg * LLColor3 (s0, s1, s2); mAbsCoef = 0.01f * (s0 + s1 + s2) / 3; } @@ -399,10 +378,11 @@ public: static inline LLColor3 calcAirSca(const F32 h); static inline void calcAirSca(const F32 h, LLColor3 &result); - static LLColor3 calcAirScaSeaLevel() { return gAirScaSeaLevel; } - static const LLColor3 &getAirScaSeaLevel() { return sAirScaSeaLevel; } -public: - static LLColor3 sAirScaSeaLevel; + +private: + static LLColor3 const sAirScaSeaLevel; + static F32 const sAirScaIntense; + static F32 const sAirScaAvg; protected: F32 mG; @@ -480,7 +460,6 @@ public: LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); // Initialize/delete data that's only inited once per class. - static void initClass(); void init(); void initCubeMap(); void initEmpty(); @@ -614,7 +593,7 @@ protected: LLColor3 mLastTotalAmbient; F32 mAmbientScale; LLColor3 mNightColorShift; - F32 sInterpVal; + F32 mInterpVal; LLColor4 mFogColor; LLColor4 mGLFogCol; @@ -661,14 +640,12 @@ F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE); inline LLColor3 LLHaze::calcAirSca(const F32 h) { - static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel(); - return calcFalloff(h) * air_sca_sea_level; + return calcFalloff(h) * sAirScaSeaLevel; } inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result) { - static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel(); - result = air_sca_sea_level; + result = sAirScaSeaLevel; result *= calcFalloff(h); } diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 1671880ba..0cb390f02 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -177,11 +177,19 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) } +void LLVOSurfacePatch::updateGL() +{ + if (mPatchp) + { + mPatchp->updateGL(); + } +} + BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN); - dirtySpatialGroup(); + dirtySpatialGroup(TRUE); S32 min_comp, max_comp, range; min_comp = lltrunc(mPatchp->getMinComposition()); @@ -1013,12 +1021,10 @@ U32 LLVOSurfacePatch::getPartitionType() const } LLTerrainPartition::LLTerrainPartition() -: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK) +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB) { mOcclusionEnabled = FALSE; - mRenderByGroup = FALSE; mInfiniteFarClip = TRUE; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; mPartitionType = LLViewerRegion::PARTITION_TERRAIN; } diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index d3b144774..10a588852 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -64,6 +64,7 @@ public: virtual U32 getPartitionType() const; /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ void updateGL(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); /*virtual*/ void updateFaceSize(S32 idx); diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index b5481d100..2c6fa925a 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -101,6 +101,12 @@ LLVOTree::~LLVOTree() } } +//static +bool LLVOTree::isTreeRenderingStopped() +{ + return LLVOTree::sTreeFactor < LLVOTree::sLODAngles[4 - 1] ; +} + // static void LLVOTree::initClass() { @@ -1324,9 +1330,8 @@ U32 LLVOTree::getPartitionType() const } LLTreePartition::LLTreePartition() -: LLSpatialPartition(0) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; mSlopRatio = 0.f; diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 6de872ae6..133f39352 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -59,6 +59,7 @@ public: // Initialize data that's only inited once per class. static void initClass(); static void cleanupClass(); + static bool isTreeRenderingStopped(); /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f0da8ddba..03c2c5345 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -87,8 +87,10 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXform.setIdentity(); mRelativeXformInvTrans.setIdentity(); + mFaceMappingChanged = FALSE; mLOD = MIN_LOD; mTextureAnimp = NULL; + mVolumeChanged = FALSE; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; mLODChanged = FALSE; @@ -104,6 +106,20 @@ LLVOVolume::~LLVOVolume() mVolumeImpl = NULL; } +void LLVOVolume::markDead() +{ + if (!mDead) + { + + if (mSculptTexture.notNull()) + { + mSculptTexture->removeVolume(this); + } + } + + LLViewerObject::markDead(); +} + // static void LLVOVolume::initClass() @@ -407,6 +423,18 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) mVolumeImpl->doIdleUpdate(agent, world, time); } + const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; + + if (mDrawable->isActive()) + { + if (mDrawable->isRoot() && + mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && + (!mDrawable->getParent() || !mDrawable->getParent()->isActive())) + { + mDrawable->makeStatic(); + } + } + return TRUE; } @@ -443,7 +471,7 @@ void LLVOVolume::updateTextureVirtualSize() { // Update the pixel area of all faces - if(mDrawable.isNull() || !mDrawable->isVisible()) + if(!isVisible()) { return ; } @@ -465,6 +493,7 @@ void LLVOVolume::updateTextureVirtualSize() const S32 num_faces = mDrawable->getNumFaces(); F32 min_vsize=999999999.f, max_vsize=0.f; + LLViewerCamera* camera = LLViewerCamera::getInstance(); for (S32 i = 0; i < num_faces; i++) { LLFace* face = mDrawable->getFace(i); @@ -485,6 +514,7 @@ void LLVOVolume::updateTextureVirtualSize() vsize = area; imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_HUD); face->setPixelArea(area); // treat as full screen + face->setVirtualSize(vsize); } else { @@ -513,8 +543,7 @@ void LLVOVolume::updateTextureVirtualSize() gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); } } - - face->setVirtualSize(vsize); + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { if (vsize < min_vsize) min_vsize = vsize; @@ -554,9 +583,9 @@ void LLVOVolume::updateTextureVirtualSize() //if the sculpty very close to the view point, load first { - LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin(); + LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; } } @@ -719,6 +748,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail if (isSculpted()) { + updateSculptTexture(); + if (mSculptTexture.notNull()) { sculpt(); @@ -850,9 +881,6 @@ BOOL LLVOVolume::calcLOD() return FALSE; } - //update face texture sizes on lod calculation - updateTextureVirtualSize(); - S32 cur_detail = 0; F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); @@ -1163,7 +1191,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return res; } - dirtySpatialGroup(); + dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); BOOL compiled = FALSE; @@ -2124,7 +2152,7 @@ U32 LLVOVolume::getPartitionType() const } LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE) +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) { mLODPeriod = 16; mDepthMask = FALSE; @@ -2135,7 +2163,7 @@ LLVolumePartition::LLVolumePartition() } LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) { mDepthMask = FALSE; mLODPeriod = 16; @@ -2169,6 +2197,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || (type == LLRenderPass::PASS_INVISIBLE) || (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)); + + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + llwarns << "Non fullbright face has no normals!" << llendl; + return; + } const LLMatrix4* tex_mat = NULL; if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) @@ -2481,7 +2515,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (LLPipeline::sDelayVBUpdate) { - group->setState(LLSpatialGroup::MESH_DIRTY); + group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } mFaceList.clear(); @@ -2572,7 +2606,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } - group->clearState(LLSpatialGroup::MESH_DIRTY); + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } } @@ -2752,74 +2786,77 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } else if (gPipeline.canUseVertexShaders() + && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) - { + { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim+shiny registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (LLPipeline::sRenderDeferred) - { + { //deferred rendering if (te->getBumpmap()) - { + { //register in deferred bump pass registerFace(group, facep, LLRenderPass::PASS_BUMP); } else if (te->getFullbright()) - { + { //register in post deferred fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else - { + { //register in deferred simple pass (deferred simple includes shiny) llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } else if (fullbright) - { + { //not deferred, register in standard fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else - { + { //not deferred or fullbright, register in standard shiny pass registerFace(group, facep, LLRenderPass::PASS_SHINY); } } else - { + { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (fullbright) - { + { //fullbright registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); } else { - if (LLPipeline::sRenderDeferred && te->getBumpmap()) - { + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //non-shiny or fullbright deferred bump registerFace(group, facep, LLRenderPass::PASS_BUMP); } else - { + { //all around simple llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } - if (!is_alpha && te->getShiny()) + //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 + if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) { registerFace(group, facep, LLRenderPass::PASS_SHINY); } } + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 if (!is_alpha && !LLPipeline::sRenderDeferred) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - if (!force_simple && te->getBumpmap()) + if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump) { registerFace(group, facep, LLRenderPass::PASS_BUMP); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 5935316e4..371a01d5d 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -92,6 +92,7 @@ public: public: LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 501f3c2da..f53654179 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -69,8 +69,9 @@ const U32 WIDTH = (N_RES * WAVE_STEP); //128.f //64 // width of wave tile, in const F32 WAVE_STEP_INV = (1. / WAVE_STEP); -LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLStaticViewerObject(id, pcode, regionp) +LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : + LLStaticViewerObject(id, pcode, regionp), + mRenderType(LLPipeline::RENDER_TYPE_WATER) { // Terrain must draw during selection passes so it can block objects behind it. mbCanSelect = FALSE; @@ -78,9 +79,9 @@ LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regi mUseTexture = TRUE; mIsEdgePatch = FALSE; - mRenderType = LLPipeline::RENDER_TYPE_WATER; } + void LLVOWater::markDead() { LLViewerObject::markDead(); @@ -281,9 +282,8 @@ U32 LLVOVoidWater::getPartitionType() const } LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; mPartitionType = LLViewerRegion::PARTITION_WATER; diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 55ce6d789..30753daa3 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -72,7 +72,7 @@ public: /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area - /*virtual*/ U32 getPartitionType() const; + virtual U32 getPartitionType() const; /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index abd25e659..8d63b069c 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -49,12 +49,12 @@ const U32 LLVOWLSky::MAX_SKY_DETAIL = 180; inline U32 LLVOWLSky::getNumStacks(void) { - return gSavedSettings.getU32("WLSkyDetail"); + return llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail"))); } inline U32 LLVOWLSky::getNumSlices(void) { - return 2 * gSavedSettings.getU32("WLSkyDetail"); + return 2 * llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail"))); } inline U32 LLVOWLSky::getFanNumVerts(void) @@ -489,7 +489,7 @@ void LLVOWLSky::drawStars(void) if (mStarsVerts.notNull()) { mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK); - mStarsVerts->draw(LLRender::POINTS, getStarsNumIndices(), 0); + mStarsVerts->drawArrays(LLRender::QUADS, 0, getStarsNumVerts()*4); } } @@ -769,17 +769,17 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) { LLStrider verticesp; LLStrider colorsp; - LLStrider indicesp; + LLStrider texcoordsp; if (mStarsVerts.isNull()) { mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW); - mStarsVerts->allocateBuffer(getStarsNumVerts(), getStarsNumIndices(), TRUE); + mStarsVerts->allocateBuffer(getStarsNumVerts()*4, 0, TRUE); } BOOL success = mStarsVerts->getVertexStrider(verticesp) - && mStarsVerts->getIndexStrider(indicesp) - && mStarsVerts->getColorStrider(colorsp); + && mStarsVerts->getColorStrider(colorsp) + && mStarsVerts->getTexCoord0Strider(texcoordsp); if(!success) { @@ -789,11 +789,37 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) // *TODO: fix LLStrider with a real prefix increment operator so it can be // used as a model of OutputIterator. -Brad // std::copy(mStarVertices.begin(), mStarVertices.end(), verticesp); + + if (mStarVertices.size() < getStarsNumVerts()) + { + llerrs << "Star reference geometry insufficient." << llendl; + } + for (U32 vtx = 0; vtx < getStarsNumVerts(); ++vtx) { + LLVector3 at = mStarVertices[vtx]; + at.normVec(); + LLVector3 left = at%LLVector3(0,0,1); + LLVector3 up = at%left; + + F32 sc = 0.5f+ll_frand()*1.25f; + left *= sc; + up *= sc; + *(verticesp++) = mStarVertices[vtx]; + *(verticesp++) = mStarVertices[vtx]+left; + *(verticesp++) = mStarVertices[vtx]+left+up; + *(verticesp++) = mStarVertices[vtx]+up; + + *(texcoordsp++) = LLVector2(0,0); + *(texcoordsp++) = LLVector2(0,1); + *(texcoordsp++) = LLVector2(1,1); + *(texcoordsp++) = LLVector2(1,0); + + *(colorsp++) = LLColor4U(mStarColors[vtx]); + *(colorsp++) = LLColor4U(mStarColors[vtx]); + *(colorsp++) = LLColor4U(mStarColors[vtx]); *(colorsp++) = LLColor4U(mStarColors[vtx]); - *(indicesp++) = vtx; } mStarsVerts->setBuffer(0); diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 50e407739..848c8137f 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -301,7 +301,7 @@ void LLWaterParamManager::update(LLViewerCamera * cam) mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); LLVector3 sunMoonDir; - if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) { sunMoonDir = gSky.getSunDirection(); } diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index c4d146664..dfe921667 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -315,7 +315,7 @@ void LLWLParamManager::propagateParameters(void) { mLightDir = sunDir; } - else if(sunDir.mV[1] < 0 && sunDir.mV[1] > NIGHTTIME_ELEVATION_COS) + else if(sunDir.mV[1] < 0 && sunDir.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS) { // clamp v1 to 0 so sun never points up and causes weirdness on some machines LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ad6a702dd..21ab8e598 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -259,7 +259,10 @@ BOOL LLPipeline::sRenderFrameTest = FALSE; BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; BOOL LLPipeline::sRenderDeferred = FALSE; +BOOL LLPipeline::sAllowRebuildPriorityGroup = FALSE ; S32 LLPipeline::sVisibleLightCount = 0; +F32 LLPipeline::sMinRenderSize = 0.f; + static LLCullResult* sCull = NULL; @@ -300,7 +303,6 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), - mRenderTypeMask(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), @@ -350,7 +352,11 @@ void LLPipeline::init() mTrianglesDrawnStat.reset(); resetFrameStats(); - mRenderTypeMask = 0xffffffff; // All render types start on + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + } + mRenderDebugFeatureMask = 0xffffffff; // All debugging features on mRenderDebugMask = 0; // All debug starts off @@ -383,6 +389,9 @@ void LLPipeline::cleanup() { assertInitialized(); + mGroupQ1.clear() ; + mGroupQ2.clear() ; + for(pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ) { @@ -963,6 +972,10 @@ void LLPipeline::addPool(LLDrawPool *new_poolp) void LLPipeline::allocDrawable(LLViewerObject *vobj) { + if(!vobj) + { + llerrs << "Null object passed to allocDrawable!" << llendl; + } LLMemType mt(LLMemType::MTYPE_DRAWABLE); LLDrawable *drawable = new LLDrawable(); vobj->mDrawable = drawable; @@ -1237,28 +1250,8 @@ void LLPipeline::updateMove() } } mRetexturedList.clear(); - - updateMovedList(mMovedList); - - for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin(); - iter != mActiveQ.end(); ) { - LLDrawable::drawable_set_t::iterator curiter = iter++; - LLDrawable* drawablep = *curiter; - if (drawablep && !drawablep->isDead()) - { - if (drawablep->isRoot() && - drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && - (!drawablep->getParent() || !drawablep->getParent()->isActive())) - { - drawablep->makeStatic(); // removes drawable and its children from mActiveQ - iter = mActiveQ.upper_bound(drawablep); // next valid entry - } - } - else - { - mActiveQ.erase(curiter); - } + updateMovedList(mMovedList); } //balance octrees @@ -1342,6 +1335,8 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& min = LLVector3(F32_MAX, F32_MAX, F32_MAX); max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX); + U32 saved_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; BOOL res = TRUE; @@ -1366,6 +1361,8 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& } } + LLViewerCamera::sCurCameraID = saved_camera_id; + return res; } @@ -1381,8 +1378,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl BOOL to_texture = LLPipeline::sUseOcclusion > 1 && !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && - !sReflectionRender && - !sShadowRender && + LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && gPipeline.canUseVertexShaders() && sRenderGlow; @@ -1391,9 +1387,12 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl mScreen.bindTarget(); } + /*glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixd(gGLLastProjection); + glMatrixMode(GL_MODELVIEW);*/ glPushMatrix(); gGLLastMatrix = NULL; - //glLoadMatrixd(gGLModelView); glLoadMatrixd(gGLLastModelView); LLVertexBuffer::unbind(); @@ -1459,6 +1458,9 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } + /*glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW);*/ glPopMatrix(); if (sUseOcclusion > 1) @@ -1470,10 +1472,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { mScreen.flush(); } - else if (LLPipeline::sUseOcclusion > 1) + /*else if (LLPipeline::sUseOcclusion > 1) { glFlush(); - } + }*/ } void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) @@ -1485,7 +1487,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) group->setVisible(); - if (!sSkipUpdate) + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { group->updateDistance(camera); } @@ -1497,6 +1499,12 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } + if (sMinRenderSize > 0.f && + llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize) + { + return; + } + assertInitialized(); if (!group->mSpatialPartition->mRenderByGroup) @@ -1513,22 +1521,22 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) void LLPipeline::markOccluder(LLSpatialGroup* group) { - if (sUseOcclusion > 1 && group && !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) + if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION)) { LLSpatialGroup* parent = group->getParent(); - if (!parent || !parent->isState(LLSpatialGroup::OCCLUDED)) + if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) { //only mark top most occluders as active occlusion sCull->pushOcclusionGroup(group); - group->setState(LLSpatialGroup::ACTIVE_OCCLUSION); + group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); if (parent && - !parent->isState(LLSpatialGroup::ACTIVE_OCCLUSION) && + !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) && parent->getElementCount() == 0 && parent->needsUpdate()) { sCull->pushOcclusionGroup(group); - parent->setState(LLSpatialGroup::ACTIVE_OCCLUSION); + parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } } } @@ -1558,7 +1566,7 @@ void LLPipeline::doOcclusion(LLCamera& camera) { LLSpatialGroup* group = *iter; group->doOcclusion(&camera); - group->clearState(LLSpatialGroup::ACTIVE_OCCLUSION); + group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } } @@ -1576,6 +1584,84 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +void LLPipeline::updateGL() +{ + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } +} + +void LLPipeline::rebuildPriorityGroups() +{ + if(!sAllowRebuildPriorityGroup) + { + return ; + } + sAllowRebuildPriorityGroup = FALSE ; + + LLTimer update_timer; + LLMemType mt(LLMemType::MTYPE_PIPELINE); + + assertInitialized(); + + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + group->rebuildGeom(); + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } + + mGroupQ1.clear(); +} + +void LLPipeline::rebuildGroups() +{ + // Iterate through some drawables on the non-priority build queue + S32 size = (S32) mGroupQ2.size(); + S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size); + + S32 count = 0; + + std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency()); + + LLSpatialGroup::sg_vector_t::iterator iter; + for (iter = mGroupQ2.begin(); + iter != mGroupQ2.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + if (group->isDead()) + { + continue; + } + + group->rebuildGeom(); + + if (group->mSpatialPartition->mRenderByGroup) + { + count++; + } + + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + + if (count > min_count) + { + ++iter; + break; + } + } + + mGroupQ2.erase(mGroupQ2.begin(), iter); + + updateMovedList(mMovedBridge); +} + void LLPipeline::updateGeom(F32 max_dtime) { LLTimer update_timer; @@ -1839,6 +1925,59 @@ void LLPipeline::markTextured(LLDrawable *drawablep) } } +void LLPipeline::markGLRebuild(LLGLUpdate* glu) +{ + if (glu && !glu->mInQ) + { + LLGLUpdate::sGLQ.push_back(glu); + glu->mInQ = TRUE; + } +} + +void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + //assert_main_thread(); + + if (group && !group->isDead() && group->mSpatialPartition) + { + if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD) + { + priority = TRUE; + } + + if (priority) + { + if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) + { + mGroupQ1.push_back(group); + group->setState(LLSpatialGroup::IN_BUILD_Q1); + + if (group->isState(LLSpatialGroup::IN_BUILD_Q2)) + { + LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); + if (iter != mGroupQ2.end()) + { + mGroupQ2.erase(iter); + } + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + } + } + } + else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) + { + //llerrs << "Non-priority updates not yet supported!" << llendl; + if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end()) + { + llerrs << "WTF?" << llendl; + } + mGroupQ2.push_back(group); + group->setState(LLSpatialGroup::IN_BUILD_Q2); + + } + } +} + void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority) { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -1872,15 +2011,14 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { - const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_GROUND) | - (1 << LLPipeline::RENDER_TYPE_TERRAIN) | - (1 << LLPipeline::RENDER_TYPE_TREE) | - (1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_VOIDWATER) | - (1 << LLPipeline::RENDER_TYPE_WATER); - - if (mRenderTypeMask & face_mask) + if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools LLFastTimer t(LLFastTimer::FTM_RESET_DRAWORDER); @@ -1893,55 +2031,51 @@ 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_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + LLSpatialGroup* group = *iter; + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { - LLSpatialGroup* group = *iter; - group->checkOcclusion(); - if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) - { - markOccluder(group); - } - else - { - group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) - { - markVisible(*i, camera); - } - } + markOccluder(group); } - - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + else { - LLSpatialGroup* group = *iter; - group->checkOcclusion(); - if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) + group->setVisible(); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { - markOccluder(group); - } - else - { - group->setVisible(); - stateSort(group, camera); + markVisible(*i, camera); } } } - + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + markOccluder(group); + } + else + { + group->setVisible(); + stateSort(group, camera); + } + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLCullResult::bridge_list_t::iterator cur_iter = i; LLSpatialBridge* bridge = *cur_iter; LLSpatialGroup* group = bridge->getSpatialGroup(); - if (!bridge->isDead() && group && !group->isState(LLSpatialGroup::OCCLUDED)) + if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { stateSort(bridge, camera); } } } - { LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); @@ -1980,7 +2114,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) + if (!sShadowRender && !sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) { bool force_update = false; bridge->updateDistance(camera, force_update); @@ -2042,21 +2176,24 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - LLSpatialGroup* group = drawablep->getSpatialGroup(); - if (!group || group->changeLOD()) + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { - if (drawablep->isVisible() && !sSkipUpdate) + LLSpatialGroup* group = drawablep->getSpatialGroup(); + if (!group || group->changeLOD()) { - if (!drawablep->isActive()) + if (drawablep->isVisible() && !sSkipUpdate) { - bool force_update = false; - drawablep->updateDistance(camera, force_update); + if (!drawablep->isActive()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); + } + else if (drawablep->isAvatar()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() + } } - else if (drawablep->isAvatar()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() - } } } @@ -2080,6 +2217,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } } + mNumVisibleFaces += drawablep->getNumFaces(); } @@ -2236,7 +2374,7 @@ void LLPipeline::postSort(LLCamera& camera) { LLSpatialGroup* group = *i; if (!sUseOcclusion || - !group->isState(LLSpatialGroup::OCCLUDED)) + !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { group->rebuildGeom(); } @@ -2245,7 +2383,7 @@ void LLPipeline::postSort(LLCamera& camera) //rebuild groups sCull->assertDrawMapsEmpty(); - LLSpatialGroup::sNoDelete = FALSE; + /*LLSpatialGroup::sNoDelete = FALSE; for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; @@ -2257,9 +2395,12 @@ void LLPipeline::postSort(LLCamera& camera) group->rebuildGeom(); } - LLSpatialGroup::sNoDelete = TRUE; - + LLSpatialGroup::sNoDelete = TRUE;*/ + rebuildPriorityGroups(); + + + const S32 bin_count = 1024*8; static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; @@ -2280,50 +2421,67 @@ void LLPipeline::postSort(LLCamera& camera) { LLSpatialGroup* group = *i; if (sUseOcclusion && - group->isState(LLSpatialGroup::OCCLUDED)) + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { continue; } - + + if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY)) + { //no way this group is going to be drawable without a rebuild + group->rebuildGeom(); + } + for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) { LLSpatialGroup::drawmap_elem_t& src_vec = j->second; - /*if (!hasRenderType(j->first)) //No worky yet. + if (!hasRenderType(j->first)) { continue; - }*/ + } for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) { - sCull->pushDrawInfo(j->first, *k); - } - } - - - LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); - - if (alpha != group->mDrawMap.end()) - { //store alpha groups for sorting - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); - if (!sSkipUpdate) - { - if (bridge) + if (sMinRenderSize > 0.f) { - LLCamera trans_camera = bridge->transformCamera(camera); - group->updateDistance(trans_camera); + LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0]; + if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize) + { + sCull->pushDrawInfo(j->first, *k); + } } else { - group->updateDistance(camera); + sCull->pushDrawInfo(j->first, *k); } } + } + + if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA)) + { + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); - if (hasRenderType(LLDrawPool::POOL_ALPHA)) - { - sCull->pushAlphaGroup(group); + if (alpha != group->mDrawMap.end()) + { //store alpha groups for sorting + LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + if (bridge) + { + LLCamera trans_camera = bridge->transformCamera(camera); + group->updateDistance(trans_camera); + } + else + { + group->updateDistance(camera); + } + } + + if (hasRenderType(LLDrawPool::POOL_ALPHA)) + { + sCull->pushAlphaGroup(group); + } } } - } if (!sShadowRender) @@ -2421,7 +2579,7 @@ void LLPipeline::postSort(LLCamera& camera) } } - LLSpatialGroup::sNoDelete = FALSE; + //LLSpatialGroup::sNoDelete = FALSE; } @@ -3032,6 +3190,8 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); doOcclusion(camera); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); } } @@ -3823,7 +3983,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) } } F32 backlight_mag; - if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) { backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; } @@ -4012,7 +4172,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) // Light 0 = Sun or Moon (All objects) { - if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) + if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS) { mSunDir.setVec(gSky.getSunDirection()); mSunDiffuse.setVec(gSky.getSunDiffuseColor()); @@ -4278,10 +4438,10 @@ void LLPipeline::enableLightsFullbright(const LLColor4& color) enableLights(mask); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV); - if (mLightingDetail >= 2) + /*if (mLightingDetail >= 2) { glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default - } + }*/ } void LLPipeline::disableLights() @@ -4318,10 +4478,6 @@ void LLPipeline::findReferences(LLDrawable *drawablep) llinfos << "In mRetexturedList" << llendl; } - if (mActiveQ.find(drawablep) != mActiveQ.end()) - { - llinfos << "In mActiveQ" << llendl; - } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { llinfos << "In mBuildQ1" << llendl; @@ -4478,28 +4634,13 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light) } } -void LLPipeline::setActive(LLDrawable *drawablep, BOOL active) -{ - assertInitialized(); - if (active) - { - mActiveQ.insert(drawablep); - } - else - { - mActiveQ.erase(drawablep); - } -} - //static void LLPipeline::toggleRenderType(U32 type) { - U32 bit = (1<getNear()*2.f); shader.uniform1f("alpha_soften", render_deferred_alpha_soft); + if (shader.getUniformLocation("norm_mat") >= 0) + { + glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose(); + shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m); + } } void LLPipeline::renderDeferredLighting() @@ -5528,6 +5700,7 @@ void LLPipeline::renderDeferredLighting() return; } + LLViewerCamera* camera = LLViewerCamera::getInstance(); LLGLEnable multisample(GL_MULTISAMPLE_ARB); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -5542,15 +5715,13 @@ void LLPipeline::renderDeferredLighting() gGL.setColorMask(true, true); - mDeferredLight[0].bindTarget(); - //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); //draw a cube around every light LLVertexBuffer::unbind(); - glBlendFunc(GL_ONE, GL_ONE); + //glBlendFunc(GL_ONE, GL_ONE); LLGLEnable cull(GL_CULL_FACE); LLGLEnable blend(GL_BLEND); @@ -5562,126 +5733,130 @@ void LLPipeline::renderDeferredLighting() -1,-3, 3,1, }; + glVertexPointer(2, GL_FLOAT, 0, vert); + glColor3f(1,1,1); - bindDeferredShader(gDeferredSunProgram); - - glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); - - const U32 slice = 32; - F32 offset[slice*3]; - for (U32 i = 0; i < 4; i++) { - for (U32 j = 0; j < 8; j++) - { - glh::vec3f v; - v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); - v.normalize(); - inv_trans.mult_matrix_vec(v); - v.normalize(); - offset[(i*8+j)*3+0] = v.v[0]; - offset[(i*8+j)*3+1] = v.v[2]; - offset[(i*8+j)*3+2] = v.v[1]; - } + setupHWLights(NULL); //to set mSunDir; + LLVector4 dir(mSunDir, 0.f); + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); } - gDeferredSunProgram.uniform3fv("offset", slice, offset); - gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); - - setupHWLights(NULL); //to set mSunDir; - glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - LLVector4 dir(mSunDir, 0.f); - - glh::vec4f tc(dir.mV); - mat.mult_matrix_vec(tc); - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); - glColor3f(1,1,1); - - glVertexPointer(2, GL_FLOAT, 0, vert); - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - unbindDeferredShader(gDeferredSunProgram); - - mDeferredLight[0].flush(); - - //blur lightmap - mDeferredLight[1].bindTarget(); - - //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - - bindDeferredShader(gDeferredBlurLightProgram); - - LLVector3 gauss[32]; // xweight, yweight, offset - - LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); - U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; - F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); - - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = -(kern_length/2.0f) + 0.5f; - - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go.mV[0]); - gauss[i].mV[1] = llgaussian(x, go.mV[1]); - gauss[i].mV[2] = x; - x += 1.f; - } - /* swap the x=0 position to the start of gauss[] so we can - treat it specially as an optimization. */ - LLVector3 swap; - swap = gauss[kern_length/2]; - gauss[kern_length/2] = gauss[0]; - gauss[0] = swap; - llassert(gauss[0].mV[2] == 0.0f); - - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - mDeferredLight[1].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); - - bindDeferredShader(gDeferredBlurLightProgram, 1); mDeferredLight[0].bindTarget(); - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - + //Sun shadows. { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - stop_glerror(); + bindDeferredShader(gDeferredSunProgram); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv("offset", slice, offset); + gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); } + mDeferredLight[0].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + + //SSAO + { + //blur lightmap + mDeferredLight[1].bindTarget(); + + //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + bindDeferredShader(gDeferredBlurLightProgram); + + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = -(kern_length/2.0f) + 0.5f; + + LLVector3 gauss[32]; // xweight, yweight, offset + + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go.mV[0]); + gauss[i].mV[1] = llgaussian(x, go.mV[1]); + gauss[i].mV[2] = x; + x += 1.f; + } + /* swap the x=0 position to the start of gauss[] so we can + treat it specially as an optimization. */ + LLVector3 swap; + swap = gauss[kern_length/2]; + gauss[kern_length/2] = gauss[0]; + gauss[0] = swap; + llassert(gauss[0].mV[2] == 0.0f); + + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); + + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + stop_glerror(); + } + mDeferredLight[0].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + } stop_glerror(); glPopMatrix(); @@ -5696,6 +5871,8 @@ void LLPipeline::renderDeferredLighting() // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); mScreen.bindTarget(); + // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); mScreen.clear(GL_COLOR_BUFFER_BIT); bindDeferredShader(gDeferredSoftenProgram); @@ -5722,7 +5899,23 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredSoftenProgram); - bindDeferredShader(gDeferredLightProgram); + + { //render sky + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gPipeline.pushRenderTypeMask(); + + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_WL_CLOUDS, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); + + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + gPipeline.popRenderTypeMask(); + } std::list fullscreen_lights; std::list light_colors; @@ -5730,6 +5923,7 @@ void LLPipeline::renderDeferredLighting() F32 v[24]; glVertexPointer(3, GL_FLOAT, 0, v); { + bindDeferredShader(gDeferredLightProgram); LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { @@ -5741,22 +5935,42 @@ void LLPipeline::renderDeferredLighting() continue; } + if (volume->isAttachment()) + { + if (!sRenderAttachedLights) + { + continue; + } + } + + LLVector3 center = drawablep->getPositionAgent(); F32* c = center.mV; F32 s = volume->getLightRadius()*1.5f; - if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + if (col.magVecSquared() < 0.001f) + { + continue; + } + + if (s <= 0.001f) + { + continue; + } + + if (camera->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) { continue; } sVisibleLightCount++; + glh::vec3f tc(c); mat.mult_matrix_vec(tc); - - LLColor3 col = volume->getLightColor(); - col *= volume->getLightIntensity(); - + //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 @@ -5771,17 +5985,17 @@ void LLPipeline::renderDeferredLighting() v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 - if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) + 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 || + camera->getOrigin().mV[1] < c[1] - s - 0.2f || + camera->getOrigin().mV[2] > c[2] + s + 0.2f || + camera->getOrigin().mV[2] < c[2] - s - 0.2f) { //draw box if camera is outside box glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center)); } else { @@ -5789,9 +6003,10 @@ void LLPipeline::renderDeferredLighting() light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } + unbindDeferredShader(gDeferredLightProgram); } - unbindDeferredShader(gDeferredLightProgram); + if (!fullscreen_lights.empty()) { @@ -5807,8 +6022,9 @@ void LLPipeline::renderDeferredLighting() U32 count = 0; - LLVector4 light[16]; - LLVector4 col[16]; + const U32 max_count = 16; + LLVector4 light[max_count]; + LLVector4 col[max_count]; glVertexPointer(2, GL_FLOAT, 0, vert); @@ -5818,9 +6034,9 @@ void LLPipeline::renderDeferredLighting() fullscreen_lights.pop_front(); col[count] = light_colors.front(); light_colors.pop_front(); - count++; - if (count == 16 || fullscreen_lights.empty()) + + if (count == max_count || fullscreen_lights.empty()) { gDeferredMultiLightProgram.uniform1i("light_count", count); gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); @@ -5828,40 +6044,45 @@ void LLPipeline::renderDeferredLighting() gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); count = 0; - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } } - glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); unbindDeferredShader(gDeferredMultiLightProgram); } - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); { //render non-deferred geometry LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); - U32 render_mask = mRenderTypeMask; - mRenderTypeMask = mRenderTypeMask & - ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY) | - (1 << LLPipeline::RENDER_TYPE_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_VOIDWATER) | - (1 << LLPipeline::RENDER_TYPE_WATER) | - (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_VOLUME) | - (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_BUMP)); + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_GLOW, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_ALPHA, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_GLOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISIBLE, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_AVATAR, + END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); - mRenderTypeMask = render_mask; + popRenderTypeMask(); } mScreen.flush(); @@ -5931,9 +6152,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) camera.setFar(camera.getFar()*0.87654321f); LLPipeline::sReflectionRender = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLPipeline::sUseOcclusion = llmin(occlusion, 1); - U32 type_mask = gPipeline.mRenderTypeMask; + gPipeline.pushRenderTypeMask(); glh::matrix4f projection = glh_get_current_projection(); glh::matrix4f mat; @@ -5965,22 +6189,19 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) water_clip = 1; } - - if (!LLViewerCamera::getInstance()->cameraUnderWater()) { //generate planar reflection map gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glClearColor(0,0,0,0); - gGL.setColorMask(true, true); mWaterRef.bindTarget(); - mWaterRef.getViewport(gGLViewport); + gGL.setColorMask(true, true); mWaterRef.clear(); gGL.setColorMask(true, false); + mWaterRef.getViewport(gGLViewport); + stop_glerror(); - LLVector3 origin = camera.getOrigin(); - glPushMatrix(); mat.set_scale(glh::vec3f(1,1,-1)); @@ -5995,60 +6216,80 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE); + glh::matrix4f inv_mat = mat.inverse(); + + glh::vec3f origin(0,0,0); + inv_mat.mult_matrix_vec(origin); + + camera.setOrigin(origin.v); + glCullFace(GL_FRONT); - //initial sky pass (no user clip plane) - { //mask out everything but the sky - U32 tmp = mRenderTypeMask; - mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY)); - static LLCullResult result; - updateCull(camera, result); - stateSort(camera, result); - mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY)); - renderGeom(camera, TRUE); - mRenderTypeMask = tmp; - } - + static LLCullResult ref_result; + if (LLDrawPoolWater::sNeedsDistortionUpdate) { - mRenderTypeMask &= ~((1< 0) + { //mask out selected geometry based on reflection detail { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_AVATAR); - if (detail < 1) + if (detail < 4) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_VOLUME); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); + if (detail < 3) + { + clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); + if (detail < 2) + { + clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES); + } + } } + static LLCachedControl skip_distortion_updates("SkipReflectOcclusionUpdates",false); + LLPipeline::sSkipUpdate = skip_distortion_updates; + LLGLUserClipPlane clip_plane(plane, mat, projection); + LLGLDisable cull(GL_CULL_FACE); + updateCull(camera, ref_result, 1); + stateSort(camera, ref_result); } - } - - LLSpatialPartition::sFreezeState = TRUE; - LLPipeline::sSkipUpdate = TRUE; - LLGLUserClipPlane clip_plane(plane, mat, projection); - static LLCullResult result; - updateCull(camera, result, 1); - stateSort(camera, result); - renderGeom(camera); - LLSpatialPartition::sFreezeState = FALSE; - LLPipeline::sSkipUpdate = FALSE; + gPipeline.grabReferences(ref_result); + LLGLUserClipPlane clip_plane(plane, mat, projection); + renderGeom(camera); + LLPipeline::sSkipUpdate = FALSE; + } } + gPipeline.popRenderTypeMask(); } glCullFace(GL_BACK); glPopMatrix(); @@ -6057,37 +6298,37 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) glh_set_current_modelview(current); } + camera.setOrigin(camera_in.getOrigin()); //render distortion map static BOOL last_update = TRUE; if (last_update) { camera.setFar(camera_in.getFar()); - mRenderTypeMask = type_mask & ~((1<cameraUnderWater() ? FALSE : TRUE; if (LLPipeline::sUnderWaterRender) { - mRenderTypeMask &= ~((1<unbind(LLTexUnit::TT_TEXTURE); LLColor4& col = LLDrawPoolWater::sWaterFogColor; glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); - gGL.setColorMask(true, true); mWaterDis.bindTarget(); mWaterDis.getViewport(gGLViewport); - mWaterDis.clear(); - gGL.setColorMask(true, false); - + if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate) { //clip out geometry on the same side of water as the camera @@ -6096,6 +6337,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) static LLCullResult result; updateCull(camera, result, water_clip); stateSort(camera, result); + + gGL.setColorMask(true, true); + mWaterDis.clear(); + gGL.setColorMask(true, false); + renderGeom(camera); } @@ -6115,7 +6361,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) glClearColor(0.f, 0.f, 0.f, 0.f); gViewerWindow->setupViewport(); - mRenderTypeMask = type_mask; + gPipeline.popRenderTypeMask(); LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd)); @@ -6201,7 +6447,6 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) void LLPipeline::generateSunShadow(LLCamera& camera) { - if (!sRenderDeferred) { return; @@ -6225,6 +6470,25 @@ void LLPipeline::generateSunShadow(LLCamera& camera) return; } clear = TRUE; + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, + LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_GRASS, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + END_RENDER_TYPES); gGL.setColorMask(false, false); @@ -6303,6 +6567,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) at = -at; } + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j; LLVector3 left = lightDir%at; up = left%lightDir; up.normVec(); @@ -6419,17 +6685,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; - U32 type_mask = mRenderTypeMask; - mRenderTypeMask = type_mask & ((1<isDead() && - (!sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && + (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && group->mDrawMap.find(type) != group->mDrawMap.end()) { @@ -6574,35 +6831,44 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) assertInitialized(); - U32 mask; BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID()); + pushRenderTypeMask(); + if (muted) { - mask = 1 << LLPipeline::RENDER_TYPE_AVATAR; + andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); } else { - mask = (1<mDrawable, *LLViewerCamera::getInstance()); + LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); + markVisible(avatar->mDrawable, *viewer_camera); LLVOAvatar::sUseImpostors = FALSE; LLVOAvatar::attachment_map_t::iterator iter; @@ -6617,7 +6883,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) { if (LLViewerObject* attached_object = (*attachment_iter)) { - markVisible(attached_object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance()); + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); } } } @@ -6627,9 +6893,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) const LLVector3* ext = avatar->mDrawable->getSpatialExtents(); LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLCamera camera = *LLViewerCamera::getInstance(); + LLCamera camera = *viewer_camera; - camera.lookAt(LLViewerCamera::getInstance()->getOrigin(), pos, LLViewerCamera::getInstance()->getUpAxis()); + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); LLVector2 tdim; @@ -6695,6 +6961,10 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilMask(0xFFFFFFFF); + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, resX, resY); @@ -6702,15 +6972,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->mImpostor.clear(); } - LLGLEnable stencil(GL_STENCIL_TEST); - - glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - if (LLPipeline::sRenderDeferred) { stop_glerror(); renderGeomDeferred(camera); + renderGeomPostDeferred(camera); } else { @@ -6720,11 +6986,18 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFFFFFF); - if (!sRenderDeferred || muted) + //if (!sRenderDeferred || muted) { LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f; LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f; + //Safe?? + if (LLPipeline::sRenderDeferred) + { + GLuint buff = GL_COLOR_ATTACHMENT0_EXT; + glDrawBuffersARB(1, &buff); + } + LLGLEnable blend(muted ? 0 : GL_BLEND); if (muted) @@ -6763,7 +7036,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sUseOcclusion = occlusion; sReflectionRender = FALSE; sImpostorRender = FALSE; - gPipeline.mRenderTypeMask = saved_mask; + sShadowRender = FALSE; + popRenderTypeMask(); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -6804,3 +7078,123 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() return sCull->endAlphaGroups(); } +BOOL LLPipeline::hasRenderType(const U32 type) const +{ + // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render" + // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance) + // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely + return (type == 0 ? FALSE : mRenderTypeEnabled[type]); +} + +void LLPipeline::setRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = TRUE; + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + +BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + return TRUE; + } + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + return FALSE; +} + +void LLPipeline::pushRenderTypeMask() +{ + std::string cur_mask; + cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.push(cur_mask); +} + +void LLPipeline::popRenderTypeMask() +{ + if (mRenderTypeEnableStack.empty()) + { + llerrs << "Depleted render type stack." << llendl; + } + + memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.pop(); +} + +void LLPipeline::andRenderTypeMask(U32 type, ...) +{ + va_list args; + + BOOL tmp[NUM_RENDER_TYPES]; + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + tmp[i] = FALSE; + } + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + tmp[type] = TRUE; + } + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = tmp[i]; + } + +} + +void LLPipeline::clearRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = FALSE; + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e60c6f861..36f4c33ec 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -46,6 +46,8 @@ #include "lldrawable.h" #include "llrendertarget.h" +#include + class LLViewerImage; class LLEdge; class LLFace; @@ -94,6 +96,7 @@ public: void resetVertexBuffers(LLDrawable* drawable); void setUseVBO(BOOL use_vbo); + void setDisableVBOMapping(BOOL no_vbo_mapping); void generateImpostor(LLVOAvatar* avatar); void bindScreenToTexture(); void renderBloom(BOOL for_snapshot, F32 zoom_factor = 1.f, int subfield = 0); @@ -129,6 +132,8 @@ public: void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE); void markShift(LLDrawable *drawablep); void markTextured(LLDrawable *drawablep); + void markGLRebuild(LLGLUpdate* glu); + void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); //get the object between start and end that's closest to start. @@ -179,10 +184,14 @@ public: void updateMove(); BOOL visibleObjectsInFrustum(LLCamera& camera); BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); + BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); + void updateGL(); + void rebuildPriorityGroups(); + void rebuildGroups(); //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); @@ -234,8 +243,7 @@ public: void shiftObjects(const LLVector3 &offset); void setLight(LLDrawable *drawablep, BOOL is_light); - void setActive(LLDrawable *drawablep, BOOL active); - + BOOL hasRenderBatches(const U32 type) const; LLCullResult::drawinfo_list_t::iterator beginRenderMap(U32 type); LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); @@ -243,11 +251,20 @@ public: LLCullResult::sg_list_t::iterator endAlphaGroups(); void addTrianglesDrawn(S32 count); - BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< mRenderTypeEnableStack; + U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; @@ -508,10 +543,10 @@ protected: // LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority + LLSpatialGroup::sg_vector_t mGroupQ1; //priority + LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority LLViewerObject::vobj_list_t mCreateQ; - LLDrawable::drawable_set_t mActiveQ; - LLDrawable::drawable_set_t mRetexturedList; //////////////////////////////////////////////////