summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2012-04-02 19:05:32 -0700
committerMerov Linden <merov@lindenlab.com>2012-04-02 19:05:32 -0700
commitdf09fd8e8b5b73330e4942c2cb218a216d7aca99 (patch)
tree7b945cde73ff1cc666c1f2b03d522452d2102eea /indra
parent792943c211f90738e245b11e128525190ff1b107 (diff)
SH-3060 : Preliminary implementation of the new byte range computation, implement setting to turn it on or off
Diffstat (limited to 'indra')
-rw-r--r--indra/llimage/llimage.cpp4
-rw-r--r--indra/llimage/llimage.h5
-rw-r--r--indra/llimage/llimagej2c.cpp47
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp14
-rwxr-xr-xindra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llappviewer.cpp2
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);