summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/00-Common.cmake13
-rw-r--r--indra/cmake/APR.cmake12
-rw-r--r--indra/cmake/Audio.cmake16
-rw-r--r--indra/cmake/Boost.cmake12
-rw-r--r--indra/cmake/GooglePerfTools.cmake5
-rw-r--r--indra/cmake/JPEG.cmake2
-rw-r--r--indra/cmake/LLRender.cmake4
-rw-r--r--indra/cmake/LLWindow.cmake5
-rw-r--r--indra/cmake/Linking.cmake5
-rw-r--r--indra/cmake/PNG.cmake8
-rw-r--r--indra/cmake/ZLIB.cmake4
-rw-r--r--indra/llcharacter/llbvhloader.cpp9
-rw-r--r--indra/llcharacter/llkeyframemotionparam.cpp7
-rw-r--r--indra/llcharacter/llstatemachine.cpp6
-rw-r--r--indra/llcommon/llapr.cpp502
-rw-r--r--indra/llcommon/llapr.h124
-rw-r--r--indra/llcommon/llcrc.cpp4
-rw-r--r--indra/llcommon/llerror.cpp123
-rw-r--r--indra/llcommon/llerror.h36
-rw-r--r--indra/llcommon/llfasttimer.h12
-rw-r--r--indra/llcommon/llfixedbuffer.cpp7
-rw-r--r--indra/llcommon/llfixedbuffer.h10
-rw-r--r--indra/llcommon/llthread.cpp8
-rw-r--r--indra/llcommon/llthread.h8
-rw-r--r--indra/llcommon/llworkerthread.cpp18
-rw-r--r--indra/llcommon/llworkerthread.h6
-rwxr-xr-xindra/llcrashlogger/llcrashlogger.cpp2
-rw-r--r--indra/llimage/llimage.cpp18
-rw-r--r--indra/llimage/llimagej2c.cpp10
-rw-r--r--indra/llmath/llcamera.cpp95
-rw-r--r--indra/llmath/llmath.h8
-rw-r--r--indra/llmessage/llares.cpp20
-rw-r--r--indra/llmessage/llurlrequest.cpp10
-rw-r--r--indra/llrender/CMakeLists.txt6
-rw-r--r--indra/llrender/llcubemap.cpp11
-rw-r--r--indra/llrender/llfontgl.cpp69
-rw-r--r--indra/llrender/llfontgl.h2
-rw-r--r--indra/llrender/llgl.cpp101
-rw-r--r--indra/llrender/llgl.h4
-rw-r--r--indra/llrender/llglheaders.h32
-rw-r--r--indra/llrender/llglslshader.cpp86
-rw-r--r--indra/llrender/llglslshader.h4
-rw-r--r--indra/llrender/llimagegl.cpp305
-rw-r--r--indra/llrender/llimagegl.h75
-rw-r--r--indra/llrender/llpostprocess.cpp22
-rw-r--r--indra/llrender/llpostprocess.h2
-rw-r--r--indra/llrender/llrender.cpp134
-rw-r--r--indra/llrender/llrender.h44
-rw-r--r--indra/llrender/llrendertarget.cpp533
-rw-r--r--indra/llrender/llrendertarget.h58
-rw-r--r--indra/llrender/llvertexbuffer.cpp106
-rw-r--r--indra/llrender/llvertexbuffer.h15
-rw-r--r--indra/llui/lllineeditor.cpp2
-rw-r--r--indra/llui/llviewborder.cpp3
-rw-r--r--indra/llvfs/lllfsthread.cpp29
-rw-r--r--indra/llvfs/llvfs.cpp8
-rw-r--r--indra/llwindow/llwindowsdl.cpp15
-rw-r--r--indra/llwindow/llwindowwin32.cpp48
-rw-r--r--indra/newview/CMakeLists.txt5
-rw-r--r--indra/newview/app_settings/logcontrol.xml1
-rw-r--r--indra/newview/app_settings/settings.xml310
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl88
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl69
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl78
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl42
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl48
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl63
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl41
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl83
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl75
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl28
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl279
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl24
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl139
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl36
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl41
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl157
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterV.glsl76
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterF.glsl1
-rw-r--r--indra/newview/featuretable.txt32
-rw-r--r--indra/newview/licenses-win32.txt34
-rw-r--r--indra/newview/llagent.cpp15
-rw-r--r--indra/newview/llagent.h2
-rw-r--r--indra/newview/llappviewer.cpp116
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llcloud.cpp2
-rw-r--r--indra/newview/lldrawable.cpp8
-rw-r--r--indra/newview/lldrawable.h1
-rw-r--r--indra/newview/lldrawpool.cpp88
-rw-r--r--indra/newview/lldrawpool.h25
-rw-r--r--indra/newview/lldrawpoolalpha.cpp302
-rw-r--r--indra/newview/lldrawpoolalpha.h12
-rw-r--r--indra/newview/lldrawpoolavatar.cpp304
-rw-r--r--indra/newview/lldrawpoolavatar.h28
-rw-r--r--indra/newview/lldrawpoolbump.cpp245
-rw-r--r--indra/newview/lldrawpoolbump.h26
-rw-r--r--indra/newview/lldrawpoolclouds.h2
-rw-r--r--indra/newview/lldrawpoolground.h2
-rw-r--r--indra/newview/lldrawpoolsimple.cpp204
-rw-r--r--indra/newview/lldrawpoolsimple.h67
-rw-r--r--indra/newview/lldrawpoolsky.cpp2
-rw-r--r--indra/newview/lldrawpoolsky.h7
-rw-r--r--indra/newview/lldrawpoolterrain.cpp118
-rw-r--r--indra/newview/lldrawpoolterrain.h15
-rw-r--r--indra/newview/lldrawpooltree.cpp109
-rw-r--r--indra/newview/lldrawpooltree.h13
-rw-r--r--indra/newview/lldrawpoolwater.cpp68
-rw-r--r--indra/newview/lldrawpoolwater.h7
-rw-r--r--indra/newview/lldrawpoolwlsky.h7
-rw-r--r--indra/newview/lldynamictexture.cpp2
-rw-r--r--indra/newview/llface.cpp182
-rw-r--r--indra/newview/llface.h9
-rw-r--r--indra/newview/llfasttimerview.cpp10
-rw-r--r--indra/newview/llfloaterabout.cpp8
-rw-r--r--indra/newview/llfloateranimpreview.cpp12
-rw-r--r--indra/newview/llfloaterauction.cpp2
-rw-r--r--indra/newview/llfloatercolorpicker.cpp2
-rw-r--r--indra/newview/llfloaterimagepreview.cpp3
-rw-r--r--indra/newview/llfloatersnapshot.cpp14
-rw-r--r--indra/newview/llhudicon.cpp2
-rw-r--r--indra/newview/llhudobject.cpp2
-rw-r--r--indra/newview/llhudtext.cpp17
-rw-r--r--indra/newview/lljoystickbutton.cpp2
-rw-r--r--indra/newview/lljoystickbutton.h2
-rw-r--r--indra/newview/llmaniptranslate.cpp7
-rw-r--r--indra/newview/llmimetypes.h4
-rw-r--r--indra/newview/llsky.cpp29
-rw-r--r--indra/newview/llspatialpartition.cpp345
-rw-r--r--indra/newview/llspatialpartition.h46
-rw-r--r--indra/newview/llsprite.cpp2
-rw-r--r--indra/newview/llstartup.cpp20
-rw-r--r--indra/newview/llsurface.cpp6
-rw-r--r--indra/newview/llsurfacepatch.cpp2
-rw-r--r--indra/newview/lltexlayer.cpp45
-rw-r--r--indra/newview/lltexlayer.h1
-rw-r--r--indra/newview/lltexturecache.cpp135
-rw-r--r--indra/newview/lltexturecache.h6
-rw-r--r--indra/newview/lltexturefetch.cpp3
-rw-r--r--indra/newview/llviewercamera.cpp45
-rw-r--r--indra/newview/llviewercamera.h2
-rw-r--r--indra/newview/llviewercontrol.cpp9
-rw-r--r--indra/newview/llviewerdisplay.cpp119
-rw-r--r--indra/newview/llviewerjoint.cpp6
-rw-r--r--indra/newview/llviewerjointmesh.cpp18
-rw-r--r--indra/newview/llviewermenu.cpp4
-rw-r--r--indra/newview/llviewermenufile.cpp8
-rw-r--r--indra/newview/llviewerobject.cpp8
-rw-r--r--indra/newview/llviewerobject.h2
-rw-r--r--indra/newview/llviewerparceloverlay.cpp4
-rw-r--r--indra/newview/llviewerpartsim.cpp4
-rw-r--r--indra/newview/llviewerpartsource.cpp2
-rw-r--r--indra/newview/llviewershadermgr.cpp281
-rw-r--r--indra/newview/llviewershadermgr.h29
-rw-r--r--indra/newview/llviewerstats.cpp1
-rw-r--r--indra/newview/llviewerwindow.cpp70
-rw-r--r--indra/newview/llvlcomposition.cpp1
-rw-r--r--indra/newview/llvoavatar.cpp150
-rw-r--r--indra/newview/llvoavatar.h7
-rw-r--r--indra/newview/llvoicevisualizer.cpp2
-rw-r--r--indra/newview/llvopartgroup.cpp10
-rw-r--r--indra/newview/llvopartgroup.h2
-rw-r--r--indra/newview/llvosky.cpp24
-rw-r--r--indra/newview/llvosurfacepatch.cpp32
-rw-r--r--indra/newview/llvosurfacepatch.h4
-rw-r--r--indra/newview/llvotree.cpp921
-rw-r--r--indra/newview/llvotree.h37
-rw-r--r--indra/newview/llvovolume.cpp721
-rw-r--r--indra/newview/llvovolume.h4
-rw-r--r--indra/newview/llvowater.h2
-rw-r--r--indra/newview/llvowlsky.cpp4
-rw-r--r--indra/newview/llworld.cpp6
-rw-r--r--indra/newview/llworldmap.cpp7
-rw-r--r--indra/newview/llworldmapview.cpp4
-rw-r--r--indra/newview/pipeline.cpp2388
-rw-r--r--indra/newview/pipeline.h102
-rwxr-xr-xindra/newview/viewer_manifest.py6
-rw-r--r--indra/test/CMakeLists.txt4
-rw-r--r--indra/win_crash_logger/CMakeLists.txt9
-rw-r--r--indra/win_updater/CMakeLists.txt11
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 &center, 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 &center_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\""
)