diff options
Diffstat (limited to 'indra')
196 files changed, 9992 insertions, 2758 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 333860a31a..c939afc863 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -9,9 +9,9 @@ include(Variables) set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1") set(CMAKE_CXX_FLAGS_RELEASE - "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -DLL_SEND_CRASH_REPORTS=1 -DNDEBUG") + "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=1 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "-DLL_RELEASE=1 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") + "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") # Don't bother with a MinSizeRel build. @@ -26,15 +26,18 @@ if (WINDOWS) # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MTd" + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd" CACHE STRING "C++ compiler debug options" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MT" + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MT" + "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD" CACHE STRING "C++ compiler release options" FORCE) + set(CMAKE_CXX_STANDARD_LIBRARIES "") + set(CMAKE_C_STANDARD_LIBRARIES "") + add_definitions( /DLL_WINDOWS=1 /DUNICODE diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index 2563a98c52..25ee364db8 100644 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -1,5 +1,3 @@ -# -*- cmake -*- - include(BerkeleyDB) include(Linking) include(Prebuilt) @@ -19,12 +17,14 @@ else (STANDALONE) debug ${ARCH_PREBUILT_DIRS_DEBUG}/apr-1.lib optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apr-1.lib ) + set(APRICONV_LIBRARIES + debug ${ARCH_PREBUILT_DIRS_DEBUG}/apriconv-1.lib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apriconv-1.lib + ) set(APRUTIL_LIBRARIES - debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib ${APRICONV_LIBRARIES} + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib ${APRICONV_LIBRARIES} ) - # Doesn't need to link with iconv.dll - set(APRICONV_LIBRARIES "") elseif (DARWIN) set(APR_LIBRARIES debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.a diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake index c6ccab2613..d23bc2f9c6 100644 --- a/indra/cmake/Audio.cmake +++ b/indra/cmake/Audio.cmake @@ -14,10 +14,18 @@ else (STANDALONE) set(VORBISFILE_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS}) if (WINDOWS) - set(OGG_LIBRARIES ogg_static_mt) - set(VORBIS_LIBRARIES vorbis_static_mt) - set(VORBISENC_LIBRARIES vorbisenc_static_mt) - set(VORBISFILE_LIBRARIES vorbisfile_static_mt) + set(OGG_LIBRARIES + optimized ogg_static + debug ogg_static_d) + set(VORBIS_LIBRARIES + optimized vorbis_static + debug vorbis_static_d) + set(VORBISENC_LIBRARIES + optimized vorbisenc_static + debug vorbisenc_static_d) + set(VORBISFILE_LIBRARIES + optimized vorbisfile_static + debug vorbisfile_static_d) else (WINDOWS) set(OGG_LIBRARIES ogg) set(VORBIS_LIBRARIES vorbis) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index a7db67c915..0578ae95ff 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -28,14 +28,14 @@ else (STANDALONE) debug libboost_signals-vc71-mt-sgd-${BOOST_VERSION}) else (MSVC71) set(BOOST_PROGRAM_OPTIONS_LIBRARY - optimized libboost_program_options-vc80-mt-s-${BOOST_VERSION} - debug libboost_program_options-vc80-mt-sgd-${BOOST_VERSION}) + optimized libboost_program_options-vc80-mt-${BOOST_VERSION} + debug libboost_program_options-vc80-mt-gd-${BOOST_VERSION}) set(BOOST_REGEX_LIBRARY - optimized libboost_regex-vc80-mt-s-${BOOST_VERSION} - debug libboost_regex-vc80-mt-sgd-${BOOST_VERSION}) + optimized libboost_regex-vc80-mt-${BOOST_VERSION} + debug libboost_regex-vc80-mt-gd-${BOOST_VERSION}) set(BOOST_SIGNALS_LIBRARY - optimized libboost_signals-vc80-mt-s-${BOOST_VERSION} - debug libboost_signals-vc80-mt-sgd-${BOOST_VERSION}) + optimized libboost_signals-vc80-mt-${BOOST_VERSION} + debug libboost_signals-vc80-mt-gd-${BOOST_VERSION}) endif (MSVC71) elseif (DARWIN) set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 25e9f6d4f4..aff65cb53e 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -5,6 +5,11 @@ if (STANDALONE) include(FindGooglePerfTools) else (STANDALONE) use_prebuilt_binary(google) + if (WINDOWS) + set(TCMALLOC_LIBRARIES + debug libtcmalloc_minimal-debug + optimized libtcmalloc_minimal-debug) + endif (WINDOWS) if (LINUX) set(TCMALLOC_LIBRARIES tcmalloc) set(STACKTRACE_LIBRARIES stacktrace) diff --git a/indra/cmake/JPEG.cmake b/indra/cmake/JPEG.cmake index 5d0ee0d2fd..9514d59f64 100644 --- a/indra/cmake/JPEG.cmake +++ b/indra/cmake/JPEG.cmake @@ -17,7 +17,7 @@ else (STANDALONE) debug ${ARCH_PREBUILT_DIRS_DEBUG}/liblljpeg.a ) elseif (WINDOWS) - set(JPEG_LIBRARIES jpeglib_6b) + set(JPEG_LIBRARIES jpeglib) endif (LINUX) set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake index bbcf4cd57d..c47e8878e9 100644 --- a/indra/cmake/LLRender.cmake +++ b/indra/cmake/LLRender.cmake @@ -18,8 +18,8 @@ endif (SERVER AND LINUX) # mapserver requires certain files to be copied so LL_MESA_HEADLESS can be set # differently for different object files. -macro (copy_server_sources _copied_SOURCES) - foreach (PREFIX ${_copied_SOURCES}) +macro (copy_server_sources ) + foreach (PREFIX ${ARGV}) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp COMMAND ${CMAKE_COMMAND} diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index c0efa27f6e..e749055abf 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -40,4 +40,9 @@ else (SERVER AND LINUX) set(LLWINDOW_LIBRARIES llwindow ) + if (WINDOWS) + list(APPEND LLWINDOW_LIBRARIES + comdlg32 + ) + endif (WINDOWS) endif (SERVER AND LINUX) diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 167c5dd31c..2bddb95178 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -32,11 +32,16 @@ endif (LINUX) if (WINDOWS) set(WINDOWS_LIBRARIES + advapi32 + shell32 ws2_32 mswsock psapi winmm netapi32 + wldap32 + gdi32 + user32 ) else (WINDOWS) set(WINDOWS_LIBRARIES "") diff --git a/indra/cmake/PNG.cmake b/indra/cmake/PNG.cmake index 4d0b7b2d8d..cf10c2dda5 100644 --- a/indra/cmake/PNG.cmake +++ b/indra/cmake/PNG.cmake @@ -8,6 +8,12 @@ if (STANDALONE) include(FindPNG) else (STANDALONE) use_prebuilt_binary(libpng) - set(PNG_LIBRARIES png12) + if (WINDOWS) + set(PNG_LIBRARIES + debug libpngd + optimized libpng) + else (WINDOWS) + set(PNG_LIBRARIES png12) + endif (WINDOWS) set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) endif (STANDALONE) diff --git a/indra/cmake/ZLIB.cmake b/indra/cmake/ZLIB.cmake index 80d4191971..c133248bed 100644 --- a/indra/cmake/ZLIB.cmake +++ b/indra/cmake/ZLIB.cmake @@ -10,7 +10,9 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(zlib) if (WINDOWS) - set(ZLIB_LIBRARIES zlib) + set(ZLIB_LIBRARIES + debug zlibd + optimized zlib) else (WINDOWS) set(ZLIB_LIBRARIES z) endif (WINDOWS) diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 7b53de06b9..e1f8ce53fb 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -178,7 +178,9 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); - apr_file_t *fp = ll_apr_file_open(path, LL_APR_R); + LLAPRFile infile ; + infile.open(path, LL_APR_R); + apr_file_t *fp = infile.getFileHandle(); if (!fp) return ST_NO_XLT_FILE; @@ -187,8 +189,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) //-------------------------------------------------------------------- // register file to be closed on function exit //-------------------------------------------------------------------- - FileCloser fileCloser(fp); - + //-------------------------------------------------------------------- // load header //-------------------------------------------------------------------- @@ -618,6 +619,8 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } } + + infile.close() ; return ST_OK; } diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index c0af6250c2..a9c1f6fc45 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -354,7 +354,9 @@ BOOL LLKeyframeMotionParam::loadMotions() // open the file //------------------------------------------------------------------------- S32 fileSize = 0; - apr_file_t* fp = ll_apr_file_open(path, LL_APR_R, &fileSize); + LLAPRFile infile ; + infile.open(path, LL_APR_R, NULL, &fileSize); + apr_file_t* fp = infile.getFileHandle() ; if (!fp || fileSize == 0) { llinfos << "ERROR: can't open: " << path << llendl; @@ -366,7 +368,6 @@ BOOL LLKeyframeMotionParam::loadMotions() if ( !text ) { llinfos << "ERROR: can't allocated keyframe text buffer." << llendl; - apr_file_close(fp); return FALSE; } @@ -393,7 +394,7 @@ BOOL LLKeyframeMotionParam::loadMotions() //------------------------------------------------------------------------- // close the file //------------------------------------------------------------------------- - apr_file_close( fp ); + infile.close(); //------------------------------------------------------------------------- // check for error diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp index 5a2faf6e71..73c6951211 100644 --- a/indra/llcharacter/llstatemachine.cpp +++ b/indra/llcharacter/llstatemachine.cpp @@ -209,7 +209,9 @@ LLFSMState* LLStateDiagram::getState(U32 state_id) BOOL LLStateDiagram::saveDotFile(const std::string& filename) { - apr_file_t* dot_file = ll_apr_file_open(filename, LL_APR_W); + LLAPRFile outfile ; + outfile.open(filename, LL_APR_W); + apr_file_t* dot_file = outfile.getFileHandle() ; if (!dot_file) { @@ -258,8 +260,6 @@ BOOL LLStateDiagram::saveDotFile(const std::string& filename) apr_file_printf(dot_file, "}\n"); - apr_file_close(dot_file); - return TRUE; } diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 74d821c721..82530b1489 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -36,8 +36,10 @@ #include "llapr.h" apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool +LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. apr_thread_mutex_t *gLogMutexp = NULL; +const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool void ll_init_apr() { @@ -46,10 +48,15 @@ void ll_init_apr() // Initialize APR and create the global pool apr_initialize(); apr_pool_create(&gAPRPoolp, NULL); - + // Initialize the logging mutex apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp); } + + if(!LLAPRFile::sAPRFilePoolp) + { + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ; + } } @@ -70,31 +77,127 @@ void ll_cleanup_apr() apr_pool_destroy(gAPRPoolp); gAPRPoolp = NULL; } + if (LLAPRFile::sAPRFilePoolp) + { + delete LLAPRFile::sAPRFilePoolp ; + LLAPRFile::sAPRFilePoolp = NULL ; + } apr_terminate(); } // +// //LLAPRPool // -LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size) +LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) { - mStatus = apr_pool_create(&mPool, parent); + mParent = parent ; + mReleasePoolFlag = releasePoolFlag ; + mMaxSize = size ; + mPool = NULL ; + + createAPRPool() ; +} + +LLAPRPool::~LLAPRPool() +{ + releaseAPRPool() ; +} - if(size > 0) //size is the number of blocks (which is usually 4K), NOT bytes. +void LLAPRPool::createAPRPool() +{ + if(mPool) + { + return ; + } + + mStatus = apr_pool_create(&mPool, mParent); + ll_apr_warn_status(mStatus) ; + + if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes. { apr_allocator_t *allocator = apr_pool_allocator_get(mPool); if (allocator) { - apr_allocator_max_free_set(allocator, size) ; + apr_allocator_max_free_set(allocator, mMaxSize) ; } } } -LLAPRPool::~LLAPRPool() +void LLAPRPool::releaseAPRPool() +{ + if(!mPool) + { + return ; + } + + if(!mParent || mReleasePoolFlag) + { + apr_pool_destroy(mPool) ; + mPool = NULL ; + } +} + +apr_pool_t* LLAPRPool::getAPRPool() { - apr_pool_destroy(mPool) ; + if(!mPool) + { + createAPRPool() ; + } + + return mPool ; +} +LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : LLAPRPool(parent, size, releasePoolFlag) +{ + mNumActiveRef = 0 ; + mNumTotalRef = 0 ; } +apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +{ + mNumTotalRef++ ; + mNumActiveRef++ ; + return getAPRPool() ; +} + +void LLVolatileAPRPool::clearVolatileAPRPool() +{ + if(mNumActiveRef > 0) + { + mNumActiveRef--; + if(mNumActiveRef < 1) + { + if(isFull()) + { + mNumTotalRef = 0 ; + + //destroy the apr_pool. + releaseAPRPool() ; + } + else + { + //This does not actually free the memory, + //it just allows the pool to re-use this memory for the next allocation. + apr_pool_clear(mPool) ; + } + } + } + else + { + llassert_always(mNumActiveRef > 0) ; + } + + //paranoia check if the pool is jammed. + //will remove the check before going to release. + llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; +} + +BOOL LLVolatileAPRPool::isFull() +{ + return mNumTotalRef > FULL_VOLATILE_APR_POOL ; +} +//--------------------------------------------------------------------- // // LLScopedLock // @@ -133,9 +236,8 @@ void LLScopedLock::unlock() } } -// -// Misc functions -// +//--------------------------------------------------------------------- + bool ll_apr_warn_status(apr_status_t status) { if(APR_SUCCESS == status) return false; @@ -151,55 +253,110 @@ void ll_apr_assert_status(apr_status_t status) llassert(ll_apr_warn_status(status) == false); } -// File I/O -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool) +//--------------------------------------------------------------------- +// +// LLAPRFile functions +// +LLAPRFile::LLAPRFile() +{ + mFile = NULL ; + mCurrentFilePoolp = NULL ; +} +LLAPRFile::~LLAPRFile() +{ + close() ; +} + +apr_status_t LLAPRFile::close() +{ + apr_status_t ret = APR_SUCCESS ; + if(mFile) + { + ret = apr_file_close(mFile); + mFile = NULL ; + } + + if(mCurrentFilePoolp) + { + mCurrentFilePoolp->clearVolatileAPRPool() ; + mCurrentFilePoolp = NULL ; + } + + return ret ; +} + +apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep) +{ + apr_status_t s ; + s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ; + + if(!mCurrentFilePoolp) + { + mCurrentFilePoolp = pool ; + + if(!mFile) + { + close() ; + } + } + + return s ; +} +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep) { - apr_file_t* apr_file; apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool); - if (s != APR_SUCCESS) + + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool)); + if (s != APR_SUCCESS || !mFile) { + mFile = NULL ; + close() ; if (sizep) { *sizep = 0; } - return NULL; + return s; } if (sizep) { S32 file_size = 0; apr_off_t offset = 0; - if (apr_file_seek(apr_file, APR_END, &offset) == APR_SUCCESS) + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) { llassert_always(offset <= 0x7fffffff); file_size = (S32)offset; offset = 0; - apr_file_seek(apr_file, APR_SET, &offset); + apr_file_seek(mFile, APR_SET, &offset); } *sizep = file_size; } - return apr_file; + return s; } -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, S32* sizep) -{ - return ll_apr_file_open(filename, flags, sizep, NULL); -} -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool) -{ - return ll_apr_file_open(filename, flags, NULL, pool); -} -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags) -{ - return ll_apr_file_open(filename, flags, NULL, NULL); + +apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool) +{ + if(!pool) + { + mCurrentFilePoolp = sAPRFilePoolp ; + return mCurrentFilePoolp->getVolatileAPRPool() ; + } + + return pool ; } -S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes) +// File I/O +S32 LLAPRFile::read(void *buf, S32 nbytes) { + llassert_always(mFile) ; + apr_size_t sz = nbytes; - apr_status_t s = apr_file_read(apr_file, buf, &sz); + apr_status_t s = apr_file_read(mFile, buf, &sz); if (s != APR_SUCCESS) { return 0; @@ -211,165 +368,273 @@ S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes) } } -S32 ll_apr_file_read_ex(const std::string& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes) +S32 LLAPRFile::write(const void *buf, S32 nbytes) { - if (pool == NULL) pool = gAPRPoolp; - apr_file_t* filep = ll_apr_file_open(filename, APR_READ|APR_BINARY, pool); - if (!filep) + llassert_always(mFile) ; + + apr_size_t sz = nbytes; + apr_status_t s = apr_file_write(mFile, buf, &sz); + if (s != APR_SUCCESS) { return 0; } - S32 off; - if (offset < 0) - off = ll_apr_file_seek(filep, APR_END, 0); else - off = ll_apr_file_seek(filep, APR_SET, offset); - S32 bytes_read; - if (off < 0) { - bytes_read = 0; + llassert_always(sz <= 0x7fffffff); + return (S32)sz; } - else +} + +S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) +{ + return LLAPRFile::seek(mFile, where, offset) ; +} + +// +//******************************************************************************************************************************* +//static components of LLAPRFile +// + +//static +apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) +{ + apr_status_t ret = APR_SUCCESS ; + if(file_handle) { - bytes_read = ll_apr_file_read(filep, buf, nbytes ); + ret = apr_file_close(file_handle); + file_handle = NULL ; } - apr_file_close(filep); - return bytes_read; + if(pool) + { + pool->clearVolatileAPRPool() ; + } + + return ret ; } -S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes) +//static +apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) { - apr_size_t sz = nbytes; - apr_status_t s = apr_file_write(apr_file, buf, &sz); + apr_status_t s; + apr_file_t* file_handle ; + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + + s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); + if (s != APR_SUCCESS || !file_handle) + { + file_handle = NULL ; + close(file_handle, pool) ; + return NULL; + } + + return file_handle ; +} + +//static +S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) +{ + if(!file_handle) + { + return -1 ; + } + + apr_status_t s; + apr_off_t apr_offset; + if (offset >= 0) + { + apr_offset = (apr_off_t)offset; + s = apr_file_seek(file_handle, where, &apr_offset); + } + else + { + apr_offset = 0; + s = apr_file_seek(file_handle, APR_END, &apr_offset); + } if (s != APR_SUCCESS) { + return -1; + } + else + { + llassert_always(apr_offset <= 0x7fffffff); + return (S32)apr_offset; + } +} + +//static +S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) +{ + //***************************************** + apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); + //***************************************** + if (!file_handle) + { return 0; } + + S32 off; + if (offset < 0) + off = LLAPRFile::seek(file_handle, APR_END, 0); else + off = LLAPRFile::seek(file_handle, APR_SET, offset); + + apr_size_t bytes_read; + if (off < 0) { - llassert_always(sz <= 0x7fffffff); - return (S32)sz; + bytes_read = 0; } + else + { + bytes_read = nbytes ; + apr_status_t s = apr_file_read(file_handle, buf, &bytes_read); + if (s != APR_SUCCESS) + { + bytes_read = 0; + } + else + { + llassert_always(bytes_read <= 0x7fffffff); + } + } + + //***************************************** + close(file_handle, pool) ; + //***************************************** + return (S32)bytes_read; } -S32 ll_apr_file_write_ex(const std::string& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes) +//static +S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { - if (pool == NULL) pool = gAPRPoolp; apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; if (offset < 0) { flags |= APR_APPEND; offset = 0; } - apr_file_t* filep = ll_apr_file_open(filename, flags, pool); - if (!filep) + + //***************************************** + apr_file_t* file_handle = open(filename, pool, flags); + //***************************************** + if (!file_handle) { return 0; } + if (offset > 0) { - offset = ll_apr_file_seek(filep, APR_SET, offset); + offset = LLAPRFile::seek(file_handle, APR_SET, offset); } - S32 bytes_written; + + apr_size_t bytes_written; if (offset < 0) { bytes_written = 0; } else { - bytes_written = ll_apr_file_write(filep, buf, nbytes ); + bytes_written = nbytes ; + apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); + if (s != APR_SUCCESS) + { + bytes_written = 0; + } + else + { + llassert_always(bytes_written <= 0x7fffffff); + } } - apr_file_close(filep); - return bytes_written; -} + //***************************************** + LLAPRFile::close(file_handle, pool); + //***************************************** -S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset) -{ - apr_status_t s; - apr_off_t apr_offset; - if (offset >= 0) - { - apr_offset = (apr_off_t)offset; - s = apr_file_seek(apr_file, where, &apr_offset); - } - else - { - apr_offset = 0; - s = apr_file_seek(apr_file, APR_END, &apr_offset); - } - if (s != APR_SUCCESS) - { - return -1; - } - else - { - llassert_always(apr_offset <= 0x7fffffff); - return (S32)apr_offset; - } + return (S32)bytes_written; } -bool ll_apr_file_remove(const std::string& filename, apr_pool_t* pool) +//static +bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) { apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_remove(filename.c_str(), pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; + if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "ll_apr_file_remove failed on file: " << filename << LL_ENDL; + LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); return false; } return true; } -bool ll_apr_file_rename(const std::string& filename, const std::string& newname, apr_pool_t* pool) +//static +bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool) { apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_rename(filename.c_str(), newname.c_str(), pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; + if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "ll_apr_file_rename failed on file: " << filename << LL_ENDL; + LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); return false; } return true; } -bool ll_apr_file_exists(const std::string& filename, apr_pool_t* pool) +//static +bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) { apr_file_t* apr_file; apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); + if (s != APR_SUCCESS || !apr_file) { + pool->clearVolatileAPRPool() ; return false; } else { - apr_file_close(apr_file); + apr_file_close(apr_file) ; + pool->clearVolatileAPRPool() ; return true; } } -S32 ll_apr_file_size(const std::string& filename, apr_pool_t* pool) +//static +S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool) { apr_file_t* apr_file; apr_finfo_t info; apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool()); + if (s != APR_SUCCESS || !apr_file) - { + { + pool->clearVolatileAPRPool() ; + return 0; } else { - apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); - apr_file_close(apr_file); + apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); + + apr_file_close(apr_file) ; + pool->clearVolatileAPRPool() ; + if (s == APR_SUCCESS) { return (S32)info.size; @@ -381,31 +646,42 @@ S32 ll_apr_file_size(const std::string& filename, apr_pool_t* pool) } } -bool ll_apr_dir_make(const std::string& dirname, apr_pool_t* pool) +//static +bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) { apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; + if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "ll_apr_dir_make failed on file: " << dirname << LL_ENDL; + LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); return false; } return true; } -bool ll_apr_dir_remove(const std::string& dirname, apr_pool_t* pool) +//static +bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) { apr_status_t s; - if (pool == NULL) pool = gAPRPoolp; - s = apr_file_remove(dirname.c_str(), pool); + + pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; + s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool()); + pool->clearVolatileAPRPool() ; + if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "ll_apr_dir_remove failed on file: " << dirname << LL_ENDL; + LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); return false; } return true; } - +// +//end of static components of LLAPRFile +//******************************************************************************************************************************* +// diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index b8723562d7..44ad2dd50f 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -61,18 +61,51 @@ void ll_init_apr(); */ void ll_cleanup_apr(); +// +//LL apr_pool +//manage apr_pool_t, destroy allocated apr_pool in the destruction function. +// class LLAPRPool { public: - LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0) ; + LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; ~LLAPRPool() ; - apr_pool_t* getAPRPool() {return mPool ; } + apr_pool_t* getAPRPool() ; apr_status_t getStatus() {return mStatus ; } +protected: + void releaseAPRPool() ; + void createAPRPool() ; + +protected: + apr_pool_t* mPool ; //pointing to an apr_pool + apr_pool_t* mParent ; //parent pool + apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work. + apr_status_t mStatus ; //status when creating the pool + BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. +}; + +// +//volatile LL apr_pool +//which clears memory automatically. +//so it can not hold static data or data after memory is cleared +// +class LLVolatileAPRPool : public LLAPRPool +{ +public: + LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); + ~LLVolatileAPRPool(){} + + apr_pool_t* getVolatileAPRPool() ; + + void clearVolatileAPRPool() ; + + BOOL isFull() ; + BOOL isEmpty() {return !mNumActiveRef ;} private: - apr_pool_t* mPool ; - apr_status_t mStatus ; + S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. + S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. } ; /** @@ -145,24 +178,71 @@ typedef LLAtomic32<S32> LLAtomicS32; #define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" #define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b" #define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, S32* sizep, apr_pool_t* pool); -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, S32* sizep); -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool); -apr_file_t* ll_apr_file_open(const std::string& filename, apr_int32_t flags); -// Returns actual offset, -1 if seek fails -S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset); -// Returns bytes read/written, 0 if read/write fails: -S32 ll_apr_file_read(apr_file_t* apr_file, void* buf, S32 nbytes); -S32 ll_apr_file_read_ex(const std::string& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes); -S32 ll_apr_file_write(apr_file_t* apr_file, const void* buf, S32 nbytes); -S32 ll_apr_file_write_ex(const std::string& filename, apr_pool_t* pool, void *buf, S32 offset, S32 nbytes); -// returns false if failure: -bool ll_apr_file_remove(const std::string& filename, apr_pool_t* pool = NULL); -bool ll_apr_file_rename(const std::string& filename, const std::string& newname, apr_pool_t* pool = NULL); -bool ll_apr_file_exists(const std::string& filename, apr_pool_t* pool = NULL); -S32 ll_apr_file_size(const std::string& filename, apr_pool_t* pool = NULL); -bool ll_apr_dir_make(const std::string& dirname, apr_pool_t* pool = NULL); -bool ll_apr_dir_remove(const std::string& dirname, apr_pool_t* pool = NULL); + +// +//apr_file manager +//which: 1)only keeps one file open; +// 2)closes the open file in the destruction function +// 3)informs the apr_pool to clean the memory when the file is closed. +//Note: please close an open file at the earliest convenience. +// especially do not put some time-costly operations between open() and close(). +// otherwise it might lock the APRFilePool. +//there are two different apr_pools the APRFile can use: +// 1, a temperary pool passed to an APRFile function, which is used within this function and only once. +// 2, a global pool. +// +class LLAPRFile +{ +private: + apr_file_t* mFile ; + LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. + +public: + LLAPRFile() ; + ~LLAPRFile() ; + + apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL); + apr_status_t close() ; + + // Returns actual offset, -1 if seek fails + S32 seek(apr_seek_where_t where, S32 offset); + apr_status_t eof() { return apr_file_eof(mFile);} + + // Returns bytes read/written, 0 if read/write fails: + S32 read(void* buf, S32 nbytes); + S32 write(const void* buf, S32 nbytes); + + apr_file_t* getFileHandle() {return mFile;} + +private: + apr_pool_t* getAPRFilePool(apr_pool_t* pool) ; + +// +//******************************************************************************************************************************* +//static components +// +public: + static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist. + +private: + static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags); + static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ; + static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset); +public: + // returns false if failure: + static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL); + static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ); + static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); + static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); + + // Returns bytes read/written, 0 if read/write fails: + static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); + static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); +//******************************************************************************************************************************* +}; /** * @brief Function which approprately logs error or remains quiet on diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp index ad4211f9e8..7f183dc9ae 100644 --- a/indra/llcommon/llcrc.cpp +++ b/indra/llcommon/llcrc.cpp @@ -197,6 +197,10 @@ void LLCRC::update(const std::string& filename) update(data, nread); delete[] data; } + else + { + fclose(fp); + } } } diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 2943d7b288..5e520afab9 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -990,6 +990,38 @@ namespace LLError return new std::ostringstream; } + + void Log::flush(std::ostringstream* out, char* message) + { + LogLock lock; + if (!lock.ok()) + { + return; + } + + if(strlen(out->str().c_str()) < 128) + { + strcpy(message, out->str().c_str()); + } + else + { + strncpy(message, out->str().c_str(), 127); + message[127] = '\0' ; + } + + Globals& g = Globals::get(); + if (out == &g.messageStream) + { + g.messageStream.clear(); + g.messageStream.str(""); + g.messageStreamInUse = false; + } + else + { + delete out; + } + return ; + } void Log::flush(std::ostringstream* out, const CallSite& site) { @@ -1205,3 +1237,94 @@ namespace LLError } } +namespace LLError +{ + char** LLCallStacks::sBuffer = NULL ; + S32 LLCallStacks::sIndex = 0 ; + + //static + void LLCallStacks::push(const char* function, const int line) + { + if(!sBuffer) + { + sBuffer = new char*[512] ; + sBuffer[0] = new char[512 * 128] ; + for(S32 i = 1 ; i < 512 ; i++) + { + sBuffer[i] = sBuffer[i-1] + 128 ; + } + sIndex = 0 ; + } + + if(sIndex > 511) + { + clear() ; + } + + strcpy(sBuffer[sIndex], function) ; + sprintf(sBuffer[sIndex] + strlen(function), " line: %d ", line) ; + sIndex++ ; + + return ; + } + + //static + std::ostringstream* LLCallStacks::insert(const char* function, const int line) + { + std::ostringstream* _out = LLError::Log::out(); + *_out << function << " line " << line << " " ; + + return _out ; + } + + //static + void LLCallStacks::end(std::ostringstream* _out) + { + if(!sBuffer) + { + sBuffer = new char*[512] ; + sBuffer[0] = new char[512 * 128] ; + for(S32 i = 1 ; i < 512 ; i++) + { + sBuffer[i] = sBuffer[i-1] + 128 ; + } + sIndex = 0 ; + } + + if(sIndex > 511) + { + clear() ; + } + + LLError::Log::flush(_out, sBuffer[sIndex++]) ; + } + + //static + void LLCallStacks::print() + { + if(sIndex > 0) + { + llinfos << " ************* PRINT OUT LL CALL STACKS ************* " << llendl ; + while(sIndex > 0) + { + sIndex-- ; + llinfos << sBuffer[sIndex] << llendl ; + } + llinfos << " *************** END OF LL CALL STACKS *************** " << llendl ; + } + + if(sBuffer) + { + delete[] sBuffer[0] ; + delete[] sBuffer ; + sBuffer = NULL ; + } + } + + //static + void LLCallStacks::clear() + { + sIndex = 0 ; + } +} + diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index e39d19741b..6794be4904 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -38,6 +38,7 @@ #include <typeinfo> #include "llerrorlegacy.h" +#include "stdtypes.h" /* Error Logging Facility @@ -135,6 +136,7 @@ namespace LLError public: static bool shouldLog(CallSite&); static std::ostringstream* out(); + static void flush(std::ostringstream* out, char* message) ; static void flush(std::ostringstream*, const CallSite&); }; @@ -179,9 +181,41 @@ namespace LLError class NoClassInfo { }; // used to indicate no class info known for logging -} + //LLCallStacks keeps track of call stacks and output the call stacks to log file + //when LLAppViewer::handleViewerCrash() is triggered. + // + //Note: to be simple, efficient and necessary to keep track of correct call stacks, + //LLCallStacks is designed not to be thread-safe. + //so try not to use it in multiple parallel threads at same time. + //Used in a single thread at a time is fine. + class LLCallStacks + { + private: + static char** sBuffer ; + static S32 sIndex ; + + public: + static void push(const char* function, const int line) ; + static std::ostringstream* insert(const char* function, const int line) ; + static void print() ; + static void clear() ; + static void end(std::ostringstream* _out) ; + }; +} +//this is cheaper than llcallstacks if no need to output other variables to call stacks. +#define llpushcallstacks LLError::LLCallStacks::push(__FUNCTION__, __LINE__) +#define llcallstacks \ + {\ + std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \ + (*_out) +#define llcallstacksendl \ + LLError::End(); \ + LLError::LLCallStacks::end(_out) ; \ + } +#define llclearcallstacks LLError::LLCallStacks::clear() +#define llprintcallstacks LLError::LLCallStacks::print() /* Class type information for logging diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 666aac70fc..94b51119e4 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -71,6 +71,14 @@ public: FTM_UPDATE_AVATAR, // common render components + FTM_SHADOW_GEOMETRY, + FTM_SHADOW_RENDER, + FTM_SHADOW_TERRAIN, + FTM_SHADOW_AVATAR, + FTM_SHADOW_SIMPLE, + FTM_SHADOW_ALPHA, + FTM_SHADOW_TREE, + FTM_RENDER_GEOMETRY, FTM_RENDER_TERRAIN, FTM_RENDER_SIMPLE, @@ -186,11 +194,13 @@ public: enum { FTM_MAX_DEPTH = 64 }; public: + static LLFastTimer::EFastTimerType sCurType; + LLFastTimer(EFastTimerType type) { #if FAST_TIMER_ON mType = type; - + sCurType = type; // These don't get counted, because they use CPU clockticks //gTimerBins[gCurTimerBin]++; //LLTimer::sNumTimerCalls++; diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index d4cb604c5b..e9d6029378 100644 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp @@ -33,6 +33,7 @@ #include "llfixedbuffer.h" LLFixedBuffer::LLFixedBuffer(const U32 max_lines) + : mMutex(NULL) { mMaxLines = max_lines; mTimer.reset(); @@ -47,9 +48,11 @@ LLFixedBuffer::~LLFixedBuffer() void LLFixedBuffer::clear() { + mMutex.lock() ; mLines.clear(); mAddTimes.clear(); mLineLengths.clear(); + mMutex.unlock() ; mTimer.reset(); } @@ -70,9 +73,11 @@ void LLFixedBuffer::addLine(const LLWString& line) removeExtraLines(); + mMutex.lock() ; mLines.push_back(line); mLineLengths.push_back((S32)line.length()); mAddTimes.push_back(mTimer.getElapsedTimeF32()); + mMutex.unlock() ; } @@ -86,10 +91,12 @@ void LLFixedBuffer::setMaxLines(S32 max_lines) void LLFixedBuffer::removeExtraLines() { + mMutex.lock() ; while ((S32)mLines.size() > llmax((S32)0, (S32)(mMaxLines - 1))) { mLines.pop_front(); mAddTimes.pop_front(); mLineLengths.pop_front(); } + mMutex.unlock() ; } diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h index 5d84cd96cb..992a024df1 100644 --- a/indra/llcommon/llfixedbuffer.h +++ b/indra/llcommon/llfixedbuffer.h @@ -37,6 +37,7 @@ #include <deque> #include <string> #include "llstring.h" +#include "llthread.h" // Fixed size buffer for console output and other things. @@ -53,14 +54,19 @@ public: std::deque<S32> mLineLengths; void clear(); // Clear the buffer, and reset it. - virtual void addLine(const std::string& utf8line); - virtual void addLine(const LLWString& line); + + //do not make these two "virtual" + void addLine(const std::string& utf8line); + void addLine(const LLWString& line); // Get lines currently in the buffer, up to max_size chars, max_length lines char *getLines(U32 max_size = 0, U32 max_length = 0); void setMaxLines(S32 max_lines); protected: virtual void removeExtraLines(); + +protected: + LLMutex mMutex ; }; const U32 FIXED_BUF_MAX_LINE_LEN = 255; // Not including termnating 0 diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 01647c671b..920d8c0977 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -102,12 +102,20 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread } mRunCondition = new LLCondition(mAPRPoolp); + + mLocalAPRFilePoolp = NULL ; } LLThread::~LLThread() { shutdown(); + + if(mLocalAPRFilePoolp) + { + delete mLocalAPRFilePoolp ; + mLocalAPRFilePoolp = NULL ; + } } void LLThread::shutdown() diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index d48d1ba7fa..c8c9fd4eec 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -83,7 +83,8 @@ public: void start(void); apr_pool_t *getAPRPool() { return mAPRPoolp; } - + LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } + private: BOOL mPaused; @@ -99,6 +100,11 @@ protected: BOOL mIsLocalPool; EThreadStatus mStatus; + //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. + //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. + // otherwise it will cause severe memory leaking!!! --bao + LLVolatileAPRPool *mLocalAPRFilePoolp ; + void setQuitting(); // virtual function overridden by subclass -- this will be called when the thread runs diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index cdc7c02348..5dda600755 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -37,16 +37,18 @@ #include "llframecallbackmanager.h" #endif -BOOL LLWorkerClass::sDeleteLock = FALSE ; //============================================================================ // Run on MAIN thread LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : - LLQueuedThread(name, threaded), - mWorkerAPRPoolp(NULL) + LLQueuedThread(name, threaded) { - apr_pool_create(&mWorkerAPRPoolp, NULL); - mDeleteMutex = new LLMutex(getAPRPool()); + mDeleteMutex = new LLMutex(NULL); + + if(!mLocalAPRFilePoolp) + { + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + } } LLWorkerThread::~LLWorkerThread() @@ -96,7 +98,6 @@ S32 LLWorkerThread::update(U32 max_time_ms) { (*iter)->abortWork(false); } - LLWorkerClass::sDeleteLock = TRUE ; for (std::vector<LLWorkerClass*>::iterator iter = delete_list.begin(); iter != delete_list.end(); ++iter) { @@ -110,8 +111,7 @@ S32 LLWorkerThread::update(U32 max_time_ms) } delete *iter; } - LLWorkerClass::sDeleteLock = FALSE ; - // delete and aborted entries mean there's still work to do + // delete and aborted entries mean there's still work to do res += delete_list.size() + abort_list.size(); return res; } @@ -188,7 +188,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na : mWorkerThread(workerthread), mWorkerClassName(name), mRequestHandle(LLWorkerThread::nullHandle()), - mMutex(workerthread->getWorkerAPRPool()), + mMutex(NULL), mWorkFlags(0) { if (!mWorkerThread) diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 745310840b..19407f4463 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -38,6 +38,7 @@ #include <set> #include "llqueuedthread.h" +#include "llapr.h" #define USE_FRAME_CALLBACK_MANAGER 0 @@ -82,14 +83,11 @@ private: typedef std::list<LLWorkerClass*> delete_list_t; delete_list_t mDeleteList; LLMutex* mDeleteMutex; - apr_pool_t* mWorkerAPRPoolp; public: LLWorkerThread(const std::string& name, bool threaded = true); ~LLWorkerThread(); - apr_pool_t* getWorkerAPRPool() { return mWorkerAPRPoolp; } - /*virtual*/ S32 update(U32 max_time_ms); handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); @@ -121,8 +119,6 @@ class LLWorkerClass friend class LLWorkerThread::WorkRequest; public: - static BOOL sDeleteLock ; -public: typedef LLWorkerThread::handle_t handle_t; enum FLAGS { diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index c550304c6b..78c4f8e742 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -392,7 +392,7 @@ bool LLCrashLogger::init() if( gDirUtilp ) { std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.exec_marker"); - ll_apr_file_remove( marker_file ); + LLAPRFile::remove( marker_file ); } return true; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index bfa129ea1d..88edc9943c 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1513,7 +1513,9 @@ BOOL LLImageFormatted::load(const std::string &filename) resetLastError(); S32 file_size = 0; - apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + apr_file_t* apr_file = infile.getFileHandle(); if (!apr_file) { setLastError("Unable to open file for reading", filename); @@ -1522,7 +1524,6 @@ BOOL LLImageFormatted::load(const std::string &filename) if (file_size == 0) { setLastError("File is empty",filename); - apr_file_close(apr_file); return FALSE; } @@ -1540,8 +1541,7 @@ BOOL LLImageFormatted::load(const std::string &filename) { res = updateData(); } - apr_file_close(apr_file); - + return res; } @@ -1549,16 +1549,16 @@ BOOL LLImageFormatted::save(const std::string &filename) { resetLastError(); - apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_WB); - if (!apr_file) + LLAPRFile outfile ; + outfile.open(filename, LL_APR_WB); + if (!outfile.getFileHandle()) { setLastError("Unable to open file for writing", filename); return FALSE; } - ll_apr_file_write(apr_file, getData(), getDataSize()); - apr_file_close(apr_file); - + outfile.write(getData(), getDataSize()); + outfile.close() ; return TRUE; } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 52eb009cb7..1b93c21982 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -419,7 +419,9 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) resetLastError(); S32 file_size = 0; - apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size); + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + apr_file_t* apr_file = infile.getFileHandle() ; if (!apr_file) { setLastError("Unable to open file for reading", filename); @@ -428,7 +430,6 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) else if (file_size == 0) { setLastError("File is empty",filename); - apr_file_close(apr_file); res = FALSE; } else @@ -436,7 +437,8 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) U8 *data = new U8[file_size]; apr_size_t bytes_read = file_size; apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read - apr_file_close(apr_file); + infile.close() ; + if (s != APR_SUCCESS || (S32)bytes_read != file_size) { delete[] data; @@ -448,7 +450,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) res = validate(data, file_size); } } - + if (!mLastError.empty()) { LLImage::setLastError(mLastError); diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index b782d4f3b9..0f343bcefe 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -178,28 +178,95 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) U8 mask = 0; S32 result = 2; - for (U32 i = 0; i < mPlaneCount; i++) - { - mask = mAgentPlanes[i].mask; - LLPlane p = mAgentPlanes[i].p; - LLVector3 n = LLVector3(p); - float d = p.mV[3]; - LLVector3 rscale = radius.scaledVec(scaler[mask]); + if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist) + { //box is larger than frustum, check frustum quads against box planes - LLVector3 minp = center - rscale; - LLVector3 maxp = center + rscale; - - if (n * minp > -d) + static const LLVector3 dir[] = { - return 0; + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), + LLVector3(0, 1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1) + }; + + U32 quads[] = + { + 0, 1, 2, 3, + 0, 1, 5, 4, + 2, 3, 7, 6, + 3, 0, 7, 4, + 1, 2, 6, 4, + 4, 5, 6, 7 + }; + + result = 0; + + BOOL total_inside = TRUE; + for (U32 i = 0; i < 6; i++) + { + LLVector3 p = center + radius.scaledVec(dir[i]); + F32 d = -p*dir[i]; + + for (U32 j = 0; j < 6; j++) + { //for each quad + F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d; + if (dist > 0) + { //at least one frustum point is outside the AABB + total_inside = FALSE; + for (U32 k = 1; k < 4; k++) + { //for each other point on quad + if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d <= 0.f) + { //quad is straddling some plane of AABB + return 1; + } + } + } + else + { + for (U32 k = 1; k < 4; k++) + { + if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f) + { + return 1; + } + } + } + } } - - if (n * maxp > -d) + + if (total_inside) { result = 1; } } + else + { + for (U32 i = 0; i < mPlaneCount; i++) + { + mask = mAgentPlanes[i].mask; + LLPlane p = mAgentPlanes[i].p; + LLVector3 n = LLVector3(p); + float d = p.mV[3]; + LLVector3 rscale = radius.scaledVec(scaler[mask]); + + LLVector3 minp = center - rscale; + LLVector3 maxp = center + rscale; + + if (n * minp > -d) + { + return 0; + } + + if (n * maxp > -d) + { + result = 1; + } + } + } + return result; } diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 5e987f3193..12fc116714 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -86,6 +86,8 @@ const F32 GRAVITY = -9.8f; const F32 F_PI = 3.1415926535897932384626433832795f; const F32 F_TWO_PI = 6.283185307179586476925286766559f; const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f; +const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f; +const F32 F_E = 2.71828182845904523536f; const F32 F_SQRT2 = 1.4142135623730950488016887242097f; const F32 F_SQRT3 = 1.73205080756888288657986402541f; const F32 OO_SQRT2 = 0.7071067811865475244008443621049f; @@ -548,4 +550,10 @@ inline U32 get_next_power_two(U32 val, U32 max_power_two) return val; } +//get the gaussian value given the linear distance from axis x and guassian value o +inline F32 llgaussian(F32 x, F32 o) +{ + return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); +} + #endif diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index af6b7fee2c..fe37fe8142 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -470,9 +470,7 @@ bool LLAres::process(U64 timeout) int socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; - apr_int32_t nsds = 0; - apr_status_t status; - apr_pool_t *pool; + apr_int32_t nsds = 0; int nactive = 0; int bitmask; @@ -480,10 +478,12 @@ bool LLAres::process(U64 timeout) if (bitmask == 0) { - goto bail; + return nsds > 0; } - status = apr_pool_create(&pool, gAPRPoolp); + apr_status_t status; + LLAPRPool pool; + status = pool.getStatus() ; ll_apr_assert_status(status); for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) @@ -501,16 +501,16 @@ bool LLAres::process(U64 timeout) apr_socket_t *aprSock = NULL; - status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool); + status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); if (status != APR_SUCCESS) { ll_apr_warn_status(status); - goto bail_pool; + return nsds > 0; } aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc_type = APR_POLL_SOCKET; - aprFds[nactive].p = pool; + aprFds[nactive].p = pool.getAPRPool(); aprFds[nactive].rtnevents = 0; aprFds[nactive].client_data = &socks[i]; @@ -538,10 +538,6 @@ bool LLAres::process(U64 timeout) } } -bail_pool: - apr_pool_destroy(pool); - -bail: return nsds > 0; } diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 6ef97bea58..46e976fe35 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -44,7 +44,7 @@ #include "llsd.h" #include "llstring.h" #include "apr_env.h" - +#include "llapr.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -166,18 +166,16 @@ void LLURLRequest::useProxy(bool use_proxy) if (use_proxy && (env_proxy == NULL)) { apr_status_t status; - apr_pool_t* pool; - apr_pool_create(&pool, NULL); - status = apr_env_get(&env_proxy, "ALL_PROXY", pool); + LLAPRPool pool; + status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); if (status != APR_SUCCESS) { - status = apr_env_get(&env_proxy, "http_proxy", pool); + status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); } if (status != APR_SUCCESS) { use_proxy = FALSE; } - apr_pool_destroy(pool); } diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 76858d9839..72aa3715c0 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -27,9 +27,7 @@ set(llrender_SOURCE_FILES llglslshader.cpp llimagegl.cpp llpostprocess.cpp - llrender.cpp llrendersphere.cpp - llrendertarget.cpp llshadermgr.cpp llvertexbuffer.cpp ) @@ -50,7 +48,6 @@ set(llrender_HEADER_FILES llpostprocess.h llrender.h llrendersphere.h - llrendertarget.h llshadermgr.h llvertexbuffer.h ) @@ -63,6 +60,7 @@ list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES}) if (SERVER AND NOT WINDOWS AND NOT DARWIN) copy_server_sources( llgl + llrender ) @@ -78,6 +76,8 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) else (SERVER AND NOT WINDOWS AND NOT DARWIN) list(APPEND llrender_SOURCE_FILES llgl.cpp + llrender.cpp + llrendertarget.cpp ) endif (SERVER AND NOT WINDOWS AND NOT DARWIN) add_library (llrender ${llrender_SOURCE_FILES}) diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 14b95c25e7..754d90c854 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -85,9 +85,9 @@ void LLCubeMap::initGL() // Not initialized, do stuff. if (mImages[0].isNull()) { - GLuint texname = 0; + U32 texname = 0; - glGenTextures(1, &texname); + LLImageGL::generateTextures(1, &texname); for (int i = 0; i < 6; i++) { @@ -97,9 +97,10 @@ void LLCubeMap::initGL() mImages[i]->createGLTexture(0, mRawImages[i], texname); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); - mImages[i]->setClampCubemap (TRUE, TRUE, TRUE); + mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } + gGL.getTexUnit(0)->disable(); } disable(); } @@ -311,8 +312,8 @@ void LLCubeMap::restoreMatrix() void LLCubeMap::setReflection (void) { gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName()); - mImages[0]->setMipFilterNearest (FALSE, FALSE); - mImages[0]->setClampCubemap (TRUE, TRUE); + mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP); } LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 846f18f4a9..3829306e25 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -535,7 +535,7 @@ BOOL LLFontGL::loadFace(const std::string& filename, } mImageGLp->createGLTexture(0, mRawImageGLp); gGL.getTexUnit(0)->bind(mImageGLp); - mImageGLp->setMipFilterNearest(TRUE, TRUE); + mImageGLp->setFilteringOption(LLTexUnit::TFO_POINT); return TRUE; } @@ -549,7 +549,7 @@ BOOL LLFontGL::addChar(const llwchar wch) stop_glerror(); mImageGLp->setSubImage(mRawImageGLp, 0, 0, mImageGLp->getWidth(), mImageGLp->getHeight()); gGL.getTexUnit(0)->bind(mImageGLp); - mImageGLp->setMipFilterNearest(TRUE, TRUE); + mImageGLp->setFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); return TRUE; } @@ -565,7 +565,7 @@ S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset, BOOL use_ellipses) const { LLWString wstr = utf8str_to_wstring(text); - return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, use_ellipses); + return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses); } S32 LLFontGL::render(const LLWString &wstr, @@ -1104,59 +1104,32 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ llwchar wch = wchars[i]; const embedded_data_t* ext_data = getEmbeddedCharData(wch); - if (ext_data) - { - F32 char_width = getEmbeddedCharAdvance(ext_data); - - if( scaled_max_pixels < (total_width + char_width) ) - { - break; - } - - total_width += char_width; - - drawable_chars++; - if( max_chars >= 0 && drawable_chars >= max_chars ) - { - break; - } - - if ( i > 0 ) - { - total_width += EXT_KERNING * sScaleX; - } + F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch); - // Round after kerning. - total_width = (F32)llfloor(total_width + 0.5f); - } - else + if( scaled_max_pixels < (total_width + char_width) ) { - F32 char_width = getXAdvance(wch); - if( scaled_max_pixels < (total_width + char_width) ) - { - break; - } - - total_width += char_width; + break; + } - drawable_chars++; - if( max_chars >= 0 && drawable_chars >= max_chars ) - { - break; - } + total_width += char_width; + drawable_chars++; - if ( i > 0 ) - { - // Kerning - total_width += getXKerning(wchars[i-1], wch); - } + if( max_chars >= 0 && drawable_chars >= max_chars ) + { + break; + } - // Round after kerning. - total_width = (F32)llfloor(total_width + 0.5f); + if ( i > 0 ) + { + // kerning + total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch); } + + // Round after kerning. + total_width = llround(total_width); } - return text_len - drawable_chars; + return start_pos - drawable_chars; } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index b369e42ce1..f8da460de2 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -181,7 +181,7 @@ public: F32* drawn_pixels = NULL) const; // Returns the index of the first complete characters from text that can be drawn in max_pixels - // starting on the right side (at character start_pos). + // given that the character at start_pos should be the last character (or as close to last as possible). virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 74313974c9..61194c4ecf 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -133,6 +133,15 @@ PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; +// GL_EXT_framebuffer_multisample +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; + +// GL_EXT_framebuffer_blit +PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; + +// GL_ARB_draw_buffers +PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL; + //shader object prototypes PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; PFNGLGETHANDLEARBPROC glGetHandleARB = NULL; @@ -249,6 +258,12 @@ PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; #endif +#if LL_LINUX_NV_GL_HEADERS +// linux nvidia headers. these define these differently to mesa's. ugh. +PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL; +PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL; +#endif // LL_LINUX_NV_GL_HEADERS #endif LLGLManager gGLManager; @@ -262,6 +277,7 @@ LLGLManager::LLGLManager() : mHasMipMapGeneration(FALSE), mHasCompressedTextures(FALSE), mHasFramebufferObject(FALSE), + mHasFramebufferMultisample(FALSE), mHasVertexBufferObject(FALSE), mHasPBuffer(FALSE), @@ -561,6 +577,16 @@ void LLGLManager::initExtensions() # else mHasFramebufferObject = FALSE; # endif +# if GL_EXT_framebuffer_multisample + mHasFramebufferMultisample = TRUE; +# else + mHasFramebufferMultisample = FALSE; +# endif +# if GL_ARB_draw_buffers + mHasDrawBuffers = TRUE; +#else + mHasDrawBuffers = FALSE; +# endif mHasMipMapGeneration = FALSE; mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; @@ -584,6 +610,8 @@ void LLGLManager::initExtensions() // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); + mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); + mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -604,6 +632,8 @@ void LLGLManager::initExtensions() mHasCompressedTextures = FALSE; mHasVertexBufferObject = FALSE; mHasFramebufferObject = FALSE; + mHasFramebufferMultisample = FALSE; + mHasDrawBuffers = FALSE; mHasMipMapGeneration = FALSE; mHasSeparateSpecularColor = FALSE; mHasAnisotropic = FALSE; @@ -653,6 +683,9 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S + if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S + if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; + } #endif // LL_LINUX || LL_SOLARIS @@ -761,15 +794,29 @@ void LLGLManager::initExtensions() glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); } -#if !LL_LINUX && !LL_SOLARIS - // This is expected to be a static symbol on Linux GL implementations + if (mHasFramebufferMultisample) + { + glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); + glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT"); + } + if (mHasDrawBuffers) + { + glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB"); + } +#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS + // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); if (!glDrawRangeElements) { mGLMaxVertexRange = 0; mGLMaxIndexRange = 0; } -#endif // !LL_LINUX +#endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS +#if LL_LINUX_NV_GL_HEADERS + // nvidia headers are critically different from mesa-esque + glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB"); + glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB"); +#endif // LL_LINUX_NV_GL_HEADERS if (mHasOcclusionQuery) { @@ -946,7 +993,7 @@ void assert_glerror() { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. - LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << LL_ENDL; + LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; } error = glGetError(); #endif @@ -986,6 +1033,11 @@ void LLGLState::initClass() //make sure multisample defaults to disabled sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; glDisable(GL_MULTISAMPLE_ARB); + + sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; + glDisable(GL_MULTISAMPLE_ARB); + + glEnableClientState(GL_VERTEX_ARRAY); } //static @@ -1037,7 +1089,7 @@ void LLGLState::checkStates(const std::string& msg) if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) { - LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << LL_ENDL; + LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; } for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); @@ -1076,7 +1128,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) if (tex_env_mode != GL_MODULATE) { error = TRUE; - LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << LL_ENDL; + LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL; } } @@ -1092,7 +1144,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) "GL_TEXTURE_GEN_S", "GL_TEXTURE_GEN_T", "GL_TEXTURE_GEN_Q", - "GL_TEXTURE_GEN_R" + "GL_TEXTURE_GEN_R", + "GL_TEXTURE_RECTANGLE_ARB" }; static GLint value[] = @@ -1104,7 +1157,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T, GL_TEXTURE_GEN_Q, - GL_TEXTURE_GEN_R + GL_TEXTURE_GEN_R, + GL_TEXTURE_RECTANGLE_ARB }; GLint stackDepth = 0; @@ -1132,7 +1186,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; } - for (S32 j = (i == 0 ? 1 : 0); j < 8; j++) + for (S32 j = (i == 0 ? 1 : 0); j < 9; j++) { if (glIsEnabled(value[j])) { @@ -1140,6 +1194,18 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; } } + + glh::matrix4f mat; + glh::matrix4f identity; + identity.identity(); + + glGetFloatv(GL_TEXTURE_MATRIX, mat.m); + + if (mat != identity) + { + error = TRUE; + LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; + } } gGL.getTexUnit(0)->activate(); @@ -1261,6 +1327,22 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); + if (gGLManager.mHasVertexShader) + { //make sure vertex attribs are all disabled + GLint count; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count); + for (GLint i = 0; i < count; i++) + { + GLint enabled; + glGetVertexAttribivARB((GLuint) i, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &enabled); + if (enabled) + { + error = TRUE; + LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; + } + } + } + if (error) { LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; @@ -1646,6 +1728,7 @@ void LLGLNamePool::cleanupPools() LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func) : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) { + stop_glerror(); if (depth_enabled != sDepthEnabled) { gGL.flush(); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 8caef2016e..00ff1e2f53 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -77,7 +77,8 @@ public: BOOL mHasMipMapGeneration; BOOL mHasCompressedTextures; BOOL mHasFramebufferObject; - + BOOL mHasFramebufferMultisample; + // ARB Extensions BOOL mHasVertexBufferObject; BOOL mHasPBuffer; @@ -86,6 +87,7 @@ public: BOOL mHasFragmentShader; BOOL mHasOcclusionQuery; BOOL mHasPointParameters; + BOOL mHasDrawBuffers; // Other extensions. BOOL mHasAnisotropic; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index e9a9ad1a77..91a01a9266 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -281,6 +281,18 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; #undef Status #endif // LL_LINUX && !LL_MESA_HEADLESS +#if LL_LINUX && defined(WINGDIAPI) +// WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs +// the functions below setting up. +# define LL_LINUX_NV_GL_HEADERS +#endif // LL_LINUX && defined(WINGDIAPI) + +#ifdef LL_LINUX_NV_GL_HEADERS +// Missing functions when using nvidia headers: +extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; +extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; +extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; +#endif // LL_LINUX_NV_GL_HEADERS // GL_ARB_vertex_buffer_object extern PFNGLBINDBUFFERARBPROC glBindBufferARB; @@ -435,8 +447,6 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; -extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; - //GL_EXT_framebuffer_object extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -456,6 +466,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +// GL_EXT_framebuffer_multisample +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; + +// GL_EXT_framebuffer_blit +extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; + +//GL_ARB_draw_buffers +extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; #elif LL_WINDOWS @@ -644,6 +662,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +// GL_EXT_framebuffer_multisample +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; + +// GL_EXT_framebuffer_blit +extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; + +//GL_ARB_draw_buffers +extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; #elif LL_DARWIN //---------------------------------------------------------------------------- @@ -680,6 +706,8 @@ extern void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenu extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +// GL_ARB_draw_buffers +extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; #ifdef __cplusplus extern "C" { diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 6464846c63..08d654805e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -256,6 +256,14 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) S32 location = glGetUniformLocationARB(mProgramObject, name); if (location != -1) { + //chop off "[0]" so we can always access the first element + //of an array by the array name + char* is_array = strstr(name, "[0]"); + if (is_array) + { + is_array[0] = 0; + } + mUniformMap[name] = location; LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; @@ -353,11 +361,17 @@ void LLGLSLShader::unbind() { if (gGLManager.mHasShaderObjects) { - for (U32 i = 0; i < mAttribute.size(); ++i) + stop_glerror(); + if (gGLManager.mIsNVIDIA) { - vertexAttrib4f(i, 0,0,0,1); + for (U32 i = 0; i < mAttribute.size(); ++i) + { + vertexAttrib4f(i, 0,0,0,1); + stop_glerror(); + } } glUseProgramObjectARB(0); + stop_glerror(); } } @@ -390,14 +404,39 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) return -1; } S32 index = mTexture[uniform]; - if (index != -1) + if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) { - gGL.getTexUnit(index)->activate(); + if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) + { + llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + } gGL.getTexUnit(index)->disable(); } return index; } +void LLGLSLShader::uniform1i(U32 index, GLint x) +{ + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + if (iter == mValue.end() || iter->second.mV[0] != x) + { + glUniform1iARB(mUniform[index], x); + mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); + } + } + } +} + void LLGLSLShader::uniform1f(U32 index, GLfloat x) { if (mProgramObject > 0) @@ -489,6 +528,29 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat } } +void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) +{ + if (mProgramObject > 0) + { + if (mUniform.size() <= index) + { + UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + std::map<GLint, LLVector4>::iterator 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) + { + glUniform1ivARB(mUniform[index], count, v); + mValue[mUniform[index]] = vec; + } + } + } +} + void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) { if (mProgramObject > 0) @@ -647,6 +709,22 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform) return -1; } +void LLGLSLShader::uniform1i(const string& uniform, GLint v) +{ + GLint location = getUniformLocation(uniform); + + if (location >= 0) + { + std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + LLVector4 vec(v,0.f,0.f,0.f); + if (iter == mValue.end() || shouldChange(iter->second,vec)) + { + glUniform1iARB(location, v); + mValue[location] = vec; + } + } +} + void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) { GLint location = getUniformLocation(uniform); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index c495a08726..166d4af04c 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -78,18 +78,22 @@ public: BOOL mapAttributes(const std::vector<std::string> * attributes); BOOL mapUniforms(const std::vector<std::string> * uniforms); void mapUniform(GLint index, const std::vector<std::string> * uniforms); + void uniform1i(U32 index, GLint i); void uniform1f(U32 index, GLfloat v); void uniform2f(U32 index, GLfloat x, GLfloat y); void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform1iv(U32 index, U32 count, const GLint* i); void uniform1fv(U32 index, U32 count, const GLfloat* v); void uniform2fv(U32 index, U32 count, const GLfloat* v); void uniform3fv(U32 index, U32 count, const GLfloat* v); void uniform4fv(U32 index, U32 count, const GLfloat* v); + void uniform1i(const std::string& uniform, GLint i); void uniform1f(const std::string& uniform, GLfloat v); void uniform2f(const std::string& uniform, GLfloat x, GLfloat y); void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z); void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform1iv(const std::string& uniform, U32 count, const GLint* i); void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v); void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v); void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index f5b596b963..307147798e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -63,7 +63,6 @@ BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; std::set<LLImageGL*> LLImageGL::sImageList; - //************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. @@ -309,21 +308,21 @@ void LLImageGL::init(BOOL usemipmaps) #endif mPickMask = NULL; + mTextureState = NO_DELETE ; mTextureMemory = 0; mLastBindTime = 0.f; mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mUseMipMaps = usemipmaps; - mHasMipMaps = FALSE; + mHasMipMaps = false; mAutoGenMips = FALSE; mTexName = 0; mIsResident = 0; - mClampS = FALSE; - mClampT = FALSE; - mClampR = FALSE; - mMagFilterNearest = FALSE; - mMinFilterNearest = FALSE; + + mTexOptionsDirty = true; + mAddressMode = LLTexUnit::TAM_WRAP; + mFilterOption = LLTexUnit::TFO_ANISOTROPIC; mWidth = 0; mHeight = 0; mComponents = 0; @@ -339,6 +338,7 @@ void LLImageGL::init(BOOL usemipmaps) mHasExplicitFormat = FALSE; mGLTextureCreated = FALSE ; + mIsMask = FALSE; } void LLImageGL::cleanup() @@ -469,6 +469,11 @@ bool LLImageGL::bindDefaultImage(const S32 stage) const return false; } +//virtual +void LLImageGL::forceImmediateUpdate() +{ + return ; +} void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) { @@ -498,7 +503,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { // LLFastTimer t1(LLFastTimer::FTM_TEMP1); - + llpushcallstacks ; bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { @@ -519,6 +524,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) // are stored BEFORE the largest image for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++) { + S32 w = getWidth(d); S32 h = getHeight(d); S32 gl_level = d-mCurrentDiscardLevel; @@ -529,7 +535,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) if (is_compressed) { // LLFastTimer t2(LLFastTimer::FTM_TEMP4); - S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); + S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); stop_glerror(); } @@ -543,7 +549,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - glTexImage2D(mTarget, gl_level, mFormatInternal, w, h, 0, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); + LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); + if (gl_level == 0) + { + analyzeAlpha(data_in, w, h); + } updatePickMask(w, h, data_in); if(mFormatSwapBytes) @@ -575,10 +585,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); - glTexImage2D(mTarget, 0, mFormatInternal, - w, h, 0, + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, + w, h, mFormatPrimary, mFormatType, data_in); + analyzeAlpha(data_in, w, h); stop_glerror(); updatePickMask(w, h, data_in); @@ -630,7 +641,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data); + LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data); + if (m == 0) + { + analyzeAlpha(data_in, w, h); + } stop_glerror(); if (m == 0) { @@ -663,7 +678,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; } - mHasMipMaps = TRUE; + mHasMipMaps = true; } else { @@ -684,8 +699,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - glTexImage2D(mTarget, 0, mFormatInternal, w, h, 0, + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, (GLvoid *)data_in); + analyzeAlpha(data_in, w, h); + updatePickMask(w, h, data_in); stop_glerror(); @@ -697,14 +714,16 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } } - mHasMipMaps = FALSE; + mHasMipMaps = false; } stop_glerror(); mGLTextureCreated = true; + llpushcallstacks ; } BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) { + llpushcallstacks ; if (!width || !height) { return TRUE; @@ -780,6 +799,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 glTexSubImage2D(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, datap); + gGL.getTexUnit(0)->disable(); stop_glerror(); if(mFormatSwapBytes) @@ -792,6 +812,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 stop_glerror(); mGLTextureCreated = true; } + llpushcallstacks ; return TRUE; } @@ -816,6 +837,24 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } } +// static +void LLImageGL::generateTextures(S32 numTextures, U32 *textures) +{ + glGenTextures(numTextures, (GLuint*)textures); +} + +// static +void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +{ + glDeleteTextures(numTextures, (GLuint*)textures); +} + +// static +void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) +{ + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); +} + //create an empty GL texture: just create a texture name //the texture is assiciate with some image by calling glTexImage outside LLImageGL BOOL LLImageGL::createGLTexture() @@ -848,6 +887,7 @@ BOOL LLImageGL::createGLTexture() BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) { + llpushcallstacks ; if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; @@ -908,6 +948,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { + llpushcallstacks ; llassert(data_in); if (discard_level < 0) @@ -924,7 +965,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } - GLuint old_name = mTexName; + U32 old_name = mTexName; // S32 old_discard = mCurrentDiscardLevel; if (usename != 0) @@ -933,7 +974,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } else { - glGenTextures(1, (GLuint*)&mTexName); + LLImageGL::generateTextures(1, &mTexName); stop_glerror(); { // LLFastTimer t1(LLFastTimer::FTM_TEMP6); @@ -963,9 +1004,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ setImage(data_in, data_hasmips); - setClamp(mClampS, mClampT); - setMipFilterNearest(mMagFilterNearest); - + // 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(); @@ -973,16 +1016,18 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { sGlobalTextureMemory -= mTextureMemory; - glDeleteTextures(1, &old_name); + LLImageGL::deleteTextures(1, &old_name); stop_glerror(); } mTextureMemory = getMipBytes(discard_level); sGlobalTextureMemory += mTextureMemory; - + setActive() ; + // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; + llpushcallstacks ; return TRUE; } @@ -1055,6 +1100,7 @@ BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_h BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) { + llpushcallstacks ; if (discard_level < 0) { discard_level = mCurrentDiscardLevel; @@ -1069,7 +1115,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre //explicitly unbind texture gGL.getTexUnit(0)->unbind(mBindTarget); - llverify(gGL.getTexUnit(0)->bind(this)); + llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName)); //debug code, leave it there commented. //checkTexSize() ; @@ -1157,7 +1203,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return FALSE ; } //----------------------------------------------------------------------------------------------- - + llpushcallstacks ; return TRUE ; } @@ -1179,8 +1225,10 @@ void LLImageGL::destroyGLTexture() sGlobalTextureMemory -= mTextureMemory; mTextureMemory = 0; - glDeleteTextures(1, (GLuint*)&mTexName); + LLImageGL::deleteTextures(1, &mTexName); + mTextureState = DELETED ; mTexName = 0; + mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mGLTextureCreated = FALSE ; stop_glerror(); } @@ -1188,89 +1236,35 @@ void LLImageGL::destroyGLTexture() //---------------------------------------------------------------------------- -void LLImageGL::glClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr) -{ - glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); -} - -void LLImageGL::glClamp (BOOL clamps, BOOL clampt) +void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { - if (mTexName != 0) + if (mAddressMode != mode) { - glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT); + mTexOptionsDirty = true; + mAddressMode = mode; } -} -void LLImageGL::setClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr) -{ - mClampS = clamps; - mClampT = clampt; - mClampR = clampr; - glClampCubemap (clamps, clampt, clampr); -} - -void LLImageGL::setClamp(BOOL clamps, BOOL clampt) -{ - mClampS = clamps; - mClampT = clampt; - glClamp (clamps, clampt); -} - -void LLImageGL::overrideClamp (BOOL clamps, BOOL clampt) -{ - glClamp (clamps, clampt); -} - -void LLImageGL::restoreClamp (void) -{ - glClamp (mClampS, mClampT); + if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + { + gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode); + mTexOptionsDirty = false; + } } -void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest) +void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) { - mMagFilterNearest = mag_nearest; - mMinFilterNearest = min_nearest; + if (mFilterOption != option) + { + mTexOptionsDirty = true; + mFilterOption = option; + } - if (mTexName != 0) + if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) { - if (mMinFilterNearest) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - else if (mHasMipMaps) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - if (mMagFilterNearest) - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else - { - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - if (gGLManager.mHasAnisotropic) - { - if (sGlobalUseAnisotropic && !mMagFilterNearest) - { - F32 largest_anisotropy; - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_anisotropy); - glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy); - } - else - { - glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - } - } - stop_glerror(); - } + gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); + mTexOptionsDirty = false; + } + stop_glerror(); } BOOL LLImageGL::getIsResident(BOOL test_now) @@ -1357,6 +1351,115 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b mBindTarget = bind_target; } +void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) +{ + if (mFormatType != GL_UNSIGNED_BYTE) + { + llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; + } + + U32 stride = 0; + switch (mFormatPrimary) + { + case GL_LUMINANCE: + case GL_ALPHA: + stride = 1; + break; + case GL_LUMINANCE_ALPHA: + stride = 2; + break; + case GL_RGB: + //no alpha + mIsMask = FALSE; + return; + case GL_RGBA: + stride = 4; + break; + default: + llwarns << "Cannot analyze alpha of image with primary format " << std::hex << mFormatPrimary << std::dec << llendl; + return; + } + + U32 length = w * h; + const GLubyte* current = ((const GLubyte*) data_in)+stride-1; + + S32 sample[16]; + memset(sample, 0, sizeof(S32)*16); + + for (U32 i = 0; i < length; i++) + { + ++sample[*current/16]; + current += stride; + } + + U32 total = 0; + for (U32 i = 4; i < 11; i++) + { + total += sample[i]; + } + + if (total > length/16) + { + mIsMask = FALSE; + } + else + { + mIsMask = TRUE; + } +} + +BOOL LLImageGL::isDeleted() +{ + return mTextureState == DELETED ; +} + +BOOL LLImageGL::isInactive() +{ + return mTextureState == INACTIVE ; +} + +BOOL LLImageGL::isDeletionCandidate() +{ + return mTextureState == DELETION_CANDIDATE ; +} + +void LLImageGL::setDeletionCandidate() +{ + if(mTexName && (mTextureState == INACTIVE)) + { + mTextureState = DELETION_CANDIDATE ; + } +} + +void LLImageGL::forceActive() +{ + mTextureState = ACTIVE ; +} + +void LLImageGL::setActive() +{ + if(mTextureState != NO_DELETE) + { + mTextureState = ACTIVE ; + } +} + +//set the texture inactive +void LLImageGL::setInactive() +{ + if(mTexName && (mTextureState == ACTIVE) && !getBoundRecently()) + { + mTextureState = INACTIVE ; + } +} + +//set the texture to stay in memory +void LLImageGL::setNoDelete() +{ + mTextureState = NO_DELETE ; +} + +//---------------------------------------------------------------------------- void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) { if (mFormatType != GL_UNSIGNED_BYTE || @@ -1469,7 +1572,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) llassert(w > 0 && h > 0 && cur_mip_data); U8 test = cur_mip_data[w*h*mComponents-1]; { - glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data); + LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data); stop_glerror(); } if (prev_mip_data && prev_mip_data != rawdata) diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index cb565939d9..4f737bcaae 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -46,6 +46,7 @@ class LLImageGL : public LLRefCount { + friend class LLTexUnit; public: // Size calculation static S32 dataFormatBits(S32 dataformat); @@ -80,17 +81,22 @@ public: protected: virtual ~LLImageGL(); -private: - void glClamp (BOOL clamps, BOOL clampt); - void glClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr = FALSE); + void analyzeAlpha(const void* data_in, S32 w, S32 h); public: virtual void dump(); // debugging info to llinfos virtual bool bindError(const S32 stage = 0) const; virtual bool bindDefaultImage(const S32 stage = 0) const; + virtual void forceImmediateUpdate() ; void setSize(S32 width, S32 height, S32 ncomponents); + // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() + // for tracking purposes and will be deprecated in the future + static void generateTextures(S32 numTextures, U32 *textures); + static void deleteTextures(S32 numTextures, U32 *textures); + static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); + BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); @@ -103,14 +109,9 @@ public: // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); void destroyGLTexture(); - - void setClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr = FALSE); - void setClamp(BOOL clamps, BOOL clampt); - void overrideClamp (BOOL clamps, BOOL clampt); - void restoreClamp (void); - void setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest = FALSE); + void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); - void dontDiscard() { mDontDiscard = 1; } + void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } S32 getDiscardLevel() const { return mCurrentDiscardLevel; } S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } @@ -124,15 +125,12 @@ public: S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } - - BOOL getClampS() const { return mClampS; } - BOOL getClampT() const { return mClampT; } - BOOL getClampR() const { return mClampR; } - BOOL getMipFilterNearest() const { return mMagFilterNearest; } - + BOOL getHasGLTexture() const { return mTexName != 0; } LLGLuint getTexName() const { return mTexName; } + BOOL getIsAlphaMask() const { return mIsMask; } + BOOL getIsResident(BOOL test_now = FALSE); // not const void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target); @@ -152,6 +150,27 @@ public: BOOL getMask(const LLVector2 &tc); void checkTexSize() const ; + + // Sets the addressing mode used to sample the texture + // (such as wrapping, mirrored wrapping, and clamp) + // Note: this actually gets set the next time the texture is bound. + void setAddressMode(LLTexUnit::eTextureAddressMode mode); + LLTexUnit::eTextureAddressMode getAddressMode(void) const { return mAddressMode; } + + // Sets the filtering options used to sample the texture + // (such as point sampling, bilinear interpolation, mipmapping, and anisotropic filtering) + // Note: this actually gets set the next time the texture is bound. + void setFilteringOption(LLTexUnit::eTextureFilterOptions option); + LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } + + BOOL isDeleted() ; + BOOL isInactive() ; + BOOL isDeletionCandidate(); + void setDeletionCandidate() ; + void setInactive() ; + void setActive() ; + void forceActive() ; + void setNoDelete() ; protected: void init(BOOL usemipmaps); @@ -166,9 +185,10 @@ private: LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel S8 mUseMipMaps; - S8 mHasMipMaps; S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) S8 mAutoGenMips; + + BOOL mIsMask; bool mGLTextureCreated ; LLGLuint mTexName; @@ -179,6 +199,7 @@ private: protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) + bool mHasMipMaps; LLGLboolean mIsResident; @@ -186,17 +207,27 @@ protected: S8 mMaxDiscardLevel; S8 mDontDiscard; // Keep full res version of this image (for UI, etc) - S8 mClampS; // Need to save clamp state - S8 mClampT; - S8 mClampR; - S8 mMagFilterNearest; // if TRUE, set magfilter to GL_NEAREST - S8 mMinFilterNearest; // if TRUE, set minfilter to GL_NEAREST + bool mTexOptionsDirty; + LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP + LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_TRILINEAR + LLGLint mFormatInternal; // = GL internalformat LLGLenum mFormatPrimary; // = GL format (pixel data format) LLGLenum mFormatType; BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1) +protected: + typedef enum + { + DELETED = 0, //removed from memory + DELETION_CANDIDATE, //ready to be removed from memory + INACTIVE, //not be used for the last certain period (i.e., 30 seconds). + ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). + NO_DELETE = 99 //stay in memory, can not be removed. + } LLGLTexureState; + LLGLTexureState mTextureState ; + // STATICS public: static std::set<LLImageGL*> sImageList; diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 940abb54d4..7f4be6a866 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -208,7 +208,7 @@ void LLPostProcess::applyShaders(void) /// If any of the above shaders have been called update the frame buffer; if (tweaks.useColorFilter()) { - GLuint tex = mSceneRenderTexture->getTexName() ; + U32 tex = mSceneRenderTexture->getTexName() ; copyFrameBuffer(tex, screenW, screenH); } applyNightVisionShader(); @@ -218,7 +218,7 @@ void LLPostProcess::applyShaders(void) /// If any of the above shaders have been called update the frame buffer; if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) { - GLuint tex = mSceneRenderTexture->getTexName() ; + U32 tex = mSceneRenderTexture->getTexName() ; copyFrameBuffer(tex, screenW, screenH); } applyBloomShader(); @@ -360,7 +360,7 @@ void LLPostProcess::doEffects(void) /// Copy the screen buffer to the render texture { - GLuint tex = mSceneRenderTexture->getTexName() ; + U32 tex = mSceneRenderTexture->getTexName() ; copyFrameBuffer(tex, screenW, screenH); } @@ -386,7 +386,7 @@ void LLPostProcess::doEffects(void) checkError(); } -void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height) +void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); @@ -503,10 +503,8 @@ void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int wi gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } } @@ -523,11 +521,9 @@ void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture) if(texture->createGLTexture()) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); } } diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index e5e34d920c..009e4bd415 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -256,7 +256,7 @@ private: /// OpenGL Helper Functions void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); - void copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height); + void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height); void createNoiseTexture(LLPointer<LLImageGL>& texture); bool checkError(void); void checkShaderError(GLhandleARB shader); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c7068133d2..bee41f556e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -75,7 +75,7 @@ static GLenum sGLCompareFunc[] = GL_GREATER }; -const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD; +const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; static GLenum sGLBlendFactor[] = { @@ -96,7 +96,8 @@ LLTexUnit::LLTexUnit(S32 index) mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), -mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0) +mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), +mHasMipMaps(false) { llassert_always(index < LL_NUM_TEXTURE_LAYERS); mIndex = index; @@ -176,8 +177,9 @@ void LLTexUnit::disable(void) } } -bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) +bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) { + stop_glerror(); if (mIndex < 0) return false; gGL.flush(); @@ -190,15 +192,30 @@ bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) if (!texture->getTexName()) //if texture does not exist { + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate() ; + return texture->bindDefaultImage(mIndex); } - // Disabled caching of binding state. - activate(); - enable(texture->getTarget()); - mCurrTexture = texture->getTexName(); - glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); - texture->updateBindStats(); - return true; + + if (texture != NULL && ((mCurrTexture != texture->getTexName()) || forceBind)) + { + activate(); + enable(texture->getTarget()); + mCurrTexture = texture->getTexName(); + glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); + texture->updateBindStats(); + texture->setActive() ; + mHasMipMaps = texture->mHasMipMaps; + if (texture->mTexOptionsDirty) + { + texture->mTexOptionsDirty = false; + setTextureAddressMode(texture->mAddressMode); + setTextureFilteringOption(texture->mFilterOption); + } + return true; + } + return false; } bool LLTexUnit::bind(LLCubeMap* cubeMap) @@ -207,8 +224,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) gGL.flush(); - // Disabled caching of binding state. - if (cubeMap != NULL) + if (cubeMap != NULL && mCurrTexture != cubeMap->mImages[0]->getTexName()) { if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { @@ -216,8 +232,14 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) enable(LLTexUnit::TT_CUBE_MAP); mCurrTexture = cubeMap->mImages[0]->getTexName(); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture); + mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; cubeMap->mImages[0]->updateBindStats(); - cubeMap->mImages[0]->setMipFilterNearest (FALSE, FALSE); + if (cubeMap->mImages[0]->mTexOptionsDirty) + { + cubeMap->mImages[0]->mTexOptionsDirty = false; + setTextureAddressMode(cubeMap->mImages[0]->mAddressMode); + setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); + } return true; } else @@ -228,6 +250,8 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) return false; } +// LLRenderTarget is unavailible on the mapserver since it uses FBOs. +#if !LL_MESA_HEADLESS bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) { if (mIndex < 0) return false; @@ -245,23 +269,26 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) return true; } +#endif // LL_MESA_HEADLESS -bool LLTexUnit::bindManual(eTextureType type, U32 texture) +bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { - if (mIndex < 0) return false; + if (mIndex < 0 || mCurrTexture == texture) return false; - // Disabled caching of binding state. gGL.flush(); activate(); enable(type); mCurrTexture = texture; glBindTexture(sGLTextureType[type], texture); + mHasMipMaps = hasMips; return true; } void LLTexUnit::unbind(eTextureType type) { + stop_glerror(); + if (mIndex < 0) return; // Disabled caching of binding state. @@ -277,17 +304,57 @@ void LLTexUnit::unbind(eTextureType type) void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) { - if (mIndex < 0) return; + if (mIndex < 0 || mCurrTexture == 0) return; + + activate(); - if (true) + glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); + glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); + if (mCurrTexType == TT_CUBE_MAP) { - activate(); + glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + } +} + +void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) +{ + if (mIndex < 0 || mCurrTexture == 0) return; + + if (option == TFO_POINT) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (option >= TFO_TRILINEAR && mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + else if (option >= TFO_BILINEAR) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); - if (mCurrTexType == TT_CUBE_MAP) + if (gGLManager.mHasAnisotropic) + { + if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + if (gGL.mMaxAnisotropy < 1.f) + { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy); + } + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy); + } + else + { + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } } } @@ -590,12 +657,13 @@ void LLTexUnit::debugTextureUnit(void) LLRender::LLRender() -: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES) +: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES), + mMaxAnisotropy(0.f) { mBuffer = new LLVertexBuffer(immediate_mask, 0); mBuffer->allocateBuffer(4096, 0, TRUE); mBuffer->getVertexStrider(mVerticesp); - mBuffer->getTexCoordStrider(mTexcoordsp); + mBuffer->getTexCoord0Strider(mTexcoordsp); mBuffer->getColorStrider(mColorsp); mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); @@ -688,7 +756,10 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB mCurrColorMask[2] = writeColorB; mCurrColorMask[3] = writeAlpha; - glColorMask(writeColorR, writeColorG, writeColorB, writeAlpha); + glColorMask(writeColorR ? GL_TRUE : GL_FALSE, + writeColorG ? GL_TRUE : GL_FALSE, + writeColorB ? GL_TRUE : GL_FALSE, + writeAlpha ? GL_TRUE : GL_FALSE); } void LLRender::setSceneBlendType(eBlendType type) @@ -768,6 +839,14 @@ bool LLRender::verifyTexUnitActive(U32 unitToVerify) } } +void LLRender::clearErrors() +{ + while (glGetError()) + { + //loop until no more error flags left + } +} + void LLRender::begin(const GLuint& mode) { if (mode != mMode) @@ -853,13 +932,14 @@ void LLRender::flush() mBuffer->setBuffer(immediate_mask); mBuffer->drawArrays(mMode, 0, mCount); - + mVerticesp[0] = mVerticesp[mCount]; mTexcoordsp[0] = mTexcoordsp[mCount]; mColorsp[0] = mColorsp[mCount]; mCount = 0; } } + void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) { //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 752a4e0b37..437c715c2f 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -71,6 +71,14 @@ public: TAM_CLAMP // No texture type is currently enabled } eTextureAddressMode; + typedef enum + { // Note: If mipmapping or anisotropic are not enabled or supported it should fall back gracefully + TFO_POINT = 0, // Equal to: min=point, mag=point, mip=none. + TFO_BILINEAR, // Equal to: min=linear, mag=linear, mip=point. + TFO_TRILINEAR, // Equal to: min=linear, mag=linear, mip=linear. + TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear. + } eTextureFilterOptions; + typedef enum { TB_REPLACE = 0, @@ -131,30 +139,43 @@ public: // Sets this tex unit to be the currently active one void activate(void); - // Enables this texture unit for the given texture type (automatically disables any previously enabled texture type) + // Enables this texture unit for the given texture type + // (automatically disables any previously enabled texture type) void enable(eTextureType type); + // Disables the current texture unit void disable(void); // Binds the LLImageGL to this texture unit // (automatically enables the unit for the LLImageGL's texture type) - bool bind(const LLImageGL* texture, bool forceBind = false); + bool bind(LLImageGL* texture, bool forceBind = false); // Binds a cubemap to this texture unit // (automatically enables the texture unit for cubemaps) bool bind(LLCubeMap* cubeMap); - // Binds a render target to this texture unit (automatically enables the texture unit for the RT's texture type) + // Binds a render target to this texture unit + // (automatically enables the texture unit for the RT's texture type) bool bind(LLRenderTarget * renderTarget, bool bindDepth = false); - // Manually binds a texture to the texture unit (automatically enables the tex unit for the given texture type) - bool bindManual(eTextureType type, U32 texture); + // Manually binds a texture to the texture unit + // (automatically enables the tex unit for the given texture type) + bool bindManual(eTextureType type, U32 texture, bool hasMips = false); - // Unbinds the currently bound texture of the given type (only if there's a texture of the given type currently bound) + // Unbinds the currently bound texture of the given type + // (only if there's a texture of the given type currently bound) void unbind(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. void setTextureAddressMode(eTextureAddressMode mode); + // Sets the filtering options used to sample the texture + // Warning: this stays set for the bound texture forever, + // make sure you want to permanently change the filtering for the bound texture. + void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); + void setTextureBlendType(eTextureBlendType type); inline void setTextureColorBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_COLOR) @@ -166,6 +187,12 @@ public: static U32 getInternalType(eTextureType type); + U32 getCurrTexture(void) { return mCurrTexture; } + + eTextureType getCurrType(void) { return mCurrTexType; } + + void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } + protected: S32 mIndex; U32 mCurrTexture; @@ -179,6 +206,7 @@ protected: eTextureBlendSrc mCurrAlphaSrc2; S32 mCurrColorScale; S32 mCurrAlphaScale; + bool mHasMipMaps; void debugTextureUnit(void); void setColorScale(S32 scale); @@ -292,6 +320,8 @@ public: void debugTexUnits(void); + void clearErrors(); + struct Vertex { GLfloat v[3]; @@ -316,6 +346,8 @@ private: LLStrider<LLColor4U> mColorsp; std::vector<LLTexUnit*> mTexUnits; LLTexUnit* mDummyTexUnit; + + F32 mMaxAnisotropy; }; extern F64 gGLModelView[16]; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 623c1df4db..b7f31779ca 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -37,6 +37,24 @@ #include "llgl.h" +void check_framebuffer_status() +{ + if (gDebugGL) + { + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch (status) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + llerrs << "WTF?" << llendl; + break; + default: + llerrs << "WTF?" << llendl; + } + } +} + BOOL LLRenderTarget::sUseFBO = FALSE; LLRenderTarget::LLRenderTarget() : @@ -48,7 +66,9 @@ LLRenderTarget::LLRenderTarget() : mStencil(0), mUseDepth(FALSE), mRenderDepth(FALSE), - mUsage(LLTexUnit::TT_TEXTURE) + mUsage(LLTexUnit::TT_TEXTURE), + mSamples(0), + mSampleBuffer(NULL) { } @@ -57,40 +77,26 @@ LLRenderTarget::~LLRenderTarget() release(); } -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage, BOOL use_fbo) + +void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) +{ + mSampleBuffer = buffer; +} + +void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) { stop_glerror(); mResX = resx; mResY = resy; + mStencil = stencil; mUsage = usage; mUseDepth = depth; - release(); - - glGenTextures(1, (GLuint *) &mTex); - gGL.getTexUnit(0)->bindManual(mUsage, mTex); - glTexImage2D(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) - { - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - stop_glerror(); + release(); if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) { - if (depth) { stop_glerror(); @@ -100,37 +106,141 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLT glGenFramebuffersEXT(1, (GLuint *) &mFBO); + if (mDepth) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + if (mStencil) + { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + stop_glerror(); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + stop_glerror(); + } + else + { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + stop_glerror(); + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + stop_glerror(); + } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + addColorAttachment(color_fmt); +} - stop_glerror(); +void LLRenderTarget::addColorAttachment(U32 color_fmt) +{ + if (color_fmt == 0) + { + return; + } - if (mDepth) - { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - } + U32 offset = mTex.size(); + if (offset >= 4 || + offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) + { + llerrs << "Too many color attachments!" << llendl; + } - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - LLTexUnit::getInternalType(mUsage), mTex, 0); - stop_glerror(); + U32 tex; + LLImageGL::generateTextures(1, &tex); + gGL.getTexUnit(0)->bindManual(mUsage, tex); + + stop_glerror(); + + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + stop_glerror(); + + if (offset == 0) + { + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + else + { //don't filter data attachments + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + if (mUsage != LLTexUnit::TT_RECT_TEXTURE) + { + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + } + else + { + // ATI doesn't support mirrored repeat for rectangular textures. + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + if (mFBO) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, + LLTexUnit::getInternalType(mUsage), tex, 0); + stop_glerror(); + + check_framebuffer_status(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - stop_glerror(); } + + mTex.push_back(tex); + } void LLRenderTarget::allocateDepth() { - glGenTextures(1, (GLuint *) &mDepth); - gGL.getTexUnit(0)->bindManual(mUsage, mDepth); - U32 internal_type = LLTexUnit::getInternalType(mUsage); - glTexParameteri(internal_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(internal_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); + if (mStencil) + { + //use render buffers where stencil buffers are in play + glGenRenderbuffersEXT(1, (GLuint *) &mDepth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + else + { + LLImageGL::generateTextures(1, &mDepth); + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); + } +} + +void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) +{ + if (!mFBO || !target.mFBO) + { + llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; + } + + if (mDepth) + { + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, target.mFBO); + stop_glerror(); + + if (mStencil) + { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + stop_glerror(); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + stop_glerror(); + } + else + { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + stop_glerror(); + if (mStencil) + { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + stop_glerror(); + } + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + target.mUseDepth = TRUE; + } } void LLRenderTarget::release() @@ -141,24 +251,63 @@ void LLRenderTarget::release() mFBO = 0; } - if (mTex) + if (mTex.size() > 0) { - glDeleteTextures(1, (GLuint *) &mTex); - mTex = 0; + LLImageGL::deleteTextures(mTex.size(), &mTex[0]); + mTex.clear(); } if (mDepth) { - glDeleteTextures(1, (GLuint *) &mDepth); + if (mStencil) + { + glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth); + stop_glerror(); + } + else + { + LLImageGL::deleteTextures(1, &mDepth); + stop_glerror(); + } mDepth = 0; } + + mSampleBuffer = NULL; } void LLRenderTarget::bindTarget() { if (mFBO) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + stop_glerror(); + if (mSampleBuffer) + { + mSampleBuffer->bindTarget(this); + stop_glerror(); + } + else + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + stop_glerror(); + if (gGLManager.mHasDrawBuffers) + { //setup multiple render targets + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, + GL_COLOR_ATTACHMENT3_EXT}; + glDrawBuffersARB(mTex.size(), drawbuffers); + } + + if (mTex.empty()) + { //no color buffer to draw to + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + + check_framebuffer_status(); + + stop_glerror(); + } } glViewport(0, 0, mResX, mResY); @@ -173,7 +322,7 @@ void LLRenderTarget::unbindTarget() } } -void LLRenderTarget::clear() +void LLRenderTarget::clear(U32 mask_in) { U32 mask = GL_COLOR_BUFFER_BIT; if (mUseDepth) @@ -182,15 +331,36 @@ void LLRenderTarget::clear() } if (mFBO) { - glClear(mask); + check_framebuffer_status(); + stop_glerror(); + glClear(mask & mask_in); + stop_glerror(); } else { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, mResX, mResY); stop_glerror(); - glClear(mask); + glClear(mask & mask_in); + } +} + +U32 LLRenderTarget::getTexture(U32 attachment) const +{ + if (attachment > mTex.size()-1) + { + llerrs << "Invalid attachment index." << llendl; + } + return mTex[attachment]; +} + +void LLRenderTarget::bindTexture(U32 index, S32 channel) +{ + if (index > mTex.size()-1) + { + llerrs << "Invalid attachment index." << llendl; } + gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); } void LLRenderTarget::flush(BOOL fetch_depth) @@ -211,16 +381,87 @@ void LLRenderTarget::flush(BOOL fetch_depth) gGL.getTexUnit(0)->bind(this, true); glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); } + + gGL.getTexUnit(0)->disable(); + } + else + { +#if !LL_DARWIN + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + if (mSampleBuffer) + { + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + stop_glerror(); + check_framebuffer_status(); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); + check_framebuffer_status(); + + stop_glerror(); + glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + stop_glerror(); + + if (mTex.size() > 1) + { + for (U32 i = 1; i < mTex.size(); ++i) + { + glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + LLTexUnit::getInternalType(mUsage), mTex[i], 0); + stop_glerror(); + glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); + stop_glerror(); + glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); + stop_glerror(); + } + + for (U32 i = 0; i < mTex.size(); ++i) + { + glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, + LLTexUnit::getInternalType(mUsage), mTex[i], 0); + stop_glerror(); + glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); + stop_glerror(); + } + } + } +#endif + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glFlush(); + } +} + +void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, + S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) +{ +#if !LL_DARWIN + if (!source.mFBO || !mFBO) + { + llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; + } + + if (mSampleBuffer) + { + mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } else { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); + + glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } +#endif } BOOL LLRenderTarget::isComplete() const { - return (mTex || mDepth) ? TRUE : FALSE; + return (!mTex.empty() || mDepth) ? TRUE : FALSE; } void LLRenderTarget::getViewport(S32* viewport) @@ -231,3 +472,191 @@ void LLRenderTarget::getViewport(S32* viewport) viewport[3] = mResY; } +//================================================== +// LLMultisampleBuffer implementation +//================================================== +LLMultisampleBuffer::LLMultisampleBuffer() +{ + +} + +LLMultisampleBuffer::~LLMultisampleBuffer() +{ + releaseSampleBuffer(); +} + +void LLMultisampleBuffer::releaseSampleBuffer() +{ + if (mFBO) + { + glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); + mFBO = 0; + } + + if (mTex.size() > 0) + { + glDeleteRenderbuffersEXT(mTex.size(), (GLuint *) &mTex[0]); + mTex.clear(); + } + + if (mDepth) + { + glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth); + mDepth = 0; + } +} + +void LLMultisampleBuffer::bindTarget() +{ + bindTarget(this); +} + +void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) +{ + if (!ref) + { + ref = this; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + if (gGLManager.mHasDrawBuffers) + { //setup multiple render targets + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, + GL_COLOR_ATTACHMENT1_EXT, + GL_COLOR_ATTACHMENT2_EXT, + GL_COLOR_ATTACHMENT3_EXT}; + glDrawBuffersARB(ref->mTex.size(), drawbuffers); + } + + check_framebuffer_status(); + + glViewport(0, 0, mResX, mResY); + +} + +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo ) +{ + allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); +} + +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) +{ + stop_glerror(); + mResX = resx; + mResY = resy; + + mUsage = usage; + mUseDepth = depth; + mStencil = stencil; + + releaseSampleBuffer(); + + if (!gGLManager.mHasFramebufferMultisample) + { + llerrs << "Attempting to allocate unsupported render target type!" << llendl; + } + + mSamples = samples; + + if (mSamples <= 1) + { + llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; + } + + stop_glerror(); + + if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) + { + + if (depth) + { + stop_glerror(); + allocateDepth(); + stop_glerror(); + } + + glGenFramebuffersEXT(1, (GLuint *) &mFBO); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + + if (mDepth) + { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + if (mStencil) + { + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + + stop_glerror(); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + stop_glerror(); + } + + addColorAttachment(color_fmt); +} + +void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) +{ +#if !LL_DARWIN + if (color_fmt == 0) + { + return; + } + + U32 offset = mTex.size(); + if (offset >= 4 || + offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) + { + llerrs << "Too many color attachments!" << llendl; + } + + U32 tex; + glGenRenderbuffersEXT(1, &tex); + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY); + stop_glerror(); + + if (mFBO) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex); + stop_glerror(); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch (status) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + llerrs << "WTF?" << llendl; + break; + default: + llerrs << "WTF?" << llendl; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + + mTex.push_back(tex); +#endif +} + +void LLMultisampleBuffer::allocateDepth() +{ +#if !LL_DARWIN + glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); + if (mStencil) + { + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); + } + else + { + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); + } +#endif +} + diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index d6db054e45..d5d809b791 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -33,6 +33,9 @@ #ifndef LL_LLRENDERTARGET_H #define LL_LLRENDERTARGET_H +// LLRenderTarget is unavailible on the mapserver since it uses FBOs. +#if !LL_MESA_HEADLESS + #include "llgl.h" #include "llrender.h" @@ -60,6 +63,7 @@ */ +class LLMultisampleBuffer; class LLRenderTarget { @@ -68,15 +72,25 @@ public: static BOOL sUseFBO; LLRenderTarget(); - ~LLRenderTarget(); + virtual ~LLRenderTarget(); //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); + void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); + + //provide this render target with a multisample resource. + void setSampleBuffer(LLMultisampleBuffer* buffer); + + //add color buffer attachment + //limit of 4 color attachments per render target + virtual void addColorAttachment(U32 color_fmt); //allocate a depth texture - void allocateDepth(); + virtual void allocateDepth(); + + //share depth buffer with provided render target + virtual void shareDepthBuffer(LLRenderTarget& target); //free any allocated resources //safe to call redundantly @@ -84,14 +98,14 @@ public: //bind target for rendering //applies appropriate viewport - void bindTarget(); + virtual void bindTarget(); //unbind target for rendering static void unbindTarget(); //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode - void clear(); + void clear(U32 mask = 0xFFFFFFFF); //get applied viewport void getViewport(S32* viewport); @@ -104,10 +118,12 @@ public: LLTexUnit::eTextureType getUsage(void) const { return mUsage; } - U32 getTexture(void) const { return mTex; } + U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } + void bindTexture(U32 index, S32 channel); + //flush rendering operations //must be called when rendering is complete //should be used 1:1 with bindTarget @@ -116,23 +132,47 @@ public: // the current depth texture. A depth texture will be allocated if needed. void flush(BOOL fetch_depth = FALSE); + void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, + S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); + //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). BOOL isComplete() const; -private: +protected: + friend class LLMultisampleBuffer; U32 mResX; U32 mResY; - U32 mTex; + std::vector<U32> mTex; U32 mFBO; U32 mDepth; - U32 mStencil; + BOOL mStencil; BOOL mUseDepth; BOOL mRenderDepth; LLTexUnit::eTextureType mUsage; + U32 mSamples; + LLMultisampleBuffer* mSampleBuffer; }; +class LLMultisampleBuffer : public LLRenderTarget +{ +public: + LLMultisampleBuffer(); + virtual ~LLMultisampleBuffer(); + + void releaseSampleBuffer(); + + virtual void bindTarget(); + void bindTarget(LLRenderTarget* ref); + virtual void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo); + void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples); + virtual void addColorAttachment(U32 color_fmt); + virtual void allocateDepth(); +}; + +#endif //!LL_MESA_HEADLESS + #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4d16741794..461edbeec7 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -69,8 +69,10 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = { sizeof(LLVector3), // TYPE_VERTEX, sizeof(LLVector3), // TYPE_NORMAL, - sizeof(LLVector2), // TYPE_TEXCOORD, + sizeof(LLVector2), // TYPE_TEXCOORD0, + sizeof(LLVector2), // TYPE_TEXCOORD1, sizeof(LLVector2), // TYPE_TEXCOORD2, + sizeof(LLVector2), // TYPE_TEXCOORD3, sizeof(LLColor4U), // TYPE_COLOR, sizeof(LLVector3), // TYPE_BINORMAL, sizeof(F32), // TYPE_WEIGHT, @@ -103,8 +105,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { MAP_VERTEX, MAP_NORMAL, - MAP_TEXCOORD, - MAP_COLOR + MAP_TEXCOORD0, + MAP_COLOR, }; GLenum array[] = @@ -112,7 +114,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY, - GL_COLOR_ARRAY + GL_COLOR_ARRAY, }; for (U32 i = 0; i < 4; ++i) @@ -123,7 +125,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be disabled glDisableClientState(array[i]); } - else + else if (gDebugGL) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { @@ -137,29 +139,55 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled glEnableClientState(array[i]); } - else if (glIsEnabled(array[i])) + else if (gDebugGL && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) llerrs << "Bad client state! " << array[i] << " enabled." << llendl; } } } - if (sLastMask & MAP_TEXCOORD2) + U32 map_tc[] = { - if (!(data_mask & MAP_TEXCOORD2)) + MAP_TEXCOORD1, + MAP_TEXCOORD2, + MAP_TEXCOORD3 + }; + + for (U32 i = 0; i < 3; i++) + { + if (sLastMask & map_tc[i]) { - glClientActiveTextureARB(GL_TEXTURE1_ARB); + if (!(data_mask & map_tc[i])) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB+i); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + } + else if (data_mask & map_tc[i]) + { + glClientActiveTextureARB(GL_TEXTURE1_ARB+i); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + } + + if (sLastMask & MAP_BINORMAL) + { + if (!(data_mask & MAP_BINORMAL)) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); } } - else if (data_mask & MAP_TEXCOORD2) + else if (data_mask & MAP_BINORMAL) { - glClientActiveTextureARB(GL_TEXTURE1_ARB); + glClientActiveTextureARB(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); } - + sLastMask = data_mask; } } @@ -194,6 +222,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi return; } + stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); @@ -223,13 +252,14 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const return; } + stop_glerror(); glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); + stop_glerror(); } void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { - if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { @@ -247,6 +277,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const return; } + stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); } @@ -767,11 +798,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access) stop_glerror(); mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); stop_glerror(); - /*if (sMapped) - { - llerrs << "Mapped two VBOs at the same time!" << llendl; - } - sMapped = TRUE;*/ + if (!mMappedData) { //-------------------- @@ -896,14 +923,22 @@ bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index) { return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index); } -bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) +bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index) +{ + return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index); +} +bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index) { - return VertexBufferStrider<LLVector2,TYPE_TEXCOORD>::get(*this, strider, index); + return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index); } -bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index) +/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index) { return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index); } +bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index) +{ + return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index); +}*/ bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index) { return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index); @@ -1101,24 +1136,39 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); } + if (data_mask & MAP_TEXCOORD3) + { + glClientActiveTextureARB(GL_TEXTURE3_ARB); + glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } if (data_mask & MAP_TEXCOORD2) { - glClientActiveTextureARB(GL_TEXTURE1_ARB); + glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } - if (data_mask & MAP_TEXCOORD) + if (data_mask & MAP_TEXCOORD1) { - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD])); + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); } - if (data_mask & MAP_COLOR) + if (data_mask & MAP_BINORMAL) { - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); } - if (data_mask & MAP_BINORMAL) + if (data_mask & MAP_TEXCOORD0) { - glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); + glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); } + if (data_mask & MAP_COLOR) + { + glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); + } + if (data_mask & MAP_WEIGHT) { glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index fbddd9d887..aad948e17f 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -100,8 +100,10 @@ public: enum { TYPE_VERTEX, TYPE_NORMAL, - TYPE_TEXCOORD, + TYPE_TEXCOORD0, + TYPE_TEXCOORD1, TYPE_TEXCOORD2, + TYPE_TEXCOORD3, TYPE_COLOR, // These use VertexAttribPointer and should possibly be made generic TYPE_BINORMAL, @@ -113,16 +115,15 @@ public: enum { MAP_VERTEX = (1<<TYPE_VERTEX), MAP_NORMAL = (1<<TYPE_NORMAL), - MAP_TEXCOORD = (1<<TYPE_TEXCOORD), + MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0), + MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1), MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2), + MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3), MAP_COLOR = (1<<TYPE_COLOR), // These use VertexAttribPointer and should possibly be made generic MAP_BINORMAL = (1<<TYPE_BINORMAL), MAP_WEIGHT = (1<<TYPE_WEIGHT), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), - MAP_DRAW = 0x2000, // Buffer is in draw (read-only) mode - MAP_MAPPED = 0x4000, // Indicates that buffer has been mapped, but not to any type of data - MAP_UNMAPPED = 0x8000 // Indicates that buffer has been logically un-mapped }; protected: @@ -165,8 +166,8 @@ public: // vb->unmapBuffer(); bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0); bool getIndexStrider(LLStrider<U16>& strider, S32 index=0); - bool getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index=0); - bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0); + bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0); + bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0); bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0); bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 16c7d69b32..609763ce15 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -362,7 +362,7 @@ void LLLineEditor::setCursor( S32 pos ) { S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos); S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left))); - S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels), mText.length(), getCursor()); + S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), mText.length(), getCursor()); if (old_cursor_pos == last_visible_char) { mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD)); diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index ce6cf6574f..d4a9e9d1bf 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -232,8 +232,7 @@ void LLViewBorder::drawTextures() //gGL.color4fv(UI_VERTEX_COLOR.mV); //gGL.getTexUnit(0)->bind(mTexture); - //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + //gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); //drawTextureTrapezoid( 0.f, mBorderWidth, getRect().getWidth(), 0, 0 ); //drawTextureTrapezoid( 90.f, mBorderWidth, getRect().getHeight(), (F32)getRect().getWidth(),0 ); diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index a55b5402ed..704e1ab142 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -73,6 +73,10 @@ LLLFSThread::LLLFSThread(bool threaded) : LLQueuedThread("LFS", threaded), mPriorityCounter(PRIORITY_LOWBITS) { + if(!mLocalAPRFilePoolp) + { + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + } } LLLFSThread::~LLLFSThread() @@ -184,8 +188,9 @@ bool LLLFSThread::Request::processRequest() if (mOperation == FILE_READ) { llassert(mOffset >= 0); - apr_file_t* filep = ll_apr_file_open(mFileName, LL_APR_RB, mThread->mAPRPoolp); - if (!filep) + LLAPRFile infile ; + infile.open(mThread->getLocalAPRFilePool(), mFileName, LL_APR_RB); + if (!infile.getFileHandle()) { llwarns << "LLLFS: Unable to read file: " << mFileName << llendl; mBytesRead = 0; // fail @@ -193,13 +198,13 @@ bool LLLFSThread::Request::processRequest() } S32 off; if (mOffset < 0) - off = ll_apr_file_seek(filep, APR_END, 0); + off = infile.seek(APR_END, 0); else - off = ll_apr_file_seek(filep, APR_SET, mOffset); + off = infile.seek(APR_SET, mOffset); llassert_always(off >= 0); - mBytesRead = ll_apr_file_read(filep, mBuffer, mBytes ); - apr_file_close(filep); + mBytesRead = infile.read(mBuffer, mBytes ); complete = true; + infile.close() ; // llinfos << "LLLFSThread::READ:" << mFileName << " Bytes: " << mBytesRead << llendl; } else if (mOperation == FILE_WRITE) @@ -207,8 +212,9 @@ bool LLLFSThread::Request::processRequest() apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; if (mOffset < 0) flags |= APR_APPEND; - apr_file_t* filep = ll_apr_file_open(mFileName, flags, mThread->mAPRPoolp); - if (!filep) + LLAPRFile outfile ; + outfile.open(mThread->getLocalAPRFilePool(), mFileName, flags); + if (!outfile.getFileHandle()) { llwarns << "LLLFS: Unable to write file: " << mFileName << llendl; mBytesRead = 0; // fail @@ -216,18 +222,17 @@ bool LLLFSThread::Request::processRequest() } if (mOffset >= 0) { - S32 seek = ll_apr_file_seek(filep, APR_SET, mOffset); + S32 seek = outfile.seek(APR_SET, mOffset); if (seek < 0) { - apr_file_close(filep); llwarns << "LLLFS: Unable to write file (seek failed): " << mFileName << llendl; mBytesRead = 0; // fail return true; } } - mBytesRead = ll_apr_file_write(filep, mBuffer, mBytes ); + mBytesRead = outfile.write(mBuffer, mBytes ); complete = true; - apr_file_close(filep); + // llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl; } else diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 30d20bb35a..8c0ea5fd14 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2070,9 +2070,11 @@ void LLVFS::dumpFiles() std::string extension = get_extension(type); std::string filename = id.asString() + extension; llinfos << " Writing " << filename << llendl; - apr_file_t* file = ll_apr_file_open(filename, LL_APR_WB); - ll_apr_file_write(file, buffer, size); - apr_file_close(file); + + LLAPRFile outfile ; + outfile.open(filename, LL_APR_WB); + outfile.write(buffer, size); + outfile.close(); delete[] buffer; files_extracted++; } diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 6b1b6f4d60..1a724b5f77 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -271,7 +271,7 @@ static SDL_Surface *Load_BMP_Resource(const char *basename) #if LL_X11 // This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM // on this machine. It works by searching /var/log/var/log/Xorg.?.log or -// /var/log/XFree86.?.log for a ': (VideoRAM|Memory): (%d+) kB' regex, where +// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where // '?' is the X11 display number derived from $DISPLAY static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str) { @@ -285,6 +285,8 @@ static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str) // favourite regex implementation - libboost_regex - is // quite a heavy and troublesome dependency for the client, so // it seems a shame to introduce it for such a simple task. + // *FIXME: libboost_regex is a dependency now anyway, so we may + // as well use it instead of this hand-rolled nonsense. const char *part1_template = prefix_str; const char part2_template[] = " kB"; char *part1 = strstr(line_buf, part1_template); @@ -361,8 +363,17 @@ static int x11_detect_VRAM_kb() fp = fopen(fname.c_str(), "r"); if (fp) { - rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: "); + rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: "); fclose(fp); + if (0 == rtn) + { + fp = fopen(fname.c_str(), "r"); + if (fp) + { + rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: "); + fclose(fp); + } + } } } } diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index d1fdc8caa1..b1eb4d9391 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -373,6 +373,8 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, mMousePositionModified = FALSE; mInputProcessingPaused = FALSE; mPreeditor = NULL; + mhDC = NULL; + mhRC = NULL; // Initialize the keyboard gKeyboard = new LLKeyboardWin32(); @@ -418,7 +420,7 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, mhInstance = GetModuleHandle(NULL); mWndProc = NULL; - mSwapMethod = SWAP_METHOD_EXCHANGE; + mSwapMethod = SWAP_METHOD_UNDEFINED; // No WPARAM yet. mLastSizeWParam = 0; @@ -844,8 +846,13 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO RECT window_rect; S32 width = size.mX; S32 height = size.mY; + BOOL auto_show = FALSE; - resetDisplayResolution(); + if (mhRC) + { + auto_show = TRUE; + resetDisplayResolution(); + } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) { @@ -1183,8 +1190,28 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL; } - pixel_format = pixel_formats[0]; + + + S32 swap_method = 0; + S32 cur_format = num_formats-1; + GLint swap_query = WGL_SWAP_METHOD_ARB; + + BOOL found_format = FALSE; + while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) + { + if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0) + { + found_format = TRUE; + } + else + { + --cur_format; + } + } + + pixel_format = pixel_formats[cur_format]; + if (mhDC != 0) // Does The Window Have A Device Context? { wglMakeCurrent(mhDC, 0); // Set The Current Active Rendering Context To Zero @@ -1227,9 +1254,6 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO return FALSE; } - int swap_method = 0; - GLint swap_query = WGL_SWAP_METHOD_ARB; - if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) { switch (swap_method) @@ -1342,13 +1366,21 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO } SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this); - show(); - + //register joystick timer callback SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer // ok to post quit messages now mPostQuit = TRUE; + + if (auto_show) + { + show(); + glClearColor(0.0f, 0.0f, 0.0f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + swapBuffers(); + } + return TRUE; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e532793a82..123f3b72a3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -30,6 +30,7 @@ include(LScript) include(Linking) include(Mozlib) include(NDOF) +include(GooglePerfTools) include(TemplateCheck) include(UI) include(UnixInstall) @@ -1330,8 +1331,8 @@ if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - LINK_FLAGS "/debug /NODEFAULTLIB:MSVCRT /SUBSYSTEM:WINDOWS" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" LINK_FLAGS_RELEASE ${release_flags} ) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index d7bb64ce8a..a49ccb77b4 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -40,6 +40,7 @@ </array> <key>tags</key> <array> + <string>ShaderLoading</string> </array> </map> </array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2cc8224fc6..523032bf67 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2256,7 +2256,18 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugShowTime</key> + <key>DebugShowRenderMatrices</key> + <map> + <key>Comment</key> + <string>Display values of current view and projection matrices.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DebugShowTime</key> <map> <key>Comment</key> <string>Show depth buffer contents</string> @@ -2635,6 +2646,17 @@ <key>Value</key> <real>60.0</real> </map> + <key>FPSLogFrequency</key> + <map> + <key>Comment</key> + <string>Seconds between display of FPS in log (0 for never)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> <key>FilterItemsPerFrame</key> <map> <key>Comment</key> @@ -6141,7 +6163,102 @@ <key>Value</key> <integer>1</integer> </map> - <key>RenderBumpmapMinDistanceSquared</key> + + <key>RenderShadowGaussian</key> + <map> + <key>Comment</key> + <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>2.0</real> + <real>2.0</real> + <real>0.0</real> + </array> + </map> + + <key>RenderShadowNearDist</key> + <map> + <key>Comment</key> + <string>Near clip plane of shadow camera (affects precision of depth shadows).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>256</real> + <real>256</real> + <real>256</real> + </array> + </map> + <key>RenderShadowClipPlanes</key> + <map> + <key>Comment</key> + <string>Near clip plane split distances for shadow map frusta.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>4.0</real> + <real>8.0</real> + <real>24.0</real> + </array> + </map> + <key>RenderSSAOScale</key> + <map> + <key>Comment</key> + <string>Scaling factor for the area to sample for occluders (pixels at 1 meter away, inversely varying with distance)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>500.0</real> + </map> + <key>RenderSSAOMaxScale</key> + <map> + <key>Comment</key> + <string>Maximum screen radius for sampling (pixels)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>60</integer> + </map> + <key>RenderSSAOFactor</key> + <map> + <key>Comment</key> + <string>Occlusion sensitivity factor for ambient occlusion (larger is more)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.30</real> + </map> + <key>RenderSSAOEffect</key> + <map> + <key>Comment</key> + <string>Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.40</real> + <real>1.00</real> + <real>0.00</real> + </array> + </map> + <key>RenderBumpmapMinDistanceSquared</key> <map> <key>Comment</key> <string>Maximum distance at which to render bumpmapped primitives (distance in meters, squared)</string> @@ -6152,6 +6269,17 @@ <key>Value</key> <real>100.0</real> </map> + <key>RenderNormalMapScale</key> + <map> + <key>Comment</key> + <string>Scaler applied to height map when generating normal maps</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>128</real> + </map> <key>RenderCubeMap</key> <map> <key>Comment</key> @@ -6192,7 +6320,7 @@ <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> @@ -6207,18 +6335,129 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderDeferred</key> - <map> - <key>Comment</key> - <string>Use deferred rendering pipeline.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>RenderDynamicLOD</key> + <key>RenderDelayCreation</key> + <map> + <key>Comment</key> + <string>Throttle creation of drawables.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderAnimateRes</key> + <map> + <key>Comment</key> + <string>Animate rezing prims.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderAnimateTrees</key> + <map> + <key>Comment</key> + <string>Use GL matrix ops to animate tree branches.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDeferredAlphaSoften</key> + <map> + <key>Comment</key> + <string>Scalar for softening alpha surfaces (for soft particles).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.75</real> + </map> + <key>RenderDeferredNoise</key> + <map> + <key>Comment</key> + <string>Noise scalar to hide banding in deferred render.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>4</real> + </map> + <key>RenderDeferred</key> + <map> + <key>Comment</key> + <string>Use deferred rendering pipeline.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDeferredSunShadow</key> + <map> + <key>Comment</key> + <string>Generate shadows from the sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>RenderDeferredSunWash</key> + <map> + <key>Comment</key> + <string>Amount local lights are washed out by sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + <key>RenderShadowNoise</key> + <map> + <key>Comment</key> + <string>Magnitude of noise on shadow samples.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>-0.0001</real> + </map> + <key>RenderShadowBlurSize</key> + <map> + <key>Comment</key> + <string>Scale of shadow softening kernel.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.7</real> + </map> + <key>RenderShadowBlurSamples</key> + <map> + <key>Comment</key> + <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>5</real> + </map> + <key>RenderDynamicLOD</key> <map> <key>Comment</key> <string>Dynamically adjust level of detail.</string> @@ -6368,13 +6607,13 @@ <key>RenderGlowMinLuminance</key> <map> <key>Comment</key> - <string>Min luminance intensity necessary to consider an object bright enough to automatically glow. (Gets clamped to 0 - 1.0 range)</string> + <string>Min luminance intensity necessary to consider an object bright enough to automatically glow.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> + <real>2.5</real> </map> <key>RenderGlowResolutionPow</key> <map> @@ -6534,6 +6773,17 @@ <key>Value</key> <integer>4096</integer> </map> + <key>RenderMaxNodeSize</key> + <map> + <key>Comment</key> + <string>Maximum size of a single node's vertex data (in KB).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>4096</integer> + </map> <key>RenderMaxVBOSize</key> <map> <key>Comment</key> @@ -6543,7 +6793,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>32</integer> + <integer>512</integer> </map> <key>RenderName</key> <map> @@ -6644,6 +6894,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderShaderLightingMaxLevel</key> + <map> + <key>Comment</key> + <string>Max lighting level to use in the shader (class 3 is default, 2 is less lights, 1 is sun/moon only. Works around shader compiler bugs on certain platforms.)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> <key>RenderShaderLODThreshold</key> <map> <key>Comment</key> @@ -9760,6 +10021,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderDelayVBUpdate</key> + <map> + <key>Comment</key> + <string>Delay vertex buffer updates until just before rendering</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UseStartScreen</key> <map> <key>Comment</key> @@ -10507,7 +10779,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>WindowWidth</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl new file mode 100644 index 0000000000..a91e9fa15b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -0,0 +1,88 @@ +/** + * @file alphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; +uniform sampler2DRect positionMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; + +uniform float alpha_soften; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + + float shadow = 1.0; + vec4 pos = vec4(vary_position, 1.0); + + if (pos.z > -shadow_clip.w) + { + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + if (samp_pos.z != 0.0) + { + float dist_factor = alpha_soften; + float a = gl_Color.a; + a *= a; + dist_factor *= 1.0/(1.0-a); + color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); + } + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1); + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl new file mode 100644 index 0000000000..b496bd674f --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -0,0 +1,69 @@ +/** + * @file alphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; + +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + vary_position = pos.xyz; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl new file mode 100644 index 0000000000..6c94f5c5a7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl @@ -0,0 +1,68 @@ +/** + * @file avatarAlphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec4 vary_position; +varying vec3 vary_normal; + +void main() +{ + float shadow = 1.0; + vec4 pos = vary_position; + vec3 norm = normalize(vary_normal); + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + + if (pos.z > -shadow_clip.w) + { + + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + + vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl new file mode 100644 index 0000000000..c1988d3c78 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -0,0 +1,78 @@ +/** + * @file avatarAlphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec4 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + gl_Position = gl_ProjectionMatrix * pos; + vary_position = pos; + vary_normal = norm; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl new file mode 100644 index 0000000000..58aa5a9cb5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -0,0 +1,20 @@ +/** + * @file avatarF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl new file mode 100644 index 0000000000..27c09db922 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -0,0 +1,15 @@ +/** + * @file avatarShadowF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + + +void main() +{ + gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy)); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl new file mode 100644 index 0000000000..14da6b1ad4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -0,0 +1,38 @@ +/** + * @file avatarShadowV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +mat4 getSkinnedTransform(); + +attribute vec4 weight; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + pos = gl_ProjectionMatrix * pos; + //smash geometry against near clip plane + pos.z = max(pos.z, -1.0); + gl_Position = pos; + + gl_FrontColor = gl_Color; +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl new file mode 100644 index 0000000000..12a7ff7f29 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -0,0 +1,42 @@ +/** + * @file avatarV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +mat4 getSkinnedTransform(); + +attribute vec4 weight; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + vary_position = pos; + vary_normal = norm; + + gl_Position = gl_ProjectionMatrix * pos; + //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + gl_FrontColor = gl_Color; +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl new file mode 100644 index 0000000000..3c6700a871 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -0,0 +1,48 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; + +uniform float blur_size; +uniform vec2 delta; +uniform vec3 kern[32]; +uniform int kern_length; +uniform float kern_scale; + +varying vec2 vary_fragcoord; + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz; + vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg; + + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' + vec2 col = defined_weight * ccol; + + for (int i = 1; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; + vec3 samppos = texture2DRect(positionMap, tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc).rg*kern[i].xy; + defined_weight += kern[i].xy; + } + } + + col /= defined_weight; + + gl_FragColor = vec4(col.r, col.g, 0.0, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl new file mode 100644 index 0000000000..b7f07e5702 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl @@ -0,0 +1,17 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl new file mode 100644 index 0000000000..a8712bc8cc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -0,0 +1,29 @@ +/** + * @file bumpF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; +varying vec4 vary_position; + +void main() +{ + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; + + vec3 tnorm = vec3(dot(norm,vary_mat0), + dot(norm,vary_mat1), + dot(norm,vary_mat2)); + + gl_FragData[0].rgb = gl_Color.rgb*col; + gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); + gl_FragData[2] = vec4(normalize(tnorm), 0.0); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl new file mode 100644 index 0000000000..ba180922cc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -0,0 +1,30 @@ +/** + * @file bumpV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + vec3 n = normalize(gl_NormalMatrix * gl_Normal); + vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); + vec3 t = cross(b, n); + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 14e6361f83..f2ba2df69a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -8,9 +8,13 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; +varying vec4 vary_position; void main() { - gl_FragColor = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); - gl_FragColor.rgb = vary_normal*0.5+0.5; + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); + gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 8e9069368a..3413a7f9d6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -6,7 +6,7 @@ */ varying vec3 vary_normal; -varying vec3 vary_position; +varying vec4 vary_position; void main() { @@ -14,7 +14,7 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = (gl_ModelViewMatrix * gl_Vertex).xyz; + vary_position = gl_ModelViewMatrix * gl_Vertex; vary_normal = normalize(gl_NormalMatrix * gl_Normal); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl new file mode 100644 index 0000000000..2a811c5897 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -0,0 +1,63 @@ +/** + * @file fullbrightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; +uniform sampler2DRect positionMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec4 vary_position; +varying vec3 vary_normal; +varying vec3 vary_fragcoord; + +uniform float alpha_soften; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + + float shadow = 1.0; + vec4 pos = vary_position; + + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color; + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + if (samp_pos.z != 0.0) + { + float dist_factor = alpha_soften; + float a = gl_Color.a; + a *= a; + dist_factor *= 1.0/(1.0-a); + color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); + } + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1); + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl new file mode 100644 index 0000000000..6381a1ced8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -0,0 +1,41 @@ +/** + * @file fullbrightV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void calcAtmospherics(vec3 inPositionEye); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec4 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; +varying vec3 vary_fragcoord; +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vary_position = pos; + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_FogFragCoord = pos.z; + + pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl new file mode 100644 index 0000000000..20a3f3df5b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -0,0 +1,20 @@ +/** + * @file impostorF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2D normalMap; +uniform sampler2D specularMap; + +varying vec4 vary_position; + +void main() +{ + gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); + gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl new file mode 100644 index 0000000000..9c5ae31541 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl @@ -0,0 +1,19 @@ +/** + * @file impostorV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl new file mode 100644 index 0000000000..3689d12840 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -0,0 +1,83 @@ +/** + * @file multiPointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; + +uniform vec3 env_mat[3]; +uniform float sun_wash; + +uniform int light_count; + +uniform vec4 light[16]; +uniform vec4 light_col[16]; + +varying vec3 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; + vec3 pos = texture2DRect(positionMap, frag.xy).xyz; + vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz); + vec4 spec = texture2DRect(specularRect, frag.xy); + vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; + float noise = texture2D(noiseMap, frag.xy/128.0).b; + vec3 out_col = vec3(0,0,0); + + for (int i = 0; i < light_count; ++i) + { + vec3 lv = light[i].xyz-pos; + float dist2 = dot(lv,lv); + if (dist2 > light[i].w) + { + continue; + } + + float da = dot(norm, lv); + if (da < 0.0) + { + continue; + } + + lv = normalize(lv); + da = dot(norm, lv); + + float fa = light_col[i].a+1.0; + float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0); + dist_atten *= noise; + + float lit = da * dist_atten; + + vec3 col = light_col[i].rgb*lit*diff; + + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*light_col[i].rgb*spec.rgb; + } + + out_col += col; + } + + //attenuate point light contribution by SSAO component + out_col *= texture2DRect(lightMap, frag.xy).g; + + gl_FragColor.rgb = out_col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl new file mode 100644 index 0000000000..52bad1f34c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -0,0 +1,75 @@ +/** + * @file pointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; + +uniform vec3 env_mat[3]; +uniform float sun_wash; + +varying vec4 vary_light; + +varying vec3 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + vec3 pos = texture2DRect(positionMap, frag).xyz; + vec3 lv = vary_light.xyz-pos; + float dist2 = dot(lv,lv); + if (dist2 > vary_light.w) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag).xyz; + float da = dot(norm, lv); + if (da < 0.0) + { + discard; + } + + norm = normalize(norm); + lv = normalize(lv); + da = dot(norm, lv); + + float noise = texture2D(noiseMap, frag/128.0).b; + + vec3 col = texture2DRect(diffuseRect, frag).rgb; + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0); + float lit = da * dist_atten * noise; + + col = gl_Color.rgb*lit*col; + + vec4 spec = texture2DRect(specularRect, frag); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*gl_Color.rgb*spec.rgb; + } + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl new file mode 100644 index 0000000000..a4edb88259 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -0,0 +1,28 @@ +/** + * @file pointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_light; +varying vec3 vary_fragcoord; + +uniform vec2 screen_res; +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl new file mode 100644 index 0000000000..b3758c3638 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -0,0 +1,14 @@ +/** + * @file shadowF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + + +void main() +{ + gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl new file mode 100644 index 0000000000..aae1beeae3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -0,0 +1,17 @@ +/** + * @file shadowV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; + //smash geometry against the near clip plane (great for ortho projections) + pos.z = max(pos.z, -1.0); + gl_Position = pos; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl new file mode 100644 index 0000000000..d5671a6ce4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -0,0 +1,279 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 distance_multiplier; +uniform vec4 max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +uniform mat4 shadow_matrix[3]; +uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + //(TERRAIN) limit altitude + if (P.y > max_y.x) P *= (max_y.x / P.y); + if (P.y < -max_y.x) P *= (-max_y.x / P.y); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_color; + vec4 light_atten; + + //sunlight attenuation effect (hue and brightness) due to atmosphere + //this is used later for sunlight modulation at various altitudes + light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density.r); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 pos = texture2DRect(positionMap, tc).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = vec4(texture2DRect(diffuseRect, tc).rgb, 1.0); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = scol_ambocc.r; + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + vec3 col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(min(da, scol)); + + col *= diffuse.rgb; + + if (spec.a > 0.2) + { + vec3 ref = reflect(pos.xyz, norm.xyz); + vec3 rc; + rc.x = dot(ref, env_mat[0]); + rc.y = dot(ref, env_mat[1]); + rc.z = dot(ref, env_mat[2]); + + vec3 refcol = textureCube(environmentMap, rc).rgb; + col.rgb += refcol * spec.rgb; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl new file mode 100644 index 0000000000..ad8af4780d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl @@ -0,0 +1,24 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl new file mode 100644 index 0000000000..d43fe6ca95 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -0,0 +1,139 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +// Inputs +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces + // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + return 1.0 - (float(points != 0) * angle_hidden); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0); + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else if (pos.z > -shadow_clip.w) + { + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + } + else + { + // more distant than the shadow map covers - just use directional shading as shadow + shadow = dp_directional_light; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + //gl_FragColor[2] is unused as of August 2008, may be used for debugging +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl new file mode 100644 index 0000000000..5081485c4b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl @@ -0,0 +1,25 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl new file mode 100644 index 0000000000..211b2e0397 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -0,0 +1,36 @@ +/** + * @file terrainF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D detail_0; +uniform sampler2D detail_1; +uniform sampler2D detail_2; +uniform sampler2D detail_3; +uniform sampler2D alpha_ramp; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + /// Note: This should duplicate the blending functionality currently used for the terrain rendering. + + vec4 color0 = texture2D(detail_0, gl_TexCoord[0].xy); + vec4 color1 = texture2D(detail_1, gl_TexCoord[0].xy); + vec4 color2 = texture2D(detail_2, gl_TexCoord[0].xy); + vec4 color3 = texture2D(detail_3, gl_TexCoord[0].xy); + + float alpha1 = texture2D(alpha_ramp, gl_TexCoord[0].zw).a; + float alpha2 = texture2D(alpha_ramp,gl_TexCoord[1].xy).a; + float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a; + vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); + + gl_FragData[0] = vec4(outColor.rgb, 1.0); + gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl new file mode 100644 index 0000000000..e9d6dcabff --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -0,0 +1,41 @@ +/** + * @file terrainV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_normal; +varying vec4 vary_position; + +vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) +{ + vec4 tcoord; + + tcoord.x = dot(vpos, tp0); + tcoord.y = dot(vpos, tp1); + tcoord.z = tc.z; + tcoord.w = tc.w; + + tcoord = mat * tcoord; + + return tcoord; +} + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + vary_normal = normalize(gl_NormalMatrix * gl_Normal); + + // Transform and pass tex coords + gl_TexCoord[0].xy = texgen_object(gl_Vertex, gl_MultiTexCoord0, gl_TextureMatrix[0], gl_ObjectPlaneS[0], gl_ObjectPlaneT[0]).xy; + + vec4 t = gl_MultiTexCoord1; + + gl_TexCoord[0].zw = t.xy; + gl_TexCoord[1].xy = t.xy-vec2(2.0, 0.0); + gl_TexCoord[1].zw = t.xy-vec2(1.0, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl new file mode 100644 index 0000000000..bc2c9816dc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -0,0 +1,20 @@ +/** + * @file treeF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = gl_Color*col; + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl new file mode 100644 index 0000000000..9131d7c2b3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -0,0 +1,22 @@ +/** + * @file treeV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + vary_normal = normalize(gl_NormalMatrix * gl_Normal); + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl new file mode 100644 index 0000000000..0a1f019e3d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -0,0 +1,157 @@ +/** + * @file waterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec3 scaleSoftClip(vec3 inColor); +vec3 atmosTransport(vec3 inColor); + +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; + +uniform float sunAngle; +uniform float sunAngle2; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform float refScale; +uniform float kd; +uniform vec2 screenRes; +uniform vec3 normScale; +uniform float fresnelScale; +uniform float fresnelOffset; +uniform float blurMultiplier; + + +//bigWave is (refCoord.w, view.w); +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; +varying vec4 vary_position; + +void main() +{ + vec4 color; + float dist = length(view.xy); + + //normalize view vector + vec3 viewVec = normalize(view.xyz); + + //get wave normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + //get base fresnel components + + vec3 df = vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset; + df *= df; + + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + + float dist2 = dist; + dist = max(dist, 5.0); + + float dmod = sqrt(dist); + + vec2 dmod_scale = vec2(dmod*dmod, dmod); + + //get reflected color + vec2 refdistort1 = wave1.xy*normScale.x; + vec2 refvec1 = distort+refdistort1/dmod_scale; + vec4 refcol1 = texture2D(refTex, refvec1); + + vec2 refdistort2 = wave2.xy*normScale.y; + vec2 refvec2 = distort+refdistort2/dmod_scale; + vec4 refcol2 = texture2D(refTex, refvec2); + + vec2 refdistort3 = wave3.xy*normScale.z; + vec2 refvec3 = distort+refdistort3/dmod_scale; + vec4 refcol3 = texture2D(refTex, refvec3); + + vec4 refcol = refcol1 + refcol2 + refcol3; + float df1 = df.x + df.y + df.z; + refcol *= df1 * 0.333; + + vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; + wavef.z *= max(-viewVec.z, 0.1); + wavef = normalize(wavef); + + float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; + + vec2 refdistort4 = wavef.xy*0.125; + refdistort4.y -= abs(refdistort4.y); + vec2 refvec4 = distort+refdistort4/dmod; + float dweight = min(dist2*blurMultiplier, 1.0); + vec4 baseCol = texture2D(refTex, refvec4); + refcol = mix(baseCol*df2, refcol, dweight); + + //get specular component + float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); + + //harden specular + spec = pow(spec, 128.0); + + //figure out distortion vector (ripply) + vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); + + vec4 fb = texture2D(screenTex, distort2); + + //mix with reflection + // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); + + float shadow = 1.0; + vec4 pos = vary_position; + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + + if (pos.z > -shadow_clip.w) + { + vec4 spos = pos; + + if (pos.z < -shadow_clip.z) + { + vec4 lpos = (shadow_matrix[3]*spos); + shadow = shadow2DProj(shadowMap3, lpos).x; + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = (shadow_matrix[2]*spos); + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = (shadow_matrix[1]*spos); + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = (shadow_matrix[0]*spos); + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + spec *= shadow; + color.rgb += spec * specular; + + color.rgb = atmosTransport(color.rgb); + color.rgb = scaleSoftClip(color.rgb); + color.a = spec * sunAngle2; + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl new file mode 100644 index 0000000000..b45e5c5302 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -0,0 +1,76 @@ +/** + * @file waterV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void calcAtmospherics(vec3 inPositionEye); + +uniform vec2 d1; +uniform vec2 d2; +uniform float time; +uniform vec3 eyeVec; +uniform float waterHeight; + +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; + +varying vec4 vary_position; + +float wave(vec2 v, float t, float f, vec2 d, float s) +{ + return (dot(d, v)*f + t*s)*f; +} + +void main() +{ + //transform vertex + vec4 position = gl_Vertex; + mat4 modelViewProj = gl_ModelViewProjectionMatrix; + + vec4 oPosition; + + //get view vector + vec3 oEyeVec; + oEyeVec.xyz = position.xyz-eyeVec; + + float d = length(oEyeVec.xy); + float ld = min(d, 2560.0); + + position.xy = eyeVec.xy + oEyeVec.xy/d*ld; + view.xyz = oEyeVec; + + d = clamp(ld/1536.0-0.5, 0.0, 1.0); + d *= d; + + oPosition = position; + oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); + vary_position = gl_ModelViewMatrix * oPosition; + oPosition = modelViewProj * oPosition; + + refCoord.xyz = oPosition.xyz + vec3(0,0,0.2); + + //get wave position parameter (create sweeping horizontal waves) + vec3 v = position.xyz; + v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0; + + //push position for further horizon effect. + position.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z); + position.w = 1.0; + position = position*gl_ModelViewMatrix; + + calcAtmospherics((gl_ModelViewMatrix * gl_Vertex).xyz); + + + //pass wave parameters to pixel shader + vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; + //get two normal map (detail map) texture coordinates + littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13; + littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1; + view.w = bigWave.y; + refCoord.w = bigWave.x; + + gl_Position = oPosition; +} diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index dbdfe1174c..5d7af2c13a 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -20,8 +20,8 @@ void main() /// CALCULATING LUMINANCE (Using NTSC lum weights) /// http://en.wikipedia.org/wiki/Luma_%28video%29 - float lum = smoothstep(minLuminance, 1.0, dot(col.rgb, lumWeights ) ); - float warmth = smoothstep(minLuminance, 1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); + float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) ); + float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); gl_FragColor.rgb = col.rgb; gl_FragColor.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index bd9b30a075..7e1788678d 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -7,6 +7,7 @@ vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); +vec3 applyWaterFog(vec4 inColor); uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index c02ba86d6c..05bdf64b42 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -54,6 +54,8 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderShaderLightingMaxLevel 1 3 + // // Low Graphics Settings @@ -473,17 +475,47 @@ list NVIDIA_GeForce_Go_6 RenderVBOEnable 1 0 Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt index 5f6cf14c05..7e6d4b4561 100644 --- a/indra/newview/licenses-win32.txt +++ b/indra/newview/licenses-win32.txt @@ -735,3 +735,37 @@ From Vivox: Attn: customer support 40 Speen Street Suite 402 Framingham, MA 01701 + + +======================== +google-perftools license +======================== + +Copyright (c) 2005, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7ef757f1ba..569de267e7 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -358,7 +358,6 @@ LLAgent::LLAgent() : mFrameAgent(), - mCrouching(FALSE), mIsBusy(FALSE), mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed @@ -477,8 +476,16 @@ void LLAgent::cleanup() { setSitCamera(LLUUID::null); mAvatarObject = NULL; - mLookAt = NULL; - mPointAt = NULL; + if(mLookAt) + { + mLookAt->markDead() ; + mLookAt = NULL; + } + if(mPointAt) + { + mPointAt->markDead() ; + mPointAt = NULL; + } mRegionp = NULL; setFocusObject(NULL); } @@ -2726,7 +2733,7 @@ BOOL LLAgent::needsRenderAvatar() // TRUE if we need to render your own avatar's head. BOOL LLAgent::needsRenderHead() { - return mShowAvatar && !cameraMouselook(); + return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook()); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index c9e256fbbc..9d08c94150 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -544,6 +544,7 @@ public: void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region ); BOOL getHomePosGlobal( LLVector3d* pos_global ); void setCameraAnimating( BOOL b ) { mCameraAnimating = b; } + BOOL getCameraAnimating( ) { return mCameraAnimating; } void setAnimationDuration( F32 seconds ) { mAnimationDuration = seconds; } F32 getNearChatRadius() { return mNearChatRadius; } @@ -811,7 +812,6 @@ private: LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates - BOOL mCrouching; BOOL mIsBusy; S32 mAtKey; // Either 1, 0, or -1... indicates that movement-key is pressed diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9a8d211cf6..fc37c42f99 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -159,7 +159,7 @@ #include "llimview.h" #include "llviewerthrottle.h" #include "llparcel.h" -// + #include "llinventoryview.h" @@ -508,7 +508,7 @@ LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL; LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : - mMarkerFile(NULL), + mMarkerFile(), mReportedCrash(false), mNumSessions(0), mPurgeCache(false), @@ -1056,6 +1056,9 @@ bool LLAppViewer::mainLoop() } else { + //output possible call stacks to log file. + LLError::LLCallStacks::print() ; + llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } } @@ -1091,6 +1094,16 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { + //---------------------------------------------- + //this test code will be removed after the test + //test manual call stack tracer + if(gSavedSettings.getBOOL("QAMode")) + { + LLError::LLCallStacks::print() ; + } + //end of the test code + //---------------------------------------------- + //flag all elements as needing to be destroyed immediately // to ensure shutdown order LLMortician::setZealous(TRUE); @@ -1110,6 +1123,9 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; // Must clean up texture references before viewer window is destroyed. + LLHUDManager::getInstance()->updateEffects(); + LLHUDObject::updateAll(); + LLHUDManager::getInstance()->cleanupEffects(); LLHUDObject::cleanupHUDObjects(); llinfos << "HUD Objects cleaned up" << llendflush; @@ -2118,7 +2134,7 @@ bool LLAppViewer::initWindow() gViewerWindow->initBase(); // show viewer window - gViewerWindow->mWindow->show(); + //gViewerWindow->mWindow->show(); return true; @@ -2264,6 +2280,9 @@ void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; + //print out recorded call stacks if there are any. + LLError::LLCallStacks::print() ; + LLAppViewer* pApp = LLAppViewer::instance(); if (pApp->beingDebugged()) { @@ -2348,16 +2367,17 @@ void LLAppViewer::handleViewerCrash() if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME); else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME); llinfos << "Creating crash marker file " << crash_file_name << llendl; - apr_file_t* crash_file = ll_apr_file_open(crash_file_name, LL_APR_W); - if (crash_file) + + LLAPRFile crash_file ; + crash_file.open(crash_file_name, LL_APR_W); + if (crash_file.getFileHandle()) { LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL; } else { LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL; - } - apr_file_close(crash_file); + } } if (gMessageSystem && gDirUtilp) @@ -2411,13 +2431,13 @@ bool LLAppViewer::anotherInstanceRunning() LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; //Freeze case checks - apr_file_t* fMarker = ll_apr_file_open(marker_file, LL_APR_RB); - if (fMarker != NULL) + if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB)) { // File exists, try opening with write permissions - apr_file_close(fMarker); - fMarker = ll_apr_file_open(marker_file, LL_APR_WB); - if (fMarker == NULL) + LLAPRFile outfile ; + outfile.open(marker_file, LL_APR_WB); + apr_file_t* fMarker = outfile.getFileHandle() ; + if (!fMarker) { // Another instance is running. Skip the rest of these operations. LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; @@ -2425,12 +2445,10 @@ bool LLAppViewer::anotherInstanceRunning() } if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; return true; } - // No other instances; we'll lock this file now & delete on quit. - apr_file_close(fMarker); + // No other instances; we'll lock this file now & delete on quit. } LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL; return false; @@ -2456,33 +2474,27 @@ void LLAppViewer::initMarkerFile() std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); - apr_file_t* fMarker = ll_apr_file_open(logout_marker_file, LL_APR_RB); - if(fMarker != NULL) + if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL; gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; - } - fMarker = ll_apr_file_open(llerror_marker_file, LL_APR_RB); - if(fMarker != NULL) + } + if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); llinfos << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << llendl; if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_LLERROR_CRASH; } - fMarker = ll_apr_file_open(error_marker_file, LL_APR_RB); - if(fMarker != NULL) + if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL; if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_OTHER_CRASH; } - - ll_apr_file_remove(logout_marker_file); - ll_apr_file_remove(llerror_marker_file); - ll_apr_file_remove(error_marker_file); + + LLAPRFile::remove(logout_marker_file); + LLAPRFile::remove(llerror_marker_file); + LLAPRFile::remove(error_marker_file); //Freeze case checks if(anotherInstanceRunning()) @@ -2490,17 +2502,17 @@ void LLAppViewer::initMarkerFile() return; } - fMarker = ll_apr_file_open(mMarkerFileName, LL_APR_RB); - if (fMarker != NULL) - { - apr_file_close(fMarker); + if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB)) + { gLastExecEvent = LAST_EXEC_FROZE; LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; } - + // Create the marker file for this execution & lock it - mMarkerFile = ll_apr_file_open(mMarkerFileName, LL_APR_W); - if (mMarkerFile) + apr_status_t s; + s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp); + + if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) { LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL; } @@ -2509,9 +2521,9 @@ void LLAppViewer::initMarkerFile() LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL; return; } - if (apr_file_lock(mMarkerFile, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) + if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) { - apr_file_close(mMarkerFile); + mMarkerFile.close() ; LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL; return; } @@ -2522,14 +2534,14 @@ void LLAppViewer::initMarkerFile() void LLAppViewer::removeMarkerFile(bool leave_logout_marker) { LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL; - if (mMarkerFile != NULL) + if (mMarkerFile.getFileHandle()) { - ll_apr_file_remove( mMarkerFileName ); - mMarkerFile = NULL; + mMarkerFile.close() ; + LLAPRFile::remove( mMarkerFileName ); } if (mLogoutMarkerFile != NULL && !leave_logout_marker) { - ll_apr_file_remove( mLogoutMarkerFileName ); + LLAPRFile::remove( mLogoutMarkerFileName ); mLogoutMarkerFile = NULL; } } @@ -2556,6 +2568,7 @@ void LLAppViewer::requestQuit() effectp->setPositionGlobal(gAgent.getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLHUDManager::getInstance()->sendEffects(); + effectp->markDead() ;//remove it. // Attempt to close all floaters that might be // editing things. @@ -3228,6 +3241,7 @@ void LLAppViewer::idle() // gFrameStats.start(LLFrameStats::IDLE_NETWORK); + stop_glerror(); idleNetwork(); stop_glerror(); @@ -3535,7 +3549,10 @@ void LLAppViewer::sendLogoutRequest() //Set internal status variables and marker files gLogoutInProgress = TRUE; mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - mLogoutMarkerFile = ll_apr_file_open(mLogoutMarkerFileName, LL_APR_W); + + LLAPRFile outfile ; + outfile.open(mLogoutMarkerFileName, LL_APR_W); + mLogoutMarkerFile = outfile.getFileHandle() ; if (mLogoutMarkerFile) { llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl; @@ -3544,7 +3561,7 @@ void LLAppViewer::sendLogoutRequest() else { llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl; - } + } } } @@ -3562,6 +3579,8 @@ static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; void LLAppViewer::idleNetwork() { pingMainloopTimeout("idleNetwork"); + LLError::LLCallStacks::clear() ; + llpushcallstacks ; gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; @@ -3572,7 +3591,7 @@ void LLAppViewer::idleNetwork() // deal with any queued name requests and replies. gCacheName->processPending(); - + llpushcallstacks ; LLTimer check_message_timer; // Read all available packets from network stop_glerror(); @@ -3644,16 +3663,16 @@ void LLAppViewer::idleNetwork() gPrintMessagesThisFrame = FALSE; } } - + llpushcallstacks ; gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); gAssetStorage->checkForTimeouts(); - + llpushcallstacks ; gViewerThrottle.updateDynamicThrottle(); - + llpushcallstacks ; // Check that the circuit between the viewer and the agent's current // region is still alive LLViewerRegion *agent_region = gAgent.getRegion(); @@ -3669,6 +3688,7 @@ void LLAppViewer::idleNetwork() mAgentRegionLastID = this_region_id; mAgentRegionLastAlive = this_region_alive; } + llpushcallstacks ; } void LLAppViewer::disconnectViewer() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 638bd241ce..cb10ad3661 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -198,7 +198,7 @@ private: bool mSecondInstance; // Is this a second instance of the app? std::string mMarkerFileName; - apr_file_t* mMarkerFile; // A file created to indicate the app is running. + LLAPRFile mMarkerFile; // A file created to indicate the app is running. std::string mLogoutMarkerFileName; apr_file_t* mLogoutMarkerFile; // A file created to indicate the app is running. diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp index 4656fb45a6..0099817de4 100644 --- a/indra/newview/llcloud.cpp +++ b/indra/newview/llcloud.cpp @@ -122,7 +122,7 @@ void LLCloudGroup::updatePuffs(const F32 dt) mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f); - gPipeline.addObject(mVOCloudsp); + gPipeline.createObject(mVOCloudsp); } LLVector3 velocity; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index d5619f2bf0..47e4a2278f 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -532,10 +532,10 @@ F32 LLDrawable::updateXform(BOOL undamped) if ((mCurrentScale != target_scale) || (!isRoot() && - (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED) || + (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || !mVObjp->getAngularVelocity().isExactlyZero() || target_pos != mXform.getPosition() || - target_rot != mXform.getRotation())) + target_rot != mXform.getRotation()))) { //child prim moving or scale change requires immediate rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } @@ -1233,7 +1233,8 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f; LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f; - if (LLPipeline::sImpostorRender || + if ((LLPipeline::sShadowRender && camera_in.AABBInFrustum(center, size)) || + LLPipeline::sImpostorRender || (camera_in.AABBInFrustumNoFarClip(center, size) && AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist))) { @@ -1290,7 +1291,6 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in) LLDrawable* drawable = child->mDrawable; if (!drawable) { - llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl; continue; } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 77715cbedf..f5a66a3a78 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -98,6 +98,7 @@ public: const LLVector3 getPositionAgent() const; const LLVector3d& getPositionGroup() const { return mPositionGroup; } const LLVector3& getScale() const { return mCurrentScale; } + void setScale(const LLVector3& scale) { mCurrentScale = scale; } const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } const LLQuaternion& getRotation() const { return mXform.getRotation(); } F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index bd30d47426..9f05ce3c46 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -68,6 +68,12 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) case POOL_SIMPLE: poolp = new LLDrawPoolSimple(); break; + case POOL_GRASS: + poolp = new LLDrawPoolGrass(); + break; + case POOL_FULLBRIGHT: + poolp = new LLDrawPoolFullbright(); + break; case POOL_INVISIBLE: poolp = new LLDrawPoolInvisible(); break; @@ -133,11 +139,89 @@ void LLDrawPool::beginRenderPass( S32 pass ) { } +//virtual +S32 LLDrawPool::getNumPasses() +{ + return 1; +} + +//virtual +void LLDrawPool::beginDeferredPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endDeferredPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumDeferredPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderDeferred(S32 pass) +{ + +} + +//virtual +void LLDrawPool::beginPostDeferredPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endPostDeferredPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumPostDeferredPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderPostDeferred(S32 pass) +{ + +} + //virtual void LLDrawPool::endRenderPass( S32 pass ) { } +//virtual +void LLDrawPool::beginShadowPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endShadowPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumShadowPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderShadow(S32 pass) +{ + +} + //============================= // Face Pool Implementation //============================= @@ -414,6 +498,10 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) if (params.mVertexBuffer.notNull()) { + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 45a47f4c3f..b75de02ffc 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -58,10 +58,12 @@ public: POOL_SKY, POOL_WL_SKY, POOL_GROUND, - POOL_BUMP, POOL_INVISIBLE, POOL_AVATAR, POOL_WATER, + POOL_GRASS, + POOL_FULLBRIGHT, + POOL_BUMP, POOL_GLOW, POOL_ALPHA, NUM_POOL_TYPES, @@ -78,7 +80,23 @@ public: virtual LLViewerImage *getDebugTexture(); virtual void beginRenderPass( S32 pass ); virtual void endRenderPass( S32 pass ); - virtual S32 getNumPasses() { return 1; } + virtual S32 getNumPasses(); + + virtual void beginDeferredPass(S32 pass); + virtual void endDeferredPass(S32 pass); + virtual S32 getNumDeferredPasses(); + virtual void renderDeferred(S32 pass = 0); + + virtual void beginPostDeferredPass(S32 pass); + virtual void endPostDeferredPass(S32 pass); + virtual S32 getNumPostDeferredPasses(); + virtual void renderPostDeferred(S32 pass = 0); + + virtual void beginShadowPass(S32 pass); + virtual void endShadowPass(S32 pass); + virtual S32 getNumShadowPasses(); + virtual void renderShadow(S32 pass = 0); + virtual void render(S32 pass = 0) = 0; virtual void prerender() = 0; virtual U32 getVertexDataMask() = 0; @@ -112,6 +130,9 @@ public: PASS_BUMP, PASS_GLOW, PASS_ALPHA, + PASS_ALPHA_MASK, + PASS_FULLBRIGHT_ALPHA_MASK, + PASS_ALPHA_SHADOW, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 8c4a0ab2b5..7e470bd01f 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -57,7 +57,7 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; - +static BOOL deferred_render = FALSE; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), @@ -76,6 +76,67 @@ void LLDrawPoolAlpha::prerender() mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } +S32 LLDrawPoolAlpha::getNumDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAlpha::beginDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolAlpha::endDeferredPass(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); + { + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + gDeferredTreeProgram.bind(); + LLGLEnable test(GL_ALPHA_TEST); + //render alpha masked objects + LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolAlpha::renderDeferred(S32 pass) +{ + +} + + +S32 LLDrawPoolAlpha::getNumPostDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + + simple_shader = &gDeferredAlphaProgram; + fullbright_shader = &gDeferredFullbrightProgram; + + deferred_render = TRUE; + if (mVertexShaderLevel > 0) + { + // Start out with no shaders. + current_shader = target_shader = NULL; + } + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) +{ + deferred_render = FALSE; + endRenderPass(pass); +} + +void LLDrawPoolAlpha::renderPostDeferred(S32 pass) +{ + render(pass); +} + void LLDrawPoolAlpha::beginRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); @@ -115,12 +176,40 @@ void LLDrawPoolAlpha::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); - LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); - LLGLSPipelineAlpha gls_pipeline_alpha; - + + if (LLPipeline::sFastAlpha && !deferred_render) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); + if (mVertexShaderLevel > 0) + { + if (!LLPipeline::sRenderDeferred) + { + simple_shader->bind(); + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + fullbright_shader->bind(); + pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); + LLGLSLShader::bindNoShader(); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); + gPipeline.enableLightsDynamic(); + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); renderAlpha(getVertexDataMask()); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + } + if (sShowDebugAlpha) { if(gPipeline.canUseWindLightShaders()) @@ -132,20 +221,7 @@ void LLDrawPoolAlpha::render(S32 pass) LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(0)->bind(LLViewerImage::sSmokeImagep.get()); renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD); - } -} - -void LLDrawPoolAlpha::renderAlpha(U32 mask) -{ - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (group->mSpatialPartition->mRenderByGroup && - !group->isDead()) - { - renderGroupAlpha(group,LLRenderPass::PASS_ALPHA,mask,TRUE); - } + LLVertexBuffer::MAP_TEXCOORD0); } } @@ -169,7 +245,10 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } LLRenderPass::applyModelMatrix(params); - + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -178,40 +257,15 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } } -void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) +void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - BOOL is_particle = FALSE; + //BOOL is_particle = FALSE; BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) || gPipeline.canUseWindLightShadersOnObjects(); - F32 dist; - - // check to see if it's a particle and if it's "close" - is_particle = !LLPipeline::sUnderWaterRender && (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_PARTICLES); - dist = group->mDistance; - // don't use shader if debug setting is off and it's close or if it's a particle - // and it's close - if(is_particle && !gSavedSettings.getBOOL("RenderUseShaderNearParticles")) - { - if((dist < LLViewerCamera::getInstance()->getFar() * gSavedSettings.getF32("RenderShaderParticleThreshold"))) - { - use_shaders = FALSE; - } - } - - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - - if (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CLOUDS) - { - if (!gSavedSettings.getBOOL("SkyUseClassicClouds")) - { - return; - } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - } - else + // check to see if it's a particle and if it's "close" { if (LLPipeline::sImpostorRender) { @@ -223,79 +277,109 @@ void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask } } - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { - LLDrawInfo& params = **k; - - LLRenderPass::applyModelMatrix(params); - - if (texture && params.mTexture.notNull()) + LLSpatialGroup* group = *i; + if (group->mSpatialPartition->mRenderByGroup && + !group->isDead()) { - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(params.mTexture.get()); - params.mTexture->addTextureStats(params.mVSize); - if (params.mTextureMatrix) - { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; - if (params.mFullbright) - { - // Turn off lighting if it hasn't already been so. - if (light_enabled || !initialized_lighting) + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - initialized_lighting = TRUE; - if (use_shaders) + LLDrawInfo& params = **k; + + LLRenderPass::applyModelMatrix(params); + + if (params.mTexture.notNull()) { - target_shader = fullbright_shader; + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(params.mTexture.get()); + params.mTexture->addTextureStats(params.mVSize); + if (params.mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } } - else + + if (params.mFullbright) { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + // Turn off lighting if it hasn't already been so. + if (light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = fullbright_shader; + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + light_enabled = FALSE; + } + } + // Turn on lighting if it isn't already. + else if (!light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = simple_shader; + } + else + { + gPipeline.enableLightsDynamic(); + } + light_enabled = TRUE; } - light_enabled = FALSE; - } - } - // Turn on lighting if it isn't already. - else if (!light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } - light_enabled = TRUE; - } - // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) - { - llassert(target_shader != NULL); - current_shader = target_shader; - current_shader->bind(); - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } + // If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + if(use_shaders && (current_shader != target_shader)) + { + llassert(target_shader != NULL); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + } + current_shader = target_shader; + if (deferred_render) + { + gPipeline.bindDeferredShader(*current_shader); + } + else + { + current_shader->bind(); + } + } + else if (!use_shaders && current_shader != NULL) + { + LLGLSLShader::bindNoShader(); + if (deferred_render) + { + gPipeline.unbindDeferredShader(*current_shader); + } + current_shader = NULL; + } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + params.mVertexBuffer->setBuffer(mask); + params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount/3); - if (params.mTextureMatrix && texture && params.mTexture.notNull()) - { - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); + if (params.mTextureMatrix && params.mTexture.notNull()) + { + gGL.getTexUnit(0)->activate(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + } } } diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index bae3c6f225..3aa752f72c 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -48,13 +48,23 @@ public: VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA); /*virtual*/ ~LLDrawPoolAlpha(); + /*virtual*/ S32 getNumDeferredPasses(); + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumPostDeferredPasses(); + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + /*virtual*/ void beginRenderPass(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses() { return 1; } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 563f537b11..9db9197500 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -48,12 +48,19 @@ #include "pipeline.h" #include "llviewershadermgr.h" #include "llappviewer.h" +#include "llrendersphere.h" +#include "llviewerpartsim.h" static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; static LLGLSLShader* sVertexProgram = NULL; +BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; +BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; + +extern BOOL gUseGLPick; + F32 CLOTHING_GRAVITY_EFFECT = 0.7f; F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f; const S32 NUM_TEST_AVATARS = 30; @@ -85,6 +92,8 @@ S32 AVATAR_VERTEX_BYTES = 48; BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; +S32 normal_channel = -1; +S32 specular_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -111,6 +120,7 @@ S32 LLDrawPoolAvatar::getVertexShaderLevel() const void LLDrawPoolAvatar::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); + sShaderLevel = mVertexShaderLevel; if (sShaderLevel > 0) @@ -139,6 +149,177 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() // render() //----------------------------------------------------------------------------- + +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ + return getNumPasses(); +} + +void LLDrawPoolAvatar::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + + if (LLPipeline::sImpostorRender) + { + beginDeferredSkinned(); + return; + } + + switch (pass) + { + case 0: + beginDeferredImpostor(); + break; + case 1: + beginDeferredRigid(); + break; + case 2: + beginDeferredSkinned(); + break; + } +} + +void LLDrawPoolAvatar::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + + if (LLPipeline::sImpostorRender) + { + endDeferredSkinned(); + return; + } + + switch (pass) + { + case 0: + endDeferredImpostor(); + break; + case 1: + endDeferredRigid(); + break; + case 2: + endDeferredSkinned(); + break; + } +} + +void LLDrawPoolAvatar::renderDeferred(S32 pass) +{ + render(pass); +} + +S32 LLDrawPoolAvatar::getNumPostDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + sSkipOpaque = TRUE; + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarAlphaProgram; + + sRenderingSkinned = TRUE; + + gPipeline.bindDeferredShader(*sVertexProgram); + + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); +} + +void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + sSkipOpaque = FALSE; + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + + gPipeline.unbindDeferredShader(*sVertexProgram); + + sShaderLevel = mVertexShaderLevel; +} + +void LLDrawPoolAvatar::renderPostDeferred(S32 pass) +{ + render(2); //pass 2 = skinned +} + + +S32 LLDrawPoolAvatar::getNumShadowPasses() +{ + return 1; +} + +void LLDrawPoolAvatar::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + + sVertexProgram = &gDeferredAvatarShadowProgram; + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); + + glColor4f(1,1,1,1); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + +} + +void LLDrawPoolAvatar::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + + if (sShaderLevel > 0) + { + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolAvatar::renderShadow(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + if (!gRenderAvatar) + { + return; + } + + if (mDrawFace.empty()) + { + return; + } + + const LLFace *facep = mDrawFace[0]; + if (!facep->getDrawable()) + { + return; + } + LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); + + if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) + { + return; + } + + BOOL impostor = avatarp->isImpostor(); + if (impostor) + { + return; + } + + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + +} + S32 LLDrawPoolAvatar::getNumPasses() { return LLPipeline::sImpostorRender ? 1 : 3; @@ -254,6 +435,46 @@ void LLDrawPoolAvatar::endRigid() } } +void LLDrawPoolAvatar::beginDeferredImpostor() +{ + if (!LLPipeline::sReflectionRender) + { + LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); + LLVOAvatar::sNumVisibleAvatars = 0; + } + + sVertexProgram = &gDeferredImpostorProgram; + + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + + sVertexProgram->bind(); +} + +void LLDrawPoolAvatar::endDeferredImpostor() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->unbind(); + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::beginDeferredRigid() +{ + sVertexProgram = &gDeferredDiffuseProgram; + + sVertexProgram->bind(); +} + +void LLDrawPoolAvatar::endDeferredRigid() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->unbind(); + gGL.getTexUnit(0)->activate(); +} + + void LLDrawPoolAvatar::beginSkinned() { if (sShaderLevel > 0) @@ -283,7 +504,7 @@ void LLDrawPoolAvatar::beginSkinned() if (sShaderLevel > 0) // for hardware blending { sRenderingSkinned = TRUE; - + sVertexProgram->bind(); if (sShaderLevel >= SHADER_LEVEL_CLOTH) { @@ -344,6 +565,34 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } +void LLDrawPoolAvatar::beginDeferredSkinned() +{ + sSkipTransparent = TRUE; + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarProgram; + + sRenderingSkinned = TRUE; + + sVertexProgram->bind(); + + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::endDeferredSkinned() +{ + sSkipTransparent = FALSE; + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + sVertexProgram->unbind(); + + sShaderLevel = mVertexShaderLevel; + + gGL.getTexUnit(0)->activate(); +} + void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { @@ -393,27 +642,25 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } - if (!single_avatar && !avatarp->isFullyLoaded()) + if (!single_avatar && !avatarp->isFullyLoaded() ) { - - /* // debug code to draw a cube in place of avatar - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLVector3 pos = avatarp->getPositionAgent(); - - gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); - gGL.begin(GL_LINES); + if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + // debug code to draw a sphere in place of avatar + gGL.getTexUnit(0)->bind(LLViewerImage::sWhiteImagep.get()); + gGL.setColorMask(true, true); + LLVector3 pos = avatarp->getPositionAgent(); + gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); + + gGL.pushMatrix(); + gGL.translatef((F32)(pos.mV[VX]), + (F32)(pos.mV[VY]), + (F32)(pos.mV[VZ])); + gGL.scalef(0.15f, 0.15f, 0.3f); + gSphere.render(); + gGL.popMatrix(); + gGL.setColorMask(true, false); } - gGL.end(); - */ - - // don't render please return; } @@ -441,9 +688,20 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (impostor) { + if (LLPipeline::sRenderDeferred && avatarp->mImpostor.isComplete()) + { + if (normal_channel > -1) + { + avatarp->mImpostor.bindTexture(2, normal_channel); + } + if (specular_channel > -1) + { + avatarp->mImpostor.bindTexture(1, specular_channel); + } + } avatarp->renderImpostor(); } - else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS)) + else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { avatarp->renderFootShadows(); } @@ -680,11 +938,7 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD])); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 9df510f1e0..0dc95ff536 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -52,7 +52,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_WEIGHT | LLVertexBuffer::MAP_CLOTHWEIGHT }; @@ -74,6 +74,21 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); + /*virtual*/ S32 getNumDeferredPasses(); + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumPostDeferredPasses(); + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses(); + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); + void beginRigid(); void beginFootShadow(); void beginSkinned(); @@ -81,11 +96,22 @@ public: void endRigid(); void endFootShadow(); void endSkinned(); + + void beginDeferredImpostor(); + void beginDeferredRigid(); + void beginDeferredSkinned(); + + void endDeferredImpostor(); + void endDeferredRigid(); + void endDeferredSkinned(); /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. + + static BOOL sSkipOpaque; + static BOOL sSkipTransparent; }; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 60c41159d2..b11dcc1608 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -71,13 +71,14 @@ LLBumpImageList gBumpImageList; const S32 STD_BUMP_LATEST_FILE_VERSION = 1; const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; -const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2; +const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY; static LLGLSLShader* shader = NULL; static S32 cube_channel = -1; static S32 diffuse_channel = -1; +static S32 bump_channel = -1; // static void LLStandardBumpmap::init() @@ -146,7 +147,8 @@ void LLStandardBumpmap::restoreGL() TRUE, FALSE, 0, - 0); + 0); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL ); LLStandardBumpmap::sStandardBumpmapCount++; } @@ -318,7 +320,7 @@ void LLDrawPoolBump::beginShiny(bool invisible) // Second pass: environment map if (!invisible && mVertexShaderLevel > 1) { - sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD; + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } if (LLPipeline::sUnderWaterRender) @@ -432,15 +434,7 @@ void LLDrawPoolBump::endShiny(bool invisible) shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } } - shader->unbind(); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - } - if (cube_channel >= 0) - { - gGL.getTexUnit(cube_channel)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(cube_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } } gGL.getTexUnit(diffuse_channel)->disable(); @@ -462,7 +456,7 @@ void LLDrawPoolBump::beginFullbrightShiny() return; } - sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD; + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; // Second pass: environment map @@ -561,6 +555,10 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL applyModelMatrix(params); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -569,7 +567,7 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL // static -BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params) +BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { LLImageGL* bump = NULL; @@ -600,10 +598,19 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params) if (bump) { - gGL.getTexUnit(1)->bind(bump); - gGL.getTexUnit(0)->bind(bump); + if (channel == -2) + { + gGL.getTexUnit(1)->bind(bump); + gGL.getTexUnit(0)->bind(bump); + } + else + { + gGL.getTexUnit(channel)->bind(bump); + } + return TRUE; } + return FALSE; } @@ -691,6 +698,73 @@ void LLDrawPoolBump::endBump() gGL.setSceneBlendType(LLRender::BT_ALPHA); } +void LLDrawPoolBump::beginDeferredPass(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + mShiny = TRUE; + gDeferredBumpProgram.bind(); + diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE); +} + +void LLDrawPoolBump::endDeferredPass(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + mShiny = FALSE; + gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); + gDeferredBumpProgram.unbind(); + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolBump::renderDeferred(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + + U32 type = LLRenderPass::PASS_BUMP; + LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; + + for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; + + LLDrawPoolBump::bindBumpMap(params, bump_channel); + pushBatch(params, mask, TRUE); + } +} + +void LLDrawPoolBump::beginPostDeferredPass(S32 pass) +{ + beginFullbrightShiny(); +} + +void LLDrawPoolBump::endPostDeferredPass(S32 pass) +{ + endFullbrightShiny(); +} + +void LLDrawPoolBump::renderPostDeferred(S32 pass) +{ + renderFullbrightShiny(); +} + //////////////////////////////////////////////////////////////// // List of one-component bump-maps created from other texures. @@ -748,6 +822,7 @@ void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 void LLBumpImageList::updateImages() { + llpushcallstacks ; for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -774,7 +849,7 @@ void LLBumpImageList::updateImages() } } } - + llpushcallstacks ; for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -801,7 +876,7 @@ void LLBumpImageList::updateImages() } } } - + llpushcallstacks ; } @@ -886,6 +961,71 @@ void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_v } } +void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerImage* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + if (success && LLPipeline::sRenderDeferred) + { + LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); + generateNormalMapFromAlpha(src, nrm_image); + src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); + src_vi->createGLTexture(0, nrm_image); + } +} + +void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image) +{ + U8* nrm_data = nrm_image->getData(); + S32 resX = src->getWidth(); + S32 resY = src->getHeight(); + + U8* src_data = src->getData(); + + S32 src_cmp = src->getComponents(); + + F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale"); + + U32 idx = 0; + //generate normal map from pseudo-heightfield + for (S32 j = 0; j < resY; ++j) + { + for (S32 i = 0; i < resX; ++i) + { + S32 rX = (i+1)%resX; + S32 rY = (j+1)%resY; + S32 lX = (i-1)%resX; + S32 lY = (j-1)%resY; + + if (lX < 0) + { + lX += resX; + } + if (lY < 0) + { + lY += resY; + } + + F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1]; + + LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH); + LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH); + LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH); + LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH); + + LLVector3 norm = right%down + down%left + left%up + up%right; + + norm.normVec(); + + norm *= 0.5f; + norm += LLVector3(0.5f,0.5f,0.5f); + + idx = (j*resX+i)*4; + nrm_data[idx+0]= (U8) (norm.mV[0]*255); + nrm_data[idx+1]= (U8) (norm.mV[1]*255); + nrm_data[idx+2]= (U8) (norm.mV[2]*255); + nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1]; + } + } +} // static void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code ) @@ -1005,14 +1145,26 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma } //--------------------------------------------------- - LLImageGL* bump = new LLImageGL( TRUE); //immediately assign bump to a global smart pointer in case some local smart pointer //accidently releases it. + LLPointer<LLImageGL> bump = new LLImageGL( TRUE); + + if (!LLPipeline::sRenderDeferred) + { + bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); + bump->createGLTexture(0, dst_image); + } + else + { + LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); + generateNormalMapFromAlpha(src, nrm_image); + bump->setExplicitFormat(GL_RGBA, GL_RGBA); + bump->createGLTexture(0, nrm_image); + } + + iter->second = bump; // derefs (and deletes) old image //--------------------------------------------------- - - bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); } else { @@ -1040,21 +1192,6 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) } } -void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask) -{ - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - if (LLDrawPoolBump::bindBumpMap(params)) - { - pushBatch(params, mask, FALSE); - } - } -} - void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { applyModelMatrix(params); @@ -1088,10 +1225,14 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); } } + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -1131,3 +1272,33 @@ void LLDrawPoolInvisible::render(S32 pass) } } +void LLDrawPoolInvisible::beginDeferredPass(S32 pass) +{ + beginRenderPass(pass); +} + +void LLDrawPoolInvisible::endDeferredPass( S32 pass ) +{ + endRenderPass(pass); +} + +void LLDrawPoolInvisible::renderDeferred( S32 pass ) +{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff + LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + + U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; + glStencilMask(0); + glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); + gGL.setColorMask(false, false); + pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE); + gGL.setColorMask(true, true); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFFFFFFFF); + + if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + { + beginShiny(true); + renderShiny(true); + endShiny(true); + } +} diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index f5cb0cb769..34c1e9c29f 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -49,7 +49,7 @@ protected : public: static U32 sVertexMask; BOOL mShiny; - + virtual U32 getVertexDataMask() { return sVertexMask; } LLDrawPoolBump(); @@ -63,8 +63,7 @@ public: void renderBump(U32 type, U32 mask); void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); - void renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask); - + S32 numBumpPasses(); void beginShiny(bool invisible = false); @@ -78,7 +77,18 @@ public: void beginBump(); void renderBump(); void endBump(); - BOOL bindBumpMap(LLDrawInfo& params); + + virtual S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + virtual S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + + BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); }; enum EBumpEffect @@ -136,6 +146,9 @@ public: static void onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); static void onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); + static void onSourceStandardLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); + static void generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image); + private: static void onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump ); @@ -166,6 +179,11 @@ public: virtual void beginRenderPass( S32 pass ) { } virtual void endRenderPass( S32 pass ) { } virtual S32 getNumPasses() {return 1;} + + virtual S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); }; diff --git a/indra/newview/lldrawpoolclouds.h b/indra/newview/lldrawpoolclouds.h index 0346e1aa4e..c70dd41f78 100644 --- a/indra/newview/lldrawpoolclouds.h +++ b/indra/newview/lldrawpoolclouds.h @@ -42,7 +42,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; BOOL addFace(LLFace* face); diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h index 0badb59968..6c7d20beca 100644 --- a/indra/newview/lldrawpoolground.h +++ b/indra/newview/lldrawpoolground.h @@ -42,7 +42,7 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index d4bdfc494a..1fdf87f6d2 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -103,18 +103,15 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { simple_shader = &gObjectSimpleWaterProgram; - fullbright_shader = &gObjectFullbrightWaterProgram; } else { simple_shader = &gObjectSimpleProgram; - fullbright_shader = &gObjectFullbrightProgram; } if (mVertexShaderLevel > 0) { simple_shader->bind(); - simple_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 0.f); } else { @@ -140,39 +137,204 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) void LLDrawPoolSimple::render(S32 pass) { LLGLDisable blend(GL_BLEND); - LLGLState alpha_test(GL_ALPHA_TEST, gPipeline.canUseWindLightShadersOnObjects()); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + LLGLDisable alpha_test(GL_ALPHA_TEST); + { //render simple LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); gPipeline.enableLightsDynamic(); renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + + if (LLPipeline::sRenderDeferred) + { + renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask()); + } } +} + +//=============================== +//DEFERRED IMPLEMENTATION +//=============================== + +void LLDrawPoolSimple::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + gDeferredDiffuseProgram.bind(); +} + +void LLDrawPoolSimple::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLRenderPass::endRenderPass(pass); + + gDeferredDiffuseProgram.unbind(); +} + +void LLDrawPoolSimple::renderDeferred(S32 pass) +{ + LLGLDisable blend(GL_BLEND); + LLGLDisable alpha_test(GL_ALPHA_TEST); + + { //render simple + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + } +} + +// grass drawpool +LLDrawPoolGrass::LLDrawPoolGrass() : + LLRenderPass(POOL_GRASS) +{ + +} + +void LLDrawPoolGrass::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + + +void LLDrawPoolGrass::beginRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + + if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gObjectSimpleWaterProgram; + } + else + { + simple_shader = &gObjectSimpleProgram; + } + + if (mVertexShaderLevel > 0) + { + simple_shader->bind(); + } + else + { + // don't use shaders! + if (gGLManager.mHasShaderObjects) + { + LLGLSLShader::bindNoShader(); + } + } +} + +void LLDrawPoolGrass::endRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLRenderPass::endRenderPass(pass); + + if (mVertexShaderLevel > 0) + { + simple_shader->unbind(); + } +} + +void LLDrawPoolGrass::render(S32 pass) +{ + LLGLDisable blend(GL_BLEND); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); LLGLEnable test(GL_ALPHA_TEST); - LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); } - { //render fullbright - if (mVertexShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); - } - else - { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - } - LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR; - renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); - } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolGrass::beginDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolGrass::endDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolGrass::renderDeferred(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + + { + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + gDeferredTreeProgram.bind(); + LLGLEnable test(GL_ALPHA_TEST); + //render grass + LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); + } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } + +// Fullbright drawpool +LLDrawPoolFullbright::LLDrawPoolFullbright() : + LLRenderPass(POOL_FULLBRIGHT) +{ +} + +void LLDrawPoolFullbright::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + +void LLDrawPoolFullbright::beginRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + + if (LLPipeline::sUnderWaterRender) + { + fullbright_shader = &gObjectFullbrightWaterProgram; + } + else + { + fullbright_shader = &gObjectFullbrightProgram; + } +} + +void LLDrawPoolFullbright::endRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + LLRenderPass::endRenderPass(pass); + + if (mVertexShaderLevel > 0) + { + fullbright_shader->unbind(); + } +} + +void LLDrawPoolFullbright::render(S32 pass) +{ //render fullbright + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + if (mVertexShaderLevel > 0) + { + fullbright_shader->bind(); + fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + + //gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); + + //LLGLEnable test(GL_ALPHA_TEST); + //LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; + renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); + + //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +S32 LLDrawPoolFullbright::getNumPasses() +{ + return 1; +} + diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 6702715b9e..f561510375 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -42,19 +42,77 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } LLDrawPoolSimple(); + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /// We need two passes so we can handle emissive materials separately. + /*virtual*/ S32 getNumPasses() { return 1; } + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); + +}; + +class LLDrawPoolGrass : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolGrass(); + + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + /*virtual*/ void beginRenderPass(S32 pass); /*virtual*/ void endRenderPass(S32 pass); /// We need two passes so we can handle emissive materials separately. /*virtual*/ S32 getNumPasses() { return 1; } /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); +}; + +class LLDrawPoolFullbright : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolFullbright(); + + /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /*virtual*/ S32 getNumPasses(); + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); }; @@ -66,13 +124,18 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } virtual void prerender() { } + /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + void render(S32 pass = 0); void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 027b925e09..7f21adcc94 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -62,7 +62,7 @@ LLDrawPool *LLDrawPoolSky::instancePool() void LLDrawPoolSky::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); - gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); +// gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); } void LLDrawPoolSky::render(S32 pass) diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h index a7fad72ea1..f35b114730 100644 --- a/indra/newview/lldrawpoolsky.h +++ b/indra/newview/lldrawpoolsky.h @@ -50,7 +50,7 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -59,6 +59,11 @@ public: /*virtual*/ LLDrawPool *instancePool(); + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 3080f99d9f..2c644b0fd5 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -74,14 +74,14 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); - mAlphaRampImagep->setClamp(TRUE, TRUE); + mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c", TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); - m2DAlphaRampImagep->setClamp(TRUE, TRUE); + m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mTexturep->setBoostLevel(LLViewerImage::BOOST_TERRAIN); @@ -100,6 +100,18 @@ LLDrawPool *LLDrawPoolTerrain::instancePool() } +U32 LLDrawPoolTerrain::getVertexDataMask() +{ + if (LLPipeline::sShadowRender) + { + return LLVertexBuffer::MAP_VERTEX; + } + else + { + return VERTEX_DATA_MASK; + } +} + void LLDrawPoolTerrain::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); @@ -217,6 +229,60 @@ void LLDrawPoolTerrain::render(S32 pass) } } +void LLDrawPoolTerrain::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFacePool::beginRenderPass(pass); + + sShader = &gDeferredTerrainProgram; + + sShader->bind(); +} + +void LLDrawPoolTerrain::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFacePool::endRenderPass(pass); + sShader->unbind(); +} + +void LLDrawPoolTerrain::renderDeferred(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + if (mDrawFace.empty()) + { + return; + } + renderFullShader(); +} + +void LLDrawPoolTerrain::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFacePool::beginRenderPass(pass); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gDeferredShadowProgram.bind(); +} + +void LLDrawPoolTerrain::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFacePool::endRenderPass(pass); + gDeferredShadowProgram.unbind(); +} + +void LLDrawPoolTerrain::renderShadow(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + if (mDrawFace.empty()) + { + return; + } + //LLGLEnable offset(GL_POLYGON_OFFSET); + //glCullFace(GL_FRONT); + drawLoop(); + //glCullFace(GL_BACK); +} void LLDrawPoolTerrain::renderFullShader() { @@ -360,9 +426,6 @@ void LLDrawPoolTerrain::renderFullShader() void LLDrawPoolTerrain::renderFull4TU() { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); @@ -390,7 +453,6 @@ void LLDrawPoolTerrain::renderFull4TU() // gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture0p); - glClientActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); @@ -409,9 +471,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - + // Care about alpha only gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); @@ -423,9 +483,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -441,14 +498,12 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->bind(detail_texture1p); gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - + // Set alpha texture and do lighting modulation gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR); gGL.getTexUnit(0)->activate(); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - + // GL_BLEND disabled by default drawLoop(); @@ -459,9 +514,7 @@ void LLDrawPoolTerrain::renderFull4TU() // gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture3p); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -477,9 +530,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Set the texture matrix glMatrixMode(GL_TEXTURE); @@ -490,7 +540,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // // Stage 2: Interpolate detail2 with existing based on ramp // @@ -498,9 +547,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -517,9 +563,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - // Set the texture matrix glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -530,7 +573,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); gGL.getTexUnit(0)->activate(); - glClientActiveTextureARB(GL_TEXTURE0_ARB); { LLGLEnable blend(GL_BLEND); drawLoop(); @@ -541,9 +583,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->disable(); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -551,9 +591,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->disable(); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glMatrixMode(GL_TEXTURE); @@ -563,9 +601,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -579,9 +615,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glDisableClientState(GL_NORMAL_ARRAY); - + glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glMatrixMode(GL_TEXTURE); @@ -856,7 +890,7 @@ void LLDrawPoolTerrain::renderOwnership() { LLFace *facep = *iter; facep->renderIndexed(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD); + LLVertexBuffer::MAP_TEXCOORD0); } glMatrixMode(GL_TEXTURE); diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index b243486bf4..19d09e2feb 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -43,12 +43,14 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_TEXCOORD3 | LLVertexBuffer::MAP_COLOR }; - virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + virtual U32 getVertexDataMask(); static S32 getDetailMode(); LLDrawPoolTerrain(LLViewerImage *texturep); @@ -56,6 +58,15 @@ public: /*virtual*/ LLDrawPool *instancePool(); + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses() { return 1; } + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 616461d06e..2f2b07232a 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -43,6 +43,7 @@ #include "llviewercamera.h" #include "llviewershadermgr.h" #include "llrender.h" +#include "llviewercontrol.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -52,7 +53,7 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : mTexturep(texturep) { gGL.getTexUnit(0)->bind(mTexturep.get()); - mTexturep->setClamp(FALSE, FALSE); + mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } LLDrawPool *LLDrawPoolTree::instancePool() @@ -91,7 +92,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) void LLDrawPoolTree::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(LLPipeline::sShadowRender ? LLFastTimer::FTM_SHADOW_TREE : LLFastTimer::FTM_RENDER_TREES); if (mDrawFace.empty()) { @@ -101,7 +102,23 @@ void LLDrawPoolTree::render(S32 pass) LLGLEnable test(GL_ALPHA_TEST); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); - renderTree(); + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + renderTree(); + } + else + { + gGL.getTexUnit(sDiffTex)->bind(mTexturep); + + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + } + } } void LLDrawPoolTree::endRenderPass(S32 pass) @@ -115,6 +132,54 @@ void LLDrawPoolTree::endRenderPass(S32 pass) } } +//============================================ +// deferred implementation +//============================================ +void LLDrawPoolTree::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + + shader = &gDeferredTreeProgram; + shader->bind(); +} + +void LLDrawPoolTree::renderDeferred(S32 pass) +{ + render(pass); +} + +void LLDrawPoolTree::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + + shader->unbind(); +} + +//============================================ +// shadow implementation +//============================================ +void LLDrawPoolTree::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gDeferredShadowProgram.bind(); +} + +void LLDrawPoolTree::renderShadow(S32 pass) +{ + render(pass); +} + +void LLDrawPoolTree::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gDeferredShadowProgram.unbind(); +} + + void LLDrawPoolTree::renderForSelect() { if (mDrawFace.empty()) @@ -133,7 +198,43 @@ void LLDrawPoolTree::renderForSelect() gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - renderTree(TRUE); + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + renderTree(TRUE); + } + else + { + gGL.getTexUnit(sDiffTex)->bind(mTexturep); + + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + LLDrawable *drawablep = face->getDrawable(); + + if (drawablep->isDead() || face->mVertexBuffer.isNull()) + { + continue; + } + + // Render each of the trees + LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get(); + + LLColor4U color(255,255,255,255); + + if (treep->mGLName != 0) + { + S32 name = treep->mGLName; + color = LLColor4U((U8)(name >> 16), (U8)(name >> 8), (U8)name, 255); + + LLFacePool::LLOverrideFaceColor col(this, color); + + face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + } + } + } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ALPHA); diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h index 5fbbb20bc0..80c4fdfffe 100644 --- a/indra/newview/lldrawpooltree.h +++ b/indra/newview/lldrawpooltree.h @@ -43,7 +43,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -53,6 +53,17 @@ public: /*virtual*/ LLDrawPool *instancePool(); /*virtual*/ void prerender(); + + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses() { return 1; } + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); + /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 2005184454..ce3425dd9e 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -59,6 +59,8 @@ const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004"); static float sTime; +BOOL deferred_render = FALSE; + BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; @@ -70,14 +72,16 @@ LLDrawPoolWater::LLDrawPoolWater() : { mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE); gGL.getTexUnit(0)->bind(mHBTex[0].get()); - mHBTex[0]->setClamp(TRUE, TRUE); + mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE); gGL.getTexUnit(0)->bind(mHBTex[1].get()); - mHBTex[1]->setClamp(TRUE, TRUE); + mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); mWaterImagep = gImageList.getImage(WATER_TEST); + mWaterImagep->setNoDelete() ; mWaterNormp = gImageList.getImage(DEFAULT_WATER_NORMAL); + mWaterNormp->setNoDelete() ; restoreGL(); } @@ -121,6 +125,18 @@ S32 LLDrawPoolWater::getNumPasses() return 0; } +void LLDrawPoolWater::beginPostDeferredPass(S32 pass) +{ + beginRenderPass(pass); + deferred_render = TRUE; +} + +void LLDrawPoolWater::endPostDeferredPass(S32 pass) +{ + endRenderPass(pass); + deferred_render = FALSE; +} + void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); @@ -271,10 +287,7 @@ void LLDrawPoolWater::render(S32 pass) gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - if (gSky.mVOSkyp->getCubeMap()) - { - gSky.mVOSkyp->getCubeMap()->disable(); - } + gSky.mVOSkyp->getCubeMap()->disable(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); @@ -375,7 +388,11 @@ void LLDrawPoolWater::shade() F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); - if (eyedepth < 0.f && LLPipeline::sWaterReflections) + if (deferred_render) + { + shader = &gDeferredWaterProgram; + } + else if (eyedepth < 0.f && LLPipeline::sWaterReflections) { shader = &gUnderWaterProgram; } @@ -408,21 +425,36 @@ void LLDrawPoolWater::shade() mWaterNormp->addTextureStats(1024.f*1024.f); gGL.getTexUnit(bumpTex)->bind(mWaterNormp.get()); - mWaterNormp->setMipFilterNearest (mWaterNormp->getMipFilterNearest(), - !gSavedSettings.getBOOL("RenderWaterMipNormal")); + if (gSavedSettings.getBOOL("RenderWaterMipNormal")) + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT); + } S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX); - stop_glerror(); + + if (deferred_render) + { + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); + } - shader->bind(); - if (screentex > -1) { shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); shader->uniform1f(LLViewerShaderMgr::WATER_FOGDENSITY, param_mgr->getFogDensity()); + gPipeline.mWaterDis.bindTexture(0, screentex); } - + + stop_glerror(); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); if (mVertexShaderLevel == 1) @@ -534,7 +566,15 @@ void LLDrawPoolWater::shade() shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); shader->disableTexture(LLViewerShaderMgr::WATER_REFTEX); shader->disableTexture(LLViewerShaderMgr::WATER_SCREENDEPTH); - shader->unbind(); + + if (deferred_render) + { + gPipeline.unbindDeferredShader(*shader); + } + else + { + shader->unbind(); + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index 2eb358b289..6351041140 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -60,7 +60,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -70,6 +70,11 @@ public: /*virtual*/ LLDrawPool *instancePool(); static void restoreGL(); + + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } /*virtual*/ S32 getNumPasses(); /*virtual*/ void render(S32 pass = 0); diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index 1eb3e5fd90..c7a1f3fe27 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -41,7 +41,7 @@ class LLDrawPoolWLSky : public LLDrawPool { public: static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; @@ -50,6 +50,11 @@ public: /*virtual*/ BOOL isDead() { return FALSE; } + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void endRenderPass( S32 pass ); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 6951f3a96a..62fcf60e7f 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -112,7 +112,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima } // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; mTexture->createGLTexture(0, raw_image); - mTexture->setClamp(mClamp, mClamp); + mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mTexture->setGLTextureCreated(false); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index dc3e2f1896..e096bc07bd 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -165,6 +165,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mReferenceIndex = -1; mTextureMatrix = NULL; + mDrawInfo = NULL; mFaceColor = LLColor4(1,0,0,1); @@ -178,9 +179,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) void LLFace::destroy() { - mDrawablep = NULL; - mVObjp = NULL; - if (mDrawPoolp) { mDrawPoolp->removeFace(this); @@ -191,7 +189,21 @@ void LLFace::destroy() { delete mTextureMatrix; mTextureMatrix = NULL; + + if (mDrawablep.notNull()) + { + LLSpatialGroup* group = mDrawablep->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + } + } } + + setDrawInfo(NULL); + + mDrawablep = NULL; + mVObjp = NULL; } @@ -289,7 +301,7 @@ U16 LLFace::getGeometryAvatar( { mVertexBuffer->getVertexStrider (vertices, mGeomIndex); mVertexBuffer->getNormalStrider (normals, mGeomIndex); - mVertexBuffer->getTexCoordStrider (tex_coords, mGeomIndex); + mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex); mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex); mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex); } @@ -309,9 +321,9 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no { mVertexBuffer->getNormalStrider(normals, mGeomIndex); } - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD)) + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0)) { - mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex); + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); } mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); @@ -435,12 +447,13 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) setFaceColor(color); renderSetColor(); - mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #endif mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - + + unsetFaceColor(); unsetFaceColor(); gGL.popMatrix(); } @@ -477,9 +490,27 @@ void LLFace::renderSelectedUV() glMatrixMode(GL_MODELVIEW); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } - */ +void LLFace::setDrawInfo(LLDrawInfo* draw_info) +{ + if (draw_info) + { + if (draw_info->mFace) + { + draw_info->mFace->setDrawInfo(NULL); + } + draw_info->mFace = this; + } + + if (mDrawInfo) + { + mDrawInfo->mFace = NULL; + } + + mDrawInfo = draw_info; +} + void LLFace::printDebugInfo() const { LLFacePool *poolp = getPool(); @@ -587,11 +618,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) { - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - { //vertex buffer no longer valid - mVertexBuffer = NULL; - mLastVertexBuffer = NULL; - } + //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + //{ //vertex buffer no longer valid + // mVertexBuffer = NULL; + // mLastVertexBuffer = NULL; + //} LLVector3 min,max; @@ -739,6 +770,34 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, return tc; } +void LLFace::updateRebuildFlags() +{ + if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + BOOL moved = TRUE; + if (mLastVertexBuffer == mVertexBuffer && + !mVertexBuffer->isEmpty()) + { //this face really doesn't need to be regenerated, try real hard not to do so + if (mLastGeomCount == mGeomCount && + mLastGeomIndex == mGeomIndex && + mLastIndicesCount == mIndicesCount && + mLastIndicesIndex == mIndicesIndex) + { //data is in same location in vertex buffer + moved = FALSE; + } + } + mLastMoveTime = gFrameTimeSeconds; + + if (moved) + { + mDrawablep->setState(LLDrawable::REBUILD_VOLUME); + } + } + else + { + mLastUpdateTime = gFrameTimeSeconds; + } +} BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, @@ -764,16 +823,16 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - LLStrider<LLVector3> old_verts,vertices; - LLStrider<LLVector2> old_texcoords,tex_coords; - LLStrider<LLVector2> old_texcoords2,tex_coords2; - LLStrider<LLVector3> old_normals,normals; - LLStrider<LLColor4U> old_colors,colors; + LLStrider<LLVector3> vertices; + LLStrider<LLVector2> tex_coords; + LLStrider<LLVector2> tex_coords2; + LLStrider<LLVector3> normals; + LLStrider<LLColor4U> colors; + LLStrider<LLVector3> binormals; LLStrider<U16> indicesp; BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); - BOOL moved = TRUE; - + BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; if (global_volume) @@ -784,35 +843,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { scale = mVObjp->getScale(); } - - if (!full_rebuild) - { - if (mLastVertexBuffer == mVertexBuffer && - !mVertexBuffer->isEmpty()) - { //this face really doesn't need to be regenerated, try real hard not to do so - if (mLastGeomCount == mGeomCount && - mLastGeomIndex == mGeomIndex && - mLastIndicesCount == mIndicesCount && - mLastIndicesIndex == mIndicesIndex) - { //data is in same location in vertex buffer - moved = FALSE; - } - - if (!moved && !mDrawablep->isState(LLDrawable::REBUILD_ALL)) - { //nothing needs to be done - return FALSE; - } - } - mLastMoveTime = gFrameTimeSeconds; - } - else - { - mLastUpdateTime = gFrameTimeSeconds; - } - BOOL rebuild_pos = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_POSITION); - BOOL rebuild_color = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_COLOR); - BOOL rebuild_tcoord = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); + BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); + BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); const LLTextureEntry *tep = mVObjp->getTE(f); U8 bump_code = tep ? tep->getBumpmap() : 0; @@ -820,14 +856,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_pos) { mVertexBuffer->getVertexStrider(vertices, mGeomIndex); + } + if (rebuild_normal) + { mVertexBuffer->getNormalStrider(normals, mGeomIndex); } + if (rebuild_binormal) + { + mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); + } if (rebuild_tcoord) { - mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex); - if (bump_code) + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); + if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { - mVertexBuffer->getTexCoord2Strider(tex_coords2, mGeomIndex); + mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); } } if (rebuild_color) @@ -922,14 +965,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 0.75f }; - if (getPoolType() != LLDrawPool::POOL_ALPHA && LLPipeline::sRenderBump && tep->getShiny()) + if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } } // INDICES - if (full_rebuild || moved) + if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); for (U16 i = 0; i < num_indices; i++) @@ -1046,7 +1089,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords++ = tc; - if (bump_code) + if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; @@ -1066,38 +1109,31 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords2++ = tc; } } - else if (moved) - { - *tex_coords++ = *old_texcoords++; - if (bump_code) - { - *tex_coords2++ = *old_texcoords2++; - } - } if (rebuild_pos) { *vertices++ = vf.mVertices[i].mPosition * mat_vert; - + } + + if (rebuild_normal) + { LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; normal.normVec(); *normals++ = normal; } - else if (moved) + + if (rebuild_binormal) { - *normals++ = *old_normals++; - *vertices++ = *old_verts++; + LLVector3 binormal = vf.mVertices[i].mBinormal * mat_normal; + binormal.normVec(); + *binormals++ = binormal; } - + if (rebuild_color) { *colors++ = color; } - else if (moved) - { - *colors++ = *old_colors++; - } } if (rebuild_tcoord) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index dfe5ab6277..4a551ff261 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -134,7 +134,9 @@ public: const LLColor4& getFaceColor() const { return mFaceColor; } const LLColor4& getRenderColor() const; + //for volumes + void updateRebuildFlags(); BOOL getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, @@ -169,7 +171,7 @@ public: void updateCenterAgent(); // Update center when xform has changed. void renderSelectedUV(); - void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); void renderSelected(LLImageGL *image, const LLColor4 &color); F32 getKey() const { return mDistance; } @@ -182,10 +184,12 @@ public: void setGeomIndex(U16 idx) { mGeomIndex = idx; } void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } - + void setDrawInfo(LLDrawInfo* draw_info); + protected: public: + LLVector3 mCenterLocal; LLVector3 mCenterAgent; LLVector3 mExtents[2]; @@ -196,6 +200,7 @@ public: F32 mLastUpdateTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; + LLDrawInfo* mDrawInfo; protected: friend class LLGeometryManager; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 25a26f05d8..340254a909 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -162,8 +162,14 @@ static struct ft_display_info ft_display_table[] = // { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 }, { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 }, // { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 }, -// { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, - { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, + { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, + { LLFastTimer::FTM_SHADOW_RENDER, " Shadow", &LLColor4::green5, 1 }, + { LLFastTimer::FTM_SHADOW_SIMPLE, " Simple", &LLColor4::yellow2, 1 }, + { LLFastTimer::FTM_SHADOW_ALPHA, " Alpha", &LLColor4::yellow6, 1 }, + { LLFastTimer::FTM_SHADOW_TERRAIN, " Terrain", &LLColor4::green6, 1 }, + { LLFastTimer::FTM_SHADOW_AVATAR, " Avatar", &LLColor4::yellow1, 1 }, + { LLFastTimer::FTM_SHADOW_TREE, " Tree", &LLColor4::yellow8, 1 }, + { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 }, { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 }, { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 }, diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index c23d58cb7a..2652387bfe 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -122,6 +122,14 @@ LLFloaterAbout::LLFloaterAbout() std::string support; support.append("\n\n"); +#if LL_MSVC + support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER)); +#endif + +#if LL_GNUC + support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION)); +#endif + // Position LLViewerRegion* region = gAgent.getRegion(); if (region) diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 045ca6aa36..747b685b5e 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -236,9 +236,11 @@ BOOL LLFloaterAnimPreview::postBuild() // now load bvh file S32 file_size; - apr_file_t* fp = ll_apr_file_open(mFilenameAndPath, LL_APR_RB, &file_size); - - if (!fp) + + LLAPRFile infile ; + infile.open(mFilenameAndPath, LL_APR_RB, NULL, &file_size); + + if (!infile.getFileHandle()) { llwarns << "Can't open BVH file:" << mFilename << llendl; } @@ -248,14 +250,14 @@ BOOL LLFloaterAnimPreview::postBuild() file_buffer = new char[file_size + 1]; - if (file_size == ll_apr_file_read(fp, file_buffer, file_size)) + if (file_size == infile.read(file_buffer, file_size)) { file_buffer[file_size] = '\0'; llinfos << "Loading BVH file " << mFilename << llendl; loaderp = new LLBVHLoader(file_buffer); } - apr_file_close(fp); + infile.close() ; delete[] file_buffer; } } diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 2dabb55eaa..747431fb19 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -207,7 +207,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) self->mImage = new LLImageGL((LLImageRaw*)raw, FALSE); gGL.getTexUnit(0)->bind(self->mImage); - self->mImage->setClamp(TRUE, TRUE); + self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP); } else { diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 4f8c5ce4eb..f82d692dd3 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -167,7 +167,7 @@ createUI () } mRGBImage = new LLImageGL ( (LLImageRaw*)raw, FALSE ); gGL.getTexUnit(0)->bind(mRGBImage); - mRGBImage->setClamp(TRUE, TRUE); + mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP); // create palette for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each ) diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 67be553ae7..689f9f48d0 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -234,8 +234,7 @@ void LLFloaterImagePreview::draw() gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); if (mAvatarPreview) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 14caed9d97..164c33b10d 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -862,9 +862,17 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE); - previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE); - gGL.getTexUnit(0)->bind(previewp->mViewerImage[previewp->mCurImageIndex]); - previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE); + LLPointer<LLImageGL> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; + gGL.getTexUnit(0)->bind(curr_preview_image); + if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) + { + curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); + } + else + { + curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); previewp->mSnapshotUpToDate = TRUE; previewp->generateThumbnailImage(TRUE) ; diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index 0c7d785ae0..3535fe185c 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -184,7 +184,7 @@ void LLHUDIcon::renderIcon(BOOL for_select) void LLHUDIcon::setImage(LLViewerImage* imagep) { mImagep = imagep; - mImagep->setClamp(TRUE, TRUE); + mImagep->setAddressMode(LLTexUnit::TAM_CLAMP); } void LLHUDIcon::setScale(F32 fraction_of_fov) diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 0e9f7c16a6..bdff492948 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -131,7 +131,7 @@ void LLHUDObject::cleanupHUDObjects() (*object_it)->markDead(); if ((*object_it)->getNumRefs() > 1) { - llinfos << "LLHUDObject " << (LLHUDObject *)(*object_it) << " has " << (*object_it)->getNumRefs() << " refs!" << llendl; + llinfos << "LLHUDObject " << (LLHUDObject *)(*object_it) << " type " << (S32)(*object_it)->getType() << " has " << (*object_it)->getNumRefs() << " refs!" << llendl; } } sHUDObjects.clear(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index e3483fdaca..2e59240c49 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -737,11 +737,12 @@ void LLHUDText::updateVisibility() dir_from_camera.normVec(); if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f) - { - mPositionAgent -= projected_vec(vec_from_camera, LLViewerCamera::getInstance()->getAtAxis()) * 1.f; - mPositionAgent += LLViewerCamera::getInstance()->getAtAxis() * (LLViewerCamera::getInstance()->getNear() + 0.1f); + { //text is behind camera, don't render + mVisible = FALSE; + return; } - else if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius()) + + if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius()) { mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis())); } @@ -1068,6 +1069,10 @@ void LLHUDText::markDead() void LLHUDText::renderAllHUD() { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + LLGLEnable color_mat(GL_COLOR_MATERIAL); LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -1077,6 +1082,10 @@ void LLHUDText::renderAllHUD() { (*text_it)->renderText(FALSE); } + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } void LLHUDText::shiftAll(const LLVector3& offset) diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 95825aa2f2..326c511fcf 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -639,7 +639,7 @@ void LLJoystickCameraRotate::draw() } // Draws image rotated by multiples of 90 degrees -void LLJoystickCameraRotate::drawRotatedImage( const LLImageGL* image, S32 rotations ) +void LLJoystickCameraRotate::drawRotatedImage( LLImageGL* image, S32 rotations ) { S32 width = image->getWidth(); S32 height = image->getHeight(); diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index e7d4beb375..076a506f14 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -134,7 +134,7 @@ public: protected: F32 getOrbitRate(); virtual void updateSlop(); - void drawRotatedImage( const LLImageGL* image, S32 rotations ); + void drawRotatedImage( LLImageGL* image, S32 rotations ); protected: BOOL mInLeft; diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 959a575950..dfa624a59c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -164,8 +164,7 @@ void LLManipTranslate::restoreGL() GLuint* d = new GLuint[rez*rez]; gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); while (rez >= 1) { @@ -261,9 +260,9 @@ void LLManipTranslate::restoreGL() } } #ifdef LL_WINDOWS - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_BYTE, d); + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); #else - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d); + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d); #endif rez = rez >> 1; mip++; diff --git a/indra/newview/llmimetypes.h b/indra/newview/llmimetypes.h index 4b48bd8daa..7a50c29429 100644 --- a/indra/newview/llmimetypes.h +++ b/indra/newview/llmimetypes.h @@ -101,10 +101,10 @@ public: std::string mPlayTip; // custom tool tip to display for Play button - bool mAllowResize; + BOOL mAllowResize; // enable/disable media size edit fields - bool mAllowLooping; + BOOL mAllowLooping; // enable/disable media looping checkbox }; typedef std::map< std::string, LLMIMEInfo > mime_info_map_t; diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index 24fea645d4..b779aa0f83 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -285,18 +285,37 @@ LLColor4U LLSky::getFadeColor() const void LLSky::init(const LLVector3 &sun_direction) { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + mVOWLSkyp = static_cast<LLVOWLSky*>(gObjectList.createObjectViewer(LLViewerObject::LL_VO_WL_SKY, NULL)); mVOWLSkyp->initSunDirection(sun_direction, LLVector3::zero); - gPipeline.addObject(mVOWLSkyp.get()); + gPipeline.createObject(mVOWLSkyp.get()); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mVOSkyp = (LLVOSky *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SKY, NULL); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + mVOSkyp->initSunDirection(sun_direction, LLVector3()); - gPipeline.addObject((LLViewerObject *)mVOSkyp); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + + gPipeline.createObject((LLViewerObject *)mVOSkyp); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mVOGroundp = (LLVOGround*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_GROUND, NULL); LLVOGround *groundp = mVOGroundp; - gPipeline.addObject((LLViewerObject *)groundp); + gPipeline.createObject((LLViewerObject *)groundp); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio")); @@ -309,6 +328,8 @@ void LLSky::init(const LLVector3 &sun_direction) // Get the parameters. mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition"); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || mOverrideSimSunPosition) { @@ -319,6 +340,8 @@ void LLSky::init(const LLVector3 &sun_direction) setSunDirection(sun_direction, LLVector3(0.f, 0.f, 0.f)); } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mUpdatedThisFrame = TRUE; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dc4b8134dc..6e5231bddd 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -49,7 +49,7 @@ #include "lloctree.h" #include "llvoavatar.h" -const F32 SG_OCCLUSION_FUDGE = 1.01f; +const F32 SG_OCCLUSION_FUDGE = 0.25f; #define SG_DISCARD_TOLERANCE 0.01f #if LL_OCTREE_PARANOIA_CHECK @@ -191,7 +191,7 @@ static U8 sOcclusionIndices[] = b000, b110, b100, b101, b001, b011, b010, b110, }; -U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center) +U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center) { LLVector3 d = center - camera->getOrigin(); @@ -219,7 +219,7 @@ void LLSpatialGroup::buildOcclusion() mOcclusionVerts = new F32[8*3]; } - LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f); + LLVector3 r = mBounds[1] + LLVector3(SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE); for (U32 k = 0; k < 3; k++) { @@ -562,8 +562,21 @@ void LLSpatialGroup::rebuildGeom() } } +void LLSpatialGroup::rebuildMesh() +{ + if (!isDead()) + { + mSpatialPartition->rebuildMesh(this); + } +} + void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { + if (!gPipeline.hasRenderType(mDrawableType)) + { + return; + } + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -612,6 +625,11 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->clearState(LLSpatialGroup::GEOM_DIRTY); } +void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) +{ + +} + BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) { const OctreeNode* node = mOctreeNode; @@ -778,7 +796,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset) mObjectExtents[0] += offset; mObjectExtents[1] += offset; - if (!mSpatialPartition->mRenderByGroup) + //if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); } @@ -1271,8 +1289,8 @@ void LLSpatialGroup::checkOcclusion() clearState(QUERY_PENDING | DISCARD_QUERY); } - else if (mSpatialPartition->mOcclusionEnabled) - { + else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED)) + { //check occlusion has been issued for occluded node that has not had a query issued assert_states_valid(this); clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); @@ -1282,7 +1300,7 @@ void LLSpatialGroup::checkOcclusion() void LLSpatialGroup::doOcclusion(LLCamera* camera) { - if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1) + if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) { if (earlyFail(camera, this)) { @@ -1309,7 +1327,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery); glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_occlusion_indices(camera, mBounds[0])); + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); glEndQueryARB(GL_SAMPLES_PASSED_ARB); } @@ -1470,7 +1488,7 @@ public: group->checkOcclusion(); if (group->mOctreeNode->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled + LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isState(LLSpatialGroup::OCCLUDED)) { gPipeline.markOccluder(group); @@ -1594,6 +1612,86 @@ public: } }; +class LLOctreeCullShadow : public LLOctreeCull +{ +public: + LLOctreeCullShadow(LLCamera* camera) + : LLOctreeCull(camera) { } + + virtual S32 frustumCheck(const LLSpatialGroup* group) + { + return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); + } + + virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + { + return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); + } +}; + +class LLOctreeCullVisExtents: public LLOctreeCullShadow +{ +public: + LLOctreeCullVisExtents(LLCamera* camera, LLVector3& min, LLVector3& max) + : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } + + virtual bool earlyFail(LLSpatialGroup* group) + { + if (group->mOctreeNode->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + virtual void processGroup(LLSpatialGroup* group) + { + if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) + { //megaprims and water edge patches be damned! + mEmpty = FALSE; + update_min_max(mMin, mMax, group->mObjectExtents[0]); + update_min_max(mMin, mMax, group->mObjectExtents[1]); + } + } + + BOOL mEmpty; + LLVector3& mMin; + LLVector3& mMax; +}; + +class LLOctreeCullDetectVisible: public LLOctreeCullShadow +{ +public: + LLOctreeCullDetectVisible(LLCamera* camera) + : LLOctreeCullShadow(camera), mResult(FALSE) { } + + virtual bool earlyFail(LLSpatialGroup* group) + { + if (mResult || //already found a node, don't check any more + group->mOctreeNode->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + virtual void processGroup(LLSpatialGroup* group) + { + if (group->isVisible()) + { + mResult = TRUE; + } + } + + BOOL mResult; +}; + class LLOctreeSelect : public LLOctreeCull { public: @@ -1747,6 +1845,25 @@ void LLSpatialPartition::resetVertexBuffers() dirty.traverse(mOctree); } +BOOL LLSpatialPartition::isOcclusionEnabled() +{ + return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2; +} + +BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) +{ + LLOctreeCullVisExtents vis(&camera, visMin, visMax); + vis.traverse(mOctree); + return vis.mEmpty; +} + +BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) +{ + LLOctreeCullDetectVisible vis(&camera); + vis.traverse(mOctree); + return vis.mResult; +} + S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1772,6 +1889,12 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result LLOctreeSelect selecter(&camera, results); selecter.traverse(mOctree); } + else if (LLPipeline::sShadowRender) + { + LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLOctreeCullShadow culler(&camera); + culler.traverse(mOctree); + } else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); @@ -1790,14 +1913,14 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) { - const F32 vel = (LLViewerCamera::getInstance()->getVelocityStat()->getCurrent()+0.2f); + const F32 vel = SG_OCCLUSION_FUDGE*2.f; LLVector3 c = group->mBounds[0]; - LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel); + LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel); - if (r.magVecSquared() > 1024.0*1024.0) + /*if (r.magVecSquared() > 1024.0*1024.0) { return TRUE; - } + }*/ LLVector3 e = camera->getOrigin(); @@ -1865,21 +1988,31 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) void pushBufferVerts(LLSpatialGroup* group, U32 mask) { - if (!group->mDrawMap.empty()) + if (group->mSpatialPartition->mRenderByGroup) { - LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); - LLRenderPass::applyModelMatrix(*params); - - pushBufferVerts(group->mVertexBuffer, mask); - - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + if (!group->mDrawMap.empty()) { - for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); + LLRenderPass::applyModelMatrix(*params); + + pushBufferVerts(group->mVertexBuffer, mask); + + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) { - pushBufferVerts(*j, mask); + for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k) + { + pushBufferVerts(*k, mask); + } + } } } } + else + { + drawBox(group->mBounds[0], group->mBounds[1]); + } } void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) @@ -2026,6 +2159,23 @@ void renderOctree(LLSpatialGroup* group) } drawBoxOutline(group->mBounds[0],group->mBounds[1]); + + + //draw bounding box for draw info + if (group->mSpatialPartition->mRenderByGroup) + { + gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f); + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* draw_info = *j; + LLVector3 center = (draw_info->mExtents[1] + draw_info->mExtents[0])*0.5f; + LLVector3 size = (draw_info->mExtents[1] - draw_info->mExtents[0])*0.5f; + drawBoxOutline(center, size); + } + } + } } // LLSpatialGroup::OctreeNode* node = group->mOctreeNode; @@ -2046,6 +2196,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) { LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); glColor4f(0, 0.5f, 0, 0.5f); + gGL.color4f(0, 0.5f, 0, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2055,6 +2206,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) if (render_objects) { glColor4f(0.f, 0.5f, 0.f,1.f); + gGL.color4f(0.f, 0.5f, 0.f, 1.f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2063,6 +2215,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) if (render_objects) { glColor4f(0.f, 0.75f, 0.f,0.5f); + gGL.color4f(0.f, 0.75f, 0.f, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } else if (camera && group->mOcclusionVerts) @@ -2071,60 +2224,63 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts); glColor4f(1.0f, 0.f, 0.f, 0.5f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor4f(1.0f, 1.f, 1.f, 1.0f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } } -void renderBoundingBox(LLDrawable* drawable) +void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { - if (drawable->isSpatialBridge()) - { - gGL.color4f(1,0.5f,0,1); - } - else if (drawable->getVOVolume()) + if (set_color) { - if (drawable->isRoot()) + if (drawable->isSpatialBridge()) { - gGL.color4f(1,1,0,1); + gGL.color4f(1,0.5f,0,1); } - else + else if (drawable->getVOVolume()) { - gGL.color4f(0,1,0,1); + if (drawable->isRoot()) + { + gGL.color4f(1,1,0,1); + } + else + { + gGL.color4f(0,1,0,1); + } } - } - else if (drawable->getVObj()) - { - switch (drawable->getVObj()->getPCode()) + else if (drawable->getVObj()) { - case LLViewerObject::LL_VO_SURFACE_PATCH: - gGL.color4f(0,1,1,1); - break; - case LLViewerObject::LL_VO_CLOUDS: - gGL.color4f(0.5f,0.5f,0.5f,1.0f); - break; - case LLViewerObject::LL_VO_PART_GROUP: + switch (drawable->getVObj()->getPCode()) + { + case LLViewerObject::LL_VO_SURFACE_PATCH: + gGL.color4f(0,1,1,1); + break; + case LLViewerObject::LL_VO_CLOUDS: + gGL.color4f(0.5f,0.5f,0.5f,1.0f); + break; + case LLViewerObject::LL_VO_PART_GROUP: case LLViewerObject::LL_VO_HUD_PART_GROUP: - gGL.color4f(0,0,1,1); - break; - case LLViewerObject::LL_VO_WATER: - gGL.color4f(0,0.5f,1,1); - break; - case LL_PCODE_LEGACY_TREE: - gGL.color4f(0,0.5f,0,1); - default: - gGL.color4f(1,0,1,1); - break; + gGL.color4f(0,0,1,1); + break; + case LLViewerObject::LL_VO_WATER: + gGL.color4f(0,0.5f,1,1); + break; + case LL_PCODE_LEGACY_TREE: + gGL.color4f(0,0.5f,0,1); + default: + gGL.color4f(1,0,1,1); + break; + } + } + else + { + gGL.color4f(1,0,0,1); } - } - else - { - gGL.color4f(1,0,0,1); } const LLVector3* ext; @@ -2156,7 +2312,8 @@ void renderBoundingBox(LLDrawable* drawable) if (vobj && vobj->onActiveList()) { gGL.flush(); - glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); + glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); + //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); stop_glerror(); drawBoxOutline(pos,size); gGL.flush(); @@ -2379,8 +2536,7 @@ public: } //render visibility wireframe - if (group->mSpatialPartition->mRenderByGroup && - gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { gGL.flush(); glPushMatrix(); @@ -2456,6 +2612,51 @@ public: } }; +class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable> +{ +public: + LLCamera* mCamera; + LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const LLSpatialGroup::OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + if (!mCamera || mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + } + } + + virtual void visit(const LLSpatialGroup::OctreeNode* branch) + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + + if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + { + return; + } + + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + { + LLDrawable* drawable = *i; + + renderBoundingBox(drawable, FALSE); + } + } +}; + +void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) +{ + LLOctreePushBBoxVerts pusher(camera); + pusher.traverse(mOctree); +} + void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | @@ -2661,9 +2862,22 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mParticle(particle), mPartSize(part_size), mVSize(0.f), - mGroup(NULL) + mGroup(NULL), + mFace(NULL), + mDistance(0.f) { mDebugColor = (rand() << 16) + rand(); + if (mStart >= mVertexBuffer->getRequestedVerts() || + mEnd >= mVertexBuffer->getRequestedVerts()) + { + llerrs << "Invalid draw info vertex range." << llendl; + } + + if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() || + mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices()) + { + llerrs << "Invalid draw info index range." << llendl; + } } LLDrawInfo::~LLDrawInfo() @@ -2672,6 +2886,11 @@ LLDrawInfo::~LLDrawInfo() { llerrs << "LLDrawInfo deleted illegally!" << llendl; } + + if (mFace) + { + mFace->setDrawInfo(NULL); + } } LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 2f0d80414d..4d67b374c8 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -42,6 +42,7 @@ #include "llgltypes.h" #include "llcubemap.h" #include "lldrawpool.h" +#include "llface.h" #include <queue> @@ -55,6 +56,9 @@ class LLSpatialGroup; S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); +// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera +U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center); + class LLDrawInfo : public LLRefCount { protected: @@ -82,6 +86,9 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; + LLFace* mFace; //associated face + F32 mDistance; + LLVector3 mExtents[2]; struct CompareTexture { @@ -101,6 +108,16 @@ public: } }; + struct CompareVertexBuffer + { //sort by texture + bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) + { + // sort by pointer, sort NULL down to the end + return lhs.get() != rhs.get() + && (lhs.isNull() || (rhs.notNull() && lhs->mVertexBuffer.get() > rhs->mVertexBuffer.get())); + } + }; + struct CompareTexturePtrMatrix { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) @@ -121,6 +138,16 @@ public: && (lhs.isNull() || (rhs.notNull() && lhs->mBump > rhs->mBump)); } }; + + struct CompareDistanceGreater + { + bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) + { + // sort by mBump value, sort NULL down to the end + return lhs.get() != rhs.get() + && (lhs.isNull() || (rhs.notNull() && lhs->mDistance > rhs->mDistance)); + } + }; }; class LLSpatialGroup : public LLOctreeListener<LLDrawable> @@ -136,7 +163,8 @@ public: typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_map_t; + typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; + typedef std::map<U32, buffer_texture_map_t> buffer_map_t; typedef LLOctreeListener<LLDrawable> BaseType; typedef LLOctreeListener<LLDrawable> OctreeListener; @@ -226,6 +254,7 @@ public: BOOL needsUpdate(); BOOL changeLOD(); void rebuildGeom(); + void rebuildMesh(); void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } @@ -286,8 +315,10 @@ public: std::vector<LLFace*> mFaceList; virtual ~LLGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group) = 0; + virtual void rebuildMesh(LLSpatialGroup* group) = 0; virtual void getGeometry(LLSpatialGroup* group) = 0; virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count); + virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; @@ -320,7 +351,9 @@ public: virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); virtual void rebuildGeom(LLSpatialGroup* group); + virtual void rebuildMesh(LLSpatialGroup* group); + BOOL visibleObjectsInFrustum(LLCamera& camera); S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); @@ -329,9 +362,12 @@ public: virtual BOOL isBridge() { return asBridge() != NULL; } void renderDebug(); + void renderIntersectingBBoxes(LLCamera* camera); void restoreGL(); void resetVertexBuffers(); - + BOOL isOcclusionEnabled(); + BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax); + public: LLSpatialGroup::OctreeNode* mOctree; BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed @@ -445,6 +481,7 @@ private: drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; }; + //spatial partition for water (implemented in LLVOWater.cpp) class LLWaterPartition : public LLSpatialPartition { @@ -511,8 +548,11 @@ class LLVolumeGeometryManager: public LLGeometryManager public: virtual ~LLVolumeGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group); + virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); + void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); + }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) @@ -522,6 +562,7 @@ public: LLVolumePartition(); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; @@ -532,6 +573,7 @@ public: LLVolumeBridge(LLDrawable* drawable); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp index a819903d80..893ed22297 100644 --- a/indra/newview/llsprite.cpp +++ b/indra/newview/llsprite.cpp @@ -195,7 +195,7 @@ void LLSprite::updateFace(LLFace &face) if (face.mVertexBuffer.isNull()) { face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD, + LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); face.mVertexBuffer->allocateBuffer(4, 12, TRUE); face.setGeomIndex(0); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b4f8f6b71e..f6e3b14ddb 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -737,8 +737,6 @@ bool idle_startup() LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL; gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - // Push our window frontmost - gViewerWindow->getWindow()->show(); timeout_count = 0; @@ -794,6 +792,10 @@ bool idle_startup() gLoginMenuBarView->setVisible( TRUE ); gLoginMenuBarView->setEnabled( TRUE ); + // Push our window frontmost + gViewerWindow->getWindow()->show(); + display_startup(); + // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. #ifdef _WIN32 @@ -1800,7 +1802,13 @@ bool idle_startup() { LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; // Initialize all of the viewer object classes for the first time (doing things like texture fetches. + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + gSky.init(initial_sun_direction); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); } LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; @@ -2372,8 +2380,14 @@ bool idle_startup() { update_texture_fetch(); set_startup_status(0.60f + 0.30f * timeout_frac, - "Loading world...", + LLTrans::getString("LoginPrecaching"), gAgent.mMOTD); + display_startup(); + if (!LLViewerShaderMgr::sInitialized) + { + LLViewerShaderMgr::sInitialized = TRUE; + LLViewerShaderMgr::instance()->setShaders(); + } } return TRUE; diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index dcb8f6d5b1..a27f0e2254 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -253,7 +253,7 @@ void LLSurface::createSTexture() mSTexturep = new LLViewerImage(raw, FALSE); mSTexturep->dontDiscard(); gGL.getTexUnit(0)->bind(mSTexturep.get()); - mSTexturep->setClamp(TRUE, TRUE); + mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mSTexturep); } } @@ -278,7 +278,7 @@ void LLSurface::createWaterTexture() mWaterTexturep = new LLViewerImage(raw, FALSE); mWaterTexturep->dontDiscard(); gGL.getTexUnit(0)->bind(mWaterTexturep.get()); - mWaterTexturep->setClamp(TRUE, TRUE); + mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mWaterTexturep); } } @@ -299,7 +299,7 @@ void LLSurface::initTextures() { createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); - gPipeline.addObject(mWaterObjp); + gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 59231b3d69..5fac5fd1e4 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -128,7 +128,7 @@ void LLSurfacePatch::setSurface(LLSurface *surfacep) mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion()); mVObjp->setPatch(this); mVObjp->setPositionRegion(mCenterRegion); - gPipeline.addObject(mVObjp); + gPipeline.createObject(mVObjp); } } diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 709fcd166b..6a7ba7b7f4 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -57,10 +57,6 @@ //#include "../tools/imdebug/imdebug.h" - -// SJB: We really always want to use the GL cache; -// let GL page textures in and out of video RAM instead of trying to do so by hand. - // static S32 LLTexLayerSetBuffer::sGLByteCount = 0; S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; @@ -151,10 +147,9 @@ void LLTexLayerSetBuffer::createBumpTexture() gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL); stop_glerror(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1375,15 +1370,14 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) { LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0); - BOOL old_clamps = image_gl->getClampS(); - BOOL old_clampt = image_gl->getClampT(); + LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); - image_gl->setClamp(old_clamps, old_clampt); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -1575,14 +1569,14 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 { LLGLSNoAlphaTest gls_no_alpha_test; - BOOL old_clamps = image_gl->getClampS(); - BOOL old_clampt = image_gl->getClampT(); + LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); + gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); - image_gl->setClamp(old_clamps, old_clampt); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -1719,21 +1713,20 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i internal_format = GL_ALPHA8; } - GLuint name = 0; - glGenTextures(1, &name ); + U32 name = 0; + LLImageGL::generateTextures(1, &name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, in_width, in_height, - 0, format, GL_UNSIGNED_BYTE, in_data ); + format, GL_UNSIGNED_BYTE, in_data ); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -1741,7 +1734,7 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glDeleteTextures(1, &name ); + LLImageGL::deleteTextures(1, &name ); stop_glerror(); } else @@ -2016,7 +2009,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) if( !mCachedProcessedImageGL || (mCachedProcessedImageGL->getWidth() != image_tga_width) || (mCachedProcessedImageGL->getHeight() != image_tga_height) || - (weight_changed )) + (weight_changed) ) { // llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; mCachedEffectiveWeight = effective_weight; @@ -2028,7 +2021,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) // We now have something in one of our caches LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE; - mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } @@ -2047,9 +2039,8 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) { mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); mNeedsCreateTexture = FALSE; - gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); - mCachedProcessedImageGL->setClamp(TRUE, TRUE); + mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); } LLGLSNoAlphaTest gls_no_alpha_test; @@ -2504,7 +2495,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i image_gl->createGLTexture(0, image_raw); gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); mStaticImageListGL [ namekey ] = image_gl; mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 97b55a3d06..5ab8c91f72 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -533,7 +533,6 @@ public: S32 mTGABytes; }; - // Used by LLTexLayerSetBuffer for a callback. class LLBakedUploadData { diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d3f1744f2f..69723f622a 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -175,7 +175,7 @@ private: bool LLTextureCacheLocalFileWorker::doRead() { - S32 local_size = ll_apr_file_size(mFileName, mCache->getFileAPRPool()); + S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool()); if (local_size > 0 && mFileName.size() > 4) { @@ -248,8 +248,9 @@ bool LLTextureCacheLocalFileWorker::doRead() mDataSize = local_size; } mReadData = new U8[mDataSize]; - S32 bytes_read = ll_apr_file_read_ex(mFileName, mCache->getFileAPRPool(), - mReadData, mOffset, mDataSize); + + S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); + if (bytes_read != mDataSize) { // llwarns << "Error reading file from local cache: " << mFileName @@ -317,11 +318,11 @@ bool LLTextureCacheRemoteWorker::doRead() { std::string filename = mCache->getLocalFileName(mID); local_filename = filename + ".j2c"; - local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size == 0) { local_filename = filename + ".tga"; - local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { mImageFormat = IMG_CODEC_TGA; @@ -389,8 +390,8 @@ bool LLTextureCacheRemoteWorker::doRead() mDataSize = local_size; } mReadData = new U8[mDataSize]; - S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(), - mReadData, mOffset, mDataSize); + S32 bytes_read = LLAPRFile::readEx(local_filename, + mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); if (bytes_read != mDataSize) { // llwarns << "Error reading file from local cache: " << local_filename @@ -483,8 +484,8 @@ bool LLTextureCacheRemoteWorker::doRead() S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; mReadData = new U8[size]; - S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), - mReadData, offset, size); + S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, + mReadData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_read != size) { // llwarns << "LLTextureCacheWorker: " << mID @@ -510,7 +511,7 @@ bool LLTextureCacheRemoteWorker::doRead() if (mFileHandle == LLLFSThread::nullHandle()) { std::string filename = mCache->getTextureFileName(mID); - S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); if (filesize > mOffset) { S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; @@ -569,7 +570,7 @@ bool LLTextureCacheRemoteWorker::doRead() } #else std::string filename = mCache->getTextureFileName(mID); - S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); S32 bytes_read = 0; if (filesize > mOffset) { @@ -589,9 +590,10 @@ bool LLTextureCacheRemoteWorker::doRead() delete[] mReadData; } mReadData = data; - bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(), + bytes_read = LLAPRFile::readEx(filename, mReadData + data_offset, - file_offset, file_size); + file_offset, file_size, + mCache->getLocalAPRFilePool()); if (bytes_read != file_size) { // llwarns << "LLTextureCacheWorker: " << mID @@ -694,8 +696,7 @@ bool LLTextureCacheRemoteWorker::doWrite() llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), - mWriteData, offset, size); + S32 bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { @@ -770,9 +771,11 @@ bool LLTextureCacheRemoteWorker::doWrite() if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) { std::string filename = mCache->getTextureFileName(mID); - bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(), + + bytes_written = LLAPRFile::writeEx(filename, mWriteData + data_offset, - file_offset, file_size); + file_offset, file_size, + mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { mDataSize = -1; // failed @@ -793,13 +796,14 @@ bool LLTextureCacheRemoteWorker::doWrite() //virtual bool LLTextureCacheWorker::doWork(S32 param) { +// *TODO reenable disabled apr_pool usage disabled due to maint-render-9 merge breakage -brad //allocate a new local apr_pool - LLAPRPool pool ; +// LLAPRPool pool ; //save the current mFileAPRPool to avoid breaking anything. - apr_pool_t* old_pool = mCache->getFileAPRPool() ; +// apr_pool_t* old_pool = mCache->getFileAPRPool() ; //make mFileAPRPool to point to the local one - mCache->setFileAPRPool(pool.getAPRPool()) ; +// mCache->setFileAPRPool(pool.getAPRPool()) ; bool res = false; if (param == 0) // read @@ -816,7 +820,7 @@ bool LLTextureCacheWorker::doWork(S32 param) } //set mFileAPRPool back, the local one will be released automatically. - mCache->setFileAPRPool(old_pool) ; +// mCache->setFileAPRPool(old_pool) ; return res; } @@ -880,20 +884,17 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted) LLTextureCache::LLTextureCache(bool threaded) : LLWorkerThread("TextureCache", threaded), - mWorkersMutex(getAPRPool()), - mHeaderMutex(getAPRPool()), - mListMutex(getAPRPool()), - mFileAPRPool(NULL), + mWorkersMutex(NULL), + mHeaderMutex(NULL), + mListMutex(NULL), mReadOnly(FALSE), mTexturesSizeTotal(0), mDoPurge(FALSE) { - apr_pool_create(&mFileAPRPool, NULL); } LLTextureCache::~LLTextureCache() { - apr_pool_destroy(mFileAPRPool); } ////////////////////////////////////////////////////////////////////////////// @@ -969,8 +970,10 @@ bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) { llassert_always(bodysize > 0); Entry* entry = new Entry(id, bodysize, time(NULL)); - ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(), - (U8*)entry, -1, 1*sizeof(Entry)); + + LLAPRFile::writeEx(mTexturesDirEntriesFileName, + (U8*)entry, -1, 1*sizeof(Entry), + getLocalAPRFilePool()); delete entry; if (iter != mTexturesSizeMap.end()) { @@ -1018,8 +1021,8 @@ void LLTextureCache::purgeCache(ELLPath location) { setDirNames(location); - ll_apr_file_remove(mHeaderEntriesFileName, NULL); - ll_apr_file_remove(mHeaderDataFileName, NULL); + LLAPRFile::remove(mHeaderEntriesFileName, getLocalAPRFilePool()); + LLAPRFile::remove(mHeaderDataFileName, getLocalAPRFilePool()); } purgeAllTextures(true); } @@ -1081,15 +1084,16 @@ struct lru_data }; // Called from either the main thread or the worker thread -void LLTextureCache::readHeaderCache(apr_pool_t* poolp) +void LLTextureCache::readHeaderCache() { LLMutexLock lock(&mHeaderMutex); mHeaderEntriesInfo.mVersion = 0.f; mHeaderEntriesInfo.mEntries = 0; - if (ll_apr_file_exists(mHeaderEntriesFileName, poolp)) + if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) { - ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) { @@ -1097,8 +1101,10 @@ void LLTextureCache::readHeaderCache(apr_pool_t* poolp) { // Info with 0 entries mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; - ll_apr_file_write_ex(mHeaderEntriesFileName, poolp, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } } else @@ -1107,8 +1113,11 @@ void LLTextureCache::readHeaderCache(apr_pool_t* poolp) if (num_entries) { Entry* entries = new Entry[num_entries]; - ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, - (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry)); + { + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry), + getLocalAPRFilePool()); + } typedef std::set<lru_data*, lru_data::Compare> lru_set_t; lru_set_t lru; for (S32 i=0; i<num_entries; i++) @@ -1153,7 +1162,7 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) LLFile::rmdir(dirname); } } - ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); + LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); if (purge_directories) { LLFile::rmdir(mTexturesDirName); @@ -1174,7 +1183,7 @@ void LLTextureCache::purgeTextures(bool validate) LLMutexLock lock(&mHeaderMutex); - S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL); + S32 filesize = LLAPRFile::size(mTexturesDirEntriesFileName, getLocalAPRFilePool()); S32 num_entries = filesize / sizeof(Entry); if (num_entries * (S32)sizeof(Entry) != filesize) { @@ -1188,8 +1197,9 @@ void LLTextureCache::purgeTextures(bool validate) } Entry* entries = new Entry[num_entries]; - S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL, - (U8*)entries, 0, num_entries*sizeof(Entry)); + S32 bytes_read = LLAPRFile::readEx(mTexturesDirEntriesFileName, + (U8*)entries, 0, num_entries*sizeof(Entry), + getLocalAPRFilePool()); if (bytes_read != filesize) { LL_WARNS("TextureCache") << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; @@ -1248,7 +1258,7 @@ void LLTextureCache::purgeTextures(bool validate) if (uuididx == validate_idx) { LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mSize << LL_ENDL; - S32 bodysize = ll_apr_file_size(filename, NULL); + S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool()); if (bodysize != entries[idx].mSize) { LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize @@ -1261,7 +1271,7 @@ void LLTextureCache::purgeTextures(bool validate) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; - ll_apr_file_remove(filename, NULL); + LLAPRFile::remove(filename, getLocalAPRFilePool()); total_size -= entries[idx].mSize; entries[idx].mSize = 0; } @@ -1278,9 +1288,10 @@ void LLTextureCache::purgeTextures(bool validate) LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL; - ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); - ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL, - (U8*)&entries[0], 0, num_entries*sizeof(Entry)); + LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); + LLAPRFile::writeEx(mTexturesDirEntriesFileName, + (U8*)&entries[0], 0, num_entries*sizeof(Entry), + getLocalAPRFilePool()); mTexturesSizeTotal = 0; mTexturesSizeMap.clear(); @@ -1351,8 +1362,9 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image idx = mHeaderEntriesInfo.mEntries++; mHeaderIDMap[id] = idx; // Update Info - ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } else if (!mLRU.empty()) { @@ -1377,8 +1389,9 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image llassert_always(imagesize && *imagesize > 0); Entry* entry = new Entry(id, *imagesize, time(NULL)); S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)entry, offset, sizeof(Entry)); + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)entry, offset, sizeof(Entry), + getLocalAPRFilePool()); delete entry; } else if (imagesize) @@ -1386,15 +1399,17 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image // Get the image size Entry entry; S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)&entry, offset, sizeof(Entry)); + + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)&entry, offset, sizeof(Entry), + getLocalAPRFilePool()); *imagesize = entry.mSize; } } } if (retry) { - readHeaderCache(getFileAPRPool()); // updates the lru + readHeaderCache(); // updates the lru llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion } @@ -1468,7 +1483,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio { // NOTE: This may cause an occasional hiccup, // but it really needs to be done on the control thread - // (i.e. here) + // (i.e. here) purgeTextures(false); mDoPurge = FALSE; } @@ -1540,8 +1555,10 @@ bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) { Entry* entry = new Entry(id, -1, time(NULL)); S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_write_ex(mHeaderEntriesFileName, NULL, - (U8*)entry, offset, sizeof(Entry)); + + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)entry, offset, sizeof(Entry), + getLocalAPRFilePool()); delete entry; mLRU[idx] = id; mHeaderIDMap.erase(id); @@ -1558,7 +1575,7 @@ void LLTextureCache::removeFromCache(const LLUUID& id) if (!mReadOnly) { removeHeaderCacheEntry(id); - ll_apr_file_remove(getTextureFileName(id), NULL); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); } } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index fa42b5d58e..68b1458e9a 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -109,18 +109,17 @@ public: protected: // Accessed by LLTextureCacheWorker - apr_pool_t* getFileAPRPool() { return mFileAPRPool; } bool appendToTextureEntryList(const LLUUID& id, S32 size); std::string getLocalFileName(const LLUUID& id); std::string getTextureFileName(const LLUUID& id); void addCompleted(Responder* responder, bool success); protected: - void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } + //void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } private: void setDirNames(ELLPath location); - void readHeaderCache(apr_pool_t* poolp = NULL); + void readHeaderCache(); void purgeAllTextures(bool purge_directories); void purgeTextures(bool validate); S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); @@ -133,7 +132,6 @@ private: LLMutex mWorkersMutex; LLMutex mHeaderMutex; LLMutex mListMutex; - apr_pool_t* mFileAPRPool; typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; handle_map_t mReaders; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 3fcb9c50be..e9dd7921cd 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -416,7 +416,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mInLocalCache(FALSE), mRetryAttempt(0), mActiveCount(0), - mWorkMutex(fetcher->getWorkerAPRPool()), + mWorkMutex(NULL), mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), @@ -435,7 +435,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, LLTextureFetchWorker::~LLTextureFetchWorker() { - llassert_always(LLWorkerClass::sDeleteLock) ; // llinfos << "Destroy: " << mID // << " Decoded=" << mDecodedDiscard // << " Requested=" << mRequestedDiscard diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 5a2230c34c..f54830f39f 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -83,6 +83,21 @@ glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloa 0, 0, -1.f, 0); } +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) +{ + LLVector3 f = center-eye; + f.normVec(); + up.normVec(); + LLVector3 s = f % up; + LLVector3 u = s % f; + + return glh::matrix4f(s[0], s[1], s[2], 0, + u[0], u[1], u[2], 0, + -f[0], -f[1], -f[2], 0, + 0, 0, 0, 1); + +} + LLViewerCamera::LLViewerCamera() : LLCamera() { calcProjection(getFar()); @@ -183,7 +198,7 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const // height. //static -void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip) +void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks) { GLint* viewport = (GLint*) gGLViewport; GLdouble* model = gGLModelView; @@ -192,7 +207,27 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli LLVector3 frust[8]; - if (zflip) + if (no_hacks) + { + gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); + + gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); + } + else if (zflip) { gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); @@ -232,7 +267,7 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli if (ortho) { - LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0); + LLVector3 far_shift = camera.getAtAxis()*camera.getFar()*2.f; for (U32 i = 0; i < 4; i++) { frust[i+4] = frust[i] + far_shift; @@ -369,13 +404,13 @@ void LLViewerCamera::setPerspective(BOOL for_selection, updateFrustumPlanes(*this); - if (gSavedSettings.getBOOL("CameraOffset")) + /*if (gSavedSettings.getBOOL("CameraOffset")) { glMatrixMode(GL_PROJECTION); glTranslatef(0,0,-50); glRotatef(20.0,1,0,0); glMatrixMode(GL_MODELVIEW); - } + }*/ } diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 5e21fda09d..6a0c42beec 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -60,7 +60,7 @@ public: const LLVector3 &up_direction, const LLVector3 &point_of_interest); - static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE); + static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE, BOOL no_hacks = FALSE); void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0); const LLMatrix4 &getProjection() const; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 16a830a110..1a40da9c1f 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -355,19 +355,24 @@ static bool handleRenderUseFBOChanged(const LLSD& newvalue) { gPipeline.releaseGLBuffers(); gPipeline.createGLBuffers(); + if (LLPipeline::sRenderDeferred && LLRenderTarget::sUseFBO) + { + LLViewerShaderMgr::instance()->setShaders(); + } } return true; } static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) { - LLVOAvatar::sUseImpostors = FALSE; //newvalue.asBoolean(); + LLVOAvatar::sUseImpostors = newvalue.asBoolean(); return true; } static bool handleRenderDebugGLChanged(const LLSD& newvalue) { gDebugGL = newvalue.asBoolean(); + gGL.clearErrors(); return true; } @@ -437,6 +442,7 @@ void settings_setup_listeners() gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _1)); gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _1)); gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _1)); + gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); @@ -462,6 +468,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _1)); + gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderUseImpostors")->getSignal()->connect(boost::bind(&handleRenderUseImpostorsChanged, _1)); gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _1)); gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 9099ddc896..54c6f0a71f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -108,7 +108,7 @@ LLFrameTimer gRecentMemoryTime; // Rendering stuff void pre_show_depth_buffer(); void post_show_depth_buffer(); -void render_ui(); +void render_ui(F32 zoom_factor = 1.f, int subfield = 0); void render_hud_attachments(); void render_ui_3d(); void render_ui_2d(); @@ -161,9 +161,9 @@ void display_startup() glClear(GL_DEPTH_BUFFER_BIT); } - void display_update_camera() { + llpushcallstacks ; // TODO: cut draw distance down if customizing avatar? // TODO: cut draw distance on per-parcel basis? @@ -500,12 +500,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (LLDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); } } gViewerWindow->setupViewport(); - + + gPipeline.resetFrameStats(); // Reset per-frame statistics. if (!gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); @@ -528,6 +529,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time + gPipeline.createObjects(max_geom_update_time); gPipeline.updateGeom(max_geom_update_time); stop_glerror(); @@ -557,10 +559,17 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; + + if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) + { //force occlusion on for all render types if doing deferred render + LLPipeline::sUseOcclusion = 3; + } + LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); - + LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); + S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state @@ -568,18 +577,25 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gDepthDirty = FALSE; + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + static LLCullResult result; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + BOOL to_texture = !for_snapshot && gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); - // now do the swap buffer (just before rendering to framebuffer) - { //swap and flush state from previous frame + { { LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(0.016); @@ -593,14 +609,29 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gGL.setColorMask(true, true); glClearColor(0,0,0,0); - + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + if (!for_snapshot) { + if (gFrameCount > 1) + { //for some reason, ATI 4800 series will error out if you + //try to generate a shadow before the first frame is through + gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); + } + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + glh::matrix4f proj = glh_get_current_projection(); glh::matrix4f mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; LLVOAvatar::updateImpostors(); + glh_set_current_projection(proj); glh_set_current_modelview(mod); glMatrixMode(GL_PROJECTION); @@ -608,8 +639,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) glMatrixMode(GL_MODELVIEW); glLoadMatrixf(mod.m); gViewerWindow->setupViewport(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!for_snapshot) @@ -626,6 +662,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // // Doing this here gives hardware occlusion queries extra time to complete LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); + LLError::LLCallStacks::clear() ; + llpushcallstacks ; gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { @@ -640,7 +678,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gImageList.updateImages(max_image_decode_time); stop_glerror(); } - + llpushcallstacks ; /////////////////////////////////// // // StateSort @@ -722,11 +760,25 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // glPopMatrix(); //} + LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; + LLPipeline::updateRenderDeferred(); + + stop_glerror(); + if (to_texture) { gGL.setColorMask(true, true); - gPipeline.mScreen.bindTarget(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.mDeferredScreen.bindTarget(); + gPipeline.mDeferredScreen.clear(); + } + else + { + gPipeline.mScreen.bindTarget(); + gPipeline.mScreen.clear(); + } + gGL.setColorMask(true, false); } @@ -737,9 +789,15 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { gGL.setColorMask(true, false); - LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; - gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); - LLPipeline::sUnderWaterRender = FALSE; + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); + } + else + { + gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); + } + gGL.setColorMask(true, true); //store this frame's modelview matrix for use @@ -755,8 +813,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (to_texture) { - - gPipeline.mScreen.flush(); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.mDeferredScreen.flush(); + } + else + { + gPipeline.mScreen.flush(); + } } /// We copy the frame buffer straight into a texture here, @@ -765,8 +829,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) /// grasp of their full display stack just yet. // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.renderDeferredLighting(); + } + + LLPipeline::sUnderWaterRender = FALSE; + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); - if (!for_snapshot) { gFrameStats.start(LLFrameStats::RENDER_UI); @@ -818,7 +888,10 @@ void render_hud_attachments() //only render hud objects U32 mask = gPipeline.getRenderTypeMask(); gPipeline.setRenderTypeMask(0); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } BOOL has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); if (has_ui) @@ -829,16 +902,18 @@ void render_hud_attachments() S32 use_occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = 0; LLPipeline::sDisableShaders = TRUE; - + //cull, sort, and render hud objects static LLCullResult result; LLSpatialGroup::sNoDelete = TRUE; + gPipeline.updateCull(hud_cam, result); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); gPipeline.stateSort(hud_cam, result); @@ -935,7 +1010,7 @@ BOOL setup_hud_matrices(const LLRect& screen_region) } -void render_ui() +void render_ui(F32 zoom_factor, int subfield) { LLGLState::checkStates(); @@ -950,7 +1025,7 @@ void render_ui() if (to_texture) { - gPipeline.renderBloom(gSnapshot); + gPipeline.renderBloom(gSnapshot, zoom_factor, subfield); } render_hud_elements(); diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 5a21ac68d3..89490e08bf 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -244,6 +244,8 @@ void LLViewerJoint::setValid( BOOL valid, BOOL recursive ) //-------------------------------------------------------------------- U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass ) { + stop_glerror(); + U32 triangle_count = 0; //---------------------------------------------------------------- @@ -261,6 +263,10 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass ) { triangle_count += drawShape( pixelArea, first_pass ); } + else if (LLPipeline::sShadowRender) + { + triangle_count += drawShape(pixelArea, first_pass); + } else if ( isTransparent() && !LLPipeline::sReflectionRender) { // Hair and Skirt diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 0d5c19570a..4cacc5c97b 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -73,7 +73,7 @@ extern BOOL gRenderForSelect; static LLPointer<LLVertexBuffer> sRenderBuffer = NULL; static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; //----------------------------------------------------------------------------- @@ -459,14 +459,13 @@ void LLViewerJointMesh::uploadJointMatrices() for (S32 axis = 0; axis < NUM_AXES; axis++) { F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis]; - //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector); U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num; memcpy(mat+offset*4, vector, sizeof(GLfloat)*4); - //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+6, (GLfloat*)vector); - //cgGLSetParameterArray4f(gPipeline.mAvatarMatrix, offset, 1, vector); } } + stop_glerror(); glUniform4fvARB(gAvatarMatrixParam, 45, mat); + stop_glerror(); } } @@ -536,6 +535,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive + LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); @@ -565,11 +565,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) else if ( mTexture.notNull() ) { - if (!mTexture->getClampS() || !mTexture->getClampT()) - { - gGL.getTexUnit(0)->bind(mTexture.get()); - mTexture->overrideClamp (TRUE, TRUE); - } + old_mode = mTexture->getAddressMode(); + gGL.getTexUnit(0)->bind(mTexture.get()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { @@ -628,7 +626,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) if (mTexture.notNull()) { gGL.getTexUnit(0)->bind(mTexture.get()); - mTexture->restoreClamp(); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); } return triangle_count; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 417117bdf1..de16bbf8a1 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1047,6 +1047,7 @@ void init_debug_ui_menu(LLMenuGL* menu) menu->appendSeparator(); menu->append(new LLMenuItemCheckGL("Show Time", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowTime")); menu->append(new LLMenuItemCheckGL("Show Render Info", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderInfo")); + menu->append(new LLMenuItemCheckGL("Show Matrices", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderMatrices")); menu->append(new LLMenuItemCheckGL("Show Color Under Cursor", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowColor")); menu->createJumpKeys(); @@ -1184,6 +1185,9 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("Octree", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCTREE)); + sub_menu->append(new LLMenuItemCheckGL("Shadow Frusta", &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)); sub_menu->append(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCCLUSION)); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index a6dede1e38..2925916e2a 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -788,8 +788,9 @@ void upload_new_resource(const std::string& src_filename, std::string name, uuid = tid.makeAssetID(gAgent.getSecureSessionID()); // copy this file into the vfs for upload S32 file_size; - apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); - if (fp) + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + if (infile.getFileHandle()) { LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); @@ -797,11 +798,10 @@ void upload_new_resource(const std::string& src_filename, std::string name, const S32 buf_size = 65536; U8 copy_buf[buf_size]; - while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) + while ((file_size = infile.read(copy_buf, buf_size))) { file.write(copy_buf, file_size); } - apr_file_close(fp); } else { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index bd433c0c73..e4ddbd42dd 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1406,7 +1406,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Setup object text - if (!mText) + if (!mText && (value & 0x4)) { mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); mText->setFont(LLFontGL::sSansSerif); @@ -1428,7 +1428,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(TEXTURE); } - else + else if(mText.notNull()) { mText->markDead(); mText = NULL; @@ -3730,11 +3730,11 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) else if (color != tep->getColor()) { retval = LLPrimitive::setTEColor(te, color); - setChanged(TEXTURE); + //setChanged(TEXTURE); if (mDrawable.notNull() && retval) { // These should only happen on updates which are not the initial update. - gPipeline.markTextured(mDrawable); + dirtyMesh(); } } return retval; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 45ab630e35..16a3b98d12 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -131,6 +131,8 @@ protected: public: typedef std::list<LLPointer<LLViewerObject> > child_list_t; + typedef std::list<LLPointer<LLViewerObject> > vobj_list_t; + typedef const child_list_t const_child_list_t; LLViewerObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp, BOOL is_global = FALSE); diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index b66f2c83be..866c2a91eb 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -74,8 +74,8 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ mTexture->createGLTexture(0, mImageRaw); gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(mTexture); - mTexture->setClamp(TRUE, TRUE); - mTexture->setMipFilterNearest(TRUE); + mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); + mTexture->setFilteringOption(LLTexUnit::TFO_POINT); // // Initialize the GL texture with empty data. diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index d513c021ee..b74f9e9f2c 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -152,7 +152,9 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo mVOPartGroupp->setPositionAgent(getCenterAgent()); F32 scale = box_side * 0.5f; mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); - gPipeline.addObject(mVOPartGroupp); + + //gPipeline.addObject(mVOPartGroupp); + gPipeline.createObject(mVOPartGroupp); LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index dfd97b8e65..38c75a84d1 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -102,7 +102,7 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) mPosAgent = mSourceObjectp->getPositionAgent(); mImagep = gImageList.getImageFromFile("pixiesmall.j2c"); gGL.getTexUnit(0)->bind(mImagep.get()); - mImagep->setClamp(TRUE, TRUE); + mImagep->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 1c025b42c9..b5bd2f93af 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,6 +63,8 @@ using std::pair; using std::make_pair; using std::string; +BOOL LLViewerShaderMgr::sInitialized = FALSE; + LLVector4 gShinyOrigin; //object shaders @@ -101,7 +103,23 @@ LLGLSLShader gPostColorFilterProgram; LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders +LLGLSLShader gDeferredImpostorProgram; +LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredBumpProgram; +LLGLSLShader gDeferredTerrainProgram; +LLGLSLShader gDeferredTreeProgram; +LLGLSLShader gDeferredAvatarProgram; +LLGLSLShader gDeferredAvatarAlphaProgram; +LLGLSLShader gDeferredLightProgram; +LLGLSLShader gDeferredMultiLightProgram; +LLGLSLShader gDeferredSunProgram; +LLGLSLShader gDeferredBlurLightProgram; +LLGLSLShader gDeferredSoftenProgram; +LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredAvatarShadowProgram; +LLGLSLShader gDeferredAlphaProgram; +LLGLSLShader gDeferredFullbrightProgram; //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -126,6 +144,15 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gAvatarWaterProgram); mShaderList.push_back(&gObjectShinyWaterProgram); mShaderList.push_back(&gUnderWaterProgram); + mShaderList.push_back(&gDeferredSunProgram); + mShaderList.push_back(&gDeferredBlurLightProgram); + mShaderList.push_back(&gDeferredSoftenProgram); + mShaderList.push_back(&gDeferredLightProgram); + mShaderList.push_back(&gDeferredMultiLightProgram); + mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredFullbrightProgram); + mShaderList.push_back(&gDeferredWaterProgram); + mShaderList.push_back(&gDeferredAvatarAlphaProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() @@ -188,6 +215,18 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedUniforms.push_back("gamma"); mReservedUniforms.push_back("scene_light_strength"); + mReservedUniforms.push_back("depthMap"); + mReservedUniforms.push_back("shadowMap0"); + mReservedUniforms.push_back("shadowMap1"); + mReservedUniforms.push_back("shadowMap2"); + mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("normalMap"); + mReservedUniforms.push_back("positionMap"); + mReservedUniforms.push_back("diffuseRect"); + mReservedUniforms.push_back("specularRect"); + mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightMap"); + mWLUniforms.push_back("camPosLocal"); mTerrainUniforms.reserve(5); @@ -240,7 +279,7 @@ S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type) void LLViewerShaderMgr::setShaders() { - if (!gPipeline.mInitialized) + if (!gPipeline.mInitialized || !sInitialized) { return; } @@ -254,6 +293,7 @@ void LLViewerShaderMgr::setShaders() { LLPipeline::sWaterReflections = gGLManager.mHasCubeMap; LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); + LLPipeline::updateRenderDeferred(); } else { @@ -290,36 +330,16 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; - if (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")) + if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") + && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) { // user has disabled WindLight in their settings, downgrade // windlight shaders to stub versions. wl_class = 1; - - // if class one or less, turn off more shaders - // since higher end cards won't see any real gain - // from turning off most of the shaders, - // but class one would - // TODO: Make water on class one cards color things - // beneath it properly - if(LLFeatureManager::getInstance()->getGPUClass() < GPU_CLASS_2) - { - // use lesser water and other stuff - light_class = 2; - env_class = 0; - obj_class = 0; - effect_class = 1; - water_class = 1; - } } - if (gSavedSettings.getBOOL("RenderDeferred")) + if (LLPipeline::sRenderDeferred) { - light_class = 1; - env_class = 0; - obj_class = 0; - water_class = 1; - effect_class = 1; deferred_class = 1; } @@ -358,8 +378,7 @@ void LLViewerShaderMgr::setShaders() loadShadersWindLight(); loadShadersEffects(); loadShadersInterface(); - loadShadersDeferred(); - + // Load max avatar shaders to set the max level mVertexShaderLevel[SHADER_AVATAR] = 3; mMaxAvatarShaderLevel = 3; @@ -406,6 +425,11 @@ void LLViewerShaderMgr::setShaders() gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); loadShadersAvatar(); // unloads } + + if (!loadShadersDeferred()) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + } #endif } else @@ -511,6 +535,10 @@ BOOL LLViewerShaderMgr::loadBasicShaders() sum_lights_class = 1; } + // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. + S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); + sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); + // Load the Basic Vertex Shaders at the appropriate level. // (in order of shader function call depth for reference purposes, deepest level first) @@ -779,15 +807,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { if (mVertexShaderLevel[SHADER_DEFERRED] == 0) { + gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredBumpProgram.unload(); + gDeferredImpostorProgram.unload(); + gDeferredTerrainProgram.unload(); + gDeferredLightProgram.unload(); + gDeferredMultiLightProgram.unload(); + gDeferredSunProgram.unload(); + gDeferredBlurLightProgram.unload(); + gDeferredSoftenProgram.unload(); + gDeferredShadowProgram.unload(); + gDeferredAvatarShadowProgram.unload(); + gDeferredAvatarProgram.unload(); + gDeferredAvatarAlphaProgram.unload(); + gDeferredAlphaProgram.unload(); + gDeferredFullbrightProgram.unload(); + gDeferredWaterProgram.unload(); return FALSE; } + mVertexShaderLevel[SHADER_AVATAR] = 1; + BOOL success = TRUE; if (success) { - gDeferredDiffuseProgram.mName = "Deffered Diffuse Shader"; + gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -795,6 +841,187 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredBumpProgram.mName = "Deferred Bump Shader"; + gDeferredBumpProgram.mShaderFiles.clear(); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredBumpProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredTreeProgram.mName = "Deferred Tree Shader"; + gDeferredTreeProgram.mShaderFiles.clear(); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredTreeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; + gDeferredImpostorProgram.mShaderFiles.clear(); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredLightProgram.mName = "Deferred Light Shader"; + gDeferredLightProgram.mShaderFiles.clear(); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader"; + gDeferredMultiLightProgram.mShaderFiles.clear(); + gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredMultiLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSunProgram.mName = "Deferred Sun Shader"; + gDeferredSunProgram.mShaderFiles.clear(); + gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSunProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; + gDeferredBlurLightProgram.mShaderFiles.clear(); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredBlurLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; + gDeferredAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAlphaProgram.mFeatures.hasGamma = true; + gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredAlphaProgram.mFeatures.hasLighting = true; + gDeferredAlphaProgram.mShaderFiles.clear(); + gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAlphaProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader"; + gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightProgram.mFeatures.hasGamma = true; + gDeferredFullbrightProgram.mFeatures.hasTransport = true; + gDeferredFullbrightProgram.mFeatures.isFullbright = true; + gDeferredFullbrightProgram.mShaderFiles.clear(); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + // load water shader + gDeferredWaterProgram.mName = "Deferred Water Shader"; + gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredWaterProgram.mFeatures.hasGamma = true; + gDeferredWaterProgram.mFeatures.hasTransport = true; + gDeferredWaterProgram.mShaderFiles.clear(); + gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredWaterProgram.createShader(NULL, &mWaterUniforms); + } + + if (success) + { + gDeferredSoftenProgram.mName = "Deferred Soften Shader"; + gDeferredSoftenProgram.mShaderFiles.clear(); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSoftenProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredShadowProgram.mName = "Deferred Shadow Shader"; + gDeferredShadowProgram.mShaderFiles.clear(); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; + gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; + gDeferredAvatarShadowProgram.mShaderFiles.clear(); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarShadowProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + + if (success) + { + gTerrainProgram.mName = "Deferred Terrain Shader"; + gDeferredTerrainProgram.mShaderFiles.clear(); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredTerrainProgram.createShader(NULL, &mTerrainUniforms); + } + + if (success) + { + gDeferredAvatarProgram.mName = "Avatar Shader"; + gDeferredAvatarProgram.mFeatures.hasSkinning = true; + gDeferredAvatarProgram.mShaderFiles.clear(); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + + if (success) + { + gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader"; + gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; + gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; + gDeferredAvatarAlphaProgram.mShaderFiles.clear(); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + return success; } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 4cad3a23a8..a743966d93 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -38,6 +38,8 @@ class LLViewerShaderMgr: public LLShaderMgr { public: + static BOOL sInitialized; + LLViewerShaderMgr(); /* virtual */ ~LLViewerShaderMgr(); @@ -109,6 +111,17 @@ public: CLOUD_SCALE, GAMMA, SCENE_LIGHT_STRENGTH, + DEFERRED_DEPTH, + DEFERRED_SHADOW0, + DEFERRED_SHADOW1, + DEFERRED_SHADOW2, + DEFERRED_SHADOW3, + DEFERRED_NORMAL, + DEFERRED_POSITION, + DEFERRED_DIFFUSE, + DEFERRED_SPECULAR, + DEFERRED_NOISE, + DEFERRED_LIGHT, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -305,7 +318,23 @@ extern LLGLSLShader gPostColorFilterProgram; extern LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders +extern LLGLSLShader gDeferredImpostorProgram; +extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredBumpProgram; +extern LLGLSLShader gDeferredTerrainProgram; +extern LLGLSLShader gDeferredTreeProgram; +extern LLGLSLShader gDeferredLightProgram; +extern LLGLSLShader gDeferredMultiLightProgram; +extern LLGLSLShader gDeferredSunProgram; +extern LLGLSLShader gDeferredBlurLightProgram; +extern LLGLSLShader gDeferredAvatarProgram; +extern LLGLSLShader gDeferredSoftenProgram; +extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredAvatarShadowProgram; +extern LLGLSLShader gDeferredAlphaProgram; +extern LLGLSLShader gDeferredFullbrightProgram; +extern LLGLSLShader gDeferredAvatarAlphaProgram; //current avatar shader parameter pointer extern GLint gAvatarMatrixParam; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 2af3854816..648fbd4714 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -351,7 +351,6 @@ void LLViewerStats::addToMessage(LLSD &body) const // Moving them here, but not merging them into LLViewerStats yet. void reset_statistics() { - gPipeline.resetFrameStats(); // Reset per-frame statistics. if (LLSurface::sTextureUpdateTime) { LLSurface::sTexelsUpdatedPerSecStat.addValue(0.001f*(LLSurface::sTexelsUpdated / LLSurface::sTextureUpdateTime)); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e73736bc61..cddca66220 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -194,7 +194,7 @@ // // Globals // -void render_ui(); +void render_ui(F32 zoom_factor = 1.f, int subfield = 0); LLBottomPanel* gBottomPanel = NULL; extern BOOL gDebugClicks; @@ -447,7 +447,7 @@ public: if (gPipeline.mBatchCount > 0) { addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, - gPipeline.mMeanBatchSize)); + gPipeline.mTrianglesDrawn/gPipeline.mBatchCount)); gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize; gPipeline.mMaxBatchSize = 0; @@ -464,9 +464,46 @@ public: ypos += y_inc; + addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); + + ypos += y_inc; + LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = - gPipeline.mNumVisibleNodes = 0; + gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; + } + if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + { + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3])); + ypos += y_inc; + + addText(xpos, ypos, "Projection Matrix"); + ypos += y_inc; + + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3])); + ypos += y_inc; + + addText(xpos, ypos, "View Matrix"); + ypos += y_inc; } if (gSavedSettings.getBOOL("DebugShowColor")) { @@ -3473,9 +3510,9 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) LLGLState scissor_state(GL_SCISSOR_TEST); scissor_state.enable(); glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight()); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } // build perspective transform and picking viewport @@ -4028,6 +4065,10 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { + return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); + + // *TODO below code was broken in deferred pipeline + /* if ((!raw) || preview_width < 10 || preview_height < 10) { return FALSE; @@ -4059,7 +4100,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame S32 w = preview_width ; - S32 h = preview_height ; + S32 h = preview_height ; LLVector2 display_scale = mDisplayScale ; mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ; LLRect window_rect = mWindowRect; @@ -4098,7 +4139,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p gltype = GL_UNSIGNED_BYTE ; } - raw->resize(w, h, glpixel_length); + raw->resize(w, h, glpixel_length); glReadPixels(0, 0, w, h, glformat, gltype, raw->getData()); if(SNAPSHOT_TYPE_DEPTH == type) @@ -4160,7 +4201,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p gSavedSettings.setS32("RenderName", render_name); - return TRUE; + return TRUE;*/ } // Saves the image from the screen to the specified filename and path. @@ -4210,7 +4251,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; snapshot_width = (S32)(ratio * image_width) ; snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; + scale_factor = llmax(1.0f, 1.0f / ratio) ; } else //the scene(window) proportion needs to be maintained. { @@ -4227,7 +4268,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei snapshot_width = image_width; snapshot_height = image_height; - target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE); + target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE); window_width = snapshot_width; window_height = snapshot_height; scale_factor = 1.f; @@ -4304,9 +4345,10 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei } else { - display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), TRUE); + const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); + display(do_rebuild, scale_factor, subfield, TRUE); // Required for showing the GUI in snapshots? See DEV-16350 for details. JC - render_ui(); + render_ui(scale_factor, subfield); } S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); @@ -4777,8 +4819,6 @@ BOOL LLViewerWindow::checkSettings() } mResDirty = false; - // This will force a state update the next frame. - mStatesDirty = true; } BOOL is_fullscreen = mWindow->getFullscreen(); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index b58f1147f3..b79d7d10ff 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -107,6 +107,7 @@ void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id) return; } mDetailTextures[corner] = gImageList.getImage(id); + mDetailTextures[corner]->setNoDelete() ; mRawImages[corner] = NULL; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7e22eb40bb..3757923e27 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -684,9 +684,6 @@ LLVOAvatar::LLVOAvatar( mLowerMaskTexName(0), mCulled( FALSE ), mVisibilityRank(0), - mFadeTime(0.f), - mLastFadeTime(0.f), - mLastFadeDistance(1.f), mTexSkinColor( NULL ), mTexHairColor( NULL ), mTexEyeColor( NULL ), @@ -764,7 +761,7 @@ LLVOAvatar::LLVOAvatar( mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c"); gGL.getTexUnit(0)->bind(mShadowImagep.get()); - mShadowImagep->setClamp(TRUE, TRUE); + mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mInAir = FALSE; @@ -1362,11 +1359,11 @@ void LLVOAvatar::deleteCachedImages() LLTexLayerSet::sHasCaches = FALSE; } - for( GLuint* namep = (GLuint*)sScratchTexNames.getFirstData(); + for( LLGLuint * namep = sScratchTexNames.getFirstData(); namep; - namep = (GLuint*)sScratchTexNames.getNextData() ) + namep = sScratchTexNames.getNextData() ) { - glDeleteTextures(1, namep ); + LLImageGL::deleteTextures(1, (U32 *)namep ); stop_glerror(); } @@ -2868,12 +2865,15 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - mDrawable->movePartition(); - - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + if (mDrawable.notNull()) { - gPipeline.markMoved(mDrawable, TRUE); + mDrawable->movePartition(); + + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + { + gPipeline.markMoved(mDrawable, TRUE); + } } } @@ -3576,6 +3576,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { //back 25% of max visible avatars are slow updating impostors mUpdatePeriod = 8; } + else if (visible && mVisibilityRank > (U32) LLVOAvatar::sMaxVisible) + { //background avatars are REALLY slow updating impostors + mUpdatePeriod = 16; + } else if (visible && mImpostorPixelArea <= impostor_area) { // stuff in between gets an update period based on pixel area mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8); @@ -4193,7 +4197,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mSkirtLOD.updateJointGeometry(); } - if (!mIsSelf || gAgent.needsRenderHead()) + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { mEyeLashLOD.updateJointGeometry(); mHeadLOD.updateJointGeometry(); @@ -4294,18 +4298,22 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { BOOL first_pass = TRUE; - if (!mIsSelf || gAgent.needsRenderHead()) + if (!LLDrawPoolAvatar::sSkipOpaque) { - num_indices += mHeadLOD.render(mAdjustedPixelArea); - first_pass = FALSE; + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + { + num_indices += mHeadLOD.render(mAdjustedPixelArea); + first_pass = FALSE; + } + num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { LLGLEnable blend(GL_BLEND); LLGLEnable test(GL_ALPHA_TEST); - num_indices += renderTransparent(); + num_indices += renderTransparent(first_pass); } } @@ -4318,10 +4326,9 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } -U32 LLVOAvatar::renderTransparent() +U32 LLVOAvatar::renderTransparent(BOOL first_pass) { U32 num_indices = 0; - BOOL first_pass = FALSE; if( isWearingWearableType( WT_SKIRT ) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); @@ -4330,7 +4337,7 @@ U32 LLVOAvatar::renderTransparent() gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } - if (!mIsSelf || gAgent.needsRenderHead()) + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (LLPipeline::sImpostorRender) { @@ -4402,7 +4409,7 @@ U32 LLVOAvatar::renderFootShadows() } U32 foot_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; LLGLDepthTest test(GL_TRUE, GL_FALSE); //render foot shadows @@ -4435,23 +4442,6 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) LLGLEnable test(GL_ALPHA_TEST); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - F32 blend = gFrameTimeSeconds - mFadeTime; - - LLGLState gl_blend(GL_BLEND, blend < 1.f ? TRUE : FALSE); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - F32 alpha; - if (mVisibilityRank >= (U32) LLVOAvatar::sMaxVisible) - { //fade out - alpha = 1.f - llmin(blend, 1.f); - } - else - { //fade in - alpha = llmin(blend, 1.f); - } - - color.mV[3] = (U8) (alpha*255); - gGL.color4ubv(color.mV); gGL.getTexUnit(0)->bind(&mImpostor); gGL.begin(LLRender::QUADS); @@ -5945,6 +5935,11 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); + if (mDrawable.isNull()) + { + return; + } + const LLVector3* ext = mDrawable->getSpatialExtents(); LLVector3 center = (ext[1] + ext[0]) * 0.5f; LLVector3 size = (ext[1]-ext[0])*0.5f; @@ -6349,15 +6344,21 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) //----------------------------------------------------------------------------- void LLVOAvatar::lazyAttach() { + std::vector<LLPointer<LLViewerObject> > still_pending; + for (U32 i = 0; i < mPendingAttachment.size(); i++) { if (mPendingAttachment[i]->mDrawable) { attachObject(mPendingAttachment[i]); } + else + { + still_pending.push_back(mPendingAttachment[i]); + } } - mPendingAttachment.clear(); + mPendingAttachment = still_pending; } void LLVOAvatar::resetHUDAttachments() @@ -6957,8 +6958,7 @@ void LLVOAvatar::dumpTotalLocalTextureByteCount() BOOL LLVOAvatar::isVisible() { return mDrawable.notNull() - && (mDrawable->isVisible() || mIsDummy) - && (mVisibilityRank < (U32) sMaxVisible || gFrameTimeSeconds - mFadeTime < 1.f); + && (mDrawable->isVisible() || mIsDummy); } @@ -7133,23 +7133,21 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLGLSUIDefault gls_ui; - GLuint name = 0; - glGenTextures(1, &name ); + U32 name = 0; + LLImageGL::generateTextures(1, &name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, VOAVATAR_SCRATCH_TEX_WIDTH, VOAVATAR_SCRATCH_TEX_HEIGHT, - 0, format, GL_UNSIGNED_BYTE, NULL ); + format, GL_UNSIGNED_BYTE, NULL ); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -8758,20 +8756,19 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, } U32 gl_name; - glGenTextures(1, (GLuint*) &gl_name ); + LLImageGL::generateTextures(1, &gl_name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, GL_ALPHA8, aux_src->getWidth(), aux_src->getHeight(), - 0, GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); + GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); if( id == head_baked->getID() ) { @@ -8783,7 +8780,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mHeadMaskDiscard = discard_level; if (self->mHeadMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mHeadMaskTexName); + LLImageGL::deleteTextures(1, &self->mHeadMaskTexName); } self->mHeadMaskTexName = gl_name; } @@ -8803,7 +8800,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mUpperMaskDiscard = discard_level; if (self->mUpperMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mUpperMaskTexName); + LLImageGL::deleteTextures(1, &self->mUpperMaskTexName); } self->mUpperMaskTexName = gl_name; } @@ -8823,7 +8820,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mLowerMaskDiscard = discard_level; if (self->mLowerMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mLowerMaskTexName); + LLImageGL::deleteTextures(1, &self->mLowerMaskTexName); } self->mLowerMaskTexName = gl_name; } @@ -9010,7 +9007,9 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) void LLVOAvatar::dumpArchetypeXML( void* ) { LLVOAvatar* avatar = gAgent.getAvatarObject(); - apr_file_t* file = ll_apr_file_open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); + LLAPRFile outfile ; + outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle() ; if( !file ) { return; @@ -9053,7 +9052,6 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } apr_file_printf( file, "\t</archetype>\n" ); apr_file_printf( file, "\n</linden_genepool>\n" ); - apr_file_close( file ); } @@ -9069,33 +9067,7 @@ void LLVOAvatar::setVisibilityRank(U32 rank) return; } - BOOL stale = gFrameTimeSeconds - mLastFadeTime > 10.f; - - //only raise visibility rank or trigger a fade out every 10 seconds - if (mVisibilityRank >= (U32) LLVOAvatar::sMaxVisible && rank < (U32) LLVOAvatar::sMaxVisible || - (stale && mVisibilityRank < (U32) LLVOAvatar::sMaxVisible && rank >= (U32) LLVOAvatar::sMaxVisible)) - { //remember the time we became visible/invisible based on visibility rank - mVisibilityRank = rank; - mLastFadeTime = gFrameTimeSeconds; - mLastFadeDistance = mDrawable->mDistanceWRTCamera; - - F32 blend = gFrameTimeSeconds - mFadeTime; - mFadeTime = gFrameTimeSeconds; - if (blend < 1.f) - { //move the blend time back if a blend is already in progress (prevent flashes) - mFadeTime -= 1.f-blend; - } - } - else if (stale) - { - mLastFadeTime = gFrameTimeSeconds; - mLastFadeDistance = mDrawable->mDistanceWRTCamera; - mVisibilityRank = rank; - } - else - { - mVisibilityRank = llmin(mVisibilityRank, rank); - } + mVisibilityRank = rank; } // Assumes LLVOAvatar::sInstances has already been sorted. @@ -10023,7 +9995,7 @@ BOOL LLVOAvatar::isImpostor() const BOOL LLVOAvatar::needsImpostorUpdate() const { - return mNeedsImpostorUpdate ; + return mNeedsImpostorUpdate; } const LLVector3& LLVOAvatar::getImpostorOffset() const diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 81ab0fd49c..14f7bd6dcc 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -263,7 +263,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | (1 << LLVertexBuffer::TYPE_WEIGHT) | (1 << LLVertexBuffer::TYPE_CLOTHWEIGHT) }; @@ -306,7 +306,7 @@ public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255)); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); - U32 renderTransparent(); + U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, @@ -978,9 +978,6 @@ protected: BOOL mCulled; U32 mVisibilityRank; - F32 mFadeTime; - F32 mLastFadeTime; - F32 mLastFadeDistance; F32 mMinPixelArea; // debug F32 mMaxPixelArea; // debug BOOL mHasGrey; // debug diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 95c4550fde..5606398aaf 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -149,6 +149,8 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) mSoundSymbol.mWaveExpansion [i] = 1.0f; } + mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + // The first instance loads the initial state from prefs. if (!sPrefsInitialized) { diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 322516fe56..6dfe23ba98 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -418,7 +418,9 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? + LLFastTimer::FTM_REBUILD_GRASS_VB : + LLFastTimer::FTM_REBUILD_PARTICLE_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -438,7 +440,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoordStrider(texcoordsp); + buffer->getTexCoord0Strider(texcoordsp); buffer->getIndexStrider(indicesp); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; @@ -479,8 +481,12 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); } } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 30a3165826..3dc3292992 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -47,7 +47,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 3ec043eb39..c3366cad90 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -213,7 +213,7 @@ void LLSkyTex::init() for (S32 i = 0; i < 2; ++i) { mImageGL[i] = new LLImageGL(FALSE); - mImageGL[i]->setClamp(TRUE, TRUE); + mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP); mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents); initEmpty(i); @@ -231,7 +231,7 @@ void LLSkyTex::restoreGL() for (S32 i = 0; i < 2; i++) { mImageGL[i] = new LLImageGL(FALSE); - mImageGL[i]->setClamp(TRUE, TRUE); + mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP); } } @@ -290,7 +290,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { mImageGL[which]->createGLTexture(0, mImageRaw[which]); - mImageGL[which]->setClamp(TRUE, TRUE); + mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } void LLSkyTex::bindTexture(BOOL curr) @@ -377,11 +377,12 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mMoon.setIntensity(0.1f * SUN_INTENSITY); mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE); - mSunTexturep->setClamp(TRUE, TRUE); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE); - mMoonTexturep->setClamp(TRUE, TRUE); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = gImageList.getImage(IMG_BLOOM1); - mBloomTexturep->setClamp(TRUE, TRUE); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mHeavenlyBodyUpdated = FALSE ; } @@ -447,6 +448,7 @@ void LLVOSky::initCubeMap() mCubeMap = new LLCubeMap(); mCubeMap->init(images); } + gGL.getTexUnit(0)->disable(); } @@ -471,11 +473,12 @@ void LLVOSky::restoreGL() mSkyTex[i].restoreGL(); } mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE); - mSunTexturep->setClamp(TRUE, TRUE); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE); - mMoonTexturep->setClamp(TRUE, TRUE); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = gImageList.getImage(IMG_BLOOM1); - mBloomTexturep->setClamp(TRUE, TRUE); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); calcAtmospherics(); @@ -1153,6 +1156,7 @@ BOOL LLVOSky::updateSky() images.push_back(mShinyTex[side].getImageRaw(TRUE)); } mCubeMap->init(images); + gGL.getTexUnit(0)->disable(); } gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); @@ -2024,7 +2028,7 @@ void LLVOSky::updateFog(const F32 distance) const BOOL hide_clip_plane = TRUE; LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f); - const F32 water_height = gAgent.getRegion()->getWaterHeight(); + const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f; // LLWorld::getInstance()->getWaterHeight(); F32 camera_height = gAgent.getCameraPositionAgent().mV[2]; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 3a90a665a8..4980b50de4 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -57,40 +57,30 @@ class LLVertexBufferTerrain : public LLVertexBuffer { public: LLVertexBufferTerrain() : - LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD | MAP_TEXCOORD2 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) + LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0 | MAP_TEXCOORD1 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) { + //texture coordinates 2 and 3 exist, but use the same data as texture coordinate 1 + mOffsets[TYPE_TEXCOORD3] = mOffsets[TYPE_TEXCOORD2] = mOffsets[TYPE_TEXCOORD1]; + mTypeMask |= MAP_TEXCOORD2 | MAP_TEXCOORD3; }; - // virtual + /*// virtual void setupVertexBuffer(U32 data_mask) const { - if (LLDrawPoolTerrain::getDetailMode() == 0) + if (LLDrawPoolTerrain::getDetailMode() == 0 || LLPipeline::sShadowRender) { LLVertexBuffer::setupVertexBuffer(data_mask); } - else if (data_mask & LLVertexBuffer::MAP_TEXCOORD2) + else if (data_mask & LLVertexBuffer::MAP_TEXCOORD1) { - U8* base = useVBOs() ? NULL : mMappedData; - - glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); - glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - glColorPointer(4, GL_UNSIGNED_BYTE, mStride, (void*)(base + mOffsets[TYPE_COLOR])); - - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + LLVertexBuffer::setupVertexBuffer(data_mask); } else { LLVertexBuffer::setupVertexBuffer(data_mask); } llglassertok(); - } + }*/ }; //============================================================================ @@ -1054,8 +1044,8 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); - llassert_always(buffer->getTexCoordStrider(texcoords)); - llassert_always(buffer->getTexCoord2Strider(texcoords2)); + llassert_always(buffer->getTexCoord0Strider(texcoords)); + llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getColorStrider(colors)); llassert_always(buffer->getIndexStrider(indices)); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 7b0529287c..2dd8651899 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -49,8 +49,8 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | - (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4c7b90d8a1..3b76127eb2 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -86,6 +86,7 @@ LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *region mSpecies = 0; mFrameCount = 0; mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + mTrunkLOD = 0; } @@ -343,41 +344,69 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } - F32 mass_inv; - - // For all tree objects, update the trunk bending with the current wind - // Walk sprite list in order away from viewer - if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) + if (gSavedSettings.getBOOL("RenderAnimateTrees")) { - // If needed, Get latest wind for this tree - mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + F32 mass_inv; + + // For all tree objects, update the trunk bending with the current wind + // Walk sprite list in order away from viewer + if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) + { + // If needed, Get latest wind for this tree + mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + } + mFrameCount++; + + mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); + mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind + mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk + mTrunkBend += mTrunkVel; + mTrunkVel *= 0.99f; // Add damping + + if (mTrunkBend.length() > 1.f) + { + mTrunkBend.normalize(); + } + + if (mTrunkVel.length() > 1.f) + { + mTrunkVel.normalize(); + } } - mFrameCount++; - mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); - mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind - mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk - mTrunkBend += mTrunkVel; - mTrunkVel *= 0.99f; // Add damping + S32 trunk_LOD = 0; + F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; - if (mTrunkBend.length() > 1.f) + for (S32 j = 0; j < 4; j++) { - mTrunkBend.normalize(); - } - if (mTrunkVel.length() > 1.f) + if (app_angle > LLVOTree::sLODAngles[j]) + { + trunk_LOD = j; + break; + } + } + + if (!gSavedSettings.getBOOL("RenderAnimateTrees")) { - mTrunkVel.normalize(); + if (mReferenceBuffer.isNull()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + else if (trunk_LOD != mTrunkLOD) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); + } } + mTrunkLOD = trunk_LOD; + return TRUE; } - const F32 TREE_BLEND_MIN = 1.f; const F32 TREE_BLEND_RANGE = 1.f; - void LLVOTree::render(LLAgent &agent) { } @@ -450,338 +479,604 @@ const S32 LEAF_VERTICES = 16; BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE); - const F32 SRR3 = 0.577350269f; // sqrt(1/3) - const F32 SRR2 = 0.707106781f; // sqrt(1/2) - U32 i, j; - U32 slices = MAX_SLICES; + if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull()) + { + const F32 SRR3 = 0.577350269f; // sqrt(1/3) + const F32 SRR2 = 0.707106781f; // sqrt(1/2) + U32 i, j; + + U32 slices = MAX_SLICES; + + S32 max_indices = LEAF_INDICES; + S32 max_vertices = LEAF_VERTICES; + S32 lod; + + LLFace *face = drawable->getFace(0); + + face->mCenterAgent = getPositionAgent(); + face->mCenterLocal = face->mCenterAgent; + + for (lod = 0; lod < 4; lod++) + { + slices = sLODSlices[lod]; + sLODVertexOffset[lod] = max_vertices; + sLODVertexCount[lod] = slices*slices; + sLODIndexOffset[lod] = max_indices; + sLODIndexCount[lod] = (slices-1)*(slices-1)*6; + max_indices += sLODIndexCount[lod]; + max_vertices += sLODVertexCount[lod]; + } + + mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, gSavedSettings.getBOOL("RenderAnimateTrees") ? GL_STATIC_DRAW_ARB : 0); + mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE); + + LLStrider<LLVector3> vertices; + LLStrider<LLVector3> normals; + LLStrider<LLVector2> tex_coords; + LLStrider<U16> indicesp; + + mReferenceBuffer->getVertexStrider(vertices); + mReferenceBuffer->getNormalStrider(normals); + mReferenceBuffer->getTexCoord0Strider(tex_coords); + mReferenceBuffer->getIndexStrider(indicesp); + + S32 vertex_count = 0; + S32 index_count = 0; + + // First leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 1; + index_count++; + *(indicesp++) = 2; + index_count++; + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 3; + index_count++; + *(indicesp++) = 1; + index_count++; + + // Same leaf, inverse winding/normals + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 6; + index_count++; + *(indicesp++) = 5; + index_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 5; + index_count++; + *(indicesp++) = 7; + index_count++; + + + // next leaf + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 9; + index_count++; + *(indicesp++) = 10; + index_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 11; + index_count++; + *(indicesp++) = 9; + index_count++; + + + // other side of same leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 14; + index_count++; + *(indicesp++) = 13; + index_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 13; + index_count++; + *(indicesp++) = 15; + index_count++; + + // Generate geometry for the cylinders + + // Different LOD's + + // Generate the vertices + // Generate the indices + + for (lod = 0; lod < 4; lod++) + { + slices = sLODSlices[lod]; + F32 base_radius = 0.65f; + F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; + //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl; + //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl; + F32 angle = 0; + F32 angle_inc = 360.f/(slices-1); + F32 z = 0.f; + F32 z_inc = 1.f; + if (slices > 3) + { + z_inc = 1.f/(slices - 3); + } + F32 radius = base_radius; + + F32 x1,y1; + F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; + LLVector3 nvec; + + const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch + + const S32 fractal_depth = 5; + F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; + F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; + + F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; + + F32 start_radius; + F32 nangle = 0; + F32 height = 1.f; + F32 r0; + + for (i = 0; i < slices; i++) + { + if (i == 0) + { + z = - cap_nudge; + r0 = 0.0; + } + else if (i == (slices - 1)) + { + z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; + r0 = 0.0; + } + else + { + z = (i - 1) * z_inc; + r0 = base_radius + (top_radius - base_radius)*z; + } - S32 max_indices = LEAF_INDICES; - S32 max_vertices = LEAF_VERTICES; - S32 lod; + for (j = 0; j < slices; j++) + { + if (slices - 1 == j) + { + angle = 0.f; + } + else + { + angle = j*angle_inc; + } + + nangle = angle; + + x1 = cos(angle * DEG_TO_RAD); + y1 = sin(angle * DEG_TO_RAD); + LLVector2 tc; + // This isn't totally accurate. Should compute based on slope as well. + start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); + nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + z*nvec_scalez); + // First and last slice at 0 radius (to bring in top/bottom of structure) + radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; + + if (slices - 1 == j) + { + // Not 0.5 for slight slop factor to avoid edges on leaves + tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); + } + else + { + tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); + } + + *(vertices++) = LLVector3(x1*radius, y1*radius, z); + *(normals++) = LLVector3(x1, y1, 0.f); + *(tex_coords++) = tc; + vertex_count++; + } + } - LLFace *face = drawable->getFace(0); + for (i = 0; i < (slices - 1); i++) + { + for (j = 0; j < (slices - 1); j++) + { + S32 x1_offset = j+1; + if ((j+1) == slices) + { + x1_offset = 0; + } + // Generate the matching quads + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + } + } + slices /= 2; + } - face->mCenterAgent = getPositionAgent(); - face->mCenterLocal = face->mCenterAgent; + mReferenceBuffer->setBuffer(0); + llassert(vertex_count == max_vertices); + llassert(index_count == max_indices); + } - for (lod = 0; lod < 4; lod++) + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + mDrawable->getFace(0)->mVertexBuffer = mReferenceBuffer; + } + else { - slices = sLODSlices[lod]; - sLODVertexOffset[lod] = max_vertices; - sLODVertexCount[lod] = slices*slices; - sLODIndexOffset[lod] = max_indices; - sLODIndexCount[lod] = (slices-1)*(slices-1)*6; - max_indices += sLODIndexCount[lod]; - max_vertices += sLODVertexCount[lod]; + //generate tree mesh + updateMesh(); } + + return TRUE; +} +void LLVOTree::updateMesh() +{ + LLMatrix4 matrix; + + // Translate to tree base HACK - adjustment in Z plants tree underground + const LLVector3 &pos_agent = getPositionAgent(); + //glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + LLMatrix4 trans_mat; + trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat *= matrix; + + // Rotate to tree position and bend for current trunk/wind + // Note that trunk stiffness controls the amount of bend at the trunk as + // opposed to the crown of the tree + // + const F32 TRUNK_STIFF = 22.f; + + LLQuaternion rot = + LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * + LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * + getRotation(); + + LLMatrix4 rot_mat(rot); + rot_mat *= trans_mat; + + F32 radius = getScale().magVec()*0.05f; + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = + scale_mat.mMatrix[1][1] = + scale_mat.mMatrix[2][2] = radius; + + scale_mat *= rot_mat; + +// const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; +// const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; + + F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); + + S32 stop_depth = 0; + F32 alpha = 1.0; + + + U32 vert_count = 0; + U32 index_count = 0; + + calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); + + LLFace* facep = mDrawable->getFace(0); + facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); + facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE); + LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> tex_coords; - LLStrider<U16> indicesp; - - face->setSize(max_vertices, max_indices); + LLStrider<U16> indices; + U16 idx_offset = 0; - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE); - face->setGeomIndex(0); - face->setIndicesIndex(0); + facep->mVertexBuffer->getVertexStrider(vertices); + facep->mVertexBuffer->getNormalStrider(normals); + facep->mVertexBuffer->getTexCoord0Strider(tex_coords); + facep->mVertexBuffer->getIndexStrider(indices); - face->getGeometry(vertices, normals, tex_coords, indicesp); + genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); + mReferenceBuffer->setBuffer(0); + facep->mVertexBuffer->setBuffer(0); + +} - S32 vertex_count = 0; - S32 index_count = 0; +void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& cur_idx, + LLMatrix4& matrix, + LLMatrix4& norm_mat, + S32 vert_start, + S32 vert_count, + S32 index_count, + S32 index_offset) +{ + LLStrider<LLVector3> v; + LLStrider<LLVector3> n; + LLStrider<LLVector2> t; + LLStrider<U16> idx; + + mReferenceBuffer->getVertexStrider(v); + mReferenceBuffer->getNormalStrider(n); + mReferenceBuffer->getTexCoord0Strider(t); + mReferenceBuffer->getIndexStrider(idx); - // First leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 1; - index_count++; - *(indicesp++) = 2; - index_count++; - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 3; - index_count++; - *(indicesp++) = 1; - index_count++; - - // Same leaf, inverse winding/normals - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 6; - index_count++; - *(indicesp++) = 5; - index_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 5; - index_count++; - *(indicesp++) = 7; - index_count++; - - - // next leaf - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 9; - index_count++; - *(indicesp++) = 10; - index_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 11; - index_count++; - *(indicesp++) = 9; - index_count++; - - - // other side of same leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 14; - index_count++; - *(indicesp++) = 13; - index_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 13; - index_count++; - *(indicesp++) = 15; - index_count++; - - // Generate geometry for the cylinders - - // Different LOD's - - // Generate the vertices - // Generate the indices - - for (lod = 0; lod < 4; lod++) + //copy/transform vertices into mesh - check + for (S32 i = 0; i < vert_count; i++) + { + U16 index = vert_start + i; + *vertices++ = v[index] * matrix; + LLVector3 norm = n[index] * norm_mat; + norm.normalize(); + *normals++ = norm; + *tex_coords++ = t[index]; + } + + //copy offset indices into mesh - check + for (S32 i = 0; i < index_count; i++) { - slices = sLODSlices[lod]; - F32 base_radius = 0.65f; - F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; - //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl; - //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl; - F32 angle = 0; - F32 angle_inc = 360.f/(slices-1); - F32 z = 0.f; - F32 z_inc = 1.f; - if (slices > 3) + U16 index = index_offset + i; + if (idx[index] >= vert_start + vert_count || + idx[index] < vert_start) { - z_inc = 1.f/(slices - 3); + llerrs << "WTF?" << llendl; } - F32 radius = base_radius; - - F32 x1,y1; - F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; - LLVector3 nvec; - - const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch - - const S32 fractal_depth = 5; - F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; - F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; + *indices++ = idx[index]-vert_start+cur_idx; + } - F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; + //increment index offset - check + cur_idx += vert_count; +} + + +void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& index_offset, + LLMatrix4& matrix, + S32 trunk_LOD, + S32 stop_level, + U16 depth, + U16 trunk_depth, + F32 scale, + F32 twist, + F32 droop, + F32 branches, + F32 alpha) +{ + // + // Generates a tree mesh by recursing, generating branches and then a 'leaf' texture. + + static F32 constant_twist; + static F32 width = 0; - F32 start_radius; - F32 nangle = 0; - F32 height = 1.f; - F32 r0; + F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength); + F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect); + + constant_twist = 360.f/branches; - for (i = 0; i < slices; i++) + if (stop_level >= 0) + { + if (depth > stop_level) { - if (i == 0) { - z = - cap_nudge; - r0 = 0.0; + llassert(sLODIndexCount[trunk_LOD] > 0); + width = scale * length * aspect; + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = width; + scale_mat.mMatrix[1][1] = width; + scale_mat.mMatrix[2][2] = scale*length; + scale_mat *= matrix; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + norm_mat.invert(); + appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, + sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[trunk_LOD]); } - else if (i == (slices - 1)) + + // Recurse to create more branches + for (S32 i=0; i < (S32)branches; i++) { - z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; - r0 = 0.0; + LLMatrix4 trans_mat; + trans_mat.setTranslation(0,0,scale*length); + trans_mat *= matrix; + + LLQuaternion rot = + LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) * + LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) * + LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)); + + LLMatrix4 rot_mat(rot); + rot_mat *= trans_mat; + + genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha); } - else + // Recurse to continue trunk + if (trunk_depth) { - z = (i - 1) * z_inc; - r0 = base_radius + (top_radius - base_radius)*z; - } + LLMatrix4 trans_mat; + trans_mat.setTranslation(0,0,scale*length); + trans_mat *= matrix; - for (j = 0; j < slices; j++) + LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1)); + rot_mat *= trans_mat; // rotate a bit around Z when ascending + genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); + } + } + else + { + // + // Append leaves as two 90 deg crossed quads with leaf textures + // { - if (slices - 1 == j) - { - angle = 0.f; - } - else - { - angle = j*angle_inc; - } - - nangle = angle; - - x1 = cos(angle * DEG_TO_RAD); - y1 = sin(angle * DEG_TO_RAD); - LLVector2 tc; - // This isn't totally accurate. Should compute based on slope as well. - start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); - nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - z*nvec_scalez); - // First and last slice at 0 radius (to bring in top/bottom of structure) - radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; - - if (slices - 1 == j) - { - // Not 0.5 for slight slop factor to avoid edges on leaves - tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); - } - else - { - tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); - } + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = + scale_mat.mMatrix[1][1] = + scale_mat.mMatrix[2][2] = scale*mLeafScale; - *(vertices++) = LLVector3(x1*radius, y1*radius, z); - *(normals++) = LLVector3(x1, y1, 0.f); - *(tex_coords++) = tc; - vertex_count++; + scale_mat *= matrix; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0); } } + } +} + - for (i = 0; i < (slices - 1); i++) + +void LLVOTree::calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches) +{ + if (stop_level >= 0) + { + if (depth > stop_level) { - for (j = 0; j < (slices - 1); j++) + index_count += sLODIndexCount[trunk_LOD]; + vert_count += sLODVertexCount[trunk_LOD]; + + // Recurse to create more branches + for (S32 i=0; i < (S32)branches; i++) { - S32 x1_offset = j+1; - if ((j+1) == slices) - { - x1_offset = 0; - } - // Generate the matching quads - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth - 1, 0, branches); } + + // Recurse to continue trunk + if (trunk_depth) + { + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth, trunk_depth-1, branches); + } + } + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; } - slices /= 2; } - - face->mVertexBuffer->setBuffer(0); - llassert(vertex_count == max_vertices); - llassert(index_count == max_indices); - - return TRUE; + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; + } } U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha) diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 7e81dc3e08..473f1c340e 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -51,7 +51,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) + (1 << LLVertexBuffer::TYPE_TEXCOORD0) }; LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); @@ -79,6 +79,38 @@ public: void updateRadius(); + void calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches); + + void updateMesh(); + + void appendMesh(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& idx_offset, + LLMatrix4& matrix, + LLMatrix4& norm_mat, + S32 vertex_offset, + S32 vertex_count, + S32 index_count, + S32 index_offset); + + void genBranchPipeline(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& index_offset, + LLMatrix4& matrix, + S32 trunk_LOD, + S32 stop_level, + U16 depth, + U16 trunk_depth, + F32 scale, + F32 twist, + F32 droop, + F32 branches, + F32 alpha); + U32 drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha); @@ -127,6 +159,7 @@ protected: LLVector3 mTrunkVel; // LLVector3 mWind; + LLPointer<LLVertexBuffer> mReferenceBuffer; //reference geometry for generating tree mesh LLPointer<LLViewerImage> mTreeImagep; // Pointer to proper tree image U8 mSpecies; // Species of tree @@ -138,7 +171,7 @@ protected: U8 mDepth; // Number of recursions to tips of branches F32 mScaleStep; // Multiplier for scale at each recursion level U8 mTrunkDepth; - + U32 mTrunkLOD; F32 mLeafScale; // Scales leaf texture when rendering F32 mBillboardScale; // How big to draw the billboard? diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9023147a7d..9e051a6470 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -409,7 +409,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) void LLVOVolume::updateTextures(LLAgent &agent) { const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { if (mDrawable->isVisible()) { @@ -468,17 +468,6 @@ void LLVOVolume::updateTextures() F32 old_size = face->getVirtualSize(); - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - - if (LLPipeline::sFastAlpha && - vsize < MIN_ALPHA_SIZE && old_size > MIN_ALPHA_SIZE || - vsize > MIN_ALPHA_SIZE && old_size < MIN_ALPHA_SIZE) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_COLOR, FALSE); - } - } - if (face->mTextureMatrix != NULL) { if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || @@ -1283,10 +1272,12 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { S32 res = LLViewerObject::setTEColor(te, color); - if (res) + if (res && mDrawable.notNull()) { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; + //gPipeline.markTextured(mDrawable); + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + //mFaceMappingChanged = TRUE; } return res; } @@ -1392,11 +1383,11 @@ S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) void LLVOVolume::updateTEData() { - if (mDrawable.notNull()) + /*if (mDrawable.notNull()) { mFaceMappingChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); - } + }*/ } //---------------------------------------------------------------------------- @@ -1824,7 +1815,9 @@ F32 LLVOVolume::getBinRadius() { LLFace* face = mDrawable->getFace(i); if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - (!LLPipeline::sFastAlpha || face->getVirtualSize() > MIN_ALPHA_SIZE)) + (!LLPipeline::sFastAlpha || + face->getFaceColor().mV[3] != 1.f || + !face->getTexture()->getIsAlphaMask())) { alpha_wrap = TRUE; break; @@ -1849,14 +1842,20 @@ F32 LLVOVolume::getBinRadius() } else if (mDrawable->isStatic()) { - if (mDrawable->getRadius() < 2.0f) + /*if (mDrawable->getRadius() < 2.0f) { radius = 16.f; } else { radius = llmax(mDrawable->getRadius(), 32.f); - } + }*/ + + radius = (((S32) mDrawable->getRadius())/2+1)*8; + } + else if (mDrawable->getVObj()->isAttachment()) + { + radius = (((S32) (mDrawable->getRadius()*4)+1))*2; } else { @@ -2128,6 +2127,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, glow = (U8) (facep->getTextureEntry()->getGlow() * 255); } + if (facep->mVertexBuffer.isNull()) + { + llerrs << "WTF?" << llendl; + } + if (idx >= 0 && draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && @@ -2146,6 +2150,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); validate_draw_info(*draw_vec[idx]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); } else { @@ -2161,6 +2167,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mTextureMatrix = tex_mat; draw_info->mModelMatrix = model_mat; draw_info->mGlowColor.setVec(0,0,0,glow); + if (type == LLRenderPass::PASS_ALPHA) + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + draw_info->mExtents[0] = facep->mExtents[0]; + draw_info->mExtents[1] = facep->mExtents[1]; validate_draw_info(*draw_info); } } @@ -2184,89 +2196,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; - if (!group->isState(LLSpatialGroup::GEOM_DIRTY | - LLSpatialGroup::ALPHA_DIRTY)) + if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) { - if (group->isState(LLSpatialGroup::MESH_DIRTY)) + if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; - - group->mBuilt = 1.f; LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); - LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); - - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isState(LLDrawable::REBUILD_ALL)) - { - LLVOVolume* vobj = drawablep->getVOVolume(); - vobj->preRebuild(); - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull()) - { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); - } - } - - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - //unmap all the buffers - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) - { - LLSpatialGroup::buffer_list_t& list = i->second; - for (LLSpatialGroup::buffer_list_t::iterator j = list.begin(); j != list.end(); ++j) - { - LLVertexBuffer* buffer = *j; - if (buffer->isLocked()) - { - buffer->setBuffer(0); - } - } - } - - // don't forget alpha - if( group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->setBuffer(0); - } - - //if not all buffers are unmapped - if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) - { - llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked()) - { - face->mVertexBuffer->setBuffer(0) ; - } - } - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY); + + rebuildMesh(group); } - return; } @@ -2279,15 +2217,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) mFaceList.clear(); + std::vector<LLFace*> fullbright_faces; + std::vector<LLFace*> bump_faces; + std::vector<LLFace*> simple_faces; + std::vector<LLFace*> alpha_faces; - U32 vertex_count = 0; - U32 index_count = 0; U32 useage = group->mSpatialPartition->mBufferUsage; U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); - //get all the faces into a list, putting alpha faces in their own list + U32 cur_total = 0; + + //get all the faces into a list for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -2313,6 +2256,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); + + if (cur_total > max_total) + { + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + continue; + } + + cur_total += facep->getGeomCount(); + if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) { const LLTextureEntry* te = facep->getTextureEntry(); @@ -2349,36 +2302,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - BOOL alpha_opt = LLPipeline::sFastAlpha && gPipeline.canUseWindLightShadersOnObjects() && facep->getVirtualSize() < MIN_ALPHA_SIZE; - - const LLColor4& col = facep->getTextureEntry()->getColor(); - - if (alpha_opt) - { //if we're applying the alpha optimization, only blend faces that have alpha (0.15, 0.5] - //for faces with alpha (0.5, 1.0], render with an alpha mask - //for faces with alpha [0.0, 0.15], don't render - if (col.mV[3] > 0.5f) - { - mFaceList.push_back(facep); - } - else if (col.mV[3] > 0.15f) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - alpha_faces.push_back(facep); - } - else - { //face has no renderable geometry - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; - //don't alpha wrap drawables that have only tiny tiny alpha faces - facep->setPoolType(LLDrawPool::POOL_SIMPLE); - } + if (LLPipeline::sFastAlpha && + (te->getColor().mV[VW] == 1.0f) && + facep->getTexture()->getIsAlphaMask()) + { //can be treated as alpha mask + simple_faces.push_back(facep); } else { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); alpha_faces.push_back(facep); } } @@ -2388,124 +2319,300 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { facep->mLastUpdateTime = gFrameTimeSeconds; } - mFaceList.push_back(facep); + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + fullbright_faces.push_back(facep); + } + } + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() && LLPipeline::sRenderBump || + !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + fullbright_faces.push_back(facep); + } + } } } else { //face has no renderable geometry facep->mVertexBuffer = NULL; facep->mLastVertexBuffer = NULL; - //don't alpha wrap drawables that have only tiny tiny alpha faces - facep->setPoolType(LLDrawPool::POOL_SIMPLE); } } } - U16 alpha_vertex_count = vertex_count > 65535 ? 65535 : vertex_count; - U32 alpha_index_count = index_count; - group->mBufferUsage = useage; //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + if (LLPipeline::sRenderDeferred) { - //sort faces by things that break batches - std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareBatchBreaker()); - - std::vector<LLFace*>::iterator face_iter = mFaceList.begin(); - - LLSpatialGroup::buffer_map_t buffer_map; + bump_mask |= LLVertexBuffer::MAP_BINORMAL; + } - LLViewerImage* last_tex = NULL; - U32 buffer_index = 0; + genDrawInfo(group, simple_mask, simple_faces); + genDrawInfo(group, bump_mask, bump_faces); + genDrawInfo(group, fullbright_mask, fullbright_faces); + genDrawInfo(group, alpha_mask, alpha_faces, TRUE); - while (face_iter != mFaceList.end()) + if (!LLPipeline::sDelayVBUpdate) + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - //pull off next face - LLFace* facep = *face_iter; - LLViewerImage* tex = facep->getTexture(); + LLDrawable* drawablep = *drawable_iter; + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } - if (last_tex == tex) - { - buffer_index++; - } - else + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + + if (LLPipeline::sDelayVBUpdate) + { + group->setState(LLSpatialGroup::MESH_DIRTY); + } + + mFaceList.clear(); +} + +void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) +{ + if (group->isState(LLSpatialGroup::MESH_DIRTY)) + { + S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; + + group->mBuilt = 1.f; + + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { - last_tex = tex; - buffer_index = 0; + continue; } - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); - - //sum up vertices needed for this texture - std::vector<LLFace*>::iterator i = face_iter; - ++i; - - while (i != mFaceList.end() && - (LLPipeline::sTextureBindTest || (*i)->getTexture() == tex)) + if (drawablep->isState(LLDrawable::REBUILD_ALL)) { - facep = *i; - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut vertex buffers on geom count too big - break; + LLVOVolume* vobj = drawablep->getVOVolume(); + vobj->preRebuild(); + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face && face->mVertexBuffer.notNull()) + { + face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + } } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + drawablep->clearState(LLDrawable::REBUILD_ALL); } + } - //create/delete/resize vertex buffer if needed - LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex); - if (found_iter != group->mBufferMap.end()) + //unmap all the buffers + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + { + LLSpatialGroup::buffer_texture_map_t& map = i->second; + for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j) { - if (buffer_index < found_iter->second.size()) + LLSpatialGroup::buffer_list_t& list = j->second; + for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k) { - buffer = found_iter->second[buffer_index]; + LLVertexBuffer* buffer = *k; + if (buffer->isLocked()) + { + buffer->setBuffer(0); + } } } - - if (!buffer) - { //create new buffer if needed + } + + // don't forget alpha + if( group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->setBuffer(0); + } + + //if not all buffers are unmapped + if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) + { + llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked()) + { + face->mVertexBuffer->setBuffer(0) ; + } + } + } + } + + group->clearState(LLSpatialGroup::MESH_DIRTY); + } +} + +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) +{ + //calculate maximum number of vertices to store in a single buffer + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } + + std::vector<LLFace*>::iterator face_iter = faces.begin(); + + LLSpatialGroup::buffer_map_t buffer_map; + + LLViewerImage* last_tex = NULL; + S32 buffer_index = 0; + + if (distance_sort) + { + buffer_index = -1; + } + + while (face_iter != faces.end()) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerImage* tex = facep->getTexture(); + + if (distance_sort) + { + tex = NULL; + } + + if (last_tex == tex) + { + buffer_index++; + } + else + { + last_tex = tex; + buffer_index = 0; + } + + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); + + //sum up vertices needed for this texture + std::vector<LLFace*>::iterator i = face_iter; + ++i; + + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut vertex buffers on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } + + //create/delete/resize vertex buffer if needed + LLVertexBuffer* buffer = NULL; + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex); + + if (found_iter != group->mBufferMap[mask].end()) + { + if ((U32) buffer_index < found_iter->second.size()) + { + buffer = found_iter->second[buffer_index]; + } + } + + if (!buffer) + { //create new buffer if needed + buffer = createVertexBuffer(mask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { + if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) + { buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); + group->mBufferUsage); buffer->allocateBuffer(geom_count, index_count, TRUE); } - else + else { - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) - { - buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } + buffer->resizeBuffer(geom_count, index_count); } + } - buffer_map[tex].push_back(buffer); + buffer_map[mask][tex].push_back(buffer); - //add face geometry + //add face geometry - U32 indices_index = 0; - U16 index_offset = 0; + U32 indices_index = 0; + U16 index_offset = 0; - while (face_iter < i) + while (face_iter < i) + { + facep = *face_iter; + facep->mIndicesIndex = indices_index; + facep->mGeomIndex = index_offset; + facep->mVertexBuffer = buffer; { - facep = *face_iter; - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - U32 te_idx = facep->getTEOffset(); - facep->mIndicesIndex = indices_index; - facep->mGeomIndex = index_offset; - facep->mVertexBuffer = buffer; + facep->updateRebuildFlags(); + if (!LLPipeline::sDelayVBUpdate) { + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + U32 te_idx = facep->getTEOffset(); + if (facep->getGeometryVolume(*volume, te_idx, vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) { @@ -2513,168 +2620,130 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->getIndicesStart(), facep->getIndicesCount()); } } + } - index_offset += facep->getGeomCount(); - indices_index += facep->mIndicesCount; - - BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - const LLTextureEntry* te = facep->getTextureEntry(); + index_offset += facep->getGeomCount(); + indices_index += facep->mIndicesCount; - BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; + BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + const LLTextureEntry* te = facep->getTextureEntry(); - if (!is_alpha - && gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump - && te->getShiny()) + BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; + + if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (LLPipeline::sFastAlpha && + (te->getColor().mV[VW] == 1.0f) && + facep->getTexture()->getIsAlphaMask()) { - if (tex->getPrimaryFormat() == GL_ALPHA) + if (te->getFullbright()) { - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); } else { - registerFace(group, facep, LLRenderPass::PASS_SHINY); + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); } } else { - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + + if (LLPipeline::sRenderDeferred) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_SHADOW); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny()) + { + if (tex->getPrimaryFormat() == GL_ALPHA) + { + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (LLPipeline::sRenderDeferred) + { + if (te->getBumpmap()) { - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + registerFace(group, facep, LLRenderPass::PASS_BUMP); } - else if (fullbright) + else if (te->getFullbright()) { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } - - if (!is_alpha && te->getShiny()) - { - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } } - - if (!is_alpha) + else if (fullbright) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else { - facep->setPoolType(LLDrawPool::POOL_SIMPLE); - - if (!force_simple && te->getBumpmap()) + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + else + { + if (LLPipeline::sRenderDeferred && te->getBumpmap()) { registerFace(group, facep, LLRenderPass::PASS_BUMP); } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } } - - if (LLPipeline::sRenderGlow && te->getGlow() > 0.f) + + if (!is_alpha && te->getShiny()) { - registerFace(group, facep, LLRenderPass::PASS_GLOW); + registerFace(group, facep, LLRenderPass::PASS_SHINY); } - - ++face_iter; - } - - buffer->setBuffer(0); - } - - group->mBufferMap.clear(); - for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i) - { - group->mBufferMap[i->first] = i->second; - } - } - - //PROCESS ALPHA FACES - if (!alpha_faces.empty()) - { - //sort alpha faces by distance - std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater()); - - //store alpha faces in root vertex buffer - if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage())) - { - group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); - group->mVertexBuffer->allocateBuffer(alpha_vertex_count, alpha_index_count, true); - stop_glerror(); - } - else - { - group->mVertexBuffer->resizeBuffer(alpha_vertex_count, alpha_index_count); - stop_glerror(); - } - - //get vertex buffer striders - LLVertexBuffer* buffer = group->mVertexBuffer; - - U32 index_offset = 0; - U32 indices_index = 0; - - for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i) - { - LLFace* facep = *i; - - if (facep->mGeomCount + index_offset > 65535) - { //cut off alpha nodes at 64k vertices - facep->mVertexBuffer = NULL ; - facep->mLastVertexBuffer = NULL ; - continue ; } - - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - U32 te_idx = facep->getTEOffset(); - facep->mIndicesIndex = indices_index; - facep->mGeomIndex = index_offset; - facep->mVertexBuffer = group->mVertexBuffer; - if (facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), - index_offset)) + + if (!is_alpha && !LLPipeline::sRenderDeferred) { - buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), - facep->getIndicesStart(), facep->getIndicesCount()); + facep->setPoolType(LLDrawPool::POOL_SIMPLE); + + if (!force_simple && te->getBumpmap()) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } } - index_offset += facep->getGeomCount(); - indices_index += facep->mIndicesCount; - - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - - if (LLPipeline::sRenderGlow && facep->getTextureEntry()->getGlow() > 0.f) + if (LLPipeline::sRenderGlow && te->getGlow() > 0.f) { registerFace(group, facep, LLRenderPass::PASS_GLOW); - } + } + + ++face_iter; } buffer->setBuffer(0); } - else - { - group->mVertexBuffer = NULL; - } - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) { - LLDrawable* drawablep = *drawable_iter; - drawablep->clearState(LLDrawable::REBUILD_ALL); + group->mBufferMap[mask][i->first] = i->second; } - - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | - LLSpatialGroup::ALPHA_DIRTY | LLSpatialGroup::MESH_DIRTY); - - mFaceList.clear(); } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 50f754b882..155775510e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -84,8 +84,8 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | - (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 8ea47387c8..cdda48f6f2 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -52,7 +52,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) + (1 << LLVertexBuffer::TYPE_TEXCOORD0) }; LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 635989e3af..abd25e6598 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -320,7 +320,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); BOOL success = mFanVerts->getVertexStrider(vertices) - && mFanVerts->getTexCoordStrider(texCoords) + && mFanVerts->getTexCoord0Strider(texCoords) && mFanVerts->getIndexStrider(indices); if(!success) @@ -380,7 +380,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) // lock the buffer BOOL success = segment->getVertexStrider(vertices) - && segment->getTexCoordStrider(texCoords) + && segment->getTexCoord0Strider(texCoords) && segment->getIndexStrider(indices); if(!success) diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 4239996017..f11ef97b55 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -111,7 +111,7 @@ LLWorld::LLWorld() : mDefaultWaterTexturep = new LLViewerImage(raw, FALSE); gGL.getTexUnit(0)->bind(mDefaultWaterTexturep.get()); - mDefaultWaterTexturep->setClamp(TRUE, TRUE); + mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -872,7 +872,7 @@ void LLWorld::updateWaterObjects() y + rwidth/2, 256.f+DEFAULT_WATER_HEIGHT)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); - gPipeline.addObject(waterp); + gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); } } @@ -923,7 +923,7 @@ void LLWorld::updateWaterObjects() waterp = mEdgeWaterObjects[dir]; waterp->setUseTexture(FALSE); waterp->setIsEdgePatch(TRUE); - gPipeline.addObject(waterp); + gPipeline.createObject(waterp); } waterp->setRegion(gAgent.getRegion()); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 4d46ff19cc..c9a3bd2112 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -506,9 +506,9 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) new_layer.LayerDefined = TRUE; msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE); - + gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); - new_layer.LayerImage->setClamp(TRUE, TRUE); + new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); U32 left, right, top, bottom; msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block); @@ -618,10 +618,11 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) siminfo->mRegionFlags = region_flags; siminfo->mWaterHeight = (F32) water_height; siminfo->mMapImageID[agent_flags] = image_id; + #ifdef IMMEDIATE_IMAGE_LOAD siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - siminfo->mCurrentImage->setClamp(TRUE, TRUE); + siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); #endif if (siminfo->mMapImageID[2].notNull()) diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 1cf8755e62..db36fa0ffe 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -511,7 +511,7 @@ void LLWorldMapView::draw() { textures_requested_this_tick++; info->mCurrentImage = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); - info->mCurrentImage->setClamp(TRUE, TRUE); + info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); simimage = info->mCurrentImage; gGL.getTexUnit(0)->bind(simimage); } @@ -524,7 +524,7 @@ void LLWorldMapView::draw() { textures_requested_this_tick++; info->mOverlayImage = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE); - info->mOverlayImage->setClamp(TRUE, TRUE); + info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); overlayimage = info->mOverlayImage; gGL.getTexUnit(0)->bind(overlayimage); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 62e337b2d1..3a5e41e3ca 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -139,21 +139,22 @@ LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; //---------------------------------------- - std::string gPoolNames[] = { // Correspond to LLDrawpool enum render type "NONE", "POOL_SIMPLE", - "POOL_TERRAIN", + "POOL_TERRAIN", + "POOL_BUMP", "POOL_TREE", "POOL_SKY", "POOL_WL_SKY", "POOL_GROUND", - "POOL_BUMP", "POOL_INVISIBLE", "POOL_AVATAR", "POOL_WATER", + "POOL_GRASS", + "POOL_FULLBRIGHT", "POOL_GLOW", "POOL_ALPHA", }; @@ -232,10 +233,12 @@ BOOL LLPipeline::sRenderSoundBeacons = FALSE; BOOL LLPipeline::sRenderBeacons = FALSE; BOOL LLPipeline::sRenderHighlight = TRUE; S32 LLPipeline::sUseOcclusion = 0; +BOOL LLPipeline::sDelayVBUpdate = TRUE; BOOL LLPipeline::sFastAlpha = TRUE; BOOL LLPipeline::sDisableShaders = FALSE; BOOL LLPipeline::sRenderBump = TRUE; BOOL LLPipeline::sUseFarClip = TRUE; +BOOL LLPipeline::sShadowRender = FALSE; BOOL LLPipeline::sSkipUpdate = FALSE; BOOL LLPipeline::sWaterReflections = FALSE; BOOL LLPipeline::sRenderGlow = FALSE; @@ -246,6 +249,8 @@ BOOL LLPipeline::sTextureBindTest = FALSE; BOOL LLPipeline::sRenderFrameTest = FALSE; BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; +BOOL LLPipeline::sRenderDeferred = FALSE; +S32 LLPipeline::sVisibleLightCount = 0; static LLCullResult* sCull = NULL; @@ -261,6 +266,13 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); +void addDeferredAttachments(LLRenderTarget& target) +{ + target.addColorAttachment(GL_RGBA16F_ARB); //specular + target.addColorAttachment(GL_RGBA16F_ARB); //normal+z + target.addColorAttachment(GL_RGBA16F_ARB); //position +} + LLPipeline::LLPipeline() : mBackfaceCull(FALSE), mBatchCount(0), @@ -276,9 +288,6 @@ LLPipeline::LLPipeline() : mGeometryChanges(0), mNumVisibleFaces(0), - mCubeBuffer(NULL), - mCubeFrameBuffer(0), - mCubeDepth(0), mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), @@ -293,6 +302,7 @@ LLPipeline::LLPipeline() : mWaterPool(NULL), mGroundPool(NULL), mSimplePool(NULL), + mFullbrightPool(NULL), mInvisiblePool(NULL), mGlowPool(NULL), mBumpPool(NULL), @@ -301,8 +311,7 @@ LLPipeline::LLPipeline() : mLightMovingMask(0), mLightingDetail(0) { - mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0; - mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0; + mNoiseMap = 0; } void LLPipeline::init() @@ -321,6 +330,8 @@ void LLPipeline::init() //create render pass pools getPool(LLDrawPool::POOL_ALPHA); getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_GRASS); + getPool(LLDrawPool::POOL_FULLBRIGHT); getPool(LLDrawPool::POOL_INVISIBLE); getPool(LLDrawPool::POOL_BUMP); getPool(LLDrawPool::POOL_GLOW); @@ -405,6 +416,8 @@ void LLPipeline::cleanup() mGroundPool = NULL; delete mSimplePool; mSimplePool = NULL; + delete mFullbrightPool; + mFullbrightPool = NULL; delete mInvisiblePool; mInvisiblePool = NULL; delete mGlowPool; @@ -456,52 +469,103 @@ void LLPipeline::resizeScreenTexture() GLuint resY = gViewerWindow->getWindowDisplayHeight(); U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); - if (res_mod > 1) + if (res_mod > 1 && res_mod < resX && res_mod < resY) { resX /= res_mod; resY /= res_mod; } - - mScreen.release(); - mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE); + + allocateScreenBuffer(resX,resY); llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl; } } - -void LLPipeline::releaseGLBuffers() +void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { - assertInitialized(); - - if (mCubeBuffer) + U32 samples = gSavedSettings.getU32("RenderFSAASamples"); + if (LLPipeline::sRenderDeferred) { - mCubeBuffer = NULL; + //allocate deferred rendering color buffers + mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + addDeferredAttachments(mDeferredScreen); + mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + + for (U32 i = 0; i < 2; i++) + { + mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } } - - if (mCubeFrameBuffer) + else { - glDeleteFramebuffersEXT(1, &mCubeFrameBuffer); - glDeleteRenderbuffersEXT(1, &mCubeDepth); - mCubeDepth = mCubeFrameBuffer = 0; + mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); } + - if (mBlurCubeBuffer[0]) + if (gGLManager.mHasFramebufferMultisample && samples > 1) { - glDeleteFramebuffersEXT(3, mBlurCubeBuffer); - mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0; + if (LLPipeline::sRenderDeferred) + { + mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + addDeferredAttachments(mSampleBuffer); + mDeferredScreen.setSampleBuffer(&mSampleBuffer); + } + else + { + mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + } + + mScreen.setSampleBuffer(&mSampleBuffer); + stop_glerror(); + } + else if (LLPipeline::sRenderDeferred) + { //share depth buffer between deferred targets + mDeferredScreen.shareDepthBuffer(mScreen); + for (U32 i = 0; i < 2; i++) + { + mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); + } } - if (mBlurCubeTexture[0]) + gGL.getTexUnit(0)->disable(); + + stop_glerror(); + +} + +//static +void LLPipeline::updateRenderDeferred() +{ + BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") && + LLRenderTarget::sUseFBO && + gSavedSettings.getBOOL("VertexShaderEnable") && + gSavedSettings.getBOOL("RenderAvatarVP") && + gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE; + + sRenderDeferred = deferred; +} + +void LLPipeline::releaseGLBuffers() +{ + assertInitialized(); + + if (mNoiseMap) { - glDeleteTextures(3, mBlurCubeTexture); - mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0; + LLImageGL::deleteTextures(1, &mNoiseMap); + mNoiseMap = 0; } mWaterRef.release(); mWaterDis.release(); mScreen.release(); - + mSampleBuffer.releaseSampleBuffer(); + mDeferredScreen.release(); + + + for (U32 i = 0; i < 4; i++) + { + mSunShadow[i].release(); + } for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -514,72 +578,17 @@ void LLPipeline::createGLBuffers() { assertInitialized(); + updateRenderDeferred(); + if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution"); - mWaterRef.allocate(res,res,GL_RGBA,TRUE); - mWaterDis.allocate(res,res,GL_RGBA,TRUE); - -#if 0 //cube map buffers (keep for future work) - { - //reflection map generation buffers - if (mCubeFrameBuffer == 0) - { - glGenFramebuffersEXT(1, &mCubeFrameBuffer); - glGenRenderbuffersEXT(1, &mCubeDepth); - - U32 res = REFLECTION_MAP_RES; - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth); - - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,res,res); - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - } - - if (mCubeBuffer.isNull()) - { - res = 128; - mCubeBuffer = new LLCubeMap(); - mCubeBuffer->initGL(); - mCubeBuffer->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - - if (mBlurCubeBuffer[0] == 0) - { - glGenFramebuffersEXT(3, mBlurCubeBuffer); - } - - if (mBlurCubeTexture[0] == 0) - { - glGenTextures(3, mBlurCubeTexture); - } - - res = (U32) gSavedSettings.getS32("RenderReflectionRes"); - - for (U32 j = 0; j < 3; j++) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j]); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - } -#endif + mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); } + stop_glerror(); if (LLPipeline::sRenderGlow) @@ -589,14 +598,41 @@ void LLPipeline::createGLBuffers() for (U32 i = 0; i < 3; i++) { - mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE); + mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); } - + } - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); + GLuint resX = gViewerWindow->getWindowDisplayWidth(); + GLuint resY = gViewerWindow->getWindowDisplayHeight(); - mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE); + allocateScreenBuffer(resX,resY); + + if (sRenderDeferred) + { + mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE); + + if (!mNoiseMap) + { + const U32 noiseRes = 128; + LLVector3 noise[noiseRes*noiseRes]; + + F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; + for (U32 i = 0; i < noiseRes*noiseRes; ++i) + { + noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + noise[i].normVec(); + noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + } + + LLImageGL::generateTextures(1, &mNoiseMap); + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } } } @@ -627,7 +663,8 @@ void LLPipeline::restoreGL() BOOL LLPipeline::canUseVertexShaders() { - if (!gGLManager.mHasVertexShader || + if (sDisableShaders || + !gGLManager.mHasVertexShader || !gGLManager.mHasFragmentShader || !LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") || (assertInitialized() && mVertexShadersLoaded != 1) ) @@ -785,6 +822,14 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) poolp = mSimplePool; break; + case LLDrawPool::POOL_GRASS: + poolp = mGrassPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + poolp = mFullbrightPool; + break; + case LLDrawPool::POOL_INVISIBLE: poolp = mInvisiblePool; break; @@ -964,19 +1009,61 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) U32 LLPipeline::addObject(LLViewerObject *vobj) { - LLMemType mt(LLMemType::MTYPE_DRAWABLE); if (gNoRender) { return 0; } + if (gSavedSettings.getBOOL("RenderDelayCreation")) + { + mCreateQ.push_back(vobj); + } + else + { + createObject(vobj); + } + + return 1; +} + +void LLPipeline::createObjects(F32 max_dtime) +{ + LLFastTimer ftm(LLFastTimer::FTM_GEO_UPDATE); + LLMemType mt(LLMemType::MTYPE_DRAWABLE); + + LLTimer update_timer; + + while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) + { + LLViewerObject* vobj = mCreateQ.front(); + if (!vobj->isDead()) + { + createObject(vobj); + } + mCreateQ.pop_front(); + } + + //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) + //{ + // createObject(*iter); + //} + + //mCreateQ.clear(); +} + +void LLPipeline::createObject(LLViewerObject* vobj) +{ LLDrawable* drawablep = vobj->mDrawable; if (!drawablep) { drawablep = vobj->createDrawable(this); } - + else + { + llerrs << "Redundant drawable creation!" << llendl; + } + llassert(drawablep); if (vobj->getParent()) @@ -990,7 +1077,14 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); - return 1; + if (drawablep->getVOVolume() && gSavedSettings.getBOOL("RenderAnimateRes")) + { + // fun animated res + drawablep->updateXform(TRUE); + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + drawablep->setScale(LLVector3(0,0,0)); + drawablep->makeActive(); + } } @@ -1195,6 +1289,65 @@ void LLPipeline::grabReferences(LLCullResult& result) sCull = &result; } +BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) +{ + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (part->visibleObjectsInFrustum(camera)) + { + return TRUE; + } + } + } + } + } + + return FALSE; +} + +BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) +{ + min = LLVector3(F32_MAX, F32_MAX, F32_MAX); + max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX); + + + BOOL res = TRUE; + + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (!part->getVisibleExtents(camera, min, max)) + { + res = FALSE; + } + } + } + } + } + + return res; +} + + void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip) { LLFastTimer t(LLFastTimer::FTM_CULL); @@ -1207,6 +1360,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl BOOL to_texture = LLPipeline::sUseOcclusion > 1 && !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !sReflectionRender && + !sShadowRender && gPipeline.canUseVertexShaders() && sRenderGlow; @@ -1217,6 +1371,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl glPushMatrix(); gGLLastMatrix = NULL; + //glLoadMatrixd(gGLModelView); glLoadMatrixd(gGLLastModelView); LLVertexBuffer::unbind(); @@ -1224,7 +1379,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setColorMask(false, false); + if (sUseOcclusion > 1) + { + gGL.setColorMask(false, false); + } + LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -1282,13 +1441,17 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl sCull->pushDrawable(gSky.mVOGroundp->mDrawable); } - gGL.setColorMask(true, false); + glPopMatrix(); + if (sUseOcclusion > 1) + { + gGL.setColorMask(true, false); + } + if (to_texture) { mScreen.flush(); - LLRenderTarget::unbindTarget(); } else if (LLPipeline::sUseOcclusion > 1) { @@ -1357,6 +1520,7 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) void LLPipeline::doOcclusion(LLCamera& camera) { LLVertexBuffer::unbind(); + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { gGL.setColorMask(true, false, false, false); @@ -1525,7 +1689,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) if (!drawablep) { - llerrs << "Sending null drawable to moved list!" << llendl; + //llerrs << "Sending null drawable to moved list!" << llendl; return; } @@ -1595,8 +1759,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) assertInitialized(); glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = FALSE; - + gDepthDirty = TRUE; + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); iter++) { @@ -1772,6 +1936,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) stateSort(drawablep, camera); } } + } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) @@ -2045,6 +2210,22 @@ void LLPipeline::postSort(LLCamera& camera) } LLSpatialGroup::sNoDelete = TRUE; + + const S32 bin_count = 1024*8; + + static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; + static U32 bin_size[bin_count]; + + //clear one bin per frame to avoid memory bloat + static S32 clear_idx = 0; + clear_idx = (1+clear_idx)%bin_count; + alpha_bins[clear_idx].clear(); + + for (U32 j = 0; j < bin_count; j++) + { + bin_size[j] = 0; + } + //build render map for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { @@ -2064,7 +2245,7 @@ void LLPipeline::postSort(LLCamera& camera) sCull->pushDrawInfo(j->first, *k); } } - + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); if (alpha != group->mDrawMap.end()) @@ -2090,28 +2271,26 @@ void LLPipeline::postSort(LLCamera& camera) } } + if (!sShadowRender) { //sort by texture or bump map for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i) { - //if (!mRenderMap[i].empty()) + if (i == LLRenderPass::PASS_BUMP) { - if (i == LLRenderPass::PASS_BUMP) - { - std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump()); - } - else - { - std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix()); - } + std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump()); } + else + { + std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix()); + } } std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } - + // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus - if (gSavedSettings.getBOOL("BeaconAlwaysOn")) + if (gSavedSettings.getBOOL("BeaconAlwaysOn") && !sShadowRender) { if (sRenderScriptedTouchBeacons) { @@ -2164,23 +2343,26 @@ void LLPipeline::postSort(LLCamera& camera) LLFloaterTelehub::addBeacons(); } - mSelectedFaces.clear(); - - // Draw face highlights for selected faces. - if (LLSelectMgr::getInstance()->getTEMode()) + if (!sShadowRender) { - struct f : public LLSelectedTEFunctor + mSelectedFaces.clear(); + + // Draw face highlights for selected faces. + if (LLSelectMgr::getInstance()->getTEMode()) { - virtual bool apply(LLViewerObject* object, S32 te) + struct f : public LLSelectedTEFunctor { - if (object->mDrawable) + virtual bool apply(LLViewerObject* object, S32 te) { - gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + if (object->mDrawable) + { + gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + } + return true; } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + } func; + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + } } LLSpatialGroup::sNoDelete = FALSE; @@ -2328,8 +2510,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) stop_glerror(); gFrameStats.start(LLFrameStats::RENDER_SYNC); - glEnableClientState(GL_VERTEX_ARRAY); - LLVertexBuffer::unbind(); // Do verification of GL state @@ -2379,7 +2559,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } gGL.getTexUnit(0)->bind(LLViewerImage::sDefaultImagep); - LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE); + LLViewerImage::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP); ////////////////////////////////////////////// // @@ -2387,37 +2567,39 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) // // stop_glerror(); - BOOL occlude = sUseOcclusion > 1; - U32 cur_type = 0; - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) - { LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); - gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } } - else if (gSavedSettings.getBOOL("RenderDeferred")) + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); - renderGeomDeferred(); + gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); } else { - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + LLFastTimer t(LLFastTimer::FTM_POOLS); + + // HACK: don't calculate local lights if we're rendering the HUD! + // Removing this check will cause bad flickering when there are + // HUD elements being rendered AND the user is in flycam mode -nyx + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) - { - poolp->prerender(); - } + calcNearbyLights(camera); + setupHWLights(NULL); } - - LLFastTimer t(LLFastTimer::FTM_POOLS); - calcNearbyLights(camera); - setupHWLights(NULL); + BOOL occlude = sUseOcclusion > 1; + U32 cur_type = 0; pool_set_t::iterator iter1 = mPools.begin(); while ( iter1 != mPools.end() ) @@ -2426,7 +2608,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) cur_type = poolp->getType(); - if (occlude && cur_type > LLDrawPool::POOL_AVATAR) + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) { occlude = FALSE; gGLLastMatrix = NULL; @@ -2444,6 +2626,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) for( S32 i = 0; i < poolp->getNumPasses(); i++ ) { + LLVertexBuffer::unbind(); poolp->beginRenderPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -2487,25 +2670,29 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) iter1 = iter2; stop_glerror(); } - } LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd"); LLVertexBuffer::unbind(); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + if (occlude) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + } + } + + LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); - gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); - - if (occlude) - { - occlude = FALSE; - gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); - doOcclusion(camera); - } + stop_glerror(); @@ -2530,7 +2717,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); - if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { // Render debugging beacons. gObjectList.renderObjectBeacons(); @@ -2557,13 +2744,283 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLGLState::checkClientArrays(); } -void LLPipeline::renderGeomDeferred() +void LLPipeline::renderGeomDeferred(LLCamera& camera) { - gDeferredDiffuseProgram.bind(); - gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE); - gDeferredDiffuseProgram.unbind(); + LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); + + LLFastTimer t2(LLFastTimer::FTM_POOLS); + + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); + stop_glerror(); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + stop_glerror(); + + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + + U32 cur_type = 0; + + gGL.setColorMask(true, true); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderDeferred(i); + } + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); + + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + gGL.setColorMask(true, false); +} + +void LLPipeline::renderGeomPostDeferred(LLCamera& camera) +{ + LLFastTimer t(LLFastTimer::FTM_POOLS); + U32 cur_type = 0; + + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + calcNearbyLights(camera); + setupHWLights(NULL); + + gGL.setColorMask(true, false); + + pool_set_t::iterator iter1 = mPools.begin(); + BOOL occlude = LLPipeline::sUseOcclusion > 1; + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + gGL.setColorMask(true, false); + } + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) + { + LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginPostDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderPostDeferred(i); + } + poolp->endPostDeferredPass(i); + LLVertexBuffer::unbind(); + + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); + } + + if (occlude) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + } } +void LLPipeline::renderGeomShadow(LLCamera& camera) +{ + U32 cur_type = 0; + + LLGLEnable cull(GL_CULL_FACE); + + LLVertexBuffer::unbind(); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) + { + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginShadowPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderShadow(i); + } + poolp->endShadowPass(i); + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); +} + + void LLPipeline::addTrianglesDrawn(S32 count) { assertInitialized(); @@ -2621,6 +3078,99 @@ void LLPipeline::renderDebug() } } + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + gGL.color4f(1,1,1,1); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + F32 col[] = + { + 1,1,0, + 0,1,1, + 1,0,1, + 1,1,1, + 1,0,0, + 0,1,0, + 0,0,1, + 0,0,0 + }; + + for (U32 i = 0; i < 8; i++) + { + gGL.color3fv(col+i*3); + + gGL.begin(LLRender::LINES); + + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + + if (i < 4) + { + LLVector3* ext = mShadowExtents[i]; + + LLVector3 box[] = + { + LLVector3(ext[0][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[1][1], ext[1][2]), + LLVector3(ext[0][0], ext[1][1], ext[1][2]), + }; + + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV); + + gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV); + gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV); + + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV); + } + + gGL.end(); + + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + part->renderIntersectingBBoxes(&mShadowCamera[i]); + } + } + } + } + } + } + if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) { // Debug composition layers @@ -2653,6 +3203,7 @@ void LLPipeline::renderDebug() gGL.end(); } } + gGL.flush(); } @@ -2735,7 +3286,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); U32 prim_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i) { @@ -2891,6 +3442,30 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_GRASS: + if (mGrassPool) + { + llassert(0); + llwarns << "Ignoring duplicate grass pool." << llendl; + } + else + { + mGrassPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT: + if (mFullbrightPool) + { + llassert(0); + llwarns << "Ignoring duplicate simple pool." << llendl; + } + else + { + mFullbrightPool = (LLRenderPass*) new_poolp; + } + break; + case LLDrawPool::POOL_INVISIBLE: if (mInvisiblePool) { @@ -3024,6 +3599,16 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mSimplePool = NULL; break; + case LLDrawPool::POOL_GRASS: + llassert(mGrassPool == poolp); + mGrassPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + llassert(mFullbrightPool == poolp); + mFullbrightPool = NULL; + break; + case LLDrawPool::POOL_INVISIBLE: llassert(mInvisiblePool == poolp); mInvisiblePool = NULL; @@ -3117,7 +3702,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) if (for_edit) { - LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f); + LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); LLMatrix4 camera_rot(camera_mat.getMat3()); @@ -3288,6 +3873,10 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { continue; } + if (!sRenderAttachedLights && light && light->isAttachment()) + { + continue; + } new_nearby_lights.insert(Light(drawable, dist, 0.f)); if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) { @@ -4282,11 +4871,11 @@ void LLPipeline::resetVertexBuffers() void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture) { assertInitialized(); + glLoadMatrixd(gGLModelView); gGLLastMatrix = NULL; - glLoadMatrixd(gGLLastModelView); - mSimplePool->renderGroups(type, mask, texture); - gGLLastMatrix = NULL; - glLoadMatrixd(gGLLastModelView); + mSimplePool->pushBatches(type, mask); + glLoadMatrixd(gGLModelView); + gGLLastMatrix = NULL; } void LLPipeline::setUseVBO(BOOL use_vbo) @@ -4334,191 +4923,6 @@ void apply_cube_face_rotation(U32 face) break; } } -void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam) -{ - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - assertInitialized(); - - //render dynamic cube map - U32 type_mask = gPipeline.getRenderTypeMask(); - S32 use_occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - LLPipeline::sSkipUpdate = TRUE; - U32 res = REFLECTION_MAP_RES; - - LLPipeline::sReflectionRender = TRUE; - - gGL.getTexUnit(cube_map->getStage())->bind(cube_map); - gGL.getTexUnit(0)->activate(); - GLint width; - glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width); - if (width != res) - { - cube_map->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - gGL.getTexUnit(cube_map->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - gGL.getTexUnit(cube_map->getStage())->disable(); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - - BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - if (toggle_ui) - { - gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_WATER) | - //(1 << LLPipeline::RENDER_TYPE_BUMP) | - (1 << LLPipeline::RENDER_TYPE_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_TREE) | - //(1 << LLPipeline::RENDER_TYPE_PARTICLES) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | - //(1 << LLPipeline::RENDER_TYPE_STARS) | - //(1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_GRASS) | - (1 << LLPipeline::RENDER_TYPE_VOLUME) | - (1 << LLPipeline::RENDER_TYPE_TERRAIN) | - (1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY) | - (1 << LLPipeline::RENDER_TYPE_GROUND); - - LLDrawPoolWater::sSkipScreenCopy = TRUE; - LLPipeline::sSkipUpdate = TRUE; - cube_mask = cube_mask & type_mask; - gPipeline.setRenderTypeMask(cube_mask); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glViewport(0,0,res,res); - - glClearColor(0,0,0,0); - - LLVector3 origin = cube_cam.getOrigin(); - - gPipeline.calcNearbyLights(cube_cam); - - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, mCubeDepth); - stop_glerror(); - - for (S32 i = 0; i < 6; i++) - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - gl_cube_face[i], cube_map->getGLName(), 0); - validate_framebuffer_object(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.f, 1.f, 0.1f, 1024.f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - apply_cube_face_rotation(i); - - glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]); - cube_cam.setOrigin(origin); - LLViewerCamera::updateFrustumPlanes(cube_cam); - cube_cam.setOrigin(LLViewerCamera::getInstance()->getOrigin()); - static LLCullResult result; - gPipeline.updateCull(cube_cam, result); - gPipeline.stateSort(cube_cam, result); - - glClearColor(0,0,0,0); - gGL.setColorMask(true, true); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - gGL.setColorMask(true, false); - stop_glerror(); - gPipeline.renderGeom(cube_cam); - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - cube_cam.setOrigin(origin); - gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - gViewerWindow->setupViewport(); - - gPipeline.setRenderTypeMask(type_mask); - LLPipeline::sUseOcclusion = use_occlusion; - LLPipeline::sSkipUpdate = FALSE; - - if (toggle_ui) - { - gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - LLDrawPoolWater::sSkipScreenCopy = FALSE; - LLPipeline::sSkipUpdate = FALSE; - LLPipeline::sReflectionRender = FALSE; - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); -} - -//send cube map vertices and texture coordinates -void render_cube_map() -{ - U16 idx[36]; - - idx[0] = 1; idx[1] = 0; idx[2] = 2; //front - idx[3] = 3; idx[4] = 2; idx[5] = 0; - - idx[6] = 4; idx[7] = 5; idx[8] = 1; //top - idx[9] = 0; idx[10] = 1; idx[11] = 5; - - idx[12] = 5; idx[13] = 4; idx[14] = 6; //back - idx[15] = 7; idx[16] = 6; idx[17] = 4; - - idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom - idx[21] = 2; idx[22] = 3; idx[23] = 7; - - idx[24] = 0; idx[25] = 5; idx[26] = 3; //left - idx[27] = 6; idx[28] = 3; idx[29] = 5; - - idx[30] = 4; idx[31] = 1; idx[32] = 7; //right - idx[33] = 2; idx[34] = 7; idx[35] = 1; - - LLVector3 vert[8]; - LLVector3 r = LLVector3(1,1,1); - - vert[0] = r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front - vert[1] = r.scaledVec(LLVector3(1,1,1)); // 1 - right top front - vert[2] = r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front - vert[3] = r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front - - vert[4] = r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back - vert[5] = r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back - vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back - vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(3, GL_FLOAT, 0, vert); - glVertexPointer(3, GL_FLOAT, 0, vert); - - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (GLushort*) idx); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} void validate_framebuffer_object() { @@ -4547,132 +4951,12 @@ void validate_framebuffer_object() } } -void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out) -{ - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - assertInitialized(); - - U32 res = (U32) gSavedSettings.getS32("RenderReflectionRes"); - enableLightsFullbright(LLColor4::white); - LLGLDepthTest depth(GL_FALSE); - gGL.setColorMask(true, true); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - cube_out->enableTexture(0); - gGL.getTexUnit(cube_out->getStage())->bind(cube_out); - gGL.getTexUnit(0)->activate(); - GLint width; - glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width); - if (width != res) - { - cube_out->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - gGL.getTexUnit(cube_out->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - gGL.getTexUnit(0)->activate(); - glViewport(0, 0, res, res); - LLGLEnable blend(GL_BLEND); - - S32 kernel = 2; - F32 step = 90.f/res; - F32 alpha = 1.f / ((kernel*2)+1); - - gGL.color4f(alpha,alpha,alpha,alpha*1.25f); - - LLVector3 axis[] = - { - LLVector3(1,0,0), - LLVector3(0,1,0), - LLVector3(0,0,1) - }; - - stop_glerror(); - glViewport(0,0,res, res); - gGL.setSceneBlendType(LLRender::BT_ADD); - cube_in->enableTexture(0); - //3-axis blur - for (U32 j = 0; j < 3; j++) - { - stop_glerror(); - - if (j == 0) - { - gGL.getTexUnit(cube_in->getStage())->bind(cube_in); - } - else - { - gGL.getTexUnit(cube_in->getStage())->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j-1]); - } - gGL.getTexUnit(0)->activate(); - - stop_glerror(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mBlurCubeBuffer[j]); - stop_glerror(); - - for (U32 i = 0; i < 6; i++) - { - stop_glerror(); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, - gl_cube_face[i], - j < 2 ? mBlurCubeTexture[j] : cube_out->getGLName(), 0); - validate_framebuffer_object(); - gGL.setColorMask(true, true); - glClear(GL_COLOR_BUFFER_BIT); - glLoadIdentity(); - apply_cube_face_rotation(i); - for (S32 x = -kernel; x <= kernel; ++x) - { - glPushMatrix(); - glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]); - render_cube_map(); - glPopMatrix(); - } - stop_glerror(); - } - } - - stop_glerror(); - - gGL.getTexUnit(cube_in->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - gGL.setColorMask(true, false); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - gGL.getTexUnit(cube_in->getStage())->disable(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gViewerWindow->setupViewport(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); -} - void LLPipeline::bindScreenToTexture() { } -void LLPipeline::renderBloom(BOOL for_snapshot) +void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { if (!(gPipeline.canUseVertexShaders() && sRenderGlow)) @@ -4694,8 +4978,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot) U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); LLVector2 tc1(0,0); - LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); + LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth()*2, + (F32) gViewerWindow->getWindowDisplayHeight()*2); if (res_mod > 1) { @@ -4732,9 +5016,22 @@ void LLPipeline::renderBloom(BOOL for_snapshot) //glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF); //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //LLGLDisable blend(GL_BLEND); + + // If the snapshot is constructed from tiles, calculate which + // tile we're in. + const S32 num_horizontal_tiles = llceil(zoom_factor); + const LLVector2 tile(subfield % num_horizontal_tiles, + (S32)(subfield / num_horizontal_tiles)); + llassert(zoom_factor > 0.0); // Non-zero, non-negative. + const F32 tile_size = 1.0/zoom_factor; + + tc1 = tile*tile_size; // Top left texture coordinates + tc2 = (tile+LLVector2(1,1))*tile_size; // Bottom right texture coordinates + LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ADD); - tc2.setVec(1,1); + + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.color4f(1,1,1,1); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); @@ -4748,6 +5045,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); gGL.vertex2f(1,1); + gGL.end(); gGL.flush(); @@ -4771,7 +5069,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } gGlowExtractProgram.bind(); - F32 minLum = llclamp(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f, 1.0f); + F32 minLum = llmax(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f); F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); @@ -4798,13 +5096,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.vertex2f(-1,-1); gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); + gGL.vertex2f(-1,3); gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); + gGL.vertex2f(3,-1); - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); gGL.end(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); @@ -4813,7 +5109,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } tc1.setVec(0,0); - tc2.setVec(1,1); + tc2.setVec(2,2); @@ -4867,13 +5163,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.vertex2f(-1,-1); gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); + gGL.vertex2f(-1,3); gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); + gGL.vertex2f(3,-1); - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); gGL.end(); mGlow[i%2].flush(); @@ -4889,81 +5183,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gViewerWindow->setupViewport(); - /*mGlow[1].bindTexture(); - { - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - LLGLDisable blend(GL_BLEND); - - gGL.begin(LLVertexBuffer::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); - - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); - gGL.end(); - - gGL.flush(); - } - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW)) - { - tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); - - if (res_mod > 1) - { - tc2 /= (F32) res_mod; - } - - LLGLEnable blend(GL_BLEND); - gGL.blendFunc(GL_ONE, GL_ONE); - - gGL.getTexUnit(0)->disable(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); - mScreen.bindTexture(); - - gGL.begin(LLVertexBuffer::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); - - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); - gGL.end(); - - gGL.flush(); - - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - }*/ gGL.flush(); { LLVertexBuffer::unbind(); - F32 uv0[] = - { - tc1.mV[0], tc1.mV[1], - tc1.mV[0], tc2.mV[1], - tc2.mV[0], tc1.mV[1], - tc2.mV[0], tc2.mV[1] - }; + tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), (F32) gViewerWindow->getWindowDisplayHeight()); @@ -4973,55 +5198,56 @@ void LLPipeline::renderBloom(BOOL for_snapshot) tc2 /= (F32) res_mod; } - F32 uv1[] = - { - tc1.mV[0], tc1.mV[1], - tc1.mV[0], tc2.mV[1], - tc2.mV[0], tc1.mV[1], - tc2.mV[0], tc2.mV[1] - }; + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; + LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0); + buff->allocateBuffer(3,0,TRUE); - F32 v[] = - { - -1,-1, - -1,1, - 1,-1, - 1,1 - }; + LLStrider<LLVector3> v; + LLStrider<LLVector2> uv1; + LLStrider<LLVector2> uv2; + + buff->getVertexStrider(v); + buff->getTexCoord0Strider(uv1); + buff->getTexCoord1Strider(uv2); + uv1[0] = LLVector2(0, 0); + uv1[1] = LLVector2(0, 2); + uv1[2] = LLVector2(2, 0); + + uv2[0] = LLVector2(0, 0); + uv2[1] = LLVector2(0, tc2.mV[1]*2.f); + uv2[2] = LLVector2(tc2.mV[0]*2.f, 0); + + v[0] = LLVector3(-1,-1,0); + v[1] = LLVector3(-1,3,0); + v[2] = LLVector3(3,-1,0); + + buff->setBuffer(0); + LLGLDisable blend(GL_BLEND); //tex unit 0 gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); gGL.getTexUnit(0)->bind(&mGlow[1]); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, uv0); gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE); //tex unit 1 gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, uv1); - - glVertexPointer(2, GL_FLOAT, 0, v); - gGL.getTexUnit(1)->bind(&mScreen); gGL.getTexUnit(1)->activate(); LLGLEnable multisample(GL_MULTISAMPLE_ARB); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + buff->setBuffer(mask); + buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); gGL.getTexUnit(1)->disable(); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } @@ -5038,6 +5264,515 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) +{ + shader.bind(); + S32 channel = 0; + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(0,channel); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(1, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(2, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(3, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + } + + stop_glerror(); + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[light_index].bindTexture(0, channel); + } + + stop_glerror(); + + for (U32 i = 0; i < 4; i++) + { + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i); + stop_glerror(); + if (channel > -1) + { + stop_glerror(); + gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + stop_glerror(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + stop_glerror(); + } + } + + stop_glerror(); + + F32 mat[64]; + for (U32 i = 0; i < 16; i++) + { + mat[i] = mSunShadowMatrix[0].m[i]; + mat[i+16] = mSunShadowMatrix[1].m[i]; + mat[i+32] = mSunShadowMatrix[2].m[i]; + mat[i+48] = mSunShadowMatrix[3].m[i]; + } + + shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat); + + stop_glerror(); + + channel = shader.enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->enable(channel); + cube_map->bind(); + F64* m = gGLModelView; + + + F32 mat[] = { m[0], m[1], m[2], + m[4], m[5], m[6], + m[8], m[9], m[10] }; + + shader.uniform3fv("env_mat[0]", 3, mat); + shader.uniform3fv("env_mat", 3, mat); + } + } + + shader.uniform4fv("shadow_clip", 1, mSunClipPlanes.mV); + shader.uniform1f("sun_wash", gSavedSettings.getF32("RenderDeferredSunWash")); + shader.uniform1f("shadow_noise", gSavedSettings.getF32("RenderShadowNoise")); + shader.uniform1f("blur_size", gSavedSettings.getF32("RenderShadowBlurSize")); + + shader.uniform1f("ssao_radius", gSavedSettings.getF32("RenderSSAOScale")); + shader.uniform1f("ssao_max_radius", gSavedSettings.getU32("RenderSSAOMaxScale")); + + F32 ssao_factor = gSavedSettings.getF32("RenderSSAOFactor"); + shader.uniform1f("ssao_factor", ssao_factor); + shader.uniform1f("ssao_factor_inv", 1.0/ssao_factor); + + LLVector3 ssao_effect = gSavedSettings.getVector3("RenderSSAOEffect"); + F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; + F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; + // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by + // value factor, and scales remainder by saturation factor + F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, + matrix_nondiag, matrix_diag, matrix_nondiag, + matrix_nondiag, matrix_nondiag, matrix_diag}; + shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat); + + shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); + shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); + shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); +} + +void LLPipeline::renderDeferredLighting() +{ + if (!sCull) + { + return; + } + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + //ati doesn't seem to love actually using the stencil buffer on FBO's + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gGL.setColorMask(true, true); + + mDeferredLight[0].bindTarget(); + + //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + //draw a cube around every light + LLVertexBuffer::unbind(); + + glBlendFunc(GL_ONE, GL_ONE); + LLGLEnable cull(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + + glh::matrix4f mat = glh_copy_matrix(gGLModelView); + + F32 vert[] = + { + -1,1, + -1,-3, + 3,1, + }; + + bindDeferredShader(gDeferredSunProgram); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv("offset", slice, offset); + gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + + setupHWLights(NULL); //to set mSunDir; + + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + LLVector4 dir(mSunDir, 0.f); + + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); + glColor3f(1,1,1); + + glVertexPointer(2, GL_FLOAT, 0, vert); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + + mDeferredLight[0].flush(); + + //blur lightmap + mDeferredLight[1].bindTarget(); + + //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + bindDeferredShader(gDeferredBlurLightProgram); + + LLVector3 gauss[32]; // xweight, yweight, offset + + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = -(kern_length/2.0f) + 0.5f; + + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go.mV[0]); + gauss[i].mV[1] = llgaussian(x, go.mV[1]); + gauss[i].mV[2] = x; + x += 1.f; + } + /* swap the x=0 position to the start of gauss[] so we can + treat it specially as an optimization. */ + LLVector3 swap; + swap = gauss[kern_length/2]; + gauss[kern_length/2] = gauss[0]; + gauss[0] = swap; + llassert(gauss[0].mV[2] == 0.0f); + + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); + + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + stop_glerror(); + } + mDeferredLight[0].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + stop_glerror(); + glPopMatrix(); + stop_glerror(); + glMatrixMode(GL_MODELVIEW); + stop_glerror(); + glPopMatrix(); + stop_glerror(); + + //copy depth and stencil from deferred screen + //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + mScreen.bindTarget(); + mScreen.clear(GL_COLOR_BUFFER_BIT); + + bindDeferredShader(gDeferredSoftenProgram); + { + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glVertexPointer(2, GL_FLOAT, 0, vert); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + + unbindDeferredShader(gDeferredSoftenProgram); + + bindDeferredShader(gDeferredLightProgram); + + std::list<LLVector4> fullscreen_lights; + std::list<LLVector4> light_colors; + + F32 v[24]; + glVertexPointer(3, GL_FLOAT, 0, v); + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + { + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + if (!volume) + { + continue; + } + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) + { + continue; + } + + sVisibleLightCount++; + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + //vertex positions are encoded so the 3 bits of their vertex index + //correspond to their axis facing, with bit position 3,2,1 matching + //axis facing x,y,z, bit set meaning positive facing, bit clear + //meaning negative facing + v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 + v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 + v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 + v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 + + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 + v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 + v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 + v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 + + if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) + { //draw box if camera is outside box + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); + } + else + { + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + } + } + } + + unbindDeferredShader(gDeferredLightProgram); + + if (!fullscreen_lights.empty()) + { + bindDeferredShader(gDeferredMultiLightProgram); + LLGLDepthTest depth(GL_FALSE); + + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + U32 count = 0; + + LLVector4 light[16]; + LLVector4 col[16]; + + glVertexPointer(2, GL_FLOAT, 0, vert); + + while (!fullscreen_lights.empty()) + { + light[count] = fullscreen_lights.front(); + fullscreen_lights.pop_front(); + col[count] = light_colors.front(); + light_colors.pop_front(); + + count++; + if (count == 16 || fullscreen_lights.empty()) + { + gDeferredMultiLightProgram.uniform1i("light_count", count); + gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); + gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); + count = 0; + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + } + } + + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + unbindDeferredShader(gDeferredMultiLightProgram); + } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + { //render non-deferred geometry + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + + U32 render_mask = mRenderTypeMask; + mRenderTypeMask = mRenderTypeMask & + ((1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + (1 << LLPipeline::RENDER_TYPE_WL_SKY) | + (1 << LLPipeline::RENDER_TYPE_ALPHA) | + (1 << LLPipeline::RENDER_TYPE_AVATAR) | + (1 << LLPipeline::RENDER_TYPE_WATER) | + (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_VOLUME) | + (1 << LLPipeline::RENDER_TYPE_GLOW) | + (1 << LLPipeline::RENDER_TYPE_BUMP)); + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + mRenderTypeMask = render_mask; + } + + mScreen.flush(); + +} + +void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) +{ + stop_glerror(); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + for (U32 i = 0; i < 4; i++) + { + if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + } + } + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + + S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->disable(); + } + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->activate(); + shader.unbind(); +} + inline float sgn(float a) { if (a > 0.0F) return (1.0F); @@ -5049,6 +5784,16 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate) { + LLVOAvatar* agent = gAgent.getAvatarObject(); + if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) + { + agent = NULL; + } + + if (agent) + { + agent->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON); + } LLVertexBuffer::unbind(); LLGLState::checkStates(); @@ -5060,6 +5805,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPipeline::sReflectionRender = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = llmin(occlusion, 1); + U32 type_mask = gPipeline.mRenderTypeMask; glh::matrix4f projection = glh_get_current_projection(); @@ -5127,15 +5873,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) //initial sky pass (no user clip plane) { //mask out everything but the sky U32 tmp = mRenderTypeMask; - mRenderTypeMask &= ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | (1 << LLPipeline::RENDER_TYPE_WL_SKY)); - static LLCullResult result; updateCull(camera, result); stateSort(camera, result); + mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + (1 << LLPipeline::RENDER_TYPE_WL_SKY)); renderGeom(camera, TRUE); - mRenderTypeMask = tmp; } @@ -5227,6 +5973,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; LLRenderTarget::unbindTarget(); + LLPipeline::sReflectionRender = FALSE; if (!LLRenderTarget::sUseFBO) @@ -5245,9 +5992,424 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); + + if (agent) + { + agent->updateAttachmentVisibility(gAgent.getCameraMode()); + } } } +glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) +{ + glh::matrix4f ret; + + LLVector3 dirN; + LLVector3 upN; + LLVector3 lftN; + + lftN = dir % up; + lftN.normVec(); + + upN = lftN % dir; + upN.normVec(); + + dirN = dir; + dirN.normVec(); + + + ret.m[ 0] = lftN[0]; + ret.m[ 1] = upN[0]; + ret.m[ 2] = -dirN[0]; + ret.m[ 3] = 0.f; + + ret.m[ 4] = lftN[1]; + ret.m[ 5] = upN[1]; + ret.m[ 6] = -dirN[1]; + ret.m[ 7] = 0.f; + + ret.m[ 8] = lftN[2]; + ret.m[ 9] = upN[2]; + ret.m[10] = -dirN[2]; + ret.m[11] = 0.f; + + ret.m[12] = -(lftN*pos); + ret.m[13] = -(upN*pos); + ret.m[14] = dirN*pos; + ret.m[15] = 1.f; + + return ret; +} + +glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) +{ + glh::matrix4f ret; + ret.m[ 0] = 2/(max[0]-min[0]); + ret.m[ 4] = 0; + ret.m[ 8] = 0; + ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); + + ret.m[ 1] = 0; + ret.m[ 5] = 2/(max[1]-min[1]); + ret.m[ 9] = 0; + ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); + + ret.m[ 2] = 0; + ret.m[ 6] = 0; + ret.m[10] = 2/(max[2]-min[2]); + ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); + + ret.m[ 3] = 0; + ret.m[ 7] = 0; + ret.m[11] = 0; + ret.m[15] = 1; + + return ret; +} + +void LLPipeline::generateSunShadow(LLCamera& camera) +{ + + if (!sRenderDeferred) + { + return; + } + + //temporary hack to disable shadows but keep local lights + static BOOL clear = TRUE; + BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); + if (!gen_shadow) + { + if (clear) + { + clear = FALSE; + for (U32 i = 0; i < 4; i++) + { + mSunShadow[i].bindTarget(); + mSunShadow[i].clear(); + mSunShadow[i].flush(); + } + } + return; + } + clear = TRUE; + + gGL.setColorMask(false, false); + + //get sun view matrix + + F32 range = 128.f; + + //store current projection/modelview matrix + glh::matrix4f saved_proj = glh_get_current_projection(); + glh::matrix4f saved_view = glh_get_current_modelview(); + glh::matrix4f inv_view = saved_view.inverse(); + + glh::matrix4f view[4]; + glh::matrix4f proj[4]; + LLVector3 up; + + //clip contains parallel split distances for 3 splits + LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes"); + + //far clip on last split is minimum of camera view distance and 128 + mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]); + + const LLPickInfo& pick_info = gViewerWindow->getLastPick(); + + if (!pick_info.mPosGlobal.isExactlyZero()) + { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object + F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec(); + mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]); + } + + // convenience array of 4 near clip plane distances + F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; + + //currently used for amount to extrude frusta corners for constructing shadow frusta + LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist"); + F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; + + for (S32 j = 0; j < 4; j++) + { + //restore render matrices + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); + + //get center of far clip plane (for point of interest later) + LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range; + + LLVector3 eye = camera.getOrigin(); + + //camera used for shadow cull/render + LLCamera shadow_cam; + + // perspective shadow map + glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space) + glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space) + + LLVector3 lightDir = -mSunDir; + glh::vec3f light_dir(lightDir.mV); + + //create light space camera matrix + LLVector3 at; + F32 dl = camera.getLeftAxis() * lightDir; + F32 du = camera.getUpAxis() * lightDir; + + //choose an at axis such that up will be most aligned with lightDir + if (dl*dl < du*du) + { + at = lightDir%camera.getLeftAxis(); + } + else + { + at = lightDir%camera.getUpAxis(); + } + + if (at * camera.getAtAxis() < 0) + { + at = -at; + } + + LLVector3 left = lightDir%at; + up = left%lightDir; + up.normVec(); + + //create world space camera frustum for this split + shadow_cam = camera; + shadow_cam.setFar(16.f); + + LLViewerCamera::updateFrustumPlanes(shadow_cam); + + LLVector3* frust = shadow_cam.mAgentFrustum; + + LLVector3 pn = shadow_cam.getAtAxis(); + + LLVector3 frust_center; + + LLVector3 min, max; + + //construct 8 corners of split frustum section + for (U32 i = 0; i < 4; i++) + { + LLVector3 delta = frust[i+4]-eye; + delta.normVec(); + F32 dp = delta*pn; + frust[i] = eye + (delta*dist[j])/dp; + frust[i+4] = eye + (delta*dist[j+1])/dp; + frust_center += frust[i] + frust[i+4]; + } + + //get frustum center + frust_center /= 8.f; + + shadow_cam.calcAgentFrustumPlanes(frust); + + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowCamera[j] = shadow_cam; + } + + if (gPipeline.getVisibleExtents(shadow_cam, min, max)) + { + //no possible shadow receivers + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowExtents[j][0] = LLVector3(); + mShadowExtents[j][1] = LLVector3(); + mShadowCamera[j+4] = shadow_cam; + } + + continue; + } + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowExtents[j][0] = min; + mShadowExtents[j][1] = max; + } + + view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up); + F32 shadow_dist = nearDist[j]; + + for (U32 i = 0; i < 8; i++) + { + //points in worldspace (wp) and light camera space (p) + //that must be included in shadow generation + wp[i] = glh::vec3f(frust[i].mV); + wp[i+8] = wp[i] - light_dir*shadow_dist; + view[j].mult_matrix_vec(wp[i], p[i]); + view[j].mult_matrix_vec(wp[i+8], p[i+8]); + } + + min = LLVector3(p[0].v); + max = LLVector3(p[0].v); + + LLVector3 fmin = min; + LLVector3 fmax = max; + + for (U32 i = 1; i < 16; i++) + { //find camera space AABB of frustum in light camera space + update_min_max(min, max, LLVector3(p[i].v)); + if (i < 8) + { + update_min_max(fmin, fmax, LLVector3(p[i].v)); + } + } + + //generate perspective matrix that contains frustum + //proj[j] = matrix_perspective(min, max); + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + + shadow_cam.setFar(128.f); + shadow_cam.setOriginAndLookAt(eye, up, center); + + glh_set_current_modelview(view[j]); + glh_set_current_projection(proj[j]); + + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + + proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0], + fmin.mV[1], fmax.mV[1], + -fmax.mV[2], -fmin.mV[2]); + + //translate and scale to from [-1, 1] to [0, 1] + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); + + glh_set_current_modelview(view[j]); + glh_set_current_projection(proj[j]); + + mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; + + U32 type_mask = mRenderTypeMask; + mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_ALPHA) | + (1<<LLPipeline::RENDER_TYPE_GRASS) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1<<LLPipeline::RENDER_TYPE_BUMP) | + (1<<LLPipeline::RENDER_TYPE_VOLUME) | + (1<<LLPipeline::RENDER_TYPE_AVATAR) | + (1<<LLPipeline::RENDER_TYPE_TREE) | + (1<<LLPipeline::RENDER_TYPE_TERRAIN) | + 0); + + //clip out geometry on the same side of water as the camera + static LLCullResult result; + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 1; + LLPipeline::sShadowRender = TRUE; + //hack to prevent LOD updates from using sun camera origin + shadow_cam.setOrigin(camera.getOrigin()); + updateCull(shadow_cam, result); + stateSort(shadow_cam, result); + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + mShadowCamera[j+4] = shadow_cam; + } + + LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + + stop_glerror(); + + mSunShadow[j].bindTarget(); + mSunShadow[j].getViewport(gGLViewport); + + { + LLGLDepthTest depth(GL_TRUE); + mSunShadow[j].clear(); + } + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; + LLGLEnable cull(GL_CULL_FACE); + + //generate sun shadow map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj[j].m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view[j].m); + + stop_glerror(); + gGLLastMatrix = NULL; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + glColor4f(1,1,1,1); + + glCullFace(GL_FRONT); + + stop_glerror(); + + gGL.setColorMask(false, false); + + gDeferredShadowProgram.bind(); + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->disable(); + for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) + { + renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + } + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLGLEnable test(GL_ALPHA_TEST); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); + glColor4f(1,1,1,1); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + gDeferredShadowProgram.unbind(); + + renderGeomShadow(shadow_cam); + + gGL.setColorMask(true, true); + + glCullFace(GL_BACK); + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; + mRenderTypeMask = type_mask; + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + mSunShadow[j].flush(); + } + + if (!gSavedSettings.getBOOL("CameraOffset")) + { + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); + } + else + { + glh_set_current_modelview(view[1]); + glh_set_current_projection(proj[1]); + glLoadMatrixf(view[1].m); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj[1].m); + glMatrixMode(GL_MODELVIEW); + } + gGL.setColorMask(true, false); +} + void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) { for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) @@ -5265,6 +6427,10 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu void LLPipeline::generateImpostor(LLVOAvatar* avatar) { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + static LLCullResult result; result.clear(); grabReferences(result); @@ -5290,6 +6456,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) (1<<LLPipeline::RENDER_TYPE_BUMP) | (1<<LLPipeline::RENDER_TYPE_GRASS) | (1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1<<LLPipeline::RENDER_TYPE_ALPHA) | (1<<LLPipeline::RENDER_TYPE_INVISIBLE); } @@ -5300,7 +6467,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) S32 occlusion = sUseOcclusion; sUseOcclusion = 0; - sReflectionRender = TRUE; + sReflectionRender = sRenderDeferred ? FALSE : TRUE; sImpostorRender = TRUE; markVisible(avatar->mDrawable, *LLViewerCamera::getInstance()); @@ -5377,10 +6544,17 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE); + if (LLPipeline::sRenderDeferred) + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE); + addDeferredAttachments(avatar->mImpostor); + } + else + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE); + } gGL.getTexUnit(0)->bind(&avatar->mImpostor); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -5388,8 +6562,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, resX, resY); avatar->mImpostor.bindTarget(); - avatar->mImpostor.getViewport(gGLViewport); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + avatar->mImpostor.clear(); } LLGLEnable stencil(GL_STENCIL_TEST); @@ -5397,11 +6570,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - renderGeom(camera); + if (LLPipeline::sRenderDeferred) + { + stop_glerror(); + renderGeomDeferred(camera); + } + else + { + renderGeom(camera); + } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFFFFFF); + if (!sRenderDeferred || muted) { LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f; LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f; @@ -5432,7 +6614,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.end(); gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -5454,6 +6635,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->mNeedsImpostorUpdate = FALSE; avatar->cacheImpostorValues(); + + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } BOOL LLPipeline::hasRenderBatches(const U32 type) const diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5ab3831753..e8673c7d4c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -57,6 +57,7 @@ class LLRenderFunc; class LLCubeMap; class LLCullResult; class LLVOAvatar; +class LLGLSLShader; typedef enum e_avatar_skinning_method { @@ -75,6 +76,7 @@ glh::matrix4f glh_get_current_projection(); void glh_set_current_projection(glh::matrix4f& mat); glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar); glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar); +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up); class LLPipeline { @@ -88,14 +90,13 @@ public: void resizeScreenTexture(); void releaseGLBuffers(); void createGLBuffers(); + void allocateScreenBuffer(U32 resX, U32 resY); void resetVertexBuffers(LLDrawable* drawable); void setUseVBO(BOOL use_vbo); void generateImpostor(LLVOAvatar* avatar); - void generateReflectionMap(LLCubeMap* cube_map, LLCamera& camera); - void blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out); void bindScreenToTexture(); - void renderBloom(BOOL for_snapshot); + void renderBloom(BOOL for_snapshot, F32 zoom_factor = 1.f, int subfield = 0); void init(); void cleanup(); @@ -176,7 +177,11 @@ public: void updateMoveNormalAsync(LLDrawable* drawablep); void updateMovedList(LLDrawable::drawable_vector_t& move_list); void updateMove(); + BOOL visibleObjectsInFrustum(LLCamera& camera); + BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane + void createObjects(F32 max_dtime); + void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); //calculate pixel area of given box from vantage point of given camera @@ -195,9 +200,15 @@ public: void grabReferences(LLCullResult& result); void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE); - void renderGeomDeferred(); - + void renderGeomDeferred(LLCamera& camera); + void renderGeomPostDeferred(LLCamera& camera); + void renderGeomShadow(LLCamera& camera); + void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0); + void unbindDeferredShader(LLGLSLShader& shader); + void renderDeferredLighting(); + void generateWaterReflection(LLCamera& camera); + void generateSunShadow(LLCamera& camera); void renderHighlights(); void renderDebug(); @@ -230,7 +241,7 @@ public: LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); - + void addTrianglesDrawn(S32 count); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; } BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } @@ -276,6 +287,8 @@ public: static void toggleRenderHighlights(void* data); static BOOL getRenderHighlights(void* data); + static void updateRenderDeferred(); + private: void unloadShaders(); void addToQuickLookup( LLDrawPool* new_poolp ); @@ -295,6 +308,8 @@ public: RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, @@ -306,7 +321,6 @@ public: // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES, RENDER_TYPE_VOLUME, - RENDER_TYPE_GRASS, RENDER_TYPE_PARTICLES, RENDER_TYPE_CLOUDS, }; @@ -326,24 +340,26 @@ public: enum LLRenderDebugMask { - RENDER_DEBUG_COMPOSITION = 0x000020, - RENDER_DEBUG_VERIFY = 0x000080, - RENDER_DEBUG_BBOXES = 0x000200, - RENDER_DEBUG_OCTREE = 0x000400, - RENDER_DEBUG_PICKING = 0x000800, - RENDER_DEBUG_OCCLUSION = 0x001000, - RENDER_DEBUG_POINTS = 0x002000, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x004000, - RENDER_DEBUG_TEXTURE_AREA = 0x008000, - RENDER_DEBUG_FACE_AREA = 0x010000, - RENDER_DEBUG_PARTICLES = 0x020000, - RENDER_DEBUG_GLOW = 0x040000, - RENDER_DEBUG_TEXTURE_ANIM = 0x080000, - RENDER_DEBUG_LIGHTS = 0x100000, - RENDER_DEBUG_BATCH_SIZE = 0x200000, - RENDER_DEBUG_RAYCAST = 0x400000, - RENDER_DEBUG_SHAME = 0x800000, - RENDER_DEBUG_SCULPTED = 0x1000000 + RENDER_DEBUG_COMPOSITION = 0x0000001, + RENDER_DEBUG_VERIFY = 0x0000002, + RENDER_DEBUG_BBOXES = 0x0000004, + RENDER_DEBUG_OCTREE = 0x0000008, + RENDER_DEBUG_PICKING = 0x0000010, + RENDER_DEBUG_OCCLUSION = 0x0000020, + RENDER_DEBUG_POINTS = 0x0000040, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x0000080, + RENDER_DEBUG_TEXTURE_AREA = 0x0000100, + RENDER_DEBUG_FACE_AREA = 0x0000200, + RENDER_DEBUG_PARTICLES = 0x0000400, + RENDER_DEBUG_GLOW = 0x0000800, + RENDER_DEBUG_TEXTURE_ANIM = 0x0001000, + RENDER_DEBUG_LIGHTS = 0x0002000, + RENDER_DEBUG_BATCH_SIZE = 0x0004000, + RENDER_DEBUG_ALPHA_BINS = 0x0008000, + RENDER_DEBUG_RAYCAST = 0x0010000, + RENDER_DEBUG_SHAME = 0x0020000, + RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000, + RENDER_DEBUG_SCULPTED = 0x0080000, }; public: @@ -376,11 +392,13 @@ public: static BOOL sShowHUDAttachments; static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write + static BOOL sDelayVBUpdate; static BOOL sFastAlpha; static BOOL sDisableShaders; // if TRUE, rendering will be done without shaders static BOOL sRenderBump; static BOOL sUseFBO; static BOOL sUseFarClip; + static BOOL sShadowRender; static BOOL sSkipUpdate; //skip lod updates static BOOL sWaterReflections; static BOOL sDynamicLOD; @@ -393,10 +411,22 @@ public: static BOOL sRenderFrameTest; static BOOL sRenderAttachedLights; static BOOL sRenderAttachedParticles; - + static BOOL sRenderDeferred; + static S32 sVisibleLightCount; + //screen texture LLRenderTarget mScreen; - + LLRenderTarget mDeferredScreen; + LLRenderTarget mDeferredLight[2]; + LLMultisampleBuffer mSampleBuffer; + + //sun shadow map + LLRenderTarget mSunShadow[4]; + LLCamera mShadowCamera[8]; + LLVector3 mShadowExtents[4][2]; + glh::matrix4f mSunShadowMatrix[4]; + LLVector4 mSunClipPlanes; + LLVector2 mScreenScale; //water reflection texture @@ -408,20 +438,9 @@ public: //texture for making the glow LLRenderTarget mGlow[3]; - //dynamic cube map scratch space - LLPointer<LLCubeMap> mCubeBuffer; - - //cube map anti-aliasing buffers - GLuint mBlurCubeBuffer[3]; - GLuint mBlurCubeTexture[3]; + //noise map + U32 mNoiseMap; - //frambuffer object for rendering dynamic cube maps - GLuint mCubeFrameBuffer; - - //depth buffer object for rendering dynamic cube maps - GLuint mCubeDepth; - - LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -481,6 +500,7 @@ protected: // LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority + LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mActiveQ; @@ -525,6 +545,8 @@ protected: LLDrawPool* mWaterPool; LLDrawPool* mGroundPool; LLRenderPass* mSimplePool; + LLRenderPass* mGrassPool; + LLRenderPass* mFullbrightPool; LLDrawPool* mInvisiblePool; LLDrawPool* mGlowPool; LLDrawPool* mBumpPool; diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index f249f53105..249787ad8d 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -260,6 +260,12 @@ class WindowsManifest(ViewerManifest): "../win_updater/relwithdebinfo/windows-updater.exe"), dst="updater.exe") + # For google-perftools tcmalloc allocator. + #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + # self.path("libtcmalloc_minimal.dll") + # self.end_prefix() + + def nsi_file_commands(self, install=True): def wpath(path): if path.endswith('/') or path.endswith(os.path.sep): diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 3490ad6f68..01c291be7b 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -118,8 +118,8 @@ target_link_libraries(test if (WINDOWS) set_target_properties(test PROPERTIES - LINK_FLAGS "/NODEFAULTLIB:MSVCRT" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" ) endif (WINDOWS) diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index d15377a26b..27022680b8 100644 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -72,12 +72,17 @@ target_link_libraries(windows-crash-logger ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${DXGUID_LIBRARY} + user32 + gdi32 + ole32 + oleaut32 + Wldap32 ) if (WINDOWS) set_target_properties(windows-crash-logger PROPERTIES - LINK_FLAGS "/NODEFAULTLIB:MSVCRT" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD" + LINK_FLAGS "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" ) endif (WINDOWS) diff --git a/indra/win_updater/CMakeLists.txt b/indra/win_updater/CMakeLists.txt index 6379d7c59b..dedb7cfcc7 100644 --- a/indra/win_updater/CMakeLists.txt +++ b/indra/win_updater/CMakeLists.txt @@ -21,10 +21,15 @@ list(APPEND win_updater_SOURCE_FILES ${win_updater_HEADER_FILES}) add_executable(windows-updater WIN32 ${win_updater_SOURCE_FILES}) -target_link_libraries(windows-updater wininet) +target_link_libraries(windows-updater + wininet + user32 + gdi32 + shell32 + ) set_target_properties(windows-updater PROPERTIES - LINK_FLAGS "/NODEFAULTLIB:MSVCRT" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;MSVCRTD\"" + LINK_FLAGS "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" ) |