diff options
Diffstat (limited to 'indra')
84 files changed, 2329 insertions, 2065 deletions
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake index 1b8c3db2e2..cfff956bcf 100644 --- a/indra/cmake/Tracy.cmake +++ b/indra/cmake/Tracy.cmake @@ -7,7 +7,7 @@ if (USE_TRACY) set(TRACY_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tracy) # See: indra/llcommon/llprofiler.h - add_definitions(-DLL_PROFILER_CONFIGURATION=2) + add_definitions(-DLL_PROFILER_CONFIGURATION=3) use_prebuilt_binary(tracy) if (WINDOWS) diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 5d4a623bf6..25a809dad2 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -33,11 +33,22 @@ #include "lltracethreadrecorder.h" #include "llcleanup.h" +thread_local bool gProfilerEnabled = false; + #if (TRACY_ENABLE) // Override new/delete for tracy memory profiling void *operator new(size_t size) { - auto ptr = (malloc) (size); + void* ptr; + if (gProfilerEnabled) + { + LL_PROFILE_ZONE_SCOPED; + ptr = (malloc)(size); + } + else + { + ptr = (malloc)(size); + } if (!ptr) { throw std::bad_alloc(); @@ -49,7 +60,15 @@ void *operator new(size_t size) void operator delete(void *ptr) noexcept { TracyFree(ptr); - (free)(ptr); + if (gProfilerEnabled) + { + LL_PROFILE_ZONE_SCOPED; + (free)(ptr); + } + else + { + (free)(ptr); + } } // C-style malloc/free can't be so easily overridden, so we define tracy versions and use diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index 49510df913..e36f693dd3 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -36,6 +36,8 @@ #define LL_PROFILER_CONFIGURATION LL_PROFILER_CONFIG_FAST_TIMER #endif +extern thread_local bool gProfilerEnabled; + #if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE) #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER #define TRACY_ENABLE 1 @@ -52,7 +54,7 @@ #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY #define LL_PROFILER_FRAME_END FrameMark - #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ) + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; #define LL_RECORD_BLOCK_TIME(name) ZoneScoped // Want descriptive names; was: ZoneNamedN( ___tracy_scoped_zone, #name, true ); #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, name, true ); #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB @@ -82,7 +84,7 @@ #endif #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER #define LL_PROFILER_FRAME_END FrameMark - #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ) + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; #define LL_RECORD_BLOCK_TIME(name) ZoneScoped const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__); #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, #name, true ); #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 57b746889d..605f6bf0e3 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -400,6 +400,7 @@ namespace ImplMap& ImplMap::makeMap(LLSD::Impl*& var) { + LL_PROFILE_ZONE_SCOPED; if (shared()) { ImplMap* i = new ImplMap(mData); @@ -414,18 +415,21 @@ namespace bool ImplMap::has(const LLSD::String& k) const { + LL_PROFILE_ZONE_SCOPED; DataMap::const_iterator i = mData.find(k); return i != mData.end(); } LLSD ImplMap::get(const LLSD::String& k) const { + LL_PROFILE_ZONE_SCOPED; DataMap::const_iterator i = mData.find(k); return (i != mData.end()) ? i->second : LLSD(); } LLSD ImplMap::getKeys() const { + LL_PROFILE_ZONE_SCOPED; LLSD keys = LLSD::emptyArray(); DataMap::const_iterator iter = mData.begin(); while (iter != mData.end()) @@ -438,11 +442,13 @@ namespace void ImplMap::insert(const LLSD::String& k, const LLSD& v) { + LL_PROFILE_ZONE_SCOPED; mData.insert(DataMap::value_type(k, v)); } void ImplMap::erase(const LLSD::String& k) { + LL_PROFILE_ZONE_SCOPED; mData.erase(k); } @@ -684,6 +690,7 @@ const LLSD::Impl& LLSD::Impl::safe(const Impl* impl) ImplMap& LLSD::Impl::makeMap(Impl*& var) { + LL_PROFILE_ZONE_SCOPED; ImplMap* im = new ImplMap; reset(var, im); return *im; @@ -887,11 +894,16 @@ LLSD& LLSD::with(const String& k, const LLSD& v) } void LLSD::erase(const String& k) { makeMap(impl).erase(k); } -LLSD& LLSD::operator[](const String& k) - { return makeMap(impl).ref(k); } +LLSD& LLSD::operator[](const String& k) +{ + LL_PROFILE_ZONE_SCOPED; + return makeMap(impl).ref(k); +} const LLSD& LLSD::operator[](const String& k) const - { return safe(impl).ref(k); } - +{ + LL_PROFILE_ZONE_SCOPED; + return safe(impl).ref(k); +} LLSD LLSD::emptyArray() { @@ -914,10 +926,16 @@ LLSD& LLSD::with(Integer i, const LLSD& v) LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); } void LLSD::erase(Integer i) { makeArray(impl).erase(i); } -LLSD& LLSD::operator[](Integer i) - { return makeArray(impl).ref(i); } +LLSD& LLSD::operator[](Integer i) +{ + LL_PROFILE_ZONE_SCOPED; + return makeArray(impl).ref(i); +} const LLSD& LLSD::operator[](Integer i) const - { return safe(impl).ref(i); } +{ + LL_PROFILE_ZONE_SCOPED; + return safe(impl).ref(i); +} static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat) { diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 5b6d5545af..b8ddf21596 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -290,9 +290,17 @@ public: LLSD& with(const String&, const LLSD&); LLSD& operator[](const String&); - LLSD& operator[](const char* c) { return (*this)[String(c)]; } + LLSD& operator[](const char* c) + { + LL_PROFILE_ZONE_SCOPED; + return (*this)[String(c)]; + } const LLSD& operator[](const String&) const; - const LLSD& operator[](const char* c) const { return (*this)[String(c)]; } + const LLSD& operator[](const char* c) const + { + LL_PROFILE_ZONE_SCOPED; + return (*this)[String(c)]; + } //@} /** @name Array Values */ diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 7c81d65a8b..2e43a3cbed 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -455,6 +455,7 @@ public: static DERIVED_TYPE* getInstance() { + LL_PROFILE_ZONE_SCOPED; // We know the viewer has LLSingleton dependency circularities. If you // feel strongly motivated to eliminate them, cheers and good luck. // (At that point we could consider a much simpler locking mechanism.) diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index f0eafa8201..447c7f50f2 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -356,14 +356,15 @@ namespace tut // Create a script file in a temporary place. NamedTempFile script("py", + "from __future__ import print_function" EOL "import sys" EOL "import time" EOL EOL "time.sleep(2)" EOL - "print >>sys.stdout, 'stdout after wait'" EOL + "print('stdout after wait',file=sys.stdout)" EOL "sys.stdout.flush()" EOL "time.sleep(2)" EOL - "print >>sys.stderr, 'stderr after wait'" EOL + "print('stderr after wait',file=sys.stderr)" EOL "sys.stderr.flush()" EOL ); @@ -568,12 +569,12 @@ namespace tut { set_test_name("arguments"); PythonProcessLauncher py(get_test_name(), - "from __future__ import with_statement\n" + "from __future__ import with_statement, print_function\n" "import sys\n" // note nonstandard output-file arg! "with open(sys.argv[3], 'w') as f:\n" " for arg in sys.argv[1:]:\n" - " print >>f, arg\n"); + " print(arg,file=f)\n"); // We expect that PythonProcessLauncher has already appended // its own NamedTempFile to mParams.args (sys.argv[0]). py.mParams.args.add("first arg"); // sys.argv[1] @@ -857,7 +858,8 @@ namespace tut set_test_name("'bogus' test"); CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam("bogus")); py.mPy = LLProcess::create(py.mParams); ensure("should have rejected 'bogus'", ! py.mPy); @@ -872,7 +874,8 @@ namespace tut // Replace this test with one or more real 'file' tests when we // implement 'file' support PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("file")); py.mPy = LLProcess::create(py.mParams); @@ -887,7 +890,8 @@ namespace tut // implement 'tpipe' support CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("tpipe")); py.mPy = LLProcess::create(py.mParams); @@ -904,7 +908,8 @@ namespace tut // implement 'npipe' support CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("npipe")); @@ -980,7 +985,8 @@ namespace tut { set_test_name("get*Pipe() validation"); PythonProcessLauncher py(get_test_name(), - "print 'this output is expected'\n"); + "from __future__ import print_function\n" + "print('this output is expected')\n"); py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stdin py.mParams.files.add(LLProcess::FileParam()); // inherit stdout py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr @@ -1000,14 +1006,15 @@ namespace tut { set_test_name("talk to stdin/stdout"); PythonProcessLauncher py(get_test_name(), + "from __future__ import print_function\n" "import sys, time\n" - "print 'ok'\n" + "print('ok')\n" "sys.stdout.flush()\n" "# wait for 'go' from test program\n" "go = sys.stdin.readline()\n" "if go != 'go\\n':\n" " sys.exit('expected \"go\", saw %r' % go)\n" - "print 'ack'\n"); + "print('ack')\n"); py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout py.launch(); @@ -1118,7 +1125,8 @@ namespace tut { set_test_name("ReadPipe \"eof\" event"); PythonProcessLauncher py(get_test_name(), - "print 'Hello from Python!'\n"); + "from __future__ import print_function\n" + "print('Hello from Python!')\n"); py.mParams.files.add(LLProcess::FileParam()); // stdin py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout py.launch(); diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index ffc9a97dc0..b32357e832 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -54,6 +54,7 @@ void LL::WorkQueue::runUntilClose() bool LL::WorkQueue::runPending() { + LL_PROFILE_ZONE_SCOPED; for (Work work; mQueue.tryPop(work); ) { callWork(work); @@ -110,6 +111,7 @@ void LL::WorkQueue::callWork(const Queue::DataTuple& work) void LL::WorkQueue::callWork(const Work& work) { + LL_PROFILE_ZONE_SCOPED; try { work(); diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index 61b59e35aa..89a4eebf26 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -683,6 +683,7 @@ bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length) //========================================================================= void LLSettingsBlender::update(const LLSettingsBase::BlendFactor& blendf) { + LL_PROFILE_ZONE_SCOPED; F64 res = setBlendFactor(blendf); llassert(res >= 0.0 && res <= 1.0); (void)res; @@ -713,6 +714,7 @@ F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_ void LLSettingsBlender::triggerComplete() { + LL_PROFILE_ZONE_SCOPED; if (mTarget) mTarget->replaceSettings(mFinal->getSettings()); LLSettingsBlender::ptr_t hold = shared_from_this(); // prevents this from deleting too soon @@ -725,11 +727,13 @@ const LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::MIN_BLEND_DELTA(FL LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const { + LL_PROFILE_ZONE_SCOPED; return LLSettingsBase::BlendFactor(fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen); } bool LLSettingsBlenderTimeDelta::applyTimeDelta(const LLSettingsBase::Seconds& timedelta) { + LL_PROFILE_ZONE_SCOPED; mTimeSpent += timedelta; if (mTimeSpent > mBlendSpan) diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 69b4a4929d..82c67a1066 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -444,6 +444,7 @@ void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) { + LL_PROFILE_ZONE_SCOPED; llassert(getSettingsType() == end->getSettingsType()); LLSettingsSky::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(end); @@ -1022,6 +1023,7 @@ LLColor3 LLSettingsSky::getLightDiffuse() const LLColor3 LLSettingsSky::getColor(const std::string& key, const LLColor3& default_value) const { + LL_PROFILE_ZONE_SCOPED; if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key)) { return LLColor3(mSettings[SETTING_LEGACY_HAZE][key]); @@ -1035,6 +1037,7 @@ LLColor3 LLSettingsSky::getColor(const std::string& key, const LLColor3& default F32 LLSettingsSky::getFloat(const std::string& key, F32 default_value) const { + LL_PROFILE_ZONE_SCOPED; if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key)) { return mSettings[SETTING_LEGACY_HAZE][key].asReal(); diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 673f6cb6df..b66521132c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -62,6 +62,7 @@ BOOL gDebugSession = FALSE; BOOL gClothRipple = FALSE; BOOL gHeadlessClient = FALSE; +BOOL gNonInteractive = FALSE; BOOL gGLActive = FALSE; BOOL gGLDebugLoggingEnabled = TRUE; @@ -2116,6 +2117,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { + LL_PROFILE_ZONE_SCOPED; if (LLGLSLShader::sNoFixedFunction) { //always ignore state that's deprecated post GL 3.0 switch (state) @@ -2174,6 +2176,7 @@ void LLGLState::setEnabled(S32 enabled) LLGLState::~LLGLState() { + LL_PROFILE_ZONE_SCOPED; stop_glerror(); if (mState) { diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index a03d5352be..6e1f5e6deb 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -485,6 +485,7 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gHeadlessClient; +extern BOOL gNonInteractive; extern BOOL gGLActive; // Deal with changing glext.h definitions for newer SDK versions, specifically diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 394fcd2b2f..0e4753fcc6 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1017,7 +1017,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu if (uniform > -1) { - gGL.getTexUnit(uniform)->bind(texture, mode); + gGL.getTexUnit(uniform)->bindFast(texture); gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); } @@ -1048,7 +1048,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) if (uniform > -1) { - gGL.getTexUnit(uniform)->unbind(mode); + gGL.getTexUnit(uniform)->unbindFast(mode); } return uniform; @@ -1104,6 +1104,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe void LLGLSLShader::uniform1i(U32 index, GLint x) { + LL_PROFILE_ZONE_SCOPED if (mProgramObject) { if (mUniform.size() <= index) @@ -1114,7 +1115,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1iARB(mUniform[index], x); @@ -1126,6 +1127,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) void LLGLSLShader::uniform1f(U32 index, GLfloat x) { + LL_PROFILE_ZONE_SCOPED if (mProgramObject) { if (mUniform.size() <= index) @@ -1136,7 +1138,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1fARB(mUniform[index], x); @@ -1158,7 +1160,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1181,7 +1183,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,z,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1204,7 +1206,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,z,w); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1227,7 +1229,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(v[0],0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1250,7 +1252,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(v[0],0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1273,7 +1275,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(v[0],v[1],0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1296,7 +1298,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(v[0],v[1],v[2],0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1319,10 +1321,11 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(v[0],v[1],v[2],v[3]); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { + LL_PROFILE_ZONE_SCOPED; glUniform4fvARB(mUniform[index], count, v); mValue[mUniform[index]] = vec; } @@ -1460,7 +1463,7 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v,0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1476,7 +1479,7 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(i,j,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1493,7 +1496,7 @@ void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v,0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1509,7 +1512,7 @@ void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLf if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(x,y,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1526,7 +1529,7 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(x,y,z,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1542,7 +1545,7 @@ void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v[0],0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1558,7 +1561,7 @@ void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v[0],v[1],0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1574,7 +1577,7 @@ void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v[0],v[1],v[2],0.f); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { @@ -1591,12 +1594,11 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { LLVector4 vec(v); - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { - stop_glerror(); + LL_PROFILE_ZONE_SCOPED; glUniform4fvARB(location, count, v); - stop_glerror(); mValue[location] = vec; } } @@ -1636,3 +1638,27 @@ void LLGLSLShader::setMinimumAlpha(F32 minimum) gGL.flush(); uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); } + +void LLShaderUniforms::apply(LLGLSLShader* shader) +{ + LL_PROFILE_ZONE_SCOPED; + for (auto& uniform : mIntegers) + { + shader->uniform1i(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mFloats) + { + shader->uniform1f(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mVectors) + { + shader->uniform4fv(uniform.mUniform, 1, uniform.mValue.mV); + } + + for (auto& uniform : mVector3s) + { + shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV); + } +} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7cf6d3c941..3b23cf1b28 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -30,6 +30,7 @@ #include "llgl.h" #include "llrender.h" #include "llstaticstringtable.h" +#include <unordered_map> class LLShaderFeatures { @@ -64,16 +65,79 @@ public: LLShaderFeatures(); }; +// ============= Structure for caching shader uniforms =============== +class LLGLSLShader; + +class LLShaderUniforms +{ +public: + + template<typename T> + struct UniformSetting + { + S32 mUniform; + T mValue; + }; + + typedef UniformSetting<S32> IntSetting; + typedef UniformSetting<F32> FloatSetting; + typedef UniformSetting<LLVector4> VectorSetting; + typedef UniformSetting<LLVector3> Vector3Setting; + + void clear() + { + mIntegers.resize(0); + mFloats.resize(0); + mVectors.resize(0); + mVector3s.resize(0); + } + + void uniform1i(S32 index, S32 value) + { + mIntegers.push_back({ index, value }); + } + + void uniform1f(S32 index, F32 value) + { + mFloats.push_back({ index, value }); + } + + void uniform4fv(S32 index, const LLVector4& value) + { + mVectors.push_back({ index, value }); + } + + void uniform4fv(S32 index, const F32* value) + { + mVectors.push_back({ index, LLVector4(value) }); + } + + void uniform3fv(S32 index, const LLVector3& value) + { + mVector3s.push_back({ index, value }); + } + + void apply(LLGLSLShader* shader); + + + std::vector<IntSetting> mIntegers; + std::vector<FloatSetting> mFloats; + std::vector<VectorSetting> mVectors; + std::vector<Vector3Setting> mVector3s; +}; class LLGLSLShader { public: - enum + // enum primarily used to control application sky settings uniforms + typedef enum { - SG_DEFAULT = 0, - SG_SKY, - SG_WATER - }; + SG_DEFAULT = 0, // not sky or water specific + SG_SKY, // + SG_WATER, + SG_ANY, + SG_COUNT + } eGroup; static std::set<LLGLSLShader*> sInstances; static bool sProfileEnabled; @@ -190,13 +254,15 @@ public: U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location - std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name - std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value + typedef std::unordered_map<GLint, std::string> uniform_name_map_t; + typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t; + uniform_name_map_t mUniformNameMap; //lookup map of uniform location to uniform name + uniform_value_map_t mValue; //lookup map of uniform location to last known value std::vector<GLint> mTexture; S32 mTotalUniformSize; S32 mActiveTextureChannels; S32 mShaderLevel; - S32 mShaderGroup; + S32 mShaderGroup; // see LLGLSLShader::eGroup BOOL mUniformsDirty; LLShaderFeatures mFeatures; std::vector< std::pair< std::string, GLenum > > mShaderFiles; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 071912c2c2..028457c510 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -176,7 +176,7 @@ private: protected: void setTexelsPerImage(); - //note: do not make this function public. +public: /*virtual*/ LLImageGL* getGLTexture() const ; protected: diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index aff29bd857..b5e1910242 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -683,7 +683,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) } static LLTrace::BlockTimerStatHandle FTM_SET_IMAGE("setImage"); -BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) +BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) { LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE); bool is_compressed = false; @@ -702,12 +702,11 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) break; } - - if (mUseMipMaps) { //set has mip maps to true before binding image so tex parameters get set properly - gGL.getTexUnit(0)->unbind(mBindTarget); + gGL.getTexUnit(0)->unbind(mBindTarget); + mHasMipMaps = true; mTexOptionsDirty = true; setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); @@ -717,7 +716,8 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) mHasMipMaps = false; } - llverify(gGL.getTexUnit(0)->bind(this)); + gGL.getTexUnit(0)->bind(this, false, false, usename); + if (mUseMipMaps) { @@ -1211,7 +1211,7 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) { if (gGLManager.mInited) { @@ -1381,13 +1381,13 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return FALSE; } - mGLTextureCreated = false ; llassert(gGLManager.mInited); stop_glerror(); if (!imageraw || imageraw->isBufferInvalid()) { LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL; + mGLTextureCreated = false; return FALSE; } @@ -1407,6 +1407,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S if (!setSize(w, h, imageraw->getComponents(), discard_level)) { LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL; + mGLTextureCreated = false; return FALSE; } @@ -1475,6 +1476,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S destroyGLTexture(); mCurrentDiscardLevel = discard_level; mLastBindTime = sLastFrameTime; + mGLTextureCreated = false; return TRUE ; } @@ -1486,104 +1488,123 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)"); BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { - LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); - llassert(data_in); - stop_glerror(); - - if (discard_level < 0) - { - llassert(mCurrentDiscardLevel >= 0); - discard_level = mCurrentDiscardLevel; - } - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); + llassert(data_in); + stop_glerror(); - if (mTexName != 0 && discard_level == mCurrentDiscardLevel) - { - // This will only be true if the size has not changed - return setImage(data_in, data_hasmips); - } - - U32 old_name = mTexName; -// S32 old_discard = mCurrentDiscardLevel; - - if (usename != 0) - { - mTexName = usename; - } - else - { - LLImageGL::generateTextures(1, &mTexName); - stop_glerror(); - { - llverify(gGL.getTexUnit(0)->bind(this)); - stop_glerror(); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); - stop_glerror(); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level); - stop_glerror(); - } - } - if (!mTexName) - { - if (old_name) - { - sGlobalTextureMemory -= mTextureMemory; - LLImageGL::deleteTextures(1, &old_name); - disclaimMem(mTextureMemory); - stop_glerror(); - } + if (discard_level < 0) + { + llassert(mCurrentDiscardLevel >= 0); + discard_level = mCurrentDiscardLevel; + } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - LL_WARNS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL; - return FALSE; - } + if (mTexName != 0 && discard_level == mCurrentDiscardLevel) + { + // This will only be true if the size has not changed + return setImage(data_in, data_hasmips); + } - if (mUseMipMaps) - { - mAutoGenMips = gGLManager.mHasMipMapGeneration; + GLuint old_texname = mTexName; + + if (usename != 0) + { + mNewTexName = usename; + } + else + { + LLImageGL::generateTextures(1, &mNewTexName); + { + gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); + } + } + + if (mUseMipMaps) + { + mAutoGenMips = gGLManager.mHasMipMapGeneration; #if LL_DARWIN - // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. - if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) - { - mAutoGenMips = FALSE; - } + // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. + if (gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) + { + mAutoGenMips = FALSE; + } #endif - } + } - mCurrentDiscardLevel = discard_level; + mCurrentDiscardLevel = discard_level; - if (!setImage(data_in, data_hasmips)) - { - stop_glerror(); - return FALSE; - } + if (!setImage(data_in, data_hasmips, mNewTexName)) + { + return FALSE; + } - // Set texture options to our defaults. - gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); - gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + // Set texture options to our defaults. + gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); + gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - // things will break if we don't unbind after creation - gGL.getTexUnit(0)->unbind(mBindTarget); - stop_glerror(); + // things will break if we don't unbind after creation + gGL.getTexUnit(0)->unbind(mBindTarget); - if (old_name != 0) - { - sGlobalTextureMemory -= mTextureMemory; + if (old_texname != 0) + { + sGlobalTextureMemory -= mTextureMemory; + } - LLImageGL::deleteTextures(1, &old_name); + //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread + if (LLImageGLThread::sInstance != nullptr && + LLThread::currentID() == LLImageGLThread::sInstance->getID()) + { + { + LL_PROFILE_ZONE_NAMED("cglt - sync"); + if (gGLManager.mHasSync) + { + auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glClientWaitSync(sync, 0, 0); + glDeleteSync(sync); + } + else + { + glFinish(); + } + } - stop_glerror(); - } + ref(); + LLImageGLThread::sInstance->postCallback([=]() + { + LL_PROFILE_ZONE_NAMED("cglt - delete callback"); + if (old_texname != 0) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = mNewTexName; + mNewTexName = 0; + unref(); + }); + } + else + { + //not on background thread, immediately set mTexName + if (old_texname != 0) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = mNewTexName; + mNewTexName = 0; + } + + disclaimMem(mTextureMemory); + mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); + claimMem(mTextureMemory); + sGlobalTextureMemory += mTextureMemory; + mTexelsInGLTexture = getWidth() * getHeight(); - disclaimMem(mTextureMemory); - mTextureMemory = (S32Bytes)getMipBytes(discard_level); - claimMem(mTextureMemory); - sGlobalTextureMemory += mTextureMemory; - mTexelsInGLTexture = getWidth() * getHeight() ; + // mark this as bound at this point, so we don't throw it out immediately + mLastBindTime = sLastFrameTime; - // mark this as bound at this point, so we don't throw it out immediately - mLastBindTime = sLastFrameTime; - return TRUE; + return TRUE; } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -2274,17 +2295,7 @@ bool LLImageGLThread::post(const std::function<void()>& func) { try { - if (mFunctionQueue.size() < mFunctionQueue.capacity()) - { - //NOTE: tryPushFront will return immediately if the lock is held - // desired behavior here is to push and return true unless the - // queue is full or closed - mFunctionQueue.pushFront(func); - } - else - { - return false; - } + mFunctionQueue.post(func); } catch (LLThreadSafeQueueInterrupt e) { @@ -2300,7 +2311,7 @@ bool LLImageGLThread::postCallback(const std::function<void()>& callback) { try { - mCallbackQueue.pushFront(callback); + mCallbackQueue.post(callback); } catch (LLThreadSafeQueueInterrupt e) { @@ -2315,34 +2326,14 @@ void LLImageGLThread::executeCallbacks() { LL_PROFILE_ZONE_SCOPED; //executed from main thread - std::function<void()> callback; - while (mCallbackQueue.tryPopBack(callback)) - { - LL_PROFILE_ZONE_NAMED("iglt - callback"); - callback(); - } + mCallbackQueue.runPending(); } void LLImageGLThread::run() { mWindow->makeContextCurrent(mContext); gGL.init(); - try - { - while (true) - { - LL_PROFILE_ZONE_SCOPED; - std::function<void()> curFunc = mFunctionQueue.popBack(); - { - LL_PROFILE_ZONE_NAMED("iglt - function") - curFunc(); - } - } - } - catch (LLThreadSafeQueueInterrupt e) - { - //queue is closed, fall out of run loop - } + mFunctionQueue.runUntilClose(); gGL.shutdown(); mWindow->destroySharedContext(mContext); } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 8e9b483c2d..da626a1093 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,6 +37,8 @@ #include "llunits.h" #include "llthreadsafequeue.h" #include "llrender.h" +#include "workqueue.h" + class LLTextureAtlas ; class LLWindow; @@ -50,7 +52,7 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL> public: // These 2 functions replace glGenTextures() and glDeleteTextures() static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures); + static void deleteTextures(S32 numTextures, const U32 *textures); static void deleteDeadTextures(); // Size calculation @@ -110,7 +112,7 @@ public: S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); - BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE); + BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); @@ -210,8 +212,9 @@ private: bool mGLTextureCreated ; LLGLuint mTexName; + LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread U16 mWidth; - U16 mHeight; + U16 mHeight; S8 mCurrentDiscardLevel; S8 mDiscardLevelInAtlas; @@ -319,8 +322,11 @@ public: void run() override; - LLThreadSafeQueue<std::function<void()>> mFunctionQueue; - LLThreadSafeQueue<std::function<void()>> mCallbackQueue; + // Work Queue for background thread + LL::WorkQueue mFunctionQueue; + + // Work Queue for main thread (run from updateClass) + LL::WorkQueue mCallbackQueue; LLWindow* mWindow; void* mContext; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b6711e44e3..aad04beea2 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -229,8 +229,24 @@ void LLTexUnit::disable(void) } } +void LLTexUnit::bindFast(LLTexture* texture) +{ + LLImageGL* gl_tex = texture->getGLTexture(); + + glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); + gGL.mCurrTextureUnitIndex = mIndex; + mCurrTexture = gl_tex->getTexName(); + if (!mCurrTexture) + { + mCurrTexture = LLImageGL::sDefaultGLTexture->getTexName(); + } + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + mHasMipMaps = gl_tex->mHasMipMaps; +} + bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { + LL_PROFILE_ZONE_SCOPED; stop_glerror(); if (mIndex >= 0) { @@ -294,18 +310,20 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) return true; } -bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) +bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename) { stop_glerror(); if (mIndex < 0) return false; + U32 texname = usename ? usename : texture->getTexName(); + if(!texture) { LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; return false; } - if(!texture->getTexName()) + if(!texname) { if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName()) { @@ -315,7 +333,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) return false ; } - if ((mCurrTexture != texture->getTexName()) || forceBind) + if ((mCurrTexture != texname) || forceBind) { gGL.flush(); stop_glerror(); @@ -323,7 +341,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) stop_glerror(); enable(texture->getTarget()); stop_glerror(); - mCurrTexture = texture->getTexName(); + mCurrTexture = texname; glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); stop_glerror(); texture->updateBindStats(texture->mTextureMemory); @@ -459,6 +477,28 @@ void LLTexUnit::unbind(eTextureType type) } } +void LLTexUnit::unbindFast(eTextureType type) +{ + activate(); + + // Disabled caching of binding state. + if (mCurrTexType == type) + { + mCurrTexture = 0; + + // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". + mTexColorSpace = TCS_LINEAR; + if (type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } + } +} + void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) { if (mIndex < 0 || mCurrTexture == 0) return; @@ -1243,8 +1283,6 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - stop_glerror(); - static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, @@ -1415,8 +1453,6 @@ void LLRender::syncMatrices() } } } - - stop_glerror(); } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1927,6 +1963,7 @@ void LLRender::flush() { if (mCount > 0) { + LL_PROFILE_ZONE_SCOPED; if (!mUIOffset.empty()) { sUICalls++; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index c08c2d6881..7f19a45410 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -158,9 +158,20 @@ public: // Binds the LLImageGL to this texture unit // (automatically enables the unit for the LLImageGL's texture type) - bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false); + bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0); bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false); + // bind implementation for inner loops + // makes the following assumptions: + // - No need for gGL.flush() + // - texture is not null + // - gl_tex->getTexName() is not zero + // - This texture is not being bound redundantly + // - USE_SRGB_DECODE is disabled + // - mTexOptionsDirty is false + // - + void bindFast(LLTexture* texture); + // Binds a cubemap to this texture unit // (automatically enables the texture unit for cubemaps) bool bind(LLCubeMap* cubeMap); @@ -177,6 +188,9 @@ public: // (only if there's a texture of the given type currently bound) void unbind(eTextureType type); + // Fast but unsafe version of unbind + void unbindFast(eTextureType type); + // Sets the addressing mode used to sample the texture // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the address mode for the bound texture. diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 41481fb8a7..256d85ce5a 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -67,11 +67,9 @@ public: virtual S32 getWidth(S32 discard_level = -1) const; virtual S32 getHeight(S32 discard_level = -1) const; virtual bool isActiveFetching(); + virtual LLImageGL* getGLTexture() const; private: - //note: do not make this function public. - virtual LLImageGL* getGLTexture() const; - virtual void updateBindStatsForTester(); }; #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 0449ac392c..7e726df907 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -577,63 +577,22 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } //static -static LLTrace::BlockTimerStatHandle FTM_VB_DRAW_ARRAYS("drawArrays"); -void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) +void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos) { - LL_RECORD_BLOCK_TIME(FTM_VB_DRAW_ARRAYS); - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - gGL.syncMatrices(); - - U32 count = pos.size(); - - llassert(norm.size() >= pos.size()); - llassert(count > 0); - - if( count == 0 ) - { - LL_WARNS() << "Called drawArrays with 0 vertices" << LL_ENDL; - return; - } - - if( norm.size() < pos.size() ) - { - LL_WARNS() << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << LL_ENDL; - return; - } - - unbind(); - - setupClientArrays(MAP_VERTEX | MAP_NORMAL); - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) - { - S32 loc = LLVertexBuffer::TYPE_VERTEX; - if (loc > -1) - { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV); - } - loc = LLVertexBuffer::TYPE_NORMAL; - if (loc > -1) - { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV); - } - } - else - { - glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); - glNormalPointer(GL_FLOAT, 0, norm[0].mV); - } - LLGLSLShader::startProfile(); - LL_PROFILER_GPU_ZONEC( "gl.DrawArrays", 0xFF0000 ) - glDrawArrays(sGLMode[mode], 0, count); - LLGLSLShader::stopProfile(count, mode); + LL_PROFILE_ZONE_SCOPED; + gGL.begin(mode); + for (auto& v : pos) + { + gGL.vertex3fv(v.mV); + } + gGL.end(); + gGL.flush(); } //static void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) { + LL_PROFILE_ZONE_SCOPED; llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); gGL.syncMatrices(); @@ -646,29 +605,27 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto unbind(); - setupClientArrays(mask); - - if (LLGLSLShader::sNoFixedFunction) - { - S32 loc = LLVertexBuffer::TYPE_VERTEX; - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos); - - if (tc) - { - loc = LLVertexBuffer::TYPE_TEXCOORD0; - glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc); - } - } - else - { - glTexCoordPointer(2, GL_FLOAT, 0, tc); - glVertexPointer(3, GL_FLOAT, 16, pos); - } - - LLGLSLShader::startProfile(); - LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x80FF80 ) - glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp); - LLGLSLShader::stopProfile(num_indices, mode); + gGL.begin(mode); + + if (tc != nullptr) + { + for (int i = 0; i < num_indices; ++i) + { + U16 idx = indicesp[i]; + gGL.texCoord2fv(tc[idx].mV); + gGL.vertex3fv(pos[idx].getF32ptr()); + } + } + else + { + for (int i = 0; i < num_indices; ++i) + { + U16 idx = indicesp[i]; + gGL.vertex3fv(pos[idx].getF32ptr()); + } + } + gGL.end(); + gGL.flush(); } void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const @@ -787,6 +744,18 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi placeFence(); } +void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const +{ + mMappable = false; + gGL.syncMatrices(); + + U16* idx = ((U16*)(U8*)mAlignedIndexOffset) + indices_offset; + + LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00) + glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, + idx); +} + void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); @@ -839,51 +808,51 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const static LLTrace::BlockTimerStatHandle FTM_GL_DRAW_ARRAYS("GL draw arrays"); void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = false; - gGL.syncMatrices(); - - llassert(mNumVerts >= 0); - if (first >= (U32) mNumVerts || - first + count > (U32) mNumVerts) - { - LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << LL_ENDL; - } - - if (mGLArray) - { - if (mGLArray != sGLRenderArray) - { - LL_ERRS() << "Wrong vertex array bound." << LL_ENDL; - } - } - else - { - if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) - { - LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; - } - } - - if (mode >= LLRender::NUM_MODES) - { - LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL; - return; - } - - { - LL_RECORD_BLOCK_TIME(FTM_GL_DRAW_ARRAYS); - stop_glerror(); - LLGLSLShader::startProfile(); - stop_glerror(); - LL_PROFILER_GPU_ZONEC( "gl.DrawArrays", 0xFF4040 ) - glDrawArrays(sGLMode[mode], first, count); - stop_glerror(); - LLGLSLShader::stopProfile(count, mode); - } - - stop_glerror(); - placeFence(); + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + mMappable = false; + gGL.syncMatrices(); + + llassert(mNumVerts >= 0); + if (first >= (U32)mNumVerts || + first + count > (U32)mNumVerts) + { + LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first + count << "]" << LL_ENDL; + } + + if (mGLArray) + { + if (mGLArray != sGLRenderArray) + { + LL_ERRS() << "Wrong vertex array bound." << LL_ENDL; + } + } + else + { + if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) + { + LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; + } + } + + if (mode >= LLRender::NUM_MODES) + { + LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL; + return; + } + + { + LL_RECORD_BLOCK_TIME(FTM_GL_DRAW_ARRAYS); + stop_glerror(); + LLGLSLShader::startProfile(); + stop_glerror(); + LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040) + glDrawArrays(sGLMode[mode], first, count); + stop_glerror(); + LLGLSLShader::stopProfile(count, mode); + } + + stop_glerror(); + placeFence(); } //static @@ -2272,6 +2241,21 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) return ret; } +bool LLVertexBuffer::bindGLBufferFast() +{ + if (mGLBuffer != sGLRenderBuffer || !sVBOActive) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + sBindCount++; + sVBOActive = true; + + return true; + } + + return false; +} + static LLTrace::BlockTimerStatHandle FTM_BIND_GL_INDICES("Bind Indices"); bool LLVertexBuffer::bindGLIndices(bool force_bind) @@ -2297,6 +2281,21 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind) return ret; } +bool LLVertexBuffer::bindGLIndicesFast() +{ + if (mGLIndices != sGLRenderIndices || !sIBOActive) + { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); + sGLRenderIndices = mGLIndices; + sBindCount++; + sIBOActive = true; + + return true; + } + + return false; +} + void LLVertexBuffer::flush() { if (useVBOs()) @@ -2487,6 +2486,26 @@ void LLVertexBuffer::setBuffer(U32 data_mask) } } +void LLVertexBuffer::setBufferFast(U32 data_mask) +{ + //set up pointers if the data mask is different ... + bool setup = (sLastMask != data_mask); + + + const bool bindBuffer = bindGLBufferFast(); + const bool bindIndices = bindGLIndicesFast(); + + setup = setup || bindBuffer || bindIndices; + + setupClientArrays(data_mask); + + if (data_mask && setup) + { + setupVertexBufferFast(data_mask); + sSetCount++; + } +} + // virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { @@ -2644,6 +2663,99 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) llglassertok(); } +void LLVertexBuffer::setupVertexBufferFast(U32 data_mask) +{ + U8* base = (U8*)mAlignedOffset; + + if (data_mask & MAP_NORMAL) + { + S32 loc = TYPE_NORMAL; + void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); + } + if (data_mask & MAP_TEXCOORD3) + { + S32 loc = TYPE_TEXCOORD3; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); + } + if (data_mask & MAP_TEXCOORD2) + { + S32 loc = TYPE_TEXCOORD2; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + } + if (data_mask & MAP_TEXCOORD1) + { + S32 loc = TYPE_TEXCOORD1; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); + } + if (data_mask & MAP_TANGENT) + { + S32 loc = TYPE_TANGENT; + void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + } + if (data_mask & MAP_TEXCOORD0) + { + S32 loc = TYPE_TEXCOORD0; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + } + if (data_mask & MAP_COLOR) + { + S32 loc = TYPE_COLOR; + //bind emissive instead of color pointer if emissive is present + void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + } + if (data_mask & MAP_EMISSIVE) + { + S32 loc = TYPE_EMISSIVE; + void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + + if (!(data_mask & MAP_COLOR)) + { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps + loc = TYPE_COLOR; + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + } + } + if (data_mask & MAP_WEIGHT) + { + S32 loc = TYPE_WEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); + glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + } + if (data_mask & MAP_WEIGHT4) + { + S32 loc = TYPE_WEIGHT4; + void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + } + if (data_mask & MAP_CLOTHWEIGHT) + { + S32 loc = TYPE_CLOTHWEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + } + if (data_mask & MAP_TEXTURE_INDEX) + { +#if !LL_DARWIN + S32 loc = TYPE_TEXTURE_INDEX; + void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); +#endif + } + if (data_mask & MAP_VERTEX) + { + S32 loc = TYPE_VERTEX; + void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + } +} + LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count) : mType(type), mIndex(index), mCount(count) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 1d60970df4..fad474a143 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -146,8 +146,7 @@ public: static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); - static void pushPositions(U32 mode, const LLVector4a* pos, U32 count); - static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); + static void drawArrays(U32 mode, const std::vector<LLVector3>& pos); static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); static void unbind(); //unbind any bound vertex buffer @@ -210,13 +209,17 @@ protected: virtual ~LLVertexBuffer(); // use unref() - virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer() + virtual void setupVertexBuffer(U32 data_mask); + void setupVertexBufferFast(U32 data_mask); + void setupVertexArray(); void genBuffer(U32 size); void genIndices(U32 size); bool bindGLBuffer(bool force_bind = false); + bool bindGLBufferFast(); bool bindGLIndices(bool force_bind = false); + bool bindGLIndicesFast(); bool bindGLArray(); void releaseBuffer(); void releaseIndices(); @@ -239,6 +242,8 @@ public: // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 + void setBufferFast(U32 data_mask); // calls setupVertexBufferFast(), assumes data_mask is not 0 among other assumptions + void flush(); //flush pending data to GL memory // allocate buffer bool allocateBuffer(S32 nverts, S32 nindices, bool create); @@ -290,6 +295,9 @@ public: void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //implementation for inner loops that does no safety checking + void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //for debugging, validate data in given range is valid void validateRange(U32 start, U32 end, U32 count, U32 offset) const; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2672d600c6..306760b7fb 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -346,6 +346,8 @@ public: // handle refocusing. static void closeFrontmostFloater(); + static bool isQuitRequested() { return sQuitting; } + // LLNotification::Params contextualNotification(const std::string& name) // { // return LLNotification::Params(name).context(mNotificationContext); diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 30bc743e72..67ef98d7b3 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -137,6 +137,12 @@ BOOL LLWindow::canDelete() return TRUE; } +//virtual +void LLWindow::setTitle(const std::string title) +{ + // the action happens in the platform specific impl +} + // virtual void LLWindow::incBusyCount() { diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0100c3bf0a..b76d313011 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -91,12 +91,22 @@ public: virtual BOOL setCursorPosition(LLCoordWindow position) = 0; virtual BOOL getCursorPosition(LLCoordWindow *position) = 0; +#if LL_WINDOWS + virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0; +#endif virtual void showCursor() = 0; virtual void hideCursor() = 0; virtual BOOL isCursorHidden() = 0; virtual void showCursorFromMouseMove() = 0; virtual void hideCursorUntilMouseMove() = 0; + // Provide a way to set the Viewer window title after the + // windows has been created. The initial use case for this + // is described in SL-16102 (update window title with agent + // name, location etc. for non-interactive viewer) but it + // may also be useful in other cases. + virtual void setTitle(const std::string title); + // These two functions create a way to make a busy cursor instead // of an arrow when someone's busy doing something. Draw an // arrow/hour if busycount > 0. diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index a7ae28aa24..f8ba9bbed4 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -54,6 +54,9 @@ public: void destroySharedContext(void*) {} /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; +#if LL_WINDOWS + /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; } +#endif /*virtual*/ void showCursor() {}; /*virtual*/ void hideCursor() {}; /*virtual*/ void showCursorFromMouseMove() {}; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 12d4c6c30e..26bb56d72d 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -28,8 +28,6 @@ #if LL_WINDOWS && !LL_MESA_HEADLESS -#define LL_WINDOW_SINGLE_THREADED 0 - #include "llwindowwin32.h" // LLWindow library includes @@ -85,7 +83,7 @@ extern BOOL gDebugWindowProc; static std::thread::id sWindowThreadId; static std::thread::id sMainThreadId; -#if 1 || LL_WINDOW_SINGLE_THREADED +#if 1 // flip to zero to enable assertions for functions being called from wrong thread #define ASSERT_MAIN_THREAD() #define ASSERT_WINDOW_THREAD() #else @@ -482,9 +480,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, { sMainThreadId = LLThread::currentID(); mWindowThread = new LLWindowWin32Thread(this); -#if !LL_WINDOW_SINGLE_THREADED mWindowThread->start(); -#endif //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -492,7 +488,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mIconResource = gIconResource; mOverrideAspectRatio = 0.f; mNativeAspectRatio = 0.f; - mMousePositionModified = FALSE; mInputProcessingPaused = FALSE; mPreeditor = NULL; mKeyCharCode = 0; @@ -814,6 +809,13 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, initCursors(); setCursor( UI_CURSOR_ARROW ); + mRawMouse.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + mRawMouse.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE + mRawMouse.dwFlags = 0; // adds mouse and also ignores legacy mouse messages + mRawMouse.hwndTarget = 0; + + RegisterRawInputDevices(&mRawMouse, 1, sizeof(mRawMouse)); + // Initialize (boot strap) the Language text input management, // based on the system's (or user's) default settings. allowLanguageTextInput(NULL, FALSE); @@ -1923,35 +1925,37 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); } +void LLWindowWin32::setTitle(const std::string title) +{ + // TODO: Do we need to use the wide string version of this call + // to support non-ascii usernames (and region names?) + SetWindowTextA(mWindowHandle, title.c_str()); +} + BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { ASSERT_MAIN_THREAD(); - if (!mWindowHandle) - { - return FALSE; - } + if (!mWindowHandle) + { + return FALSE; + } - // Inform the application of the new mouse position (needed for per-frame - // hover/picking to function). - mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); - - mMousePositionModified = TRUE; LLCoordScreen screen_pos(position.convert()); - - mWindowThread->post([=] + + // instantly set the cursor position from the app's point of view + mCursorPosition = position; + mLastCursorPosition = position; + + // Inform the application of the new mouse position (needed for per-frame + // hover/picking to function). + mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); + + // actually set the cursor position on the window thread + mWindowThread->post([=]() { + // actually set the OS cursor position SetCursorPos(screen_pos.mX, screen_pos.mY); - // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. - // Because we have preemptively notified the application of the new - // mouse position via handleMouseMove() above, we need to clear out - // any stale mouse move events. RN/JC - MSG msg; - while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - { - } - - mMousePositionModified = FALSE; }); return TRUE; @@ -1960,19 +1964,27 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) { ASSERT_MAIN_THREAD(); - POINT cursor_point; - - if (!mWindowHandle - || !GetCursorPos(&cursor_point) - || !position) - { - return FALSE; - } + if (!position) + { + return FALSE; + } - *position = LLCoordScreen(cursor_point.x, cursor_point.y).convert(); + *position = mCursorPosition; return TRUE; } +BOOL LLWindowWin32::getCursorDelta(LLCoordCommon* delta) +{ + if (delta == nullptr) + { + return FALSE; + } + + *delta = mMouseFrameDelta; + + return TRUE; +} + void LLWindowWin32::hideCursor() { ASSERT_MAIN_THREAD(); @@ -2153,34 +2165,31 @@ void LLWindowWin32::gatherInput() LL_PROFILE_ZONE_SCOPED MSG msg; -#if LL_WINDOW_SINGLE_THREADED - int msg_count = 0; - - while ((msg_count < MAX_MESSAGE_PER_UPDATE)) { - LL_PROFILE_ZONE_NAMED("gi - loop"); - ++msg_count; - { - LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); - if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - break; - } - } + LLMutexLock lock(&mRawMouseMutex); + mMouseFrameDelta = mRawMouseDelta; - { - LL_PROFILE_ZONE_NAMED("gi - translate"); - TranslateMessage(&msg); - } + mRawMouseDelta.mX = 0; + mRawMouseDelta.mY = 0; + } - { - LL_PROFILE_ZONE_NAMED("gi - dispatch"); - DispatchMessage(&msg); - } + if (mWindowThread->mFunctionQueue.size() > 0) + { + LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + if (mWindowHandle) + { // post a nonsense user message to wake up the Window Thread in case any functions are pending + // and no windows events came through this frame + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } + } + + while (mWindowThread->mMessageQueue.tryPopBack(msg)) + { + LL_PROFILE_ZONE_NAMED("gi - message queue"); if (mInputProcessingPaused) { - break; + continue; } // For async host by name support. Really hacky. @@ -2190,45 +2199,35 @@ void LLWindowWin32::gatherInput() gAsyncMsgCallback(msg); } } -#else //multi-threaded window impl + { - if (mWindowThread->mFunctionQueue.size() > 0) + LL_PROFILE_ZONE_NAMED("gi - function queue"); + //process any pending functions + std::function<void()> curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) { - LL_PROFILE_ZONE_NAMED("gi - PostMessage"); - if (mWindowHandle) - { // post a nonsense user message to wake up the Window Thread in case any functions are pending - // and no windows events came through this frame - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - } + curFunc(); } - - while (mWindowThread->mMessageQueue.tryPopBack(msg)) - { - LL_PROFILE_ZONE_NAMED("gi - message queue"); - if (mInputProcessingPaused) - { - continue; - } + } - // For async host by name support. Really hacky. - if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) - { - LL_PROFILE_ZONE_NAMED("gi - callback"); - gAsyncMsgCallback(msg); - } - } + // send one and only one mouse move event per frame BEFORE handling mouse button presses + if (mLastCursorPosition != mCursorPosition) + { + LL_PROFILE_ZONE_NAMED("gi - mouse move"); + mCallbacks->handleMouseMove(this, mCursorPosition.convert(), mMouseMask); } + + mLastCursorPosition = mCursorPosition; { - LL_PROFILE_ZONE_NAMED("gi - function queue"); - //process any pending functions + LL_PROFILE_ZONE_NAMED("gi - mouse queue"); + // handle mouse button presses AFTER updating mouse cursor position std::function<void()> curFunc; - while (mFunctionQueue.tryPopBack(curFunc)) + while (mMouseQueue.tryPopBack(curFunc)) { curFunc(); } } -#endif mInputProcessingPaused = FALSE; @@ -2238,11 +2237,7 @@ void LLWindowWin32::gatherInput() static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); -#if LL_WINDOW_SINGLE_THREADED -#define WINDOW_IMP_POST(x) x -#else #define WINDOW_IMP_POST(x) window_imp->post([=]() { x; }) -#endif LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { @@ -2278,10 +2273,6 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // mouse is outside window. LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - // This doesn't work, as LOWORD returns unsigned short. - //LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); - LLCoordGL gl_coord; - // pass along extended flag in mask MASK mask = (l_param >> 16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; BOOL eat_keystroke = TRUE; @@ -2665,35 +2656,19 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - auto glc = gl_coord; sHandleLeftMouseUp = true; - + if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); } - - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - glc = cursor_coord_window.convert(); - } - else - { - glc = window_coord.convert(); - } + MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); - window_imp->mCallbacks->handleMouseDown(window_imp, glc, mask); + auto gl_coord = window_imp->mCursorPosition.convert(); + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask); }); return 0; @@ -2704,77 +2679,43 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONDBLCLK: { LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDBLCLK"); - //RN: ignore right button double clicks for now - //case WM_RBUTTONDBLCLK: - if (!sHandleDoubleClick) - { - sHandleDoubleClick = true; - return 0; - } - - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask); + //RN: ignore right button double clicks for now + //case WM_RBUTTONDBLCLK: + if (!sHandleDoubleClick) + { + sHandleDoubleClick = true; + return; + } + MASK mask = gKeyboard->currentMask(TRUE); + + // generate move event to update mouse coordinates + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleDoubleClick(window_imp, window_imp->mCursorPosition.convert(), mask); }); + return 0; } case WM_LBUTTONUP: { LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONUP"); { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - - if (!sHandleLeftMouseUp) - { - sHandleLeftMouseUp = true; - return 0; - } - sHandleDoubleClick = true; - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - auto glc = gl_coord; - - //if (gDebugClicks) - //{ - // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; - //} - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - glc = cursor_coord_window.convert(); - } - else + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + if (!sHandleLeftMouseUp) { - glc = window_coord.convert(); + sHandleLeftMouseUp = true; + return; } + sHandleDoubleClick = true; + + MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); - window_imp->mCallbacks->handleMouseUp(window_imp, glc, mask); + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); }); } return 0; @@ -2785,30 +2726,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); - } - - // Because we move the cursor position in the llviewerapp, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates window_imp->post([=]() { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); + } + + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + auto gl_coord = window_imp->mCursorPosition.convert(); window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask); }); @@ -2822,28 +2749,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleRightMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; @@ -2854,33 +2764,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + window_imp->postMouseButtonEvent([=]() + { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; @@ -2890,99 +2783,47 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; case WM_XBUTTONDOWN: { LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONDOWN"); - { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) + window_imp->postMouseButtonEvent([=]() { - window_imp->interruptLanguageTextInput(); - } + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + S32 button = GET_XBUTTON_WPARAM(w_param); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); + } break; case WM_XBUTTONUP: { LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONUP"); - { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else + window_imp->postMouseButtonEvent([=]() { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } + + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + + S32 button = GET_XBUTTON_WPARAM(w_param); + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); } break; @@ -3022,7 +2863,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // large deltas, like 480 or so. Thus we need to scroll more quickly. if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) { - window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); + short clicks = -z_delta / WHEEL_DELTA; + WINDOW_IMP_POST(window_imp->mCallbacks->handleScrollWheel(window_imp, clicks)); z_delta = 0; } return 0; @@ -3082,11 +2924,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MOUSEMOVE: { LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE"); - if (!window_imp->mMousePositionModified) - { - MASK mask = gKeyboard->currentMask(TRUE); - WINDOW_IMP_POST(window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask)); - } + // DO NOT use mouse event queue for move events to ensure cursor position is updated + // when button events are handled + WINDOW_IMP_POST( + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE lambda"); + + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mMouseMask = mask; + window_imp->mCursorPosition = window_coord; + }); return 0; } @@ -3235,6 +3082,28 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } break; + case WM_INPUT: + { + LL_PROFILE_ZONE_NAMED("MWP - WM_INPUT"); + + UINT dwSize = 0; + GetRawInputData((HRAWINPUT)l_param, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + llassert(dwSize < 1024); + + U8 lpb[1024]; + + if (GetRawInputData((HRAWINPUT)l_param, RID_INPUT, (void*)lpb, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize) + { + RAWINPUT* raw = (RAWINPUT*)lpb; + + if (raw->header.dwType == RIM_TYPEMOUSE) + { + LLMutexLock lock(&window_imp->mRawMouseMutex); + window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; + window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + } + } + } //list of messages we get often that we don't care to log about case WM_NCHITTEST: case WM_NCMOUSEMOVE: @@ -4740,18 +4609,16 @@ inline void LLWindowWin32Thread::run() void LLWindowWin32Thread::post(const std::function<void()>& func) { -#if LL_WINDOW_SINGLE_THREADED - func(); -#else mFunctionQueue.pushFront(func); -#endif } void LLWindowWin32::post(const std::function<void()>& func) { -#if LL_WINDOW_SINGLE_THREADED - func(); -#else mFunctionQueue.pushFront(func); -#endif } + +void LLWindowWin32::postMouseButtonEvent(const std::function<void()>& func) +{ + mMouseQueue.pushFront(func); +} + diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 5f253b5df3..7a9a30ccea 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -35,6 +35,7 @@ #include "lldragdropwin32.h" #include "llthread.h" #include "llthreadsafequeue.h" +#include "llmutex.h" // Hack for async host by name #define LL_WM_HOST_RESOLVED (WM_APP + 1) @@ -93,11 +94,13 @@ public: /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); + /*virtual*/ void setTitle(const std::string title); void* createSharedContext() override; void makeContextCurrent(void* context) override; void destroySharedContext(void* context) override; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); + /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta); /*virtual*/ void showCursor(); /*virtual*/ void hideCursor(); /*virtual*/ void showCursorFromMouseMove(); @@ -221,6 +224,14 @@ protected: F32 mNativeAspectRatio; HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors + LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread + LLMutex mRawMouseMutex; + RAWINPUTDEVICE mRawMouse; + LLCoordWindow mLastCursorPosition; // mouse cursor position from previous frame + LLCoordCommon mRawMouseDelta; // raw mouse delta according to window thread + LLCoordCommon mMouseFrameDelta; // how much the mouse moved between the last two calls to gatherInput + + MASK mMouseMask; static BOOL sIsClassRegistered; // has the window class been registered? @@ -231,7 +242,6 @@ protected: BOOL mCustomGammaSet; LPWSTR mIconResource; - BOOL mMousePositionModified; BOOL mInputProcessingPaused; // The following variables are for Language Text Input control. @@ -261,7 +271,9 @@ protected: LLWindowWin32Thread* mWindowThread = nullptr; LLThreadSafeQueue<std::function<void()>> mFunctionQueue; + LLThreadSafeQueue<std::function<void()>> mMouseQueue; void post(const std::function<void()>& func); + void postMouseButtonEvent(const std::function<void()>& func); friend class LLWindowManager; friend class LLWindowWin32Thread; diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 4e186292f7..7514913d13 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -217,6 +217,14 @@ <string>NoInventoryLibrary</string> </map> + <key>noninteractive</key> + <map> + <key>desc</key> + <string>Run in semi-headless mode where only login and logout need to work.</string> + <key>map-to</key> + <string>NonInteractive</string> + </map> + <key>nonotifications</key> <map> <key>desc</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index eeadea76a2..aeeba58a68 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7015,6 +7015,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>NonInteractive</key> + <map> + <key>Comment</key> + <string>Run in a semi-headless mode where only logging in and logging out needs to work.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>NonvisibleObjectsInMemoryTime</key> <map> <key>Comment</key> @@ -16644,6 +16655,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>UpdateAppWindowTitleBar</key> + <map> + <key>Comment</key> + <string>Updates the application window title bar with brief information about user/location</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 389448654a..b35eef20f7 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1481,7 +1481,7 @@ void LLAgent::resetControlFlags() //----------------------------------------------------------------------------- void LLAgent::setAFK() { - if (!gAgent.getRegion()) + if (gNonInteractive || !gAgent.getRegion()) { // Don't set AFK if we're not talking to a region yet. return; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 691c3f3798..400a6a722b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -864,8 +864,6 @@ bool LLAppViewer::init() LLNotifications::instance(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; - writeSystemInfo(); - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -986,6 +984,9 @@ bool LLAppViewer::init() initWindow(); LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; + // writeSystemInfo can be called after window is initialized (gViewerWindow non-null) + writeSystemInfo(); + // initWindow also initializes the Feature List, so now we can initialize this global. LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); @@ -1555,6 +1556,14 @@ bool LLAppViewer::doFrame() ms_sleep(yield_time); } + if (gNonInteractive) + { + S32 non_interactive_ms_sleep_time = 100; + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); + ms_sleep(non_interactive_ms_sleep_time); + } + // yield cooperatively when not running as foreground window // and when not quiting (causes trouble at mac's cleanup stage) if (!LLApp::isExiting() @@ -1562,8 +1571,8 @@ bool LLAppViewer::doFrame() || !gFocusMgr.getAppHasFocus())) { // Sleep if we're not rendering, or the window is minimized. - static LLCachedControl<S32> s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40); - S32 milliseconds_to_sleep = llclamp((S32)s_bacground_yeild_time, 0, 1000); + static LLCachedControl<S32> s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40); + S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000); // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads // of equal priority on Windows if (milliseconds_to_sleep > 0) @@ -2440,6 +2449,38 @@ namespace } } // anonymous namespace +// Set a named control temporarily for this session, as when set via the command line --set option. +// Name can be specified as "<control_group>.<control_name>", with default group being Global. +bool tempSetControl(const std::string& name, const std::string& value) +{ + std::string name_part; + std::string group_part; + LLControlVariable* control = NULL; + + // Name can be further split into ControlGroup.Name, with the default control group being Global + size_t pos = name.find('.'); + if (pos != std::string::npos) + { + group_part = name.substr(0, pos); + name_part = name.substr(pos+1); + LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; + auto g = LLControlGroup::getInstance(group_part); + if (g) control = g->getControl(name_part); + } + else + { + LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; + control = gSavedSettings.getControl(name); + } + + if (control) + { + control->setValue(value, false); + return true; + } + return false; +} + bool LLAppViewer::initConfiguration() { //Load settings files list @@ -2596,9 +2637,10 @@ bool LLAppViewer::initConfiguration() disableCrashlogger(); } + gNonInteractive = gSavedSettings.getBOOL("NonInteractive"); // Handle initialization from settings. // Start up the debugging console before handling other options. - if (gSavedSettings.getBOOL("ShowConsoleWindow")) + if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive) { initConsole(); } @@ -2631,33 +2673,9 @@ bool LLAppViewer::initConfiguration() { const std::string& name = *itr; const std::string& value = *(++itr); - std::string name_part; - std::string group_part; - LLControlVariable* control = NULL; - - // Name can be further split into ControlGroup.Name, with the default control group being Global - size_t pos = name.find('.'); - if (pos != std::string::npos) - { - group_part = name.substr(0, pos); - name_part = name.substr(pos+1); - LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; - auto g = LLControlGroup::getInstance(group_part); - if (g) control = g->getControl(name_part); - } - else - { - LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; - control = gSavedSettings.getControl(name); - } - - if (control) + if (!tempSetControl(name,value)) { - control->setValue(value, false); - } - else - { - LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL; + LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL; } } } @@ -2743,6 +2761,19 @@ bool LLAppViewer::initConfiguration() } } + if (gNonInteractive) + { + tempSetControl("AllowMultipleViewers", "TRUE"); + tempSetControl("SLURLPassToOtherInstance", "FALSE"); + tempSetControl("RenderWater", "FALSE"); + tempSetControl("FlyingAtExit", "FALSE"); + tempSetControl("WindowWidth", "1024"); + tempSetControl("WindowHeight", "200"); + LLError::setEnabledLogTypesMask(0); + llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance")); + } + + // Handle slurl use. NOTE: Don't let SL-55321 reappear. // This initial-SLURL logic, up through the call to // sendURLToOtherInstance(), must precede LLSplashScreen::show() -- @@ -3510,12 +3541,15 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin()); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); - - std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList(); - for (auto res_iter : resolutions) - { - gDebugInfo["DisplayInfo"].append(res_iter); - } + + if (gViewerWindow) + { + std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList(); + for (auto res_iter : resolutions) + { + gDebugInfo["DisplayInfo"].append(res_iter); + } + } writeDebugInfo(); // Save out debug_info.log early, in case of crash. } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 758bd73cb0..9074e6a6cf 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -325,7 +325,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, { // Call Tracy first thing to have it allocate memory // https://github.com/wolfpld/tracy/issues/196 - LL_PROFILER_FRAME_END + LL_PROFILER_FRAME_END; + LL_PROFILER_SET_THREAD_NAME("App"); const S32 MAX_HEAPS = 255; DWORD heap_enable_lfh_error[MAX_HEAPS]; diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 6d20b23e9f..9ee9900eba 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -257,7 +257,6 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) LLAvatarName av_name; LLAvatarNameCache::get(agent_id, &av_name); - addChangedMask(LLFriendObserver::ADD, agent_id); LL_DEBUGS() << "Added buddy " << agent_id << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline") << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo() @@ -493,6 +492,7 @@ void LLAvatarTracker::notifyObservers() // new masks and ids will be processed later from idle. return; } + LL_PROFILE_ZONE_SCOPED mIsNotifyObservers = TRUE; observer_list_t observers(mObservers); @@ -678,6 +678,7 @@ void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**) void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) { + LL_PROFILE_ZONE_SCOPED S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock); BOOL chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification"); @@ -712,8 +713,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) // we were tracking someone who went offline deleteTrackingData(); } - // *TODO: get actual inventory id - gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null); } if(chat_notify) { diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 30c4a21e1c..495e06b6f7 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -234,8 +234,6 @@ void LLDrawable::markDead() LLVOVolume* LLDrawable::getVOVolume() const { - LL_PROFILE_ZONE_SCOPED - LLViewerObject* objectp = mVObjp; if ( !isDead() && objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) { diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index d583a692f9..3e4f97e494 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -404,6 +404,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures) void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; @@ -452,6 +453,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; if (!params.mCount) { return; @@ -469,7 +471,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { if (params.mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); } } } @@ -477,8 +479,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { //not batching textures or batch has only 1 texture -- might need a texture matrix if (params.mTexture.notNull()) { - params.mTexture->addTextureStats(params.mVSize); - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + gGL.getTexUnit(0)->bindFast(params.mTexture); if (params.mTextureMatrix) { tex_setup = true; @@ -490,24 +491,20 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); } } } - if (params.mVertexBuffer.notNull()) - { - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); - - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - } + LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); + + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); if (tex_setup) { diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 4ee08e869a..369d7a6bb8 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -55,19 +55,7 @@ static BOOL deferred_render = FALSE; static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup"); static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup"); LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), @@ -86,6 +74,10 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha() void LLDrawPoolAlpha::prerender() { mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + + // TODO: is this even necessay? These are probably set to never discard + LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f); + LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f); } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() @@ -309,7 +301,7 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.diffuseColor4f(1,0,0,1); LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; + gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep); renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); @@ -358,9 +350,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { params.mGroup->rebuildMesh(); } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); } } } @@ -383,27 +374,23 @@ inline bool IsEmissive(LLDrawInfo& params) inline void Draw(LLDrawInfo* draw, U32 mask) { - draw->mVertexBuffer->setBuffer(mask); + draw->mVertexBuffer->setBufferFast(mask); LLRenderPass::applyModelMatrix(*draw); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } -bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader) +bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS); - bool tex_setup = false; if (deferred_render && use_material && current_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); if (draw->mNormalMap) - { + { draw->mNormalMap->addTextureStats(draw->mVSize); current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); } - + if (draw->mSpecularMap) { draw->mSpecularMap->addTextureStats(draw->mVSize); @@ -412,18 +399,16 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate } else if (current_shader == simple_shader) { - LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize); - LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); } - if (use_shaders && draw->mTextureList.size() > 1) + if (draw->mTextureList.size() > 1) { for (U32 i = 0; i < draw->mTextureList.size(); ++i) { if (draw->mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]); } } } @@ -431,16 +416,15 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate { //not batching textures or batch has only 1 texture -- might need a texture matrix if (draw->mTexture.notNull()) { - draw->mTexture->addTextureStats(draw->mVSize); - if (use_shaders && use_material) + if (use_material) { current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture); } else { - gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ; + gGL.getTexUnit(0)->bindFast(draw->mTexture); } - + if (draw->mTextureMatrix) { tex_setup = true; @@ -452,7 +436,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); } } @@ -470,37 +454,15 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup) } } -void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples) -{ - gPipeline.enableLightsDynamic(); - simple_shader->bind(); - simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); - simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); - simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); - simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); - simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : simples) - { - bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); - RestoreTexSetup(tex_setup); - } - simple_shader->unbind(); -} - void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights) { gPipeline.enableLightsFullbright(); fullbright_shader->bind(); fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); + for (LLDrawInfo* draw : fullbrights) { - bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader); + bool tex_setup = TexSetup(draw, false, fullbright_shader); LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); @@ -511,65 +473,10 @@ void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& full fullbright_shader->unbind(); } -void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials) -{ - LLGLSLShader::bindNoShader(); - current_shader = NULL; - - gPipeline.enableLightsDynamic(); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : materials) - { - U32 mask = draw->mShaderMask; - - llassert(mask < LLMaterial::SHADER_COUNT); - target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]); - - if (current_shader != target_shader) - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); - if (current_shader) - { - gPipeline.unbindDeferredShader(*current_shader); - } - gPipeline.bindDeferredShader(*target_shader); - current_shader = target_shader; - } - - bool tex_setup = TexSetup(draw, use_shaders, true, current_shader); - - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]); - current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity); - current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f); - - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); - if (draw->mNormalMap) - { - draw->mNormalMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); - } - - if (draw->mSpecularMap) - { - draw->mSpecularMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap); - } - } - - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); - RestoreTexSetup(tex_setup); - } -} - void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw) { - draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); + draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw) @@ -599,10 +506,10 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi // install glow-accumulating blend mode // don't touch color, add to alpha (glow) gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); - bool use_shaders = gPipeline.canUseVertexShaders(); + for (LLDrawInfo* draw : emissives) { - bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader); + bool tex_setup = TexSetup(draw, false, emissive_shader); drawEmissive(mask, draw); RestoreTexSetup(tex_setup); } @@ -620,8 +527,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - BOOL use_shaders = gPipeline.canUseVertexShaders(); - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; @@ -631,8 +536,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { - std::vector<LLDrawInfo*> emissives; - std::vector<LLDrawInfo*> fullbrights; + static std::vector<LLDrawInfo*> emissives; + static std::vector<LLDrawInfo*> fullbrights; + emissives.resize(0); + fullbrights.resize(0); bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; @@ -649,6 +556,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { + LL_PROFILE_ZONE_NAMED("ra - push batch") LLDrawInfo& params = **k; U32 have_mask = params.mVertexBuffer->getTypeMask() & mask; if (have_mask != mask) @@ -696,34 +604,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) // Turn off lighting if it hasn't already been so. if (light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = fullbright_shader; - } - else - { - gPipeline.enableLightsFullbright(); - } + target_shader = fullbright_shader; + light_enabled = FALSE; } } // Turn on lighting if it isn't already. else if (!light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } + target_shader = simple_shader; light_enabled = TRUE; } @@ -741,7 +632,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (current_shader != target_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); gPipeline.bindDeferredShader(*target_shader); current_shader = target_shader; } @@ -755,25 +645,19 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) target_shader = fullbright_shader; } - if(use_shaders && (current_shader != target_shader)) + if(current_shader != target_shader) {// If we need shaders, and we're not ALREADY using the proper shader, then bind it // (this way we won't rebind shaders unnecessarily). - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS); current_shader = target_shader; current_shader->bind(); } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } LLVector4 spec_color(1, 1, 1, 1); F32 env_intensity = 0.0f; F32 brightness = 1.0f; // We have a material. Supply the appropriate data here. - if (use_shaders && mat && deferred_render) + if (mat && deferred_render) { spec_color = params.mSpecColor; env_intensity = params.mEnvIntensity; @@ -792,20 +676,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) params.mGroup->rebuildMesh(); } - bool tex_setup = TexSetup(¶ms, use_shaders, use_shaders && (mat != nullptr), current_shader); + bool tex_setup = TexSetup(¶ms, (mat != nullptr), current_shader); { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); + params.mVertexBuffer->setBufferFast(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); } } @@ -814,8 +694,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) draw_glow_for_this_partition && params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE); - if (batch_emissives) { emissives.push_back(¶ms); @@ -835,19 +713,29 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } } + + bool rebind = false; if (batch_fullbrights) { - light_enabled = false; - renderFullbrights(mask, fullbrights); + if (!fullbrights.empty()) + { + light_enabled = false; + renderFullbrights(mask, fullbrights); + rebind = true; + } } if (batch_emissives) { - light_enabled = true; - renderEmissives(mask, emissives); + if (!emissives.empty()) + { + light_enabled = true; + renderEmissives(mask, emissives); + rebind = true; + } } - if (current_shader) + if (current_shader && rebind) { current_shader->bind(); } diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index a069f805e8..a50b1d929e 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -75,15 +75,13 @@ private: LLGLSLShader* fullbright_shader; LLGLSLShader* emissive_shader; - void renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples); void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights); - void renderMaterials(U32 mask, std::vector<LLDrawInfo*>& fullbrights); void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives); void drawEmissive(U32 mask, LLDrawInfo* draw); void drawEmissiveInline(U32 mask, LLDrawInfo* draw); - bool TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader); + bool TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader); void RestoreTexSetup(bool tex_setup); // our 'normal' alpha blend function for this pass diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 02ab316256..52d308f6bd 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1685,7 +1685,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); renderRigged(avatarp, RIGGED_NORMMAP); renderRigged(avatarp, RIGGED_NORMMAP_MASK); - renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); renderRigged(avatarp, RIGGED_SPECMAP); renderRigged(avatarp, RIGGED_SPECMAP_MASK); renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); @@ -2067,56 +2067,12 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( LLVector4a* pos = (LLVector4a*) position.get(); LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; - - if (skin == nullptr) - { - skin = vobj->getSkinInfo(); - } - const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin); + const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, vobj->getMeshID()); const LLMatrix4a* mat = &(mpc.mMatrixPalette[0]); + const LLMatrix4a& bind_shape_matrix = mpc.mBindShapeMatrix; - LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin); - const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix; - -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - U8* joint_indices_cursor = vol_face.mJointIndices; - // fast path with joint indices separate from weights - if (joint_indices_cursor) - { - LLMatrix4a src[4]; - for (U32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - //LLMatrix4a final_mat_correct; - - F32* jw = just_weights[j].getF32ptr(); - - LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src); - - joint_indices_cursor += 4; - - LLVector4a& v = vol_face.mPositions[j]; - - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - - if (norm) - { - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - dst.normalize3fast(); - norm[j] = dst; - } - } - } - // slow path with joint indices calculated from weights - else -#endif + if (!mpc.mMatrixPalette.empty()) { for (U32 j = 0; j < buffer->getNumVerts(); ++j) { @@ -2152,9 +2108,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) return; } - stop_glerror(); - - const LLMeshSkinInfo* lastSkin = nullptr; + LLUUID lastMeshId; for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { @@ -2188,19 +2142,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) continue; } - const LLMeshSkinInfo* skin = vobj->getSkinInfo(); - if (!skin) - { - continue; - } - - //stop_glerror(); - - //const LLVolumeFace& vol_face = volume->getVolumeFace(te); - //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); - - //stop_glerror(); - U32 data_mask = LLFace::getRiggedDataMask(type); LLVertexBuffer* buff = face->getVertexBuffer(); @@ -2290,34 +2231,33 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { if (sShaderLevel > 0) { - if (lastSkin != skin) // <== only upload matrix palette to GL if the skininfo changed + auto& meshId = vobj->getMeshID(); + + if (lastMeshId != meshId) // <== only upload matrix palette to GL if the skininfo changed { // upload matrix palette to shader - const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin); + const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, meshId); U32 count = mpc.mMatrixPalette.size(); - stop_glerror(); + if (count == 0) + { + //skin info not loaded yet, don't render + continue; + } LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, count, FALSE, (GLfloat*) &(mpc.mGLMp[0])); - - stop_glerror(); } + + lastMeshId = meshId; } else { data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; } - lastSkin = skin; - - /*if (glow) - { - gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); - }*/ - if (mat) { //order is important here LLRender::DIFFUSE_MAP should be last, becouse it change @@ -2332,13 +2272,25 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { specular = face->getTexture(LLRender::SPECULAR_MAP); } - if (specular) + if (specular && specular_channel >= 0) { - gGL.getTexUnit(specular_channel)->bind(specular); + gGL.getTexUnit(specular_channel)->bindFast(specular); } - gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP), false, true); + if (normal_channel >= 0) + { + auto* texture = face->getTexture(LLRender::NORMAL_MAP); + if (texture) + { + gGL.getTexUnit(normal_channel)->bindFast(texture); + } + //else + //{ + // TODO handle missing normal map + //} + } + + gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture(LLRender::DIFFUSE_MAP)); LLColor4 col = mat->getSpecularLightColor(); @@ -2369,23 +2321,28 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) sVertexProgram->setMinimumAlpha(0.f); } - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - LLViewerTexture* tex = face->getTexture(i); - if (tex) - { - tex->addTextureStats(avatar->getPixelArea()); - } - } + if (!LLPipeline::sShadowRender && !LLPipeline::sReflectionRender) + { + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + LLViewerTexture* tex = face->getTexture(i); + if (tex) + { + tex->addTextureStats(avatar->getPixelArea()); + } + } + } } else { - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); sVertexProgram->setMinimumAlpha(0.f); if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); } + + gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture()); + } if (face->mTextureMatrix && vobj->mTexAnimMode) @@ -2399,8 +2356,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); } - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + buff->setBufferFast(data_mask); + buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset); if (tex_index <= 1) { @@ -2411,11 +2368,9 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) } else { - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + buff->setBufferFast(data_mask); + buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset); } - - gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); } } } @@ -2476,8 +2431,6 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) continue; } - stop_glerror(); - LLVolumeFace& vol_face = volume->getVolumeFace(te); updateRiggedFaceVertexBuffer(avatar, face, vobj, volume, vol_face); } @@ -2501,47 +2454,58 @@ void LLDrawPoolAvatar::updateSkinInfoMatrixPalettes(LLVOAvatar* avatarp) } } -const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLMeshSkinInfo* skin) +const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLUUID& meshId) { - MatrixPaletteCache& entry = mMatrixPaletteCache[skin]; + MatrixPaletteCache& entry = mMatrixPaletteCache[meshId]; if (entry.mFrame != gFrameCount) { LL_PROFILE_ZONE_SCOPED; + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(meshId); entry.mFrame = gFrameCount; - //build matrix palette - U32 count = LLSkinningUtil::getMeshJointCount(skin); - entry.mMatrixPalette.resize(count); - LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp); - const LLMatrix4a* mat = &(entry.mMatrixPalette[0]); + if (skin != nullptr) + { + entry.mBindShapeMatrix = skin->mBindShapeMatrix; + + //build matrix palette + U32 count = LLSkinningUtil::getMeshJointCount(skin); + entry.mMatrixPalette.resize(count); + LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp); - stop_glerror(); - - entry.mGLMp.resize(count * 12); + const LLMatrix4a* mat = &(entry.mMatrixPalette[0]); - F32* mp = &(entry.mGLMp[0]); - - for (U32 i = 0; i < count; ++i) - { - F32* m = (F32*)mat[i].mMatrix[0].getF32ptr(); + entry.mGLMp.resize(count * 12); + + F32* mp = &(entry.mGLMp[0]); + + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*)mat[i].mMatrix[0].getF32ptr(); - U32 idx = i * 12; + U32 idx = i * 12; - mp[idx + 0] = m[0]; - mp[idx + 1] = m[1]; - mp[idx + 2] = m[2]; - mp[idx + 3] = m[12]; + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; - mp[idx + 4] = m[4]; - mp[idx + 5] = m[5]; - mp[idx + 6] = m[6]; - mp[idx + 7] = m[13]; + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; - mp[idx + 8] = m[8]; - mp[idx + 9] = m[9]; - mp[idx + 10] = m[10]; - mp[idx + 11] = m[14]; + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + } + else + { + entry.mMatrixPalette.resize(0); + entry.mGLMp.resize(0); } } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 0c1ee2cced..800bbc5f62 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -283,12 +283,13 @@ typedef enum std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES]; + LL_ALIGN_PREFIX(16) class MatrixPaletteCache { public: U32 mFrame; LLMeshSkinInfo::matrix_list_t mMatrixPalette; - + LL_ALIGN_16(LLMatrix4a mBindShapeMatrix); // Float array ready to be sent to GL std::vector<F32> mGLMp; @@ -296,11 +297,11 @@ typedef enum mFrame(gFrameCount-1) { } - }; + } LL_ALIGN_POSTFIX(16); - const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLMeshSkinInfo* skin); + const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLUUID& meshId); - typedef std::unordered_map<const LLMeshSkinInfo*, MatrixPaletteCache> matrix_palette_cache_t; + typedef std::unordered_map<LLUUID, MatrixPaletteCache> matrix_palette_cache_t; matrix_palette_cache_t mMatrixPaletteCache; /*virtual*/ LLViewerTexture *getDebugTexture(); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 14069fa6c2..b08fbcbd89 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -677,6 +677,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) //static BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel) { + LL_PROFILE_ZONE_SCOPED; //Note: texture atlas does not support bump texture now. LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; if(!tex) @@ -693,7 +694,7 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi break; case BE_BRIGHTNESS: case BE_DARKNESS: - bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); + bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); break; default: @@ -709,12 +710,13 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi { if (channel == -2) { - gGL.getTexUnit(1)->bind(bump); - gGL.getTexUnit(0)->bind(bump); + gGL.getTexUnit(1)->bindFast(bump); + gGL.getTexUnit(0)->bindFast(bump); } else { - gGL.getTexUnit(channel)->bind(bump); + // NOTE: do not use bindFast here (see SL-16222) + gGL.getTexUnit(channel)->bind(bump); } return TRUE; @@ -1061,6 +1063,7 @@ void LLBumpImageList::updateImages() // Note: the caller SHOULD NOT keep the pointer that this function returns. It may be updated as more data arrives. LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code ) { + LL_PROFILE_ZONE_SCOPED; llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) ); LLViewerTexture* bump = NULL; @@ -1497,6 +1500,7 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; applyModelMatrix(params); bool tex_setup = false; @@ -1507,7 +1511,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { if (params.mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); } } } @@ -1522,13 +1526,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL } else { - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.getTexUnit(1)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - } - gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); @@ -1545,8 +1542,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { if (params.mTexture.notNull()) { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture); - params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); } else { @@ -1559,10 +1555,10 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { params.mGroup->rebuildMesh(); } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - if (tex_setup) + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + + if (tex_setup) { if (mShiny) { @@ -1570,12 +1566,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL } else { - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.getTexUnit(1)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - } gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 476b1d41b7..bab160c34d 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -32,6 +32,8 @@ #include "lltextureentry.h" #include "lluuid.h" +#include <unordered_map> + class LLImageRaw; class LLSpatialGroup; class LLDrawInfo; @@ -161,7 +163,7 @@ private: static void onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump ); private: - typedef std::map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t; bump_image_map_t mBrightnessEntries; bump_image_map_t mDarknessEntries; }; diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 05b0c1f1a9..d2a8757379 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -106,6 +106,7 @@ void LLDrawPoolMaterials::endDeferredPass(S32 pass) void LLDrawPoolMaterials::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED; static const U32 type_list[] = { LLRenderPass::PASS_MATERIAL, @@ -157,7 +158,10 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) mShader->setMinimumAlpha(params.mAlphaMaskCutoff); mShader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); - pushBatch(params, mask, TRUE); + { + LL_PROFILE_ZONE_SCOPED; + pushMaterialsBatch(params, mask); + } } } @@ -171,49 +175,37 @@ void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex) mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex); } -void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) +void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask) { + LL_PROFILE_ZONE_SCOPED; applyModelMatrix(params); bool tex_setup = false; - if (batch_textures && params.mTextureList.size() > 1) + //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTextureMatrix) { - for (U32 i = 0; i < params.mTextureList.size(); ++i) + //if (mShiny) { - if (params.mTextureList[i].notNull()) - { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); - } + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); } - } - else - { //not batching textures or batch has only 1 texture -- might need a texture matrix - if (params.mTextureMatrix) - { - //if (mShiny) - { - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - } - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; - tex_setup = true; - } + tex_setup = true; + } - if (mShaderLevel > 1 && texture) + if (mShaderLevel > 1) + { + if (params.mTexture.notNull()) + { + gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); + } + else { - if (params.mTexture.notNull()) - { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture); - params.mTexture->addTextureStats(params.mVSize); - } - else - { - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); - } + gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE); } } @@ -224,9 +216,9 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + if (tex_setup) { gGL.getTexUnit(0)->activate(); diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h index eae1aba87c..6e39821b07 100644 --- a/indra/newview/lldrawpoolmaterials.h +++ b/indra/newview/lldrawpoolmaterials.h @@ -69,7 +69,7 @@ public: void bindSpecularMap(LLViewerTexture* tex); void bindNormalMap(LLViewerTexture* tex); - /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); + /*virtual*/ void pushMaterialsBatch(LLDrawInfo& params, U32 mask); }; #endif //LL_LLDRAWPOOLMATERIALS_H diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 74e6665a96..843288cfb0 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -150,13 +150,6 @@ void LLDrawPoolGlow::render(S32 pass) } } -void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) -{ - //gGL.diffuseColor4ubv(params.mGlowColor.mV); - LLRenderPass::pushBatch(params, mask, texture, batch_textures); -} - - LLDrawPoolSimple::LLDrawPoolSimple() : LLRenderPass(POOL_SIMPLE) { @@ -471,6 +464,7 @@ void LLDrawPoolSimple::endDeferredPass(S32 pass) void LLDrawPoolSimple::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED; LLGLDisable blend(GL_BLEND); LLGLDisable alpha_test(GL_ALPHA_TEST); diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 608ad9e1eb..b27cc4babc 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -187,7 +187,6 @@ public: /*virtual*/ S32 getNumPasses(); void render(S32 pass = 0); - void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); }; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 37dc80e2b7..34a8b6b2cc 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -343,8 +343,6 @@ void LLDrawPoolTerrain::renderFullShader() LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - ((LLSettingsVOWater*)pwater.get())->updateShader(shader); - // // detail texture 1 // diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 0d5195bdbf..a1ff020068 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -153,6 +153,7 @@ void LLDrawPoolTree::beginDeferredPass(S32 pass) void LLDrawPoolTree::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED; render(pass); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 0c3d8f3098..8c8dc3f3d2 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -182,8 +182,6 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca sky_shader->bindTexture(LLShaderMgr::RAINBOW_MAP, rainbow_tex); sky_shader->bindTexture(LLShaderMgr::HALO_MAP, halo_tex); - ((LLSettingsVOSky*)psky.get())->updateShader(sky_shader); - F32 moisture_level = (float)psky->getSkyMoistureLevel(); F32 droplet_radius = (float)psky->getSkyDropletRadius(); F32 ice_level = (float)psky->getSkyIceLevel(); @@ -406,8 +404,6 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance); cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor()); - ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader); - /// Render the skydome renderDome(camPosLocal, camHeightLocal, cloudshader); @@ -462,8 +458,6 @@ void LLDrawPoolWLSky::renderSkyClouds(const LLVector3& camPosLocal, F32 camHeigh cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance); cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor()); - ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader); - /// Render the skydome renderDome(camPosLocal, camHeightLocal, cloudshader); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 8b8273d183..31ca2531ba 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -119,8 +119,11 @@ BOOL LLViewerDynamicTexture::render() void LLViewerDynamicTexture::preRender(BOOL clear_depth) { gPipeline.allocatePhysicsBuffer(); - llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth())); - llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight())); + if (!gNonInteractive) + { + llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth())); + llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight())); + } if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsATI) { //using offscreen render target, just use the bottom left corner diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 8881d11802..69d3075928 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1471,6 +1471,7 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getSharedEnvironmentInstance() void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool forced) { + LL_PROFILE_ZONE_SCOPED; DayInstance::ptr_t pinstance = getSelectedEnvironmentInstance(); if ((mCurrentEnvironment != pinstance) || forced) @@ -1488,6 +1489,8 @@ void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool f { mCurrentEnvironment = pinstance; } + + updateSettingsUniforms(); } } @@ -1614,6 +1617,8 @@ void LLEnvironment::update(const LLViewerCamera * cam) stop_glerror(); + updateSettingsUniforms(); + // *TODO: potential optimization - this block may only need to be // executed some of the time. For example for water shaders only. { @@ -1648,10 +1653,16 @@ void LLEnvironment::updateCloudScroll() } // static -void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting) +void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting) { LL_RECORD_BLOCK_TIME(FTM_SHADER_PARAM_UPDATE); + for (int i = 0; i < LLGLSLShader::SG_COUNT; ++i) + { + uniforms[i].clear(); + } + + LLShaderUniforms* shader = &uniforms[LLGLSLShader::SG_ANY]; //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL; LLSettingsBase::parammapping_t params = psetting->getParameterMap(); for (auto &it: params) @@ -1694,7 +1705,7 @@ void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLS { LLVector4 vect4(value); //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << vect4 << LL_ENDL; - shader->uniform4fv(it.second.getShaderKey(), 1, vect4.mV); + shader->uniform4fv(it.second.getShaderKey(), vect4 ); break; } @@ -1707,17 +1718,30 @@ void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLS default: break; } - stop_glerror(); } //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL; - psetting->applySpecial(shader); + psetting->applySpecial(uniforms); +} + +void LLEnvironment::updateShaderUniforms(LLGLSLShader* shader) +{ + LL_PROFILE_ZONE_SCOPED; + + // apply uniforms that should be applied to all shaders + mSkyUniforms[LLGLSLShader::SG_ANY].apply(shader); + mWaterUniforms[LLGLSLShader::SG_ANY].apply(shader); + + // apply uniforms specific to the given shader's shader group + auto group = shader->mShaderGroup; + mSkyUniforms[group].apply(shader); + mWaterUniforms[group].apply(shader); } -void LLEnvironment::updateShaderUniforms(LLGLSLShader *shader) +void LLEnvironment::updateSettingsUniforms() { - updateGLVariablesForSettings(shader, mCurrentEnvironment->getWater()); - updateGLVariablesForSettings(shader, mCurrentEnvironment->getSky()); + updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater()); + updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky()); } void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envinfo, LLSettingsBase::Seconds transition) @@ -2618,6 +2642,7 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::DayInstance::clone() const bool LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& delta) { + LL_PROFILE_ZONE_SCOPED; ptr_t keeper(shared_from_this()); // makes sure that this does not go away while it is being worked on. bool changed(false); diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index 7cbf2d25bb..3568fbcfd1 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -38,11 +38,12 @@ #include "llatmosphere.h" +#include "llglslshader.h" + #include <boost/signals2.hpp> //------------------------------------------------------------------------- class LLViewerCamera; -class LLGLSLShader; class LLParcel; //------------------------------------------------------------------------- @@ -50,8 +51,8 @@ class LLEnvironment : public LLSingleton<LLEnvironment> { LLSINGLETON_C11(LLEnvironment); LOG_CLASS(LLEnvironment); - public: + static const F64Seconds TRANSITION_INSTANT; static const F64Seconds TRANSITION_FAST; static const F64Seconds TRANSITION_DEFAULT; @@ -131,9 +132,14 @@ public: void update(const LLViewerCamera * cam); - static void updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting); + static void updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting); + + // apply current sky settings to given shader void updateShaderUniforms(LLGLSLShader *shader); + // prepare settings to be applied to shaders (call whenever settings are updated) + void updateSettingsUniforms(); + void setSelectedEnvironment(EnvSelection_t env, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false); EnvSelection_t getSelectedEnvironment() const { return mSelectedEnvironment; } @@ -234,6 +240,11 @@ public: void handleEnvironmentPush(LLSD &message); + //cached uniform values from LLSD values + LLShaderUniforms mWaterUniforms[LLGLSLShader::SG_COUNT]; + LLShaderUniforms mSkyUniforms[LLGLSLShader::SG_COUNT]; + // ======================================================================================= + class DayInstance: public std::enable_shared_from_this<DayInstance> { public: @@ -288,6 +299,7 @@ public: LLSettingsDay::ptr_t mDayCycle; LLSettingsSky::ptr_t mSky; LLSettingsWater::ptr_t mWater; + S32 mSkyTrack; bool mInitialized; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 3611539ff8..9dd365e3dc 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -271,10 +271,10 @@ private: LLColor4 mFaceColor; // overrides material color if state |= USE_FACE_COLOR U16 mGeomCount; // vertex count for this face - U16 mGeomIndex; // index into draw pool + U16 mGeomIndex; // starting index into mVertexBuffer's vertex array U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing U32 mIndicesCount; - U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) + U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; LLXformMatrix* mXform; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 9c84fa1991..112ece0fbf 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -723,7 +723,8 @@ void LLFloaterIMContainer::setMinimized(BOOL b) } void LLFloaterIMContainer::setVisible(BOOL visible) -{ LLFloaterIMNearbyChat* nearby_chat; +{ + LLFloaterIMNearbyChat* nearby_chat; if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container @@ -758,22 +759,25 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLFloaterIMSessionTab::addToHost(LLUUID()); } - // We need to show/hide all the associated conversations that have been torn off - // (and therefore, are not longer managed by the multifloater), - // so that they show/hide with the conversations manager. - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - for (;widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - if (widget) - { - LLFloater* session_floater = widget->getSessionFloater(); - if (session_floater != nearby_chat) - { - widget->setVisibleIfDetached(visible); - } - } - } + if (!LLFloater::isQuitRequested()) + { + // We need to show/hide all the associated conversations that have been torn off + // (and therefore, are not longer managed by the multifloater), + // so that they show/hide with the conversations manager. + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (; widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + LLFloater* session_floater = widget->getSessionFloater(); + if (session_floater != nearby_chat) + { + widget->setVisibleIfDetached(visible); + } + } + } + } // Now, do the normal multifloater show/hide LLMultiFloater::setVisible(visible); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 0f288e05ca..91f314c115 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1090,7 +1090,7 @@ F32 gpu_benchmark() delete [] pixels; //make a dummy triangle to draw with - LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); + LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, GL_STREAM_DRAW_ARB); if (!buff->allocateBuffer(3, 0, true)) { @@ -1100,7 +1100,6 @@ F32 gpu_benchmark() } LLStrider<LLVector3> v; - LLStrider<LLVector2> tc; if (! buff->getVertexStrider(v)) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 1059324a16..f5358ba5f2 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1229,7 +1229,6 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, if (!session) { - LL_WARNS() << "session " << session_id << "does not exist " << LL_ENDL; return NULL; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fc8179f3b4..844d544e16 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5714,14 +5714,14 @@ class LLCallingCardObserver : public LLFriendObserver public: LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {} virtual ~LLCallingCardObserver() { mBridgep = NULL; } - virtual void changed(U32 mask) - { - mBridgep->refreshFolderViewItem(); - if (mask & LLFriendObserver::ONLINE) - { - mBridgep->checkSearchBySuffixChanges(); - } - } + virtual void changed(U32 mask) + { + if (mask & LLFriendObserver::ONLINE) + { + mBridgep->refreshFolderViewItem(); + mBridgep->checkSearchBySuffixChanges(); + } + } protected: LLCallingCardBridge* mBridgep; }; @@ -5735,14 +5735,15 @@ LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory, const LLUUID& uuid ) : LLItemBridge(inventory, root, uuid) { - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); + mObserver = new LLCallingCardObserver(this); + LLAvatarTracker::instance().addParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); } LLCallingCardBridge::~LLCallingCardBridge() { - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; + LLAvatarTracker::instance().removeParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); + + delete mObserver; } void LLCallingCardBridge::refreshFolderViewItem() diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 8ac64dbd15..a19d6d0b19 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4045,7 +4045,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) { - LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); + LL_PROFILE_ZONE_SCOPED; if (mesh_id.notNull()) { skin_map::iterator iter = mSkinMap.find(mesh_id); @@ -4055,6 +4055,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const } //no skin info known about given mesh, try to fetch it + if (requesting_obj != nullptr) { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index c1698194cb..c0e894fda4 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -586,7 +586,7 @@ public: S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); static S32 getActualMeshLOD(LLSD& header, S32 lod); - const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj); + const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr); LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); void fetchPhysicsShape(const LLUUID& mesh_id); bool hasPhysicsShape(const LLUUID& mesh_id); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 01bddd781d..4fce6735e0 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -3126,7 +3126,7 @@ BOOL LLModelPreview::render() } gGL.diffuseColor4ubv(hull_colors[i].mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions); if (explode > 0.f) { diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index ba831ab2ed..d896c409d7 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -69,7 +69,8 @@ void LLScriptHandler::initChannel() //-------------------------------------------------------------------------- void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notification) { - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + LL_PROFILE_ZONE_SCOPED + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 681787bcbe..ca48c9d58c 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -259,7 +259,8 @@ void LLScreenChannel::updatePositionAndSize(LLRect new_world_rect) //-------------------------------------------------------------------------- void LLScreenChannel::addToast(const LLToast::Params& p) { - bool store_toast = false, show_toast = false; + LL_PROFILE_ZONE_SCOPED + bool store_toast = false, show_toast = false; if (mDisplayToastsAlways) { diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 1e5b893cbc..6a88a8ef2c 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -637,6 +637,7 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA //------------------------------------------------------------------------- void LLSettingsVOSky::updateSettings() { + LL_PROFILE_ZONE_SCOPED; LLSettingsSky::updateSettings(); LLVector3 sun_direction = getSunDirection(); LLVector3 moon_direction = getMoonDirection(); @@ -665,55 +666,55 @@ void LLSettingsVOSky::updateSettings() void LLSettingsVOSky::applySpecial(void *ptarget, bool force) { - LLGLSLShader *shader = (LLGLSLShader *)ptarget; - LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm(); - if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT) + LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT]; { - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, light_direction); + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, LLViewerCamera::getInstance()->getOrigin()); } - else if (shader->mShaderGroup == LLGLSLShader::SG_SKY) + + shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_SKY]; { - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, light_direction); - // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") - LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); - LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); + // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") + LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); + LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); - // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll - // Keep in Sync! - // * indra\newview\llsettingsvo.cpp - // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl - // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl - cloud_scroll[0] = -cloud_scroll[0]; - vect_c_p_d1 += cloud_scroll; - shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV); + // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll + // Keep in Sync! + // * indra\newview\llsettingsvo.cpp + // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl + // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl + cloud_scroll[0] = -cloud_scroll[0]; + vect_c_p_d1 += cloud_scroll; + shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, vect_c_p_d1); - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - LLColor4 sunDiffuse = psky->getSunlightColor(); - LLColor4 moonDiffuse = psky->getMoonlightColor(); + LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV); + LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV); - shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, sunDiffuse.mV); - shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, moonDiffuse.mV); + shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); + shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); - LLColor4 cloud_color(psky->getCloudColor(), 1.0); - shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, 1, cloud_color.mV); + LLVector4 cloud_color(LLVector3(psky->getCloudColor().mV), 1.0); + shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, cloud_color); } + shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_ANY]; shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength); LLColor4 ambient(getTotalAmbient()); - shader->uniform4fv(LLShaderMgr::AMBIENT, 1, ambient.mV); + shader->uniform4fv(LLShaderMgr::AMBIENT, LLVector4(ambient.mV)); shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, getIsSunUp() ? 1 : 0); shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor()); shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier()); shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier()); - F32 g = getGamma(); + F32 g = getGamma(); F32 display_gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); shader->uniform1f(LLShaderMgr::GAMMA, g); @@ -907,11 +908,11 @@ LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater) //------------------------------------------------------------------------- void LLSettingsVOWater::applySpecial(void *ptarget, bool force) { - LLGLSLShader *shader = (LLGLSLShader *)ptarget; - LLEnvironment& env = LLEnvironment::instance(); - if (force || (shader->mShaderGroup == LLGLSLShader::SG_WATER)) + auto group = LLGLSLShader::SG_WATER; + LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[group]; + { F32 water_height = env.getWaterHeight(); @@ -935,7 +936,7 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); - shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, waterPlane.mV); + shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, waterPlane.mV); LLVector4 light_direction = env.getClampedLightNorm(); @@ -950,18 +951,19 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, waterFogDensity); LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor(), 0.0f); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, fog_color.mV); F32 blend_factor = env.getCurrentWater()->getBlendFactor(); shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); // update to normal lightnorm, water shader itself will use rotated lightnorm as necessary - shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, light_direction.mV); + shader->uniform4fv(LLShaderMgr::LIGHTNORM, light_direction.mV); } } void LLSettingsVOWater::updateSettings() { + LL_PROFILE_ZONE_SCOPED; // base class clears dirty flag so as to not trigger recursive update LLSettingsBase::updateSettings(); diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h index 65136ad2f5..caa3ac18d3 100644 --- a/indra/newview/llsettingsvo.h +++ b/indra/newview/llsettingsvo.h @@ -102,8 +102,6 @@ public: bool isAdvanced() const { return m_isAdvanced; } - virtual void updateShader(LLGLSLShader* shader) { applySpecial(shader, true); } - protected: LLSettingsVOSky(); @@ -136,8 +134,6 @@ public: static LLSD convertToLegacy(const ptr_t &); - virtual void updateShader(LLGLSLShader* shader) { applySpecial(shader, true); } - protected: LLSettingsVOWater(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 253b6b9953..5cac9cd7ae 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2386,7 +2386,12 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo if (!decomp->mBaseHullMesh.empty()) { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else { @@ -2406,13 +2411,11 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glPolygonOffset(3.f, 3.f); glLineWidth(3.f); gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); glLineWidth(1.f); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } @@ -2467,6 +2470,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) gGL.pushMatrix(); gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); + LLGLEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(3.f, 3.f); + if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) { LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); @@ -2494,12 +2500,12 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) { //decomp has physics mesh, render that mesh gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else { //no mesh or decomposition, render base hull @@ -2626,8 +2632,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) LLVertexBuffer::unbind(); llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); - - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); gGL.diffuseColor4fv(color.mV); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 919f386d29..6ef82fac9c 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -41,6 +41,7 @@ #include "llviewercamera.h" #include "llvector4a.h" #include <queue> +#include <unordered_map> #define SG_STATE_INHERIT_MASK (OCCLUDED) #define SG_INITIAL_STATE_MASK (DIRTY | GEOM_DIRTY) @@ -216,10 +217,10 @@ public: typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t; typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t; typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; - typedef std::map<U32, drawmap_elem_t > draw_map_t; + typedef std::unordered_map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t; - typedef std::map<U32, buffer_texture_map_t> buffer_map_t; + typedef std::unordered_map<LLFace*, buffer_list_t> buffer_texture_map_t; + typedef std::unordered_map<U32, buffer_texture_map_t> buffer_map_t; struct CompareDistanceGreater { diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp index 3c3c1c96ef..3ece12931c 100644 --- a/indra/newview/llteleporthistory.cpp +++ b/indra/newview/llteleporthistory.cpp @@ -39,6 +39,11 @@ #include "llviewerregion.h" #include "llworldmap.h" #include "llagentui.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" + ////////////////////////////////////////////////////////////////////////////// // LLTeleportHistoryItem @@ -113,6 +118,20 @@ void LLTeleportHistory::handleLoginComplete() updateCurrentLocation(gAgent.getPositionGlobal()); } +static void on_avatar_name_update_title(const LLAvatarName& av_name) +{ + if (gAgent.getRegion() && gViewerWindow && gViewerWindow->getWindow()) + { + std::string region = gAgent.getRegion()->getName(); + std::string username = av_name.getUserName(); + + // this first pass simply displays username and region name + // but could easily be extended to include other details like + // X/Y/Z location within a region etc. + std::string new_title = STRINGIZE(username << " @ " << region); + gViewerWindow->getWindow()->setTitle(new_title); + } +} void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos) { @@ -174,6 +193,14 @@ void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos) if (!mGotInitialUpdate) mGotInitialUpdate = true; + // update Viewer window title with username and region name + // if we are in "non-interactive mode" (SL-15999) or the debug + // setting to allow it is enabled (may be useful in other situations) + if (gNonInteractive || gSavedSettings.getBOOL("UpdateAppWindowTitleBar")) + { + LLAvatarNameCache::get(gAgent.getID(), boost::bind(&on_avatar_name_update_title, _2)); + } + // Signal the interesting party that we've changed. onHistoryChanged(); } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 63e561147d..73a25397fd 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1143,6 +1143,10 @@ void LLTextureFetchWorker::startWork(S32 param) bool LLTextureFetchWorker::doWork(S32 param) { LL_PROFILE_ZONE_SCOPED; + if (gNonInteractive) + { + return true; + } static const LLCore::HttpStatus http_not_found(HTTP_NOT_FOUND); // 404 static const LLCore::HttpStatus http_service_unavail(HTTP_SERVICE_UNAVAILABLE); // 503 static const LLCore::HttpStatus http_not_sat(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE); // 416; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 100d5ee713..d43da93c61 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -114,7 +114,8 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) LLToastPanel* LLToastPanel::buidPanelFromNotification( const LLNotificationPtr& notification) { - LLToastPanel* res = NULL; + LL_PROFILE_ZONE_SCOPED + LLToastPanel* res = NULL; //process tip toast panels if ("notifytip" == notification->getType()) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 33842497d1..1236695e4f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -124,7 +124,8 @@ void display_startup() if ( !gViewerWindow || !gViewerWindow->getActive() || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() ) + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) { return; } @@ -313,7 +314,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() ) + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) { // Clean up memory the pools may have allocated if (rebuild) diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5a05f89758..98b76328de 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -192,6 +192,10 @@ LLFloaterOpenHandler gFloaterOpenHandler; void LLViewerFloaterReg::registerFloaters() { + if (gNonInteractive) + { + return; + } // *NOTE: Please keep these alphabetized for easier merges LLFloaterAboutUtil::registerFloater(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index d35dbda907..c347e0eb76 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1216,7 +1216,7 @@ LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders() ///////////////////////////////////////////////////////////////////////////////////////// void LLViewerMedia::setOpenIDCookie(const std::string& url) { - if(!mOpenIDCookie.empty()) + if(!gNonInteractive && !mOpenIDCookie.empty()) { std::string profileUrl = getProfileURL(""); @@ -1687,6 +1687,11 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) /*static*/ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { + if (gNonInteractive) + { + return NULL; + } + std::string plugin_basename = LLMIMETypes::implType(media_type); LLPluginClassMedia* media_source = NULL; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 94d2d216b9..5e99d13206 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2423,6 +2423,10 @@ void translateFailure(LLChat chat, LLSD toastArgs, int status, const std::string void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { + if (gNonInteractive) + { + return; + } LLChat chat; std::string mesg; std::string from_name; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b88baf6aa7..0832415e1e 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -107,6 +107,7 @@ #include "llcleanup.h" #include "llcallstack.h" #include "llmeshrepository.h" +#include "llgl.h" //#define DEBUG_UPDATE_TYPE @@ -155,11 +156,27 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco LLViewerObject *res = NULL; LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); - + + if (gNonInteractive + && pcode != LL_PCODE_LEGACY_AVATAR + && pcode != LL_VO_SURFACE_PATCH + && pcode != LL_VO_WATER + && pcode != LL_VO_VOID_WATER + && pcode != LL_VO_WL_SKY + && pcode != LL_VO_SKY + && pcode != LL_VO_GROUND + && pcode != LL_VO_PART_GROUP + ) + { + return res; + } switch (pcode) { case LL_PCODE_VOLUME: - res = new LLVOVolume(id, pcode, regionp); break; + { + res = new LLVOVolume(id, pcode, regionp); break; + break; + } case LL_PCODE_LEGACY_AVATAR: { if (id == gAgentID) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0b20556104..097b5e3645 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -80,6 +80,7 @@ #include "llfloaterperms.h" #include "llvocache.h" #include "llcorehttputil.h" +#include "llstartup.h" #include <algorithm> #include <iterator> @@ -309,7 +310,7 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* LLDataPacker *cached_dpp = entry->getDP(); - if (!cached_dpp) + if (!cached_dpp || gNonInteractive) { return NULL; //nothing cached. } @@ -2063,7 +2064,6 @@ LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, L LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) { - LLUUID fullid; if (uuid == LLUUID::null) { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 274f53a160..34847d8618 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -845,14 +845,14 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co { //flag to reset the values because the old values are used. resetMaxVirtualSizeResetCounter(); - mMaxVirtualSize = virtual_size; - mAdditionalDecodePriority = 0.f; + mMaxVirtualSize = virtual_size; + mAdditionalDecodePriority = 0.f; mNeedsGLTexture = needs_gltexture; } else if (virtual_size > mMaxVirtualSize) { mMaxVirtualSize = virtual_size; - } + } } void LLViewerTexture::resetTextureStats() @@ -1637,19 +1637,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture() { //actually create the texture on a background thread createTexture(); - { - LL_PROFILE_ZONE_NAMED("iglt - sync"); - if (gGLManager.mHasSync) - { - auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - glClientWaitSync(sync, 0, 0); - glDeleteSync(sync); - } - else - { - glFinish(); - } - } LLImageGLThread::sInstance->postCallback([this]() { //finalize on main thread diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b6b4d1e41f..a5a1fb2c16 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -1,796 +1,796 @@ -/**
- * @file llviewertexture.h
- * @brief Object for managing images and their textures
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLVIEWERTEXTURE_H
-#define LL_LLVIEWERTEXTURE_H
-
-#include "llgltexture.h"
-#include "lltimer.h"
-#include "llframetimer.h"
-#include "llhost.h"
-#include "llgltypes.h"
-#include "llrender.h"
-#include "llmetricperformancetester.h"
-#include "httpcommon.h"
-
-#include <map>
-#include <list>
-
-extern const S32Megabytes gMinVideoRam;
-extern const S32Megabytes gMaxVideoRam;
-
-class LLFace;
-class LLImageGL ;
-class LLImageRaw;
-class LLViewerObject;
-class LLViewerTexture;
-class LLViewerFetchedTexture ;
-class LLViewerMediaTexture ;
-class LLTexturePipelineTester ;
-
-
-typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
-
-class LLVFile;
-class LLMessageSystem;
-class LLViewerMediaImpl ;
-class LLVOVolume ;
-struct LLTextureKey;
-
-class LLLoadedCallbackEntry
-{
-public:
- typedef std::set< LLTextureKey > source_callback_list_t;
-
-public:
- LLLoadedCallbackEntry(loaded_callback_func cb,
- S32 discard_level,
- BOOL need_imageraw, // Needs image raw for the callback
- void* userdata,
- source_callback_list_t* src_callback_list,
- LLViewerFetchedTexture* target,
- BOOL pause);
- ~LLLoadedCallbackEntry();
- void removeTexture(LLViewerFetchedTexture* tex) ;
-
- loaded_callback_func mCallback;
- S32 mLastUsedDiscard;
- S32 mDesiredDiscard;
- BOOL mNeedsImageRaw;
- BOOL mPaused;
- void* mUserData;
- source_callback_list_t* mSourceCallbackList;
-
-public:
- static void cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) ;
-};
-
-class LLTextureBar;
-
-class LLViewerTexture : public LLGLTexture
-{
-public:
- enum
- {
- LOCAL_TEXTURE,
- MEDIA_TEXTURE,
- DYNAMIC_TEXTURE,
- FETCHED_TEXTURE,
- LOD_TEXTURE,
- ATLAS_TEXTURE,
- INVALID_TEXTURE_TYPE
- };
-
- typedef std::vector<class LLFace*> ll_face_list_t;
- typedef std::vector<LLVOVolume*> ll_volume_list_t;
-
-
-protected:
- virtual ~LLViewerTexture();
- LOG_CLASS(LLViewerTexture);
-
-public:
- static void initClass();
- static void updateClass(const F32 velocity, const F32 angular_velocity) ;
-
- LLViewerTexture(BOOL usemipmaps = TRUE);
- LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ;
- LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
- LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
-
- virtual S8 getType() const;
- virtual BOOL isMissingAsset() const ;
- virtual void dump(); // debug info to LL_INFOS()
-
- virtual bool isViewerMediaTexture() const { return false; }
-
- /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
- /*virtual*/ bool bindDebugImage(const S32 stage = 0) ;
- /*virtual*/ void forceImmediateUpdate() ;
- /*virtual*/ bool isActiveFetching();
-
- /*virtual*/ const LLUUID& getID() const { return mID; }
- void setBoostLevel(S32 level);
- S32 getBoostLevel() { return mBoostLevel; }
- void setTextureListType(S32 tex_type) { mTextureListType = tex_type; }
- S32 getTextureListType() { return mTextureListType; }
-
- void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
- void resetTextureStats();
- void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;}
- void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;}
- S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; }
-
- virtual F32 getMaxVirtualSize() ;
-
- LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
-
- S32 getFullWidth() const { return mFullWidth; }
- S32 getFullHeight() const { return mFullHeight; }
- /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
-
- virtual void addFace(U32 channel, LLFace* facep) ;
- virtual void removeFace(U32 channel, LLFace* facep) ;
- S32 getTotalNumFaces() const;
- S32 getNumFaces(U32 ch) const;
- const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];}
-
- virtual void addVolume(U32 channel, LLVOVolume* volumep);
- virtual void removeVolume(U32 channel, LLVOVolume* volumep);
- S32 getNumVolumes(U32 channel) const;
- const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; }
-
-
- virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
- BOOL isLargeImage() ;
-
- void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
- BOOL hasParcelMedia() const { return mParcelMedia != NULL;}
- LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
-
- /*virtual*/ void updateBindStatsForTester() ;
-protected:
- void cleanup() ;
- void init(bool firstinit) ;
- void reorganizeFaceList() ;
- void reorganizeVolumeList() ;
-
- void notifyAboutMissingAsset();
- void notifyAboutCreatingTexture();
-
-private:
- friend class LLBumpImageList;
- friend class LLUIImageList;
-
- virtual void switchToCachedImage();
-
- static bool isMemoryForTextureLow() ;
- static bool isMemoryForTextureSuficientlyFree();
- static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical);
-
-protected:
- LLUUID mID;
- S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList
-
- F32 mSelectedTime; // time texture was last selected
- mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
- mutable S32 mMaxVirtualSizeResetCounter ;
- mutable S32 mMaxVirtualSizeResetInterval;
- mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority.
- LLFrameTimer mLastReferencedTimer;
-
- ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture
- U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS];
- LLFrameTimer mLastFaceListUpdateTimer ;
-
- ll_volume_list_t mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
- U32 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
- LLFrameTimer mLastVolumeListUpdateTimer;
-
- //do not use LLPointer here.
- LLViewerMediaTexture* mParcelMedia ;
-
- static F32 sTexelPixelRatio;
-public:
- static const U32 sCurrentFileVersion;
- static S32 sImageCount;
- static S32 sRawCount;
- static S32 sAuxCount;
- static LLFrameTimer sEvaluationTimer;
- static F32 sDesiredDiscardBias;
- static F32 sDesiredDiscardScale;
- static S32Bytes sBoundTextureMemory;
- static S32Bytes sTotalTextureMemory;
- static S32Megabytes sMaxBoundTextureMemory;
- static S32Megabytes sMaxTotalTextureMem;
- static S32Bytes sMaxDesiredTextureMem ;
- static S8 sCameraMovingDiscardBias;
- static F32 sCameraMovingBias;
- static S32 sMaxSculptRez ;
- static U32 sMinLargeImageSize ;
- static U32 sMaxSmallImageSize ;
- static bool sFreezeImageUpdates;
- static F32 sCurrentTime ;
-
- enum EDebugTexels
- {
- DEBUG_TEXELS_OFF,
- DEBUG_TEXELS_CURRENT,
- DEBUG_TEXELS_DESIRED,
- DEBUG_TEXELS_FULL
- };
-
- static EDebugTexels sDebugTexelsMode;
-
- static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
- static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black)
- static LLPointer<LLViewerTexture> sCheckerBoardImagep; // Texture to show NOTHING (pure black)
-};
-
-
-enum FTType
-{
- FTT_UNKNOWN = -1,
- FTT_DEFAULT = 0, // standard texture fetched by id.
- FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there.
- FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host.
- FTT_MAP_TILE, // tiles are fetched from map server directly.
- FTT_LOCAL_FILE // fetch directly from a local file.
-};
-
-const std::string& fttype_to_string(const FTType& fttype);
-
-//
-//textures are managed in gTextureList.
-//raw image data is fetched from remote or local cache
-//but the raw image this texture pointing to is fixed.
-//
-class LLViewerFetchedTexture : public LLViewerTexture
-{
- friend class LLTextureBar; // debug info only
- friend class LLTextureView; // debug info only
-
-protected:
- /*virtual*/ ~LLViewerFetchedTexture();
-public:
- LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE);
- LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps);
- LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);
-
-public:
- static F32 maxDecodePriority();
-
- struct Compare
- {
- // lhs < rhs
- bool operator()(const LLPointer<LLViewerFetchedTexture> &lhs, const LLPointer<LLViewerFetchedTexture> &rhs) const
- {
- const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs;
- const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs;
- // greater priority is "less"
- const F32 lpriority = lhsp->getDecodePriority();
- const F32 rpriority = rhsp->getDecodePriority();
- if (lpriority > rpriority) // higher priority
- return true;
- if (lpriority < rpriority)
- return false;
- return lhsp < rhsp;
- }
- };
-
-public:
- /*virtual*/ S8 getType() const ;
- FTType getFTType() const;
- /*virtual*/ void forceImmediateUpdate() ;
- /*virtual*/ void dump() ;
-
- // Set callbacks to get called when the image gets updated with higher
- // resolution versions.
- void setLoadedCallback(loaded_callback_func cb,
- S32 discard_level, BOOL keep_imageraw, BOOL needs_aux,
- void* userdata, LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause = FALSE);
- bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; }
- void pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
- void unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
- bool doLoadedCallbacks();
- void deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list);
- void clearCallbackEntryList() ;
-
- void addToCreateTexture();
-
- //call to determine if createTexture is necessary
- BOOL preCreateTexture(S32 usename = 0);
- // ONLY call from LLViewerTextureList or ImageGL background thread
- BOOL createTexture(S32 usename = 0);
- void postCreateTexture();
- void scheduleCreateTexture();
-
- void destroyTexture() ;
-
- virtual void processTextureStats() ;
- F32 calcDecodePriority() ;
-
- BOOL needsAux() const { return mNeedsAux; }
-
- // Host we think might have this image, used for baked av textures.
- void setTargetHost(LLHost host) { mTargetHost = host; }
- LLHost getTargetHost() const { return mTargetHost; }
-
- // Set the decode priority for this image...
- // DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up
- // the priority list, and cause horrible things to happen.
- void setDecodePriority(F32 priority = -1.0f);
- F32 getDecodePriority() const { return mDecodePriority; };
- F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; };
-
- void setAdditionalDecodePriority(F32 priority) ;
-
- void updateVirtualSize() ;
-
- S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; }
- void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
-
- bool updateFetch();
- bool setDebugFetching(S32 debug_level);
- bool isInDebug() const { return mInDebug; }
-
- void setUnremovable(BOOL value) { mUnremovable = value; }
- bool isUnremovable() const { return mUnremovable; }
-
- void clearFetchedResults(); //clear all fetched results, for debug use.
-
- // Override the computation of discard levels if we know the exact output
- // size of the image. Used for UI textures to not decode, even if we have
- // more data.
- /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
-
- void setIsMissingAsset(BOOL is_missing = true);
- /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
-
- // returns dimensions of original image for local files (before power of two scaling)
- // and returns 0 for all asset system images
- S32 getOriginalWidth() { return mOrigWidth; }
- S32 getOriginalHeight() { return mOrigHeight; }
-
- BOOL isInImageList() const {return mInImageList ;}
- void setInImageList(BOOL flag) {mInImageList = flag ;}
-
- LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;}
-
- U32 getFetchPriority() const { return mFetchPriority ;}
- F32 getDownloadProgress() const {return mDownloadProgress ;}
-
- LLImageRaw* reloadRawImage(S8 discard_level) ;
- void destroyRawImage();
- bool needsToSaveRawImage();
-
- const std::string& getUrl() const {return mUrl;}
- //---------------
- BOOL isDeleted() ;
- BOOL isInactive() ;
- BOOL isDeletionCandidate();
- void setDeletionCandidate() ;
- void setInactive() ;
- BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
- //---------------
-
- void setForSculpt();
- BOOL forSculpt() const {return mForSculpt;}
- BOOL isForSculptOnly() const;
-
- //raw image management
- void checkCachedRawSculptImage() ;
- LLImageRaw* getRawImage()const { return mRawImage ;}
- S32 getRawImageLevel() const {return mRawDiscardLevel;}
- LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
- S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
- BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
- BOOL isRawImageValid()const { return mIsRawImageValid ; }
- void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
- void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
- /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
- void destroySavedRawImage() ;
- LLImageRaw* getSavedRawImage() ;
- BOOL hasSavedRawImage() const ;
- F32 getElapsedLastReferencedSavedRawImageTime() const ;
- BOOL isFullyLoaded() const;
-
- BOOL hasFetcher() const { return mHasFetcher;}
- void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}
-
- void forceToDeleteRequest();
- void loadFromFastCache();
- void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }
- bool isInFastCacheList() { return mInFastCacheList; }
-
- /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline.
-
-protected:
- /*virtual*/ void switchToCachedImage();
- S32 getCurrentDiscardLevelForFetching() ;
-
-private:
- void init(bool firstinit) ;
- void cleanup() ;
-
- void saveRawImage() ;
- void setCachedRawImage() ;
-
- //for atlas
- void resetFaceAtlas() ;
- void invalidateAtlas(BOOL rebuild_geom) ;
- BOOL insertToAtlas() ;
-
-private:
- BOOL mFullyLoaded;
- BOOL mInDebug;
- BOOL mUnremovable;
- BOOL mInFastCacheList;
- BOOL mForceCallbackFetch;
-
-protected:
- std::string mLocalFileName;
-
- S32 mOrigWidth;
- S32 mOrigHeight;
-
- // Override the computation of discard levels if we know the exact output size of the image.
- // Used for UI textures to not decode, even if we have more data.
- S32 mKnownDrawWidth;
- S32 mKnownDrawHeight;
- BOOL mKnownDrawSizeChanged ;
- std::string mUrl;
-
- S32 mRequestedDiscardLevel;
- F32 mRequestedDownloadPriority;
- S32 mFetchState;
- U32 mFetchPriority;
- F32 mDownloadProgress;
- F32 mFetchDeltaTime;
- F32 mRequestDeltaTime;
- F32 mDecodePriority; // The priority for decoding this image.
- S32 mMinDiscardLevel;
- S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space
- S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
-
- S8 mNeedsAux; // We need to decode the auxiliary channels
- S8 mHasAux; // We have aux channels
- S8 mDecodingAux; // Are we decoding high components
- S8 mIsRawImageValid;
- S8 mHasFetcher; // We've made a fecth request
- S8 mIsFetching; // Fetch request is active
- bool mCanUseHTTP; //This texture can be fetched through http if true.
- LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture.
-
- FTType mFTType; // What category of image is this - map tile, server bake, etc?
- mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database.
-
- typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
- S8 mLoadedCallbackDesiredDiscardLevel;
- BOOL mPauseLoadedCallBacks;
- callback_list_t mLoadedCallbackList;
- F32 mLastCallBackActiveTime;
-
- LLPointer<LLImageRaw> mRawImage;
- S32 mRawDiscardLevel;
-
- // Used ONLY for cloth meshes right now. Make SURE you know what you're
- // doing if you use it for anything else! - djs
- LLPointer<LLImageRaw> mAuxRawImage;
-
- //keep a copy of mRawImage for some special purposes
- //when mForceToSaveRawImage is set.
- BOOL mForceToSaveRawImage ;
- BOOL mSaveRawImage;
- LLPointer<LLImageRaw> mSavedRawImage;
- S32 mSavedRawDiscardLevel;
- S32 mDesiredSavedRawDiscardLevel;
- F32 mLastReferencedSavedRawImageTime ;
- F32 mKeptSavedRawImageTime ;
-
- //a small version of the copy of the raw image (<= 64 * 64)
- LLPointer<LLImageRaw> mCachedRawImage;
- S32 mCachedRawDiscardLevel;
- BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
-
- LLHost mTargetHost; // if invalid, just request from agent's simulator
-
- // Timers
- LLFrameTimer mLastPacketTimer; // Time since last packet.
- LLFrameTimer mStopFetchingTimer; // Time since mDecodePriority == 0.f.
-
- BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!)
- BOOL mNeedsCreateTexture;
-
- BOOL mForSculpt ; //a flag if the texture is used as sculpt data.
- BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally.
-
-public:
- static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database
- static LLPointer<LLViewerFetchedTexture> sWhiteImagep; // Texture to show NOTHING (whiteness)
- static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
- static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
- static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface
-};
-
-//
-//the image data is fetched from remote or from local cache
-//the resolution of the texture is adjustable: depends on the view-dependent parameters.
-//
-class LLViewerLODTexture : public LLViewerFetchedTexture
-{
-protected:
- /*virtual*/ ~LLViewerLODTexture(){}
-
-public:
- LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE);
- LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);
-
- /*virtual*/ S8 getType() const;
- // Process image stats to determine priority/quality requirements.
- /*virtual*/ void processTextureStats();
- bool isUpdateFrozen() ;
-
-private:
- void init(bool firstinit) ;
- bool scaleDown() ;
-
-private:
- F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
- F32 mCalculatedDiscardLevel; // Last calculated discard level
-};
-
-//
-//the image data is fetched from the media pipeline periodically
-//the resolution of the texture is also adjusted by the media pipeline
-//
-class LLViewerMediaTexture : public LLViewerTexture
-{
-protected:
- /*virtual*/ ~LLViewerMediaTexture() ;
-
-public:
- LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
-
- /*virtual*/ S8 getType() const;
- void reinit(BOOL usemipmaps = TRUE);
-
- BOOL getUseMipMaps() {return mUseMipMaps ; }
- void setUseMipMaps(BOOL mipmap) ;
-
- void setPlaying(BOOL playing) ;
- BOOL isPlaying() const {return mIsPlaying;}
- void setMediaImpl() ;
-
- virtual bool isViewerMediaTexture() const { return true; }
-
- void initVirtualSize() ;
- void invalidateMediaImpl() ;
-
- void addMediaToFace(LLFace* facep) ;
- void removeMediaFromFace(LLFace* facep) ;
-
- /*virtual*/ void addFace(U32 ch, LLFace* facep) ;
- /*virtual*/ void removeFace(U32 ch, LLFace* facep) ;
-
- /*virtual*/ F32 getMaxVirtualSize() ;
-private:
- void switchTexture(U32 ch, LLFace* facep) ;
- BOOL findFaces() ;
- void stopPlaying() ;
-
-private:
- //
- //an instant list, recording all faces referencing or can reference to this media texture.
- //NOTE: it is NOT thread safe.
- //
- std::list< LLFace* > mMediaFaceList ;
-
- //an instant list keeping all textures which are replaced by the current media texture,
- //is only used to avoid the removal of those textures from memory.
- std::list< LLPointer<LLViewerTexture> > mTextureList ;
-
- LLViewerMediaImpl* mMediaImplp ;
- BOOL mIsPlaying ;
- U32 mUpdateVirtualSizeTime ;
-
-public:
- static void updateClass() ;
- static void cleanUpClass() ;
-
- static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ;
- static void removeMediaImplFromTexture(const LLUUID& media_id) ;
-
-private:
- typedef std::map< LLUUID, LLPointer<LLViewerMediaTexture> > media_map_t ;
- static media_map_t sMediaMap ;
-};
-
-//just an interface class, do not create instance from this class.
-class LLViewerTextureManager
-{
-private:
- //make the constructor private to preclude creating instances from this class.
- LLViewerTextureManager(){}
-
-public:
- //texture pipeline tester
- static LLTexturePipelineTester* sTesterp ;
-
- //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
- static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ;
-
- //
- //"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
- //
- static void findFetchedTextures(const LLUUID& id, std::vector<LLViewerFetchedTexture*> &output);
- static void findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output);
- static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id, S32 tex_type);
- static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ;
-
- static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
-
- //
- //"get-texture" will create a new texture if the texture does not exist.
- //
- static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
-
- static LLPointer<LLViewerTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE);
- static LLPointer<LLViewerTexture> getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
- static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
- static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
-
- static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
- FTType f_type = FTT_DEFAULT,
- BOOL usemipmap = TRUE,
- LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation.
- S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
- LLGLint internal_format = 0,
- LLGLenum primary_format = 0,
- LLHost request_from_host = LLHost()
- );
-
- static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename,
- FTType f_type = FTT_LOCAL_FILE,
- BOOL usemipmap = TRUE,
- LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE,
- S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
- LLGLint internal_format = 0,
- LLGLenum primary_format = 0,
- const LLUUID& force_id = LLUUID::null
- );
-
- static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url,
- FTType f_type,
- BOOL usemipmap = TRUE,
- LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE,
- S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
- LLGLint internal_format = 0,
- LLGLenum primary_format = 0,
- const LLUUID& force_id = LLUUID::null
- );
-
- static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ;
-
- static void init() ;
- static void cleanup() ;
-};
-//
-//this class is used for test/debug only
-//it tracks the activities of the texture pipeline
-//records them, and outputs them to log files
-//
-class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession
-{
- enum
- {
- MIN_LARGE_IMAGE_AREA = 262144 //512 * 512
- };
-public:
- LLTexturePipelineTester() ;
- ~LLTexturePipelineTester() ;
-
- void update();
- void updateTextureBindingStats(const LLViewerTexture* imagep) ;
- void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) ;
- void updateGrayTextureBinding() ;
- void setStablizingTime() ;
-
-private:
- void reset() ;
- void updateStablizingTime() ;
-
- /*virtual*/ void outputTestRecord(LLSD* sd) ;
-
-private:
- BOOL mPause ;
-private:
- BOOL mUsingDefaultTexture; //if set, some textures are still gray.
-
- U32Bytes mTotalBytesUsed ; //total bytes of textures bound/used for the current frame.
- U32Bytes mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256.
- U32Bytes mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame.
- U32Bytes mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256.
-
- //
- //data size
- //
- U32Bytes mTotalBytesLoaded ; //total bytes fetched by texture pipeline
- U32Bytes mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache
- U32Bytes mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256.
- U32Bytes mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties
-
- //
- //time
- //NOTE: the error tolerances of the following timers is one frame time.
- //
- F32 mStartFetchingTime ;
- F32 mTotalGrayTime ; //total loading time when no gray textures.
- F32 mTotalStablizingTime ; //total stablizing time when texture memory overflows
- F32 mStartTimeLoadingSculpties ; //the start moment of loading sculpty images.
- F32 mEndTimeLoadingSculpties ; //the end moment of loading sculpty images.
- F32 mStartStablizingTime ;
- F32 mEndStablizingTime ;
-
-private:
- //
- //The following members are used for performance analyzing
- //
- class LLTextureTestSession : public LLTestSession
- {
- public:
- LLTextureTestSession() ;
- /*virtual*/ ~LLTextureTestSession() ;
-
- void reset() ;
-
- F32 mTotalFetchingTime ;
- F32 mTotalGrayTime ;
- F32 mTotalStablizingTime ;
- F32 mStartTimeLoadingSculpties ;
- F32 mTotalTimeLoadingSculpties ;
-
- S32 mTotalBytesLoaded ;
- S32 mTotalBytesLoadedFromCache ;
- S32 mTotalBytesLoadedForLargeImage ;
- S32 mTotalBytesLoadedForSculpties ;
-
- typedef struct _texture_instant_preformance_t
- {
- S32 mAverageBytesUsedPerSecond ;
- S32 mAverageBytesUsedForLargeImagePerSecond ;
- F32 mAveragePercentageBytesUsedPerSecond ;
- F32 mTime ;
- }texture_instant_preformance_t ;
- std::vector<texture_instant_preformance_t> mInstantPerformanceList ;
- S32 mInstantPerformanceListCounter ;
- };
-
- /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ;
- /*virtual*/ void compareTestSessions(llofstream* os) ;
-};
-
-#endif
+/** + * @file llviewertexture.h + * @brief Object for managing images and their textures + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERTEXTURE_H +#define LL_LLVIEWERTEXTURE_H + +#include "llgltexture.h" +#include "lltimer.h" +#include "llframetimer.h" +#include "llhost.h" +#include "llgltypes.h" +#include "llrender.h" +#include "llmetricperformancetester.h" +#include "httpcommon.h" + +#include <map> +#include <list> + +extern const S32Megabytes gMinVideoRam; +extern const S32Megabytes gMaxVideoRam; + +class LLFace; +class LLImageGL ; +class LLImageRaw; +class LLViewerObject; +class LLViewerTexture; +class LLViewerFetchedTexture ; +class LLViewerMediaTexture ; +class LLTexturePipelineTester ; + + +typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); + +class LLVFile; +class LLMessageSystem; +class LLViewerMediaImpl ; +class LLVOVolume ; +struct LLTextureKey; + +class LLLoadedCallbackEntry +{ +public: + typedef std::set< LLTextureKey > source_callback_list_t; + +public: + LLLoadedCallbackEntry(loaded_callback_func cb, + S32 discard_level, + BOOL need_imageraw, // Needs image raw for the callback + void* userdata, + source_callback_list_t* src_callback_list, + LLViewerFetchedTexture* target, + BOOL pause); + ~LLLoadedCallbackEntry(); + void removeTexture(LLViewerFetchedTexture* tex) ; + + loaded_callback_func mCallback; + S32 mLastUsedDiscard; + S32 mDesiredDiscard; + BOOL mNeedsImageRaw; + BOOL mPaused; + void* mUserData; + source_callback_list_t* mSourceCallbackList; + +public: + static void cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) ; +}; + +class LLTextureBar; + +class LLViewerTexture : public LLGLTexture +{ +public: + enum + { + LOCAL_TEXTURE, + MEDIA_TEXTURE, + DYNAMIC_TEXTURE, + FETCHED_TEXTURE, + LOD_TEXTURE, + ATLAS_TEXTURE, + INVALID_TEXTURE_TYPE + }; + + typedef std::vector<class LLFace*> ll_face_list_t; + typedef std::vector<LLVOVolume*> ll_volume_list_t; + + +protected: + virtual ~LLViewerTexture(); + LOG_CLASS(LLViewerTexture); + +public: + static void initClass(); + static void updateClass(const F32 velocity, const F32 angular_velocity) ; + + LLViewerTexture(BOOL usemipmaps = TRUE); + LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ; + LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + + virtual S8 getType() const; + virtual BOOL isMissingAsset() const ; + virtual void dump(); // debug info to LL_INFOS() + + virtual bool isViewerMediaTexture() const { return false; } + + /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; + /*virtual*/ bool bindDebugImage(const S32 stage = 0) ; + /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ bool isActiveFetching(); + + /*virtual*/ const LLUUID& getID() const { return mID; } + void setBoostLevel(S32 level); + S32 getBoostLevel() { return mBoostLevel; } + void setTextureListType(S32 tex_type) { mTextureListType = tex_type; } + S32 getTextureListType() { return mTextureListType; } + + void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; + void resetTextureStats(); + void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} + void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;} + S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; } + + virtual F32 getMaxVirtualSize() ; + + LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} + + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } + /*virtual*/ void setKnownDrawSize(S32 width, S32 height); + + virtual void addFace(U32 channel, LLFace* facep) ; + virtual void removeFace(U32 channel, LLFace* facep) ; + S32 getTotalNumFaces() const; + S32 getNumFaces(U32 ch) const; + const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];} + + virtual void addVolume(U32 channel, LLVOVolume* volumep); + virtual void removeVolume(U32 channel, LLVOVolume* volumep); + S32 getNumVolumes(U32 channel) const; + const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; } + + + virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; + BOOL isLargeImage() ; + + void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} + BOOL hasParcelMedia() const { return mParcelMedia != NULL;} + LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} + + /*virtual*/ void updateBindStatsForTester() ; +protected: + void cleanup() ; + void init(bool firstinit) ; + void reorganizeFaceList() ; + void reorganizeVolumeList() ; + + void notifyAboutMissingAsset(); + void notifyAboutCreatingTexture(); + +private: + friend class LLBumpImageList; + friend class LLUIImageList; + + virtual void switchToCachedImage(); + + static bool isMemoryForTextureLow() ; + static bool isMemoryForTextureSuficientlyFree(); + static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical); + +protected: + LLUUID mID; + S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList + + F32 mSelectedTime; // time texture was last selected + mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? + mutable S32 mMaxVirtualSizeResetCounter ; + mutable S32 mMaxVirtualSizeResetInterval; + mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. + LLFrameTimer mLastReferencedTimer; + + ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture + U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; + LLFrameTimer mLastFaceListUpdateTimer ; + + ll_volume_list_t mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + U32 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + LLFrameTimer mLastVolumeListUpdateTimer; + + //do not use LLPointer here. + LLViewerMediaTexture* mParcelMedia ; + + static F32 sTexelPixelRatio; +public: + static const U32 sCurrentFileVersion; + static S32 sImageCount; + static S32 sRawCount; + static S32 sAuxCount; + static LLFrameTimer sEvaluationTimer; + static F32 sDesiredDiscardBias; + static F32 sDesiredDiscardScale; + static S32Bytes sBoundTextureMemory; + static S32Bytes sTotalTextureMemory; + static S32Megabytes sMaxBoundTextureMemory; + static S32Megabytes sMaxTotalTextureMem; + static S32Bytes sMaxDesiredTextureMem ; + static S8 sCameraMovingDiscardBias; + static F32 sCameraMovingBias; + static S32 sMaxSculptRez ; + static U32 sMinLargeImageSize ; + static U32 sMaxSmallImageSize ; + static bool sFreezeImageUpdates; + static F32 sCurrentTime ; + + enum EDebugTexels + { + DEBUG_TEXELS_OFF, + DEBUG_TEXELS_CURRENT, + DEBUG_TEXELS_DESIRED, + DEBUG_TEXELS_FULL + }; + + static EDebugTexels sDebugTexelsMode; + + static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. + static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black) + static LLPointer<LLViewerTexture> sCheckerBoardImagep; // Texture to show NOTHING (pure black) +}; + + +enum FTType +{ + FTT_UNKNOWN = -1, + FTT_DEFAULT = 0, // standard texture fetched by id. + FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. + FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. + FTT_MAP_TILE, // tiles are fetched from map server directly. + FTT_LOCAL_FILE // fetch directly from a local file. +}; + +const std::string& fttype_to_string(const FTType& fttype); + +// +//textures are managed in gTextureList. +//raw image data is fetched from remote or local cache +//but the raw image this texture pointing to is fixed. +// +class LLViewerFetchedTexture : public LLViewerTexture +{ + friend class LLTextureBar; // debug info only + friend class LLTextureView; // debug info only + +protected: + /*virtual*/ ~LLViewerFetchedTexture(); +public: + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); + LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); + +public: + static F32 maxDecodePriority(); + + struct Compare + { + // lhs < rhs + bool operator()(const LLPointer<LLViewerFetchedTexture> &lhs, const LLPointer<LLViewerFetchedTexture> &rhs) const + { + const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs; + const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs; + // greater priority is "less" + const F32 lpriority = lhsp->getDecodePriority(); + const F32 rpriority = rhsp->getDecodePriority(); + if (lpriority > rpriority) // higher priority + return true; + if (lpriority < rpriority) + return false; + return lhsp < rhsp; + } + }; + +public: + /*virtual*/ S8 getType() const ; + FTType getFTType() const; + /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ void dump() ; + + // Set callbacks to get called when the image gets updated with higher + // resolution versions. + void setLoadedCallback(loaded_callback_func cb, + S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, + void* userdata, LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause = FALSE); + bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; } + void pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + void unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + bool doLoadedCallbacks(); + void deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + void clearCallbackEntryList() ; + + void addToCreateTexture(); + + //call to determine if createTexture is necessary + BOOL preCreateTexture(S32 usename = 0); + // ONLY call from LLViewerTextureList or ImageGL background thread + BOOL createTexture(S32 usename = 0); + void postCreateTexture(); + void scheduleCreateTexture(); + + void destroyTexture() ; + + virtual void processTextureStats() ; + F32 calcDecodePriority() ; + + BOOL needsAux() const { return mNeedsAux; } + + // Host we think might have this image, used for baked av textures. + void setTargetHost(LLHost host) { mTargetHost = host; } + LLHost getTargetHost() const { return mTargetHost; } + + // Set the decode priority for this image... + // DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up + // the priority list, and cause horrible things to happen. + void setDecodePriority(F32 priority = -1.0f); + F32 getDecodePriority() const { return mDecodePriority; }; + F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; }; + + void setAdditionalDecodePriority(F32 priority) ; + + void updateVirtualSize() ; + + S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; } + void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } + + bool updateFetch(); + bool setDebugFetching(S32 debug_level); + bool isInDebug() const { return mInDebug; } + + void setUnremovable(BOOL value) { mUnremovable = value; } + bool isUnremovable() const { return mUnremovable; } + + void clearFetchedResults(); //clear all fetched results, for debug use. + + // Override the computation of discard levels if we know the exact output + // size of the image. Used for UI textures to not decode, even if we have + // more data. + /*virtual*/ void setKnownDrawSize(S32 width, S32 height); + + void setIsMissingAsset(BOOL is_missing = true); + /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } + + // returns dimensions of original image for local files (before power of two scaling) + // and returns 0 for all asset system images + S32 getOriginalWidth() { return mOrigWidth; } + S32 getOriginalHeight() { return mOrigHeight; } + + BOOL isInImageList() const {return mInImageList ;} + void setInImageList(BOOL flag) {mInImageList = flag ;} + + LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;} + + U32 getFetchPriority() const { return mFetchPriority ;} + F32 getDownloadProgress() const {return mDownloadProgress ;} + + LLImageRaw* reloadRawImage(S8 discard_level) ; + void destroyRawImage(); + bool needsToSaveRawImage(); + + const std::string& getUrl() const {return mUrl;} + //--------------- + BOOL isDeleted() ; + BOOL isInactive() ; + BOOL isDeletionCandidate(); + void setDeletionCandidate() ; + void setInactive() ; + BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } + //--------------- + + void setForSculpt(); + BOOL forSculpt() const {return mForSculpt;} + BOOL isForSculptOnly() const; + + //raw image management + void checkCachedRawSculptImage() ; + LLImageRaw* getRawImage()const { return mRawImage ;} + S32 getRawImageLevel() const {return mRawDiscardLevel;} + LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;} + S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} + BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} + BOOL isRawImageValid()const { return mIsRawImageValid ; } + void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; + void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); + /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; + void destroySavedRawImage() ; + LLImageRaw* getSavedRawImage() ; + BOOL hasSavedRawImage() const ; + F32 getElapsedLastReferencedSavedRawImageTime() const ; + BOOL isFullyLoaded() const; + + BOOL hasFetcher() const { return mHasFetcher;} + void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} + + void forceToDeleteRequest(); + void loadFromFastCache(); + void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; } + bool isInFastCacheList() { return mInFastCacheList; } + + /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline. + +protected: + /*virtual*/ void switchToCachedImage(); + S32 getCurrentDiscardLevelForFetching() ; + +private: + void init(bool firstinit) ; + void cleanup() ; + + void saveRawImage() ; + void setCachedRawImage() ; + + //for atlas + void resetFaceAtlas() ; + void invalidateAtlas(BOOL rebuild_geom) ; + BOOL insertToAtlas() ; + +private: + BOOL mFullyLoaded; + BOOL mInDebug; + BOOL mUnremovable; + BOOL mInFastCacheList; + BOOL mForceCallbackFetch; + +protected: + std::string mLocalFileName; + + S32 mOrigWidth; + S32 mOrigHeight; + + // Override the computation of discard levels if we know the exact output size of the image. + // Used for UI textures to not decode, even if we have more data. + S32 mKnownDrawWidth; + S32 mKnownDrawHeight; + BOOL mKnownDrawSizeChanged ; + std::string mUrl; + + S32 mRequestedDiscardLevel; + F32 mRequestedDownloadPriority; + S32 mFetchState; + U32 mFetchPriority; + F32 mDownloadProgress; + F32 mFetchDeltaTime; + F32 mRequestDeltaTime; + F32 mDecodePriority; // The priority for decoding this image. + S32 mMinDiscardLevel; + S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space + S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have + + S8 mNeedsAux; // We need to decode the auxiliary channels + S8 mHasAux; // We have aux channels + S8 mDecodingAux; // Are we decoding high components + S8 mIsRawImageValid; + S8 mHasFetcher; // We've made a fecth request + S8 mIsFetching; // Fetch request is active + bool mCanUseHTTP; //This texture can be fetched through http if true. + LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture. + + FTType mFTType; // What category of image is this - map tile, server bake, etc? + mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + + typedef std::list<LLLoadedCallbackEntry*> callback_list_t; + S8 mLoadedCallbackDesiredDiscardLevel; + BOOL mPauseLoadedCallBacks; + callback_list_t mLoadedCallbackList; + F32 mLastCallBackActiveTime; + + LLPointer<LLImageRaw> mRawImage; + S32 mRawDiscardLevel; + + // Used ONLY for cloth meshes right now. Make SURE you know what you're + // doing if you use it for anything else! - djs + LLPointer<LLImageRaw> mAuxRawImage; + + //keep a copy of mRawImage for some special purposes + //when mForceToSaveRawImage is set. + BOOL mForceToSaveRawImage ; + BOOL mSaveRawImage; + LLPointer<LLImageRaw> mSavedRawImage; + S32 mSavedRawDiscardLevel; + S32 mDesiredSavedRawDiscardLevel; + F32 mLastReferencedSavedRawImageTime ; + F32 mKeptSavedRawImageTime ; + + //a small version of the copy of the raw image (<= 64 * 64) + LLPointer<LLImageRaw> mCachedRawImage; + S32 mCachedRawDiscardLevel; + BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. + + LLHost mTargetHost; // if invalid, just request from agent's simulator + + // Timers + LLFrameTimer mLastPacketTimer; // Time since last packet. + LLFrameTimer mStopFetchingTimer; // Time since mDecodePriority == 0.f. + + BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!) + BOOL mNeedsCreateTexture; + + BOOL mForSculpt ; //a flag if the texture is used as sculpt data. + BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. + +public: + static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database + static LLPointer<LLViewerFetchedTexture> sWhiteImagep; // Texture to show NOTHING (whiteness) + static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local. + static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture + static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface +}; + +// +//the image data is fetched from remote or from local cache +//the resolution of the texture is adjustable: depends on the view-dependent parameters. +// +class LLViewerLODTexture : public LLViewerFetchedTexture +{ +protected: + /*virtual*/ ~LLViewerLODTexture(){} + +public: + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); + + /*virtual*/ S8 getType() const; + // Process image stats to determine priority/quality requirements. + /*virtual*/ void processTextureStats(); + bool isUpdateFrozen() ; + +private: + void init(bool firstinit) ; + bool scaleDown() ; + +private: + F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard + F32 mCalculatedDiscardLevel; // Last calculated discard level +}; + +// +//the image data is fetched from the media pipeline periodically +//the resolution of the texture is also adjusted by the media pipeline +// +class LLViewerMediaTexture : public LLViewerTexture +{ +protected: + /*virtual*/ ~LLViewerMediaTexture() ; + +public: + LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + + /*virtual*/ S8 getType() const; + void reinit(BOOL usemipmaps = TRUE); + + BOOL getUseMipMaps() {return mUseMipMaps ; } + void setUseMipMaps(BOOL mipmap) ; + + void setPlaying(BOOL playing) ; + BOOL isPlaying() const {return mIsPlaying;} + void setMediaImpl() ; + + virtual bool isViewerMediaTexture() const { return true; } + + void initVirtualSize() ; + void invalidateMediaImpl() ; + + void addMediaToFace(LLFace* facep) ; + void removeMediaFromFace(LLFace* facep) ; + + /*virtual*/ void addFace(U32 ch, LLFace* facep) ; + /*virtual*/ void removeFace(U32 ch, LLFace* facep) ; + + /*virtual*/ F32 getMaxVirtualSize() ; +private: + void switchTexture(U32 ch, LLFace* facep) ; + BOOL findFaces() ; + void stopPlaying() ; + +private: + // + //an instant list, recording all faces referencing or can reference to this media texture. + //NOTE: it is NOT thread safe. + // + std::list< LLFace* > mMediaFaceList ; + + //an instant list keeping all textures which are replaced by the current media texture, + //is only used to avoid the removal of those textures from memory. + std::list< LLPointer<LLViewerTexture> > mTextureList ; + + LLViewerMediaImpl* mMediaImplp ; + BOOL mIsPlaying ; + U32 mUpdateVirtualSizeTime ; + +public: + static void updateClass() ; + static void cleanUpClass() ; + + static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ; + static void removeMediaImplFromTexture(const LLUUID& media_id) ; + +private: + typedef std::map< LLUUID, LLPointer<LLViewerMediaTexture> > media_map_t ; + static media_map_t sMediaMap ; +}; + +//just an interface class, do not create instance from this class. +class LLViewerTextureManager +{ +private: + //make the constructor private to preclude creating instances from this class. + LLViewerTextureManager(){} + +public: + //texture pipeline tester + static LLTexturePipelineTester* sTesterp ; + + //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture. + static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ; + + // + //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. + // + static void findFetchedTextures(const LLUUID& id, std::vector<LLViewerFetchedTexture*> &output); + static void findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output); + static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id, S32 tex_type); + static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; + + static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + + // + //"get-texture" will create a new texture if the texture does not exist. + // + static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + + static LLPointer<LLViewerTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE); + static LLPointer<LLViewerTexture> getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; + static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; + + static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + LLHost request_from_host = LLHost() + ); + + static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + FTType f_type, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; + + static void init() ; + static void cleanup() ; +}; +// +//this class is used for test/debug only +//it tracks the activities of the texture pipeline +//records them, and outputs them to log files +// +class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession +{ + enum + { + MIN_LARGE_IMAGE_AREA = 262144 //512 * 512 + }; +public: + LLTexturePipelineTester() ; + ~LLTexturePipelineTester() ; + + void update(); + void updateTextureBindingStats(const LLViewerTexture* imagep) ; + void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) ; + void updateGrayTextureBinding() ; + void setStablizingTime() ; + +private: + void reset() ; + void updateStablizingTime() ; + + /*virtual*/ void outputTestRecord(LLSD* sd) ; + +private: + BOOL mPause ; +private: + BOOL mUsingDefaultTexture; //if set, some textures are still gray. + + U32Bytes mTotalBytesUsed ; //total bytes of textures bound/used for the current frame. + U32Bytes mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256. + U32Bytes mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame. + U32Bytes mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256. + + // + //data size + // + U32Bytes mTotalBytesLoaded ; //total bytes fetched by texture pipeline + U32Bytes mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache + U32Bytes mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256. + U32Bytes mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties + + // + //time + //NOTE: the error tolerances of the following timers is one frame time. + // + F32 mStartFetchingTime ; + F32 mTotalGrayTime ; //total loading time when no gray textures. + F32 mTotalStablizingTime ; //total stablizing time when texture memory overflows + F32 mStartTimeLoadingSculpties ; //the start moment of loading sculpty images. + F32 mEndTimeLoadingSculpties ; //the end moment of loading sculpty images. + F32 mStartStablizingTime ; + F32 mEndStablizingTime ; + +private: + // + //The following members are used for performance analyzing + // + class LLTextureTestSession : public LLTestSession + { + public: + LLTextureTestSession() ; + /*virtual*/ ~LLTextureTestSession() ; + + void reset() ; + + F32 mTotalFetchingTime ; + F32 mTotalGrayTime ; + F32 mTotalStablizingTime ; + F32 mStartTimeLoadingSculpties ; + F32 mTotalTimeLoadingSculpties ; + + S32 mTotalBytesLoaded ; + S32 mTotalBytesLoadedFromCache ; + S32 mTotalBytesLoadedForLargeImage ; + S32 mTotalBytesLoadedForSculpties ; + + typedef struct _texture_instant_preformance_t + { + S32 mAverageBytesUsedPerSecond ; + S32 mAverageBytesUsedForLargeImagePerSecond ; + F32 mAveragePercentageBytesUsedPerSecond ; + F32 mTime ; + }texture_instant_preformance_t ; + std::vector<texture_instant_preformance_t> mInstantPerformanceList ; + S32 mInstantPerformanceListCounter ; + }; + + /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ; + /*virtual*/ void compareTestSessions(llofstream* os) ; +}; + +#endif diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 82ece85c1b..7dc7b33938 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1516,8 +1516,15 @@ BOOL LLViewerWindow::handleCloseRequest(LLWindow *window) void LLViewerWindow::handleQuit(LLWindow *window) { - LL_INFOS() << "Window forced quit" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); + if (gNonInteractive) + { + LLAppViewer::instance()->requestQuit(); + } + else + { + LL_INFOS() << "Window forced quit" << LL_ENDL; + LLAppViewer::instance()->forceQuit(); + } } void LLViewerWindow::handleResize(LLWindow *window, S32 width, S32 height) @@ -2189,6 +2196,14 @@ void LLViewerWindow::initBase() void LLViewerWindow::initWorldUI() { + if (gNonInteractive) + { + gIMMgr = LLIMMgr::getInstance(); + LLNavigationBar::getInstance(); + gFloaterView->pushVisibleAll(FALSE); + return; + } + S32 height = mRootView->getRect().getHeight(); S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); @@ -2199,12 +2214,15 @@ void LLViewerWindow::initWorldUI() //getRootView()->sendChildToFront(gFloaterView); //getRootView()->sendChildToFront(gSnapshotFloaterView); - LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); - LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); - chiclet_bar->setShape(chiclet_container->getLocalRect()); - chiclet_bar->setFollowsAll(); - chiclet_container->addChild(chiclet_bar); - chiclet_container->setVisible(TRUE); + if (!gNonInteractive) + { + LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); + LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); + chiclet_bar->setShape(chiclet_container->getLocalRect()); + chiclet_bar->setFollowsAll(); + chiclet_container->addChild(chiclet_bar); + chiclet_container->setVisible(TRUE); + } LLRect morph_view_rect = full_window; morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); @@ -2293,21 +2311,24 @@ void LLViewerWindow::initWorldUI() gToolBarView->setVisible(TRUE); } - LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); - if (destinations) - { - destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("DestinationGuideURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); - if (avatar_picker) + if (!gNonInteractive) { - avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("AvatarPickerURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); + if (destinations) + { + destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("DestinationGuideURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); + if (avatar_picker) + { + avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("AvatarPickerURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } } } @@ -2551,7 +2572,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) mWindow->setMinSize(min_window_width, min_window_height); LLCoordScreen window_rect; - if (mWindow->getSize(&window_rect)) + if (!gNonInteractive && mWindow->getSize(&window_rect)) { // Only save size if not maximized gSavedSettings.setU32("WindowWidth", window_rect.mX); @@ -3781,8 +3802,15 @@ void LLViewerWindow::updateLayout() void LLViewerWindow::updateMouseDelta() { +#if LL_WINDOWS + LLCoordCommon delta; + mWindow->getCursorDelta(&delta); + S32 dx = delta.mX; + S32 dy = delta.mY; +#else S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); +#endif //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 4d2eac8c09..86fe7c19bd 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5358,7 +5358,9 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled) bool LLVivoxVoiceClient::voiceEnabled() { - return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice"); + return gSavedSettings.getBOOL("EnableVoiceChat") && + !gSavedSettings.getBOOL("CmdLineDisableVoice") && + !gNonInteractive; } void LLVivoxVoiceClient::setLipSyncEnabled(BOOL enabled) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e5a4b0f374..b86935b081 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3555,7 +3555,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const { if (getVolume()) { - return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); + return gMeshRepo.getSkinInfo(getMeshID(), this); } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index ce400a3498..b8c6f47bbd 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -296,6 +296,9 @@ public: BOOL setIsFlexible(BOOL is_flexible); const LLMeshSkinInfo* getSkinInfo() const; + + //convenience accessor for mesh ID (which is stored in sculpt id for legacy reasons) + const LLUUID& getMeshID() const { return getVolume()->getParams().getSculptID(); } // Extended Mesh Properties U32 getExtendedMeshFlags() const; diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index 8be340de4c..e4a9f9afdb 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -150,6 +150,10 @@ void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 // public static void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) { + if (gNonInteractive) + { + return; + } U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c0b469af81..7aa05fb22f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -358,7 +358,6 @@ bool LLPipeline::sRenderAttachedLights = true; bool LLPipeline::sRenderAttachedParticles = true; bool LLPipeline::sRenderDeferred = false; S32 LLPipeline::sVisibleLightCount = 0; -F32 LLPipeline::sMinRenderSize = 0.f; bool LLPipeline::sRenderingHUDs; F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f; @@ -486,6 +485,10 @@ void LLPipeline::init() { clearAllRenderTypes(); } + else if (gNonInteractive) + { + clearAllRenderTypes(); + } else { setAllRenderTypes(); // By default, all rendering types start enabled @@ -1152,6 +1155,12 @@ void LLPipeline::refreshCachedSettings() RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); RenderSpotLight = nullptr; updateRenderDeferred(); + + if (gNonInteractive) + { + LLVOAvatar::sMaxNonImpostors = 1; + LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); + } } void LLPipeline::releaseGLBuffers() @@ -2550,13 +2559,6 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } - const LLVector4a* bounds = group->getBounds(); - if (sMinRenderSize > 0.f && - llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) - { - return; - } - assertInitialized(); if (!group->getSpatialPartition()->mRenderByGroup) @@ -3480,7 +3482,6 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) group->mLastUpdateDistance = group->mDistance; } } - } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed) @@ -3787,6 +3788,27 @@ void renderSoundHighlights(LLDrawable* drawablep) } } +void LLPipeline::touchTextures(LLDrawInfo* info) +{ + LL_PROFILE_ZONE_SCOPED; + for (auto& tex : info->mTextureList) + { + if (tex.notNull()) + { + LLImageGL* gl_tex = tex->getGLTexture(); + if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory)) + { + tex->setActive(); + } + } + } + + if (info->mTexture.notNull()) + { + info->mTexture->addTextureStats(info->mVSize); + } +} + void LLPipeline::postSort(LLCamera& camera) { LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); @@ -3839,20 +3861,14 @@ void LLPipeline::postSort(LLCamera& camera) for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) { - if (sMinRenderSize > 0.f) - { - LLVector4a bounds; - bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]); - - if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize) - { - sCull->pushDrawInfo(j->first, *k); - } - } - else - { - sCull->pushDrawInfo(j->first, *k); - } + LLDrawInfo* info = *k; + + sCull->pushDrawInfo(j->first, info); + if (!sShadowRender && !sReflectionRender) + { + touchTextures(info); + addTrianglesDrawn(info->mCount, info->mDrawMode); + } } } @@ -3991,7 +4007,10 @@ void LLPipeline::postSort(LLCamera& camera) { mSelectedFaces.clear(); - LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + if (!gNonInteractive) + { + LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + } // Draw face highlights for selected faces. if (LLSelectMgr::getInstance()->getTEMode()) @@ -8421,8 +8440,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ LLEnvironment& environment = LLEnvironment::instance(); LLSettingsSky::ptr_t sky = environment.getCurrentSky(); - - static_cast<LLSettingsVOSky*>(sky.get())->updateShader(&shader); } LLColor3 pow3f(LLColor3 v, F32 f) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5605d26410..8ffbddca21 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -265,6 +265,8 @@ public: void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); void stateSort(LLDrawable* drawablep, LLCamera& camera); void postSort(LLCamera& camera); + //update stats for textures in given DrawInfo + void touchTextures(LLDrawInfo* info); void forAllVisibleDrawables(void (*func)(LLDrawable*)); void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); @@ -596,7 +598,6 @@ public: static bool sRenderAttachedParticles; static bool sRenderDeferred; static S32 sVisibleLightCount; - static F32 sMinRenderSize; static bool sRenderingHUDs; static F32 sDistortionWaterClipPlaneMargin; |