diff options
author | Merov Linden <merov@lindenlab.com> | 2012-04-02 19:05:32 -0700 |
---|---|---|
committer | Merov Linden <merov@lindenlab.com> | 2012-04-02 19:05:32 -0700 |
commit | df09fd8e8b5b73330e4942c2cb218a216d7aca99 (patch) | |
tree | 7b945cde73ff1cc666c1f2b03d522452d2102eea | |
parent | 792943c211f90738e245b11e128525190ff1b107 (diff) |
SH-3060 : Preliminary implementation of the new byte range computation, implement setting to turn it on or off
-rw-r--r-- | indra/llimage/llimage.cpp | 4 | ||||
-rw-r--r-- | indra/llimage/llimage.h | 5 | ||||
-rw-r--r-- | indra/llimage/llimagej2c.cpp | 47 | ||||
-rw-r--r-- | indra/llkdu/llimagej2ckdu.cpp | 14 | ||||
-rwxr-xr-x | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 2 |
6 files changed, 47 insertions, 36 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 937655a22d..7f95441075 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -48,11 +48,13 @@ //static std::string LLImage::sLastErrorMessage; LLMutex* LLImage::sMutex = NULL; +bool LLImage::sUseNewByteRange = false; LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ; //static -void LLImage::initClass() +void LLImage::initClass(bool use_new_byte_range) { + sUseNewByteRange = use_new_byte_range; sMutex = new LLMutex(NULL); LLImageBase::createPrivatePool() ; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index eba8362f1c..b757547ab8 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -89,15 +89,18 @@ typedef enum e_image_codec class LLImage { public: - static void initClass(); + static void initClass(bool use_new_byte_range = false); static void cleanupClass(); static const std::string& getLastError(); static void setLastError(const std::string& message); + static bool useNewByteRange() { return sUseNewByteRange; } + protected: static LLMutex* sMutex; static std::string sLastErrorMessage; + static bool sUseNewByteRange; }; //============================================================================ diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index fbf4b769e1..cbb6f75b43 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -262,10 +262,12 @@ 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; + // Note: This provides an estimation for the first 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 + if (rate <= 0.f) rate = 1.f/8.f; + // Compute w/pow(2,discard_level) and h/pow(2,discard_level) while (discard_level > 0) { if (w < 1 || h < 1) @@ -274,7 +276,13 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r h >>= 1; discard_level--; } - S32 bytes = (S32)((F32)(w*h*comp)*rate); + // 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 + // *TODO: Replace the magic "7" by the number of quality layers in the j2c image + S32 bytes; + S32 new_bytes = sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/7.f; + S32 old_bytes = (S32)((F32)(w*h*comp)*rate); + bytes = (LLImage::useNewByteRange() ? new_bytes : old_bytes); bytes = llmax(bytes, calcHeaderSizeJ2C()); return bytes; } @@ -284,11 +292,7 @@ S32 LLImageJ2C::calcHeaderSize() return calcHeaderSizeJ2C(); } - -// calcDataSize() returns how many bytes to read -// to load discard_level (including header and higher discard levels) -// *TODO: This is deeply wrong. That size should be taken from the image file header or other -// relevant infos. In any case, this is only an approximation. +// 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); @@ -304,25 +308,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]; } @@ -337,8 +322,8 @@ 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); + if (bytes >= bytes_needed) { break; } diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index fdfab5506a..4468b8563b 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -294,6 +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(); + + //kdu_coords idx; idx.x = 0; idx.y = 0; + //kdu_dims tile_indices_in; + //mCodeStreamp->get_valid_tiles(tile_indices_in); + //mCodeStreamp->create_tile(idx+tile_indices_in.pos); + //int layers = mCodeStreamp->get_max_tile_layers(); + //llinfos << "Merov debug : setupCodeStream, levels = " << mLevels << ", layers = " << layers << llendl; // Set the base dimensions base.setSize(dims.size.x, dims.size.y, components); @@ -390,7 +397,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); @@ -468,6 +475,9 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco { kdu_tile tile = mCodeStreamp->open_tile(*(mTPosp)+mTileIndicesp->pos); + int layers = mCodeStreamp->get_max_tile_layers(); + llinfos << "Merov debug : decodeImpl, levels = " << mLevels << ", layers = " << layers << llendl; + // Find the region of the buffer occupied by this // tile. Note that we have no control over // sub-sampling factors which might have been used @@ -675,7 +685,7 @@ 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()); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9fff543b13..5fc9c5d863 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10686,6 +10686,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> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index bea8303d69..1a68d0317e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1947,7 +1947,7 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - LLImage::initClass(); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange")); LLVFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false); |