Merge of QAR-1267 to trunk. This was a combo merge of QAR-1175 (maint-render-9) and QAR-1236 (dll-msvcrt-2)

svn merge -r 109838:112264 svn+ssh://svn.lindenlab.com/svn/linden/branches/maint-render/maint-render-9-merge-r109833
master
Brad Kittenbrink 2009-02-18 21:10:16 +00:00
parent 34412f0530
commit abdc99f21b
198 changed files with 10121 additions and 2883 deletions

View File

@ -108,6 +108,9 @@ Carjay McGinnis
Catherine Pfeffer
VWR-1282
VWR-8624
Celierra Darling
VWR-1274
VWR-6975
Dale Glass
VWR-120
VWR-560
@ -375,6 +378,7 @@ Renault Clio
VWR-1976
Robin Cornelius
VWR-2488
VWR-9557
Ryozu Kojima
VWR-287
Sammy Frederix

View File

@ -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

View File

@ -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(APRUTIL_LIBRARIES
debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-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 ${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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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}

View File

@ -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)

View File

@ -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 "")

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 ;
if(size > 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) ;
}
}
createAPRPool() ;
}
LLAPRPool::~LLAPRPool()
{
apr_pool_destroy(mPool) ;
releaseAPRPool() ;
}
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, mMaxSize) ;
}
}
}
void LLAPRPool::releaseAPRPool()
{
if(!mPool)
{
return ;
}
if(!mParent || mReleasePoolFlag)
{
apr_pool_destroy(mPool) ;
mPool = NULL ;
}
}
apr_pool_t* LLAPRPool::getAPRPool()
{
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()
{
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)
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_status_t s;
//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;
}
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);
return s;
}
S32 ll_apr_file_read(apr_file_t* apr_file, void *buf, S32 nbytes)
apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
{
if(!pool)
{
mCurrentFilePoolp = sAPRFilePoolp ;
return mCurrentFilePoolp->getVolatileAPRPool() ;
}
return pool ;
}
// 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,37 +368,12 @@ 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)
{
if (pool == NULL) pool = gAPRPoolp;
apr_file_t* filep = ll_apr_file_open(filename, APR_READ|APR_BINARY, pool);
if (!filep)
{
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;
}
else
{
bytes_read = ll_apr_file_read(filep, buf, nbytes );
}
apr_file_close(filep);
return bytes_read;
}
S32 ll_apr_file_write(apr_file_t* apr_file, const void *buf, S32 nbytes)
S32 LLAPRFile::write(const void *buf, S32 nbytes)
{
llassert_always(mFile) ;
apr_size_t sz = nbytes;
apr_status_t s = apr_file_write(apr_file, buf, &sz);
apr_status_t s = apr_file_write(mFile, buf, &sz);
if (s != APR_SUCCESS)
{
return 0;
@ -253,51 +385,72 @@ 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)
S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
{
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)
{
return 0;
}
if (offset > 0)
{
offset = ll_apr_file_seek(filep, APR_SET, offset);
}
S32 bytes_written;
if (offset < 0)
{
bytes_written = 0;
}
else
{
bytes_written = ll_apr_file_write(filep, buf, nbytes );
}
apr_file_close(filep);
return bytes_written;
return LLAPRFile::seek(mFile, where, offset) ;
}
S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 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)
{
ret = apr_file_close(file_handle);
file_handle = NULL ;
}
if(pool)
{
pool->clearVolatileAPRPool() ;
}
return ret ;
}
//static
apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
{
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(apr_file, where, &apr_offset);
s = apr_file_seek(file_handle, where, &apr_offset);
}
else
{
apr_offset = 0;
s = apr_file_seek(apr_file, APR_END, &apr_offset);
s = apr_file_seek(file_handle, APR_END, &apr_offset);
}
if (s != APR_SUCCESS)
{
@ -310,66 +463,178 @@ S32 ll_apr_file_seek(apr_file_t* apr_file, apr_seek_where_t where, S32 offset)
}
}
bool ll_apr_file_remove(const std::string& filename, apr_pool_t* pool)
//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)
{
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;
}
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
if (offset < 0)
{
flags |= APR_APPEND;
offset = 0;
}
//*****************************************
apr_file_t* file_handle = open(filename, pool, flags);
//*****************************************
if (!file_handle)
{
return 0;
}
if (offset > 0)
{
offset = LLAPRFile::seek(file_handle, APR_SET, offset);
}
apr_size_t bytes_written;
if (offset < 0)
{
bytes_written = 0;
}
else
{
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);
}
}
//*****************************************
LLAPRFile::close(file_handle, pool);
//*****************************************
return (S32)bytes_written;
}
//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
//*******************************************************************************************************************************
//

View File

@ -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

View File

@ -197,6 +197,10 @@ void LLCRC::update(const std::string& filename)
update(data, nread);
delete[] data;
}
else
{
fclose(fp);
}
}
}

View File

@ -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 ;
}
}

View File

@ -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

View File

@ -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++;

View File

@ -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() ;
}

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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);
@ -120,8 +118,6 @@ class LLWorkerClass
friend class LLWorkerThread;
friend class LLWorkerThread::WorkRequest;
public:
static BOOL sDeleteLock ;
public:
typedef LLWorkerThread::handle_t handle_t;
enum FLAGS

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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})

View File

@ -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

View File

@ -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 = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch);
if( scaled_max_pixels < (total_width + char_width) )
{
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;
}
// Round after kerning.
total_width = (F32)llfloor(total_width + 0.5f);
break;
}
else
total_width += char_width;
drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars )
{
F32 char_width = getXAdvance(wch);
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 )
{
// Kerning
total_width += getXKerning(wchars[i-1], wch);
}
// Round after kerning.
total_width = (F32)llfloor(total_width + 0.5f);
break;
}
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;
}

View File

@ -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)

View File

@ -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),
@ -560,6 +576,16 @@ void LLGLManager::initExtensions()
mHasFramebufferObject = TRUE;
# 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;
@ -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();

View File

@ -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;

View File

@ -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" {

View File

@ -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);

View File

@ -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);

View File

@ -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)
void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode)
{
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)
{
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;
}
if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
{
gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode);
mTexOptionsDirty = false;
}
}
void LLImageGL::setClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr)
void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
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);
}
void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest)
{
mMagFilterNearest = mag_nearest;
mMinFilterNearest = min_nearest;
if (mTexName != 0)
if (mFilterOption != option)
{
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();
}
mTexOptionsDirty = true;
mFilterOption = option;
}
if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
{
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)

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
if (true)
activate();
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]);
}
}
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
if (mCurrTexType == TT_CUBE_MAP)
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);
}
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]

View File

@ -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];

View File

@ -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();
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);
stop_glerror();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
stop_glerror();
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();
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);
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
LLTexUnit::getInternalType(mUsage), mTex, 0);
stop_glerror();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
stop_glerror();
}
addColorAttachment(color_fmt);
}
void LLRenderTarget::addColorAttachment(U32 color_fmt)
{
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;
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);
}
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,17 +331,38 @@ 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)
{
gGL.flush();
@ -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
}

View File

@ -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

View File

@ -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_TEXCOORD>::get(*this, strider, index);
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index);
}
bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, 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_BINORMAL)
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
if (data_mask & MAP_TEXCOORD0)
{
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_BINORMAL)
{
glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL]));
}
if (data_mask & MAP_WEIGHT)
{
glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));

View File

@ -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);

View File

@ -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));

View File

@ -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 );

View File

@ -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

View File

@ -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++;
}

View File

@ -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);
}
}
}
}
}

View File

@ -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;
}

View File

@ -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}
)

View File

@ -40,6 +40,7 @@
</array>
<key>tags</key>
<array>
<string>ShaderLoading</string>
</array>
</map>
</array>

View File

@ -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>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -7,6 +7,7 @@
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
vec3 applyWaterFog(vec4 inColor);
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;

View File

@ -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

View File

@ -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.

View File

@ -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());
}
//-----------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More