From 996aaf63452c9fd9ce85d0135b60ff8b375774d9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 6 Mar 2011 05:47:26 -0600 Subject: [PATCH 01/14] V2 spatial partition, and all the pipeline changes that go with it. Note: Deferred mode is not finished, and thus broken. Don't use! --- indra/llcommon/llmemory.h | 11 +- indra/llrender/llgl.cpp | 2 + indra/llrender/llgl.h | 31 + indra/llrender/llimagegl.cpp | 15 + indra/llrender/llimagegl.h | 2 + indra/newview/llappviewer.cpp | 76 +- indra/newview/lldrawable.cpp | 50 +- indra/newview/lldrawable.h | 1 + indra/newview/lldrawpool.cpp | 3 +- indra/newview/lldrawpoolalpha.cpp | 96 ++- indra/newview/lldrawpoolalpha.h | 6 + indra/newview/lldrawpoolavatar.cpp | 20 +- indra/newview/lldrawpoolavatar.h | 4 +- indra/newview/lldrawpoolsky.cpp | 7 +- indra/newview/lldrawpoolterrain.cpp | 6 +- indra/newview/lldrawpooltree.cpp | 1 - indra/newview/lldrawpoolwlsky.cpp | 27 +- indra/newview/lldrawpoolwlsky.h | 2 +- indra/newview/llface.cpp | 76 +- indra/newview/llface.h | 9 +- indra/newview/llfloaterhardwaresettings.cpp | 3 +- indra/newview/llglsandbox.cpp | 16 +- indra/newview/llhudeffectlookat.cpp | 2 + indra/newview/llselectmgr.cpp | 73 +- indra/newview/llspatialpartition.cpp | 670 ++++++++++++---- indra/newview/llspatialpartition.h | 101 ++- indra/newview/llsurface.cpp | 5 + indra/newview/llsurfacepatch.cpp | 35 +- indra/newview/llsurfacepatch.h | 1 + indra/newview/lltexturefetch.cpp | 14 +- indra/newview/llviewercamera.cpp | 2 + indra/newview/llviewercamera.h | 18 + indra/newview/llviewerdisplay.cpp | 31 +- indra/newview/llviewerjointattachment.cpp | 16 +- indra/newview/llviewermenu.cpp | 4 +- indra/newview/llviewerobject.cpp | 39 +- indra/newview/llviewerobject.h | 14 +- indra/newview/llviewerobjectlist.cpp | 5 +- indra/newview/llviewerparceloverlay.cpp | 10 +- indra/newview/llviewerparceloverlay.h | 4 +- indra/newview/llviewerpartsim.cpp | 1 + indra/newview/llviewerwindow.cpp | 13 +- indra/newview/llvoavatar.cpp | 56 +- indra/newview/llvoavatar.h | 14 +- indra/newview/llvoclouds.cpp | 5 +- indra/newview/llvograss.cpp | 54 +- indra/newview/llvopartgroup.cpp | 11 +- indra/newview/llvosurfacepatch.cpp | 14 +- indra/newview/llvosurfacepatch.h | 1 + indra/newview/llvotree.cpp | 9 +- indra/newview/llvotree.h | 1 + indra/newview/llvovolume.cpp | 59 +- indra/newview/llvovolume.h | 1 + indra/newview/llvowater.cpp | 10 +- indra/newview/llvowater.h | 2 +- indra/newview/pipeline.cpp | 826 ++++++++++++++------ indra/newview/pipeline.h | 62 +- 57 files changed, 1987 insertions(+), 660 deletions(-) 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/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/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 34fbbdbd0..b9d320454 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -178,6 +178,7 @@ #include "llinventoryview.h" #include "llcommandlineparser.h" +#include "llprogressview.h" // [RLVa:KB] #include "rlvhandler.h" @@ -730,6 +731,7 @@ bool LLAppViewer::init() // // Initialize the window // + gGLActive = TRUE; initWindow(); // call all self-registered classes @@ -871,7 +873,8 @@ bool LLAppViewer::mainLoop() { LLFastTimer t(LLFastTimer::FTM_FRAME); pingMainloopTimeout("Main:MiscNativeWindowEvents"); - + + if (gViewerWindow) { LLFastTimer t2(LLFastTimer::FTM_MESSAGES); gViewerWindow->mWindow->processMiscNativeEvents(); @@ -879,6 +882,7 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:GatherInput"); + if (gViewerWindow) { LLFastTimer t2(LLFastTimer::FTM_MESSAGES); if (!restoreErrorTrap()) @@ -954,11 +958,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"); @@ -985,7 +990,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. @@ -1137,11 +1142,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(); @@ -1153,8 +1161,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; @@ -1243,21 +1253,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; @@ -1365,6 +1379,9 @@ bool LLAppViewer::cleanup() writeDebugInfo(); + // Stop the plugin read thread if it's running. + LLPluginProcessParent::setUseReadThread(false); + // Let threads finish LLTimer idleTimer; idleTimer.reset(); @@ -1420,7 +1437,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. @@ -2521,7 +2541,7 @@ void LLAppViewer::handleViewerCrash() gMessageSystem->stopLogging(); } - LLWorld::getInstance()->getInfo(gDebugInfo); + if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo); // Close the debug file pApp->writeDebugInfo(); @@ -2688,6 +2708,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; @@ -2727,6 +2754,11 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q void LLAppViewer::userQuit() { + if (gDisconnected || gViewerWindow->getProgressView()->getVisible()) + { + requestQuit(); + } + else LLNotifications::instance().add("ConfirmQuit"); } @@ -3307,10 +3339,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; } @@ -3637,6 +3672,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..e9127ad49 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) { } @@ -178,8 +180,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 +212,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 +301,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,22 +315,10 @@ 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++; - } - } - - if (params.mFullbright) - { - // Turn off lighting if it hasn't already been so. + // Turn off lighting if it hasn't already been so. if (light_enabled || !initialized_lighting) { initialized_lighting = TRUE; @@ -357,22 +369,61 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } else if (!use_shaders && current_shader != NULL) { - LLGLSLShader::bindNoShader(); + if (deferred_render) { gPipeline.unbindDeferredShader(*current_shader); } + LLGLSLShader::bindNoShader(); current_shader = NULL; } if (params.mGroup) - { - params.mGroup->rebuildMesh(); + { + 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 +434,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/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..d3241fdf2 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); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index c32ee428c..ec8c66509 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); } 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/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/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 64f5de223..7426e59d3 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -109,6 +109,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 @@ -218,6 +219,9 @@ LLSelectMgr::LLSelectMgr() mSelectedObjects = new LLObjectSelection(); mHoverObjects = new LLObjectSelection(); mHighlightedObjects = new LLObjectSelection(); + + mForceSelection = FALSE; + mShowSelection = FALSE; } @@ -550,7 +554,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. @@ -786,41 +790,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; } @@ -5058,6 +5074,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; @@ -5096,7 +5113,7 @@ LLSelectNode::~LLSelectNode() void LLSelectNode::selectAllTEs(BOOL b) { - mTESelectMask = b ? 0xFFFFFFFF : 0x0; + mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0; mLastTESelected = 0; } @@ -5731,8 +5748,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; } //----------------------------------------------------------------------------- @@ -6135,8 +6166,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/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 1c81d4cdb..d4e63945e 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,22 +520,26 @@ 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()) + if (/*!LLPipeline::sSkipUpdate && */group->changeLOD()) { 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,45 @@ 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); } } @@ -1306,11 +1441,11 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) // 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)) + 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 +1453,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)) @@ -1339,11 +1474,21 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { 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 +1497,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 +1518,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 +1554,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 +1655,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 +1737,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 +1805,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 +1813,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 +1879,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 +2059,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 +2083,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 +2125,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 +2357,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 +2406,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 +2465,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 +2548,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 +2826,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 +2836,9 @@ public: //render visibility wireframe if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { + group->rebuildGeom(); + group->rebuildMesh(); + gGL.flush(); glPushMatrix(); gGLLastMatrix = NULL; @@ -2619,6 +2864,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 +2984,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 +3104,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 +3290,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 +3314,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 +3338,7 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; + mRenderMapEnd[i] = mRenderMap[i].begin(); } } @@ -3000,7 +3349,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 +3359,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 +3369,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 +3379,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 +3389,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 +3399,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 +3409,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 +3423,7 @@ void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) mVisibleGroups.push_back(group); } ++mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) @@ -3087,6 +3437,7 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) mAlphaGroups.push_back(group); } ++mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) @@ -3100,6 +3451,7 @@ void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) mOcclusionGroups.push_back(group); } ++mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) @@ -3113,6 +3465,7 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) mDrawableGroups.push_back(group); } ++mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) @@ -3126,6 +3479,7 @@ void LLCullResult::pushDrawable(LLDrawable* drawable) mVisibleList.push_back(drawable); } ++mVisibleListSize; + mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) @@ -3139,6 +3493,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 +3507,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/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/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0f8efb23b..7c412906f 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 @@ -706,6 +707,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(); @@ -782,6 +785,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { gFrameStats.start(LLFrameStats::STATE_SORT); + gPipeline.sAllowRebuildPriorityGroup = TRUE ; gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); @@ -866,6 +870,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 @@ -932,6 +937,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) render_ui(); } + gPipeline.rebuildGroups(); + LLSpatialGroup::sNoDelete = FALSE; } @@ -980,9 +987,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 +1017,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 +1025,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 +1042,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 +1076,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 +1177,10 @@ void render_ui(F32 zoom_factor, int subfield) render_ui_3d(); LLGLState::checkStates(); } + else + { + render_disconnected_background(); + } render_ui_2d(); LLGLState::checkStates(); 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/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 9964eea6f..71e3ddcfd 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) { @@ -2860,6 +2862,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) return TRUE; } +void LLViewerObject::updateGL() +{ + +} + void LLViewerObject::updateFaceSize(S32 idx) { @@ -3786,6 +3793,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 @@ -5071,7 +5087,7 @@ U32 LLViewerObject::getPartitionType() const return LLViewerRegion::PARTITION_NONE; } -void LLViewerObject::dirtySpatialGroup() const +void LLViewerObject::dirtySpatialGroup(BOOL priority) const { if (mDrawable) { @@ -5079,6 +5095,7 @@ void LLViewerObject::dirtySpatialGroup() const if (group) { group->dirtyGeom(); + gPipeline.markRebuild(group, priority); } } } @@ -5266,7 +5283,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..dd37136a8 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(); @@ -1064,7 +1067,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(); 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/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0bfb7de7c..48a1e3f8a 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2065,6 +2065,9 @@ LLViewerWindow::~LLViewerWindow() { llinfos << "Destroying Window" << llendl; destroyWindow(); + + delete mDebugText; + mDebugText = NULL; } @@ -5392,11 +5395,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 dc8d1bf12..6c87dcc7d 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; @@ -2456,7 +2457,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. { @@ -4898,13 +4899,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) { @@ -6655,7 +6663,7 @@ BOOL LLVOAvatar::updateJointLODs() if (res) { sNumLODChangesThisFrame++; - dirtyMesh(); + dirtyMesh(2); return TRUE; } } @@ -6690,11 +6698,20 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) mNumInitFaces = mDrawable->getNumFaces() ; - dirtyMesh(); + dirtyMesh(2); return mDrawable; } +void LLVOAvatar::updateGL() +{ + if (mMeshTexturesDirty) + { + updateMeshTextures(); + mMeshTexturesDirty = FALSE; + } +} + //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- @@ -6836,9 +6853,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() //----------------------------------------------------------------------------- @@ -9104,7 +9124,8 @@ void LLVOAvatar::onFirstTEMessageReceived() } } - updateMeshTextures(); + mMeshTexturesDirty = TRUE; + gPipeline.markGLRebuild(this); } } @@ -9189,6 +9210,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } setCompositeUpdatesEnabled( FALSE ); + mMeshTexturesDirty = TRUE; + gPipeline.markGLRebuild(this); if (!mIsSelf) { @@ -10399,21 +10422,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 bd5d38f00..70bdd6859 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); @@ -245,7 +246,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); @@ -294,7 +295,6 @@ public: void processAvatarAppearance( LLMessageSystem* mesgsys ); void onFirstTEMessageReceived(); void updateSexDependentLayerSets( BOOL set_by_user ); - void dirtyMesh(); // Dirty the avatar mesh void hideSkirt(); @@ -668,7 +668,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 @@ -681,7 +680,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 @@ -886,6 +885,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/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/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..f33b0d6e7 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(); @@ -2752,6 +2786,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } else if (gPipeline.canUseVertexShaders() + && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) { 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/pipeline.cpp b/indra/newview/pipeline.cpp index ad6a702dd..59000e600 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(); @@ -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()) { - 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)) //No worky yet. { 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) @@ -3032,6 +3190,8 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); doOcclusion(camera); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); } } @@ -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<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 +6152,78 @@ 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); + } + } } - } - } - 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; + LLGLUserClipPlane clip_plane(plane, mat, projection); + LLGLDisable cull(GL_CULL_FACE); + updateCull(camera, ref_result, 1); + stateSort(camera, ref_result); + } + gPipeline.grabReferences(ref_result); + LLGLUserClipPlane clip_plane(plane, mat, projection); + renderGeom(camera); + } } + gPipeline.popRenderTypeMask(); } glCullFace(GL_BACK); glPopMatrix(); @@ -6057,37 +6232,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 +6271,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 +6295,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)); @@ -6225,6 +6405,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 +6502,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 +6620,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 +6766,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 +6818,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 +6828,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; @@ -6763,7 +6964,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 +7006,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..d0148d2a8 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; @@ -129,6 +131,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 +183,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 +242,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 +250,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 +542,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; ////////////////////////////////////////////////// From 4c3a73658cd66522920add8cb49e83f8493856c0 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 10 Mar 2011 22:57:48 -0600 Subject: [PATCH 02/14] Browser window less likely to display garbage when resized. (Initialized gl texture to black) Could improve even further by padding area around copied plugin texture with black. Doesn't seem too necessary tho. --- indra/newview/lldynamictexture.cpp | 4 +++- indra/newview/lldynamictexture.h | 2 +- indra/newview/llmediactrl.cpp | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 61f5a8905..960d6cdf2 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -97,7 +97,7 @@ void LLDynamicTexture::generateGLTexture() generateGLTexture(-1, 0, 0, FALSE); } -void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) +void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes, const LLColor4U *fill_color/* = NULL*/) { if (mComponents < 1 || mComponents > 4) { @@ -105,6 +105,8 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima } releaseGLTexture(); LLPointer raw_image = new LLImageRaw(mWidth, mHeight, mComponents); + if(fill_color) + raw_image->fill(*fill_color); mTexture = new LLViewerImage(mWidth, mHeight, mComponents, FALSE); if (internal_format >= 0) { diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 5a20eaef9..db24000e7 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -74,7 +74,7 @@ public: protected: void releaseGLTexture(); void generateGLTexture(); - void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE); + void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE, const LLColor4U *fill_color = NULL); protected: S32 mWidth; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 153059897..db6d29cfc 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -550,7 +550,7 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() // void LLMediaCtrl::draw() { - if ( ! mWebBrowserImage ) + if ( ! mWebBrowserImage || mWebBrowserImage->getNeedsUpdate()) return; if ( gRestoreGL == 1 ) @@ -1129,12 +1129,14 @@ bool LLWebBrowserTexture::updateBrowserTexture() mHeight = media->getTextureHeight(); mTextureCoordsOpenGL = media->getTextureCoordsOpenGL(); + const LLColor4U fill_color(0,0,0,255); // will create mWidth * mHeight sized texture, using the texture params specified by the media. LLDynamicTexture::generateGLTexture( media->getTextureFormatInternal(), media->getTextureFormatPrimary(), media->getTextureFormatType(), - media->getTextureFormatSwapBytes()); + media->getTextureFormatSwapBytes(), + &fill_color); //Initialize the texture to black. mMediaSource->mNeedsNewTexture = false; From 60f3104eb6992b1be38109da1488207debfdbade Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 8 Mar 2011 23:22:46 -0600 Subject: [PATCH 03/14] V2 walk/run animations --- indra/llcharacter/llkeyframewalkmotion.cpp | 230 ++++++++++----------- indra/llcharacter/llkeyframewalkmotion.h | 8 +- indra/newview/app_settings/settings.xml | 22 ++ indra/newview/llvoavatar.cpp | 89 +++++--- indra/newview/llvoavatar.h | 1 + 5 files changed, 193 insertions(+), 157 deletions(-) diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index 034b7720e..8230379d3 100644 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -44,16 +44,18 @@ //----------------------------------------------------------------------------- // Macros //----------------------------------------------------------------------------- -const F32 MAX_WALK_PLAYBACK_SPEED = 8.f; // max m/s for which we adjust walk cycle speed +const F32 MAX_WALK_PLAYBACK_SPEED = 8.f; // max m/s for which we adjust walk cycle speed -const F32 MIN_WALK_SPEED = 0.1f; // minimum speed at which we use velocity for down foot detection -const F32 MAX_TIME_DELTA = 2.f; //max two seconds a frame for calculating interpolation -const F32 SPEED_ADJUST_MAX = 2.5f; // maximum adjustment of walk animation playback speed -const F32 SPEED_ADJUST_MAX_SEC = 3.f; // maximum adjustment to walk animation playback speed for a second -const F32 DRIFT_COMP_MAX_TOTAL = 0.07f;//0.55f; // maximum drift compensation overall, in any direction -const F32 DRIFT_COMP_MAX_SPEED = 4.f; // speed at which drift compensation total maxes out +const F32 MIN_WALK_SPEED = 0.1f; // minimum speed at which we use velocity for down foot detection +const F32 TIME_EPSILON = 0.001f; // minumum frame time +const F32 MAX_TIME_DELTA = 2.f; // max two seconds a frame for calculating interpolation +F32 SPEED_ADJUST_MAX_SEC = 2.f; // maximum adjustment to walk animation playback speed for a second +F32 ANIM_SPEED_MAX = 1.5f; // absolute upper limit on animation speed +const F32 DRIFT_COMP_MAX_TOTAL = 0.1f; // maximum drift compensation overall, in any direction +const F32 DRIFT_COMP_MAX_SPEED = 4.f; // speed at which drift compensation total maxes out const F32 MAX_ROLL = 0.6f; -const F32 SPEED_FINAL_SCALING = 0.5f; // final scaling for walk animation +const F32 PELVIS_COMPENSATION_WIEGHT = 0.7f; // proportion of foot drift that is compensated by moving the avatar directly +const F32 SPEED_ADJUST_TIME_CONSTANT = 0.1f; // time constant for speed adjustment interpolation //----------------------------------------------------------------------------- // LLKeyframeWalkMotion() @@ -145,10 +147,8 @@ BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask) LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID &id) : LLMotion(id), mLastTime(0.f), - mAvgCorrection(0.f), - mSpeedAdjust(0.f), mAnimSpeed(0.f), - mAvgSpeed(0.f), + mAdjustedSpeed(0.f), mRelativeDir(0.f), mAnkleOffset(0.f) { @@ -185,15 +185,16 @@ LLMotion::LLMotionInitStatus LLWalkAdjustMotion::onInitialize(LLCharacter *chara //----------------------------------------------------------------------------- BOOL LLWalkAdjustMotion::onActivate() { - mAvgCorrection = 0.f; - mSpeedAdjust = 0.f; mAnimSpeed = 0.f; - mAvgSpeed = 0.f; + mAdjustedSpeed = 0.f; mRelativeDir = 1.f; mPelvisState->setPosition(LLVector3::zero); // store ankle positions for next frame - mLastLeftAnklePos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition()); - mLastRightAnklePos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition()); + mLastLeftFootGlobalPos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition()); + mLastLeftFootGlobalPos.mdV[VZ] = 0.0; + + mLastRightFootGlobalPos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition()); + mLastRightFootGlobalPos.mdV[VZ] = 0.0; F32 leftAnkleOffset = (mLeftAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec(); F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec(); @@ -207,144 +208,121 @@ BOOL LLWalkAdjustMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) { - LLVector3 footCorrection; - LLVector3 vel = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation(); - F32 deltaTime = llclamp(time - mLastTime, 0.f, MAX_TIME_DELTA); + // delta_time is guaranteed to be non zero + F32 delta_time = llclamp(time - mLastTime, TIME_EPSILON, MAX_TIME_DELTA); mLastTime = time; - LLQuaternion inv_rotation = ~mPelvisJoint->getWorldRotation(); + // find the avatar motion vector in the XY plane + LLVector3 avatar_velocity = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation(); + avatar_velocity.mV[VZ] = 0.f; - // get speed and normalize velocity vector - LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation(); - F32 speed = llmin(vel.normVec(), MAX_WALK_PLAYBACK_SPEED); - mAvgSpeed = lerp(mAvgSpeed, speed, LLCriticalDamp::getInterpolant(0.2f)); + F32 speed = llclamp(avatar_velocity.magVec(), 0.f, MAX_WALK_PLAYBACK_SPEED); - // calculate facing vector in pelvis-local space - // (either straight forward or back, depending on velocity) - LLVector3 localVel = vel * inv_rotation; - if (localVel.mV[VX] > 0.f) - { - mRelativeDir = 1.f; - } - else if (localVel.mV[VX] < 0.f) - { - mRelativeDir = -1.f; - } + // grab avatar->world transforms + LLQuaternion avatar_to_world_rot = mCharacter->getRootJoint()->getWorldRotation(); - // calculate world-space foot drift - LLVector3 leftFootDelta; - LLVector3 leftFootWorldPosition = mLeftAnkleJoint->getWorldPosition(); - LLVector3d leftFootGlobalPosition = mCharacter->getPosGlobalFromAgent(leftFootWorldPosition); - leftFootDelta.setVec(mLastLeftAnklePos - leftFootGlobalPosition); - mLastLeftAnklePos = leftFootGlobalPosition; + LLQuaternion world_to_avatar_rot(avatar_to_world_rot); + world_to_avatar_rot.conjugate(); - LLVector3 rightFootDelta; - LLVector3 rightFootWorldPosition = mRightAnkleJoint->getWorldPosition(); - LLVector3d rightFootGlobalPosition = mCharacter->getPosGlobalFromAgent(rightFootWorldPosition); - rightFootDelta.setVec(mLastRightAnklePos - rightFootGlobalPosition); - mLastRightAnklePos = rightFootGlobalPosition; + LLVector3 foot_slip_vector; // find foot drift along velocity vector - if (mAvgSpeed > 0.1) - { - // walking/running - F32 leftFootDriftAmt = leftFootDelta * vel; - F32 rightFootDriftAmt = rightFootDelta * vel; + if (speed > MIN_WALK_SPEED) + { // walking/running - if (rightFootDriftAmt > leftFootDriftAmt) - { - footCorrection = rightFootDelta; - } else - { - footCorrection = leftFootDelta; - } - } - else - { - mAvgSpeed = ang_vel.magVec() * mAnkleOffset; - mRelativeDir = 1.f; + // calculate world-space foot drift + // use global coordinates to seamlessly handle region crossings + LLVector3d leftFootGlobalPosition = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition()); + leftFootGlobalPosition.mdV[VZ] = 0.0; + LLVector3 leftFootDelta(leftFootGlobalPosition - mLastLeftFootGlobalPos); + mLastLeftFootGlobalPos = leftFootGlobalPosition; - // standing/turning - // find the lower foot - if (leftFootWorldPosition.mV[VZ] < rightFootWorldPosition.mV[VZ]) - { - // pivot on left foot - footCorrection = leftFootDelta; - } + LLVector3d rightFootGlobalPosition = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition()); + rightFootGlobalPosition.mdV[VZ] = 0.0; + LLVector3 rightFootDelta(rightFootGlobalPosition - mLastRightFootGlobalPos); + mLastRightFootGlobalPos = rightFootGlobalPosition; + + // get foot drift along avatar direction of motion + F32 left_foot_slip_amt = leftFootDelta * avatar_velocity; + F32 right_foot_slip_amt = rightFootDelta * avatar_velocity; + + // if right foot is pushing back faster than left foot... + if (right_foot_slip_amt < left_foot_slip_amt) + { //...use it to calculate optimal animation speed + foot_slip_vector = rightFootDelta; + } else - { - // pivot on right foot - footCorrection = rightFootDelta; + { // otherwise use the left foot + foot_slip_vector = leftFootDelta; } - } - // rotate into avatar coordinates - footCorrection = footCorrection * inv_rotation; + // calculate ideal pelvis offset so that foot is glued to ground and damp towards it + // this will soak up transient slippage + // + // FIXME: this interacts poorly with speed adjustment + // mPelvisOffset compensates for foot drift by moving the avatar pelvis in the opposite + // direction of the drift, up to a certain limited distance + // but this will cause the animation playback rate calculation below to + // kick in too slowly and sometimes start playing the animation in reverse. - // calculate ideal pelvis offset so that foot is glued to ground and damp towards it - // the amount of foot slippage this frame + the offset applied last frame - mPelvisOffset = mPelvisState->getPosition() + lerp(LLVector3::zero, footCorrection, LLCriticalDamp::getInterpolant(0.2f)); + //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLCriticalDamp::getInterpolant(0.1f)); - // pelvis drift (along walk direction) - mAvgCorrection = lerp(mAvgCorrection, footCorrection.mV[VX] * mRelativeDir, LLCriticalDamp::getInterpolant(0.1f)); + ////F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL * (llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED); + //F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL; - // calculate average velocity of foot slippage - F32 footSlipVelocity = (deltaTime != 0.f) ? (-mAvgCorrection / deltaTime) : 0.f; + //// clamp pelvis offset to a 90 degree arc behind the nominal position + //// NB: this is an ADDITIVE amount that is accumulated every frame, so clamping it alone won't do the trick + //// must clamp with absolute position of pelvis in mind + //LLVector3 currentPelvisPos = mPelvisState->getJoint()->getPosition(); + //mPelvisOffset.mV[VX] = llclamp( mPelvisOffset.mV[VX], -drift_comp_max, drift_comp_max ); + //mPelvisOffset.mV[VY] = llclamp( mPelvisOffset.mV[VY], -drift_comp_max, drift_comp_max ); + //mPelvisOffset.mV[VZ] = 0.f; + // + //mLastRightFootGlobalPos += LLVector3d(mPelvisOffset * avatar_to_world_rot); + //mLastLeftFootGlobalPos += LLVector3d(mPelvisOffset * avatar_to_world_rot); - F32 newSpeedAdjust = 0.f; - - // modulate speed by dot products of facing and velocity - // so that if we are moving sideways, we slow down the animation - // and if we're moving backward, we walk backward + //foot_slip_vector -= mPelvisOffset; - F32 directional_factor = localVel.mV[VX] * mRelativeDir; - if (speed > 0.1f) - { - // calculate ratio of desired foot velocity to detected foot velocity - newSpeedAdjust = llclamp(footSlipVelocity - mAvgSpeed * (1.f - directional_factor), - -SPEED_ADJUST_MAX, SPEED_ADJUST_MAX); - newSpeedAdjust = lerp(mSpeedAdjust, newSpeedAdjust, LLCriticalDamp::getInterpolant(0.2f)); + LLVector3 avatar_movement_dir = avatar_velocity; + avatar_movement_dir.normalize(); - F32 speedDelta = newSpeedAdjust - mSpeedAdjust; - speedDelta = llclamp(speedDelta, -SPEED_ADJUST_MAX_SEC * deltaTime, SPEED_ADJUST_MAX_SEC * deltaTime); + // planted foot speed is avatar velocity - foot slip amount along avatar movement direction + F32 foot_speed = speed - ((foot_slip_vector * avatar_movement_dir) / delta_time); - mSpeedAdjust = mSpeedAdjust + speedDelta; + // multiply animation playback rate so that foot speed matches avatar speed + F32 min_speed_multiplier = clamp_rescale(speed, 0.f, 1.f, 0.f, 0.1f); + F32 desired_speed_multiplier = llclamp(speed / foot_speed, min_speed_multiplier, ANIM_SPEED_MAX); + + // blend towards new speed adjustment value + F32 new_speed_adjust = lerp(mAdjustedSpeed, desired_speed_multiplier, LLCriticalDamp::getInterpolant(SPEED_ADJUST_TIME_CONSTANT)); + + // limit that rate at which the speed adjustment changes + F32 speedDelta = llclamp(new_speed_adjust - mAdjustedSpeed, -SPEED_ADJUST_MAX_SEC * delta_time, SPEED_ADJUST_MAX_SEC * delta_time); + mAdjustedSpeed += speedDelta; + + // modulate speed by dot products of facing and velocity + // so that if we are moving sideways, we slow down the animation + // and if we're moving backward, we walk backward + // do this at the end to be more responsive to direction changes instead of in the above speed calculations + F32 directional_factor = (avatar_movement_dir * world_to_avatar_rot).mV[VX]; + + mAnimSpeed = mAdjustedSpeed * directional_factor; } else - { - mSpeedAdjust = lerp(mSpeedAdjust, 0.f, LLCriticalDamp::getInterpolant(0.2f)); + { // standing/turning + + // damp out speed adjustment to 0 + mAnimSpeed = lerp(mAnimSpeed, 1.f, LLCriticalDamp::getInterpolant(0.2f)); + //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLCriticalDamp::getInterpolant(0.2f)); } - mAnimSpeed = (mAvgSpeed + mSpeedAdjust) * mRelativeDir; - mAnimSpeed = mAnimSpeed * SPEED_FINAL_SCALING; -// char debug_text[64]; -// sprintf(debug_text, "Foot slip vel: %.2f", footSlipVelocity); -// mCharacter->addDebugText(debug_text); -// sprintf(debug_text, "Speed: %.2f", mAvgSpeed); -// mCharacter->addDebugText(debug_text); -// sprintf(debug_text, "Speed Adjust: %.2f", mSpeedAdjust); -// mCharacter->addDebugText(debug_text); -// sprintf(debug_text, "Animation Playback Speed: %.2f", mAnimSpeed); -// mCharacter->addDebugText(debug_text); - mCharacter->setAnimationData("Walk Speed", &mAnimSpeed); - - // clamp pelvis offset to a 90 degree arc behind the nominal position - F32 drift_comp_max = llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED; - drift_comp_max *= DRIFT_COMP_MAX_TOTAL; - - LLVector3 currentPelvisPos = mPelvisState->getJoint()->getPosition(); - - // NB: this is an ADDITIVE amount that is accumulated every frame, so clamping it alone won't do the trick - // must clamp with absolute position of pelvis in mind - mPelvisOffset.mV[VX] = llclamp( mPelvisOffset.mV[VX], -drift_comp_max - currentPelvisPos.mV[VX], drift_comp_max - currentPelvisPos.mV[VX] ); - mPelvisOffset.mV[VY] = llclamp( mPelvisOffset.mV[VY], -drift_comp_max - currentPelvisPos.mV[VY], drift_comp_max - currentPelvisPos.mV[VY]); - mPelvisOffset.mV[VZ] = 0.f; + // broadcast walk speed change + mCharacter->setAnimationData("Walk Speed", &mAnimSpeed); // set position + // need to update *some* joint to keep this animation active mPelvisState->setPosition(mPelvisOffset); - mCharacter->setAnimationData("Pelvis Offset", &mPelvisOffset); - return TRUE; } diff --git a/indra/llcharacter/llkeyframewalkmotion.h b/indra/llcharacter/llkeyframewalkmotion.h index 90dd4dbca..b507e9423 100644 --- a/indra/llcharacter/llkeyframewalkmotion.h +++ b/indra/llcharacter/llkeyframewalkmotion.h @@ -126,13 +126,11 @@ public: LLJoint* mRightAnkleJoint; LLPointer mPelvisState; LLJoint* mPelvisJoint; - LLVector3d mLastLeftAnklePos; - LLVector3d mLastRightAnklePos; + LLVector3d mLastLeftFootGlobalPos; + LLVector3d mLastRightFootGlobalPos; F32 mLastTime; - F32 mAvgCorrection; - F32 mSpeedAdjust; + F32 mAdjustedSpeed; F32 mAnimSpeed; - F32 mAvgSpeed; F32 mRelativeDir; LLVector3 mPelvisOffset; F32 mAnkleOffset; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 12bd93686..2f3cb3ec3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12822,6 +12822,28 @@ Value 1 + UseNewWalkRun + + Comment + Replace standard walk/run animations with new ones. + Persist + 1 + Type + Boolean + Value + 1 + + UseCrossWalkRun + + Comment + Use opposite gender walk/run animations. + Persist + 1 + Type + Boolean + Value + 0 + UseStartScreen Comment diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6c87dcc7d..83dba5404 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -995,7 +995,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create ); registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create ); registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create ); + registerMotion( ANIM_AGENT_FEMALE_RUN_NEW, LLKeyframeWalkMotion::create ); //v2 + registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_FEMALE_WALK_NEW, LLKeyframeWalkMotion::create ); //v2 registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_RUN_NEW, LLKeyframeWalkMotion::create ); //v2 registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create ); registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create ); registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create ); @@ -1005,13 +1009,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_WALK_NEW, LLKeyframeWalkMotion::create ); //v2 // motions without a start/stop bit registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create ); registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create ); registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create ); registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create ); - registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create ); registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create ); registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create ); @@ -5791,6 +5795,56 @@ std::string LLVOAvatar::getIdleTime() return output; } +// Override selectively based on avatar sex and whether we're using new +// animations. +LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) +{ + LLCachedControl use_new_walk_run("UseNewWalkRun",true); + LLCachedControl use_cross_walk_run("UseCrossWalkRun",false); + LLUUID result = id; + + // start special case female walk for female avatars + if ((getSex() == SEX_FEMALE) != use_cross_walk_run) + { + if (id == ANIM_AGENT_WALK) + { + if (use_new_walk_run) + result = ANIM_AGENT_FEMALE_WALK_NEW; + else + result = ANIM_AGENT_FEMALE_WALK; + } + else if (id == ANIM_AGENT_RUN) + { + // There is no old female run animation, so only override + // in one case. + if (use_new_walk_run) + result = ANIM_AGENT_FEMALE_RUN_NEW; + } + else if (id == ANIM_AGENT_SIT) + { + result = ANIM_AGENT_SIT_FEMALE; + } + } + else + { + // Male avatar. + if (id == ANIM_AGENT_WALK) + { + if (use_new_walk_run) + result = ANIM_AGENT_WALK_NEW; + } + else if (id == ANIM_AGENT_RUN) + { + if (use_new_walk_run) + result = ANIM_AGENT_RUN_NEW; + } + + } + + return result; + +} + //----------------------------------------------------------------------------- // startMotion() // id is the asset id of the animation to start @@ -5809,25 +5863,14 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) LLMemType mt(LLMemType::MTYPE_AVATAR); - // start special case female walk for female avatars - if (getSex() == SEX_FEMALE) - { - if (id == ANIM_AGENT_WALK) - { - return LLCharacter::startMotion(ANIM_AGENT_FEMALE_WALK, time_offset); - } - else if (id == ANIM_AGENT_SIT) - { - return LLCharacter::startMotion(ANIM_AGENT_SIT_FEMALE, time_offset); - } - } + LLUUID remap_id = remapMotionID(id); - if (mIsSelf && id == ANIM_AGENT_AWAY) + if (mIsSelf && remap_id == ANIM_AGENT_AWAY) { gAgent.setAFK(); } - return LLCharacter::startMotion(id, time_offset); + return LLCharacter::startMotion(remap_id, time_offset); } //----------------------------------------------------------------------------- @@ -5835,21 +5878,15 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) //----------------------------------------------------------------------------- BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) { + + LLUUID remap_id = remapMotionID(id); + if (mIsSelf) { - gAgent.onAnimStop(id); + gAgent.onAnimStop(remap_id); } - if (id == ANIM_AGENT_WALK) - { - LLCharacter::stopMotion(ANIM_AGENT_FEMALE_WALK, stop_immediate); - } - else if (id == ANIM_AGENT_SIT) - { - LLCharacter::stopMotion(ANIM_AGENT_SIT_FEMALE, stop_immediate); - } - - return LLCharacter::stopMotion(id, stop_immediate); + return LLCharacter::stopMotion(remap_id, stop_immediate); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 70bdd6859..c4c5cb33a 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -209,6 +209,7 @@ public: virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); virtual void updateVisualParams(); + LLUUID remapMotionID(const LLUUID& id); virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); virtual void stopMotionFromSource(const LLUUID& source_id); From 1b039a1be6b412d4dec972d612a4a9b92de1c890 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 8 Mar 2011 18:36:59 -0600 Subject: [PATCH 04/14] Deferred has sky and water textures now. Underwater is still borked. Deferred fastalpha behaves a bit better. Pulled over patch for https://jira.secondlife.com/browse/STORM-336 and https://jira.secondlife.com/browse/STORM-1011 from linden repo Sky rendered using new LL method. Assuming this fixes issues on AMD cards(works on cat 11.2) Added a few things missed related to spatial-parition updating. Added 'SkipReflectOcclusionUpdates' setting that prevents occlusion updates for reflection pass. Less taxing on CPU. --- indra/llrender/llvertexbuffer.cpp | 286 ++++++++++---- indra/llrender/llvertexbuffer.h | 29 +- indra/newview/app_settings/settings.xml | 22 ++ .../shaders/class1/deferred/alphaF.glsl | 4 +- .../shaders/class1/deferred/alphaV.glsl | 4 +- .../shaders/class1/deferred/avatarF.glsl | 9 +- .../shaders/class1/deferred/impostorF.glsl | 3 +- .../class1/deferred/multiPointLightF.glsl | 6 + .../shaders/class1/deferred/pointLightF.glsl | 5 + .../shaders/class1/deferred/treeF.glsl | 2 +- .../shaders/class1/deferred/waterF.glsl | 33 +- indra/newview/lldrawpoolalpha.cpp | 13 +- indra/newview/lldrawpoolsimple.cpp | 2 +- indra/newview/lldrawpooltree.cpp | 4 +- indra/newview/lldrawpoolwater.cpp | 49 ++- indra/newview/lldrawpoolwater.h | 4 +- indra/newview/lldrawpoolwlsky.cpp | 3 +- indra/newview/llsky.cpp | 3 + indra/newview/llsky.h | 6 +- indra/newview/llspatialpartition.cpp | 15 +- indra/newview/llviewercontrol.cpp | 10 + indra/newview/llviewerdisplay.cpp | 13 +- indra/newview/llviewerobject.cpp | 1 - indra/newview/llviewershadermgr.cpp | 35 +- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/llvosky.cpp | 54 +-- indra/newview/llvosky.h | 51 +-- indra/newview/llvowlsky.cpp | 42 +- indra/newview/llwaterparammanager.cpp | 2 +- indra/newview/llwlparammanager.cpp | 2 +- indra/newview/pipeline.cpp | 368 +++++++++++------- indra/newview/pipeline.h | 1 + 32 files changed, 708 insertions(+), 375 deletions(-) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 756603a32..1d5d03581 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,10 @@ 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; + sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; LLGLNamePool::registerPool(&sDynamicVBOPool); LLGLNamePool::registerPool(&sDynamicIBOPool); LLGLNamePool::registerPool(&sStreamVBOPool); @@ -346,7 +348,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 +548,8 @@ void LLVertexBuffer::destroyGLBuffer() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped!" << llendl; @@ -571,6 +577,8 @@ void LLVertexBuffer::destroyGLIndices() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped." << llendl; @@ -768,6 +776,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) if (mResized && useVBOs()) { + freeClientBuffer() ; setBuffer(0); } } @@ -782,104 +791,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 +1026,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 +1043,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 +1130,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 +1164,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) sIBOActive = TRUE; } + BOOL error = FALSE; if (gDebugGL) { GLint buff; @@ -1085,7 +1227,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 2f3cb3ec3..5538c66a0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9843,6 +9843,17 @@ Value 1 + RenderVBOMappingDisable + + Comment + Disable VBO glMapBufferARB + Persist + 1 + Type + Boolean + Value + 1 + RenderVolumeLODFactor Comment @@ -12800,6 +12811,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..99cc2f851 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 = 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/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index e9127ad49..f64672cac 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -90,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() { 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/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index d3241fdf2..f08e22569 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -141,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..89c5bb88b 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(); @@ -388,11 +404,11 @@ void LLDrawPoolWater::shade() F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); - if (deferred_render) + if (eyedepth > 0.f && deferred_render) { shader = &gDeferredWaterProgram; } - else if (eyedepth < 0.f && LLPipeline::sWaterReflections) + else if (eyedepth < 0.f /*&& LLPipeline::sWaterReflections*/) { shader = &gUnderWaterProgram; } @@ -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 ec8c66509..3f5754007 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -293,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/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 d4e63945e..63784107b 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -534,7 +534,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) return; } - if (/*!LLPipeline::sSkipUpdate && */group->changeLOD()) + if (!LLPipeline::sSkipUpdate && group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; group->mLastUpdateViewAngle = group->mViewAngle; @@ -1397,7 +1397,6 @@ void LLSpatialGroup::checkOcclusion() } else if (isOcclusionState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back - LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); GLuint res = 1; if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { @@ -1437,10 +1436,9 @@ 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)) || + if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || earlyFail(camera, this)) { setOcclusionState(LLSpatialGroup::DISCARD_QUERY); @@ -1466,10 +1464,9 @@ 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); 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 7c412906f..7bb055193 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -615,6 +615,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); @@ -667,6 +668,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(); @@ -784,6 +786,7 @@ 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); @@ -887,7 +890,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) { @@ -1366,6 +1369,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; @@ -1378,8 +1387,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/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 71e3ddcfd..f3639d3b0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -456,7 +456,6 @@ void LLViewerObject::initVOClasses() llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl; LLVOGrass::initClass(); LLVOWater::initClass(); - LLVOSky::initClass(); LLVOVolume::initClass(); } 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 48a1e3f8a..5ee61a1b8 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()) 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/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 59000e600..21ab8e598 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2114,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); @@ -2181,7 +2181,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) LLSpatialGroup* group = drawablep->getSpatialGroup(); if (!group || group->changeLOD()) { - if (drawablep->isVisible()) + if (drawablep->isVisible() && !sSkipUpdate) { if (!drawablep->isActive()) { @@ -2434,7 +2434,7 @@ void LLPipeline::postSort(LLCamera& camera) 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; } @@ -2579,7 +2579,7 @@ void LLPipeline::postSort(LLCamera& camera) } } - LLSpatialGroup::sNoDelete = FALSE; + //LLSpatialGroup::sNoDelete = FALSE; } @@ -3983,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; } @@ -4172,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()); @@ -4438,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() @@ -5149,7 +5149,25 @@ void LLPipeline::setUseVBO(BOOL use_vbo) } resetVertexBuffers(); - LLVertexBuffer::initClass(use_vbo); + LLVertexBuffer::initClass(use_vbo, gSavedSettings.getBOOL("RenderVBOMappingDisable")); + } +} + +void LLPipeline::setDisableVBOMapping(BOOL no_vbo_mapping) +{ + if (LLVertexBuffer::sEnableVBOs && no_vbo_mapping != LLVertexBuffer::sDisableVBOMapping) + { + if (no_vbo_mapping) + { + llinfos << "Disabling VBO glMapBufferARB." << llendl; + } + else + { + llinfos << "Enabling VBO glMapBufferARB." << llendl; + } + + resetVertexBuffers(); + LLVertexBuffer::initClass(true, no_vbo_mapping); } } @@ -5668,6 +5686,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->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() @@ -5677,6 +5700,7 @@ void LLPipeline::renderDeferredLighting() return; } + LLViewerCamera* camera = LLViewerCamera::getInstance(); LLGLEnable multisample(GL_MULTISAMPLE_ARB); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -5691,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); @@ -5711,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(); @@ -5845,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); @@ -5871,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; @@ -5879,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) { @@ -5890,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 @@ -5920,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 { @@ -5938,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()) { @@ -5956,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); @@ -5967,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); @@ -5977,12 +6044,9 @@ 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); @@ -5990,7 +6054,7 @@ void LLPipeline::renderDeferredLighting() 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); @@ -6212,7 +6276,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } } } - + 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); @@ -6221,6 +6286,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.grabReferences(ref_result); LLGLUserClipPlane clip_plane(plane, mat, projection); renderGeom(camera); + LLPipeline::sSkipUpdate = FALSE; } } gPipeline.popRenderTypeMask(); @@ -6381,7 +6447,6 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) void LLPipeline::generateSunShadow(LLCamera& camera) { - if (!sRenderDeferred) { return; @@ -6896,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); @@ -6903,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 { @@ -6921,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) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index d0148d2a8..36f4c33ec 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -96,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); From ef90cc74e46a1924b5f23cece98c885b534559c9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 8 Mar 2011 18:52:02 -0600 Subject: [PATCH 05/14] Whoops. Reverting some stuff I was toying around with. --- .../newview/app_settings/shaders/class1/deferred/waterF.glsl | 2 +- indra/newview/lldrawpoolwater.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 99cc2f851..83959101e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -151,7 +151,7 @@ void main() // spec *= shadow; // color.rgb += spec * specular; - color.rgb = atmosTransport(color.rgb); +// color.rgb = atmosTransport(color.rgb); // color.rgb = scaleSoftClip(color.rgb); // color.a = spec * sunAngle2; diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 89c5bb88b..4b9f55946 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -404,11 +404,11 @@ void LLDrawPoolWater::shade() F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); - if (eyedepth > 0.f && deferred_render) + if (deferred_render) { shader = &gDeferredWaterProgram; } - else if (eyedepth < 0.f /*&& LLPipeline::sWaterReflections*/) + else if (eyedepth < 0.f && LLPipeline::sWaterReflections) { shader = &gUnderWaterProgram; } From 81174cffa7b5080bf77ffe6fef5e04f67d1c18d8 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 14 Mar 2011 16:26:47 -0500 Subject: [PATCH 06/14] Fixed a snapshot crash --- indra/newview/llviewermenufile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 987c15d12..75ff06845 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -588,7 +588,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t gViewerWindow->playSnapshotAnimAndSound(); LLPointer formatted; - formatted->enableOverSize(); switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: @@ -605,6 +604,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t return true; } + formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize(); gViewerWindow->saveImageNumbered(formatted); From a8ef46888e62787f17c9206eaa7e78a183154689 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 14 Mar 2011 17:03:34 -0500 Subject: [PATCH 07/14] More STORM-1026 LL fixes. --- indra/llrender/llvertexbuffer.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1d5d03581..8d927ada5 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -290,7 +290,18 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const //static 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); From b06dcb45c0fee81f7edd330874c24d08b8f38426 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 15 Mar 2011 01:15:43 -0500 Subject: [PATCH 08/14] Applying recent commits from Snowstorm --- indra/newview/llappviewer.cpp | 2 +- indra/newview/lltexturecache.cpp | 17 ++++++++--------- indra/newview/llviewerobjectlist.cpp | 11 ++++++----- indra/newview/llvocache.cpp | 5 ++++- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b9d320454..f8e30b4b1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1407,8 +1407,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(); 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/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index dd37136a8..4f50fec6e 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -845,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. @@ -1100,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/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; + } } From e29d9696315367a5b3221dbd2490392e0957d7ab Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 15 Mar 2011 02:28:22 -0500 Subject: [PATCH 09/14] Misc llcommon tidbits from v2. --- indra/llcharacter/llcharacter.h | 4 ++-- indra/llcommon/lldarray.h | 2 +- indra/llcommon/llerrorlegacy.h | 17 +++++++++-------- indra/llcommon/llfile.cpp | 11 +++++++++++ indra/llcommon/llfile.h | 2 ++ indra/llcommon/llmd5.cpp | 29 +++++++++++++++++++++-------- indra/llcommon/llmd5.h | 8 ++++++-- indra/llcommon/llsdserialize.cpp | 2 +- indra/llcommon/lluri.cpp | 18 +++++++++++++++--- 9 files changed, 68 insertions(+), 25 deletions(-) diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 06c4e5ff4..4de59e9ee 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -246,9 +246,9 @@ public: return rtn; } - LLVisualParam* getVisualParam(S32 id) + LLVisualParam* getVisualParam(S32 id) const { - visual_param_index_map_t::iterator iter = mVisualParamIndexMap.find(id); + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(id); return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second; } S32 getVisualParamID(LLVisualParam *id) diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h index aee136363..5433e8d72 100644 --- a/indra/llcommon/lldarray.h +++ b/indra/llcommon/lldarray.h @@ -202,7 +202,7 @@ public: { U32 n = mVector.size(); mIndexMap[k] = n; - mVector.resize(n+1); + mVector.push_back(Type()); llassert(mVector.size() == mIndexMap.size()); return mVector[n]; } diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 143fe2018..fc563dc09 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -75,6 +75,10 @@ const int LL_ERR_PRICE_MISMATCH = -23018; #define SHOW_ASSERT #else // _DEBUG +#ifdef LL_RELEASE_WITH_DEBUG_INFO +#define SHOW_ASSERT +#endif // LL_RELEASE_WITH_DEBUG_INFO + #ifdef RELEASE_SHOW_DEBUG #define SHOW_DEBUG #endif @@ -103,17 +107,14 @@ const int LL_ERR_PRICE_MISMATCH = -23018; #define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl; -#ifdef SHOW_ASSERT -#define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; -#else -#define llassert(func) -#endif -#define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; +#define llassert_always(func) if (LL_UNLIKELY(!(func))) llerrs << "ASSERT (" << #func << ")" << llendl; #ifdef SHOW_ASSERT -#define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; +#define llassert(func) llassert_always(func) +#define llverify(func) llassert_always(func) #else -#define llverify(func) (func); // get rid of warning C4189 +#define llassert(func) +#define llverify(func) do {if (func) {}} while(0) #endif // handy compile-time assert - enforce those template parameters! diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 71a2df48f..d3e97f5c1 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -98,6 +98,17 @@ LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int shari #endif } +int LLFile::close(LLFILE * file) +{ + int ret_value = 0; + if (file) + { + ret_value = fclose(file); + } + return ret_value; +} + + int LLFile::remove(const std::string& filename) { #if LL_WINDOWS diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index ee376054b..8b28d77bd 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -77,6 +77,8 @@ public: static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */ static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag); + static int close(LLFILE * file); + // perms is a permissions mask like 0777 or 0700. In most cases it will // be overridden by the user's umask. It is ignored on Windows. static int mkdir(const std::string& filename, int perms = 0700); diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 887979bbf..35067b3b3 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -192,9 +192,10 @@ void LLMD5::update(std::istream& stream){ } - - - +void LLMD5::update(const std::string& s) +{ + update((unsigned char *)s.c_str(),s.length()); +} // MD5 finalization. Ends an MD5 message-digest operation, writing the // the message digest and zeroizing the context. @@ -277,7 +278,7 @@ LLMD5::LLMD5(const unsigned char *s) finalize(); } -void LLMD5::raw_digest(unsigned char *s) +void LLMD5::raw_digest(unsigned char *s) const { if (!finalized) { @@ -293,7 +294,7 @@ void LLMD5::raw_digest(unsigned char *s) -void LLMD5::hex_digest(char *s) +void LLMD5::hex_digest(char *s) const { int i; @@ -327,13 +328,25 @@ std::ostream& operator<<(std::ostream &stream, LLMD5 context) return stream; } +bool operator==(const LLMD5& a, const LLMD5& b) +{ + unsigned char a_guts[16]; + unsigned char b_guts[16]; + a.raw_digest(a_guts); + b.raw_digest(b_guts); + if (memcmp(a_guts,b_guts,16)==0) + return true; + else + return false; +} - +bool operator!=(const LLMD5& a, const LLMD5& b) +{ + return !(a==b); +} // PRIVATE METHODS: - - void LLMD5::init(){ finalized=0; // we just started! diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index df9d7324a..837dd3e5a 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -95,6 +95,7 @@ public: void update (const uint1 *input, const uint4 input_length); void update (std::istream& stream); void update (FILE *file); + void update (const std::string& str); void finalize (); // constructors for special circumstances. All these constructors finalize @@ -105,8 +106,8 @@ public: LLMD5 (const unsigned char *string, const unsigned int number); // methods to acquire finalized result - void raw_digest(unsigned char *array); // provide 16-byte array for binary data - void hex_digest(char *string); // provide 33-byte array for ascii-hex string + void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data + void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string friend std::ostream& operator<< (std::ostream&, LLMD5 context); @@ -131,4 +132,7 @@ private: }; +LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); +LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b); + #endif // LL_LLMD5_H diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 9f4ce64d2..48423934c 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -77,7 +77,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize break; default: - llwarns << "serialize request for unkown ELLSD_Serialize" << llendl; + llwarns << "serialize request for unknown ELLSD_Serialize" << llendl; } if (f.notNull()) diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 3dbc83787..673afd460 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -46,10 +46,21 @@ void encode_character(std::ostream& ostr, std::string::value_type val) { - ostr << "%" << std::uppercase << std::hex << std::setw(2) << std::setfill('0') + ostr << "%" + + << std::uppercase + << std::hex + << std::setw(2) + << std::setfill('0') + // VWR-4010 Cannot cast to U32 because sign-extension on // chars > 128 will result in FFFFFFC3 instead of F3. - << static_cast(static_cast(val)); + << static_cast(static_cast(val)) + + // reset stream state + << std::nouppercase + << std::dec + << std::setfill(' '); } // static @@ -221,7 +232,8 @@ static BOOL isDefault(const std::string& scheme, U16 port) void LLURI::parseAuthorityAndPathUsingOpaque() { if (mScheme == "http" || mScheme == "https" || - mScheme == "ftp" || mScheme == "secondlife" ) + mScheme == "ftp" || mScheme == "secondlife" || + mScheme == "x-grid-location-info") { if (mEscapedOpaque.substr(0,2) != "//") { From 6ee243d0d5a9b3e69af32a772fb23a21d50f75d9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 15 Mar 2011 02:32:14 -0500 Subject: [PATCH 10/14] Added reload button to web-based search and showcase, since a page failing to load shouldn't require a client restart in order to try it again. --- indra/newview/llpaneldirfind.cpp | 12 ++++++++++++ indra/newview/llpaneldirfind.h | 1 + .../skins/default/xui/en-us/floater_directory.xml | 11 ++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/indra/newview/llpaneldirfind.cpp b/indra/newview/llpaneldirfind.cpp index 55756a971..93e7bc2ad 100644 --- a/indra/newview/llpaneldirfind.cpp +++ b/indra/newview/llpaneldirfind.cpp @@ -109,6 +109,7 @@ BOOL LLPanelDirFind::postBuild() childSetAction("back_btn", onClickBack, this); childSetAction("home_btn", onClickHome, this); childSetAction("forward_btn", onClickForward, this); + childSetAction("reload_btn", onClickRefresh, this); childSetCommitCallback("search_editor", onCommitSearch, this); childSetAction("search_btn", onClickSearch, this); childSetAction("?", onClickHelp, this); @@ -177,6 +178,7 @@ void LLPanelDirFind::draw() bool enable_forward = mWebBrowser->canNavigateForward(); childSetEnabled( "forward_btn", enable_forward ); + childSetEnabled( "reload_btn", TRUE ); } // showcase doesn't have maturity flags -- it's all PG @@ -464,6 +466,16 @@ void LLPanelDirFind::onClickHome( void* data ) } } +// static +void LLPanelDirFind::onClickRefresh( void* data ) +{ + LLPanelDirFind* self = ( LLPanelDirFind* )data; + if ( self->mWebBrowser ) + { + self->mWebBrowser->navigateTo(self->mWebBrowser->getCurrentNavUrl()); + } +} + // static void LLPanelDirFind::onCommitSearch(LLUICtrl*, void* data) { diff --git a/indra/newview/llpaneldirfind.h b/indra/newview/llpaneldirfind.h index 95b28036d..99c9daaf1 100644 --- a/indra/newview/llpaneldirfind.h +++ b/indra/newview/llpaneldirfind.h @@ -68,6 +68,7 @@ private: static void onClickBack( void* data ); static void onClickForward( void* data ); static void onClickHome( void* data ); + static void onClickRefresh( void* data ); static void onClickSearch( void* data ); static void onCommitSearch(LLUICtrl*, void* data); static void onClickHelp( void* data ); diff --git a/indra/newview/skins/default/xui/en-us/floater_directory.xml b/indra/newview/skins/default/xui/en-us/floater_directory.xml index c7adfbd60..3c29bf6bc 100644 --- a/indra/newview/skins/default/xui/en-us/floater_directory.xml +++ b/indra/newview/skins/default/xui/en-us/floater_directory.xml @@ -30,6 +30,8 @@ left="230" name="back_btn" width="70" />