merge QAR-1829: texture pipeline branch in viewer-2.0.0.3

master
Xiaohong Bao 2009-11-06 06:52:24 +00:00
parent 2f2bdd83d6
commit 35e200881c
142 changed files with 8414 additions and 4107 deletions

View File

@ -251,10 +251,13 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
mLastHeadRot = head_rot_local;
// Set the head rotation.
LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
head_rot_local = head_rot_local * ~torsoRotLocal;
mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
if(mNeckState->getJoint() && mNeckState->getJoint()->getParent())
{
LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
head_rot_local = head_rot_local * ~torsoRotLocal;
mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
}
return TRUE;
}

View File

@ -57,7 +57,7 @@ void ll_init_apr()
if(!LLAPRFile::sAPRFilePoolp)
{
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ;
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
}
@ -99,13 +99,12 @@ void ll_cleanup_apr()
//
//LLAPRPool
//
LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
{
mParent = parent ;
mReleasePoolFlag = releasePoolFlag ;
mMaxSize = size ;
mPool = NULL ;
LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
: mParent(parent),
mReleasePoolFlag(releasePoolFlag),
mMaxSize(size),
mPool(NULL)
{
createAPRPool() ;
}
@ -148,31 +147,65 @@ void LLAPRPool::releaseAPRPool()
}
}
//virtual
apr_pool_t* LLAPRPool::getAPRPool()
{
return mPool ;
}
LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
: LLAPRPool(parent, size, releasePoolFlag),
mNumActiveRef(0),
mNumTotalRef(0),
mMutexPool(NULL),
mMutexp(NULL)
{
//create mutex
if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
{
apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
}
}
LLVolatileAPRPool::~LLVolatileAPRPool()
{
//delete mutex
if(mMutexp)
{
apr_thread_mutex_destroy(mMutexp);
apr_pool_destroy(mMutexPool);
}
}
//
//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
//
//virtual
apr_pool_t* LLVolatileAPRPool::getAPRPool()
{
return LLVolatileAPRPool::getVolatileAPRPool() ;
}
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
{
LLScopedLock lock(mMutexp) ;
mNumTotalRef++ ;
mNumActiveRef++ ;
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() ;
return mPool ;
}
void LLVolatileAPRPool::clearVolatileAPRPool()
{
LLScopedLock lock(mMutexp) ;
if(mNumActiveRef > 0)
{
mNumActiveRef--;
@ -251,10 +284,9 @@ void LLScopedLock::unlock()
bool ll_apr_warn_status(apr_status_t status)
{
if(APR_SUCCESS == status) return false;
#ifndef LL_WINDOWS
char buf[MAX_STRING]; /* Flawfinder: ignore */
LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL;
#endif
apr_strerror(status, buf, MAX_STRING);
LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
return true;
}
@ -268,10 +300,18 @@ void ll_apr_assert_status(apr_status_t status)
// LLAPRFile functions
//
LLAPRFile::LLAPRFile()
: mFile(NULL),
mCurrentFilePoolp(NULL)
{
mFile = NULL ;
mCurrentFilePoolp = NULL ;
}
LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
: mFile(NULL),
mCurrentFilePoolp(NULL)
{
open(filename, flags, pool);
}
LLAPRFile::~LLAPRFile()
{
close() ;
@ -295,11 +335,40 @@ apr_status_t LLAPRFile::close()
return ret ;
}
apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep)
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
{
apr_status_t s ;
s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ;
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
if (s != APR_SUCCESS || !mFile)
{
mFile = NULL ;
if (sizep)
{
*sizep = 0;
}
}
else if (sizep)
{
S32 file_size = 0;
apr_off_t offset = 0;
if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
{
llassert_always(offset <= 0x7fffffff);
file_size = (S32)offset;
offset = 0;
apr_file_seek(mFile, APR_SET, &offset);
}
*sizep = file_size;
}
if(!mCurrentFilePoolp)
{
mCurrentFilePoolp = pool ;
@ -312,40 +381,25 @@ apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filenam
return s ;
}
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep)
//use gAPRPoolp.
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
{
apr_status_t s;
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool));
s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
if (s != APR_SUCCESS || !mFile)
{
mFile = NULL ;
close() ;
if (sizep)
{
*sizep = 0;
}
return s;
}
if (sizep)
{
S32 file_size = 0;
apr_off_t offset = 0;
if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
{
llassert_always(offset <= 0x7fffffff);
file_size = (S32)offset;
offset = 0;
apr_file_seek(mFile, APR_SET, &offset);
}
*sizep = file_size;
}
return s;
}
@ -369,6 +423,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
apr_status_t s = apr_file_read(mFile, buf, &sz);
if (s != APR_SUCCESS)
{
ll_apr_warn_status(s);
return 0;
}
else
@ -386,6 +441,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes)
apr_status_t s = apr_file_write(mFile, buf, &sz);
if (s != APR_SUCCESS)
{
ll_apr_warn_status(s);
return 0;
}
else
@ -434,6 +490,8 @@ apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
if (s != APR_SUCCESS || !file_handle)
{
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
file_handle = NULL ;
close(file_handle, pool) ;
return NULL;
@ -464,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
}
if (s != APR_SUCCESS)
{
ll_apr_warn_status(s);
return -1;
}
else
@ -501,6 +560,8 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
if (s != APR_SUCCESS)
{
LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
ll_apr_warn_status(s);
bytes_read = 0;
}
else
@ -549,6 +610,8 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
if (s != APR_SUCCESS)
{
LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
ll_apr_warn_status(s);
bytes_written = 0;
}
else
@ -575,8 +638,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL;
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
return false;
}
return true;
@ -593,8 +656,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,
if (s != APR_SUCCESS)
{
LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL;
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
return false;
}
return true;
@ -667,8 +730,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL;
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
return false;
}
return true;
@ -685,8 +748,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL;
ll_apr_warn_status(s);
LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
return false;
}
return true;

View File

@ -70,9 +70,9 @@ class LLAPRPool
{
public:
LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
~LLAPRPool() ;
virtual ~LLAPRPool() ;
apr_pool_t* getAPRPool() ;
virtual apr_pool_t* getAPRPool() ;
apr_status_t getStatus() {return mStatus ; }
protected:
@ -95,18 +95,21 @@ protected:
class LLVolatileAPRPool : public LLAPRPool
{
public:
LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
~LLVolatileAPRPool(){}
LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
virtual ~LLVolatileAPRPool();
apr_pool_t* getVolatileAPRPool() ;
/*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
apr_pool_t* getVolatileAPRPool() ;
void clearVolatileAPRPool() ;
BOOL isFull() ;
BOOL isEmpty() {return !mNumActiveRef ;}
private:
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.
S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
apr_thread_mutex_t *mMutexp;
apr_pool_t *mMutexPool;
} ;
/**
@ -192,18 +195,21 @@ typedef LLAtomic32<S32> LLAtomicS32;
// 1, a temperary pool passed to an APRFile function, which is used within this function and only once.
// 2, a global pool.
//
class LLAPRFile
class LLAPRFile : boost::noncopyable
{
// make this non copyable since a copy closes the file
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(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
~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 open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
apr_status_t close() ;
// Returns actual offset, -1 if seek fails
@ -217,8 +223,8 @@ public:
apr_file_t* getFileHandle() {return mFile;}
private:
apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
//
//*******************************************************************************************************************************
//static components

View File

@ -42,7 +42,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
LLThread(name),
mThreaded(threaded),
mIdleThread(TRUE),
mNextHandle(0)
mNextHandle(0),
mStarted(FALSE)
{
if (mThreaded)
{
@ -53,6 +54,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
// MAIN THREAD
LLQueuedThread::~LLQueuedThread()
{
if (!mThreaded)
{
endThread();
}
shutdown();
// ~LLThread() will be called here
}
@ -106,6 +111,11 @@ void LLQueuedThread::shutdown()
// virtual
S32 LLQueuedThread::update(U32 max_time_ms)
{
if (!mStarted)
{
startThread();
mStarted = TRUE;
}
return updateQueue(max_time_ms);
}
@ -452,26 +462,12 @@ S32 LLQueuedThread::processNextRequest()
}
}
S32 res;
S32 pending = getPending();
if (pending == 0)
{
if (isQuitting())
{
res = -1; // exit thread
}
else
{
res = 0;
}
}
else
{
res = pending;
}
return res;
return pending;
}
// virtual
bool LLQueuedThread::runCondition()
{
// mRunCondition must be locked here
@ -481,35 +477,53 @@ bool LLQueuedThread::runCondition()
return true;
}
// virtual
void LLQueuedThread::run()
{
// call checPause() immediately so we don't try to do anything before the class is fully constructed
checkPause();
startThread();
mStarted = TRUE;
while (1)
{
// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
checkPause();
if(isQuitting())
if (isQuitting())
{
endThread();
break;
//llinfos << "QUEUED THREAD RUNNING, queue size = " << mRequestQueue.size() << llendl;
}
mIdleThread = FALSE;
threadedUpdate();
int res = processNextRequest();
if (res == 0)
{
mIdleThread = TRUE;
ms_sleep(1);
}
if (res < 0) // finished working and want to exit
{
break;
}
//LLThread::yield(); // thread should yield after each request
}
llinfos << "LLQueuedThread " << mName << " EXITING." << llendl;
}
llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl;
// virtual
void LLQueuedThread::startThread()
{
}
// virtual
void LLQueuedThread::endThread()
{
}
// virtual
void LLQueuedThread::threadedUpdate()
{
}
//============================================================================

View File

@ -165,6 +165,9 @@ private:
virtual bool runCondition(void);
virtual void run(void);
virtual void startThread(void);
virtual void endThread(void);
virtual void threadedUpdate(void);
protected:
handle_t generateHandle();
@ -199,6 +202,7 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;

View File

@ -33,9 +33,7 @@
#ifndef LL_LLTHREAD_H
#define LL_LLTHREAD_H
#include "llapr.h"
#include "llapp.h"
#include "apr_thread_cond.h"
class LLThread;

View File

@ -201,6 +201,7 @@ LLWorkerClass::~LLWorkerClass()
{
llassert_always(!(mWorkFlags & WCF_WORKING));
llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
llassert_always(!mMutex.isLocked());
if (mRequestHandle != LLWorkerThread::nullHandle())
{
LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);

View File

@ -52,6 +52,7 @@ class LLWorkerClass;
class LLWorkerThread : public LLQueuedThread
{
friend class LLWorkerClass;
public:
class WorkRequest : public LLQueuedThread::QueuedRequest
{
@ -92,8 +93,11 @@ public:
handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
private:
void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
};
//============================================================================

View File

@ -3,6 +3,7 @@
project(llimage)
include(00-Common)
include(LLAddBuildTest)
include(LLCommon)
include(LLImage)
include(LLMath)
@ -59,3 +60,6 @@ target_link_libraries(llimage
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
)
# Add tests
#ADD_BUILD_TEST(llimageworker llimage)

View File

@ -55,13 +55,9 @@ std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
//static
void LLImage::initClass(LLWorkerThread* workerthread)
void LLImage::initClass()
{
sMutex = new LLMutex(NULL);
if (workerthread)
{
LLImageWorker::initImageWorker(workerthread);
}
LLImageJ2C::openDSO();
}
@ -69,7 +65,6 @@ void LLImage::initClass(LLWorkerThread* workerthread)
void LLImage::cleanupClass()
{
LLImageJ2C::closeDSO();
LLImageWorker::cleanupImageWorker();
delete sMutex;
sMutex = NULL;
}
@ -316,6 +311,21 @@ void LLImageRaw::deleteData()
LLImageBase::deleteData();
}
void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
{
if(data == getData())
{
return ;
}
deleteData();
LLImageBase::setSize(width, height, components) ;
LLImageBase::setDataAndSize(data, width * height * components) ;
sGlobalRawMemory += getDataSize();
}
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@ -816,6 +826,51 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
}
//scale down image by not blending a pixel with its neighbors.
BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
{
LLMemType mt1(mMemType);
S8 c = getComponents() ;
llassert((1 == c) || (3 == c) || (4 == c) );
S32 old_width = getWidth();
S32 old_height = getHeight();
S32 new_data_size = old_width * new_height * c ;
llassert_always(new_data_size > 0);
F32 ratio_x = (F32)old_width / new_width ;
F32 ratio_y = (F32)old_height / new_height ;
if( ratio_x < 1.0f || ratio_y < 1.0f )
{
return TRUE; // Nothing to do.
}
ratio_x -= 1.0f ;
ratio_y -= 1.0f ;
U8* new_data = new U8[new_data_size] ;
llassert_always(new_data != NULL) ;
U8* old_data = getData() ;
S32 i, j, k, s, t;
for(i = 0, s = 0, t = 0 ; i < new_height ; i++)
{
for(j = 0 ; j < new_width ; j++)
{
for(k = 0 ; k < c ; k++)
{
new_data[s++] = old_data[t++] ;
}
t += (S32)(ratio_x * c + 0.1f) ;
}
t += (S32)(ratio_y * old_width * c + 0.1f) ;
}
setDataAndSize(new_data, new_width, new_height, c) ;
return TRUE ;
}
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{

View File

@ -50,7 +50,8 @@ const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
const S32 MAX_IMAGE_COMPONENTS = 8;
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS;
// Note! These CANNOT be changed without invalidating the viewer VFS files, I think?
// Note! These CANNOT be changed without modifying simulator code
// *TODO: change both to 1024 when SIM texture fetching is deprecated
const S32 FIRST_PACKET_SIZE = 600;
const S32 MAX_IMG_PACKET_SIZE = 1000;
@ -61,7 +62,6 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
class LLWorkerThread;
typedef enum e_image_codec
{
@ -82,7 +82,7 @@ typedef enum e_image_codec
class LLImage
{
public:
static void initClass(LLWorkerThread* workerthread);
static void initClass();
static void cleanupClass();
static const std::string& getLastError();
@ -131,7 +131,7 @@ public:
protected:
// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; };
void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
public:
static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@ -192,6 +192,7 @@ public:
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
// Fill the buffer with a constant color
void fill( const LLColor4U& color );
@ -240,6 +241,8 @@ protected:
U8 fastFractionalMult(U8 a,U8 b);
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
public:
static S32 sGlobalRawMemory;
static S32 sRawImageCount;
@ -310,7 +313,7 @@ protected:
protected:
S8 mCodec;
S8 mDecoding;
S8 mDecoded;
S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC
S8 mDiscardLevel;
public:

View File

@ -264,6 +264,8 @@ void LLImageDXT::setFormat()
// virtual
BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
{
// *TODO: Test! This has been tweaked since its intial inception,
// but we don't use it any more!
llassert_always(raw_image);
if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5)
@ -274,8 +276,17 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
S32 width = getWidth(), height = getHeight();
S32 ncomponents = getComponents();
U8* data = NULL;
if (mDiscardLevel >= 0)
{
data = getData() + getMipOffset(mDiscardLevel);
calcDiscardWidthHeight(mDiscardLevel, mFileFormat, width, height);
}
else
{
data = getData() + getMipOffset(0);
}
S32 image_size = formatBytes(mFileFormat, width, height);
U8* data = getData() + getMipOffset(0);
if ((!getData()) || (data + image_size > getData() + getDataSize()))
{
@ -300,10 +311,8 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
llerrs << "Request for invalid discard level" << llendl;
}
U8* data = getData() + getMipOffset(discard);
// I'm not sure these are the correct initial values for height and width,
// but previously they were being used uninitialized. JC
S32 width = raw->getWidth();
S32 height = raw->getHeight();
S32 width = 0;
S32 height = 0;
calcDiscardWidthHeight(discard, mFileFormat, width, height);
raw = new LLImageRaw(data, width, height, getComponents());
return TRUE;

View File

@ -277,6 +277,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
}
// Returns TRUE to mean done, whether successful or not.
BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
LLMemType mt1(mMemType);
@ -289,7 +290,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
if (!getData() || (getDataSize() < 16))
{
setLastError("LLImageJ2C uninitialized");
res = FALSE;
res = TRUE; // done
}
else
{
@ -342,7 +343,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
//static
S32 LLImageJ2C::calcHeaderSizeJ2C()
{
return 600; //2048; // ??? hack... just needs to be >= actual header size...
return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size...
}
//static

View File

@ -188,6 +188,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
}
// Returns true when done, whether or not decode was successful.
BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@ -198,7 +199,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageJPEG trying to decode an image with no data!");
return FALSE;
return TRUE; // done
}
S32 row_stride = 0;
@ -226,7 +227,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
return FALSE;
return TRUE; // done
}
try
{
@ -320,7 +321,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
catch (int)
{
jpeg_destroy_decompress(&cinfo);
return FALSE;
return TRUE; // done
}
// Check to see whether any corrupt-data warnings occurred
@ -328,7 +329,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
// TODO: extract the warning to find out what went wrong.
setLastError( "Unable to decode JPEG image.");
return FALSE;
return TRUE; // done
}
return TRUE;

View File

@ -37,152 +37,138 @@
//----------------------------------------------------------------------------
//static
LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
S32 LLImageWorker::sCount = 0;
//static
void LLImageWorker::initImageWorker(LLWorkerThread* workerthread)
// MAIN THREAD
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
: LLQueuedThread("imagedecode", threaded)
{
sWorkerThread = workerthread;
mCreationMutex = new LLMutex(getAPRPool());
}
//static
void LLImageWorker::cleanupImageWorker()
// MAIN THREAD
// virtual
S32 LLImageDecodeThread::update(U32 max_time_ms)
{
LLMutexLock lock(mCreationMutex);
for (creation_list_t::iterator iter = mCreationList.begin();
iter != mCreationList.end(); ++iter)
{
creation_info& info = *iter;
ImageRequest* req = new ImageRequest(info.handle, info.image,
info.priority, info.discard, info.needs_aux,
info.responder);
addRequest(req);
}
mCreationList.clear();
S32 res = LLQueuedThread::update(max_time_ms);
return res;
}
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
{
LLMutexLock lock(mCreationMutex);
handle_t handle = generateHandle();
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
return handle;
}
// Used by unit test only
// Returns the size of the mutex guarded list as an indication of sanity
S32 LLImageDecodeThread::tut_size()
{
LLMutexLock lock(mCreationMutex);
S32 res = mCreationList.size();
return res;
}
LLImageDecodeThread::Responder::~Responder()
{
}
//----------------------------------------------------------------------------
LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority,
S32 discard,
LLPointer<LLResponder> responder)
: LLWorkerClass(sWorkerThread, "Image"),
LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux,
LLImageDecodeThread::Responder* responder)
: LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
mFormattedImage(image),
mDecodedType(-1),
mDiscardLevel(discard),
mPriority(priority),
mNeedsAux(needs_aux),
mDecodedRaw(FALSE),
mDecodedAux(FALSE),
mResponder(responder)
{
++sCount;
}
LLImageWorker::~LLImageWorker()
LLImageDecodeThread::ImageRequest::~ImageRequest()
{
mDecodedImage = NULL;
mDecodedImageRaw = NULL;
mDecodedImageAux = NULL;
mFormattedImage = NULL;
--sCount;
}
//----------------------------------------------------------------------------
//virtual, main thread
void LLImageWorker::startWork(S32 param)
{
llassert_always(mDecodedImage.isNull());
mDecodedType = -1;
}
bool LLImageWorker::doWork(S32 param)
{
bool decoded = false;
if(mDecodedImage.isNull())
{
if (!mFormattedImage->updateData())
{
mDecodedType = -2; // failed
return true;
}
if (mDiscardLevel >= 0)
{
mFormattedImage->setDiscardLevel(mDiscardLevel);
}
if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
{
decoded = true; // failed
}
else
{
mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding
}
}
if (!decoded)
{
if (param == 0)
{
// Decode primary channels
decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
}
else
{
// Decode aux channel
decoded = mFormattedImage->decodeChannels(mDecodedImage, .1f, param, param); // 1ms
}
}
if (decoded)
{
// Call the callback immediately; endWork doesn't get called until ckeckWork
if (mResponder.notNull())
{
bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
mResponder->completed(success);
}
}
return decoded;
}
void LLImageWorker::endWork(S32 param, bool aborted)
{
if (mDecodedType != -2)
{
mDecodedType = aborted ? -2 : param;
}
}
//----------------------------------------------------------------------------
BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
// Returns true when done, whether or not decode was successful.
bool LLImageDecodeThread::ImageRequest::processRequest()
{
// For most codecs, only mDiscardLevel data is available.
// (see LLImageDXT for exception)
if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
const F32 decode_time_slice = .1f;
bool done = true;
if (!mDecodedRaw && mFormattedImage.notNull())
{
llerrs << "Request for invalid discard level" << llendl;
}
checkWork();
if (mDecodedType == -2)
{
return TRUE; // aborted, done
}
if (mDecodedType != channel)
{
if (!haveWork())
// Decode primary channels
if (mDecodedImageRaw.isNull())
{
addWork(channel, mPriority);
// parse formatted header
if (!mFormattedImage->updateData())
{
return true; // done (failed)
}
if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
{
return true; // done (failed)
}
if (mDiscardLevel >= 0)
{
mFormattedImage->setDiscardLevel(mDiscardLevel);
}
mDecodedImageRaw = new LLImageRaw(mFormattedImage->getWidth(),
mFormattedImage->getHeight(),
mFormattedImage->getComponents());
}
return FALSE;
done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms
mDecodedRaw = done;
}
else
if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull())
{
llassert_always(!haveWork());
llassert_always(mDecodedType == channel);
raw = mDecodedImage; // smart pointer acquires ownership of data
mDecodedImage = NULL;
return TRUE;
// Decode aux channel
if (!mDecodedImageAux)
{
mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(),
mFormattedImage->getHeight(),
1);
}
done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms
mDecodedAux = done;
}
return done;
}
BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
{
if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
if (mResponder.notNull())
{
// special case
LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
return imagedxt->getMipData(raw, discard);
}
else
{
return requestDecodedAuxData(raw, 0, discard);
bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux);
}
// Will automatically be deleted
}
// Used by unit test only
// Checks that a responder exists for this instance so that something can happen when completion is reached
bool LLImageDecodeThread::ImageRequest::tut_isOK()
{
return mResponder.notNull();
}

View File

@ -37,49 +37,72 @@
#include "llpointer.h"
#include "llworkerthread.h"
class LLImageWorker : public LLWorkerClass
class LLImageDecodeThread : public LLQueuedThread
{
public:
static void initImageWorker(LLWorkerThread* workerthread);
static void cleanupImageWorker();
class Responder : public LLThreadSafeRefCount
{
protected:
virtual ~Responder();
public:
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0;
};
class ImageRequest : public LLQueuedThread::QueuedRequest
{
protected:
virtual ~ImageRequest(); // use deleteRequest()
public:
ImageRequest(handle_t handle, LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux,
LLImageDecodeThread::Responder* responder);
/*virtual*/ bool processRequest();
/*virtual*/ void finishRequest(bool completed);
// Used by unit tests to check the consitency of the request instance
bool tut_isOK();
private:
// input
LLPointer<LLImageFormatted> mFormattedImage;
S32 mDiscardLevel;
BOOL mNeedsAux;
// output
LLPointer<LLImageRaw> mDecodedImageRaw;
LLPointer<LLImageRaw> mDecodedImageAux;
BOOL mDecodedRaw;
BOOL mDecodedAux;
LLPointer<LLImageDecodeThread::Responder> mResponder;
};
public:
static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
LLImageDecodeThread(bool threaded = true);
handle_t decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux,
Responder* responder);
S32 update(U32 max_time_ms);
// LLWorkerThread
public:
LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard,
LLPointer<LLResponder> responder);
~LLImageWorker();
// called from WORKER THREAD, returns TRUE if done
/*virtual*/ bool doWork(S32 param);
// Used by unit tests to check the consistency of the thread instance
S32 tut_size();
BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
void releaseDecodedData();
void cancelDecode();
private:
// called from MAIN THREAD
/*virtual*/ void startWork(S32 param); // called from addWork()
/*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
protected:
LLPointer<LLImageFormatted> mFormattedImage;
LLPointer<LLImageRaw> mDecodedImage;
S32 mDecodedType;
S32 mDiscardLevel;
private:
U32 mPriority;
LLPointer<LLResponder> mResponder;
protected:
static LLWorkerThread* sWorkerThread;
public:
static S32 sCount;
struct creation_info
{
handle_t handle;
LLPointer<LLImageFormatted> image;
U32 priority;
S32 discard;
BOOL needs_aux;
LLPointer<Responder> responder;
creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r)
: handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r)
{}
};
typedef std::list<creation_info> creation_list_t;
creation_list_t mCreationList;
LLMutex* mCreationMutex;
};
#endif

View File

@ -0,0 +1,260 @@
/**
* @file llimageworker_test.cpp
* @author Merov Linden
* @date 2009-04-28
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
// Precompiled header: almost always required for newview cpp files
#include <list>
#include <map>
#include <algorithm>
// Class to test
#include "../llimageworker.h"
// For timer class
#include "../llcommon/lltimer.h"
// Tut header
#include "../test/lltut.h"
// -------------------------------------------------------------------------------------------
// Stubbing: Declarations required to link and run the class being tested
// Notes:
// * Add here stubbed implementation of the few classes and methods used in the class to be tested
// * Add as little as possible (let the link errors guide you)
// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
LLImageBase::LLImageBase() {}
LLImageBase::~LLImageBase() {}
void LLImageBase::dump() { }
void LLImageBase::sanityCheck() { }
void LLImageBase::deleteData() { }
U8* LLImageBase::allocateData(S32 size) { return NULL; }
U8* LLImageBase::reallocateData(S32 size) { return NULL; }
LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) { }
LLImageRaw::~LLImageRaw() { }
void LLImageRaw::deleteData() { }
U8* LLImageRaw::allocateData(S32 size) { return NULL; }
U8* LLImageRaw::reallocateData(S32 size) { return NULL; }
// End Stubbing
// -------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------
// TUT
// -------------------------------------------------------------------------------------------
namespace tut
{
// Test wrapper declarations
// Note: We derive the responder class for 2 reasons:
// 1. It's a pure virtual class and we can't compile without completed() being implemented
// 2. We actually need a responder to test that the thread work test completed
// We implement this making no assumption on what's done in the thread or worker
// though, just that the responder's completed() method is called in the end.
// Note on responders: responders are ref counted and *will* be deleted by the request they are
// attached to when the queued request is deleted. The recommended way of using them is to
// create them when creating a request, put a callback method in completed() and not rely on
// anything to survive in the responder object once completed() has been called. Let the request
// do the deletion and clean up itself.
class responder_test : public LLImageDecodeThread::Responder
{
public:
responder_test(bool* res)
{
done = res;
*done = false;
}
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
{
*done = true;
}
private:
// This is what can be thought of as the minimal implementation of a responder
// Done will be switched to true when completed() is called and can be tested
// outside the responder. A better way of doing this is to store a callback here.
bool* done;
};
// Test wrapper declaration : decode thread
struct imagedecodethread_test
{
// Instance to be tested
LLImageDecodeThread* mThread;
// Constructor and destructor of the test wrapper
imagedecodethread_test()
{
mThread = NULL;
}
~imagedecodethread_test()
{
delete mThread;
}
};
// Test wrapper declaration : image worker
// Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance
// but it's not a bad idea to get its public API a good shake as part of a thorough unit test set.
// Some gotcha with the destructor though (see below).
struct imagerequest_test
{
// Instance to be tested
LLImageDecodeThread::ImageRequest* mRequest;
bool done;
// Constructor and destructor of the test wrapper
imagerequest_test()
{
done = false;
mRequest = new LLImageDecodeThread::ImageRequest(0, 0,
LLQueuedThread::PRIORITY_NORMAL, 0, FALSE,
new responder_test(&done));
}
~imagerequest_test()
{
// We should delete the object *but*, because its destructor is protected, that cannot be
// done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine...
//delete mRequest;
}
};
// Tut templating thingamagic: test group, object and test instance
typedef test_group<imagedecodethread_test> imagedecodethread_t;
typedef imagedecodethread_t::object imagedecodethread_object_t;
tut::imagedecodethread_t tut_imagedecodethread("imagedecodethread");
typedef test_group<imagerequest_test> imagerequest_t;
typedef imagerequest_t::object imagerequest_object_t;
tut::imagerequest_t tut_imagerequest("imagerequest");
// ---------------------------------------------------------------------------------------
// Test functions
// Notes:
// * Test as many as you possibly can without requiring a full blown simulation of everything
// * The tests are executed in sequence so the test instance state may change between calls
// * Remember that you cannot test private methods with tut
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Test the LLImageDecodeThread interface
// ---------------------------------------------------------------------------------------
//
// Note on Unit Testing Queued Thread Classes
//
// Since methods on such a class are called on a separate loop and that we can't insert tut
// ensure() calls in there, we exercise the class with 2 sets of tests:
// - 1: Test as a single threaded instance: We declare the class but ask for no thread
// to be spawned (easy with LLThreads since there's a boolean argument on the constructor
// just for that). We can then unit test each public method like we do on a normal class.
// - 2: Test as a threaded instance: We let the thread launch and check that its external
// behavior is as expected (i.e. it runs, can accept a work order and processes
// it). Typically though there's no guarantee that this exercises all the methods of the
// class which is why we also need the previous "non threaded" set of unit tests for
// complete coverage.
//
// ---------------------------------------------------------------------------------------
template<> template<>
void imagedecodethread_object_t::test<1>()
{
// Test a *non threaded* instance of the class
mThread = new LLImageDecodeThread(false);
ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL);
// Test that we start with an empty list right at creation
ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0);
// Insert something in the queue
bool done = false;
LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
// Verifies we got a valid handle
ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0);
// Verifies that we do now have something in the queued list
ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1);
// Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop)
S32 res = mThread->update(0);
// Verifies that we successfully handled the list
ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0);
// Verifies that the list is now empty
ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0);
}
template<> template<>
void imagedecodethread_object_t::test<2>()
{
// Test a *threaded* instance of the class
mThread = new LLImageDecodeThread(true);
ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL);
// Test that we start with an empty list right at creation
ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0);
// Insert something in the queue
bool done = false;
LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
// Verifies we get back a valid handle
ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0);
// Wait a little so to simulate the main thread doing something on its main loop...
ms_sleep(500); // 500 milliseconds
// Verifies that the responder has *not* been called yet in the meantime
ensure("LLImageDecodeThread: responder creation failed", done == false);
// Ask the thread to update: that means tells the queue to check itself and creates work requests
mThread->update(1);
// Wait till the thread has time to handle the work order (though it doesn't do much per work order...)
const U32 INCREMENT_TIME = 500; // 500 milliseconds
const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more
U32 total_time = 0;
while ((done == false) && (total_time < MAX_TIME))
{
ms_sleep(INCREMENT_TIME);
total_time += INCREMENT_TIME;
}
// Verifies that the responder has now been called
ensure("LLImageDecodeThread: threaded work unit not processed", done == true);
}
// ---------------------------------------------------------------------------------------
// Test the LLImageDecodeThread::ImageRequest interface
// ---------------------------------------------------------------------------------------
template<> template<>
void imagerequest_object_t::test<1>()
{
// Test that we start with a correct request at creation
ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK());
bool res = mRequest->processRequest();
// Verifies that we processed the request successfully
ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true);
// Check that we can call the finishing call safely
try {
mRequest->finishRequest(false);
} catch (...) {
fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed");
}
}
}

View File

@ -3582,7 +3582,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
if (face == -1) // ALL_SIDES
{
start_face = 0;
end_face = getNumFaces() - 1;
end_face = getNumVolumeFaces() - 1;
}
else
{

View File

@ -64,6 +64,9 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
LLTempAssetStorage::~LLTempAssetStorage()
{
}
///----------------------------------------------------------------------------
/// LLAssetInfo

View File

@ -204,7 +204,16 @@ typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
class LLAssetStorage
class LLTempAssetStorage
{
public:
virtual ~LLTempAssetStorage() =0;
virtual void addTempAssetData(const LLUUID& asset_id,
const LLUUID& agent_id,
const std::string& host_name) = 0;
};
class LLAssetStorage : public LLTempAssetStorage
{
public:
// VFS member is public because static child methods need it :(

View File

@ -220,7 +220,7 @@ public:
U32 report(CURLcode);
void getTransferInfo(LLCurl::TransferInfo* info);
void prepRequest(const std::string& url, ResponderPtr, bool post = false);
void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false);
const char* getErrorBuffer();
@ -432,7 +432,9 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data
return n;
}
void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, bool post)
void LLCurl::Easy::prepRequest(const std::string& url,
const std::vector<std::string>& headers,
ResponderPtr responder, bool post)
{
resetState();
@ -465,8 +467,13 @@ void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, b
{
slist_append("Connection: keep-alive");
slist_append("Keep-alive: 300");
// Accept and other headers
for (std::vector<std::string>::const_iterator iter = headers.begin();
iter != headers.end(); ++iter)
{
slist_append((*iter).c_str());
}
}
// *FIX: should have ACCEPT headers
}
////////////////////////////////////////////////////////////////////////////
@ -676,15 +683,18 @@ LLCurlRequest::LLCurlRequest() :
mActiveMulti(NULL),
mActiveRequestCount(0)
{
mThreadID = LLThread::currentID();
}
LLCurlRequest::~LLCurlRequest()
{
llassert_always(mThreadID == LLThread::currentID());
for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
}
void LLCurlRequest::addMulti()
{
llassert_always(mThreadID == LLThread::currentID());
LLCurl::Multi* multi = new LLCurl::Multi();
mMultiSet.insert(multi);
mActiveMulti = multi;
@ -714,17 +724,20 @@ bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
{
getByteRange(url, 0, -1, responder);
getByteRange(url, headers_t(), 0, -1, responder);
}
bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder)
bool LLCurlRequest::getByteRange(const std::string& url,
const headers_t& headers,
S32 offset, S32 length,
LLCurl::ResponderPtr responder)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
easy->prepRequest(url, responder);
easy->prepRequest(url, headers, responder);
easy->setopt(CURLOPT_HTTPGET, 1);
if (length > 0)
{
@ -736,14 +749,17 @@ bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length,
return res;
}
bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder)
bool LLCurlRequest::post(const std::string& url,
const headers_t& headers,
const LLSD& data,
LLCurl::ResponderPtr responder)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
easy->prepRequest(url, responder);
easy->prepRequest(url, headers, responder);
LLSDSerialize::toXML(data, easy->getInput());
S32 bytes = easy->getInput().str().length();
@ -763,6 +779,7 @@ bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::Respo
// Note: call once per frame
S32 LLCurlRequest::process()
{
llassert_always(mThreadID == LLThread::currentID());
S32 res = 0;
for (curlmulti_set_t::iterator iter = mMultiSet.begin();
iter != mMultiSet.end(); )
@ -782,6 +799,7 @@ S32 LLCurlRequest::process()
S32 LLCurlRequest::getQueued()
{
llassert_always(mThreadID == LLThread::currentID());
S32 queued = 0;
for (curlmulti_set_t::iterator iter = mMultiSet.begin();
iter != mMultiSet.end(); )
@ -1002,7 +1020,7 @@ void LLCurl::initClass()
S32 mutex_count = CRYPTO_num_locks();
for (S32 i=0; i<mutex_count; i++)
{
sSSLMutex.push_back(new LLMutex(gAPRPoolp));
sSSLMutex.push_back(new LLMutex(NULL));
}
CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);

View File

@ -188,12 +188,14 @@ namespace boost
class LLCurlRequest
{
public:
typedef std::vector<std::string> headers_t;
LLCurlRequest();
~LLCurlRequest();
void get(const std::string& url, LLCurl::ResponderPtr responder);
bool getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder);
bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
S32 process();
S32 getQueued();
@ -207,6 +209,7 @@ private:
curlmulti_set_t mMultiSet;
LLCurl::Multi* mActiveMulti;
S32 mActiveRequestCount;
U32 mThreadID; // debug
};
class LLCurlEasyRequest

View File

@ -20,8 +20,9 @@
*/
#include "linden_common.h"
#include "llcurl.h"
LLCurl::Responder::Responder()
LLCurl::Responder::Responder() : mReferenceCount(0)
{
}

View File

@ -50,7 +50,7 @@ std::vector<std::string> put_urls;
std::vector<LLSD> put_body;
std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders;
void LLHTTPClient::put(std::string const &url, LLSD const &body, boost::intrusive_ptr<LLCurl::Responder> responder,float)
void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
{
put_urls.push_back(url);
put_responders.push_back(responder);

View File

@ -43,7 +43,6 @@
#include "llmath.h"
#include "llgl.h"
#include "llrender.h"
//----------------------------------------------------------------------------
const F32 MIN_TEXTURE_LIFETIME = 10.f;
@ -60,21 +59,34 @@ std::list<U32> LLImageGL::sDeadTextureList;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
F32 LLImageGL::sLastFrameTime = 0.f;
BOOL LLImageGL::sAllowReadBackRaw = FALSE ;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
std::set<LLImageGL*> LLImageGL::sImageList;
#if !LL_RELEASE_FOR_DOWNLOAD
//****************************************************************************************************
//The below for texture auditing use only
//****************************************************************************************************
//-----------------------
//debug use
BOOL gAuditTexture = FALSE ;
#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048
std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
S32 LLImageGL::sCurTexSizeBar = -1 ;
S32 LLImageGL::sCurTexPickSize = -1 ;
LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL;
LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
S32 LLImageGL::sMaxCatagories = 1 ;
std::vector<S32> LLImageGL::sTextureMemByCategory;
std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
//------------------------
#endif
//****************************************************************************************************
//End for texture auditing use only
//****************************************************************************************************
//**************************************************************************************
//below are functions for debug use
//do not delete them even though they are not currently being used.
@ -144,6 +156,60 @@ void LLImageGL::checkTexSize() const
//**************************************************************************************
//----------------------------------------------------------------------------
BOOL is_little_endian()
{
S32 a = 0x12345678;
U8 *c = (U8*)(&a);
return (*c == 0x78) ;
}
//static
void LLImageGL::initClass(S32 num_catagories)
{
sMaxCatagories = num_catagories ;
sTextureMemByCategory.resize(sMaxCatagories);
sTextureMemByCategoryBound.resize(sMaxCatagories) ;
sTextureCurMemByCategoryBound.resize(sMaxCatagories) ;
}
//static
void LLImageGL::cleanupClass()
{
sTextureMemByCategory.clear() ;
sTextureMemByCategoryBound.clear() ;
sTextureCurMemByCategoryBound.clear() ;
}
//static
void LLImageGL::setHighlightTexture(S32 category)
{
const S32 dim = 128;
sHighlightTexturep = new LLImageGL() ;
LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
U8* data = image_raw->getData();
for (S32 i = 0; i<dim; i++)
{
for (S32 j = 0; j<dim; j++)
{
const S32 border = 2;
if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
{
*data++ = 0xff;
*data++ = 0xff;
*data++ = 0xff;
}
else
{
*data++ = 0xff;
*data++ = 0xff;
*data++ = 0x00;
}
}
}
sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category);
image_raw = NULL;
}
//static
S32 LLImageGL::dataFormatBits(S32 dataformat)
@ -211,19 +277,31 @@ void LLImageGL::updateStats(F32 current_time)
sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
sCurBoundTextureMemory = 0;
#if !LL_RELEASE_FOR_DOWNLOAD
for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++)
if(gAuditTexture)
{
sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ;
sTextureCurBoundCounter[i] = 0 ;
for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++)
{
sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ;
sTextureCurBoundCounter[i] = 0 ;
}
for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
{
sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
sTextureCurMemByCategoryBound[i] = 0 ;
}
}
#endif
}
//static
S32 LLImageGL::updateBoundTexMem(const S32 delta)
S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category)
{
LLImageGL::sCurBoundTextureMemory += delta;
if(gAuditTexture && ncomponents > 0 && category > -1)
{
sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
sTextureCurMemByCategoryBound[category] += mem ;
}
LLImageGL::sCurBoundTextureMemory += mem ;
return LLImageGL::sCurBoundTextureMemory;
}
@ -237,6 +315,7 @@ void LLImageGL::destroyGL(BOOL save_state)
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
sAllowReadBackRaw = true ;
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
{
@ -246,7 +325,7 @@ void LLImageGL::destroyGL(BOOL save_state)
if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
{
glimage->mSaveData = new LLImageRaw;
if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false))
if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
{
glimage->mSaveData = NULL ;
}
@ -256,6 +335,7 @@ void LLImageGL::destroyGL(BOOL save_state)
stop_glerror();
}
}
sAllowReadBackRaw = false ;
}
//static
@ -273,7 +353,7 @@ void LLImageGL::restoreGL()
{
if (glimage->getComponents() && glimage->mSaveData->getComponents())
{
glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData);
glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory());
stop_glerror();
}
glimage->mSaveData = NULL; // deletes data
@ -355,7 +435,7 @@ void LLImageGL::init(BOOL usemipmaps)
mPickMask = NULL;
mTextureMemory = 0;
mLastBindTime = 0.f;
mTarget = GL_TEXTURE_2D;
mBindTarget = LLTexUnit::TT_TEXTURE;
mUseMipMaps = usemipmaps;
@ -381,7 +461,11 @@ void LLImageGL::init(BOOL usemipmaps)
mHasExplicitFormat = FALSE;
mGLTextureCreated = FALSE ;
mIsMask = FALSE;
mCategory = -1 ;
mAlphaStride = 0 ;
mAlphaOffset = 0 ;
mNeedsAlphaAndPickMask = TRUE ;
mDiscardLevelInAtlas = -1 ;
@ -486,6 +570,10 @@ void LLImageGL::dump()
}
//----------------------------------------------------------------------------
void LLImageGL::forceUpdateBindStats(void) const
{
mLastBindTime = sLastFrameTime;
}
BOOL LLImageGL::updateBindStats(S32 tex_mem) const
{
@ -499,7 +587,7 @@ BOOL LLImageGL::updateBindStats(S32 tex_mem) const
{
// we haven't accounted for this texture yet this frame
sUniqueCount++;
updateBoundTexMem(tex_mem);
updateBoundTexMem(tex_mem, mComponents, mCategory);
mLastBindTime = sLastFrameTime;
return TRUE ;
@ -525,6 +613,8 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for
else
mFormatType = type_format;
mFormatSwapBytes = swap_bytes;
calcAlphaChannelOffsetAndStride() ;
}
//----------------------------------------------------------------------------
@ -540,7 +630,6 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
llpushcallstacks ;
bool is_compressed = false;
if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
{
@ -749,7 +838,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
stop_glerror();
mGLTextureCreated = true;
llpushcallstacks ;
}
BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
@ -840,7 +928,6 @@ void LLImageGL::postAddToAtlas()
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
{
llpushcallstacks ;
if (!width || !height)
{
return TRUE;
@ -930,7 +1017,6 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
stop_glerror();
mGLTextureCreated = true;
}
llpushcallstacks ;
return TRUE;
}
@ -942,8 +1028,9 @@ BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3
// Copy sub image from frame buffer
BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
if (gGL.getTexUnit(0)->bind(this))
if (gGL.getTexUnit(0)->bind(this, false, true))
{
//checkTexSize() ;
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
mGLTextureCreated = true;
stop_glerror();
@ -1007,7 +1094,7 @@ BOOL LLImageGL::createGLTexture()
return TRUE ;
}
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/)
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
{
if (gGLManager.mIsDisabled)
{
@ -1027,8 +1114,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
// Actual image width/height = raw image width/height * 2^discard_level
S32 w = imageraw->getWidth() << discard_level;
S32 h = imageraw->getHeight() << discard_level;
S32 raw_w = imageraw->getWidth() ;
S32 raw_h = imageraw->getHeight() ;
S32 w = raw_w << discard_level;
S32 h = raw_h << discard_level;
// setSize may call destroyGLTexture if the size does not match
setSize(w, h, imageraw->getComponents());
@ -1062,15 +1151,25 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
default:
llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
}
calcAlphaChannelOffsetAndStride() ;
}
if(!to_create) //not create a gl texture
{
destroyGLTexture();
mCurrentDiscardLevel = discard_level;
mLastBindTime = sLastFrameTime;
return TRUE ;
}
setCategory(category) ;
const U8* rawdata = imageraw->getData();
return createGLTexture(discard_level, rawdata, FALSE, usename);
}
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
{
llpushcallstacks ;
llassert(data_in);
if (discard_level < 0)
@ -1137,11 +1236,14 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
if (old_name != 0)
{
sGlobalTextureMemoryInBytes -= mTextureMemory;
#if !LL_RELEASE_FOR_DOWNLOAD
decTextureCounter(mTextureMemory / mComponents) ;
#endif
if(gAuditTexture)
{
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
LLImageGL::deleteTextures(1, &old_name);
stop_glerror();
}
@ -1149,82 +1251,20 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
sGlobalTextureMemoryInBytes += mTextureMemory;
mTexelsInGLTexture = getWidth() * getHeight() ;
#if !LL_RELEASE_FOR_DOWNLOAD
incTextureCounter(mTextureMemory / mComponents) ;
#endif
if(gAuditTexture)
{
incTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
llpushcallstacks ;
return TRUE;
}
BOOL LLImageGL::setDiscardLevel(S32 discard_level)
{
llassert(discard_level >= 0);
llassert(mCurrentDiscardLevel >= 0);
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
if (discard_level == mCurrentDiscardLevel)
{
// nothing to do
return FALSE;
}
else if (discard_level < mCurrentDiscardLevel)
{
// larger image
dump();
llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl;
return FALSE;
}
else if (mUseMipMaps)
{
LLPointer<LLImageRaw> imageraw = new LLImageRaw;
while(discard_level > mCurrentDiscardLevel)
{
if (readBackRaw(discard_level, imageraw, false))
{
break;
}
discard_level--;
}
if (discard_level == mCurrentDiscardLevel)
{
// unable to increase the discard level
return FALSE;
}
return createGLTexture(discard_level, imageraw);
}
else
{
#if !LL_LINUX && !LL_SOLARIS
// *FIX: This should not be skipped for the linux client.
llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl;
#endif
return FALSE;
}
}
BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents)
{
assert_glerror();
S32 gl_discard = discard_level - mCurrentDiscardLevel;
LLGLint glwidth = 0;
glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
LLGLint glheight = 0;
glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight);
LLGLint glcomponents = 0 ;
glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents);
assert_glerror();
return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ;
}
BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
{
llpushcallstacks ;
llassert_always(sAllowReadBackRaw) ;
//llerrs << "should not call this function!" << llendl ;
if (discard_level < 0)
{
discard_level = mCurrentDiscardLevel;
@ -1327,7 +1367,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return FALSE ;
}
//-----------------------------------------------------------------------------------------------
llpushcallstacks ;
return TRUE ;
}
@ -1345,25 +1385,26 @@ void LLImageGL::deleteDeadTextures()
stop_glerror();
}
}
glDeleteTextures(1, &tex);
stop_glerror();
}
}
void LLImageGL::destroyGLTexture()
{
if (mTexName != 0)
{
if(mTextureMemory)
{
#if !LL_RELEASE_FOR_DOWNLOAD
decTextureCounter(mTextureMemory / mComponents) ;
#endif
if(gAuditTexture)
{
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
sGlobalTextureMemoryInBytes -= mTextureMemory;
mTextureMemory = 0;
}
LLImageGL::deleteTextures(1, &mTexName);
mTexName = 0;
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
@ -1479,6 +1520,11 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const
return res;
}
BOOL LLImageGL::isJustBound() const
{
return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f);
}
BOOL LLImageGL::getBoundRecently() const
{
return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
@ -1490,6 +1536,95 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b
mBindTarget = bind_target;
}
const S8 INVALID_OFFSET = -99 ;
void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask)
{
if(mNeedsAlphaAndPickMask != need_mask)
{
mNeedsAlphaAndPickMask = need_mask;
if(mNeedsAlphaAndPickMask)
{
mAlphaOffset = 0 ;
}
else //do not need alpha mask
{
mAlphaOffset = INVALID_OFFSET ;
mIsMask = FALSE;
}
}
}
void LLImageGL::calcAlphaChannelOffsetAndStride()
{
if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask
{
return ;
}
mAlphaStride = -1 ;
switch (mFormatPrimary)
{
case GL_LUMINANCE:
case GL_ALPHA:
mAlphaStride = 1;
break;
case GL_LUMINANCE_ALPHA:
mAlphaStride = 2;
break;
case GL_RGB:
mNeedsAlphaAndPickMask = FALSE ;
mIsMask = FALSE;
return ; //no alpha channel.
case GL_RGBA:
mAlphaStride = 4;
break;
case GL_BGRA_EXT:
mAlphaStride = 4;
break;
default:
break;
}
mAlphaOffset = -1 ;
if (mFormatType == GL_UNSIGNED_BYTE)
{
mAlphaOffset = mAlphaStride - 1 ;
}
else if(is_little_endian())
{
if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
{
mAlphaOffset = 0 ;
}
else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
{
mAlphaOffset = 3 ;
}
}
else //big endian
{
if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
{
mAlphaOffset = 3 ;
}
else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
{
mAlphaOffset = 0 ;
}
}
if( mAlphaStride < 1 || //unsupported format
mAlphaOffset < 0 || //unsupported type
(mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation
{
llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl;
mNeedsAlphaAndPickMask = FALSE ;
mIsMask = FALSE;
}
}
void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
{
if(!mNeedsAlphaAndPickMask)
@ -1497,37 +1632,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
return ;
}
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;
case GL_BGRA_EXT:
stride = 4;
break;
default:
return;
}
U32 length = w * h;
const GLubyte* current = ((const GLubyte*) data_in)+stride-1;
const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ;
S32 sample[16];
memset(sample, 0, sizeof(S32)*16);
@ -1535,7 +1641,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
for (U32 i = 0; i < length; i++)
{
++sample[*current/16];
current += stride;
current += mAlphaStride ;
}
U32 total = 0;
@ -1638,8 +1744,30 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
return res;
}
//----------------------------------------------------------------------------
#if !LL_RELEASE_FOR_DOWNLOAD
void LLImageGL::setCategory(S32 category)
{
if(!gAuditTexture)
{
return ;
}
if(mCategory != category)
{
if(mCategory > -1)
{
sTextureMemByCategory[mCategory] -= mTextureMemory ;
}
if(category > -1 && category < sMaxCatagories)
{
sTextureMemByCategory[category] += mTextureMemory ;
mCategory = category;
}
else
{
mCategory = -1 ;
}
}
}
//for debug use
//val is a "power of two" number
S32 LLImageGL::getTextureCounterIndex(U32 val)
@ -1663,18 +1791,33 @@ S32 LLImageGL::getTextureCounterIndex(U32 val)
return ret ;
}
}
void LLImageGL::incTextureCounter(U32 val)
//static
void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category)
{
sTextureLoadedCounter[getTextureCounterIndex(val)]++ ;
sTextureMemByCategory[category] += (S32)val * ncomponents ;
}
void LLImageGL::decTextureCounter(U32 val)
//static
void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category)
{
sTextureLoadedCounter[getTextureCounterIndex(val)]-- ;
sTextureMemByCategory[category] += (S32)val * ncomponents ;
}
void LLImageGL::setCurTexSizebar(S32 index)
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
{
sCurTexSizeBar = index ;
sCurTexPickSize = (1 << index) ;
if(set_pick_size)
{
sCurTexPickSize = (1 << index) ;
}
else
{
sCurTexPickSize = -1 ;
}
}
void LLImageGL::resetCurTexSizebar()
{
@ -1682,7 +1825,9 @@ void LLImageGL::resetCurTexSizebar()
sCurTexPickSize = -1 ;
}
//----------------------------------------------------------------------------
#endif
//----------------------------------------------------------------------------
// Manual Mip Generation
/*

View File

@ -47,7 +47,6 @@ class LLTextureAtlas ;
#define MEGA_BYTES_TO_BYTES(x) ((x) << 20)
//============================================================================
class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
@ -63,6 +62,7 @@ public:
BOOL updateBindStats(S32 tex_mem) const ;
F32 getTimePassedSinceLastBound();
void forceUpdateBindStats(void) const;
// needs to be called every frame
static void updateStats(F32 current_time);
@ -71,8 +71,9 @@ public:
static void destroyGL(BOOL save_state = TRUE);
static void restoreGL();
// Sometimes called externally for textures not using LLImageGL (should go away...)
static S32 updateBoundTexMem(const S32 delta);
// Sometimes called externally for textures not using LLImageGL (should go away...)
static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ;
static bool checkSize(S32 width, S32 height);
//for server side use only.
@ -91,6 +92,7 @@ protected:
virtual ~LLImageGL();
void analyzeAlpha(const void* data_in, S32 w, S32 h);
void calcAlphaChannelOffsetAndStride();
public:
virtual void dump(); // debugging info to llinfos
@ -105,14 +107,15 @@ public:
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 LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
S32 category = sMaxCatagories - 1);
BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0);
void setImage(const LLImageRaw* imageraw);
void setImage(const U8* data_in, BOOL data_hasmips = FALSE);
BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);
BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);
BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
BOOL setDiscardLevel(S32 discard_level);
// Read back a raw image for this discard level, if it exists
BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
void destroyGLTexture();
@ -131,6 +134,7 @@ public:
S32 getBytes(S32 discard_level = -1) const;
S32 getMipBytes(S32 discard_level = -1) const;
BOOL getBoundRecently() const;
BOOL isJustBound() const;
LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
LLGLenum getFormatType() const { return mFormatType; }
@ -150,8 +154,6 @@ public:
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
@ -178,7 +180,7 @@ public:
void init(BOOL usemipmaps);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;}
void setNeedsAlphaAndPickMask(BOOL need_mask);
BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
void postAddToAtlas() ;
@ -187,7 +189,7 @@ public:
// Various GL/Rendering options
S32 mTextureMemory;
mutable F32 mLastBindTime; // last time this was bound, by discard level
private:
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
@ -197,13 +199,15 @@ private:
BOOL mIsMask;
BOOL mNeedsAlphaAndPickMask;
S8 mAlphaStride ;
S8 mAlphaOffset ;
bool mGLTextureCreated ;
LLGLuint mTexName;
U16 mWidth;
U16 mHeight;
S8 mCurrentDiscardLevel;
S8 mDiscardLevelInAtlas;
U32 mTexelsInAtlas ;
U32 mTexelsInGLTexture;
@ -233,7 +237,7 @@ public:
static S32 sCount;
static F32 sLastFrameTime;
static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID
// Global memory statistics
@ -246,30 +250,61 @@ public:
static LLImageGL* sDefaultGLTexture ;
static BOOL sAutomatedTest;
#if !LL_RELEASE_FOR_DOWNLOAD
//for debug use: show texture size distribution
//----------------------------------------
static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures
static std::vector<S32> sTextureLoadedCounter ;
static std::vector<S32> sTextureBoundCounter ;
static std::vector<S32> sTextureCurBoundCounter ;
static S32 sCurTexSizeBar ;
static S32 sCurTexPickSize ;
static S32 getTextureCounterIndex(U32 val) ;
static void incTextureCounter(U32 val) ;
static void decTextureCounter(U32 val) ;
static void setCurTexSizebar(S32 index) ;
static void resetCurTexSizebar();
//----------------------------------------
#endif
#if DEBUG_MISS
BOOL mMissed; // Missed on last bind?
BOOL getMissed() const { return mMissed; };
#else
BOOL getMissed() const { return FALSE; };
#endif
public:
static void initClass(S32 num_catagories) ;
static void cleanupClass() ;
private:
static S32 sMaxCatagories ;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.
static BOOL sAllowReadBackRaw ;
//
//****************************************************************************************************
//The below for texture auditing use only
//****************************************************************************************************
private:
S32 mCategory ;
public:
void setCategory(S32 category) ;
S32 getCategory()const {return mCategory ;}
//for debug use: show texture size distribution
//----------------------------------------
static LLPointer<LLImageGL> sHighlightTexturep; //default texture to replace normal textures
static std::vector<S32> sTextureLoadedCounter ;
static std::vector<S32> sTextureBoundCounter ;
static std::vector<S32> sTextureCurBoundCounter ;
static S32 sCurTexSizeBar ;
static S32 sCurTexPickSize ;
static void setHighlightTexture(S32 category) ;
static S32 getTextureCounterIndex(U32 val) ;
static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ;
static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ;
static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
static void resetCurTexSizebar();
//----------------------------------------
//for debug use: show texture category distribution
//----------------------------------------
static std::vector<S32> sTextureMemByCategory;
static std::vector<S32> sTextureMemByCategoryBound ;
static std::vector<S32> sTextureCurMemByCategoryBound ;
//----------------------------------------
//****************************************************************************************************
//End of definitions for texture auditing use only
//****************************************************************************************************
};
extern BOOL gAuditTexture;
#endif // LL_LLIMAGEGL_H

View File

@ -179,7 +179,7 @@ void LLTexUnit::disable(void)
}
}
bool LLTexUnit::bind(LLTexture* texture, bool forceBind)
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
{
stop_glerror();
if (mIndex < 0) return false;
@ -198,9 +198,19 @@ bool LLTexUnit::bind(LLTexture* texture, bool forceBind)
//if deleted, will re-generate it immediately
texture->forceImmediateUpdate() ;
gl_tex->forceUpdateBindStats() ;
return texture->bindDefaultImage(mIndex);
}
//in audit, replace the selected texture by the default one.
if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0)
{
if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize)
{
gl_tex->updateBindStats(gl_tex->mTextureMemory);
return bind(LLImageGL::sHighlightTexturep.get());
}
}
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
{
activate();
@ -223,7 +233,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool forceBind)
return true;
}
bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
{
stop_glerror();
if (mIndex < 0) return false;
@ -260,6 +270,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
setTextureFilteringOption(texture->mFilterOption);
}
}
return true;
}

View File

@ -149,8 +149,8 @@ public:
// Binds the LLImageGL to this texture unit
// (automatically enables the unit for the LLImageGL's texture type)
bool bind(LLImageGL* texture, bool forceBind = false);
bool bind(LLTexture* texture, bool forceBind = false);
bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false);
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
// Binds a cubemap to this texture unit
// (automatically enables the texture unit for cubemaps)

View File

@ -61,7 +61,7 @@ public:
//
//interfaces to access LLViewerTexture
//
virtual bool bindDefaultImage(const S32 stage = 0) const = 0 ;
virtual bool bindDefaultImage(const S32 stage = 0) = 0 ;
virtual void forceImmediateUpdate() = 0 ;
virtual void setActive() = 0 ;
virtual S32 getWidth(S32 discard_level = -1) const = 0 ;

View File

@ -189,7 +189,7 @@ bool LLLFSThread::Request::processRequest()
{
llassert(mOffset >= 0);
LLAPRFile infile ;
infile.open(mThread->getLocalAPRFilePool(), mFileName, LL_APR_RB);
infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
if (!infile.getFileHandle())
{
llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
@ -213,7 +213,7 @@ bool LLLFSThread::Request::processRequest()
if (mOffset < 0)
flags |= APR_APPEND;
LLAPRFile outfile ;
outfile.open(mThread->getLocalAPRFilePool(), mFileName, flags);
outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
if (!outfile.getFileHandle())
{
llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;

View File

@ -265,7 +265,6 @@ set(viewer_SOURCE_FILES
llmaniprotate.cpp
llmanipscale.cpp
llmaniptranslate.cpp
llmapresponders.cpp
llmediactrl.cpp
llmediadataclient.cpp
llmediaremotectrl.cpp
@ -387,6 +386,10 @@ set(viewer_SOURCE_FILES
lltexturecache.cpp
lltexturectrl.cpp
lltexturefetch.cpp
lltextureinfo.cpp
lltextureinfodetails.cpp
lltexturestats.cpp
lltexturestatsuploader.cpp
lltextureview.cpp
lltoast.cpp
lltoastalertpanel.cpp
@ -508,6 +511,8 @@ set(viewer_SOURCE_FILES
llwlparamset.cpp
llworld.cpp
llworldmap.cpp
llworldmapmessage.cpp
llworldmipmap.cpp
llworldmapview.cpp
llxmlrpctransaction.cpp
noise.cpp
@ -738,7 +743,6 @@ set(viewer_HEADER_FILES
llmaniprotate.h
llmanipscale.h
llmaniptranslate.h
llmapresponders.h
llmediadataclient.h
llmediaremotectrl.h
llmemoryview.h
@ -859,6 +863,10 @@ set(viewer_HEADER_FILES
lltexturecache.h
lltexturectrl.h
lltexturefetch.h
lltextureinfo.h
lltextureinfodetails.h
lltexturestats.h
lltexturestatsuploader.h
lltextureview.h
lltoast.h
lltoastalertpanel.h
@ -982,6 +990,8 @@ set(viewer_HEADER_FILES
llwlparamset.h
llworld.h
llworldmap.h
llworldmapmessage.h
llworldmipmap.h
llworldmapview.h
llxmlrpctransaction.h
macmain.h
@ -1574,6 +1584,12 @@ LL_ADD_INTEGRATION_TEST(llcapabilitylistener
)
#ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
#ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
#ADD_VIEWER_BUILD_TEST(llworldmap viewer)
#ADD_VIEWER_BUILD_TEST(llworldmipmap viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py

View File

@ -309,7 +309,18 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoAcceptNewInventory</key>
<key>AuditTexture</key>
<map>
<key>Comment</key>
<string>Enable texture auditting.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoAcceptNewInventory</key>
<map>
<key>Comment</key>
<string>Automatically accept new notecards/textures/landmarks</string>
@ -4545,6 +4556,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>MiniMapPrimMaxRadius</key>
<map>
<key>Comment</key>
<string>Radius of the largest prim to show on the MiniMap. Increasing beyond 256 may cause client lag.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>256.0</real>
</map>
<key>MiniMapRotate</key>
<map>
<key>Comment</key>
@ -4559,7 +4581,7 @@
<key>MiniMapScale</key>
<map>
<key>Comment</key>
<string>Miniature world map zoom levle (pixels per region)</string>
<string>Miniature world map zoom level (pixels per region)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -8468,6 +8490,28 @@
<key>Value</key>
<real>20.0</real>
</map>
<key>TextureDisable</key>
<map>
<key>Comment</key>
<string>If TRUE, do not load textures for in-world content</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureLoadFullRes</key>
<map>
<key>Comment</key>
<string>If TRUE, always load textures at full resolution (discard = 0)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureMemory</key>
<map>
<key>Comment</key>
@ -10537,5 +10581,38 @@
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>LogTextureDownloadsToViewerLog</key>
<map>
<key>Comment</key>
<string>Send texture download details to the viewer log</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LogTextureDownloadsToSimulator</key>
<map>
<key>Comment</key>
<string>Send a digest of texture info to the sim</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureLoggingThreshold</key>
<map>
<key>Comment</key>
<string>Specifies the byte threshold at which texture download data should be sent to the sim.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
</llsd>

View File

@ -74,6 +74,8 @@
#include "llstatusbar.h"
#include "llteleportflags.h"
#include "llteleporthistory.h"
#include "lltexturestats.h"
#include "lltexturestats.h"
#include "lltool.h"
#include "lltoolcomp.h"
#include "lltoolmgr.h"
@ -6087,17 +6089,16 @@ void LLAgent::teleportCancel()
void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
{
LLViewerRegion* regionp = getRegion();
LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
U64 handle = to_region_handle(pos_global);
LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
if(regionp && info)
{
U32 x_pos;
U32 y_pos;
from_region_handle(info->mHandle, &x_pos, &y_pos);
LLVector3d region_origin = info->getGlobalOrigin();
LLVector3 pos_local(
(F32)(pos_global.mdV[VX] - x_pos),
(F32)(pos_global.mdV[VY] - y_pos),
(F32)(pos_global.mdV[VX] - region_origin.mdV[VX]),
(F32)(pos_global.mdV[VY] - region_origin.mdV[VY]),
(F32)(pos_global.mdV[VZ]));
teleportRequest(info->mHandle, pos_local);
teleportRequest(handle, pos_local);
}
else if(regionp &&
teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY])))
@ -6514,3 +6515,4 @@ LLAgentQueryManager::~LLAgentQueryManager()
}
// EOF

View File

@ -58,6 +58,8 @@
#include "llallocator.h"
#include "llares.h"
#include "llcurl.h"
#include "lltexturestats.h"
#include "lltexturestats.h"
#include "llviewerwindow.h"
#include "llviewerdisplay.h"
#include "llviewermedia.h"
@ -248,9 +250,6 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
BOOL gDisconnected = FALSE;
// Map scale in pixels per region
F32 gMapScale = 128.f;
// used to restore texture state after a mode switch
LLFrameTimer gRestoreGLTimer;
BOOL gRestoreGL = FALSE;
@ -413,7 +412,7 @@ static void settings_to_globals()
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
gMapScale = gSavedSettings.getF32("MapScale");
LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
}
@ -426,7 +425,7 @@ static void settings_modify()
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
#if LL_VECTORIZE
if (gSysCPU.hasAltivec())
{
@ -547,7 +546,7 @@ LLAppViewer* LLAppViewer::sInstance = NULL;
const std::string LLAppViewer::sGlobalSettingsName = "Global";
LLTextureCache* LLAppViewer::sTextureCache = NULL;
LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL;
LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL;
LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
LLAppViewer::LLAppViewer() :
@ -639,6 +638,9 @@ bool LLAppViewer::init()
//////////////////////////////////////////////////////////////////////////////
// *FIX: The following code isn't grouped into functions yet.
// Statistics / debug timer initialization
init_statistics();
//
// Various introspection concerning the libs we're using - particularly
// the libs involved in getting to a full login screen.
@ -1596,14 +1598,14 @@ bool LLAppViewer::initThreads()
LLWatchdog::getInstance()->init(watchdog_killer_callback);
}
LLVFSThread::initClass(enable_threads && true);
LLLFSThread::initClass(enable_threads && true);
LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false);
// Image decoding
LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true);
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false);
LLImage::initClass(LLAppViewer::getImageDecodeThread());
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
LLImage::initClass();
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
{
@ -2397,7 +2399,7 @@ void LLAppViewer::cleanupSavedSettings()
}
}
gSavedSettings.setF32("MapScale", gMapScale );
gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
// Some things are cached in LLAgent.
if (gAgent.mInitialized)
@ -2723,7 +2725,7 @@ void LLAppViewer::initMarkerFile()
// Create the marker file for this execution & lock it
apr_status_t s;
s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp);
s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);
if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
{
@ -4109,3 +4111,4 @@ void LLAppViewer::handleLoginComplete()
writeDebugInfo();
}

View File

@ -41,12 +41,10 @@ class LLCommandLineParser;
class LLFrameTimer;
class LLPumpIO;
class LLTextureCache;
class LLImageDecodeThread;
class LLTextureFetch;
class LLTimer;
class LLVFS;
class LLWatchdogTimeout;
class LLWorkerThread;
class LLCommandLineParser;
class LLAppViewer : public LLApp
{
@ -98,7 +96,7 @@ public:
// Thread accessors
static LLTextureCache* getTextureCache() { return sTextureCache; }
static LLWorkerThread* getImageDecodeThread() { return sImageDecodeThread; }
static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; }
static LLTextureFetch* getTextureFetch() { return sTextureFetch; }
const std::string& getSerialNumber() { return mSerialNumber; }
@ -228,7 +226,7 @@ private:
// Thread objects.
static LLTextureCache* sTextureCache;
static LLWorkerThread* sImageDecodeThread;
static LLImageDecodeThread* sImageDecodeThread;
static LLTextureFetch* sTextureFetch;
S32 mNumSessions;
@ -322,9 +320,6 @@ extern F32 gSimFrames;
extern BOOL gDisconnected;
// Map scale in pixels per region
extern F32 gMapScale;
extern LLFrameTimer gRestoreGLTimer;
extern BOOL gRestoreGL;
extern BOOL gUseWireframe;

View File

@ -368,7 +368,7 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
std::string result = content["state"];
LLUUID new_id = content["new_asset"];
llinfos << "LLSendTexLayerResponder::result from capabilities: " << result << llendl;
llinfos << "result: " << result << "new_id:" << new_id << llendl;
if (result == "complete"
&& mBakedUploadData != NULL)
{ // Invoke
@ -382,6 +382,14 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
}
}
void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason)
{
llinfos << "status: " << statusNum << " reason: " << reason << llendl;
// Invoke the original callback with an error result
LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
}
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
const LLUUID& vfile_id,

View File

@ -84,6 +84,7 @@ public:
~LLSendTexLayerResponder();
virtual void uploadComplete(const LLSD& content);
virtual void error(U32 statusNum, const std::string& reason);
LLBakedUploadData * mBakedUploadData;
};

View File

@ -228,7 +228,7 @@ void LLColorSwatchCtrl::draw()
{
if (!mFallbackImageName.empty())
{
LLPointer<LLViewerTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
if( fallback_image->getComponents() == 4 )
{
gl_rect_2d_checkerboard( interior );

View File

@ -45,7 +45,7 @@
#include "llviewerwindow.h"
#include "llappviewer.h"
#include "llmemoryview.h"
#include "llviewertexture.h"
//
// Globals
//
@ -102,17 +102,29 @@ LLDebugView::LLDebugView(const LLDebugView::Params& p)
gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
//gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE);
#if !LL_RELEASE_FOR_DOWNLOAD
r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100);
LLTextureSizeView::Params tsvp;
tsvp.name("gTextureSizeView");
tsvp.rect(r);
tsvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
tsvp.visible(false);
gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsvp);
addChild(gTextureSizeView);
#endif
if(gAuditTexture)
{
r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100);
LLTextureSizeView::Params tsv ;
tsv.name("gTextureSizeView");
tsv.rect(r);
tsv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
tsv.visible(false);
gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsv);
addChild(gTextureSizeView);
gTextureSizeView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_SIZE) ;
r.set(150, rect.getHeight() - 50, 900 + LLViewerTexture::getTotalNumOfCategories() * 30, 100);
LLTextureSizeView::Params tcv ;
tcv.name("gTextureCategoryView");
tcv.rect(r);
tcv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
tcv.visible(false);
gTextureCategoryView = LLUICtrlFactory::create<LLTextureSizeView>(tcv);
gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY);
addChild(gTextureCategoryView);
}
}
@ -122,5 +134,6 @@ LLDebugView::~LLDebugView()
gDebugView = NULL;
gTextureView = NULL;
gTextureSizeView = NULL;
gTextureCategoryView = NULL;
}

View File

@ -105,7 +105,7 @@ void LLDrawable::init()
mVObjp = NULL;
// mFaces
mSpatialGroupp = NULL;
mVisible = 0;
mVisible = sCurVisible - 2;//invisible for the current frame and the last frame.
mRadius = 0.f;
mGeneration = -1;

View File

@ -279,7 +279,7 @@ S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage)
iter != face_list.end(); iter++)
{
LLFace *facep = *iter;
gGL.getTexUnit(stage)->bind(facep->getTexture());
gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ;
gGL.getTexUnit(0)->activate();
res += facep->renderIndexed();
}
@ -474,17 +474,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
if (params.mTexture.notNull())
{
gGL.getTexUnit(0)->bind(params.mTexture.get());
gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
if (params.mTextureMatrix)
{
glMatrixMode(GL_TEXTURE);
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
gPipeline.mTextureMatrixOps++;
}
if(params.mTexture.notNull())//will be removed.
{
params.mTexture->addTextureStats(params.mVSize);
}
}
else
{

View File

@ -219,7 +219,7 @@ void LLDrawPoolAlpha::render(S32 pass)
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
glColor4f(1,0,0,1);
LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep) ;
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0);
}

View File

@ -253,7 +253,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
LLGLState normalize(GL_NORMALIZE, TRUE);
// Bind the texture for this tree.
gGL.getTexUnit(sDiffTex)->bind(mTexturep.get());
gGL.getTexUnit(sDiffTex)->bind(mTexturep.get(), TRUE);
U32 indices_drawn = 0;

View File

@ -104,7 +104,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum
{
setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
}
createGLTexture(0, raw_image);
createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX);
setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP);
mGLTexturep->setGLTextureCreated(false);
}

View File

@ -52,6 +52,7 @@
#include "llvovolume.h"
#include "pipeline.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#define LL_MAX_INDICES_COUNT 1000000
@ -175,6 +176,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mLastIndicesCount = mIndicesCount;
mLastIndicesIndex = mIndicesIndex;
mImportanceToCamera = 0.f ;
mBoundingSphereRadius = 0.0f ;
mAtlasInfop = NULL ;
mUsingAtlas = FALSE ;
}
@ -186,6 +190,7 @@ void LLFace::destroy()
{
mTexture->removeFace(this) ;
}
if (mDrawPoolp)
{
mDrawPoolp->removeFace(this);
@ -207,7 +212,7 @@ void LLFace::destroy()
}
}
}
setDrawInfo(NULL);
removeAtlas();
@ -256,6 +261,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
}
mDrawPoolp = new_pool;
}
setTexture(texturep) ;
}
@ -750,7 +756,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
}
mCenterLocal = (newMin+newMax)*0.5f;
LLVector3 tmp = (newMin - newMax) ;
mBoundingSphereRadius = tmp.length() * 0.5f ;
updateCenterAgent();
}
@ -1305,6 +1313,151 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return TRUE;
}
const F32 LEAST_IMPORTANCE = 0.05f ;
const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
F32 LLFace::getTextureVirtualSize()
{
F32 radius;
F32 cos_angle_to_view_dir;
mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius);
if (mPixelArea <= 0)
{
return 0.f;
}
//get area of circle in texture space
LLVector2 tdim = mTexExtents[1] - mTexExtents[0];
F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
if (texel_area <= 0)
{
// Probably animated, use default
texel_area = 1.f;
}
//apply texel area to face area to get accurate ratio
//face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
F32 face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f);
if(face_area > LLViewerTexture::sMaxSmallImageSize)
{
if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res.
{
static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ;
face_area = llmin(face_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ;
}
else if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
{
if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res.
{
face_area = LLViewerTexture::sMinLargeImageSize ;
}
else if(mTexture.notNull() && mTexture->isLargeImage())
{
face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
}
}
}
return face_area;
}
F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
{
//get area of circle around face
LLVector3 center = getPositionAgent();
LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f;
LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin();
F32 dist = lookAt.normVec() ;
//get area of circle around node
F32 app_angle = atanf(size.length()/dist);
radius = app_angle*LLDrawable::sCurPixelAngle;
F32 face_area = radius*radius * 3.14159f;
if(dist < mBoundingSphereRadius) //camera is very close
{
cos_angle_to_view_dir = 1.0f ;
mImportanceToCamera = 1.0f ;
}
else
{
cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
}
return face_area ;
}
//the projection of the face partially overlaps with the screen
F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius )
{
F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ;
F32 center_angle = acosf(cos_angle_to_view_dir) ;
F32 d = center_angle * LLDrawable::sCurPixelAngle ;
if(d + radius > screen_radius + 5.f)
{
//----------------------------------------------
//calculate the intersection area of two circles
//F32 radius_square = radius * radius ;
//F32 d_square = d * d ;
//F32 screen_radius_square = screen_radius * screen_radius ;
//face_area =
// radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
// screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
// 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;
//----------------------------------------------
//the above calculation is too expensive
//the below is a good estimation: bounding box of the bounding sphere:
F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
alpha = llclamp(alpha, 0.f, 1.f) ;
return alpha * alpha ;
}
return 1.0f ;
}
const S8 FACE_IMPORTANCE_LEVEL = 4 ;
const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight}
{{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ;
const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight}
{{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ;
//static
F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
{
F32 importance = 0.f ;
if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() &&
dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0])
{
F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f)
{
//if camera moves or rotates too fast, ignore the importance factor
return 0.f ;
}
//F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ;
S32 i = 0 ;
for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
}
return importance ;
}
BOOL LLFace::verify(const U32* indices_array) const
{
BOOL ok = TRUE;

View File

@ -188,6 +188,9 @@ public:
void setIndicesIndex(S32 idx) { mIndicesIndex = idx; }
void setDrawInfo(LLDrawInfo* draw_info);
F32 getTextureVirtualSize() ;
F32 getImportanceToCamera()const {return mImportanceToCamera ;}
//for atlas
LLTextureAtlasSlot* getAtlasInfo() ;
void setAtlasInUse(BOOL flag);
@ -200,6 +203,12 @@ public:
void removeAtlas() ;
BOOL switchTexture() ;
private:
F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius );
F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ;
public:
static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist);
public:
LLVector3 mCenterLocal;
@ -214,7 +223,7 @@ public:
LLMatrix4* mTextureMatrix;
LLDrawInfo* mDrawInfo;
protected:
private:
friend class LLGeometryManager;
friend class LLVolumeGeometryManager;
@ -244,9 +253,16 @@ protected:
F32 mVSize;
F32 mPixelArea;
//importance factor, in the range [0, 1.0].
//1.0: the most important.
//based on the distance from the face to the view point and the angle from the face center to the view direction.
F32 mImportanceToCamera ;
F32 mBoundingSphereRadius ;
//atlas
LLPointer<LLTextureAtlasSlot> mAtlasInfop ;
BOOL mUsingAtlas ;
BOOL mUsingAtlas ;
protected:
static BOOL sSafeRenderSelect;

View File

@ -50,12 +50,27 @@
#include "lltextbox.h"
#include "llviewermenu.h"
//
// Constants
//
const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f;
//
// Member functions
//
LLFloaterMap::LLFloaterMap(const LLSD& key)
: LLFloater(key)
: LLFloater(key),
mPopupMenu(NULL),
mTextBoxEast(NULL),
mTextBoxNorth(NULL),
mTextBoxWest(NULL),
mTextBoxSouth(NULL),
mTextBoxSouthEast(NULL),
mTextBoxNorthEast(NULL),
mTextBoxNorthWest(NULL),
mTextBoxSouthWest(NULL),
mMap(NULL)
{
//Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_map.xml", FALSE);
}
@ -92,6 +107,8 @@ BOOL LLFloaterMap::postBuild()
mPopupMenu->setItemEnabled ("Stop Tracking", false);
}
updateMinorDirections();
// Get the drag handle all the way in back
sendChildToBack(getDragHandle());
@ -139,6 +156,23 @@ void LLFloaterMap::setDirectionPos( LLTextBox* text_box, F32 rotation )
llround(map_half_height - text_half_height + radius * sin( rotation )) );
}
void LLFloaterMap::updateMinorDirections()
{
if (mTextBoxNorthEast == NULL)
{
return;
}
// Hide minor directions if they cover too much of the map
bool show_minors = mTextBoxNorthEast->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD *
llmin(getRect().getWidth(), getRect().getHeight());
mTextBoxNorthEast->setVisible(show_minors);
mTextBoxNorthWest->setVisible(show_minors);
mTextBoxSouthWest->setVisible(show_minors);
mTextBoxSouthEast->setVisible(show_minors);
}
// virtual
void LLFloaterMap::draw()
{
@ -180,17 +214,23 @@ void LLFloaterMap::draw()
LLFloater::draw();
}
void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLFloater::reshape(width, height, called_from_parent);
updateMinorDirections();
}
void LLFloaterMap::handleZoom(const LLSD& userdata)
{
std::string level = userdata.asString();
F32 scale = 0.0f;
if (level == std::string("close"))
scale = MAP_SCALE_MAX;
scale = LLNetMap::MAP_SCALE_MAX;
else if (level == std::string("medium"))
scale = MAP_SCALE_MID;
scale = LLNetMap::MAP_SCALE_MID;
else if (level == std::string("far"))
scale = MAP_SCALE_MIN;
scale = LLNetMap::MAP_SCALE_MIN;
if (scale != 0.0f)
{
gSavedSettings.setF32("MiniMapScale", scale );

View File

@ -51,12 +51,14 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void draw();
private:
void handleZoom(const LLSD& userdata);
void handleStopTracking (const LLSD& userdata);
void setDirectionPos( LLTextBox* text_box, F32 rotation );
void updateMinorDirections();
LLMenuGL* mPopupMenu;

View File

@ -790,7 +790,7 @@ void LLFloaterReporter::takeScreenshot()
// store in the image list so it doesn't try to fetch from the server
LLPointer<LLViewerFetchedTexture> image_in_list =
LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, FALSE, LLViewerTexture::FETCHED_TEXTURE);
image_in_list->createGLTexture(0, raw);
image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER);
// the texture picker then uses that texture
LLTexturePicker* texture = getChild<LLTextureCtrl>("screenshot");

View File

@ -55,7 +55,6 @@
#include "llregionhandle.h"
#include "llscrolllistctrl.h"
#include "llslurl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltracker.h"
#include "lltrans.h"
@ -63,7 +62,9 @@
#include "llviewermenu.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewertexture.h"
#include "llworldmap.h"
#include "llworldmapmessage.h"
#include "llworldmapview.h"
#include "lluictrlfactory.h"
#include "llappviewer.h"
@ -79,6 +80,12 @@
//---------------------------------------------------------------------------
static const F32 MAP_ZOOM_TIME = 0.2f;
// Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed
// width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across
// sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
static const S32 MAX_VISIBLE_REGIONS = 512;
enum EPanDirection
{
PAN_UP,
@ -160,11 +167,11 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
gFloaterWorldMap = this;
mFactoryMap["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
mFactoryMap["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL);
//Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", FALSE);
mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this));
mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this));
mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this));
mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this));
mCommitCallbackRegistrar.add("WMap.CommitLocation", boost::bind(&LLFloaterWorldMap::onCommitLocation, this));
mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this));
@ -183,17 +190,7 @@ void* LLFloaterWorldMap::createWorldMapView(void* data)
BOOL LLFloaterWorldMap::postBuild()
{
mTabs = getChild<LLTabContainer>("maptab");
if (!mTabs) return FALSE;
mTabs->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCommitBackground, this));
// The following callback syncs the worlmap tabs with the images.
// Commented out since it was crashing when LLWorldMap became a singleton.
// We should be fine without it but override the onOpen method and put it
// there if it turns out to be needed. -MG
//
//onCommitBackground();
mPanel = getChild<LLPanel>("objects_mapview");
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
if (avatar_combo)
@ -221,8 +218,8 @@ BOOL LLFloaterWorldMap::postBuild()
landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
}
mCurZoomVal = log(gMapScale)/log(2.f);
childSetValue("zoom slider", gMapScale);
mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);
childSetValue("zoom slider", LLWorldMapView::sMapScale);
setDefaultBtn(NULL);
@ -235,7 +232,7 @@ BOOL LLFloaterWorldMap::postBuild()
LLFloaterWorldMap::~LLFloaterWorldMap()
{
// All cleaned up by LLView destructor
mTabs = NULL;
mPanel = NULL;
// Inventory deletes all observers on shutdown
mInventory = NULL;
@ -268,7 +265,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
mIsClosing = FALSE;
LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)mTabs->getCurrentPanel();
map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->clearLastClick();
{
@ -279,15 +276,8 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
}
map_panel->updateVisibleBlocks();
// Reload the agent positions when we show the window
LLWorldMap::getInstance()->eraseItems();
// Reload any maps that may have changed
LLWorldMap::getInstance()->clearSimFlags();
const S32 panel_num = mTabs->getCurrentPanelIndex();
const bool request_from_sim = true;
LLWorldMap::getInstance()->setCurrentLayer(panel_num, request_from_sim);
// Reload items as they may have changed
LLWorldMap::getInstance()->reloadItems();
// We may already have a bounding box for the regions of the world,
// so use that to adjust the view.
@ -321,12 +311,9 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
// static
void LLFloaterWorldMap::reloadIcons(void*)
{
LLWorldMap::getInstance()->eraseItems();
LLWorldMap::getInstance()->sendMapLayerRequest();
LLWorldMap::getInstance()->reloadItems();
}
// virtual
BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)
{
@ -358,12 +345,6 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent )
{
LLFloater::reshape( width, height, called_from_parent );
// Might have changed size of world display area
// JC: Technically, this is correct, but it makes the slider "pop"
// if you resize the window, then draw the slider. Just leaving it
// the way it was when you opened the window seems better.
// adjustZoomSliderBounds();
}
@ -445,7 +426,7 @@ void LLFloaterWorldMap::draw()
childSetEnabled("Teleport", (BOOL)tracking_status);
// childSetEnabled("Clear", (BOOL)tracking_status);
childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation);
childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking());
childSetEnabled("copy_slurl", (mSLURL.size() > 0) );
setMouseOpaque(TRUE);
@ -465,6 +446,18 @@ void LLFloaterWorldMap::draw()
mCurZoomVal = lerp(mCurZoomVal, (F32)childGetValue("zoom slider").asReal(), interp);
F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
LLWorldMapView::setScale( map_scale );
// Enable/disable checkboxes depending on the zoom level
// If above threshold level (i.e. low res) -> Disable all checkboxes
// If under threshold level (i.e. high res) -> Enable all checkboxes
bool enable = LLWorldMapView::showRegionInfo();
childSetEnabled("people_chk", enable);
childSetEnabled("infohub_chk", enable);
childSetEnabled("telehub_chk", enable);
childSetEnabled("land_for_sale_chk", enable);
childSetEnabled("event_chk", enable);
childSetEnabled("event_mature_chk", enable);
childSetEnabled("event_adult_chk", enable);
LLFloater::draw();
}
@ -553,14 +546,14 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info)
{
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(event_info.mPosGlobal, event_info.mName, event_info.mToolTip, LLTracker::LOCATION_EVENT);
LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT);
setDefaultBtn("Teleport");
}
void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
{
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(item.mPosGlobal, item.mName, item.mToolTip, LLTracker::LOCATION_ITEM);
LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM);
setDefaultBtn("Teleport");
}
@ -569,29 +562,27 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
if (!sim_info)
{
LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE;
LLWorldMap::getInstance()->mInvalidLocation = FALSE;
LLWorldMap::getInstance()->mUnknownLocation = pos_global;
// We haven't found a region for that point yet, leave the tracking to the world map
LLWorldMap::getInstance()->setTracking(pos_global);
LLTracker::stopTracking(NULL);
S32 world_x = S32(pos_global.mdV[0] / 256);
S32 world_y = S32(pos_global.mdV[1] / 256);
LLWorldMap::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
setDefaultBtn("");
return;
}
if (sim_info->mAccess == SIM_ACCESS_DOWN)
if (sim_info->isDown())
{
// Down sim. Show the blue circle of death!
LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE;
LLWorldMap::getInstance()->mUnknownLocation = pos_global;
LLWorldMap::getInstance()->mInvalidLocation = TRUE;
// Down region. Show the blue circle of death!
// i.e. let the world map that this and tell it it's invalid
LLWorldMap::getInstance()->setTracking(pos_global);
LLWorldMap::getInstance()->setTrackingInvalid();
LLTracker::stopTracking(NULL);
setDefaultBtn("");
return;
}
std::string sim_name;
LLWorldMap::getInstance()->simNameFromPosGlobal( pos_global, sim_name );
std::string sim_name = sim_info->getName();
F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
std::string full_name = llformat("%s (%d, %d, %d)",
@ -603,9 +594,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
std::string tooltip("");
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(pos_global, full_name, tooltip);
LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE;
LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
setDefaultBtn("Teleport");
}
@ -718,9 +707,9 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3
// pass sim name to combo box
gFloaterWorldMap->mCompletingRegionName = region_name;
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name);
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name);
LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName);
LLWorldMap::getInstance()->mIsTrackingCommit = TRUE;
LLWorldMap::getInstance()->setTrackingCommit();
}
}
@ -787,19 +776,12 @@ void LLFloaterWorldMap::buildAvatarIDList()
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
while (list_size > 1)
if (list_size > 1)
{
list->selectNthItem(1);
list->selectItemRange(1, -1);
list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
--list_size;
}
LLSD default_column;
default_column["name"] = "friend name";
default_column["label"] = "Friend Name";
default_column["width"] = 500;
list->addColumn(default_column);
// Get all of the calling cards for avatar that are currently online
LLCollectMappableBuddies collector;
LLAvatarTracker::instance().applyFunctor(collector);
@ -820,10 +802,7 @@ void LLFloaterWorldMap::buildAvatarIDList()
void LLFloaterWorldMap::buildLandmarkIDLists()
{
LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list)
{
return;
}
if (!list) return;
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
@ -864,7 +843,6 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
mLandmarkAssetIDList.put( item->getAssetUUID() );
mLandmarkItemIDList.put( item->getUUID() );
}
list->sortByColumn(std::string("landmark name"), TRUE);
list->selectFirstItem();
}
@ -901,7 +879,7 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
{
childSetValue("spin z", 0);
}
LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
LLWorldMap::getInstance()->cancelTracking();
mCompletingRegionName = "";
}
@ -937,18 +915,16 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui)
// can see the whole world, plus a little.
void LLFloaterWorldMap::adjustZoomSliderBounds()
{
// World size in regions
S32 world_width_regions = LLWorldMap::getInstance()->getWorldWidth() / REGION_WIDTH_UNITS;
S32 world_height_regions = LLWorldMap::getInstance()->getWorldHeight() / REGION_WIDTH_UNITS;
// Pad the world size a little bit, so we have a nice border on
// the edge
world_width_regions++;
world_height_regions++;
// Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed
// width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across
// sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
S32 world_width_regions = MAX_VISIBLE_REGIONS;
S32 world_height_regions = MAX_VISIBLE_REGIONS;
// Find how much space we have to display the world
LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)mTabs->getCurrentPanel();
map_panel = (LLWorldMapView*)mPanel;
LLRect view_rect = map_panel->getRect();
// View size in pixels
@ -1161,15 +1137,15 @@ void LLFloaterWorldMap::onLocationCommit()
LLStringUtil::toLower(str);
mCompletingRegionName = str;
LLWorldMap::getInstance()->mIsTrackingCommit = TRUE;
LLWorldMap::getInstance()->setTrackingCommit();
if (str.length() >= 3)
{
LLWorldMap::getInstance()->sendNamedRegionRequest(str);
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
}
else
{
str += "#";
LLWorldMap::getInstance()->sendNamedRegionRequest(str);
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
}
}
@ -1177,8 +1153,8 @@ void LLFloaterWorldMap::onClearBtn()
{
mTrackedStatus = LLTracker::TRACKING_NOTHING;
LLTracker::stopTracking((void *)(intptr_t)TRUE);
LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
mSLURL = ""; // Clear the SLURL since it's invalid
LLWorldMap::getInstance()->cancelTracking();
mSLURL = ""; // Clear the SLURL since it's invalid
mSetToUserPosition = TRUE; // Revert back to the current user position
}
@ -1230,9 +1206,9 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
pos_global = LLTracker::getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();
}
}
else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
else if(LLWorldMap::getInstance()->isTracking())
{
pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgent.getCameraPositionGlobal();;
pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();;
}
else
{
@ -1240,8 +1216,8 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
pos_global.clearVec();
}
LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sPixelsPerMeter)),
-llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sPixelsPerMeter)),
LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
-llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
!animate);
mWaitingForTracker = FALSE;
}
@ -1399,13 +1375,6 @@ void LLFloaterWorldMap::flyToAvatar()
}
}
void LLFloaterWorldMap::onCommitBackground()
{
// Find my index
S32 index = mTabs->getCurrentPanelIndex();
LLWorldMap::getInstance()->setCurrentLayer(index);
}
void LLFloaterWorldMap::updateSims(bool found_null_sim)
{
if (mCompletingRegionName == "")
@ -1422,24 +1391,23 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
S32 num_results = 0;
std::map<U64, LLSimInfo*>::const_iterator it;
for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
LLSimInfo* info = (*it).second;
std::string sim_name = info->mName;
std::string sim_name_lower = sim_name;
LLSimInfo* info = it->second;
std::string sim_name_lower = info->getName();
LLStringUtil::toLower(sim_name_lower);
if (sim_name_lower.substr(0, name_length) == mCompletingRegionName)
{
if (sim_name_lower == mCompletingRegionName)
{
match = sim_name;
match = info->getName();
}
LLSD value;
value["id"] = sim_name;
value["id"] = info->getName();
value["columns"][0]["column"] = "sim_name";
value["columns"][0]["value"] = sim_name;
value["columns"][0]["value"] = info->getName();
list->addElement(value);
num_results++;
}
@ -1496,15 +1464,13 @@ void LLFloaterWorldMap::onCommitSearchResult()
LLStringUtil::toLower(sim_name);
std::map<U64, LLSimInfo*>::const_iterator it;
for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
LLSimInfo* info = (*it).second;
std::string info_sim_name = info->mName;
LLStringUtil::toLower(info_sim_name);
LLSimInfo* info = it->second;
if (sim_name == info_sim_name)
if (info->isName(sim_name))
{
LLVector3d pos_global = from_region_handle( info->mHandle );
LLVector3d pos_global = info->getGlobalOrigin();
F64 local_x = childGetValue("spin x");
F64 local_y = childGetValue("spin y");
F64 local_z = childGetValue("spin z");

View File

@ -96,7 +96,7 @@ public:
static const LLUUID& getHomeID() { return sHomeID; }
// A z_attenuation of 0.0f collapses the distance into the X-Y plane
F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const;
F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const;
void clearLocationSelection(BOOL clear_ui = FALSE);
void clearAvatarSelection(BOOL clear_ui = FALSE);
@ -121,8 +121,6 @@ protected:
void onAvatarComboPrearrange();
void onAvatarComboCommit();
void onCommitBackground();
void onComboTextEntry( );
void onSearchTextEntry( LLLineEditor* ctrl );
@ -155,10 +153,10 @@ protected:
void cacheLandmarkPosition();
protected:
LLTabContainer* mTabs;
private:
LLPanel* mPanel; // Panel displaying the map
// Sets gMapScale, in pixels per region
// Ties to LLWorldMapView::sMapScale, in pixels per region
F32 mCurZoomVal;
LLFrameTimer mZoomTimer;

View File

@ -49,6 +49,7 @@
#include "llstring.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llworldmapmessage.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "llworldmap.h"
@ -268,13 +269,13 @@ void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slur
{
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
cb,
global_pos,
escaped,
_2);
LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
}
}
@ -285,18 +286,19 @@ void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& gl
if (sim_infop)
{
LLVector3 pos = sim_infop->getLocalPos(global_pos);
cb(sim_infop->mName, llround(pos.mV[VX]), llround(pos.mV[VY]));
std::string name = sim_infop->getName() ;
cb(name, llround(pos.mV[VX]), llround(pos.mV[VY]));
}
else
{
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
cb,
global_pos,
_1);
LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
}
}
@ -328,7 +330,8 @@ void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_cal
if (sim_infop)
{
LLVector3 local_pos = sim_infop->getLocalPos(global_pos);
cb(sim_infop->mName, llround(local_pos.mV[VX]), llround(local_pos.mV[VY]));
std::string name = sim_infop->getName() ;
cb(name, llround(local_pos.mV[VX]), llround(local_pos.mV[VY]));
}
}

View File

@ -51,7 +51,7 @@
#include "llurlsimstring.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llworldmap.h"
#include "llworldmapmessage.h"
#include "llappviewer.h"
#include "llviewercontrol.h"
#include "llfloatermediabrowser.h"
@ -386,14 +386,13 @@ void LLNavigationBar::onLocationSelection()
// Resolve the region name to its global coordinates.
// If resolution succeeds we'll teleport.
LLWorldMap::url_callback_t cb = boost::bind(
LLWorldMapMessage::url_callback_t cb = boost::bind(
&LLNavigationBar::onRegionNameResponse, this,
typed_location, region_name, local_coords, _1, _2, _3, _4);
// connect the callback each time, when user enter new location to get real location of agent after teleport
mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1,typed_location));
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false);
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false);
}
void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location)

View File

@ -65,9 +65,15 @@
static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map");
const F32 LLNetMap::MAP_SCALE_MIN = 32;
const F32 LLNetMap::MAP_SCALE_MID = 1024;
const F32 LLNetMap::MAP_SCALE_MAX = 4096;
const F32 MAP_SCALE_INCREMENT = 16;
const F32 MAP_MIN_PICK_DIST = 4;
const F32 MAX_PRIM_RADIUS = 256.0f; // Don't try to draw giant mega-prims on the mini map
const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%)
const F32 MIN_DOT_RADIUS = 3.5f;
const F32 DOT_SCALE = 0.75f;
const F32 MIN_PICK_SCALE = 2.f;
LLNetMap::LLNetMap (const Params & p)
: LLUICtrl (p),
@ -89,6 +95,7 @@ LLNetMap::LLNetMap (const Params & p)
mRotateMap(FALSE),
mToolTipMsg()
{
mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
}
LLNetMap::~LLNetMap()
@ -101,17 +108,18 @@ void LLNetMap::setScale( F32 scale )
if (mObjectImagep.notNull())
{
F32 half_width = (F32)(getRect().getWidth() / 2);
F32 half_height = (F32)(getRect().getHeight() / 2);
F32 radius = sqrt( half_width * half_width + half_height * half_height );
F32 region_widths = (2.f*radius)/mScale;
F32 width = (F32)(getRect().getWidth());
F32 height = (F32)(getRect().getHeight());
F32 diameter = sqrt(width * width + height * height);
F32 region_widths = diameter / mScale;
F32 meters = region_widths * LLWorld::getInstance()->getRegionWidthInMeters();
F32 num_pixels = (F32)mObjectImagep->getWidth();
mObjectMapTPM = num_pixels/meters;
mObjectMapPixels = 2.f*radius;
mObjectMapTPM = num_pixels / meters;
mObjectMapPixels = diameter;
}
mPixelsPerMeter = mScale / REGION_WIDTH_METERS;
mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
mUpdateNow = TRUE;
}
@ -302,6 +310,7 @@ void LLNetMap::draw()
LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
mClosestAgentToCursor.setNull();
F32 closest_dist = F32_MAX;
F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE;
// Draw avatars
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
@ -345,10 +354,10 @@ void LLNetMap::draw()
LLWorldMapView::drawAvatar(
pos_map.mV[VX], pos_map.mV[VY],
show_as_friend ? map_avatar_friend_color : map_avatar_color,
pos_map.mV[VZ]);
pos_map.mV[VZ], mDotRadius);
F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y));
if(dist_to_cursor < MAP_MIN_PICK_DIST && dist_to_cursor < closest_dist)
if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist)
{
closest_dist = dist_to_cursor;
mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i);
@ -378,10 +387,12 @@ void LLNetMap::draw()
// Draw dot for self avatar position
pos_global = gAgent.getPositionGlobal();
pos_map = globalPosToView(pos_global);
LLUIImagePtr you = LLWorldMapView::sAvatarYouSmallImage;
you->draw(
llround(pos_map.mV[VX]) - you->getWidth()/2,
llround(pos_map.mV[VY]) - you->getHeight()/2);
LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
S32 dot_width = llround(mDotRadius * 2.f);
you->draw(llround(pos_map.mV[VX] - mDotRadius),
llround(pos_map.mV[VY] - mDotRadius),
dot_width,
dot_width);
// Draw frustum
F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters();
@ -429,6 +440,12 @@ void LLNetMap::draw()
LLUICtrl::draw();
}
void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLUICtrl::reshape(width, height, called_from_parent);
createObjectImage();
}
LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
{
LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal();
@ -504,8 +521,12 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )
BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
// note that clicks are reversed from what you'd think
setScale(llclamp(mScale - clicks*MAP_SCALE_INCREMENT, MAP_SCALE_MIN, MAP_SCALE_MAX));
// note that clicks are reversed from what you'd think: i.e. > 0 means zoom out, < 0 means zoom in
F32 scale = mScale;
scale *= pow(MAP_SCALE_ZOOM_FACTOR, -clicks);
setScale(llclamp(scale, MAP_SCALE_MIN, MAP_SCALE_MAX));
return TRUE;
}
@ -567,9 +588,7 @@ void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &
LLVector3 local_pos;
local_pos.setVec( pos - mObjectImageCenterGlobal );
F32 radius_clamped = llmin(radius_meters, MAX_PRIM_RADIUS);
S32 diameter_pixels = llround(2 * radius_clamped * mObjectMapTPM);
S32 diameter_pixels = llround(2 * radius_meters * mObjectMapTPM);
renderPoint( local_pos, color, diameter_pixels );
}
@ -662,13 +681,13 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
void LLNetMap::createObjectImage()
{
// Find the size of the side of a square that surrounds the circle that surrounds getRect().
F32 half_width = (F32)(getRect().getWidth() / 2);
F32 half_height = (F32)(getRect().getHeight() / 2);
F32 radius = sqrt( half_width * half_width + half_height * half_height );
S32 square_size = S32( 2 * radius );
// ... which is, the diagonal of the rect.
F32 width = (F32)getRect().getWidth();
F32 height = (F32)getRect().getHeight();
S32 square_size = llround( sqrt(width*width + height*height) );
// Find the least power of two >= the minimum size.
const S32 MIN_SIZE = 32;
const S32 MIN_SIZE = 64;
const S32 MAX_SIZE = 256;
S32 img_size = MIN_SIZE;
while( (img_size*2 < square_size ) && (img_size < MAX_SIZE) )
@ -684,7 +703,7 @@ void LLNetMap::createObjectImage()
U8* data = mObjectRawImagep->getData();
memset( data, 0, img_size * img_size * 4 );
mObjectImagep = LLViewerTextureManager::getLocalTexture( mObjectRawImagep.get(), FALSE);
setScale(mScale);
}
setScale(mScale);
mUpdateNow = TRUE;
}

View File

@ -70,9 +70,14 @@ protected:
public:
virtual ~LLNetMap();
static const F32 MAP_SCALE_MIN;
static const F32 MAP_SCALE_MID;
static const F32 MAP_SCALE_MAX;
/*virtual*/ void draw();
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleToolTip( S32 x, S32 y, MASK mask);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
void setScale( F32 scale );
void setRotateMap( BOOL b ) { mRotateMap = b; }
@ -94,16 +99,17 @@ private:
void drawTracking( const LLVector3d& pos_global,
const LLColor4& color,
BOOL draw_arrow = TRUE);
void createObjectImage();
void createObjectImage();
private:
LLUIColor mBackgroundColor;
F32 mScale; // Size of a region in pixels
F32 mPixelsPerMeter; // world meters to map pixels
F32 mObjectMapTPM; // texels per meter on map
F32 mObjectMapPixels; // Width of object map in pixels;
F32 mObjectMapPixels; // Width of object map in pixels
F32 mDotRadius; // Size of avatar markers
F32 mTargetPanX;
F32 mTargetPanY;
F32 mCurPanX;

View File

@ -357,7 +357,7 @@ void LLTeleportHistoryPanel::onCopySLURL()
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMap::url_callback_t cb = boost::bind(
LLWorldMapMessage::url_callback_t cb = boost::bind(
&LLPanelPlacesTab::onRegionResponse, this,
global_pos, _1, _2, _3, _4);

View File

@ -192,6 +192,11 @@ void LLPreviewTexture::draw()
// Pump the texture priority
F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
mImage->addTextureStats( pixel_area );
if(pixel_area > 0.f)
{
//boost the previewed image priority to the highest to make it to get loaded first.
mImage->setAdditionalDecodePriority(1.0f) ;
}
// Don't bother decoding more than we can display, unless
// we're loading the full image.
@ -554,6 +559,7 @@ void LLPreviewTexture::loadAsset()
{
mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
mImage->forceToSaveRawImage(0) ;
mAssetStatus = PREVIEW_ASSET_LOADING;
updateDimensions();
}

View File

@ -2679,8 +2679,7 @@ void renderTexturePriority(LLDrawable* drawable)
//LLViewerTexture* imagep = facep->getTexture();
//if (imagep)
{
//F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
//F32 vsize = imagep->mMaxVirtualSize;
F32 vsize = facep->getPixelArea();

View File

@ -61,6 +61,7 @@
#include "llfocusmgr.h"
#include "llhttpsender.h"
#include "lllocationhistory.h"
#include "llimageworker.h"
#include "llloginflags.h"
#include "llmd5.h"
#include "llmemorystream.h"
@ -170,7 +171,7 @@
#include "llvoclouds.h"
#include "llweb.h"
#include "llworld.h"
#include "llworldmap.h"
#include "llworldmapmessage.h"
#include "llxfermanager.h"
#include "pipeline.h"
#include "llappviewer.h"
@ -1812,6 +1813,7 @@ bool idle_startup()
gViewerWindow->moveProgressViewToFront();
LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
// set initial visibility of debug console
gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
}
@ -3266,9 +3268,8 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply);
msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply);
msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply);
msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply);
msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply);
msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply);
msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply);

View File

@ -234,12 +234,7 @@ void LLSurface::createSTexture()
{
if (!mSTexturep)
{
// Fill with dummy gray data.
//mSTexturep = LLViewerTextureManager::getLocalTexture(sTextureSize, sTextureSize, 3, FALSE);
//mSTexturep->dontDiscard();
//mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
// Fill with dummy gray data.
// GL NOT ACTIVE HERE
LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
U8 *default_texture = raw->getData();

View File

@ -1371,7 +1371,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
gGL.getTexUnit(0)->bind(tex);
gGL.getTexUnit(0)->bind(tex, TRUE);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gl_rect_2d_simple_tex( width, height );
@ -1393,7 +1393,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
if( tex )
{
gGL.getTexUnit(0)->bind(tex);
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@ -1506,7 +1506,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
if( tex )
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(tex);
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@ -1585,7 +1585,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
gGL.getTexUnit(0)->bind(tex);
gGL.getTexUnit(0)->bind(tex, TRUE);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gl_rect_2d_simple_tex( width, height );
@ -1608,7 +1608,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.getTexUnit(0)->bind(tex);
gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@ -2034,7 +2034,7 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n
// that once an image is a mask it's always a mask.
tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
}
tex->createGLTexture(0, image_raw);
tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL);
gGL.getTexUnit(0)->bind(tex);
tex->setAddressMode(LLTexUnit::TAM_CLAMP);

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,27 @@ class LLTextureCache : public LLWorkerThread
friend class LLTextureCacheRemoteWorker;
friend class LLTextureCacheLocalFileWorker;
private:
// Entries
struct EntriesInfo
{
EntriesInfo() : mVersion(0.f), mEntries(0) {}
F32 mVersion;
U32 mEntries;
};
struct Entry
{
Entry() {}
Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) :
mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {}
void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; }
LLUUID mID; // 16 bytes
S32 mImageSize; // total size of image if known
S32 mBodySize; // size of body file in body cache
U32 mTime; // seconds since 1/1/1970
};
public:
class Responder : public LLResponder
@ -106,10 +127,16 @@ public:
// debug
S32 getNumReads() { return mReaders.size(); }
S32 getNumWrites() { return mWriters.size(); }
S64 getUsage() { return mTexturesSizeTotal; }
S64 getMaxUsage() { return sCacheMaxTexturesSize; }
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
U32 getMaxEntries() { return sCacheMaxEntries; };
BOOL isInCache(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ;
protected:
// Accessed by LLTextureCacheWorker
bool appendToTextureEntryList(const LLUUID& id, S32 size);
bool updateTextureEntryList(const LLUUID& id, S32 size);
std::string getLocalFileName(const LLUUID& id);
std::string getTextureFileName(const LLUUID& id);
void addCompleted(Responder* responder, bool success);
@ -122,7 +149,16 @@ private:
void readHeaderCache();
void purgeAllTextures(bool purge_directories);
void purgeTextures(bool validate);
S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
void closeHeaderEntriesFile();
void readEntriesHeader();
void writeEntriesHeader();
S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create);
void writeEntryAndClose(S32 idx, Entry& entry);
U32 openAndReadEntries(std::vector<Entry>& entries);
void writeEntriesAndClose(const std::vector<Entry>& entries);
S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize);
S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize);
bool removeHeaderCacheEntry(const LLUUID& id);
void lockHeaders() { mHeaderMutex.lock(); }
void unlockHeaders() { mHeaderMutex.unlock(); }
@ -132,6 +168,7 @@ private:
LLMutex mWorkersMutex;
LLMutex mHeaderMutex;
LLMutex mListMutex;
LLAPRFile* mHeaderAPRFile;
typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
handle_map_t mReaders;
@ -145,42 +182,28 @@ private:
BOOL mReadOnly;
// Entries
struct EntriesInfo
{
F32 mVersion;
U32 mEntries;
};
struct Entry
{
Entry() {}
Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {}
LLUUID mID; // 128 bits
S32 mSize; // total size of image if known (NOT size cached)
U32 mTime; // seconds since 1/1/1970
};
// HEADERS (Include first mip)
std::string mHeaderEntriesFileName;
std::string mHeaderDataFileName;
EntriesInfo mHeaderEntriesInfo;
typedef std::map<S32,LLUUID> index_map_t;
index_map_t mLRU; // index, id; stored as a map for fast removal
std::set<S32> mFreeList; // deleted entries
std::set<LLUUID> mLRU;
typedef std::map<LLUUID,S32> id_map_t;
id_map_t mHeaderIDMap;
// BODIES (TEXTURES minus headers)
std::string mTexturesDirName;
std::string mTexturesDirEntriesFileName;
typedef std::map<LLUUID,S32> size_map_t;
size_map_t mTexturesSizeMap;
S64 mTexturesSizeTotal;
LLAtomic32<BOOL> mDoPurge;
// Statics
static F32 sHeaderCacheVersion;
static U32 sCacheMaxEntries;
static S64 sCacheMaxTexturesSize;
};
extern const S32 TEXTURE_CACHE_ENTRY_SIZE;
#endif // LL_LLTEXTURECACHE_H

File diff suppressed because it is too large Load Diff

View File

@ -37,26 +37,29 @@
#include "llimage.h"
#include "lluuid.h"
#include "llworkerthread.h"
#include "llcurl.h"
#include "lltextureinfo.h"
class LLViewerTexture;
class LLTextureFetchWorker;
class HTTPGetResponder;
class LLTextureCache;
class LLImageDecodeThread;
class LLHost;
// Interface class
class LLTextureFetch : public LLWorkerThread
{
friend class LLTextureFetchWorker;
friend class HTTPGetResponder;
public:
LLTextureFetch(LLTextureCache* cache, bool threaded);
LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded);
~LLTextureFetch();
/*virtual*/ S32 update(U32 max_time_ms);
bool createRequest(const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux);
bool createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority,
bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux);
void deleteRequest(const LLUUID& id, bool cancel);
bool getRequestFinished(const LLUUID& id, S32& discard_level,
@ -66,25 +69,39 @@ public:
bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; }
F32 getTextureBandwidth() { return mTextureBandwidth; }
// Debug
BOOL isFromLocalCache(const LLUUID& id);
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p);
void dump();
S32 getNumRequests() { return mRequestMap.size(); }
S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); }
// Public for access by callbacks
void lockQueue() { mQueueMutex.lock(); }
void unlockQueue() { mQueueMutex.unlock(); }
LLTextureFetchWorker* getWorker(const LLUUID& id);
LLTextureInfo* getTextureInfo() { return &mTextureInfo; }
protected:
void addToNetworkQueue(LLTextureFetchWorker* worker);
void removeFromNetworkQueue(LLTextureFetchWorker* worker);
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
void addToHTTPQueue(const LLUUID& id);
void removeFromHTTPQueue(const LLUUID& id);
S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); }
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
// Called from worker thread (during doWork)
void processCurlRequests();
private:
void sendRequestListToSimulators();
/*virtual*/ void startThread(void);
/*virtual*/ void endThread(void);
/*virtual*/ void threadedUpdate(void);
public:
LLUUID mDebugID;
@ -95,8 +112,11 @@ public:
private:
LLMutex mQueueMutex;
LLMutex mNetworkQueueMutex;
LLTextureCache* mTextureCache;
LLImageDecodeThread* mImageDecodeThread;
LLCurlRequest* mCurlGetRequest;
// Map of all requests by UUID
typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
@ -105,10 +125,13 @@ private:
// Set of requests that require network data
typedef std::set<LLUUID> queue_t;
queue_t mNetworkQueue;
queue_t mHTTPTextureQueue;
typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t;
cancel_queue_t mCancelQueue;
LLFrameTimer mNetworkTimer;
F32 mTextureBandwidth;
F32 mMaxBandwidth;
LLTextureInfo mTextureInfo;
};
#endif // LL_LLTEXTUREFETCH_H

View File

@ -0,0 +1,290 @@
/**
* @file lltextureinfo.cpp
* @brief Object which handles local texture info
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lltextureinfo.h"
#include "lltexturestats.h"
#include "llviewercontrol.h"
LLTextureInfo::LLTextureInfo() :
mLogTextureDownloadsToViewerLog(false),
mLogTextureDownloadsToSimulator(false),
mTotalBytes(0),
mTotalMilliseconds(0),
mTextureDownloadsStarted(0),
mTextureDownloadsCompleted(0),
mTextureDownloadProtocol("NONE"),
mTextureLogThreshold(100 * 1024),
mCurrentStatsBundleStartTime(0)
{
mTextures.clear();
}
void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold)
{
mLogTextureDownloadsToViewerLog = writeToViewerLog;
mLogTextureDownloadsToSimulator = sendToSim;
mTextureLogThreshold = textureLogThreshold;
}
LLTextureInfo::~LLTextureInfo()
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator;
for (iterator = mTextures.begin(); iterator != mTextures.end(); iterator++)
{
LLTextureInfoDetails *info = (*iterator).second;
delete info;
}
mTextures.clear();
}
void LLTextureInfo::addRequest(const LLUUID& id)
{
LLTextureInfoDetails *info = new LLTextureInfoDetails();
mTextures[id] = info;
}
U32 LLTextureInfo::getTextureInfoMapSize()
{
return mTextures.size();
}
bool LLTextureInfo::has(const LLUUID& id)
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
if (iterator == mTextures.end())
{
return false;
}
else
{
return true;
}
}
void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime)
{
if (!has(id))
{
addRequest(id);
}
mTextures[id]->mStartTime = startTime;
mTextureDownloadsStarted++;
}
void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size)
{
if (!has(id))
{
addRequest(id);
}
mTextures[id]->mSize = size;
}
void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset)
{
if (!has(id))
{
addRequest(id);
}
mTextures[id]->mOffset = offset;
}
void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type)
{
if (!has(id))
{
addRequest(id);
}
mTextures[id]->mType = type;
}
void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime)
{
if (!has(id))
{
addRequest(id);
}
mTextures[id]->mCompleteTime = completeTime;
std::string protocol = "NONE";
switch(mTextures[id]->mType)
{
case LLTextureInfoDetails::REQUEST_TYPE_HTTP:
protocol = "HTTP";
break;
case LLTextureInfoDetails::REQUEST_TYPE_UDP:
protocol = "UDP";
break;
case LLTextureInfoDetails::REQUEST_TYPE_NONE:
default:
break;
}
if (mLogTextureDownloadsToViewerLog)
{
llinfos << "texture=" << id
<< " start=" << mTextures[id]->mStartTime
<< " end=" << mTextures[id]->mCompleteTime
<< " size=" << mTextures[id]->mSize
<< " offset=" << mTextures[id]->mOffset
<< " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000
<< " protocol=" << protocol
<< llendl;
}
if(mLogTextureDownloadsToSimulator)
{
S32 texture_stats_upload_threshold = mTextureLogThreshold;
mTotalBytes += mTextures[id]->mSize;
mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime;
mTextureDownloadsCompleted++;
mTextureDownloadProtocol = protocol;
if (mTotalBytes >= texture_stats_upload_threshold)
{
LLSD texture_data;
std::stringstream startTime;
startTime << mCurrentStatsBundleStartTime;
texture_data["start_time"] = startTime.str();
std::stringstream endTime;
endTime << completeTime;
texture_data["end_time"] = endTime.str();
texture_data["averages"] = getAverages();
send_texture_stats_to_sim(texture_data);
resetTextureStatistics();
}
}
mTextures.erase(id);
}
LLSD LLTextureInfo::getAverages()
{
LLSD averagedTextureData;
S32 averageDownloadRate;
if(mTotalMilliseconds == 0)
{
averageDownloadRate = 0;
}
else
{
averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds;
}
averagedTextureData["bits_per_second"] = averageDownloadRate;
averagedTextureData["bytes_downloaded"] = mTotalBytes;
averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted;
averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted;
averagedTextureData["transport"] = mTextureDownloadProtocol;
return averagedTextureData;
}
void LLTextureInfo::resetTextureStatistics()
{
mTotalMilliseconds = 0;
mTotalBytes = 0;
mTextureDownloadsStarted = 0;
mTextureDownloadsCompleted = 0;
mTextureDownloadProtocol = "NONE";
mCurrentStatsBundleStartTime = LLTimer::getTotalTime();
}
U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
{
if (!has(id))
{
return 0;
}
else
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
return (*iterator).second->mStartTime;
}
}
U32 LLTextureInfo::getRequestSize(const LLUUID& id)
{
if (!has(id))
{
return 0;
}
else
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
return (*iterator).second->mSize;
}
}
U32 LLTextureInfo::getRequestOffset(const LLUUID& id)
{
if (!has(id))
{
return 0;
}
else
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
return (*iterator).second->mOffset;
}
}
LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& id)
{
if (!has(id))
{
return LLTextureInfoDetails::REQUEST_TYPE_NONE;
}
else
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
return (*iterator).second->mType;
}
}
U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
{
if (!has(id))
{
return 0;
}
else
{
std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
return (*iterator).second->mCompleteTime;
}
}

View File

@ -0,0 +1,80 @@
/**
* @file lltextureinfo.h
* @brief Object for managing texture information.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXTUREINFO_H
#define LL_LLTEXTUREINFO_H
#include "lluuid.h"
#include "lltextureinfodetails.h"
#include <map>
class LLTextureInfo
{
public:
LLTextureInfo();
~LLTextureInfo();
void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold);
bool has(const LLUUID& id);
void setRequestStartTime(const LLUUID& id, U64 startTime);
void setRequestSize(const LLUUID& id, U32 size);
void setRequestOffset(const LLUUID& id, U32 offset);
void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type);
void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime);
U32 getRequestStartTime(const LLUUID& id);
U32 getRequestSize(const LLUUID& id);
U32 getRequestOffset(const LLUUID& id);
LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id);
U32 getRequestCompleteTime(const LLUUID& id);
void resetTextureStatistics();
U32 getTextureInfoMapSize();
LLSD getAverages();
private:
void addRequest(const LLUUID& id);
std::map<LLUUID, LLTextureInfoDetails *> mTextures;
LLSD mAverages;
bool mLogTextureDownloadsToViewerLog;
bool mLogTextureDownloadsToSimulator;
S32 mTotalBytes;
S32 mTotalMilliseconds;
S32 mTextureDownloadsStarted;
S32 mTextureDownloadsCompleted;
std::string mTextureDownloadProtocol;
U32 mTextureLogThreshold; // in bytes
U64 mCurrentStatsBundleStartTime;
};
#endif // LL_LLTEXTUREINFO_H

View File

@ -0,0 +1,40 @@
/**
* @file lltextureinfodetails.cpp
* @brief Object which handles details of any individual texture
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lltextureinfodetails.h"
LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0)
{
}

View File

@ -0,0 +1,58 @@
/**
* @file lltextureinfo.h
* @brief Object for managing texture information.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXTUREINFODETAILS_H
#define LL_LLTEXTUREINFODETAILS_H
#include "lluuid.h"
class LLTextureInfoDetails
{
public:
enum LLRequestType
{
REQUEST_TYPE_NONE,
REQUEST_TYPE_HTTP,
REQUEST_TYPE_UDP
};
U32 mStartTime;
U32 mCompleteTime;
U32 mOffset;
U32 mSize;
LLRequestType mType;
LLTextureInfoDetails();
};
#endif // LL_LLTEXTUREINFODETAILS_H

View File

@ -0,0 +1,61 @@
/**
* @file lltexturerstats.cpp
* @brief texture stats helper methods
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "pipeline.h"
#include "llagent.h"
#include "lltexturefetch.h"
#include "lltexturestats.h"
#include "lltexturestatsuploader.h"
#include "llviewerregion.h"
void send_texture_stats_to_sim(const LLSD &texture_stats)
{
LLSD texture_stats_report;
// Only send stats if the agent is connected to a region.
if (!gAgent.getRegion() || gNoRender)
{
return;
}
LLUUID agent_id = gAgent.getID();
texture_stats_report["agent_id"] = agent_id;
texture_stats_report["region_id"] = gAgent.getRegion()->getRegionID();
texture_stats_report["stats_data"] = texture_stats;
std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
LLTextureStatsUploader tsu;
llinfos << "uploading texture stats data to simulator" << llendl;
tsu.uploadStatsToSimulator(texture_cap_url, texture_stats);
}

View File

@ -0,0 +1,41 @@
/**
* @file lltexturestats.h
* @brief texture stats utilities
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXTURESTATS_H
#define LL_LLTEXTURESTATS_H
#include "llappviewer.h"
// utility functions to capture data on texture download speeds and send to simulator periodically
void send_texture_stats_to_sim(const LLSD &texture_stats);
#endif // LL_LLTEXTURESTATS_H

View File

@ -0,0 +1,59 @@
/**
* @file lltexturerstats.cpp
* @brief texture stats upload class
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lltexturestatsuploader.h"
LLTextureStatsUploader::LLTextureStatsUploader()
{
}
LLTextureStatsUploader::~LLTextureStatsUploader()
{
}
void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
{
if ( texture_cap_url != "" )
{
LLHTTPClient::post(texture_cap_url, texture_stats, NULL);
}
else
{
llinfos << "Not sending texture stats: "
<< texture_stats
<< " as there is no cap url."
<< llendl;
}
}

View File

@ -0,0 +1,48 @@
/**
* @file lltexturestatsuploader.h
* @brief Class to send the texture stats to the simulatore
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXTURESTATSUPLOADER_H
#define LL_LLTEXTURESTATSUPLOADER_H
#include "llappviewer.h"
// utility functions to capture data on texture download speeds and send to simulator periodically
class LLTextureStatsUploader
{
public:
LLTextureStatsUploader();
~LLTextureStatsUploader();
void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
};
#endif // LL_LLTEXTURESTATSUPLOADER_H

View File

@ -44,19 +44,21 @@
#include "llrender.h"
#include "lltooltip.h"
#include "llappviewer.h"
#include "llselectmgr.h"
#include "lltexlayer.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
#include "llviewercontrol.h"
#include "llviewerobject.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
#include "llappviewer.h"
#include "llvovolume.h"
extern F32 texmem_lower_bound_scale;
LLTextureView *gTextureView = NULL;
LLTextureSizeView *gTextureSizeView = NULL;
LLTextureSizeView *gTextureCategoryView = NULL;
//static
std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages;
@ -230,10 +232,10 @@ void LLTextureBar::draw()
{ "DSK", LLColor4::blue }, // CACHE_POST
{ "NET", LLColor4::green }, // LOAD_FROM_NETWORK
{ "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR
{ "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL
{ "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA
{ "REQ", LLColor4::yellow },// SEND_HTTP_REQ
{ "HTP", LLColor4::green }, // WAIT_HTTP_REQ
{ "DEC", LLColor4::yellow },// DECODE_IMAGE
{ "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE
{ "DEC", LLColor4::green }, // DECODE_IMAGE_UPDATE
{ "WRT", LLColor4::purple },// WRITE_TO_CACHE
{ "WRT", LLColor4::orange },// WAIT_ON_WRITE
{ "END", LLColor4::red }, // DONE
@ -261,7 +263,7 @@ void LLTextureBar::draw()
// Draw the progress bar.
S32 bar_width = 100;
S32 bar_left = 280;
S32 bar_left = 260;
left = bar_left;
right = left + bar_width;
@ -286,30 +288,31 @@ void LLTextureBar::draw()
S32 pip_x = title_x3 + pip_space/2;
// Draw the packet pip
const F32 pip_max_time = 5.f;
F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32();
if (last_event < 1.f)
if (last_event < pip_max_time)
{
clr = LLColor4::white;
}
else
{
last_event = mImagep->mRequestDeltaTime;
if (last_event < 1.f)
if (last_event < pip_max_time)
{
clr = LLColor4::green;
}
else
{
last_event = mImagep->mFetchDeltaTime;
if (last_event < 1.f)
if (last_event < pip_max_time)
{
clr = LLColor4::yellow;
}
}
}
if (last_event < 1.f)
if (last_event < pip_max_time)
{
clr.setAlpha(1.f - last_event);
clr.setAlpha(1.f - last_event/pip_max_time);
gGL.color4fv(clr.mV);
gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
}
@ -406,89 +409,113 @@ void LLGLTexMemBar::draw()
S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
S32 h_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f);
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
LLColor4 color;
std::string text;
text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f",
text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
total_mem,
max_total_mem,
bound_mem,
max_bound_mem,
discard_bias);
LLImageRaw::sGlobalRawMemory >> 20, discard_bias,
cache_usage, cache_max_usage);
//, cache_entries, cache_max_entries
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
text_color, LLFontGL::LEFT, LLFontGL::TOP);
//----------------------------------------------------------------------------
S32 bar_left = 380;
#if 0
S32 bar_left = 400;
S32 bar_width = 200;
S32 top = line_height*3 - 2 + h_offset;
S32 bottom = top - 6;
S32 left = bar_left;
S32 right = left + bar_width;
F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f);
F32 bar_scale;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// GL Mem Bar
left = bar_left;
text = "GL";
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
left = bar_left+20;
right = left + bar_width;
gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey
gl_rect_2d(left, top, right, bottom);
bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
right = left + llfloor(total_mem * bar_scale);
right = llclamp(right, bar_left, bar_left + bar_width);
color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green :
(total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red;
color[VALPHA] = .75f;
glColor4fv(color.mV);
gl_rect_2d(left, top, right, bottom); // red/yellow/green
//
bar_left += bar_width + bar_space;
//top = bottom - 2; bottom = top - 6;
// Bound Mem Bar
left = bar_left;
text = "GL";
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
left = bar_left + 20;
right = left + bar_width;
gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f);
gl_rect_2d(left, top, right, bottom);
left = bar_left;
right = left + llfloor(bound_mem * bar_scale);
if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale))
{
gGL.color4f(0.f, 1.f, 0.f, 0.75f);
}
else if (bound_mem < max_bound_mem)
{
gGL.color4f(1.f, 1.f, 0.f, 0.75f);
}
else
{
gGL.color4f(1.f, 0.f, 0.f, 0.75f);
}
gl_rect_2d(left, top, right, bottom);
color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green :
(bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red;
color[VALPHA] = .75f;
glColor4fv(color.mV);
bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
top = bottom - 2;
bottom = top - 6;
left = bar_left;
right = left + llfloor(total_mem * bar_scale);
if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale))
{
gGL.color4f(0.f, 1.f, 0.f, 0.75f);
}
else if (total_mem < max_total_mem)
{
gGL.color4f(1.f, 1.f, 0.f, 0.75f);
}
else
{
gGL.color4f(1.f, 0.f, 0.f, 0.75f);
}
gl_rect_2d(left, top, right, bottom);
#else
S32 left = 0 ;
#endif
//----------------------------------------------------------------------------
text = llformat("Textures: Count: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d mRaw:%d mAux:%d CB:%d",
text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d",
gTextureList.getNumImages(),
LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount,
LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
LLLFSThread::sLocal->getPending(),
LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(),
LLImageRaw::sRawImageCount, LLViewerFetchedTexture::sRawCount, LLViewerFetchedTexture::sAuxCount,
gTextureList.mCallbackList.size());
LLAppViewer::getImageDecodeThread()->getPending(),
LLImageRaw::sRawImageCount,
LLAppViewer::getTextureFetch()->getNumHTTPRequests());
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
left = 550;
F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth();
F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color;
color[VALPHA] = text_color[VALPHA];
text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2,
color, LLFontGL::LEFT, LLFontGL::TOP);
S32 dx1 = 0;
if (LLAppViewer::getTextureFetch()->mDebugPause)
@ -555,7 +582,7 @@ public:
void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;}
void draw();
BOOL handleHover(S32 x, S32 y, MASK mask) ;
BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ;
private:
S32 mIndex ;
@ -568,19 +595,16 @@ private:
F32 mScale ;
};
BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask)
BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size)
{
#if !LL_RELEASE_FOR_DOWNLOAD
if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale)))
{
LLImageGL::setCurTexSizebar(mIndex);
LLImageGL::setCurTexSizebar(mIndex, set_pick_size);
}
#endif
return TRUE ;
}
void LLGLTexSizeBar::draw()
{
#if !LL_RELEASE_FOR_DOWNLOAD
LLGLSUIDefault gls_ui;
if(LLImageGL::sCurTexSizeBar == mIndex)
@ -601,7 +625,6 @@ void LLGLTexSizeBar::draw()
F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ;
gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ;
#endif
}
////////////////////////////////////////////////////////////////////////////
@ -675,7 +698,13 @@ void LLTextureView::draw()
<< "\t" << cur_discard
<< llendl;
}
if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
{
static S32 debug_count = 0;
++debug_count; // for breakpoints
}
#if 0
if (imagep->getDontDiscard())
{
@ -889,8 +918,7 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
}
//-----------------------------------------------------------------
LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p)
: LLView(p)
LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p)
{
setVisible(FALSE) ;
@ -910,7 +938,31 @@ LLTextureSizeView::~LLTextureSizeView()
}
void LLTextureSizeView::draw()
{
#if !LL_RELEASE_FOR_DOWNLOAD
if(mType == TEXTURE_MEM_OVER_SIZE)
{
drawTextureSizeGraph();
}
else
{
drawTextureCategoryGraph() ;
}
LLView::draw();
}
BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask)
{
if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
{
mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ;
}
return TRUE ;
}
//draw real-time texture mem bar over size
void LLTextureSizeView::drawTextureSizeGraph()
{
if(mTextureSizeBar.size() == 0)
{
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
@ -931,29 +983,16 @@ void LLTextureSizeView::draw()
mTextureSizeBar[i]->draw() ;
}
LLImageGL::resetCurTexSizebar();
LLView::draw();
#endif
}
BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask)
{
if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
{
mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask) ;
}
return TRUE ;
}
//draw background of texture size bar graph
F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
{
//scale
F32 scale = 1.0f ;
#if !LL_RELEASE_FOR_DOWNLOAD
LLGLSUIDefault gls_ui;
//scale
{
S32 count = 0 ;
for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
@ -1043,8 +1082,137 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
text = llformat("Texture Size Distribution") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
#endif
return scale ;
}
//draw real-time texture mem bar over category
void LLTextureSizeView::drawTextureCategoryGraph()
{
if(mTextureSizeBar.size() == 0)
{
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;
mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
{
mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth ,
line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
}
}
F32 size_bar_scale = drawTextureCategoryDistributionGraph() ;
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
{
U32 k = LLViewerTexture::getIndexFromCategory(i) ;
mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ;
mTextureSizeBar[i]->draw() ;
}
LLImageGL::resetCurTexSizebar();
}
//draw background for TEXTURE_MEM_OVER_CATEGORY
F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()
{
//scale
F32 scale = 4.0f ;
LLGLSUIDefault gls_ui;
{
S32 count = 0 ;
for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
{
S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ;
if(tmp > count)
{
count = tmp ;
}
}
if(count > mTextureSizeBarRect.getHeight() * 0.25f)
{
scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ;
}
}
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
S32 left = mTextureSizeBarRect.mLeft ;
S32 bottom = mTextureSizeBarRect.mBottom ;
S32 right = mTextureSizeBarRect.mRight ;
S32 top = mTextureSizeBarRect.mTop ;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
//background rect
gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
//--------------------------------------------------
gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
gl_line_2d(left, bottom, right, bottom) ; //x axis
gl_line_2d(left, bottom, left, top) ; //y axis
//ruler
//--------------------------------------------------
gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
for(S32 i = bottom + 50 ; i <= top ; i += 50)
{
gl_line_2d(left, i, right, i) ;
}
//texts
//--------------------------------------------------
F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
std::string text;
//-------
//x axis: size label
static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] =
{"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ;
text = llformat("%s", category[0]) ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
{
text = llformat("%s", category[i]) ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
//-------
//y axis: number label
for(S32 i = bottom + 50 ; i <= top ; i += 50)
{
text = llformat("%d", (S32)((i - bottom) / scale)) ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
text = llformat("MB") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 ,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
//--------------------------------------------------
F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
text = llformat("Loaded") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
loaded_color,
LLFontGL::LEFT, LLFontGL::TOP);
F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
text = llformat("Bound") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
bound_color, LLFontGL::LEFT, LLFontGL::TOP);
//--------------------------------------------------
//title
text = llformat("Texture Category Distribution") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
return scale ;
}

View File

@ -79,24 +79,41 @@ public:
};
class LLGLTexSizeBar;
class LLTextureSizeView : public LLView
class LLTextureSizeView : public LLContainerView
{
public:
protected:
LLTextureSizeView(const Params&);
friend class LLUICtrlFactory;
public:
~LLTextureSizeView();
/*virtual*/ void draw();
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ;
void setType(S32 type) {mType = type ;}
enum
{
TEXTURE_MEM_OVER_SIZE,
TEXTURE_MEM_OVER_CATEGORY
};
private:
//draw background for TEXTURE_MEM_OVER_SIZE
F32 drawTextureSizeDistributionGraph() ;
//draw real-time texture mem bar over size
void drawTextureSizeGraph();
//draw background for TEXTURE_MEM_OVER_CATEGORY
F32 drawTextureCategoryDistributionGraph() ;
//draw real-time texture mem bar over category
void drawTextureCategoryGraph();
private:
std::vector<LLGLTexSizeBar*> mTextureSizeBar ;
LLRect mTextureSizeBarRect ;
S32 mTextureSizeBarWidth ;
S32 mTextureSizeBarWidth ;
S32 mType ;
};
extern LLTextureView *gTextureView;
extern LLTextureSizeView *gTextureSizeView;
extern LLTextureSizeView *gTextureCategoryView;
#endif // LL_TEXTURE_VIEW_H

View File

@ -46,7 +46,7 @@
#include "llstartup.h" // gStartupState
#include "llurlsimstring.h"
#include "llweb.h"
#include "llworldmap.h"
#include "llworldmapmessage.h"
// library includes
#include "llsd.h"
@ -201,7 +201,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous
//if(url_displayp) url_displayp->setName(region_name);
// Request a region handle by name
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
LLURLDispatcherImpl::regionNameCallback,
url,
false); // don't teleport
@ -240,7 +240,7 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::strin
LLVector3d global_pos = from_region_handle(region_handle) + LLVector3d(local_pos);
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle,
LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle,
LLURLDispatcherImpl::regionHandleCallback,
url, teleport);
}
@ -335,7 +335,7 @@ public:
{
url += tokens[i].asString() + "/";
}
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
LLURLDispatcherImpl::regionHandleCallback,
url,
true); // teleport

View File

@ -109,10 +109,13 @@ LLViewerCamera::LLViewerCamera() : LLCamera()
{
calcProjection(getFar());
mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
mPixelMeterRatio = 0.f;
mScreenPixelArea = 0;
mZoomFactor = 1.f;
mZoomSubregion = 1;
mAverageSpeed = 0.f;
mAverageAngularSpeed = 0.f;
gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2));
}
@ -151,15 +154,22 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
setOriginAndLookAt(origin, up_direction, point_of_interest);
F32 dpos = (center - last_position).magVec();
mVelocityDir = center - last_position ;
F32 dpos = mVelocityDir.normVec() ;
LLQuaternion rotation;
rotation.shortestArc(last_axis, getAtAxis());
F32 x, y, z;
F32 drot;
rotation.getAngleAxis(&drot, &x, &y, &z);
mVelocityStat.addValue(dpos);
mAngularVelocityStat.addValue(drot);
mAverageSpeed = mVelocityStat.getMeanPerSec() ;
mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ;
mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect()));
// update pixel meter ratio using default fov, not modified one
mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5));
// update screen pixel area
@ -818,10 +828,12 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
LLCamera::setView(vertical_fov_rads); // call base implementation
}
void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) {
void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
{
vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
setView(vertical_fov_rads);
mCameraFOVDefault = vertical_fov_rads;
mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
}

View File

@ -91,17 +91,20 @@ public:
BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const;
BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const;
const LLVector3* getVelocityDir() const {return &mVelocityDir;}
LLStat *getVelocityStat() { return &mVelocityStat; }
LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; }
F32 getCosHalfFov() {return mCosHalfCameraFOV;}
F32 getAverageSpeed() {return mAverageSpeed ;}
F32 getAverageAngularSpeed() {return mAverageAngularSpeed;}
void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right);
LLVector3 roundToPixel(const LLVector3 &pos_agent);
// Sets the current matrix
/* virtual */ void setView(F32 vertical_fov_rads);
// Sets the current matrix AND remembers result as default view
void setDefaultFOV(F32 vertical_fov_rads);
void setDefaultFOV(F32 fov) ;
F32 getDefaultFOV() { return mCameraFOVDefault; }
BOOL cameraUnderWater() const;
@ -120,9 +123,14 @@ protected:
LLStat mVelocityStat;
LLStat mAngularVelocityStat;
LLVector3 mVelocityDir ;
F32 mAverageSpeed ;
F32 mAverageAngularSpeed ;
mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix
mutable LLMatrix4 mModelviewMatrix;
F32 mCameraFOVDefault;
F32 mCosHalfCameraFOV;
LLVector3 mLastPointOfInterest;
F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance.
S32 mScreenPixelArea; // Pixel area of entire window

View File

@ -90,7 +90,7 @@ std::string gCurrentVersion;
extern BOOL gResizeScreenTexture;
extern BOOL gDebugGL;
extern BOOL gAuditTexture;
////////////////////////////////////////////////////////////////////////////
// Listeners
@ -378,6 +378,12 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue)
return true;
}
static bool handleAuditTextureChanged(const LLSD& newvalue)
{
gAuditTexture = newvalue.asBoolean();
return true;
}
static bool handleRenderDebugGLChanged(const LLSD& newvalue)
{
gDebugGL = newvalue.asBoolean() || gDebugSession;
@ -566,6 +572,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2));
gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2));
gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2));
gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2));

View File

@ -712,7 +712,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame)
F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
max_image_decode_time = llclamp(max_image_decode_time, 0.001f, 0.005f ); // min 1ms/frame, max 5ms/frame)
gTextureList.updateImages(max_image_decode_time);
//remove dead textures from GL

View File

@ -606,6 +606,14 @@ class LLAdvancedToggleConsole : public view_listener_t
{
toggle_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
}
else if (gTextureSizeView && "texture size" == console_type)
{
toggle_visibility( (void*)gTextureSizeView );
}
else if (gTextureCategoryView && "texture category" == console_type)
{
toggle_visibility( (void*)gTextureCategoryView );
}
else if ("fast timers" == console_type)
{
toggle_visibility( (void*)gDebugView->mFastTimerView );
@ -633,6 +641,14 @@ class LLAdvancedCheckConsole : public view_listener_t
{
new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
}
else if (gTextureSizeView && "texture size" == console_type)
{
new_value = get_visibility( (void*)gTextureSizeView );
}
else if (gTextureCategoryView && "texture category" == console_type)
{
new_value = get_visibility( (void*)gTextureCategoryView );
}
else if ("fast timers" == console_type)
{
new_value = get_visibility( (void*)gDebugView->mFastTimerView );
@ -1156,28 +1172,6 @@ class LLAdvancedCheckWireframe : public view_listener_t
}
};
//////////////////////
// DISABLE TEXTURES //
//////////////////////
class LLAdvancedToggleDisableTextures : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLViewerTexture::sDontLoadVolumeTextures = !LLViewerTexture::sDontLoadVolumeTextures;
return true;
}
};
class LLAdvancedCheckDisableTextures : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
bool new_value = LLViewerTexture::sDontLoadVolumeTextures; // <-- make this using LLCacheControl
return new_value;
}
};
//////////////////////
// TEXTURE ATLAS //
//////////////////////
@ -1909,7 +1903,7 @@ class LLAdvancedRebakeTextures : public view_listener_t
};
#ifndef LL_RELEASE_FOR_DOWNLOAD
#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD
///////////////////////////
// DEBUG AVATAR TEXTURES //
///////////////////////////
@ -3511,9 +3505,8 @@ void set_god_level(U8 god_level)
gIMMgr->refresh();
LLViewerParcelMgr::getInstance()->notifyObservers();
// God mode changes sim visibility
LLWorldMap::getInstance()->reset();
LLWorldMap::getInstance()->setCurrentLayer(0);
// God mode changes region visibility
LLWorldMap::getInstance()->reloadItems(true);
// inventory in items may change in god mode
gObjectList.dirtyAllObjectInventory();
@ -7887,8 +7880,6 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
view_listener_t::addMenu(new LLAdvancedToggleDisableTextures(), "Advanced.ToggleDisableTextures");
view_listener_t::addMenu(new LLAdvancedCheckDisableTextures(), "Advanced.CheckDisableTextures");
view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas");
view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas");
view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");

View File

@ -2906,7 +2906,7 @@ F32 LLViewerObject::getMidScale() const
}
void LLViewerObject::updateTextures(LLAgent &agent)
void LLViewerObject::updateTextures()
{
}

View File

@ -199,7 +199,7 @@ public:
S32 getNumFaces() const { return mNumFaces; }
// Graphical stuff for objects - maybe broken out into render class later?
virtual void updateTextures(LLAgent &agent);
virtual void updateTextures();
virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object
virtual LLDrawable* createDrawable(LLPipeline *pipeline);

View File

@ -642,7 +642,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
// Update distance & gpw
objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
objectp->updateTextures(agent); // Update the image levels of textures for this object.
objectp->updateTextures(); // Update the image levels of textures for this object.
}
}
@ -1074,6 +1074,7 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
LLColor4 group_own_below_water_color =
LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" );
F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius");
for (S32 i = 0; i < mMapObjects.count(); i++)
{
@ -1089,6 +1090,11 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f; // 1.3 is a fudge
// Limit the size of megaprims so they don't blot out everything on the minimap.
// Attempting to draw very large megaprims also causes client lag.
// See DEV-17370 and DEV-29869/SNOW-79 for details.
approx_radius = llmin(approx_radius, max_radius);
LLColor4U color = above_water_color;
if( objectp->permYouOwner() )
{

View File

@ -1427,11 +1427,11 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
capabilityNames.append("FetchInventory");
capabilityNames.append("WebFetchInventoryDescendents");
capabilityNames.append("ObjectMedia");
capabilityNames.append("ObjectMediaNavigate");
capabilityNames.append("FetchLib");
capabilityNames.append("FetchLibDescendents");
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
capabilityNames.append("MapLayer");
@ -1452,6 +1452,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
capabilityNames.append("UntrustedSimulatorMessage");
capabilityNames.append("UpdateAgentInformation");
capabilityNames.append("UpdateAgentLanguage");
@ -1464,6 +1465,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
capabilityNames.append("WebFetchInventoryDescendents");
// Please add new capabilities alphabetically to reduce
// merge conflicts.

View File

@ -560,12 +560,18 @@ extern U32 gVisCompared;
extern U32 gVisTested;
std::map<S32,LLFrameTimer> gDebugTimers;
std::map<S32,std::string> gDebugTimerLabel;
void init_statistics()
{
// Label debug timers
gDebugTimerLabel[0] = "Texture";
}
void update_statistics(U32 frame_count)
{
gTotalWorldBytes += gVLManager.getTotalBytes();
gTotalObjectBytes += gObjectBits / 8;
gTotalTextureBytes += gTextureList.mTextureBits / 8;
// make sure we have a valid time delta for this frame
if (gFrameIntervalSeconds > 0.f)
@ -617,7 +623,6 @@ void update_statistics(U32 frame_count)
F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f);
LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f);
LLViewerStats::getInstance()->mTextureKBitStat.addValue(gTextureList.mTextureBits/1024.f);
LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
@ -631,8 +636,6 @@ void update_statistics(U32 frame_count)
gDebugTimers[0].unpause();
}
LLViewerStats::getInstance()->mTexturePacketsStat.addValue(gTextureList.mTexturePackets);
{
static F32 visible_avatar_frames = 0.f;
static F32 avg_visible_avatars = 0;
@ -652,8 +655,20 @@ void update_statistics(U32 frame_count)
gObjectBits = 0;
// gDecodedBits = 0;
gTextureList.mTextureBits = 0;
gTextureList.mTexturePackets = 0;
// Only update texture stats ones per second so that they are less noisy
{
static const F32 texture_stats_freq = 1.f;
static LLFrameTimer texture_stats_timer;
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
{
LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
LLViewerTextureList::sTextureBits = 0;
LLViewerTextureList::sTexturePackets = 0;
texture_stats_timer.reset();
}
}
}
@ -826,3 +841,4 @@ void send_stats()
LLViewerStats::getInstance()->addToMessage(body);
LLHTTPClient::post(url, body, new ViewerStatsResponder());
}

View File

@ -34,6 +34,7 @@
#define LL_LLVIEWERSTATS_H
#include "llstat.h"
#include "lltextureinfo.h"
class LLViewerStats : public LLSingleton<LLViewerStats>
{
@ -205,10 +206,13 @@ private:
static const F32 SEND_STATS_PERIOD = 300.0f;
// The following are from (older?) statistics code found in appviewer.
void init_statistics();
void reset_statistics();
void output_statistics(void*);
void update_statistics(U32 frame_count);
void send_stats();
extern std::map<S32,LLFrameTimer> gDebugTimers;
extern std::map<S32,std::string> gDebugTimerLabel;
#endif // LL_LLVIEWERSTATS_H

File diff suppressed because it is too large Load Diff

View File

@ -121,11 +121,23 @@ public:
BOOST_UI = 15,
BOOST_PREVIEW = 16,
BOOST_MAP = 17,
BOOST_MAP_LAYER = 18,
BOOST_MAP_VISIBLE = 18,
BOOST_AVATAR_SELF = 19, // needed for baking avatar
BOOST_MAX_LEVEL
BOOST_MAX_LEVEL,
//other texture Categories
LOCAL = BOOST_MAX_LEVEL,
AVATAR_SCRATCH_TEX,
DYNAMIC_TEX,
MEDIA,
ATLAS,
OTHER,
MAX_GL_IMAGE_CATEGORY
};
static S32 getTotalNumOfCategories() ;
static S32 getIndexFromCategory(S32 category) ;
static S32 getCategoryFromIndex(S32 index) ;
typedef std::list<LLFace*> ll_face_list_t ;
protected:
@ -146,7 +158,7 @@ public:
virtual BOOL isMissingAsset()const ;
virtual void dump(); // debug info to llinfos
/*virtual*/ bool bindDefaultImage(const S32 stage = 0) const ;
/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
/*virtual*/ void forceImmediateUpdate() ;
const LLUUID& getID() const { return mID; }
@ -154,9 +166,9 @@ public:
void setBoostLevel(S32 level);
S32 getBoostLevel() { return mBoostLevel; }
//maxVirtualSize of the texture
void addTextureStats(F32 virtual_size) const ;
void resetTextureStats(BOOL zero = FALSE);
void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
void resetTextureStats();
virtual F32 getMaxVirtualSize() ;
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
@ -180,7 +192,7 @@ public:
BOOL hasGLTexture() const ;
LLGLuint getTexName() const ;
BOOL createGLTexture() ;
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0);
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER);
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
@ -188,7 +200,8 @@ public:
BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height);
BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
void setGLTextureCreated (bool initialized);
void setCategory(S32 category) ;
LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
S32 getMaxDiscardLevel() const;
S32 getDiscardLevel() const;
@ -201,8 +214,8 @@ public:
BOOL getMask(const LLVector2 &tc);
F32 getTimePassedSinceLastBound();
BOOL getMissed() const ;
BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
BOOL isJustBound()const ;
void forceUpdateBindStats(void) const;
U32 getTexelsInAtlas() const ;
U32 getTexelsInGLTexture() const ;
@ -220,6 +233,7 @@ public:
BOOL getDontDiscard() const { return mDontDiscard; }
//-----------------
BOOL isLargeImage() ;
/*virtual*/ void updateBindStatsForTester() ;
protected:
void cleanup() ;
@ -228,6 +242,7 @@ protected:
private:
//note: do not make this function public.
/*virtual*/ LLImageGL* getGLTexture() const ;
virtual void switchToCachedImage();
protected:
LLUUID mID;
@ -237,7 +252,9 @@ protected:
BOOL mUseMipMaps ;
S8 mComponents;
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
mutable S8 mNeedsGLTexture;
mutable BOOL mNeedsResetMaxVirtualSize ;
mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority.
LLFrameTimer mLastReferencedTimer;
ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture
@ -270,7 +287,12 @@ public:
static S32 sMaxBoundTextureMemInMegaBytes;
static S32 sMaxTotalTextureMemInMegaBytes;
static S32 sMaxDesiredTextureMemInBytes ;
static BOOL sDontLoadVolumeTextures;
static S8 sCameraMovingDiscardBias;
static S32 sMaxSculptRez ;
static S32 sMinLargeImageSize ;
static S32 sMaxSmallImageSize ;
static BOOL sFreezeImageScalingDown ;//do not scale down image res if set.
static F32 sCurrentTime ;
static BOOL sUseTextureAtlas ;
static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
@ -290,9 +312,9 @@ class LLViewerFetchedTexture : public LLViewerTexture
protected:
/*virtual*/ ~LLViewerFetchedTexture();
public:
LLViewerFetchedTexture(const LLUUID& id, BOOL usemipmaps = TRUE);
LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps);
LLViewerFetchedTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps = TRUE);
LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE);
public:
static F32 maxDecodePriority();
@ -328,6 +350,8 @@ public:
bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; }
bool doLoadedCallbacks();
void addToCreateTexture();
// ONLY call from LLViewerTextureList
BOOL createTexture(S32 usename = 0);
void destroyTexture() ;
@ -346,7 +370,12 @@ public:
// the priority list, and cause horrible things to happen.
void setDecodePriority(F32 priority = -1.0f);
F32 getDecodePriority() const { return mDecodePriority; };
void setAdditionalDecodePriority(F32 priority) ;
F32 maxAdditionalDecodePriority() ;
void updateVirtualSize() ;
// setDesiredDiscardLevel is only used by LLViewerTextureList
void setDesiredDiscardLevel(S32 discard) { mDesiredDiscardLevel = discard; }
S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; }
@ -370,15 +399,15 @@ public:
BOOL isInImageList() const {return mInImageList ;}
void setInImageList(BOOL flag) {mInImageList = flag ;}
const std::string& getLocalFileName() const {return mLocalFileName ;}
LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;}
U32 getFetchPriority() const { return mFetchPriority ;}
F32 getDownloadProgress() const {return mDownloadProgress ;}
LLImageRaw* readBackRawImage(S8 discard_level) ;
LLImageRaw* reloadRawImage(S8 discard_level) ;
void destroyRawImage();
const std::string& getUrl() const {return mUrl;}
//---------------
BOOL isDeleted() ;
BOOL isInactive() ;
@ -389,13 +418,36 @@ public:
//---------------
void setForSculpt();
BOOL isForSculpt() const {return mForSculpt;}
BOOL forSculpt() const {return mForSculpt;}
BOOL isForSculptOnly() const;
//raw image management
void checkCachedRawSculptImage() ;
LLImageRaw* getRawImage()const { return mRawImage ;}
S32 getRawImageLevel() const {return mRawDiscardLevel;}
LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
BOOL isRawImageValid()const { return mIsRawImageValid ; }
void forceToSaveRawImage(S32 desired_discard = 0) ;
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
BOOL hasSavedRawImage() const ;
F32 getElapsedLastReferencedSavedRawImageTime() const ;
BOOL isFullyLoaded() const;
protected:
/*virtual*/ void switchToCachedImage();
private:
void init(bool firstinit) ;
void cleanup() ;
F32 calcDecodePriorityForUnknownTexture(F32 pixel_priority) ;
void saveRawImage() ;
BOOL forceFetch() ;
void setCachedRawImage() ;
BOOL keepReuestedDiscardLevel();
//for atlas
void resetFaceAtlas() ;
@ -414,12 +466,8 @@ protected:
S32 mKnownDrawWidth;
S32 mKnownDrawHeight;
std::string mLocalFileName;
S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
S32 mMinDiscardLevel;
std::string mUrl;
S32 mRequestedDiscardLevel;
F32 mRequestedDownloadPriority;
S32 mFetchState;
@ -429,6 +477,10 @@ protected:
F32 mRequestDeltaTime;
S32 mDecodeFrame;
S32 mVisibleFrame; // decode frame where image was last visible
F32 mDecodePriority; // The priority for decoding this image.
S32 mMinDiscardLevel;
S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
S8 mNeedsAux; // We need to decode the auxiliary channels
S8 mDecodingAux; // Are we decoding high components
@ -436,10 +488,10 @@ protected:
S8 mHasFetcher; // We've made a fecth request
S8 mIsFetching; // Fetch request is active
mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database.
mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database.
F32 mDecodePriority; // The priority for decoding this image.
typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
S8 mLoadedCallbackDesiredDiscardLevel;
callback_list_t mLoadedCallbackList;
LLPointer<LLImageRaw> mRawImage;
@ -449,6 +501,19 @@ protected:
// doing if you use it for anything else! - djs
LLPointer<LLImageRaw> mAuxRawImage;
//keep a copy of mRawImage for some special purposes
//when mForceToSaveRawImage is set.
BOOL mForceToSaveRawImage ;
LLPointer<LLImageRaw> mSavedRawImage;
S32 mSavedRawDiscardLevel;
S32 mDesiredSavedRawDiscardLevel;
F32 mLastReferencedSavedRawImageTime ;
//a small version of the copy of the raw image (<= 64 * 64)
LLPointer<LLImageRaw> mCachedRawImage;
S32 mCachedRawDiscardLevel;
BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator
// Timers
@ -477,15 +542,17 @@ protected:
/*virtual*/ ~LLViewerLODTexture(){}
public:
LLViewerLODTexture(const LLUUID& id, BOOL usemipmaps = TRUE);
LLViewerLODTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps = TRUE);
LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE);
/*virtual*/ S8 getType() const;
// Process image stats to determine priority/quality requirements.
/*virtual*/ void processTextureStats();
BOOL isUpdateFrozen() ;
private:
void init(bool firstinit) ;
void scaleDown() ;
private:
@ -608,6 +675,15 @@ public:
const LLUUID& force_id = LLUUID::null
);
static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url,
BOOL usemipmap = TRUE,
BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null
);
static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) ;
static void init() ;

View File

@ -44,6 +44,7 @@
#include "llimagetga.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
#include "llimageworker.h"
#include "llsdserialize.h"
#include "llsys.h"
@ -68,10 +69,15 @@
void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL;
const S32 IMAGES_PER_REQUEST = 42;
const S32 IMAGES_MIN_UPDATES = 4; // Always update the highest N images each frame
const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_REQUEST in a frame
const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; // seconds
U32 LLViewerTextureList::sTextureBits = 0;
U32 LLViewerTextureList::sTexturePackets = 0;
S32 LLViewerTextureList::sNumImages = 0;
LLStat LLViewerTextureList::sNumImagesStat(32, TRUE);
LLStat LLViewerTextureList::sNumRawImagesStat(32, TRUE);
LLStat LLViewerTextureList::sGLTexMemStat(32, TRUE);
LLStat LLViewerTextureList::sGLBoundMemStat(32, TRUE);
LLStat LLViewerTextureList::sRawMemStat(32, TRUE);
LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE);
LLViewerTextureList gTextureList;
static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images");
@ -88,7 +94,7 @@ LLViewerTextureList::LLViewerTextureList()
void LLViewerTextureList::init()
{
mNumImages = 0;
sNumImages = 0;
mMaxResidentTexMemInMegaBytes = 0;
mMaxTotalTextureMemInMegaBytes = 0 ;
if (gNoRender)
@ -231,6 +237,10 @@ void LLViewerTextureList::shutdown()
{
continue; // avoid UI, baked, and other special images
}
if(!image->getBoundRecently())
{
continue ;
}
S32 desired = image->getDesiredDiscardLevel();
if (desired >= 0 && desired < MAX_DISCARD_LEVEL)
{
@ -321,13 +331,6 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
LLGLenum primary_format,
const LLUUID& force_id)
{
if (gNoRender)
{
// Never mind that this ignores image_set_id;
// getImage() will handle that later.
return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
}
std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename);
if (full_path.empty())
{
@ -335,6 +338,26 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
}
std::string url = "file://" + full_path;
return getImageFromUrl(url, usemipmaps, level_immediate, texture_type, internal_format, primary_format, force_id);
}
LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url,
BOOL usemipmaps,
BOOL level_immediate,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
const LLUUID& force_id)
{
if (gNoRender)
{
// Never mind that this ignores image_set_id;
// getImage() will handle that later.
return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
}
// generate UUID based on hash of filename
LLUUID new_id;
if (force_id.notNull())
@ -343,7 +366,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
}
else
{
new_id.generate(full_path);
new_id.generate(url);
}
LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id);
@ -353,10 +376,10 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
switch(texture_type)
{
case LLViewerTexture::FETCHED_TEXTURE:
imagep = new LLViewerFetchedTexture(full_path, new_id, usemipmaps);
imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps);
break ;
case LLViewerTexture::LOD_TEXTURE:
imagep = new LLViewerLODTexture(full_path, new_id, usemipmaps);
imagep = new LLViewerLODTexture(url, new_id, usemipmaps);
break ;
default:
llerrs << "Invalid texture type " << texture_type << llendl ;
@ -372,7 +395,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
if (level_immediate)
{
imagep->dontDiscard();
imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
imagep->setBoostLevel(LLViewerTexture::BOOST_UI);
}
}
@ -424,18 +447,15 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
switch(texture_type)
{
case LLViewerTexture::FETCHED_TEXTURE:
imagep = new LLViewerFetchedTexture(image_id, usemipmaps);
imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps);
break ;
case LLViewerTexture::LOD_TEXTURE:
imagep = new LLViewerLODTexture(image_id, usemipmaps);
imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps);
break ;
default:
llerrs << "Invalid texture type " << texture_type << llendl ;
}
// Might want to request from host other than where the agent is. JC
imagep->setTargetHost(request_from_host);
if (internal_format && primary_format)
{
imagep->setExplicitFormat(internal_format, primary_format);
@ -446,7 +466,7 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
if (level_immediate)
{
imagep->dontDiscard();
imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
imagep->setBoostLevel(LLViewerTexture::BOOST_UI);
}
else
{
@ -509,7 +529,7 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image)
{
llwarns << "Image with ID " << image_id << " already in list" << llendl;
}
mNumImages++;
sNumImages++;
addImageToList(new_image);
mUUIDMap[image_id] = new_image;
@ -526,7 +546,7 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
}
llverify(mUUIDMap.erase(image->getID()) == 1);
mNumImages--;
sNumImages--;
removeImageFromList(image);
}
}
@ -546,7 +566,9 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images");
void LLViewerTextureList::updateImages(F32 max_time)
{
LLViewerStats::getInstance()->mNumImagesStat.addValue(mNumImages);
LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec());
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes));
LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes));
@ -554,10 +576,13 @@ void LLViewerTextureList::updateImages(F32 max_time)
LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
updateImagesDecodePriorities();
F32 total_max_time = max_time;
max_time -= updateImagesFetchTextures(max_time);
max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f);
max_time = llmax(max_time, total_max_time*.25f); // at least 25% of max_time
max_time -= updateImagesCreateTextures(max_time);
max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f);
if (!mDirtyTextureList.empty())
{
LLFastTimer t(FTM_IMAGE_MARK_DIRTY);
@ -570,7 +595,7 @@ void LLViewerTextureList::updateImages(F32 max_time)
{
//trigger loaded callbacks on local textures immediately
LLViewerFetchedTexture* image = *iter++;
if (!image->getLocalFileName().empty())
if (!image->getUrl().empty())
{
// Do stuff to handle callbacks, update priorities, etc.
didone = image->doLoadedCallbacks();
@ -628,6 +653,14 @@ void LLViewerTextureList::updateImagesDecodePriorities()
}
else
{
if(imagep->hasSavedRawImage())
{
if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME)
{
imagep->destroySavedRawImage() ;
}
}
if(imagep->isDeleted())
{
continue ;
@ -758,74 +791,76 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256);
// 32 high priority entries
std::set<LLViewerFetchedTexture*> entries;
typedef std::vector<LLViewerFetchedTexture*> entries_list_t;
entries_list_t entries;
size_t update_counter = llmin(max_priority_count, mImageList.size());
image_priority_list_t::iterator iter1 = mImageList.begin();
while(update_counter > 0)
{
// added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad
if(iter1 == mImageList.end())
{
llerrs << "DEV-12002: update_counter not calculated correctly!" << llendl;
return 0.f;
}
LLPointer<LLViewerFetchedTexture> const & ptr = *iter1;
LLViewerFetchedTexture * img = ptr.get();
// added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad
if(img == NULL)
{
llwarns << "DEV-12002: image is NULL!" << llendl;
}
entries.insert(img);
entries.push_back(*iter1);
++iter1;
update_counter--;
}
// 256 cycled entries
update_counter = llmin(max_update_count, mUUIDMap.size());
uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
while(update_counter > 0)
update_counter = llmin(max_update_count, mUUIDMap.size());
if(update_counter > 0)
{
if (iter2 == mUUIDMap.end())
uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
uuid_map_t::iterator iter2p = iter2;
while(update_counter > 0)
{
iter2 = mUUIDMap.begin();
if (iter2 == mUUIDMap.end())
{
iter2 = mUUIDMap.begin();
}
entries.push_back(iter2->second);
iter2p = iter2++;
update_counter--;
}
mLastFetchUUID = iter2->first;
entries.insert(iter2->second);
++iter2;
update_counter--;
mLastFetchUUID = iter2p->first;
}
S32 fetch_count = 0;
S32 min_count = max_priority_count + max_update_count/4;
for (std::set<LLViewerFetchedTexture*>::iterator iter3 = entries.begin();
for (entries_list_t::iterator iter3 = entries.begin();
iter3 != entries.end(); )
{
LLPointer<LLViewerFetchedTexture> imagep = *iter3++;
imagep->updateFetch();
bool fetching = imagep->updateFetch();
if (fetching)
{
fetch_count++;
}
if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time)
{
break;
}
min_count--;
}
if (fetch_count == 0)
{
gDebugTimers[0].pause();
}
else
{
gDebugTimers[0].unpause();
}
return image_op_timer.getElapsedTimeF32();
}
void LLViewerTextureList::updateImagesUpdateStats()
{
if (mUpdateStats)
if (mUpdateStats && mForceResetTextureStats)
{
for (image_priority_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
imagep->resetTextureStats(mForceResetTextureStats);
imagep->resetTextureStats();
}
mUpdateStats = FALSE;
mForceResetTextureStats = FALSE;
@ -1011,6 +1046,9 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage
return compressedImage;
}
const S32 MIN_VIDEO_RAM = 32;
const S32 MAX_VIDEO_RAM = 512; // 512MB max for performance reasons.
// Returns min setting for TextureMemory (in MB)
S32 LLViewerTextureList::getMinVideoRamSetting()
{
@ -1129,13 +1167,13 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
if (msg->getReceiveCompressedSize())
{
gTextureList.mTextureBits += msg->getReceiveCompressedSize() * 8;
gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
}
else
{
gTextureList.mTextureBits += msg->getReceiveSize() * 8;
gTextureList.sTextureBits += msg->getReceiveSize() * 8;
}
gTextureList.mTexturePackets++;
gTextureList.sTexturePackets++;
U8 codec;
U16 packets;
@ -1194,13 +1232,13 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
if (msg->getReceiveCompressedSize())
{
gTextureList.mTextureBits += msg->getReceiveCompressedSize() * 8;
gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
}
else
{
gTextureList.mTextureBits += msg->getReceiveSize() * 8;
gTextureList.sTextureBits += msg->getReceiveSize() * 8;
}
gTextureList.mTexturePackets++;
gTextureList.sTexturePackets++;
//llprintline("Start decode, image header...");
msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
@ -1385,7 +1423,7 @@ void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_v
// for images grabbed from local files, apply clipping rectangle to restore original dimensions
// from power-of-2 gl image
if (success && imagep.notNull() && src_vi && !src_vi->getLocalFileName().empty())
if (success && imagep.notNull() && src_vi && (src_vi->getUrl().compare(0, 7, "file://")==0))
{
F32 clip_x = (F32)src_vi->getOriginalWidth() / (F32)src_vi->getFullWidth();
F32 clip_y = (F32)src_vi->getOriginalHeight() / (F32)src_vi->getFullHeight();
@ -1442,6 +1480,11 @@ bool LLUIImageList::initFromFile()
llwarns << "Unable to parse UI image list file " << base_file_path << llendl;
return false;
}
if (!root->hasAttribute("version"))
{
llwarns << "No valid version number in UI image list file " << base_file_path << llendl;
return false;
}
std::vector<std::string> paths;
// path to current selected skin

View File

@ -53,7 +53,6 @@ const BOOL GL_TEXTURE_NO = FALSE;
const BOOL IMMEDIATE_YES = TRUE;
const BOOL IMMEDIATE_NO = FALSE;
class LLImageJ2C;
class LLMessageSystem;
class LLTextureView;
@ -146,6 +145,15 @@ private:
LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null
);
LLViewerFetchedTexture* getImageFromUrl(const std::string& url,
BOOL usemipmap = TRUE,
BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null
);
LLViewerFetchedTexture* createImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
@ -190,11 +198,18 @@ private:
LLFrameTimer mForceDecodeTimer;
public:
U32 mTextureBits;
U32 mTexturePackets;
static U32 sTextureBits;
static U32 sTexturePackets;
static LLStat sNumImagesStat;
static LLStat sNumRawImagesStat;
static LLStat sGLTexMemStat;
static LLStat sGLBoundMemStat;
static LLStat sRawMemStat;
static LLStat sFormattedMemStat;
private:
S32 mNumImages;
static S32 sNumImages;
static void (*sUUIDCallback)(void**, const LLUUID &);
};

View File

@ -117,6 +117,7 @@
#include "llhudview.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
#include "llimageworker.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
@ -157,7 +158,6 @@
#include "lltoolselectland.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "lluploaddialog.h"
#include "llurldispatcher.h" // SLURL from other app instance
#include "llvieweraudio.h"
#include "llviewercamera.h"
@ -189,6 +189,7 @@
#include "llbottomtray.h"
#include "llnearbychatbar.h"
#include "llagentui.h"
#include "llwearablelist.h"
#include "llnotificationmanager.h"
@ -326,7 +327,9 @@ public:
S32 hours = (S32)(time / (60*60));
S32 mins = (S32)((time - hours*(60*60)) / 60);
S32 secs = (S32)((time - hours*(60*60) - mins*60));
addText(xpos, ypos, llformat(" Debug %d: %d:%02d:%02d", idx, hours,mins,secs)); ypos += y_inc2;
std::string label = gDebugTimerLabel[idx];
if (label.empty()) label = llformat("Debug: %d", idx);
addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
}
F32 time = gFrameTimeSeconds;
@ -1299,6 +1302,7 @@ LLViewerWindow::LLViewerWindow(
// Init the image list. Must happen after GL is initialized and before the images that
// LLViewerWindow needs are requested.
LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
gTextureList.init();
LLViewerTextureManager::init() ;
gBumpImageList.init();
@ -1657,6 +1661,8 @@ void LLViewerWindow::shutdownGL()
gSky.cleanup();
stop_glerror();
LLWearableList::instance().cleanup() ;
gTextureList.shutdown();
stop_glerror();
@ -1670,7 +1676,10 @@ void LLViewerWindow::shutdownGL()
stop_glerror();
LLViewerTextureManager::cleanup() ;
LLImageGL::cleanupClass() ;
llinfos << "All texturs and llimagegl images are destroyed!" << llendl ;
llinfos << "Cleaning up select manager" << llendl;
LLSelectMgr::getInstance()->cleanup();

View File

@ -321,7 +321,7 @@ public:
} ESnapshotType;
BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_IMAGE_SIZE );
BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE );
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
void resetSnapshotLoc() const { sSnapshotDir.clear(); }

View File

@ -279,7 +279,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
if (mRawImages[i].isNull())
{
// Read back a raw image for this discard level, if it exists
mRawImages[i] = new LLImageRaw;
S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight());
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
@ -287,12 +286,18 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
ddiscard++;
min_dim /= 2;
}
if (!mDetailTextures[i]->readBackRaw(ddiscard, mRawImages[i], false))
mDetailTextures[i]->reloadRawImage(ddiscard) ;
if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
{
llwarns << "Unable to read raw data for terrain detail texture: " << mDetailTextures[i]->getID() << llendl;
mRawImages[i] = NULL;
mDetailTextures[i]->destroyRawImage() ;
lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl;
return FALSE;
}
mRawImages[i] = mDetailTextures[i]->getRawImage() ;
mDetailTextures[i]->destroyRawImage() ;
if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getComponents() != 3)

View File

@ -988,7 +988,7 @@ void LLVOAvatar::resetImpostors()
// static
void LLVOAvatar::deleteCachedImages(bool clearAll)
{
{
if (LLTexLayerSet::sHasCaches)
{
lldebugs << "Deleting layer set caches" << llendl;
@ -3897,7 +3897,7 @@ U32 LLVOAvatar::renderFootShadows()
LLGLDepthTest test(GL_TRUE, GL_FALSE);
//render foot shadows
LLGLEnable blend(GL_BLEND);
gGL.getTexUnit(0)->bind(mShadowImagep.get());
gGL.getTexUnit(0)->bind(mShadowImagep, TRUE);
glColor4fv(mShadow0Facep->getRenderColor().mV);
mShadow0Facep->renderIndexed(foot_mask);
glColor4fv(mShadow1Facep->getRenderColor().mV);
@ -3945,7 +3945,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
//------------------------------------------------------------------------
// LLVOAvatar::updateTextures()
//------------------------------------------------------------------------
void LLVOAvatar::updateTextures(LLAgent &agent)
void LLVOAvatar::updateTextures()
{
BOOL render_avatar = TRUE;

View File

@ -125,7 +125,7 @@ public:
virtual BOOL updateLOD();
BOOL updateJointLODs();
virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate.
virtual void updateTextures(LLAgent &agent);
virtual void updateTextures();
virtual S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim.
virtual void onShift(const LLVector3& shift_vector);
virtual U32 getPartitionType() const;

View File

@ -1141,26 +1141,6 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr
}
}
// virtual
/* //unused
BOOL LLVOAvatarSelf::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw) const
{
if (!isIndexLocalTexture(index)) return FALSE;
if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) return TRUE;
const LocalTextureData *local_tex_data = getLocalTextureData(index)[0];
if (local_tex_data->mImage->readBackRaw(-1, image_raw, false))
{
return TRUE;
}
// No data loaded yet
setLocalTexture((ETextureIndex)index, getTEImage(index), FALSE); // <-- non-const, move this elsewhere
return FALSE;
}
*/
// virtual
BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex_pp, U32 index) const
{
@ -1812,12 +1792,13 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
if (!covered_by_baked)
{
if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR)
if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0)
{
F32 desired_pixels;
desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
imagep->setBoostLevel(getAvatarBoostLevel());
imagep->addTextureStats( desired_pixels / texel_area_ratio );
imagep->forceUpdateBindStats() ;
if (imagep->getDiscardLevel() < 0)
{
mHasGrey = TRUE; // for statistics gathering
@ -2115,6 +2096,49 @@ BOOL LLVOAvatarSelf::needsRenderBeam()
// static
void LLVOAvatarSelf::deleteScratchTextures()
{
if(gAuditTexture)
{
S32 total_tex_size = sScratchTexBytes ;
S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ;
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
{
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= tex_size ;
}
if( sScratchTexNames.checkData( GL_ALPHA ) )
{
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= tex_size ;
}
if( sScratchTexNames.checkData( GL_COLOR_INDEX ) )
{
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= tex_size ;
}
if( sScratchTexNames.checkData( GL_LUMINANCE_ALPHA ) )
{
LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= 2 * tex_size ;
}
if( sScratchTexNames.checkData( GL_RGB ) )
{
LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= 3 * tex_size ;
}
if( sScratchTexNames.checkData( GL_RGBA ) )
{
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= 4 * tex_size ;
}
//others
while(total_tex_size > 0)
{
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
total_tex_size -= 4 * tex_size ;
}
}
for( LLGLuint* namep = sScratchTexNames.getFirstData();
namep;
namep = sScratchTexNames.getNextData() )
@ -2137,7 +2161,8 @@ void LLVOAvatarSelf::deleteScratchTextures()
BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format )
{
U32 texture_bytes = 0;
GLuint gl_name = getScratchTexName( format, &texture_bytes );
S32 components = 0;
GLuint gl_name = getScratchTexName( format, components, &texture_bytes );
if( gl_name )
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name);
@ -2149,12 +2174,12 @@ BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format )
if( *last_bind_time != LLImageGL::sLastFrameTime )
{
*last_bind_time = LLImageGL::sLastFrameTime;
LLImageGL::updateBoundTexMem(texture_bytes);
LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
}
}
else
{
LLImageGL::updateBoundTexMem(texture_bytes);
LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) );
}
return TRUE;
@ -2162,9 +2187,8 @@ BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format )
return FALSE;
}
LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, U32* texture_bytes )
{
S32 components;
LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, S32& components, U32* texture_bytes )
{
GLenum internal_format;
switch( format )
{
@ -2210,6 +2234,11 @@ LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, U32* texture_bytes
sScratchTexBytes += *texture_bytes;
LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes;
if(gAuditTexture)
{
LLImageGL::incTextureCounter(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
}
return name;
}

View File

@ -239,7 +239,7 @@ public:
BOOL bindScratchTexture(LLGLenum format);
static void deleteScratchTextures();
protected:
LLGLuint getScratchTexName(LLGLenum format, U32* texture_bytes);
LLGLuint getScratchTexName(LLGLenum format, S32& components, U32* texture_bytes);
private:
static S32 sScratchTexBytes;
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;

View File

@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent)
mPixelArea = 1500*100;
}
void LLVOClouds::updateTextures(LLAgent &agent)
void LLVOClouds::updateTextures()
{
getTEImage(0)->addTextureStats(mPixelArea);
}

View File

@ -65,7 +65,7 @@ public:
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
F32 getPartSize(S32 idx);
/*virtual*/ void updateTextures(LLAgent &agent);
/*virtual*/ void updateTextures();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
void updateFaceSize(S32 idx) { }

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