merge changes for DRTVWR-149

master
Oz Linden 2012-05-22 06:03:42 -04:00
commit 7637acf76e
68 changed files with 3876 additions and 1297 deletions

View File

@ -1,5 +1,6 @@
syntax: glob
# WinMerge temp files
*.bak
# Compiled python bytecode

0
.hgtags Normal file → Executable file
View File

View File

@ -181,4 +181,35 @@ simon_viewer-dev-private.email_status_this_is_os = false
vir-project-1.viewer_channel = "Second Life Release"
vir-project-1.login_channel = "Second Life Release"
# ========================================
# THX-1138 / Runway projects
# ========================================
viewer-thx1138-runway-shared.viewer_channel = "Project Viewer - THX-1138 Runway"
viewer-thx1138-runway-shared.login_channel = "Project Viewer - THX-1138 Runway"
viewer-thx1138-runway-shared.viewer_grid = uma
viewer-thx1138-runway-shared.build_debug_release_separately = true
viewer-thx1138-runway-shared.build_CYGWIN_Debug = false
viewer-thx1138-runway-shared.build_viewer_update_version_manager = false
viewer-thx1138.viewer_channel = "Project Viewer - THX-1138"
viewer-thx1138.login_channel = "Project Viewer - THX-1138"
viewer-thx1138.viewer_grid = uma
viewer-thx1138.build_debug_release_separately = true
viewer-thx1138.build_CYGWIN_Debug = false
viewer-thx1138.build_viewer_update_version_manager = false
runway-merge.viewer_channel = "Project Viewer - Runway Merge"
runway-merge.login_channel = "Project Viewer - Runway Merge"
runway-merge.viewer_grid = agni
runway-merge.build_debug_release_separately = true
runway-merge.build_CYGWIN_Debug = false
runway-merge.build_viewer_update_version_manager = false
runway.viewer_channel = "Project Viewer - Runway"
runway.login_channel = "Project Viewer - Runway"
runway.viewer_grid = agni
runway.build_debug_release_separately = true
runway.build_CYGWIN_Debug = false
runway.build_viewer_update_version_manager = false
# eof

View File

@ -54,6 +54,11 @@ static const char USAGE[] = "\n"
" -o, --output <file1 .. file2> OR <type>\n"
" List of image files to create (assumes same order as for input files)\n"
" OR 3 letters file type extension to convert each input file into.\n"
" -load, --load_size <n>\n"
" Portion of the input file to load, in bytes."
" If (load == 0), it will load the whole file."
" If (load == -1), it will load the size relevant to reach the requested discard level (see -d)."
" Only valid for j2c images. Default is 0 (load whole file).\n"
" -r, --region <x0, y0, x1, y1>\n"
" Crop region applied to the input files in pixels.\n"
" Only used for j2c images. Default is no region cropping.\n"
@ -104,22 +109,52 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi
// Print out some statistical data on the image
std::cout << "Image stats for : " << filename << ", extension : " << image->getExtension() << std::endl;
std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl;
std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getDiscardLevel()) << std::endl;
std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl;
std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl;
std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getLevels()) << std::endl;
std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl;
return;
}
// Load an image from file and return a raw (decompressed) instance of its data
LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats)
LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, int load_size, bool output_stats)
{
LLPointer<LLImageFormatted> image = create_image(src_filename);
// This just loads the image file stream into a buffer. No decoding done.
if (!image->load(src_filename))
// We support partial loading only for j2c images
if (image->getCodec() == IMG_CODEC_J2C)
{
return NULL;
// Load the header
if (!image->load(src_filename, 600))
{
return NULL;
}
S32 h = ((LLImageJ2C*)(image.get()))->calcHeaderSize();
S32 d = (load_size > 0 ? ((LLImageJ2C*)(image.get()))->calcDiscardLevelBytes(load_size) : 0);
S8 r = ((LLImageJ2C*)(image.get()))->getRawDiscardLevel();
std::cout << "Merov debug : header = " << h << ", load_size = " << load_size << ", discard level = " << d << ", raw discard level = " << r << std::endl;
for (d = 0; d < MAX_DISCARD_LEVEL; d++)
{
S32 data_size = ((LLImageJ2C*)(image.get()))->calcDataSize(d);
std::cout << "Merov debug : discard_level = " << d << ", data_size = " << data_size << std::endl;
}
if (load_size < 0)
{
load_size = (discard_level != -1 ? ((LLImageJ2C*)(image.get()))->calcDataSize(discard_level) : 0);
}
// Load the requested byte range
if (!image->load(src_filename, load_size))
{
return NULL;
}
}
else
{
// This just loads the image file stream into a buffer. No decoding done.
if (!image->load(src_filename))
{
return NULL;
}
}
if( (image->getComponents() != 3) && (image->getComponents() != 4) )
@ -310,6 +345,7 @@ int main(int argc, char** argv)
bool image_stats = false;
int* region = NULL;
int discard_level = -1;
int load_size = 0;
int precincts_size = -1;
int blocks_size = -1;
int levels = 0;
@ -396,6 +432,22 @@ int main(int argc, char** argv)
discard_level = llclamp(discard_level,0,5);
}
}
else if (!strcmp(argv[arg], "--load_size") || !strcmp(argv[arg], "-load"))
{
std::string value_str;
if ((arg + 1) < argc)
{
value_str = argv[arg+1];
}
if (((arg + 1) >= argc) || (value_str[0] == '-'))
{
std::cout << "No valid --load_size argument given, load_size ignored" << std::endl;
}
else
{
load_size = atoi(value_str.c_str());
}
}
else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p"))
{
std::string value_str;
@ -510,7 +562,7 @@ int main(int argc, char** argv)
for (; in_file != in_end; ++in_file, ++out_file)
{
// Load file
LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, image_stats);
LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, load_size, image_stats);
if (!raw_image)
{
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;

View File

@ -48,11 +48,15 @@
//static
std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
bool LLImage::sUseNewByteRange = false;
S32 LLImage::sMinimalReverseByteRangePercent = 75;
LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
//static
void LLImage::initClass()
void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent)
{
sUseNewByteRange = use_new_byte_range;
sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
sMutex = new LLMutex(NULL);
LLImageBase::createPrivatePool() ;
@ -1334,7 +1338,8 @@ LLImageFormatted::LLImageFormatted(S8 codec)
mCodec(codec),
mDecoding(0),
mDecoded(0),
mDiscardLevel(-1)
mDiscardLevel(-1),
mLevels(0)
{
mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
}
@ -1561,7 +1566,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
//----------------------------------------------------------------------------
BOOL LLImageFormatted::load(const std::string &filename)
BOOL LLImageFormatted::load(const std::string &filename, int load_size)
{
resetLastError();
@ -1580,14 +1585,19 @@ BOOL LLImageFormatted::load(const std::string &filename)
return FALSE;
}
// Constrain the load size to acceptable values
if ((load_size == 0) || (load_size > file_size))
{
load_size = file_size;
}
BOOL res;
U8 *data = allocateData(file_size);
apr_size_t bytes_read = file_size;
U8 *data = allocateData(load_size);
apr_size_t bytes_read = load_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
if (s != APR_SUCCESS || (S32) bytes_read != file_size)
if (s != APR_SUCCESS || (S32) bytes_read != load_size)
{
deleteData();
setLastError("Unable to read entire file",filename);
setLastError("Unable to read file",filename);
res = FALSE;
}
else

View File

@ -48,6 +48,8 @@ const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_S
const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE
const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks
const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec
const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!!
const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit)
const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
@ -60,6 +62,7 @@ const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 *
// *TODO: change both to 1024 when SIM texture fetching is deprecated
const S32 FIRST_PACKET_SIZE = 600;
const S32 MAX_IMG_PACKET_SIZE = 1000;
const S32 HTTP_PACKET_SIZE = 1496;
// Base classes for images.
// There are two major parts for the image:
@ -89,15 +92,20 @@ typedef enum e_image_codec
class LLImage
{
public:
static void initClass();
static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75);
static void cleanupClass();
static const std::string& getLastError();
static void setLastError(const std::string& message);
static bool useNewByteRange() { return sUseNewByteRange; }
static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; }
protected:
static LLMutex* sMutex;
static std::string sLastErrorMessage;
static bool sUseNewByteRange;
static S32 sMinimalReverseByteRangePercent;
};
//============================================================================
@ -294,7 +302,7 @@ public:
// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
virtual S8 getRawDiscardLevel() { return mDiscardLevel; }
BOOL load(const std::string& filename);
BOOL load(const std::string& filename, int load_size = 0);
BOOL save(const std::string& filename);
virtual BOOL updateData() = 0; // pure virtual
@ -313,6 +321,8 @@ public:
BOOL isDecoded() const { return mDecoded ? TRUE : FALSE; }
void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
S8 getDiscardLevel() const { return mDiscardLevel; }
S8 getLevels() const { return mLevels; }
void setLevels(S8 nlevels) { mLevels = nlevels; }
// setLastError needs to be deferred for J2C images since it may be called from a DLL
virtual void resetLastError();
@ -325,7 +335,8 @@ protected:
S8 mCodec;
S8 mDecoding;
S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC
S8 mDiscardLevel;
S8 mDiscardLevel; // Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc...
S8 mLevels; // Number of resolution levels in that image. Min is 1. 0 means unknown.
public:
static S32 sGlobalFormattedMemory;

85
indra/llimage/llimagej2c.cpp Normal file → Executable file
View File

@ -56,7 +56,7 @@ std::string LLImageJ2C::getEngineInfo()
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mMaxBytes(0),
mRawDiscardLevel(-1),
mRate(0.0f),
mRate(DEFAULT_COMPRESSION_RATE),
mReversible(FALSE),
mAreaUsedForDataSizeCalcs(0)
{
@ -142,6 +142,7 @@ BOOL LLImageJ2C::updateData()
BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)
{
setDiscardLevel(discard_level != -1 ? discard_level : 0);
return mImpl->initDecode(*this,raw_image,discard_level,region);
}
@ -261,19 +262,34 @@ S32 LLImageJ2C::calcHeaderSizeJ2C()
//static
S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
{
// Note: this only provides an *estimate* of the size in bytes of an image level
// *TODO: find a way to read the true size (when available) and convey the fact
// that the result is an estimate in the other cases
if (rate <= 0.f) rate = .125f;
while (discard_level > 0)
// Note: This provides an estimation for the first to last quality layer of a given discard level
// This is however an efficient approximation, as the true discard level boundary would be
// in general too big for fast fetching.
// For details about the equation used here, see https://wiki.lindenlab.com/wiki/THX1138_KDU_Improvements#Byte_Range_Study
// Estimate the number of layers. This is consistent with what's done for j2c encoding in LLImageJ2CKDU::encodeImpl().
S32 nb_layers = 1;
S32 surface = w*h;
S32 s = 64*64;
while (surface > s)
{
if (w < 1 || h < 1)
break;
w >>= 1;
h >>= 1;
discard_level--;
nb_layers++;
s *= 4;
}
S32 bytes = (S32)((F32)(w*h*comp)*rate);
F32 layer_factor = 3.0f * (7 - llclamp(nb_layers,1,6));
// Compute w/pow(2,discard_level) and h/pow(2,discard_level)
w >>= discard_level;
h >>= discard_level;
w = llmax(w, 1);
h = llmax(h, 1);
// Temporary: compute both new and old range and pick one according to the settings TextureNewByteRange
// *TODO: Take the old code out once we have enough tests done
S32 bytes;
S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor);
S32 old_bytes = (S32)((F32)(w*h*comp)*rate);
bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes);
bytes = llmax(bytes, calcHeaderSizeJ2C());
return bytes;
}
@ -283,15 +299,12 @@ S32 LLImageJ2C::calcHeaderSize()
return calcHeaderSizeJ2C();
}
// calcDataSize() returns how many bytes to read
// to load discard_level (including header and higher discard levels)
// calcDataSize() returns how many bytes to read to load discard_level (including header)
S32 LLImageJ2C::calcDataSize(S32 discard_level)
{
discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth())
|| mDataSizes[0] == 0)
|| (mDataSizes[0] == 0))
{
mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
@ -301,25 +314,6 @@ S32 LLImageJ2C::calcDataSize(S32 discard_level)
mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
level--;
}
/* This is technically a more correct way to calculate the size required
for each discard level, since they should include the size needed for
lower levels. Unfortunately, this doesn't work well and will lead to
download stalls. The true correct way is to parse the header. This will
all go away with http textures at some point.
// Calculate the size for each discard level. Lower levels (higher quality)
// contain the cumulative size of higher levels
S32 total_size = calcHeaderSizeJ2C();
S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
while ( level >= 0 )
{ // Add in this discard level and all before it
total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
mDataSizes[level] = total_size;
level--;
}
*/
}
return mDataSizes[discard_level];
}
@ -334,8 +328,9 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
}
while (1)
{
S32 bytes_needed = calcDataSize(discard_level); // virtual
if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes
S32 bytes_needed = calcDataSize(discard_level);
// Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level
if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100))
{
break;
}
@ -348,11 +343,6 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
return discard_level;
}
void LLImageJ2C::setRate(F32 rate)
{
mRate = rate;
}
void LLImageJ2C::setMaxBytes(S32 max_bytes)
{
mMaxBytes = max_bytes;
@ -474,6 +464,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester
addMetric("Perf Compression (kB/s)");
mRunBytesInDecompression = 0;
mRunBytesOutDecompression = 0;
mRunBytesInCompression = 0;
mTotalBytesInDecompression = 0;
@ -483,6 +474,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester
mTotalTimeDecompression = 0.0f;
mTotalTimeCompression = 0.0f;
mRunTimeDecompression = 0.0f;
}
LLImageCompressionTester::~LLImageCompressionTester()
@ -565,12 +557,17 @@ void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const
mTotalBytesInDecompression += bytesIn;
mRunBytesInDecompression += bytesIn;
mTotalBytesOutDecompression += bytesOut;
if (mRunBytesInDecompression > (1000000))
mRunBytesOutDecompression += bytesOut;
//if (mRunBytesInDecompression > (1000000))
if (mRunBytesOutDecompression > (10000000))
//if ((mTotalTimeDecompression - mRunTimeDecompression) >= (5.0f))
{
// Output everything
outputTestResults();
// Reset the decompression data of the run
mRunBytesInDecompression = 0;
mRunBytesOutDecompression = 0;
mRunTimeDecompression = mTotalTimeDecompression;
}
}

View File

@ -31,6 +31,9 @@
#include "llassettype.h"
#include "llmetricperformancetester.h"
// JPEG2000 : compression rate used in j2c conversion.
const F32 DEFAULT_COMPRESSION_RATE = 1.f/8.f;
class LLImageJ2CImpl;
class LLImageCompressionTester ;
@ -67,12 +70,11 @@ public:
// Encode accessors
void setReversible(const BOOL reversible); // Use non-lossy?
void setRate(F32 rate);
void setMaxBytes(S32 max_bytes);
S32 getMaxBytes() const { return mMaxBytes; }
static S32 calcHeaderSizeJ2C();
static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f);
static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = DEFAULT_COMPRESSION_RATE);
static std::string getEngineInfo();
@ -154,13 +156,15 @@ class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
U32 mTotalBytesOutDecompression; // Total bytes produced by decompressor
U32 mTotalBytesInCompression; // Total bytes fed to compressor
U32 mTotalBytesOutCompression; // Total bytes produced by compressor
U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run
U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run
U32 mRunBytesOutDecompression; // Bytes produced by the decompressor in this run
U32 mRunBytesInCompression; // Bytes fed to compressor in this run
//
// Time
//
F32 mTotalTimeDecompression; // Total time spent in computing decompression
F32 mTotalTimeCompression; // Total time spent in computing compression
F32 mRunTimeDecompression; // Time in this run (we output every 5 sec in decompress)
};
#endif

View File

@ -32,6 +32,7 @@
#include "llmath.h"
#include "llkdumem.h"
#include "kdu_block_coding.h"
class kdc_flow_control {
@ -244,7 +245,9 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
mCodeStreamp->create(mInputp);
// Set the maximum number of bytes to use from the codestream
mCodeStreamp->set_max_bytes(max_bytes);
// *TODO: This seems to be wrong. The base class should have no idea of how j2c compression works so no
// good way of computing what's the byte range to be used.
mCodeStreamp->set_max_bytes(max_bytes,true);
// If you want to flip or rotate the image for some reason, change
// the resolution, or identify a restricted region of interest, this is
@ -291,8 +294,13 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
}
}
// Get the number of resolution levels in that image
mLevels = mCodeStreamp->get_min_dwt_levels();
// Set the base dimensions
base.setSize(dims.size.x, dims.size.y, components);
base.setLevels(mLevels);
if (!keep_codestream)
{
mCodeStreamp->destroy();
@ -351,7 +359,8 @@ BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
mLevels = levels;
if (mLevels != 0)
{
mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MIN_DECOMPOSITION_LEVELS);
mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MAX_DECOMPOSITION_LEVELS);
base.setLevels(mLevels);
}
return TRUE;
}
@ -364,6 +373,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// To regain control, we throw an exception, and catch it here.
try
{
// Merov : Test!! DO NOT COMMIT!!
//findDiscardLevelsBoundaries(base);
base.updateRawDiscardLevel();
setupCodeStream(base, TRUE, mode);
@ -381,7 +393,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
region_kdu->size.y = region[3] - region[1];
}
int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel());
//llinfos << "Merov debug : initDecode, discard used = " << discard << ", asked = " << discard_level << llendl;
// Apply loading restrictions
mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu);
@ -394,12 +406,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// Resize raw_image according to the image to be decoded
kdu_dims dims; mCodeStreamp->get_dims(0,dims);
// *TODO: Use the real number of levels read from the file throughout the code instead of relying on an infered value from dimensions
//S32 levels = mCodeStreamp->get_min_dwt_levels();
S32 channels = base.getComponents() - first_channel;
channels = llmin(channels,max_channel_count);
raw_image.resize(dims.size.x, dims.size.y, channels);
//llinfos << "j2c image dimension: width = " << dims.size.x << ", height = " << dims.size.y << ", channels = " << channels << ", levels = " << levels << llendl;
if (!mTileIndicesp)
{
@ -583,12 +592,6 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
comment.put_text(comment_text);
}
// Set codestream options
int num_layer_specs = 0;
kdu_long layer_bytes[64];
U32 max_bytes = 0;
if (num_components >= 3)
{
// Note that we always use YCC and not YUV
@ -596,66 +599,51 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
set_default_colour_weights(codestream.access_siz());
}
// Set codestream options
int nb_layers = 0;
kdu_long layer_bytes[MAX_NB_LAYERS];
U32 max_bytes = (U32)(base.getWidth() * base.getHeight() * base.getComponents());
// Rate is the argument passed into the LLImageJ2C which specifies the target compression rate. The default is 8:1.
// *TODO: mRate is actually always 8:1 in the viewer. Test different values.
llassert (base.mRate > 0.f);
max_bytes = (U32)((F32)(max_bytes) * base.mRate);
// This code is where we specify the target number of bytes for each quality layer.
// We're using a logarithmic spacing rule that fits with our way of fetching texture data.
// Note: For more info on this layers business, read kdu_codestream::flush() doc in kdu_compressed.h
layer_bytes[nb_layers++] = FIRST_PACKET_SIZE;
U32 i = MIN_LAYER_SIZE;
while ((i < max_bytes) && (nb_layers < (MAX_NB_LAYERS-1)))
{
layer_bytes[nb_layers++] = i;
i *= 4;
}
// Note: for small images, we can have (max_bytes < FIRST_PACKET_SIZE), hence the test
if (layer_bytes[nb_layers-1] < max_bytes)
{
// Set the last quality layer so to fit the preset compression ratio
layer_bytes[nb_layers++] = max_bytes;
}
if (reversible)
{
// Use 0 for a last quality layer for reversible images so all remaining code blocks will be flushed
// Hack: KDU encoding for reversible images has a bug for small images that leads to j2c images that
// cannot be open or are very blurry. Avoiding that last layer prevents the problem to happen.
if ((base.getWidth() >= 32) || (base.getHeight() >= 32))
{
layer_bytes[nb_layers++] = 0;
}
codestream.access_siz()->parse_string("Creversible=yes");
// *TODO: we should use yuv in reversible mode and one level since those images are small.
// Don't turn this on now though as both create problems on decoding for the moment
//codestream.access_siz()->parse_string("Clevels=1");
// *TODO: we should use yuv in reversible mode
// Don't turn this on now though as it creates problems on decoding for the moment
//codestream.access_siz()->parse_string("Cycc=no");
// If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers.
// *TODO: this is incorrect and unecessary. Try using the regular layer setting.
codestream.access_siz()->parse_string("Clayers=1");
num_layer_specs = 1;
layer_bytes[0] = 0;
}
else
{
// Rate is the argument passed into the LLImageJ2C which
// specifies the target compression rate. The default is 8:1.
// Possibly if max_bytes < 500, we should just use the default setting?
// *TODO: mRate is actually always 8:1 in the viewer. Test different values. Also force to reversible for small (< 500 bytes) textures.
if (base.mRate != 0.f)
{
max_bytes = (U32)(base.mRate*base.getWidth()*base.getHeight()*base.getComponents());
}
else
{
max_bytes = (U32)(base.getWidth()*base.getHeight()*base.getComponents()*0.125);
}
const U32 min_bytes = FIRST_PACKET_SIZE;
if (max_bytes > min_bytes)
{
U32 i;
// This code is where we specify the target number of bytes for
// each layer. Not sure if we should do this for small images
// or not. The goal is to have this roughly align with
// different quality levels that we decode at.
for (i = min_bytes; i < max_bytes; i*=4)
{
if (i == min_bytes * 4)
{
i = 2000;
}
layer_bytes[num_layer_specs] = i;
num_layer_specs++;
}
layer_bytes[num_layer_specs] = max_bytes;
num_layer_specs++;
std::string layer_string = llformat("Clayers=%d",num_layer_specs);
codestream.access_siz()->parse_string(layer_string.c_str());
}
else
{
layer_bytes[0] = min_bytes;
num_layer_specs = 1;
std::string layer_string = llformat("Clayers=%d",num_layer_specs);
codestream.access_siz()->parse_string(layer_string.c_str());
}
}
std::string layer_string = llformat("Clayers=%d",nb_layers);
codestream.access_siz()->parse_string(layer_string.c_str());
// Set up data ordering, markers, etc... if precincts or blocks specified
if ((mBlocksSize != -1) || (mPrecinctsSize != -1))
{
@ -669,23 +657,26 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
std::string blocks_string = llformat("Cblk={%d,%d}",mBlocksSize,mBlocksSize);
codestream.access_siz()->parse_string(blocks_string.c_str());
}
std::string ordering_string = llformat("Corder=RPCL");
std::string ordering_string = llformat("Corder=LRCP");
codestream.access_siz()->parse_string(ordering_string.c_str());
std::string PLT_string = llformat("ORGgen_plt=yes");
codestream.access_siz()->parse_string(PLT_string.c_str());
std::string Parts_string = llformat("ORGtparts=R");
codestream.access_siz()->parse_string(Parts_string.c_str());
}
// Set the number of wavelets subresolutions (aka levels)
if (mLevels != 0)
{
std::string levels_string = llformat("Clevels=%d",mLevels);
codestream.access_siz()->parse_string(levels_string.c_str());
}
// Complete the encode settings
codestream.access_siz()->finalize_all();
codestream.change_appearance(transpose,vflip,hflip);
// Now we are ready for sample data processing.
// Now we are ready for sample data processing
kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream);
bool done = false;
while (!done)
@ -702,7 +693,7 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
}
// Produce the compressed output
codestream.flush(layer_bytes,num_layer_specs);
codestream.flush(layer_bytes,nb_layers);
// Cleanup
delete tile;
@ -750,6 +741,207 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
}
}
/*****************************************************************************/
/* STATIC copy_block */
/*****************************************************************************/
static void copy_block(kdu_block *in, kdu_block *out)
{
if (in->K_max_prime != out->K_max_prime)
{
std::cout << "Cannot copy blocks belonging to subbands with different quantization parameters." << std::endl;
return;
}
if ((in->size.x != out->size.x) || (in->size.y != out->size.y))
{
std::cout << "Cannot copy code-blocks with different dimensions." << std::endl;
return;
}
out->missing_msbs = in->missing_msbs;
if (out->max_passes < (in->num_passes+2)) // Gives us enough to round up
out->set_max_passes(in->num_passes+2,false); // to the next whole bit-plane
out->num_passes = in->num_passes;
int num_bytes = 0;
for (int z=0; z < in->num_passes; z++)
{
num_bytes += (out->pass_lengths[z] = in->pass_lengths[z]);
out->pass_slopes[z] = in->pass_slopes[z];
}
// Just copy compressed code-bytes. Block transcoding not supported.
if (out->max_bytes < num_bytes)
out->set_max_bytes(num_bytes,false);
memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes);
}
/*****************************************************************************/
/* STATIC copy_tile */
/*****************************************************************************/
static void
copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
kdu_params *siz_in, kdu_params *siz_out, int skip_components,
int &num_blocks)
{
int num_components = tile_out.get_num_components();
int new_tpart=0, next_tpart = 1;
for (int c=0; c < num_components; c++)
{
kdu_tile_comp comp_in, comp_out;
comp_in = tile_in.access_component(c);
comp_out = tile_out.access_component(c);
int num_resolutions = comp_out.get_num_resolutions();
//std::cout << " Copying tile : num_resolutions = " << num_resolutions << std::endl;
for (int r=0; r < num_resolutions; r++)
{
kdu_resolution res_in; res_in = comp_in.access_resolution(r);
kdu_resolution res_out; res_out = comp_out.access_resolution(r);
int b, min_band;
int num_bands = res_in.get_valid_band_indices(min_band);
std::cout << " Copying tile : num_bands = " << num_bands << std::endl;
for (b=min_band; num_bands > 0; num_bands--, b++)
{
kdu_subband band_in; band_in = res_in.access_subband(b);
kdu_subband band_out; band_out = res_out.access_subband(b);
kdu_dims blocks_in; band_in.get_valid_blocks(blocks_in);
kdu_dims blocks_out; band_out.get_valid_blocks(blocks_out);
if ((blocks_in.size.x != blocks_out.size.x) ||
(blocks_in.size.y != blocks_out.size.y))
{
std::cout << "Transcoding operation cannot proceed: Code-block partitions for the input and output code-streams do not agree." << std::endl;
return;
}
kdu_coords idx;
//std::cout << " Copying tile : block indices, x = " << blocks_out.size.x << " and y = " << blocks_out.size.y << std::endl;
for (idx.y=0; idx.y < blocks_out.size.y; idx.y++)
{
for (idx.x=0; idx.x < blocks_out.size.x; idx.x++)
{
kdu_block *in =
band_in.open_block(idx+blocks_in.pos,&new_tpart);
for (; next_tpart <= new_tpart; next_tpart++)
siz_out->copy_from(siz_in,tnum_in,tnum_out,next_tpart,
skip_components);
kdu_block *out = band_out.open_block(idx+blocks_out.pos);
copy_block(in,out);
band_in.close_block(in);
band_out.close_block(out);
num_blocks++;
}
}
}
}
}
}
// Find the block boundary for each discard level in the input image.
// We parse the input blocks and copy them in a temporary output stream.
// For the moment, we do nothing more that parsing the raw list of blocks and outputing result.
void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
{
// We need the number of levels in that image before starting.
getMetadata(base);
for (int discard_level = 0; discard_level < mLevels; discard_level++)
{
//std::cout << "Parsing discard level = " << discard_level << std::endl;
// Create the input codestream object.
setupCodeStream(base, TRUE, MODE_FAST);
mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL);
mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true);
siz_params *siz_in = mCodeStreamp->access_siz();
// Create the output codestream object.
siz_params siz;
siz.copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false);
siz.set(Scomponents,0,0,mCodeStreamp->get_num_components());
U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents();
max_output_size = (max_output_size < 1000 ? 1000 : max_output_size);
U8 *output_buffer = new U8[max_output_size];
U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size
LLKDUMemTarget output(output_buffer, output_size, max_output_size);
kdu_codestream codestream_out;
codestream_out.create(&siz,&output);
//codestream_out.share_buffering(*mCodeStreamp);
siz_params *siz_out = codestream_out.access_siz();
siz_out->copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false);
codestream_out.access_siz()->finalize_all(-1);
// Set up rate control variables
kdu_long max_bytes = KDU_LONG_MAX;
kdu_params *cod = siz_out->access_cluster(COD_params);
int total_layers; cod->get(Clayers,0,0,total_layers);
kdu_long *layer_bytes = new kdu_long[total_layers];
int nel, non_empty_layers = 0;
// Now ready to perform the transfer of compressed data between streams
int flush_counter = INT_MAX;
kdu_dims tile_indices_in;
mCodeStreamp->get_valid_tiles(tile_indices_in);
kdu_dims tile_indices_out;
codestream_out.get_valid_tiles(tile_indices_out);
assert((tile_indices_in.size.x == tile_indices_out.size.x) &&
(tile_indices_in.size.y == tile_indices_out.size.y));
int num_blocks=0;
kdu_coords idx;
//std::cout << "Parsing tiles : x = " << tile_indices_out.size.x << " to y = " << tile_indices_out.size.y << std::endl;
for (idx.y=0; idx.y < tile_indices_out.size.y; idx.y++)
{
for (idx.x=0; idx.x < tile_indices_out.size.x; idx.x++)
{
kdu_tile tile_in = mCodeStreamp->open_tile(idx+tile_indices_in.pos);
int tnum_in = tile_in.get_tnum();
int tnum_out = idx.x + idx.y*tile_indices_out.size.x;
siz_out->copy_from(siz_in,tnum_in,tnum_out,0,0,discard_level,false,false,false);
siz_out->finalize_all(tnum_out);
// Note: do not open the output tile without first copying any tile-specific code-stream parameters
kdu_tile tile_out = codestream_out.open_tile(idx+tile_indices_out.pos);
assert(tnum_out == tile_out.get_tnum());
copy_tile(tile_in,tile_out,tnum_in,tnum_out,siz_in,siz_out,0,num_blocks);
tile_in.close();
tile_out.close();
flush_counter--;
if ((flush_counter <= 0) && codestream_out.ready_for_flush())
{
flush_counter = INT_MAX;
nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers);
non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers;
}
}
}
// Generate the output code-stream
if (codestream_out.ready_for_flush())
{
nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers);
non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers;
}
if (non_empty_layers > total_layers)
non_empty_layers = total_layers; // Can happen if a tile has more layers
// Print out stats
std::cout << "Code stream parsing for discard level = " << discard_level << std::endl;
std::cout << " Total compressed memory in = " << mCodeStreamp->get_compressed_data_memory() << " bytes" << std::endl;
std::cout << " Total compressed memory out = " << codestream_out.get_compressed_data_memory() << " bytes" << std::endl;
//std::cout << " Output contains " << total_layers << " quality layers" << std::endl;
std::cout << " Transferred " << num_blocks << " code-blocks from in to out" << std::endl;
//std::cout << " Read " << mCodeStreamp->get_num_tparts() << " tile-part(s) from a total of " << (int) tile_indices_in.area() << " tile(s)" << std::endl;
std::cout << " Total bytes read = " << mCodeStreamp->get_total_bytes() << std::endl;
//std::cout << " Wrote " << codestream_out.get_num_tparts() << " tile-part(s) in a total of " << (int) tile_indices_out.area() << " tile(s)" << std::endl;
std::cout << " Total bytes written = " << codestream_out.get_total_bytes() << std::endl;
std::cout << "-------------" << std::endl;
// Clean-up
cleanupCodeStream();
codestream_out.destroy();
delete[] output_buffer;
}
return;
}
void set_default_colour_weights(kdu_params *siz)
{
kdu_params *cod = siz->access_cluster(COD_params);

View File

@ -60,6 +60,7 @@ protected:
BOOL reversible=FALSE);
/*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
/*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
void findDiscardLevelsBoundaries(LLImageJ2C &base);
private:
BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);

View File

@ -29,6 +29,7 @@
// Class to test
#include "llimagej2ckdu.h"
#include "llkdumem.h"
#include "kdu_block_coding.h"
// Tut header
#include "lltut.h"
@ -86,7 +87,7 @@ void LLImageFormatted::resetLastError() { }
void LLImageFormatted::sanityCheck() { }
void LLImageFormatted::setLastError(const std::string& , const std::string& ) { }
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C) { }
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), mRate(DEFAULT_COMPRESSION_RATE) { }
LLImageJ2C::~LLImageJ2C() { }
S32 LLImageJ2C::calcDataSize(S32 ) { return 0; }
S32 LLImageJ2C::calcDiscardLevelBytes(S32 ) { return 0; }
@ -107,16 +108,25 @@ bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; }
// Stub Kakadu Library calls
kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }
kdu_block_encoder::kdu_block_encoder() { }
kdu_block_decoder::kdu_block_decoder() { }
void kdu_block::set_max_passes(int , bool ) { }
void kdu_block::set_max_bytes(int , bool ) { }
void kdu_block::set_max_samples(int ) { }
void kdu_tile::close(kdu_thread_env* ) { }
int kdu_tile::get_num_components() { return 0; }
bool kdu_tile::get_ycc() { return false; }
void kdu_tile::set_components_of_interest(int , const int* ) { }
int kdu_tile::get_tnum() { return 0; }
kdu_resolution kdu_tile_comp::access_resolution() { kdu_resolution a; return a; }
kdu_resolution kdu_tile_comp::access_resolution(int ) { kdu_resolution a; return a; }
int kdu_tile_comp::get_bit_depth(bool ) { return 8; }
bool kdu_tile_comp::get_reversible() { return false; }
int kdu_tile_comp::get_num_resolutions() { return 1; }
kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; }
void kdu_resolution::get_dims(kdu_dims& ) { }
int kdu_resolution::which() { return 0; }
int kdu_resolution::get_valid_band_indices(int &) { return 1; }
kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
@ -124,6 +134,7 @@ kdu_params::~kdu_params() { }
void kdu_params::set(const char* , int , int , bool ) { }
void kdu_params::set(const char* , int , int , int ) { }
void kdu_params::finalize_all(bool ) { }
void kdu_params::finalize_all(int, bool ) { }
void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { }
bool kdu_params::parse_string(const char*) { return false; }
bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; }
@ -135,6 +146,7 @@ void kdu_codestream::set_fast() { }
void kdu_codestream::set_fussy() { }
void kdu_codestream::get_dims(int, kdu_dims&, bool ) { }
int kdu_codestream::get_min_dwt_levels() { return 5; }
int kdu_codestream::get_max_tile_layers() { return 1; }
void kdu_codestream::change_appearance(bool, bool, bool) { }
void kdu_codestream::get_tile_dims(kdu_coords, int, kdu_dims&, bool ) { }
void kdu_codestream::destroy() { }
@ -148,9 +160,18 @@ void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
void kdu_codestream::flush(kdu_long *, int , kdu_uint16 *, bool, bool, double, kdu_thread_env*) { }
void kdu_codestream::set_resilient(bool ) { }
int kdu_codestream::get_num_components(bool ) { return 0; }
kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; }
kdu_long kdu_codestream::get_compressed_data_memory(bool ) {return 0; }
void kdu_codestream::share_buffering(kdu_codestream ) { }
int kdu_codestream::get_num_tparts() { return 0; }
int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; }
bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; }
siz_params* kdu_codestream::access_siz() { return NULL; }
kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; }
void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }
void kdu_subband::get_valid_blocks(kdu_dims &indices) { }
kdu_block* kdu_subband::open_block(kdu_coords, int*, kdu_thread_env*) { return NULL; }
bool kdu_codestream_comment::put_text(const char*) { return false; }
void kdu_customize_warnings(kdu_message*) { }
void kdu_customize_errors(kdu_message*) { }

View File

@ -1506,7 +1506,8 @@ void LLCurl::cleanupClass()
delete sHandleMutexp ;
sHandleMutexp = NULL ;
llassert(Easy::sActiveHandles.empty());
// removed as per https://jira.secondlife.com/browse/SH-3115
//llassert(Easy::sActiveHandles.empty());
}
//static

0
indra/llprimitive/llprimitive.cpp Normal file → Executable file
View File

166
indra/llrender/llimagegl.cpp Normal file → Executable file
View File

@ -43,7 +43,6 @@
const F32 MIN_TEXTURE_LIFETIME = 10.f;
//statics
LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 };
U32 LLImageGL::sUniqueCount = 0;
U32 LLImageGL::sBindCount = 0;
@ -65,19 +64,10 @@ std::set<LLImageGL*> LLImageGL::sImageList;
//****************************************************************************************************
//-----------------------
//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::sHighlightTexturep = NULL;
S32 LLImageGL::sMaxCatagories = 1 ;
S32 LLImageGL::sMaxCategories = 1 ;
std::vector<S32> LLImageGL::sTextureMemByCategory;
std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
//------------------------
//****************************************************************************************************
//End for texture auditing use only
@ -175,49 +165,11 @@ BOOL is_little_endian()
//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
@ -285,31 +237,11 @@ void LLImageGL::updateStats(F32 current_time)
sLastFrameTime = current_time;
sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
sCurBoundTextureMemory = 0;
if(gAuditTexture)
{
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 ;
}
}
}
//static
S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category)
{
if(gAuditTexture && ncomponents > 0 && category > -1)
{
sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
sTextureCurMemByCategoryBound[category] += mem ;
}
LLImageGL::sCurBoundTextureMemory += mem ;
return LLImageGL::sCurBoundTextureMemory;
}
@ -1284,7 +1216,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
return TRUE ;
}
setCategory(category) ;
setCategory(category);
const U8* rawdata = imageraw->getData();
return createGLTexture(discard_level, rawdata, FALSE, usename);
}
@ -1362,11 +1294,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
{
sGlobalTextureMemoryInBytes -= mTextureMemory;
if(gAuditTexture)
{
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
LLImageGL::deleteTextures(1, &old_name);
stop_glerror();
@ -1376,10 +1303,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
sGlobalTextureMemoryInBytes += mTextureMemory;
mTexelsInGLTexture = getWidth() * getHeight() ;
if(gAuditTexture)
{
incTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
return TRUE;
@ -1536,22 +1459,29 @@ void LLImageGL::destroyGLTexture()
{
if(mTextureMemory)
{
if(gAuditTexture)
{
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
}
sGlobalTextureMemoryInBytes -= mTextureMemory;
mTextureMemory = 0;
}
LLImageGL::deleteTextures(1, &mTexName);
mTexName = 0;
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
mTexName = 0;
mGLTextureCreated = FALSE ;
}
}
}
//force to invalidate the gl texture, most likely a sculpty texture
void LLImageGL::forceToInvalidateGLTexture()
{
if (mTexName != 0)
{
destroyGLTexture();
}
else
{
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
}
}
//----------------------------------------------------------------------------
@ -1969,70 +1899,6 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
return res;
}
void LLImageGL::setCategory(S32 category)
{
#if 0 //turn this off temporarily because it is not in use now.
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 ;
}
}
#endif
}
//for debug use
//val is a "power of two" number
S32 LLImageGL::getTextureCounterIndex(U32 val)
{
//index range is [0, MAX_TEXTURE_LOG_SIZE].
if(val < 2)
{
return 0 ;
}
else if(val >= (1 << MAX_TEXTURE_LOG_SIZE))
{
return MAX_TEXTURE_LOG_SIZE ;
}
else
{
S32 ret = 0 ;
while(val >>= 1)
{
++ret;
}
return ret ;
}
}
//static
void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category)
{
sTextureLoadedCounter[getTextureCounterIndex(val)]++ ;
sTextureMemByCategory[category] += (S32)val * ncomponents ;
}
//static
void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category)
{
sTextureLoadedCounter[getTextureCounterIndex(val)]-- ;
sTextureMemByCategory[category] += (S32)val * ncomponents ;
}
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
{
sCurTexSizeBar = index ;

37
indra/llrender/llimagegl.h Normal file → Executable file
View File

@ -102,8 +102,8 @@ 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 to_create = TRUE,
S32 category = sMaxCatagories - 1);
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
S32 category = sMaxCategories-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);
@ -114,6 +114,7 @@ public:
// 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();
void forceToInvalidateGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
void setComponents(S8 ncomponents) { mComponents = ncomponents; }
@ -234,8 +235,6 @@ public:
static S32 sCount;
static F32 sLastFrameTime;
static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID
// Global memory statistics
static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem
@ -257,9 +256,10 @@ public:
public:
static void initClass(S32 num_catagories) ;
static void cleanupClass() ;
private:
static S32 sMaxCatagories ;
private:
static S32 sMaxCategories;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.
static BOOL sAllowReadBackRaw ;
@ -269,39 +269,22 @@ private:
//****************************************************************************************************
private:
S32 mCategory ;
public:
void setCategory(S32 category) ;
S32 getCategory()const {return mCategory ;}
public:
void setCategory(S32 category) {mCategory = 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

@ -246,14 +246,6 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
}
//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();

18
indra/llui/llcontainerview.cpp Normal file → Executable file
View File

@ -196,24 +196,24 @@ void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent)
if (total_height < height)
total_height = height;
LLRect my_rect = getRect();
if (followsTop())
{
// HACK: casting away const. Should use setRect or some helper function instead.
const_cast<LLRect&>(getRect()).mBottom = getRect().mTop - total_height;
my_rect.mBottom = my_rect.mTop - total_height;
}
else
{
// HACK: casting away const. Should use setRect or some helper function instead.
const_cast<LLRect&>(getRect()).mTop = getRect().mBottom + total_height;
my_rect.mTop = my_rect.mBottom + total_height;
}
// HACK: casting away const. Should use setRect or some helper function instead.
const_cast<LLRect&>(getRect()).mRight = getRect().mLeft + width;
my_rect.mRight = my_rect.mLeft + width;
setRect(my_rect);
top = total_height;
if (mShowLabel)
{
top -= 20;
}
{
top -= 20;
}
bottom = top;

View File

@ -272,7 +272,7 @@ LLRect LLStatBar::getRequiredRect()
{
if (mDisplayHistory)
{
rect.mTop = 67;
rect.mTop = 35 + mStatp->getNumBins();
}
else
{

2
indra/newview/CMakeLists.txt Normal file → Executable file
View File

@ -237,6 +237,7 @@ set(viewer_SOURCE_FILES
llfloatertelehub.cpp
llfloatertestinspectors.cpp
llfloatertestlistview.cpp
llfloatertexturefetchdebugger.cpp
llfloatertools.cpp
llfloatertopobjects.cpp
llfloatertos.cpp
@ -793,6 +794,7 @@ set(viewer_HEADER_FILES
llfloatertelehub.h
llfloatertestinspectors.h
llfloatertestlistview.h
llfloatertexturefetchdebugger.h
llfloatertools.h
llfloatertopobjects.h
llfloatertos.h

8
indra/newview/app_settings/logcontrol.xml Normal file → Executable file
View File

@ -20,7 +20,7 @@
<key>tags</key>
<array>
<string>AppInit</string>
<string>Capabilities</string>
<string>Capabilities</string>
<string>SystemInfo</string>
<string>TextureCache</string>
<string>AppCache</string>
@ -42,8 +42,10 @@
</array>
<key>tags</key>
<array>
<!-- sample entry for debugging a specific item -->
<!-- <string>Voice</string> -->
<!-- sample entry for debugging specific items
<string>Avatar</string>
<string>Voice</string>
-->
</array>
</map>
</array>

90
indra/newview/app_settings/settings.xml Normal file → Executable file
View File

@ -335,17 +335,6 @@
<key>Value</key>
<integer>1</integer>
</map>
<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>
@ -1936,7 +1925,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>1</integer>
</map>
<key>DebugBeaconLineWidth</key>
<map>
@ -7183,6 +7172,17 @@
<key>Value</key>
<integer>-1</integer>
</map>
<key>QAModeMetrics</key>
<map>
<key>Comment</key>
<string>"Enables QA features (logging, faster cycling) for metrics collector"</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>QuietSnapshotsToDisk</key>
<map>
<key>Comment</key>
@ -10664,6 +10664,39 @@
<key>Value</key>
<real>20.0</real>
</map>
<key>TexelPixelRatio</key>
<map>
<key>Comment</key>
<string>texel pixel ratio = texel / pixel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>TextureCameraMotionThreshold</key>
<map>
<key>Comment</key>
<string>If the overall motion is lower than this value, textures will be loaded faster</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.2</real>
</map>
<key>TextureCameraMotionBoost</key>
<map>
<key>Comment</key>
<string>Progressive discard level decrement when the camera is still</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>3</integer>
</map>
<key>TextureDecodeDisabled</key>
<map>
<key>Comment</key>
@ -10697,6 +10730,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureFetchDebuggerEnabled</key>
<map>
<key>Comment</key>
<string>Enable the texture fetching debugger if set</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>
@ -10719,6 +10763,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureNewByteRange</key>
<map>
<key>Comment</key>
<string>Use the new more accurate byte range computation for j2c discard levels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>TexturePickerShowFolders</key>
<map>
<key>Comment</key>
@ -10741,6 +10796,17 @@
<key>Value</key>
<integer>2</integer>
</map>
<key>TextureReverseByteRange</key>
<map>
<key>Comment</key>
<string>Minimal percent of the optimal byte range allowed to render a given discard level</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>50</integer>
</map>
<key>ThrottleBandwidthKBPS</key>
<map>
<key>Comment</key>

View File

@ -3253,6 +3253,10 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
{
gAgentQueryManager.mNumPendingQueries--;
if (gAgentQueryManager.mNumPendingQueries == 0)
{
selfStopPhase("fetch_texture_cache_entries");
}
if (!isAgentAvatarValid() || gAgentAvatarp->isDead())
{
@ -3302,13 +3306,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
else
{
// no cache of this bake. request upload.
gAgentAvatarp->requestLayerSetUpload(baked_index);
gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE);
}
}
}
}
}
llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
@ -3775,7 +3778,15 @@ void LLAgent::sendAgentSetAppearance()
return;
}
llinfos << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << llendl;
if (!gAgentWearables.changeInProgress())
{
// Change is fully resolved, can close some open phases.
gAgentAvatarp->getPhases().stopPhase("process_initial_wearables_update");
gAgentAvatarp->getPhases().stopPhase("wear_inventory_category");
}
gAgentAvatarp->sendAppearanceChangeMetrics();
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL;
//dumpAvatarTEs( "sendAgentSetAppearance()" );
LLMessageSystem* msg = gMessageSystem;
@ -3822,14 +3833,14 @@ void LLAgent::sendAgentSetAppearance()
// only update cache entries if we have all our baked textures
if (textures_current)
{
llinfos << "TAT: Sending cached texture data" << llendl;
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
BOOL generate_valid_hash = TRUE;
if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index))
{
generate_valid_hash = FALSE;
llinfos << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << llendl;
LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL;
}
const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);

View File

@ -126,6 +126,17 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
"[\"obj_uuid\"]: id of object to look at, use this or [\"position\"] to indicate the target\n"
"[\"position\"]: region position {x, y, z} where to find closest object or avatar to look at",
&LLAgentListener::lookAt);
add("getGroups",
"Send information about the agent's groups on [\"reply\"]:\n"
"[\"groups\"]: array of group information\n"
"[\"id\"]: group id\n"
"[\"name\"]: group name\n"
"[\"insignia\"]: group insignia texture id\n"
"[\"notices\"]: boolean indicating if this user accepts notices from this group\n"
"[\"display\"]: boolean indicating if this group is listed in the user's profile\n"
"[\"contrib\"]: user's land contribution to this group\n",
&LLAgentListener::getGroups,
LLSDMap("reply", LLSD()));
}
void LLAgentListener::requestTeleport(LLSD const & event_data) const

21
indra/newview/llagentwearables.cpp Normal file → Executable file
View File

@ -955,6 +955,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
if (isAgentAvatarValid())
{
//gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading.
gAgentAvatarp->getPhases().startPhase("process_initial_wearables_update");
gAgentAvatarp->outputRezTiming("Received initial wearables update");
}
@ -1448,7 +1450,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
gAgentAvatarp->updateVisualParams();
gAgentAvatarp->invalidateAll();
// If we have not yet declouded, we may want to use
// baked texture UUIDs sent from the first objectUpdate message
// don't overwrite these. If we have already declouded, we've saved
// these ids as the last known good textures and can invalidate without
// re-clouding.
if (!gAgentAvatarp->getIsCloud())
{
gAgentAvatarp->invalidateAll();
}
}
// Start rendering & update the server
@ -1630,10 +1641,11 @@ void LLAgentWearables::queryWearableCache()
{
if (isAgentAvatarValid())
{
selfStartPhase("fetch_texture_cache_entries");
gAgentAvatarp->outputRezTiming("Fetching textures from cache");
}
llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL;
gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
gAgentQueryManager.mNumPendingQueries++;
gAgentQueryManager.mWearablesCacheQueryID++;
@ -2081,6 +2093,11 @@ boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_
return mLoadedSignal.connect(cb);
}
bool LLAgentWearables::changeInProgress() const
{
return mCOFChangeInProgress;
}
void LLAgentWearables::notifyLoadingStarted()
{
mCOFChangeInProgress = true;

1
indra/newview/llagentwearables.h Normal file → Executable file
View File

@ -233,6 +233,7 @@ public:
typedef boost::signals2::signal<void()> loaded_signal_t;
boost::signals2::connection addLoadedCallback(loaded_callback_t cb);
bool changeInProgress() const;
void notifyLoadingStarted();
void notifyLoadingFinished();

View File

@ -89,6 +89,7 @@ LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
{
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().startPhase("initial_wearables_fetch");
gAgentAvatarp->outputRezTiming("Initial wearables fetch started");
}
}
@ -107,6 +108,7 @@ void LLInitialWearablesFetch::done()
doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().stopPhase("initial_wearables_fetch");
gAgentAvatarp->outputRezTiming("Initial wearables fetch done");
}
}

163
indra/newview/llappearancemgr.cpp Normal file → Executable file
View File

@ -50,6 +50,11 @@
#include "llviewerregion.h"
#include "llwearablelist.h"
std::string self_av_string()
{
return gAgentAvatarp->avString();
}
// RAII thingy to guarantee that a variable gets reset when the Setter
// goes out of scope. More general utility would be handy - TODO:
// check boost.
@ -156,6 +161,10 @@ public:
{
mCatID = cat_id;
mAppend = append;
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
selfStartPhase("wear_inventory_category_callback");
}
void fire(const LLUUID& item_id)
{
@ -167,13 +176,16 @@ public:
* after the last item has fired the event and dereferenced it -- if all
* the events actually fire!
*/
LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL;
}
protected:
~LLWearInventoryCategoryCallback()
{
llinfos << "done all inventory callbacks" << llendl;
LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL;
selfStopPhase("wear_inventory_category_callback");
// Is the destructor called by ordinary dereference, or because the app's shutting down?
// If the inventory callback manager goes away, we're shutting down, no longer want the callback.
if( LLInventoryCallbackManager::is_instantiated() )
@ -182,7 +194,7 @@ protected:
}
else
{
llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
}
}
@ -212,11 +224,14 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit
mFireCount(0),
mUpdateBaseOrder(update_base_outfit_ordering)
{
selfStartPhase("update_appearance_on_destroy");
}
LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
{
llinfos << "done update appearance on destroy" << llendl;
LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL;
selfStopPhase("update_appearance_on_destroy");
if (!LLApp::isExiting())
{
@ -229,7 +244,7 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
#endif
mFireCount++;
}
@ -339,11 +354,16 @@ LLWearableHoldingPattern::LLWearableHoldingPattern():
}
sActiveHoldingPatterns.insert(this);
selfStartPhase("holding_pattern");
}
LLWearableHoldingPattern::~LLWearableHoldingPattern()
{
sActiveHoldingPatterns.erase(this);
if (isMostRecent())
{
selfStopPhase("holding_pattern");
}
}
bool LLWearableHoldingPattern::isMostRecent()
@ -390,9 +410,10 @@ void LLWearableHoldingPattern::checkMissingWearables()
{
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway why don't we actually skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0);
std::vector<S32> requested_by_type(LLWearableType::WT_COUNT,0);
for (found_list_t::iterator it = getFoundList().begin(); it != getFoundList().end(); ++it)
@ -408,7 +429,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
{
if (requested_by_type[type] > found_by_type[type])
{
llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
llwarns << self_av_string() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
}
if (found_by_type[type] > 0)
continue;
@ -425,11 +446,13 @@ void LLWearableHoldingPattern::checkMissingWearables()
mTypesToRecover.insert(type);
mTypesToLink.insert(type);
recoverMissingWearable((LLWearableType::EType)type);
llwarns << "need to replace " << type << llendl;
llwarns << self_av_string() << "need to replace " << type << llendl;
}
}
resetTime(60.0F);
selfStartPhase("get_missing_wearables");
if (!pollMissingWearables())
{
doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollMissingWearables,this));
@ -445,13 +468,14 @@ void LLWearableHoldingPattern::onAllComplete()
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway need to skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
// Activate all gestures in this folder
if (mGestItems.count() > 0)
{
llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Activating " << mGestItems.count() << " gestures" << LL_ENDL;
LLGestureMgr::instance().activateGestures(mGestItems);
@ -468,13 +492,13 @@ void LLWearableHoldingPattern::onAllComplete()
}
// Update wearables.
llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
LLAppearanceMgr::instance().updateAgentWearables(this, false);
// Update attachments to match those requested.
if (isAgentAvatarValid())
{
llinfos << "Updating " << mObjItems.count() << " attachments" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.count() << " attachments" << LL_ENDL;
LLAgentWearables::userUpdateAttachments(mObjItems);
}
@ -492,9 +516,12 @@ void LLWearableHoldingPattern::onAllComplete()
void LLWearableHoldingPattern::onFetchCompletion()
{
selfStopPhase("get_wearables");
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
checkMissingWearables();
@ -505,7 +532,8 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
{
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
bool completed = isFetchCompleted();
@ -514,14 +542,14 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
if (done)
{
llinfos << "polling, done status: " << completed << " timed out " << timed_out
<< " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out
<< " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL;
mFired = true;
if (timed_out)
{
llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
llwarns << self_av_string() << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
}
onFetchCompletion();
@ -543,6 +571,7 @@ public:
if (!mHolder->isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
}
llinfos << "Recovered item link for type " << mType << llendl;
@ -569,12 +598,12 @@ public:
}
else
{
llwarns << "inventory item not found for recovered wearable" << llendl;
llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl;
}
}
else
{
llwarns << "inventory link not found for recovered wearable" << llendl;
llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl;
}
}
private:
@ -596,10 +625,11 @@ public:
{
if (!mHolder->isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
llinfos << "Recovered item for type " << mType << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << mType << LL_ENDL;
LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
mWearable->setItemID(item_id);
LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder);
@ -626,7 +656,8 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
{
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
// Try to recover by replacing missing wearable with a new one.
@ -665,7 +696,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
{
// Wearable link that was never resolved; remove links to it from COF
llinfos << "removing link for unresolved item " << data.mItemID.asString() << llendl;
LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false);
}
}
@ -675,7 +706,8 @@ bool LLWearableHoldingPattern::pollMissingWearables()
{
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
// runway skip here?
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
bool timed_out = isTimedOut();
@ -684,15 +716,17 @@ bool LLWearableHoldingPattern::pollMissingWearables()
if (!done)
{
llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size()
LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size()
<< " links " << mTypesToLink.size()
<< " wearables, timed out " << timed_out
<< " elapsed " << mWaitTime.getElapsedTimeF32()
<< " done " << done << llendl;
<< " done " << done << LL_ENDL;
}
if (done)
{
selfStopPhase("get_missing_wearables");
gAgentAvatarp->debugWearablesLoaded();
// BAP - if we don't call clearCOFLinksForMissingWearables()
@ -722,14 +756,14 @@ void LLWearableHoldingPattern::handleLateArrivals()
}
if (!isMostRecent())
{
llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl;
llwarns << self_av_string() << "Late arrivals not handled - outfit change no longer valid" << llendl;
}
if (!mIsAllComplete)
{
llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
llwarns << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
}
llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl;
LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
// Update mFoundList using late-arriving wearables.
std::set<LLWearableType::EType> replaced_types;
@ -805,19 +839,19 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable)
{
if (!isMostRecent())
{
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
}
mResolved += 1; // just counting callbacks, not successes.
llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
if (!wearable)
{
llwarns << "no wearable found" << llendl;
llwarns << self_av_string() << "no wearable found" << llendl;
}
if (mFired)
{
llwarns << "called after holder fired" << llendl;
llwarns << self_av_string() << "called after holder fired" << llendl;
if (wearable)
{
mLateArrivals.insert(wearable);
@ -843,7 +877,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable)
// Failing this means inventory or asset server are corrupted in a way we don't handle.
if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType))
{
llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
llwarns << self_av_string() << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
break;
}
@ -1391,8 +1425,8 @@ void LLAppearanceMgr::filterWearableItems(
// Create links to all listed items.
void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
LLInventoryModel::item_array_t& items,
LLPointer<LLInventoryCallback> cb)
LLInventoryModel::item_array_t& items,
LLPointer<LLInventoryCallback> cb)
{
for (S32 i=0; i<items.count(); i++)
{
@ -1408,7 +1442,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL;
#endif
}
}
@ -1416,7 +1450,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
{
LLViewerInventoryCategory *pcat = gInventory.getCategory(category);
llinfos << "starting, cat " << (pcat ? pcat->getName() : "[UNKNOWN]") << llendl;
LL_INFOS("Avatar") << self_av_string() << "starting, cat '" << (pcat ? pcat->getName() : "[UNKNOWN]") << "'" << LL_ENDL;
const LLUUID cof = getCOF();
@ -1478,26 +1512,26 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
gInventory.notifyObservers();
// Create links to new COF contents.
llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL;
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append);
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Linking body items" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL;
#endif
linkAll(cof, body_items, link_waiter);
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Linking wear items" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL;
#endif
linkAll(cof, wear_items, link_waiter);
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Linking obj items" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL;
#endif
linkAll(cof, obj_items, link_waiter);
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Linking gesture items" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL;
#endif
linkAll(cof, gest_items, link_waiter);
@ -1506,7 +1540,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
{
createBaseOutfitLink(category, link_waiter);
}
llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
}
void LLAppearanceMgr::updatePanelOutfitName(const std::string& name)
@ -1663,7 +1697,7 @@ void LLAppearanceMgr::enforceItemRestrictions()
++it)
{
LLViewerInventoryItem *item = *it;
llinfos << "purging duplicate or excess item " << item->getName() << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL;
gInventory.purgeObject(item->getUUID());
}
gInventory.notifyObservers();
@ -1678,9 +1712,11 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
return;
}
LLVOAvatar::ScopedPhaseSetter(gAgentAvatarp,"update_appearance_from_cof");
BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
llinfos << "starting" << llendl;
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
//checking integrity of the COF in terms of ordering of wearables,
//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
@ -1772,12 +1808,14 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
}
}
selfStartPhase("get_wearables");
for (LLWearableHoldingPattern::found_list_t::iterator it = holder->getFoundList().begin();
it != holder->getFoundList().end(); ++it)
{
LLFoundData& found = *it;
lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl;
lldebugs << self_av_string() << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl;
// Fetch the wearables about to be worn.
LLWearableList::instance().getAsset(found.mAssetID,
@ -1849,11 +1887,15 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
{
if(!category) return;
selfClearPhases();
selfStartPhase("wear_inventory_category");
gAgentWearables.notifyLoadingStarted();
llinfos << "wearInventoryCategory( " << category->getName()
<< " )" << llendl;
LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName()
<< " )" << LL_ENDL;
selfStartPhase("wear_inventory_category_fetch");
callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
&LLAppearanceMgr::instance(),
category->getUUID(), copy, append));
@ -1861,7 +1903,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
{
llinfos << "starting" << llendl;
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
selfStopPhase("wear_inventory_category_fetch");
// We now have an outfit ready to be copied to agent inventory. Do
// it, and wear that outfit normally.
@ -1944,8 +1988,8 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
// wearables being dirty.
if(!category) return;
llinfos << "wearInventoryCategoryOnAvatar( " << category->getName()
<< " )" << llendl;
LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName()
<< "'" << LL_ENDL;
if (gAgentCamera.cameraCustomizeAvatar())
{
@ -1958,7 +2002,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
void LLAppearanceMgr::wearOutfitByName(const std::string& name)
{
llinfos << "Wearing category " << name << llendl;
LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL;
//inc_busy_count();
LLInventoryModel::cat_array_t cat_array;
@ -2281,7 +2325,7 @@ const std::string OTHER_GESTURES_FOLDER = "Other Gestures";
void LLAppearanceMgr::copyLibraryGestures()
{
llinfos << "Copying library gestures" << llendl;
LL_INFOS("Avatar") << self_av_string() << "Copying library gestures" << LL_ENDL;
// Copy gestures
LLUUID lib_gesture_cat_id =
@ -2337,11 +2381,11 @@ void LLAppearanceMgr::copyLibraryGestures()
LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name);
if (cat_id.isNull())
{
llwarns << "failed to find gesture folder for " << folder_name << llendl;
llwarns << self_av_string() << "failed to find gesture folder for " << folder_name << llendl;
}
else
{
llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << LL_ENDL;
callAfterCategoryFetch(cat_id,
boost::bind(&LLAppearanceMgr::shallowCopyCategory,
&LLAppearanceMgr::instance(),
@ -2355,7 +2399,7 @@ void LLAppearanceMgr::autopopulateOutfits()
// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
// then auto-populate outfits from the library into the My Outfits folder.
llinfos << "avatar fully visible" << llendl;
LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL;
static bool check_populate_my_outfits = true;
if (check_populate_my_outfits &&
@ -2731,7 +2775,7 @@ void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg)
}
void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
const std::string& msg)
const std::string& msg)
{
for (S32 i=0; i<items.count(); i++)
{
@ -2742,9 +2786,8 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
{
asset_id = linked_item->getAssetUUID();
}
llinfos << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << llendl;
LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL;
}
llinfos << llendl;
}
LLAppearanceMgr::LLAppearanceMgr():

View File

@ -93,6 +93,7 @@
#include "llsecondlifeurls.h"
#include "llupdaterservice.h"
#include "llcallfloater.h"
#include "llfloatertexturefetchdebugger.h"
// Linden library includes
#include "llavatarnamecache.h"
@ -560,7 +561,6 @@ 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");
}
class LLFastTimerLogThread : public LLThread
@ -731,12 +731,12 @@ bool LLAppViewer::init()
{
// Viewer metrics initialization
static LLCachedControl<bool> metrics_submode(gSavedSettings,
"QAModeMetrics",
false,
"Enables QA features (logging, faster cycling) for metrics collector");
//static LLCachedControl<bool> metrics_submode(gSavedSettings,
// "QAModeMetrics",
// false,
// "Enables QA features (logging, faster cycling) for metrics collector");
if (metrics_submode)
if (gSavedSettings.getBOOL("QAModeMetrics"))
{
app_metrics_qa_mode = true;
app_metrics_interval = METRICS_INTERVAL_QA;
@ -1219,7 +1219,7 @@ bool LLAppViewer::mainLoop()
if(mem_leak_instance)
{
mem_leak_instance->idle() ;
}
}
// canonical per-frame event
mainloop.post(newFrame);
@ -1340,13 +1340,11 @@ bool LLAppViewer::mainLoop()
ms_sleep(500);
}
static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds
const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second
idleTimer.reset();
bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
S32 total_work_pending = 0;
S32 total_io_pending = 0;
while(!is_slow)//do not unpause threads if the frame rates are very low.
while(1)
{
S32 work_pending = 0;
S32 io_pending = 0;
@ -1406,6 +1404,17 @@ bool LLAppViewer::mainLoop()
LLLFSThread::sLocal->pause();
}
//texture fetching debugger
if(LLTextureFetchDebugger::isEnabled())
{
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
if(tex_fetch_debugger_instance)
{
tex_fetch_debugger_instance->idle() ;
}
}
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
{
@ -1951,7 +1960,7 @@ bool LLAppViewer::initThreads()
static const bool enable_threads = true;
#endif
LLImage::initClass();
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false);
@ -4201,6 +4210,7 @@ void LLAppViewer::idle()
// The 5-second interval is nice for this purpose. If the object debug
// bit moves or is disabled, please give this a suitable home.
LLViewerAssetStatsFF::record_fps_main(gFPSClamped);
LLViewerAssetStatsFF::record_avatar_stats();
}
}
@ -4248,7 +4258,8 @@ void LLAppViewer::idle()
static LLTimer report_interval;
// *TODO: Add configuration controls for this
if (report_interval.getElapsedTimeF32() >= app_metrics_interval)
F32 seconds = report_interval.getElapsedTimeF32();
if (seconds >= app_metrics_interval)
{
metricsSend(! gDisconnected);
report_interval.reset();

View File

@ -33,6 +33,7 @@
#include "llagentpicksinfo.h"
#include "lldateutil.h"
#include "llviewergenericmessage.h"
#include "llstartup.h"
// Linden library includes
#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
@ -113,6 +114,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
{
// this is the startup state when send_complete_agent_movement() message is sent.
// Before this, the AvatarPropertiesRequest message
// won't work so don't bother trying
if (LLStartUp::getStartupState() <= STATE_AGENT_SEND)
{
return;
}
if (isPendingRequest(avatar_id, APT_PROPERTIES))
{
// waiting for a response, don't re-request

View File

@ -68,8 +68,6 @@ LLDebugView::~LLDebugView()
gDebugView = NULL;
gTextureView = NULL;
gSceneView = NULL;
gTextureSizeView = NULL;
gTextureCategoryView = NULL;
}
void LLDebugView::init()
@ -117,35 +115,11 @@ void LLDebugView::init()
LLTextureView::Params tvp;
tvp.name("gTextureView");
tvp.rect(r);
tvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
tvp.follows.flags(FOLLOWS_TOP|FOLLOWS_LEFT);
tvp.visible(false);
gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
//gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE);
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);
}
}
void LLDebugView::draw()

View File

@ -0,0 +1,390 @@
/**
* @file llfloatertexturefetchdebugger.cpp
* @brief LLFloaterTextureFetchDebugger class definition
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloatertexturefetchdebugger.h"
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llspinctrl.h"
#include "llresmgr.h"
#include "llmath.h"
#include "llviewerwindow.h"
#include "llappviewer.h"
#include "lltexturefetch.h"
#include "llviewercontrol.h"
LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
: LLFloater(key),
mDebugger(NULL)
{
setTitle("Texture Fetching Debugger Floater");
mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad", boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.Decode", boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture", boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this));
mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this));
}
//----------------------------------------------
BOOL LLFloaterTextureFetchDebugger::postBuild(void)
{
mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger();
//set states for buttons
mButtonStateMap["start_btn"] = true;
mButtonStateMap["close_btn"] = true;
mButtonStateMap["clear_btn"] = true;
mButtonStateMap["cacheread_btn"] = false;
mButtonStateMap["cachewrite_btn"] = false;
mButtonStateMap["http_btn"] = false;
mButtonStateMap["decode_btn"] = false;
mButtonStateMap["gl_btn"] = false;
mButtonStateMap["refetchviscache_btn"] = true;
mButtonStateMap["refetchvishttp_btn"] = true;
updateButtons();
getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio"));
return TRUE ;
}
LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger()
{
//stop everything
mDebugger->stopDebug();
}
void LLFloaterTextureFetchDebugger::updateButtons()
{
for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter)
{
if(iter->second)
{
childEnable(iter->first.c_str());
}
else
{
childDisable(iter->first.c_str());
}
}
}
void LLFloaterTextureFetchDebugger::disableButtons()
{
childDisable("start_btn");
childDisable("clear_btn");
childDisable("cacheread_btn");
childDisable("cachewrite_btn");
childDisable("http_btn");
childDisable("decode_btn");
childDisable("gl_btn");
childDisable("refetchviscache_btn");
childDisable("refetchvishttp_btn");
}
void LLFloaterTextureFetchDebugger::idle()
{
LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();
if(mDebugger->update())
{
switch(state)
{
case LLTextureFetchDebugger::IDLE:
break;
case LLTextureFetchDebugger::READ_CACHE:
mButtonStateMap["cachewrite_btn"] = true;
mButtonStateMap["decode_btn"] = true;
updateButtons();
break;
case LLTextureFetchDebugger::WRITE_CACHE:
updateButtons();
break;
case LLTextureFetchDebugger::DECODING:
mButtonStateMap["gl_btn"] = true;
updateButtons();
break;
case LLTextureFetchDebugger::HTTP_FETCHING:
mButtonStateMap["cacheread_btn"] = true;
mButtonStateMap["cachewrite_btn"] = true;
mButtonStateMap["decode_btn"] = true;
updateButtons();
break;
case LLTextureFetchDebugger::GL_TEX:
updateButtons();
break;
case LLTextureFetchDebugger::REFETCH_VIS_CACHE:
updateButtons();
case LLTextureFetchDebugger::REFETCH_VIS_HTTP:
updateButtons();
break;
default:
break;
}
}
}
//----------------------
void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio()
{
gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal());
}
void LLFloaterTextureFetchDebugger::onClickStart()
{
disableButtons();
mDebugger->startDebug();
mButtonStateMap["start_btn"] = false;
mButtonStateMap["cacheread_btn"] = true;
mButtonStateMap["http_btn"] = true;
updateButtons();
}
void LLFloaterTextureFetchDebugger::onClickClose()
{
setVisible(FALSE);
//stop everything
mDebugger->stopDebug();
}
void LLFloaterTextureFetchDebugger::onClickClear()
{
mButtonStateMap["start_btn"] = true;
mButtonStateMap["close_btn"] = true;
mButtonStateMap["clear_btn"] = true;
mButtonStateMap["cacheread_btn"] = false;
mButtonStateMap["cachewrite_btn"] = false;
mButtonStateMap["http_btn"] = false;
mButtonStateMap["decode_btn"] = false;
mButtonStateMap["gl_btn"] = false;
mButtonStateMap["refetchviscache_btn"] = true;
mButtonStateMap["refetchvishttp_btn"] = true;
updateButtons();
//stop everything
mDebugger->stopDebug();
mDebugger->clearHistory();
}
void LLFloaterTextureFetchDebugger::onClickCacheRead()
{
disableButtons();
mDebugger->debugCacheRead();
}
void LLFloaterTextureFetchDebugger::onClickCacheWrite()
{
disableButtons();
mDebugger->debugCacheWrite();
}
void LLFloaterTextureFetchDebugger::onClickHTTPLoad()
{
disableButtons();
mDebugger->debugHTTP();
}
void LLFloaterTextureFetchDebugger::onClickDecode()
{
disableButtons();
mDebugger->debugDecoder();
}
void LLFloaterTextureFetchDebugger::onClickGLTexture()
{
disableButtons();
mDebugger->debugGLTextureCreation();
}
void LLFloaterTextureFetchDebugger::onClickRefetchVisCache()
{
disableButtons();
mDebugger->debugRefetchVisibleFromCache();
}
void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP()
{
disableButtons();
mDebugger->debugRefetchVisibleFromHTTP();
}
void LLFloaterTextureFetchDebugger::draw()
{
//total number of fetched textures
{
getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures()));
}
//total number of fetching requests
{
getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests()));
}
//total number of cache hits
{
getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits()));
}
//total number of visible textures
{
getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures()));
}
//total number of visible texture fetching requests
{
getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests()));
}
//total number of fetched data
{
getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10));
getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10));
getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f));
}
//total number of visible fetched data
{
getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10));
getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10));
}
//total number of rendered fetched data
{
getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10));
getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10));
getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f));
}
//total time on cache readings
if(mDebugger->getCacheReadTime() < 0.f)
{
getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime()));
}
//total time on cache writings
if(mDebugger->getCacheWriteTime() < 0.f)
{
getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime()));
}
//total time on decoding
if(mDebugger->getDecodeTime() < 0.f)
{
getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime()));
}
//total time on gl texture creation
if(mDebugger->getGLCreationTime() < 0.f)
{
getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime()));
}
//total time on HTTP fetching
if(mDebugger->getHTTPTime() < 0.f)
{
getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime()));
}
//total time on entire fetching
{
getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime()));
}
//total time on refetching visible textures from cache
if(mDebugger->getRefetchVisCacheTime() < 0.f)
{
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----"));
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----"));
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime()));
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10));
getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f));
}
//total time on refetching visible textures from http
if(mDebugger->getRefetchVisHTTPTime() < 0.f)
{
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----"));
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----"));
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----"));
}
else
{
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime()));
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10));
getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f));
}
LLFloater::draw();
}

View File

@ -0,0 +1,71 @@
/**
* @file llfloatertexturefetchdebugger.h
* @brief texture fetching debugger window, debug use only
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
#include "llfloater.h"
class LLTextureFetchDebugger;
class LLFloaterTextureFetchDebugger : public LLFloater
{
friend class LLFloaterReg;
public:
/// initialize all the callbacks for the menu
virtual BOOL postBuild() ;
virtual void draw() ;
void onChangeTexelPixelRatio();
void onClickStart();
void onClickClear();
void onClickClose();
void onClickCacheRead();
void onClickCacheWrite();
void onClickHTTPLoad();
void onClickDecode();
void onClickGLTexture();
void onClickRefetchVisCache();
void onClickRefetchVisHTTP();
public:
void idle() ;
private:
LLFloaterTextureFetchDebugger(const LLSD& key);
virtual ~LLFloaterTextureFetchDebugger();
void updateButtons();
void disableButtons();
private:
LLTextureFetchDebugger* mDebugger;
std::map<std::string, bool> mButtonStateMap;
};
#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H

49
indra/newview/llinventorymodel.cpp Normal file → Executable file
View File

@ -1759,6 +1759,7 @@ bool LLInventoryModel::loadSkeleton(
update_map_t child_counts;
cat_array_t categories;
item_array_t items;
item_array_t possible_broken_links;
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
std::string owner_id_str;
owner_id.toString(owner_id_str);
@ -1807,7 +1808,7 @@ bool LLInventoryModel::loadSkeleton(
LLViewerInventoryCategory* tcat = *cit;
// we can safely ignore anything loaded from file, but
// not sent down in the skeleton.
// not sent down in the skeleton. Must have been removed from inventory.
if(cit == not_cached)
{
continue;
@ -1845,6 +1846,8 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
S32 bad_link_count = 0;
S32 good_link_count = 0;
S32 recovered_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
for(item_array_t::const_iterator item_iter = items.begin();
item_iter != items.end();
@ -1861,26 +1864,56 @@ bool LLInventoryModel::loadSkeleton(
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
if (item->getIsBrokenLink())
{
bad_link_count++;
//bad_link_count++;
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
<< item->getName() << " itemID: " << item->getUUID()
<< " assetID: " << item->getAssetUUID()
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
invalid_categories.insert(cit->second);
possible_broken_links.push_back(item);
continue;
}
else if (item->getIsLinkType())
{
good_link_count++;
}
addItem(item);
cached_item_count += 1;
++child_counts[cat->getUUID()];
}
}
}
if (bad_link_count > 0)
if (possible_broken_links.size() > 0)
{
llinfos << "Attempted to add " << bad_link_count
<< " cached link items without baseobj present. "
<< "The corresponding categories were invalidated." << llendl;
for(item_array_t::const_iterator item_iter = possible_broken_links.begin();
item_iter != possible_broken_links.end();
++item_iter)
{
LLViewerInventoryItem *item = (*item_iter).get();
const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
const LLViewerInventoryCategory* cat = cit->second.get();
if (item->getIsBrokenLink())
{
bad_link_count++;
invalid_categories.insert(cit->second);
//llinfos << "link still broken: " << item->getName() << " in folder " << cat->getName() << llendl;
}
else
{
// was marked as broken because of loading order, its actually fine to load
addItem(item);
cached_item_count += 1;
++child_counts[cat->getUUID()];
recovered_link_count++;
}
}
llinfos << "Attempted to add " << bad_link_count
<< " cached link items without baseobj present. "
<< good_link_count << " link items were successfully added. "
<< recovered_link_count << " links added in recovery. "
<< "The corresponding categories were invalidated." << llendl;
}
}
else
{
@ -2778,7 +2811,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
titem->unpackMessage(msg, _PREHASH_ItemData, i);
llinfos << "unpaked item '" << titem->getName() << "' in "
llinfos << "unpacked item '" << titem->getName() << "' in "
<< titem->getParentUUID() << llendl;
U32 callback_id;
msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);

View File

@ -34,6 +34,7 @@
#include "llfirstuse.h"
#include "llnearbychatbar.h"
#include "llnearbychatbarlistener.h"
#include "llagent.h"
#include "llgesturemgr.h"
#include "llmultigesture.h"
@ -80,6 +81,7 @@ LLNearbyChatBar::LLNearbyChatBar(const LLSD& key)
mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)
{
mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
mListener.reset(new LLNearbyChatBarListener(*this));
}
//virtual

View File

@ -35,6 +35,8 @@
#include "lloutputmonitorctrl.h"
#include "llspeakers.h"
class LLNearbyChatBarListener;
class LLNearbyChatBar : public LLFloater
{
public:
@ -92,6 +94,8 @@ protected:
LLLocalSpeakerMgr* mSpeakerMgr;
S32 mExpandedHeight;
boost::shared_ptr<LLNearbyChatBarListener> mListener;
};
#endif

View File

@ -3647,6 +3647,110 @@ void renderShadowFrusta(LLDrawInfo* params)
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
void renderTexelDensity(LLDrawable* drawable)
{
if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF
|| LLViewerTexture::sCheckerBoardImagep.isNull())
{
return;
}
LLGLEnable _(GL_BLEND);
//gObjectFullbrightProgram.bind();
LLMatrix4 checkerboard_matrix;
S32 discard_level = -1;
for (S32 f = 0; f < drawable->getNumFaces(); f++)
{
LLFace* facep = drawable->getFace(f);
LLVertexBuffer* buffer = facep->getVertexBuffer();
LLViewerTexture* texturep = facep->getTexture();
if (texturep == NULL) continue;
switch(LLViewerTexture::sDebugTexelsMode)
{
case LLViewerTexture::DEBUG_TEXELS_CURRENT:
discard_level = -1;
break;
case LLViewerTexture::DEBUG_TEXELS_DESIRED:
{
LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep);
discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1;
break;
}
default:
case LLViewerTexture::DEBUG_TEXELS_FULL:
discard_level = 0;
break;
}
checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f));
gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE);
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix);
if (buffer && (facep->getGeomCount() >= 3))
{
buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
U16 start = facep->getGeomStart();
U16 end = start + facep->getGeomCount()-1;
U32 count = facep->getIndicesCount();
U16 offset = facep->getIndicesStart();
buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
}
gGL.loadIdentity();
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
//S32 num_textures = llmax(1, (S32)params->mTextureList.size());
//for (S32 i = 0; i < num_textures; i++)
//{
// LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get();
// if (texturep == NULL) continue;
// LLMatrix4 checkboard_matrix;
// S32 discard_level = -1;
// switch(LLViewerTexture::sDebugTexelsMode)
// {
// case LLViewerTexture::DEBUG_TEXELS_CURRENT:
// discard_level = -1;
// break;
// case LLViewerTexture::DEBUG_TEXELS_DESIRED:
// {
// LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep);
// discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1;
// break;
// }
// default:
// case LLViewerTexture::DEBUG_TEXELS_FULL:
// discard_level = 0;
// break;
// }
// checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f));
// gGL.getTexUnit(i)->activate();
// glMatrixMode(GL_TEXTURE);
// glPushMatrix();
// glLoadIdentity();
// //gGL.matrixMode(LLRender::MM_TEXTURE);
// glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix);
// gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE);
// pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL );
// glPopMatrix();
// glMatrixMode(GL_MODELVIEW);
// //gGL.matrixMode(LLRender::MM_MODELVIEW);
//}
}
void renderLights(LLDrawable* drawablep)
{
@ -4042,6 +4146,10 @@ public:
{
renderComplexityDisplay(drawable);
}
if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
renderTexelDensity(drawable);
}
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
@ -4291,7 +4399,8 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_AGENT_TARGET |
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY |
LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return;
}

4
indra/newview/llstartup.cpp Normal file → Executable file
View File

@ -240,6 +240,7 @@ static bool mLoginStatePastUI = false;
boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
boost::scoped_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap);
//
// local function declaration
@ -2705,7 +2706,10 @@ void LLStartUp::setStartupState( EStartupState state )
LL_INFOS("AppInit") << "Startup state changing from " <<
getStartupStateString() << " to " <<
startupStateToString(state) << LL_ENDL;
sPhases->stopPhase(getStartupStateString());
gStartupState = state;
sPhases->startPhase(getStartupStateString());
postStartupState();
}

4
indra/newview/llstartup.h Normal file → Executable file
View File

@ -34,6 +34,8 @@ class LLEventPump;
class LLStartupListener;
class LLSLURL;
#include "llviewerstats.h"
// functions
bool idle_startup();
void release_start_screen();
@ -113,6 +115,7 @@ public:
static bool startLLProxy(); // Initialize the SOCKS 5 proxy
static LLViewerStats::PhaseMap& getPhases() { return *sPhases; }
private:
static LLSLURL sStartSLURL;
@ -120,6 +123,7 @@ private:
static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState
static boost::scoped_ptr<LLEventPump> sStateWatcher;
static boost::scoped_ptr<LLStartupListener> sListener;
static boost::scoped_ptr<LLViewerStats::PhaseMap> sPhases;
};

View File

@ -55,6 +55,9 @@ using namespace LLVOAvatarDefines;
static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt
// runway consolidate
extern std::string self_av_string();
class LLTexLayerInfo
{
friend class LLTexLayer;
@ -494,7 +497,6 @@ void LLTexLayerSetBuffer::doUpload()
}
LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
compressedImage->setRate(0.f);
const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask)
if (compressedImage->encode(baked_image, comment_text))
{
@ -577,7 +579,7 @@ void LLTexLayerSetBuffer::doUpload()
args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
args["RESOLUTION"] = lod_str;
LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args);
llinfos << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
}
}
else
@ -631,7 +633,7 @@ void LLTexLayerSetBuffer::doUpdate()
args["BODYREGION"] = mTexLayerSet->getBodyRegionName();
args["RESOLUTION"] = lod_str;
LLNotificationsUtil::add("AvatarRezSelfBakedTextureUpdateNotification",args);
llinfos << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << llendl;
LL_DEBUGS("Avatar") << self_av_string() << "Locally updating [ name: " << mTexLayerSet->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUpdateTimer.getElapsedTimeF32() << " ]" << LL_ENDL;
}
}

731
indra/newview/lltexturefetch.cpp Normal file → Executable file
View File

@ -52,12 +52,20 @@
#include "llviewerstats.h"
#include "llviewerassetstats.h"
#include "llworld.h"
#include "llsdutil.h"
#include "llstartup.h"
#include "llviewerstats.h"
bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128);
LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128);
//////////////////////////////////////////////////////////////////////////////
class LLTextureFetchWorker : public LLWorkerClass
{
friend class LLTextureFetch;
friend class HTTPGetResponder;
friend class LLTextureFetchDebugger;
private:
class CacheReadResponder : public LLTextureCache::ReadResponder
@ -242,6 +250,8 @@ private:
S32 mDecodedDiscard;
LLFrameTimer mRequestedTimer;
LLFrameTimer mFetchTimer;
LLTimer mCacheReadTimer;
F32 mCacheReadTime;
LLTextureCache::handle_t mCacheReadHandle;
LLTextureCache::handle_t mCacheWriteHandle;
U8* mBuffer;
@ -258,6 +268,7 @@ private:
BOOL mNeedsAux;
BOOL mHaveAllData;
BOOL mInLocalCache;
BOOL mInCache;
bool mCanUseHTTP ;
bool mCanUseNET ; //can get from asset server.
S32 mHTTPFailCount;
@ -653,6 +664,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mRequestedDiscard(-1),
mLoadedDiscard(-1),
mDecodedDiscard(-1),
mCacheReadTime(0.f),
mCacheReadHandle(LLTextureCache::nullHandle()),
mCacheWriteHandle(LLTextureCache::nullHandle()),
mBuffer(NULL),
@ -669,6 +681,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mNeedsAux(FALSE),
mHaveAllData(FALSE),
mInLocalCache(FALSE),
mInCache(FALSE),
mCanUseHTTP(true),
mHTTPFailCount(0),
mRetryAttempt(0),
@ -838,6 +851,8 @@ void LLTextureFetchWorker::startWork(S32 param)
// Called from LLWorkerThread::processRequest()
bool LLTextureFetchWorker::doWork(S32 param)
{
static const F32 FETCHING_TIMEOUT = 120.f;//seconds
LLMutexLock lock(&mWorkMutex);
if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED)))
@ -896,6 +911,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mCacheReadHandle = LLTextureCache::nullHandle();
mCacheWriteHandle = LLTextureCache::nullHandle();
mState = LOAD_FROM_TEXTURE_CACHE;
mInCache = FALSE;
mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE
LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)
<< " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
@ -926,6 +942,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
offset, size, responder);
mCacheReadTimer.reset();
}
else if (mUrl.empty())
{
@ -934,6 +951,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
offset, size, responder);
mCacheReadTimer.reset();
}
else if(mCanUseHTTP)
{
@ -982,11 +1000,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mFormattedImage->getDataSize() > 0);
mLoadedDiscard = mDesiredDiscard;
mState = DECODE_IMAGE;
mInCache = TRUE;
mWriteToCacheState = NOT_WRITE ;
LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
<< " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
<< " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
// fall through
LLTextureFetch::sCacheHitRate.addValue(100.f);
}
else
{
@ -1002,6 +1021,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mState = LOAD_FROM_NETWORK;
}
// fall through
LLTextureFetch::sCacheHitRate.addValue(0.f);
}
}
@ -1177,6 +1197,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
bool res = false;
if (!mUrl.empty())
{
mRequestedTimer.reset();
mLoaded = FALSE;
mGetStatus = 0;
mGetReason.clear();
@ -1335,6 +1357,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32())
{
//timeout, abort.
mState = DONE;
return true;
}
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false;
}
@ -1396,6 +1425,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if (mDecoded)
{
if(mFetcher->getFetchDebugger() && !mInLocalCache)
{
mFetcher->getFetchDebugger()->addHistoryEntry(this);
}
if (mDecodedDiscard < 0)
{
LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL;
@ -1780,6 +1814,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag
mDecoded = TRUE;
// llinfos << mID << " : DECODE COMPLETE " << llendl;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mCacheReadTime = mCacheReadTimer.getElapsedTimeF32();
}
//////////////////////////////////////////////////////////////////////////////
@ -1824,11 +1859,18 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHTTPTextureBits(0),
mTotalHTTPRequests(0),
mCurlGetRequest(NULL),
mQAMode(qa_mode)
mQAMode(qa_mode),
mFetchDebugger(NULL)
{
mCurlPOSTRequestCount = 0;
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
if(LLTextureFetchDebugger::isEnabled())
{
mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ;
}
}
LLTextureFetch::~LLTextureFetch()
@ -1843,11 +1885,17 @@ LLTextureFetch::~LLTextureFetch()
}
// ~LLQueuedThread() called here
delete mFetchDebugger;
}
bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
{
if(mFetcherLocked)
{
return false;
}
if (mDebugPause)
{
return false;
@ -2092,6 +2140,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
discard_level = worker->mDecodedDiscard;
raw = worker->mRawImage;
aux = worker->mAuxImage;
F32 cache_read_time = worker->mCacheReadTime;
if (cache_read_time != 0.f)
{
sCacheReadLatency.addValue(cache_read_time * 1000.f);
}
res = true;
LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL;
worker->unlockWorkMutex();
@ -2222,7 +2275,13 @@ S32 LLTextureFetch::update(F32 max_time_ms)
if (!mDebugPause)
{
sendRequestListToSimulators();
// this is the startup state when send_complete_agent_movement() message is sent.
// Before this, the RequestImages message sent by sendRequestListToSimulators
// won't work so don't bother trying
if (LLStartUp::getStartupState() > STATE_AGENT_SEND)
{
sendRequestListToSimulators();
}
}
if (!mThreaded)
@ -2258,6 +2317,11 @@ void LLTextureFetch::startThread()
{
// Construct mCurlGetRequest from Worker Thread
mCurlGetRequest = new LLCurlRequest();
if(mFetchDebugger)
{
mFetchDebugger->setCurlGetRequest(mCurlGetRequest);
}
}
// WORKER THREAD
@ -2266,6 +2330,10 @@ void LLTextureFetch::endThread()
// Destroy mCurlGetRequest from Worker Thread
delete mCurlGetRequest;
mCurlGetRequest = NULL;
if(mFetchDebugger)
{
mFetchDebugger->setCurlGetRequest(NULL);
}
}
// WORKER THREAD
@ -2803,7 +2871,6 @@ void LLTextureFetch::cmdDoWork()
}
}
//////////////////////////////////////////////////////////////////////////////
// Private (anonymous) class methods implementing the command scheme.
@ -2959,7 +3026,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// In QA mode, Metrics submode, log the result for ease of testing
if (fetcher->isQAMode())
{
LL_INFOS("Textures") << merged_llsd << LL_ENDL;
LL_INFOS("Textures") << ll_pretty_print_sd(merged_llsd) << LL_ENDL;
}
gViewerAssetStatsThread1->reset();
@ -3007,5 +3074,659 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics)
} // end of anonymous namespace
///////////////////////////////////////////////////////////////////////////////////////////
//Start LLTextureFetchDebugger
///////////////////////////////////////////////////////////////////////////////////////////
//---------------------
class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder
{
public:
LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image)
: mDebugger(debugger), mID(id)
{
setImage(image);
}
virtual void completed(bool success)
{
mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal);
}
private:
LLTextureFetchDebugger* mDebugger;
S32 mID;
};
class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder
{
public:
LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id)
: mDebugger(debugger), mID(id)
{
}
virtual void completed(bool success)
{
mDebugger->callbackCacheWrite(mID, success);
}
private:
LLTextureFetchDebugger* mDebugger;
S32 mID;
};
class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder
{
public:
LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id)
: mDebugger(debugger), mID(id)
{
}
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
{
mDebugger->callbackDecoded(mID, success, raw, aux);
}
private:
LLTextureFetchDebugger* mDebugger;
S32 mID;
};
class LLDebuggerHTTPResponder : public LLCurl::Responder
{
public:
LLDebuggerHTTPResponder(LLTextureFetchDebugger* debugger, S32 index)
: mDebugger(debugger), mIndex(index)
{
}
virtual void completedRaw(U32 status, const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
{
bool success = false;
bool partial = false;
if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES)
{
success = true;
if (HTTP_PARTIAL_CONTENT == status) // partial information
{
partial = true;
}
}
if (!success)
{
llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl;
}
mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success);
}
virtual bool followRedir()
{
return true;
}
private:
LLTextureFetchDebugger* mDebugger;
S32 mIndex;
};
LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) :
mFetcher(fetcher),
mTextureCache(cache),
mImageDecodeThread(imagedecodethread),
mCurlGetRequest(NULL)
{
init();
}
LLTextureFetchDebugger::~LLTextureFetchDebugger()
{
mFetchingHistory.clear();
stopDebug();
}
void LLTextureFetchDebugger::init()
{
mState = IDLE;
mCacheReadTime = -1.f;
mCacheWriteTime = -1.f;
mDecodingTime = -1.f;
mHTTPTime = -1.f;
mGLCreationTime = -1.f;
mTotalFetchingTime = 0.f;
mRefetchVisCacheTime = -1.f;
mRefetchVisHTTPTime = -1.f;
mNumFetchedTextures = 0;
mNumCacheHits = 0;
mNumVisibleFetchedTextures = 0;
mNumVisibleFetchingRequests = 0;
mFetchedData = 0;
mDecodedData = 0;
mVisibleFetchedData = 0;
mVisibleDecodedData = 0;
mRenderedData = 0;
mRenderedDecodedData = 0;
mFetchedPixels = 0;
mRenderedPixels = 0;
mRefetchedData = 0;
mRefetchedPixels = 0;
mFreezeHistory = FALSE;
}
void LLTextureFetchDebugger::startDebug()
{
//lock the fetcher
mFetcher->lockFetcher(true);
mFreezeHistory = TRUE;
//clear the current fetching queue
gTextureList.clearFetchingRequests();
//wait for all works to be done
while(1)
{
S32 pending = 0;
pending += LLAppViewer::getTextureCache()->update(1);
pending += LLAppViewer::getImageDecodeThread()->update(1);
pending += LLAppViewer::getTextureFetch()->update(1);
if(!pending)
{
break;
}
}
//collect statistics
mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
std::set<LLUUID> fetched_textures;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size; i++)
{
bool in_list = true;
if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end())
{
fetched_textures.insert(mFetchingHistory[i].mID);
in_list = false;
}
LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(mFetchingHistory[i].mID);
if(tex && tex->isJustBound()) //visible
{
if(!in_list)
{
mNumVisibleFetchedTextures++;
}
mNumVisibleFetchingRequests++;
mVisibleFetchedData += mFetchingHistory[i].mFetchedSize;
mVisibleDecodedData += mFetchingHistory[i].mDecodedSize;
if(tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel)
{
mRenderedData += mFetchingHistory[i].mFetchedSize;
mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
mRenderedPixels += tex->getWidth() * tex->getHeight();
}
}
}
mNumFetchedTextures = fetched_textures.size();
}
void LLTextureFetchDebugger::stopDebug()
{
//clear the current debug work
S32 size = mFetchingHistory.size();
switch(mState)
{
case READ_CACHE:
for(S32 i = 0 ; i < size; i++)
{
if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle())
{
mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true);
}
}
break;
case WRITE_CACHE:
for(S32 i = 0 ; i < size; i++)
{
if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle())
{
mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true);
}
}
break;
case DECODING:
break;
case HTTP_FETCHING:
break;
case GL_TEX:
break;
default:
break;
}
while(1)
{
if(update())
{
break;
}
}
//unlock the fetcher
mFetcher->lockFetcher(false);
mFreezeHistory = FALSE;
mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset
}
//called in the main thread and when the fetching queue is empty
void LLTextureFetchDebugger::clearHistory()
{
mFetchingHistory.clear();
init();
}
void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
{
if(mFreezeHistory)
{
mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
mRefetchedData += worker->mFormattedImage->getDataSize();
return;
}
if(worker->mInCache)
{
mNumCacheHits++;
}
mFetchedData += worker->mFormattedImage->getDataSize();
mDecodedData += worker->mRawImage->getDataSize();
mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
//mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(),
//worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
}
void LLTextureFetchDebugger::lockCache()
{
}
void LLTextureFetchDebugger::unlockCache()
{
}
void LLTextureFetchDebugger::debugCacheRead()
{
lockCache();
llassert_always(mState == IDLE);
mTimer.reset();
mState = READ_CACHE;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
{
mFetchingHistory[i].mFormattedImage = NULL;
mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize,
new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage));
}
}
void LLTextureFetchDebugger::clearCache()
{
S32 size = mFetchingHistory.size();
{
std::set<LLUUID> deleted_list;
for(S32 i = 0 ; i < size ; i++)
{
if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end())
{
deleted_list.insert(mFetchingHistory[i].mID);
mTextureCache->removeFromCache(mFetchingHistory[i].mID);
}
}
}
}
void LLTextureFetchDebugger::debugCacheWrite()
{
//remove from cache
clearCache();
lockCache();
llassert_always(mState == IDLE);
mTimer.reset();
mState = WRITE_CACHE;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
{
if(mFetchingHistory[i].mFormattedImage.notNull())
{
mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL,
mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize,
mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1,
new LLDebuggerCacheWriteResponder(this, i));
}
}
}
void LLTextureFetchDebugger::lockDecoder()
{
}
void LLTextureFetchDebugger::unlockDecoder()
{
}
void LLTextureFetchDebugger::debugDecoder()
{
lockDecoder();
llassert_always(mState == IDLE);
mTimer.reset();
mState = DECODING;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
{
if(mFetchingHistory[i].mFormattedImage.isNull())
{
continue;
}
mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL,
mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux,
new LLDebuggerDecodeResponder(this, i));
}
}
void LLTextureFetchDebugger::debugHTTP()
{
llassert_always(mState == IDLE);
LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
llinfos << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << llendl;
return;
}
mHTTPUrl = region->getHttpUrl();
if (mHTTPUrl.empty())
{
llinfos << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << llendl;
return;
}
mTimer.reset();
mState = HTTP_FETCHING;
S32 size = mFetchingHistory.size();
for (S32 i = 0 ; i < size ; i++)
{
mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE;
mFetchingHistory[i].mCurlReceivedSize = 0;
mFetchingHistory[i].mHTTPFailCount = 0;
}
mNbCurlRequests = 0;
mNbCurlCompleted = 0;
fillCurlQueue();
}
S32 LLTextureFetchDebugger::fillCurlQueue()
{
if (mNbCurlRequests == 24)
return mNbCurlRequests;
S32 size = mFetchingHistory.size();
for (S32 i = 0 ; i < size ; i++)
{
if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE)
continue;
std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str();
S32 requestedSize = mFetchingHistory[i].mRequestedSize;
// We request the whole file if the size was not set.
requestedSize = llmax(0,requestedSize);
// We request the whole file if the size was set to an absurdly high value (meaning all file)
requestedSize = (requestedSize == 33554432 ? 0 : requestedSize);
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
bool res = mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, new LLDebuggerHTTPResponder(this, i));
if (res)
{
mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
mNbCurlRequests++;
// Hack
if (mNbCurlRequests == 24)
break;
}
else
{
break;
}
}
//llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl;
return mNbCurlRequests;
}
void LLTextureFetchDebugger::debugGLTextureCreation()
{
llassert_always(mState == IDLE);
mState = GL_TEX;
std::vector<LLViewerFetchedTexture*> tex_list;
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
{
if(mFetchingHistory[i].mRawImage.notNull())
{
LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
if(tex && !tex->isForSculptOnly())
{
tex->destroyGLTexture() ;
tex_list.push_back(tex);
}
}
}
mTimer.reset();
S32 j = 0 ;
S32 size1 = tex_list.size();
for(S32 i = 0 ; i < size && j < size1; i++)
{
if(mFetchingHistory[i].mRawImage.notNull())
{
if(mFetchingHistory[i].mID == tex_list[j]->getID())
{
tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel());
j++;
}
}
}
mGLCreationTime = mTimer.getElapsedTimeF32() ;
return;
}
//clear fetching results of all textures.
void LLTextureFetchDebugger::clearTextures()
{
S32 size = mFetchingHistory.size();
for(S32 i = 0 ; i < size ; i++)
{
LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
if(tex)
{
tex->clearFetchedResults() ;
}
}
}
void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
{
llassert_always(mState == IDLE);
mState = REFETCH_VIS_CACHE;
clearTextures();
mTimer.reset();
mFetcher->lockFetcher(false);
}
void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
{
llassert_always(mState == IDLE);
mState = REFETCH_VIS_HTTP;
clearCache();
clearTextures();
mTimer.reset();
mFetcher->lockFetcher(false);
}
bool LLTextureFetchDebugger::update()
{
switch(mState)
{
case READ_CACHE:
if(!mTextureCache->update(1))
{
mCacheReadTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
unlockCache();
}
break;
case WRITE_CACHE:
if(!mTextureCache->update(1))
{
mCacheWriteTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
unlockCache();
}
break;
case DECODING:
if(!mImageDecodeThread->update(1))
{
mDecodingTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
unlockDecoder();
}
break;
case HTTP_FETCHING:
mCurlGetRequest->process();
LLCurl::getCurlThread()->update(1);
if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
{
mHTTPTime = mTimer.getElapsedTimeF32() ;
mState = IDLE;
}
break;
case GL_TEX:
mState = IDLE;
break;
case REFETCH_VIS_CACHE:
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{
mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
mState = IDLE;
mFetcher->lockFetcher(true);
}
break;
case REFETCH_VIS_HTTP:
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{
mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
mState = IDLE;
mFetcher->lockFetcher(true);
}
break;
default:
mState = IDLE;
break;
}
return mState == IDLE;
}
void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal)
{
if (success)
{
mFetchingHistory[id].mFormattedImage = image;
}
mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false);
mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
}
void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success)
{
mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle);
mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
}
void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux)
{
if (success)
{
llassert_always(raw);
mFetchingHistory[id].mRawImage = raw;
}
}
void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool partial, bool success)
{
mNbCurlRequests--;
if (success)
{
mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
mNbCurlCompleted++;
S32 data_size = buffer->countAfter(channels.in(), NULL);
mFetchingHistory[id].mCurlReceivedSize += data_size;
//llinfos << "Fetch Debugger : got results for " << id << ", data_size = " << data_size << ", received = " << mFetchingHistory[id].mCurlReceivedSize << ", requested = " << mFetchingHistory[id].mRequestedSize << ", partial = " << partial << llendl;
if ((mFetchingHistory[id].mCurlReceivedSize >= mFetchingHistory[id].mRequestedSize) || !partial || (mFetchingHistory[id].mRequestedSize == 600))
{
U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size);
buffer->readAfter(channels.in(), NULL, d_buffer, data_size);
llassert_always(mFetchingHistory[id].mFormattedImage.isNull());
{
// For now, create formatted image based on extension
std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str();
std::string extension = gDirUtilp->getExtension(texture_url);
mFetchingHistory[id].mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension));
if (mFetchingHistory[id].mFormattedImage.isNull())
{
mFetchingHistory[id].mFormattedImage = new LLImageJ2C; // default
}
}
mFetchingHistory[id].mFormattedImage->setData(d_buffer, data_size);
}
}
else //failed
{
mFetchingHistory[id].mHTTPFailCount++;
if(mFetchingHistory[id].mHTTPFailCount < 5)
{
// Fetch will have to be redone
mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE;
}
else //skip
{
mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
mNbCurlCompleted++;
}
}
}
//---------------------
///////////////////////////////////////////////////////////////////////////////////////////
//End LLTextureFetchDebugger
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -34,14 +34,17 @@
#include "llcurl.h"
#include "lltextureinfo.h"
#include "llapr.h"
#include "llimageworker.h"
//#include "lltexturecache.h"
class LLViewerTexture;
class LLTextureFetchWorker;
class HTTPGetResponder;
class LLTextureCache;
class LLImageDecodeThread;
class LLHost;
class LLViewerAssetStats;
class LLTextureFetchDebugger;
class LLTextureCache;
// Interface class
class LLTextureFetch : public LLWorkerThread
@ -164,6 +167,9 @@ private:
LLMutex mQueueMutex; //to protect mRequestMap and mCommands only
LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
static LLStat sCacheHitRate;
static LLStat sCacheReadLatency;
LLTextureCache* mTextureCache;
LLImageDecodeThread* mImageDecodeThread;
LLCurlRequest* mCurlGetRequest;
@ -209,7 +215,195 @@ public:
// attempt to log metrics follows a break in the metrics stream
// reporting due to either startup or a problem POSTing data.
static volatile bool svMetricsDataBreak;
private:
//debug use
LLTextureFetchDebugger* mFetchDebugger;
bool mFetcherLocked;
public:
//debug use
LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
void lockFetcher(bool lock) { mFetcherLocked = lock;}
};
//debug use
class LLTextureFetchDebugger
{
friend class LLTextureFetch;
public:
LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ;
~LLTextureFetchDebugger();
public:
enum e_debug_state
{
IDLE = 0,
READ_CACHE,
WRITE_CACHE,
DECODING,
HTTP_FETCHING,
GL_TEX,
REFETCH_VIS_CACHE,
REFETCH_VIS_HTTP,
REFETCH_ALL_CACHE,
REFETCH_ALL_HTTP,
INVALID
};
private:
struct FetchEntry
{
enum e_curl_state
{
CURL_NOT_DONE = 0,
CURL_IN_PROGRESS,
CURL_DONE
};
LLUUID mID;
S32 mRequestedSize;
S32 mDecodedLevel;
S32 mFetchedSize;
S32 mDecodedSize;
BOOL mNeedsAux;
U32 mCacheHandle;
LLPointer<LLImageFormatted> mFormattedImage;
LLPointer<LLImageRaw> mRawImage;
e_curl_state mCurlState;
S32 mCurlReceivedSize;
S32 mHTTPFailCount;
FetchEntry() :
mDecodedLevel(-1),
mFetchedSize(0),
mDecodedSize(0)
{}
FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) :
mID(id),
mRequestedSize(r_size),
mDecodedLevel(level),
mFetchedSize(f_size),
mDecodedSize(d_size),
mNeedsAux(false),
mHTTPFailCount(0)
{}
};
std::vector<FetchEntry> mFetchingHistory;
e_debug_state mState;
F32 mCacheReadTime;
F32 mCacheWriteTime;
F32 mDecodingTime;
F32 mHTTPTime;
F32 mGLCreationTime;
F32 mTotalFetchingTime;
F32 mRefetchVisCacheTime;
F32 mRefetchVisHTTPTime;
LLTimer mTimer;
LLTextureFetch* mFetcher;
LLTextureCache* mTextureCache;
LLImageDecodeThread* mImageDecodeThread;
LLCurlRequest* mCurlGetRequest;
S32 mNumFetchedTextures;
S32 mNumCacheHits;
S32 mNumVisibleFetchedTextures;
S32 mNumVisibleFetchingRequests;
U32 mFetchedData;
U32 mDecodedData;
U32 mVisibleFetchedData;
U32 mVisibleDecodedData;
U32 mRenderedData;
U32 mRenderedDecodedData;
U32 mFetchedPixels;
U32 mRenderedPixels;
U32 mRefetchedData;
U32 mRefetchedPixels;
BOOL mFreezeHistory;
std::string mHTTPUrl;
S32 mNbCurlRequests;
S32 mNbCurlCompleted;
public:
bool update(); //called in the main thread once per frame
//fetching history
void clearHistory();
void addHistoryEntry(LLTextureFetchWorker* worker);
void setCurlGetRequest(LLCurlRequest* request) { mCurlGetRequest = request;}
void startDebug();
void stopDebug(); //stop everything
void debugCacheRead();
void debugCacheWrite();
void debugHTTP();
void debugDecoder();
void debugGLTextureCreation();
void debugRefetchVisibleFromCache();
void debugRefetchVisibleFromHTTP();
void callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal);
void callbackCacheWrite(S32 id, bool success);
void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux);
void callbackHTTP(S32 id, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
bool partial, bool success);
e_debug_state getState() {return mState;}
S32 getNumFetchedTextures() {return mNumFetchedTextures;}
S32 getNumFetchingRequests() {return mFetchingHistory.size();}
S32 getNumCacheHits() {return mNumCacheHits;}
S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;}
S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;}
U32 getFetchedData() {return mFetchedData;}
U32 getDecodedData() {return mDecodedData;}
U32 getVisibleFetchedData() {return mVisibleFetchedData;}
U32 getVisibleDecodedData() {return mVisibleDecodedData;}
U32 getRenderedData() {return mRenderedData;}
U32 getRenderedDecodedData() {return mRenderedDecodedData;}
U32 getFetchedPixels() {return mFetchedPixels;}
U32 getRenderedPixels() {return mRenderedPixels;}
U32 getRefetchedData() {return mRefetchedData;}
U32 getRefetchedPixels() {return mRefetchedPixels;}
F32 getCacheReadTime() {return mCacheReadTime;}
F32 getCacheWriteTime() {return mCacheWriteTime;}
F32 getDecodeTime() {return mDecodingTime;}
F32 getGLCreationTime() {return mGLCreationTime;}
F32 getHTTPTime() {return mHTTPTime;}
F32 getTotalFetchingTime() {return mTotalFetchingTime;}
F32 getRefetchVisCacheTime() {return mRefetchVisCacheTime;}
F32 getRefetchVisHTTPTime() {return mRefetchVisHTTPTime;}
private:
void init();
void clearTextures();//clear fetching results of all textures.
void clearCache();
void lockFetcher();
void unlockFetcher();
void lockCache();
void unlockCache();
void lockDecoder();
void unlockDecoder();
S32 fillCurlQueue();
private:
static bool sDebuggerEnabled;
public:
static bool isEnabled() {return sDebuggerEnabled;}
};
#endif // LL_LLTEXTUREFETCH_H

392
indra/newview/lltextureview.cpp Normal file → Executable file
View File

@ -57,8 +57,6 @@
extern F32 texmem_lower_bound_scale;
LLTextureView *gTextureView = NULL;
LLTextureSizeView *gTextureSizeView = NULL;
LLTextureSizeView *gTextureCategoryView = NULL;
#define HIGH_PRIORITY 100000000.f
@ -512,8 +510,8 @@ void LLGLTexMemBar::draw()
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 = LLFontGL::getFontMonospace()->getLineHeight();
S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
@ -527,80 +525,24 @@ void LLGLTexMemBar::draw()
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d",
text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
total_mem,
max_total_mem,
bound_mem,
max_bound_mem,
LLRenderTarget::sBytesAllocated/(1024*1024),
LLImageRaw::sGlobalRawMemory >> 20, discard_bias,
cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests);
//, cache_entries, cache_max_entries
cache_usage, cache_max_usage);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*4,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d",
total_texture_downloaded, total_object_downloaded, total_http_requests);
//, cache_entries, cache_max_entries
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
//----------------------------------------------------------------------------
#if 0
S32 bar_left = 400;
S32 bar_width = 200;
S32 top = line_height*3 - 2 + v_offset;
S32 bottom = top - 6;
S32 left = bar_left;
S32 right = left + bar_width;
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;
gGL.diffuseColor4fv(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);
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;
gGL.diffuseColor4fv(color.mV);
gl_rect_2d(left, top, right, bottom);
#else
S32 left = 0 ;
#endif
//----------------------------------------------------------------------------
text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d",
@ -669,8 +611,7 @@ BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask)
LLRect LLGLTexMemBar::getRequiredRect()
{
LLRect rect;
//rect.mTop = 50;
rect.mTop = 0;
rect.mTop = 50; //LLFontGL::getFontMonospace()->getLineHeight() * 6;
return rect;
}
@ -954,9 +895,11 @@ void LLTextureView::draw()
LLRect tmbr;
tmbp.name("gl texmem bar");
tmbp.rect(tmbr);
tmbp.follows.flags = FOLLOWS_LEFT|FOLLOWS_TOP;
tmbp.texture_view(this);
mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp);
addChildInBack(mGLTexMemBar);
addChild(mGLTexMemBar);
sendChildToFront(mGLTexMemBar);
LLAvatarTexBar::Params atbp;
LLRect atbr;
@ -965,16 +908,13 @@ void LLTextureView::draw()
atbp.rect(atbr);
mAvatarTexBar = LLUICtrlFactory::create<LLAvatarTexBar>(atbp);
addChild(mAvatarTexBar);
sendChildToFront(mAvatarTexBar);
reshape(getRect().getWidth(), getRect().getHeight(), TRUE);
/*
count = gTextureList.getNumImages();
std::string info_string;
info_string = llformat("Global Info:\nTexture Count: %d", count);
mInfoTextp->setText(info_string);
*/
LLUI::popMatrix();
LLUI::pushMatrix();
LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom);
for (child_list_const_iter_t child_iter = getChildList()->begin();
child_iter != getChildList()->end(); ++child_iter)
@ -1049,302 +989,4 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return FALSE;
}
//-----------------------------------------------------------------
LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p)
{
setVisible(FALSE) ;
mTextureSizeBarWidth = 30 ;
}
LLTextureSizeView::~LLTextureSizeView()
{
if(mTextureSizeBar.size())
{
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
{
delete mTextureSizeBar[i] ;
}
mTextureSizeBar.clear() ;
}
}
void LLTextureSizeView::draw()
{
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 = LLFontGL::getFontMonospace()->getLineHeight();
mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
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 = drawTextureSizeDistributionGraph() ;
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
{
mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ;
mTextureSizeBar[i]->draw() ;
}
LLImageGL::resetCurTexSizebar();
}
//draw background of texture size bar graph
F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
{
//scale
F32 scale = 1.0f ;
LLGLSUIDefault gls_ui;
{
S32 count = 0 ;
for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
{
if(LLImageGL::sTextureLoadedCounter[i] > count)
{
count = LLImageGL::sTextureLoadedCounter[i] ;
}
}
if(count > mTextureSizeBarRect.getHeight())
{
scale = (F32)mTextureSizeBarRect.getHeight() / count ;
}
}
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
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
text = llformat("%d", 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("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
text = llformat("(w + h)/2") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, 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);
}
//--------------------------------------------------
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 Size Distribution") ;
LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
return scale ;
}
//draw real-time texture mem bar over category
void LLTextureSizeView::drawTextureCategoryGraph()
{
if(mTextureSizeBar.size() == 0)
{
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
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 = LLFontGL::getFontMonospace()->getLineHeight();
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

@ -75,41 +75,6 @@ public:
};
class LLGLTexSizeBar;
class LLTextureSizeView : public LLContainerView
{
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 mType ;
};
extern LLTextureView *gTextureView;
extern LLTextureSizeView *gTextureSizeView;
extern LLTextureSizeView *gTextureCategoryView;
#endif // LL_TEXTURE_VIEW_H

43
indra/newview/llviewerassetstats.cpp Normal file → Executable file
View File

@ -30,6 +30,7 @@
#include "llregionhandle.h"
#include "stdtypes.h"
#include "llvoavatar.h"
/*
* Classes and utility functions for per-thread and per-region
@ -126,6 +127,8 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta
mFPS.merge(src.mFPS);
}
// Avatar stats - data all comes from main thread, so leave alone.
// Requests
for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
{
@ -133,6 +136,7 @@ LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionSta
mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued);
mRequests[i].mResponse.merge(src.mRequests[i].mResponse);
}
}
@ -156,7 +160,9 @@ LLViewerAssetStats::LLViewerAssetStats()
LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
: mRegionHandle(src.mRegionHandle),
mResetTimestamp(src.mResetTimestamp)
mResetTimestamp(src.mResetTimestamp),
mPhaseStats(src.mPhaseStats),
mAvatarRezStates(src.mAvatarRezStates)
{
const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
@ -252,6 +258,17 @@ LLViewerAssetStats::recordFPS(F32 fps)
mCurRegionStats->mFPS.record(fps);
}
void
LLViewerAssetStats::recordAvatarStats()
{
std::vector<S32> rez_counts;
LLVOAvatar::getNearbyRezzedStats(rez_counts);
mAvatarRezStates = rez_counts;
mPhaseStats.clear();
mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud");
mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray");
}
LLSD
LLViewerAssetStats::asLLSD(bool compact_output)
{
@ -282,6 +299,11 @@ LLViewerAssetStats::asLLSD(bool compact_output)
static const LLSD::String max_tag("max");
static const LLSD::String mean_tag("mean");
// Avatar sub-tags
static const LLSD::String avatar_tag("avatar");
static const LLSD::String avatar_nearby_tag("nearby");
static const LLSD::String avatar_phase_stats_tag("phase_stats");
const duration_t now = LLViewerAssetStatsFF::get_timestamp();
mCurRegionStats->accumulateTime(now);
@ -329,7 +351,6 @@ LLViewerAssetStats::asLLSD(bool compact_output)
slot[max_tag] = LLSD(F64(stats.mFPS.getMax()));
slot[mean_tag] = LLSD(F64(stats.mFPS.getMean()));
}
U32 grid_x(0), grid_y(0);
grid_from_region_handle(it->first, &grid_x, &grid_y);
reg_stat["grid_x"] = LLSD::Integer(grid_x);
@ -341,6 +362,16 @@ LLViewerAssetStats::asLLSD(bool compact_output)
LLSD ret = LLSD::emptyMap();
ret["regions"] = regions;
ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6);
LLSD avatar_info;
avatar_info[avatar_nearby_tag] = LLSD::emptyArray();
for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat)
{
std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat);
avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat];
}
avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData();
avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData();
ret[avatar_tag] = avatar_info;
return ret;
}
@ -439,6 +470,14 @@ record_fps_main(F32 fps)
gViewerAssetStatsMain->recordFPS(fps);
}
void
record_avatar_stats()
{
if (! gViewerAssetStatsMain)
return;
gViewerAssetStatsMain->recordAvatarStats();
}
// 'thread1' - should be for TextureFetch thread

9
indra/newview/llviewerassetstats.h Normal file → Executable file
View File

@ -36,6 +36,7 @@
#include "llviewerassetstorage.h"
#include "llsimplestat.h"
#include "llsd.h"
#include "llvoavatar.h"
/**
* @class LLViewerAssetStats
@ -181,6 +182,9 @@ public:
// Frames-Per-Second Samples
void recordFPS(F32 fps);
// Avatar-related statistics
void recordAvatarStats();
// Merge a source instance into a destination instance. This is
// conceptually an 'operator+=()' method:
// - counts are added
@ -252,6 +256,10 @@ protected:
// Time of last reset
duration_t mResetTimestamp;
// Nearby avatar stats
std::vector<S32> mAvatarRezStates;
LLViewerStats::phase_stats_t mPhaseStats;
};
@ -310,6 +318,7 @@ void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_t
void record_fps_main(F32 fps);
void record_avatar_stats();
/**
* Region context, event and duration loggers for Thread 1.

View File

@ -87,7 +87,6 @@ std::string gLastRunVersion;
extern BOOL gResizeScreenTexture;
extern BOOL gDebugGL;
extern BOOL gAuditTexture;
////////////////////////////////////////////////////////////////////////////
// Listeners
@ -411,12 +410,6 @@ 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;
@ -618,7 +611,6 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _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

@ -103,6 +103,7 @@
#include "llfloatertelehub.h"
#include "llfloatertestinspectors.h"
#include "llfloatertestlistview.h"
#include "llfloatertexturefetchdebugger.h"
#include "llfloatertools.h"
#include "llfloatertos.h"
#include "llfloatertopobjects.h"
@ -227,6 +228,11 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"))
{
LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>);
}
LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);

4
indra/newview/llviewerinventory.cpp Normal file → Executable file
View File

@ -342,8 +342,8 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne
void LLViewerInventoryItem::removeFromServer()
{
llinfos << "Removing inventory item " << mUUID << " from server."
<< llendl;
lldebugs << "Removing inventory item " << mUUID << " from server."
<< llendl;
LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1);
gInventory.accountForUpdate(up);

1
indra/newview/llviewerjointmesh.cpp Normal file → Executable file
View File

@ -576,7 +576,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
old_mode = mTexture->getAddressMode();
}
gGL.getTexUnit(diffuse_channel)->bind(mTexture.get());
gGL.getTexUnit(diffuse_channel)->bind(mTexture);
gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}

1
indra/newview/llviewerjointmesh.h Normal file → Executable file
View File

@ -61,6 +61,7 @@ public:
//-----------------------------------------------------------------------------
class LLViewerJointMesh : public LLViewerJoint
{
friend class LLVOAvatar;
protected:
LLColor4 mColor; // color value
// LLColor4 mSpecular; // specular color (always white for now)

View File

@ -516,14 +516,6 @@ class LLAdvancedToggleConsole : public view_listener_t
{
toggle_visibility( (void*)static_cast<LLUICtrl*>(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)
{
LLFloaterReg::toggleInstance("fast_timers");
@ -556,14 +548,6 @@ 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 = LLFloaterReg::instanceVisible("fast_timers");
@ -866,6 +850,73 @@ class LLAdvancedCheckFeature : public view_listener_t
}
};
class LLAdvancedCheckDisplayTextureDensity : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
std::string mode = userdata.asString();
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return mode == "none";
}
if (mode == "current")
{
return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT;
}
else if (mode == "desired")
{
return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED;
}
else if (mode == "full")
{
return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL;
}
return false;
}
};
class LLAdvancedSetDisplayTextureDensity : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
std::string mode = userdata.asString();
if (mode == "none")
{
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE)
{
gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
}
LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
}
else if (mode == "current")
{
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
{
gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
}
LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT;
}
else if (mode == "desired")
{
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
{
gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
}
gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true);
LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED;
}
else if (mode == "full")
{
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
{
gPipeline.toggleRenderDebug((void*)LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
}
LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL;
}
return true;
}
};
//////////////////
// INFO DISPLAY //
@ -980,6 +1031,10 @@ U32 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_WIND_VECTORS;
}
else if ("texel density" == info_display)
{
return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY;
}
else
{
return 0;
@ -2245,6 +2300,14 @@ class LLDevelopSetLoggingLevel : public view_listener_t
}
};
class LLDevelopTextureFetchDebugger : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
}
};
//////////////////
// ADMIN MENU //
//////////////////
@ -8164,6 +8227,10 @@ void initialize_menus()
//// Advanced > Render > Features
view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity");
view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity");
// Advanced > Render > Info Displays
view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
@ -8295,6 +8362,9 @@ void initialize_menus()
// Develop >Set logging level
view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
//Develop (Texture Fetch Debug Console)
view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");

View File

@ -91,8 +91,9 @@ extern LLPipeline gPipeline;
// Statics for object lookup tables.
U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex;
std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex;
std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID;
LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128);
LLViewerObjectList::LLViewerObjectList()
{
@ -542,6 +543,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
justCreated = TRUE;
mNumNewObjects++;
sCacheHitRate.addValue(cached ? 100.f : 0.f);
}

View File

@ -192,6 +192,8 @@ protected:
std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects
S32 mNumOrphans;
static LLStat sCacheHitRate;
typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t;
vobj_list_t mObjects;

107
indra/newview/llviewerstats.cpp Normal file → Executable file
View File

@ -860,3 +860,110 @@ void send_stats()
LLHTTPClient::post(url, body, new ViewerStatsResponder());
}
LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
{
phase_map_t::iterator iter = mPhaseMap.find(phase_name);
if (iter == mPhaseMap.end())
{
LLFrameTimer timer;
mPhaseMap[phase_name] = timer;
}
LLFrameTimer& timer = mPhaseMap[phase_name];
return timer;
}
void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
{
LLFrameTimer& timer = getPhaseTimer(phase_name);
lldebugs << "startPhase " << phase_name << llendl;
timer.unpause();
}
void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
{
phase_map_t::iterator iter = mPhaseMap.find(phase_name);
if (iter != mPhaseMap.end())
{
if (iter->second.getStarted())
{
// Going from started to paused state - record stats.
recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
}
lldebugs << "stopPhase " << phase_name << llendl;
iter->second.pause();
}
else
{
lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl;
}
}
void LLViewerStats::PhaseMap::stopAllPhases()
{
for (phase_map_t::iterator iter = mPhaseMap.begin();
iter != mPhaseMap.end(); ++iter)
{
const std::string& phase_name = iter->first;
if (iter->second.getStarted())
{
// Going from started to paused state - record stats.
recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
}
lldebugs << "stopPhase (all) " << phase_name << llendl;
iter->second.pause();
}
}
void LLViewerStats::PhaseMap::clearPhases()
{
lldebugs << "clearPhases" << llendl;
mPhaseMap.clear();
}
LLSD LLViewerStats::PhaseMap::dumpPhases()
{
LLSD result;
for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter)
{
const std::string& phase_name = iter->first;
result[phase_name]["completed"] = !(iter->second.getStarted());
result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32();
#if 0 // global stats for each phase seem like overkill here
phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name);
if (stats_iter != sPhaseStats.end())
{
result[phase_name]["stats"] = stats_iter->second.getData();
}
#endif
}
return result;
}
// static initializer
//static
LLViewerStats::phase_stats_t LLViewerStats::PhaseMap::sStats;
LLViewerStats::PhaseMap::PhaseMap()
{
}
// static
LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
{
phase_stats_t::iterator it = sStats.find(phase_name);
if (it == sStats.end())
{
LLViewerStats::StatsAccumulator new_stats;
sStats[phase_name] = new_stats;
}
return sStats[phase_name];
}
// static
void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32 value)
{
LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name);
stats.push(value);
}

25
indra/newview/llviewerstats.h Normal file → Executable file
View File

@ -244,7 +244,7 @@ public:
inline F32 getStdDev() const
{
const F32 mean = getMean();
return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) );
return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean)));
}
inline U32 getCount() const
@ -274,7 +274,28 @@ public:
};
StatsAccumulator mAgentPositionSnaps;
// Phase tracking (originally put in for avatar rezzing), tracking
// progress of active/completed phases for activities like outfit changing.
typedef std::map<std::string,LLFrameTimer> phase_map_t;
typedef std::map<std::string,StatsAccumulator> phase_stats_t;
class PhaseMap
{
private:
phase_map_t mPhaseMap;
static phase_stats_t sStats;
public:
PhaseMap();
LLFrameTimer& getPhaseTimer(const std::string& phase_name);
void startPhase(const std::string& phase_name);
void stopPhase(const std::string& phase_name);
void stopAllPhases();
void clearPhases();
LLSD dumpPhases();
static StatsAccumulator& getPhaseStats(const std::string& phase_name);
static void recordPhaseStat(const std::string& phase_name, F32 value);
};
private:
F64 mStats[ST_COUNT];

View File

@ -67,6 +67,7 @@
// statics
LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL;
LLPointer<LLViewerTexture> LLViewerTexture::sCheckerBoardImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
@ -87,6 +88,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ;
F32 LLViewerTexture::sCameraMovingBias = 0.0f ;
S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ;
@ -96,6 +98,9 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
F32 LLViewerTexture::sCurrentTime = 0.0f ;
BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
F32 LLViewerTexture::sTexelPixelRatio = 1.0f;
LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by
@ -175,7 +180,12 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id)
}
return tex ;
}
LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id)
{
return gTextureList.findImage(id);
}
LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
{
return LLViewerMediaTexture::findMediaTexture(media_id) ;
@ -347,6 +357,21 @@ void LLViewerTextureManager::init()
LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
image_raw = new LLImageRaw(32,32,3);
data = image_raw->getData();
for (S32 i = 0; i < (32*32*3); i+=3)
{
S32 x = (i % (32*3)) / (3*16);
S32 y = i / (32*3*16);
U8 color = ((x + y) % 2) * 255;
data[i] = color;
data[i+1] = color;
data[i+2] = color;
}
LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE);
LLViewerTexture::initClass() ;
if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
@ -367,6 +392,7 @@ void LLViewerTextureManager::cleanup()
LLImageGL::sDefaultGLTexture = NULL ;
LLViewerTexture::sNullImagep = NULL;
LLViewerTexture::sBlackImagep = NULL;
LLViewerTexture::sCheckerBoardImagep = NULL;
LLViewerFetchedTexture::sDefaultImagep = NULL;
LLViewerFetchedTexture::sSmokeImagep = NULL;
LLViewerFetchedTexture::sMissingAssetImagep = NULL;
@ -383,11 +409,7 @@ void LLViewerTextureManager::cleanup()
void LLViewerTexture::initClass()
{
LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
if(gAuditTexture)
{
LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ;
}
sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
}
// static
@ -534,7 +556,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1);
sCameraMovingDiscardBias = (S8)(sCameraMovingBias);
LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
(BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
@ -655,10 +678,6 @@ void LLViewerTexture::setBoostLevel(S32 level)
{
setNoDelete() ;
}
if(gAuditTexture)
{
setCategory(mBoostLevel);
}
}
}
@ -712,6 +731,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co
mNeedsGLTexture = TRUE ;
}
virtual_size *= sTexelPixelRatio;
if(!mMaxVirtualSizeResetCounter)
{
//flag to reset the values because the old values are used.
@ -1287,6 +1307,7 @@ void LLViewerFetchedTexture::cleanup()
mCachedRawDiscardLevel = -1 ;
mCachedRawImageReady = FALSE ;
mSavedRawImage = NULL ;
mSavedRawDiscardLevel = -1;
}
void LLViewerFetchedTexture::setForSculpt()
@ -1880,6 +1901,8 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
bool LLViewerFetchedTexture::updateFetch()
{
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold");
static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost");
if(textures_decode_disabled)
{
return false ;
@ -2042,18 +2065,24 @@ bool LLViewerFetchedTexture::updateFetch()
// make_request = false;
//}
if(make_request)
if (make_request)
{
//load the texture progressively.
// Load the texture progressively: we try not to rush to the desired discard too fast.
// If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps
// This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around
S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ;
if(current_discard < 0)
if (current_discard < 0)
{
desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level);
}
else
else if (LLViewerTexture::sCameraMovingBias < sCameraMotionThreshold)
{
desired_discard = llmax(desired_discard, current_discard - delta_level);
desired_discard = llmax(desired_discard, current_discard - sCameraMotionBoost);
}
else
{
desired_discard = llmax(desired_discard, current_discard - delta_level);
}
if (mIsFetching)
{
@ -2121,6 +2150,30 @@ bool LLViewerFetchedTexture::updateFetch()
return mIsFetching ? true : false;
}
void LLViewerFetchedTexture::clearFetchedResults()
{
llassert_always(!mNeedsCreateTexture && !mIsFetching);
cleanup();
destroyGLTexture();
if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate
{
mGLTexturep->forceToInvalidateGLTexture();
}
}
void LLViewerFetchedTexture::forceToDeleteRequest()
{
if (mHasFetcher)
{
LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
mHasFetcher = FALSE;
mIsFetching = FALSE ;
resetTextureStats();
}
}
void LLViewerFetchedTexture::setIsMissingAsset()
{
if (mUrl.empty())

View File

@ -139,6 +139,7 @@ public:
OTHER,
MAX_GL_IMAGE_CATEGORY
};
static S32 getTotalNumOfCategories() ;
static S32 getIndexFromCategory(S32 category) ;
static S32 getCategoryFromIndex(S32 index) ;
@ -309,6 +310,7 @@ protected:
} LLGLTextureState;
LLGLTextureState mTextureState ;
static F32 sTexelPixelRatio;
public:
static const U32 sCurrentFileVersion;
static S32 sImageCount;
@ -323,6 +325,7 @@ public:
static S32 sMaxTotalTextureMemInMegaBytes;
static S32 sMaxDesiredTextureMemInBytes ;
static S8 sCameraMovingDiscardBias;
static F32 sCameraMovingBias;
static S32 sMaxSculptRez ;
static S32 sMinLargeImageSize ;
static S32 sMaxSmallImageSize ;
@ -330,8 +333,19 @@ public:
static F32 sCurrentTime ;
static BOOL sUseTextureAtlas ;
enum EDebugTexels
{
DEBUG_TEXELS_OFF,
DEBUG_TEXELS_CURRENT,
DEBUG_TEXELS_DESIRED,
DEBUG_TEXELS_FULL
};
static EDebugTexels sDebugTexelsMode;
static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
static LLPointer<LLViewerTexture> sBlackImagep; // Texture to show NOTHING (pure black)
static LLPointer<LLViewerTexture> sCheckerBoardImagep; // Texture to show NOTHING (pure black)
};
@ -420,6 +434,8 @@ public:
bool updateFetch();
void clearFetchedResults(); //clear all fetched results, for debug use.
// Override the computation of discard levels if we know the exact output
// size of the image. Used for UI textures to not decode, even if we have
// more data.
@ -478,6 +494,7 @@ public:
BOOL hasFetcher() const { return mHasFetcher;}
void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}
void forceToDeleteRequest();
protected:
/*virtual*/ void switchToCachedImage();
S32 getCurrentDiscardLevelForFetching() ;
@ -687,6 +704,7 @@ public:
//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
//
static LLViewerTexture* findTexture(const LLUUID& id) ;
static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id) ;
static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ;
static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;

View File

@ -58,6 +58,7 @@
#include "pipeline.h"
#include "llappviewer.h"
#include "llxuiparser.h"
#include "llagent.h"
////////////////////////////////////////////////////////////////////////////
@ -597,6 +598,12 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats");
void LLViewerTextureList::updateImages(F32 max_time)
{
if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
{
clearFetchingRequests();
return;
}
LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec());
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
@ -659,6 +666,24 @@ void LLViewerTextureList::updateImages(F32 max_time)
}
}
void LLViewerTextureList::clearFetchingRequests()
{
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{
return;
}
for (image_priority_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* image = *iter;
if(image->hasFetcher())
{
image->forceToDeleteRequest() ;
}
}
}
void LLViewerTextureList::updateImagesDecodePriorities()
{
// Update the decode priority for N images each frame
@ -1030,7 +1055,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage
{
raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C();
compressedImage->setRate(0.f);
if (gSavedSettings.getBOOL("LosslessJ2CUpload") &&
(raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF))

View File

@ -110,6 +110,8 @@ public:
void doPreloadImages();
void doPrefetchImages();
void clearFetchingRequests();
static S32 getMinVideoRamSetting();
static S32 getMaxVideoRamSetting(bool get_recommended = false);
@ -164,7 +166,7 @@ private:
// Request image from a specific host, used for baked avatar textures.
// Implemented in header in case someone changes default params above. JC
LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host)
{ return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
{ return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
public:
typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;

653
indra/newview/llvoavatar.cpp Normal file → Executable file

File diff suppressed because it is too large Load Diff

46
indra/newview/llvoavatar.h Normal file → Executable file
View File

@ -48,6 +48,7 @@
#include "lltexglobalcolor.h"
#include "lldriverparam.h"
#include "material_codes.h" // LL_MCODE_END
#include "llviewerstats.h"
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@ -277,14 +278,27 @@ public:
public:
BOOL isFullyLoaded() const;
bool isTooComplex() const;
bool visualParamWeightsAreDefault();
bool visualParamWeightsAreDefault();
virtual BOOL getIsCloud() const;
BOOL isFullyTextured() const;
BOOL hasGray() const;
S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured.
void updateRezzedStatusTimers();
S32 mLastRezzedStatus;
LLViewerStats::PhaseMap& getPhases()
{
return mPhases;
}
protected:
virtual BOOL getIsCloud();
BOOL updateIsFullyLoaded();
BOOL processFullyLoadedChange(bool loading);
void updateRuthTimer(bool loading);
F32 calcMorphAmount();
private:
BOOL mFirstFullyVisible;
BOOL mFullyLoaded;
BOOL mPreviousFullyLoaded;
BOOL mFullyLoadedInitialized;
@ -292,6 +306,28 @@ private:
S32 mVisualComplexity;
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
public:
class ScopedPhaseSetter
{
public:
ScopedPhaseSetter(LLVOAvatar *avatarp, std::string phase_name):
mAvatar(avatarp), mPhaseName(phase_name)
{
if (mAvatar) { mAvatar->getPhases().startPhase(mPhaseName); }
}
~ScopedPhaseSetter()
{
if (mAvatar) { mAvatar->getPhases().stopPhase(mPhaseName); }
}
private:
std::string mPhaseName;
LLVOAvatar* mAvatar;
};
private:
LLViewerStats::PhaseMap mPhases;
protected:
LLFrameTimer mInvisibleTimer;
@ -518,9 +554,10 @@ public:
virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const;
protected:
BOOL isFullyBaked();
static BOOL areAllNearbyInstancesBaked(S32& grey_avatars);
static void getNearbyRezzedStats(std::vector<S32>& counts);
static std::string rezStatusToString(S32 status);
//--------------------------------------------------------------------
// Baked textures
@ -882,6 +919,7 @@ private:
public:
std::string getFullname() const; // Returns "FirstName LastName"
std::string avString() const; // Frequently used string in log messages "Avatar '<full name'"
protected:
static void getAnimLabels(LLDynamicArray<std::string>* labels);
static void getAnimNames(LLDynamicArray<std::string>* names);
@ -983,7 +1021,9 @@ private:
// Avatar Rez Metrics
//--------------------------------------------------------------------
public:
void debugAvatarRezTime(std::string notification_name, std::string comment = "");
F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); }
protected:
LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez
LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory.

260
indra/newview/llvoavatarself.cpp Normal file → Executable file
View File

@ -58,6 +58,8 @@
#include "llappearancemgr.h"
#include "llmeshrepository.h"
#include "llvovolume.h"
#include "llsdutil.h"
#include "llstartup.h"
#if LL_MSVC
// disable boost::lexical_cast warning
@ -75,6 +77,39 @@ BOOL isAgentAvatarValid()
(!gAgentAvatarp->isDead()));
}
void selfStartPhase(const std::string& phase_name)
{
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().startPhase(phase_name);
}
}
void selfStopPhase(const std::string& phase_name)
{
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().stopPhase(phase_name);
}
}
void selfClearPhases()
{
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().clearPhases();
gAgentAvatarp->mLastRezzedStatus = -1;
}
}
void selfStopAllPhases()
{
if (isAgentAvatarValid())
{
gAgentAvatarp->getPhases().stopAllPhases();
}
}
using namespace LLVOAvatarDefines;
/*********************************************************************************
@ -131,7 +166,8 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
LLVOAvatar(id, pcode, regionp),
mScreenp(NULL),
mLastRegionHandle(0),
mRegionCrossingCount(0)
mRegionCrossingCount(0),
mInitialBakesLoaded(false)
{
gAgentWearables.setAvatarObject(this);
@ -164,6 +200,7 @@ void LLVOAvatarSelf::initInstance()
{
mDebugBakedTextureTimes[i][0] = -1.0f;
mDebugBakedTextureTimes[i][1] = -1.0f;
mInitialBakeIDs[i] = LLUUID::null;
}
status &= buildMenus();
@ -762,6 +799,41 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
}
}
//virtual
U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num,
const EObjectUpdateType update_type,
LLDataPacker *dp)
{
U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp);
if (mInitialBakesLoaded == false && retval == 0x0)
{
// call update textures to force the images to be created
updateMeshTextures();
// unpack the texture UUIDs to the texture slots
retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
// need to trigger a few operations to get the avatar to use the new bakes
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
const LLVOAvatarDefines::ETextureIndex te = mBakedTextureDatas[i].mTextureIndex;
LLUUID texture_id = getTEImage(te)->getID();
setNewBakedTexture(te, texture_id);
mInitialBakeIDs[i] = texture_id;
}
onFirstTEMessageReceived();
mInitialBakesLoaded = true;
}
return retval;
}
void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
{
if (te >= TEX_NUM_INDICES)
@ -1889,7 +1961,7 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount()
llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl;
}
BOOL LLVOAvatarSelf::getIsCloud()
BOOL LLVOAvatarSelf::getIsCloud() const
{
// do we have our body parts?
if (gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE) == 0 ||
@ -2055,6 +2127,80 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const
return text;
}
// Dump avatar metrics data.
LLSD LLVOAvatarSelf::metricsData()
{
// runway - add region info
LLSD result;
result["id"] = getID();
result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
result["is_self"] = isSelf();
std::vector<S32> rez_counts;
LLVOAvatar::getNearbyRezzedStats(rez_counts);
result["nearby"] = LLSD::emptyMap();
for (S32 i=0; i<rez_counts.size(); ++i)
{
std::string rez_status_name = LLVOAvatar::rezStatusToString(i);
result["nearby"][rez_status_name] = rez_counts[i];
}
result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32();
result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32();
result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32();
result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32();
result["phases"] = getPhases().dumpPhases();
result["startup"] = LLStartUp::getPhases().dumpPhases();
return result;
}
class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
{
public:
ViewerAppearanceChangeMetricsResponder()
{
}
virtual void completed(U32 status,
const std::string& reason,
const LLSD& content)
{
if (isGoodStatus(status))
{
LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
result(content);
}
else
{
LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL;
error(status,reason);
}
}
};
void LLVOAvatarSelf::sendAppearanceChangeMetrics()
{
// gAgentAvatarp->stopAllPhases();
LLSD msg = metricsData();
msg["message"] = "ViewerAppearanceChangeMetrics";
LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL;
std::string caps_url;
if (getRegion())
{
// runway - change here to activate.
caps_url = getRegion()->getCapability("ViewerMetrics");
}
if (!caps_url.empty())
{
LLCurlRequest::headers_t headers;
LLHTTPClient::post(caps_url,
msg,
new ViewerAppearanceChangeMetricsResponder);
}
}
const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const
{
if (canGrabBakedTexture(baked_index))
@ -2253,11 +2399,25 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
if (isAllLocalTextureDataFinal())
{
LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args);
LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
<< "sec ]"
<< avString()
<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
<< " Notification " << "AvatarRezSelfBakedDoneNotification"
<< llendl;
}
else
{
args["STATUS"] = debugDumpAllLocalTextureDataInfo();
LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args);
LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32()
<< "sec ]"
<< avString()
<< "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32()
<< " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32()
<< " Notification " << "AvatarRezSelfBakedUpdateNotification"
<< llendl;
}
}
@ -2265,7 +2425,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
}
}
// FIXME: This is never called. Something may be broken.
// FIXME: This is not called consistently. Something may be broken.
void LLVOAvatarSelf::outputRezDiagnostics() const
{
if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime"))
@ -2274,11 +2434,11 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
}
const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32();
llinfos << "REZTIME: Myself rez stats:" << llendl;
llinfos << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl;
llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl;
llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl;
llinfos << "\t Load time for each texture: " << llendl;
LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << llendl;
LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl;
LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl;
LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl;
LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl;
for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i)
{
std::stringstream out;
@ -2302,12 +2462,14 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
// Don't print out non-existent textures.
if (j != 0)
llinfos << out.str() << llendl;
{
LL_DEBUGS("Avatar") << out.str() << LL_ENDL;
}
}
llinfos << "\t Time points for each upload (start / finish)" << llendl;
LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl;
for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i)
{
llinfos << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl;
LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl;
}
for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
@ -2319,15 +2481,16 @@ void LLVOAvatarSelf::outputRezDiagnostics() const
if (!layerset) continue;
const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite();
if (!layerset_buffer) continue;
llinfos << layerset_buffer->dumpTextureInfo() << llendl;
LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl;
}
}
void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const
{
LL_DEBUGS("Avatar Rez")
LL_INFOS("Avatar")
<< avString()
<< llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32())
<< llendl;
<< LL_ENDL;
}
void LLVOAvatarSelf::reportAvatarRezTime() const
@ -2351,6 +2514,18 @@ void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid
{
if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet)
{
if (mInitialBakeIDs[i] != LLUUID::null)
{
if (mInitialBakeIDs[i] == uuid)
{
llinfos << "baked texture correctly loaded at login! " << i << llendl;
}
else
{
llwarns << "baked texture does not match id loaded at login!" << i << llendl;
}
mInitialBakeIDs[i] = LLUUID::null;
}
mBakedTextureDatas[i].mTexLayerSet->cancelUpload();
}
}
@ -2478,6 +2653,20 @@ LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const
return NULL;
}
LLTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) const
{
/* switch(index)
case TEX_HEAD_BAKED:
case TEX_HEAD_BODYPAINT:
return mHeadLayerSet; */
if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES)
{
return mBakedTextureDatas[baked_index].mTexLayerSet;
}
return NULL;
}
// static
void LLVOAvatarSelf::onCustomizeStart()
{
@ -2558,49 +2747,6 @@ 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( LLRender::sGLCoreProfile ? GL_RG : 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() )

22
indra/newview/llvoavatarself.h Normal file → Executable file
View File

@ -93,15 +93,27 @@ public:
/*virtual*/ void updateVisualParams();
/*virtual*/ void idleUpdateAppearanceAnimation();
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num,
const EObjectUpdateType update_type,
LLDataPacker *dp);
private:
// helper function. Passed in param is assumed to be in avatar's parameter list.
BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE );
/** Initialization
** **
*******************************************************************************/
private:
LLUUID mInitialBakeIDs[6];
bool mInitialBakesLoaded;
/********************************************************************************
** **
** STATE
@ -121,7 +133,7 @@ public:
// Loading state
//--------------------------------------------------------------------
public:
/*virtual*/ BOOL getIsCloud();
/*virtual*/ BOOL getIsCloud() const;
//--------------------------------------------------------------------
// Region state
@ -229,6 +241,7 @@ public:
void requestLayerSetUpload(LLVOAvatarDefines::EBakedTextureIndex i);
void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
LLTexLayerSet* getLayerSet(LLVOAvatarDefines::EBakedTextureIndex baked_index) const;
//--------------------------------------------------------------------
// Composites
@ -369,6 +382,8 @@ public:
const LLTexLayerSet* debugGetLayerSet(LLVOAvatarDefines::EBakedTextureIndex index) const { return mBakedTextureDatas[index].mTexLayerSet; }
const std::string debugDumpLocalTextureDataInfo(const LLTexLayerSet* layerset) const; // Lists out state of this particular baked texture layer
const std::string debugDumpAllLocalTextureDataInfo() const; // Lists out which baked textures are at highest LOD
LLSD metricsData();
void sendAppearanceChangeMetrics(); // send data associated with completing a change.
private:
LLFrameTimer mDebugSelfLoadTimer;
F32 mDebugTimeWearablesLoaded;
@ -387,4 +402,9 @@ extern LLPointer<LLVOAvatarSelf> gAgentAvatarp;
BOOL isAgentAvatarValid();
void selfStartPhase(const std::string& phase_name);
void selfStopPhase(const std::string& phase_name);
void selfStopAllPhases();
void selfClearPhases();
#endif // LL_VO_AVATARSELF_H

View File

@ -464,6 +464,7 @@ public:
RENDER_DEBUG_LOD_INFO = 0x04000000,
RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000,
RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000,
RENDER_DEBUG_TEXEL_DENSITY = 0x20000000
};
public:

View File

@ -149,13 +149,52 @@
show_per_sec="true"
show_bar="false">
</stat_bar>
<stat_bar
name="object_cache_hits"
label="Object Cache Hit Rate"
stat="object_cache_hits"
bar_min="0"
bar_max="100"
unit_label="%"
tick_spacing="20"
label_spacing="20"
show_history="true"
show_per_sec="false"
show_bar="false">
</stat_bar>
</stat_view>
<!--Texture Stats-->
<stat_view
name="texture"
label="Texture"
show_label="true">
<stat_bar
<stat_bar
name="texture_cache_hits"
label="Cache Hit Rate"
stat="texture_cache_hits"
bar_min="0.f"
bar_max="100.f"
unit_label="%"
tick_spacing="20"
label_spacing="20"
show_history="true"
show_per_sec="false"
show_bar="false">
</stat_bar>
<stat_bar
name="texture_cache_read_latency"
label="Cache Read Latency"
unit_label="msec"
stat="texture_cache_read_latency"
bar_min="0.f"
bar_max="1000.f"
tick_spacing="100"
label_spacing="200"
show_history="true"
show_per_sec="false"
show_bar="false">
</stat_bar>
<stat_bar
name="numimagesstat"
label="Count"
stat="numimagesstat"

View File

@ -0,0 +1,341 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
can_minimize="false"
height="550"
layout="topleft"
name="TexFetchDebugger"
help_topic="texfetchdebugger"
title="Texture Fetching Debugger"
width="540">
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left="10"
name="total_num_fetched_label"
top="30"
width="400">
1, Total number of fetched textures: [NUM]
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_num_fetching_requests_label"
top_delta="25"
width="400">
2, Total number of fetching requests: [NUM]
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_num_cache_hits_label"
top_delta="25"
width="400">
3, Total number of cache hits: [NUM]
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_num_visible_tex_label"
top_delta="25"
width="400">
4, Total number of visible textures: [NUM]
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_num_visible_tex_fetch_req_label"
top_delta="25"
width="450">
5, Total number of visible texture fetching requests: [NUM]
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_fetched_data_label"
top_delta="25"
width="530">
6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_fetched_vis_data_label"
top_delta="25"
width="480">
7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_fetched_rendered_data_label"
top_delta="25"
width="530">
8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_cache_read_label"
top_delta="25"
width="400">
9, Total time on cache readings: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_cache_write_label"
top_delta="25"
width="400">
10, Total time on cache writings: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_decode_label"
top_delta="25"
width="400">
11, Total time on decodings: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_gl_label"
top_delta="25"
width="400">
12, Total time on gl texture creation: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_http_label"
top_delta="25"
width="400">
13, Total time on HTTP fetching: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_fetch_label"
top_delta="25"
width="400">
14, Total time on entire fetching: [TIME] seconds
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_refetch_vis_cache_label"
top_delta="25"
width="540">
15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
</text>
<text
type="string"
length="1"
follows="left|top"
height="25"
layout="topleft"
left_delta="0"
name="total_time_refetch_vis_http_label"
top_delta="25"
width="540">
16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
</text>
<spinner
decimal_digits="2"
follows="left|top"
height="20"
increment="0.01"
initial_value="1.0"
label="17, Ratio of Texel/Pixel:"
label_width="130"
layout="topleft"
left_delta="0"
max_val="10.0"
min_val="0.01"
name="texel_pixel_ratio"
top_delta="30"
width="200">
<spinner.commit_callback
function="TexFetchDebugger.ChangeTexelPixelRatio" />
</spinner>
<button
follows="left|top"
height="20"
label="Start"
layout="topleft"
left_delta="0"
name="start_btn"
top_delta="30"
width="70">
<button.commit_callback
function="TexFetchDebugger.Start" />
</button>
<button
follows="left|top"
height="20"
label="Reset"
layout="topleft"
left_pad="7"
name="clear_btn"
top_delta="0"
width="70">
<button.commit_callback
function="TexFetchDebugger.Clear" />
</button>
<button
follows="left|top"
height="20"
label="Close"
layout="topleft"
left_pad="7"
name="close_btn"
top_delta="0"
width="70">
<button.commit_callback
function="TexFetchDebugger.Close" />
</button>
<button
follows="left|top"
height="20"
label="Cache Read"
layout="topleft"
left="10"
name="cacheread_btn"
top_delta="30"
width="80">
<button.commit_callback
function="TexFetchDebugger.CacheRead" />
</button>
<button
follows="left|top"
height="20"
label="Cache Write"
layout="topleft"
left_pad="7"
name="cachewrite_btn"
top_delta="0"
width="80">
<button.commit_callback
function="TexFetchDebugger.CacheWrite" />
</button>
<button
follows="left|top"
height="20"
label="HTTP"
layout="topleft"
left_pad="7"
name="http_btn"
top_delta="0"
width="70">
<button.commit_callback
function="TexFetchDebugger.HTTPLoad" />
</button>
<button
follows="left|top"
height="20"
label="Decode"
layout="topleft"
left_pad="7"
name="decode_btn"
top_delta="0"
width="70">
<button.commit_callback
function="TexFetchDebugger.Decode" />
</button>
<button
follows="left|top"
height="20"
label="GL Texture"
layout="topleft"
left_pad="7"
name="gl_btn"
top_delta="0"
width="70">
<button.commit_callback
function="TexFetchDebugger.GLTexture" />
</button>
<button
follows="left|top"
height="20"
label="Refetch Vis Cache"
layout="topleft"
left="10"
name="refetchviscache_btn"
top_delta="30"
width="120">
<button.commit_callback
function="TexFetchDebugger.RefetchVisCache" />
</button>
<button
follows="left|top"
height="20"
label="Refetch Vis HTTP"
layout="topleft"
left_pad="7"
name="refetchvishttp_btn"
top_delta="0"
width="120">
<button.commit_callback
function="TexFetchDebugger.RefetchVisHTTP" />
</button>
</floater>

View File

@ -1876,7 +1876,7 @@
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="texture" />
</menu_item_check>
</menu_item_check>
<menu_item_check
label="Debug Console"
name="Debug Console"
@ -1897,28 +1897,6 @@
function="Floater.Toggle"
parameter="notifications_console" />
</menu_item_call>
<menu_item_check
label="Texture Size Console"
name="Texture Size"
shortcut="control|shift|6">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="texture size" />
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="texture size" />
</menu_item_check>
<menu_item_check
label="Texture Category Console"
name="Texture Category"
shortcut="control|shift|7">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="texture category" />
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="texture category" />
</menu_item_check>
<menu_item_check
label="Fast Timers"
name="Fast Timers"
@ -1953,7 +1931,20 @@
function="Advanced.ToggleConsole"
parameter="scene view" />
</menu_item_check>
<menu_item_call
enabled="false"
visible="false"
label="Texture Fetch Debug Console"
name="Texture Fetch Debug Console">
<menu_item_call.on_click
function="Floater.Show"
parameter="tex_fetch_debugger" />
<on_enable
function="Develop.SetTexFetchDebugger" />
<on_visible
function="Develop.SetTexFetchDebugger" />
</menu_item_call>
<menu_item_separator/>
<menu_item_call
@ -2439,6 +2430,52 @@
function="Advanced.ToggleInfoDisplay"
parameter="sculpt" />
</menu_item_check>
<menu
create_jump_keys="true"
label="Texture Density"
name="Texture Density"
tear_off="true">
<menu_item_check
label="None"
name="None">
<menu_item_check.on_check
function="Advanced.CheckDisplayTextureDensity"
parameter="none" />
<menu_item_check.on_click
function="Advanced.SetDisplayTextureDensity"
parameter="none" />
</menu_item_check>
<menu_item_check
label="Current"
name="Current">
<menu_item_check.on_check
function="Advanced.CheckDisplayTextureDensity"
parameter="current" />
<menu_item_check.on_click
function="Advanced.SetDisplayTextureDensity"
parameter="current" />
</menu_item_check>
<menu_item_check
label="Desired"
name="Desired">
<menu_item_check.on_check
function="Advanced.CheckDisplayTextureDensity"
parameter="desired" />
<menu_item_check.on_click
function="Advanced.SetDisplayTextureDensity"
parameter="desired" />
</menu_item_check>
<menu_item_check
label="Full"
name="Full">
<menu_item_check.on_check
function="Advanced.CheckDisplayTextureDensity"
parameter="full" />
<menu_item_check.on_click
function="Advanced.SetDisplayTextureDensity"
parameter="full" />
</menu_item_check>
</menu>
</menu>
<menu
create_jump_keys="true"
@ -2605,16 +2642,6 @@
function="ToggleControl"
parameter="TextureLoadFullRes" />
</menu_item_check>
<menu_item_check
label="Audit Textures"
name="Audit Textures">
<menu_item_check.on_check
function="CheckControl"
parameter="AuditTexture" />
<menu_item_check.on_click
function="ToggleControl"
parameter="AuditTexture" />
</menu_item_check>
<menu_item_check
label="Texture Atlas (experimental)"
name="Texture Atlas">

54
indra/newview/tests/llviewerassetstats_test.cpp Normal file → Executable file
View File

@ -35,6 +35,31 @@
#include "lluuid.h"
#include "llsdutil.h"
#include "llregionhandle.h"
#include "../llvoavatar.h"
void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts)
{
counts.resize(3);
counts[0] = 0;
counts[1] = 0;
counts[2] = 1;
}
// static
std::string LLVOAvatar::rezStatusToString(S32 rez_status)
{
if (rez_status==0) return "cloud";
if (rez_status==1) return "gray";
if (rez_status==2) return "textured";
return "unknown";
}
// static
LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
{
static LLViewerStats::StatsAccumulator junk;
return junk;
}
static const char * all_keys[] =
{
@ -104,18 +129,25 @@ is_single_key_map(const LLSD & sd, const std::string & key)
{
return sd.isMap() && 1 == sd.size() && sd.has(key);
}
#endif
static bool
is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2)
{
return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2);
}
#endif
static bool
is_triple_key_map(const LLSD & sd, const std::string & key1, const std::string & key2, const std::string& key3)
{
return sd.isMap() && 3 == sd.size() && sd.has(key1) && sd.has(key2) && sd.has(key3);
}
static bool
is_no_stats_map(const LLSD & sd)
{
return is_double_key_map(sd, "duration", "regions");
return is_triple_key_map(sd, "duration", "regions", "avatar");
}
static bool
@ -226,7 +258,7 @@ namespace tut
// Once the region is set, we will get a response even with no data collection
it->setRegion(region1_handle);
sd_full = it->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd_full, "duration", "regions", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle));
LLSD sd = sd_full["regions"][0];
@ -267,7 +299,7 @@ namespace tut
it->setRegion(region1_handle);
LLSD sd = it->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd[0];
@ -292,7 +324,7 @@ namespace tut
LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
LLSD sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd["regions"][0];
@ -332,7 +364,7 @@ namespace tut
LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
ensure("Other collector is empty", is_no_stats_map(sd));
sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = sd["regions"][0];
@ -382,7 +414,7 @@ namespace tut
// std::cout << sd << std::endl;
ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
LLSD sd1 = get_region(sd, region1_handle);
LLSD sd2 = get_region(sd, region2_handle);
@ -405,7 +437,7 @@ namespace tut
// Reset leaves current region in place
gViewerAssetStatsMain->reset();
sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
sd2 = sd["regions"][0];
@ -454,7 +486,7 @@ namespace tut
LLSD sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
ensure("Correct double-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
LLSD sd1 = get_region(sd, region1_handle);
LLSD sd2 = get_region(sd, region2_handle);
@ -477,7 +509,7 @@ namespace tut
// Reset leaves current region in place
gViewerAssetStatsMain->reset();
sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "duration", "regions", "avatar"));
ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
sd2 = get_region(sd, region2_handle);
ensure("Region2 is present in results", sd2.isMap());
@ -523,7 +555,7 @@ namespace tut
LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
ensure("Other collector is empty", is_no_stats_map(sd));
sd = gViewerAssetStatsMain->asLLSD(false);
ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar"));
ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
sd = get_region(sd, region1_handle);
ensure("Region1 is present in results", sd.isMap());