From 996aaf63452c9fd9ce85d0135b60ff8b375774d9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 6 Mar 2011 05:47:26 -0600 Subject: [PATCH] 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; //////////////////////////////////////////////////