diff options
Diffstat (limited to 'linden/indra')
-rw-r--r-- | linden/indra/newview/lltexturefetch.cpp | 159 | ||||
-rw-r--r-- | linden/indra/newview/lltexturefetch.h | 2 | ||||
-rw-r--r-- | linden/indra/newview/llvoavatar.cpp | 14 |
3 files changed, 134 insertions, 41 deletions
diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp index b5ad435..f63deb8 100644 --- a/linden/indra/newview/lltexturefetch.cpp +++ b/linden/indra/newview/lltexturefetch.cpp | |||
@@ -157,7 +157,7 @@ public: | |||
157 | 157 | ||
158 | void callbackHttpGet(const LLChannelDescriptors& channels, | 158 | void callbackHttpGet(const LLChannelDescriptors& channels, |
159 | const LLIOPipe::buffer_ptr_t& buffer, | 159 | const LLIOPipe::buffer_ptr_t& buffer, |
160 | bool last_block, bool success); | 160 | bool partial, bool unsatisfiable, bool success); |
161 | void callbackCacheRead(bool success, LLImageFormatted* image, | 161 | void callbackCacheRead(bool success, LLImageFormatted* image, |
162 | S32 imagesize, BOOL islocal); | 162 | S32 imagesize, BOOL islocal); |
163 | void callbackCacheWrite(bool success); | 163 | void callbackCacheWrite(bool success); |
@@ -317,13 +317,14 @@ public: | |||
317 | mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); | 317 | mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); |
318 | } | 318 | } |
319 | 319 | ||
320 | lldebugs << "HTTP COMPLETE: " << mID << llendl; | 320 | LL_DEBUGS("TextureFetch") << "HTTP COMPLETE: " << mID << " with status: " << status << LL_ENDL; |
321 | mFetcher->lockQueue(); | 321 | mFetcher->lockQueue(); |
322 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | 322 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); |
323 | if (worker) | 323 | if (worker) |
324 | { | 324 | { |
325 | bool success = false; | 325 | bool success = false; |
326 | bool partial = false; | 326 | bool partial = false; |
327 | bool unsatisfiable = false; | ||
327 | if (200 <= status && status < 300) | 328 | if (200 <= status && status < 300) |
328 | { | 329 | { |
329 | success = true; | 330 | success = true; |
@@ -332,18 +333,19 @@ public: | |||
332 | partial = true; | 333 | partial = true; |
333 | } | 334 | } |
334 | } | 335 | } |
335 | else | 336 | else if (status == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE) |
336 | { | 337 | { |
337 | worker->setGetStatus(status, reason); | 338 | LL_DEBUGS("TextureFetch") << "Request was an unsatisfiable range: mRequestedSize=" << mRequestedSize << " mOffset=" << mOffset << " for: " << mID << LL_ENDL; |
338 | // llwarns << status << ": " << reason << llendl; | 339 | unsatisfiable = true; |
339 | } | 340 | } |
341 | |||
340 | if (!success) | 342 | if (!success) |
341 | { | 343 | { |
342 | worker->setGetStatus(status, reason); | 344 | worker->setGetStatus(status, reason); |
343 | // llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; | 345 | // llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; |
344 | } | 346 | } |
345 | mFetcher->removeFromHTTPQueue(mID); | 347 | mFetcher->removeFromHTTPQueue(mID); |
346 | worker->callbackHttpGet(channels, buffer, partial, success); | 348 | worker->callbackHttpGet(channels, buffer, partial, unsatisfiable, success); |
347 | } | 349 | } |
348 | else | 350 | else |
349 | { | 351 | { |
@@ -870,6 +872,16 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
870 | return false; | 872 | return false; |
871 | } | 873 | } |
872 | } | 874 | } |
875 | |||
876 | // *TODO: remove this hack when not needed anymore | ||
877 | S32 buggy_range_fudge = 0; | ||
878 | if (LLTextureFetch::hasBuggyHTTPRange()) | ||
879 | { | ||
880 | buggy_range_fudge = 1; | ||
881 | resetFormattedData(); // discard any previous data we had | ||
882 | cur_size = 0 ; | ||
883 | } | ||
884 | |||
873 | mRequestedSize = mDesiredSize; | 885 | mRequestedSize = mDesiredSize; |
874 | mRequestedDiscard = mDesiredDiscard; | 886 | mRequestedDiscard = mDesiredDiscard; |
875 | mRequestedSize -= cur_size; | 887 | mRequestedSize -= cur_size; |
@@ -883,10 +895,11 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
883 | mLoaded = FALSE; | 895 | mLoaded = FALSE; |
884 | mGetStatus = 0; | 896 | mGetStatus = 0; |
885 | mGetReason.clear(); | 897 | mGetReason.clear(); |
886 | lldebugs << "HTTP GET: " << mID << " Offset: " << offset | 898 | LL_DEBUGS("TextureFetch") << "HTTP GET: " << mID << " Offset: " << offset |
887 | << " Bytes: " << mRequestedSize | 899 | << " Bytes: " << mRequestedSize |
900 | << " Range: " << offset << "-" << offset+mRequestedSize-1+buggy_range_fudge | ||
888 | << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth | 901 | << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth |
889 | << llendl; | 902 | << LL_ENDL; |
890 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | 903 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); |
891 | mState = WAIT_HTTP_REQ; | 904 | mState = WAIT_HTTP_REQ; |
892 | 905 | ||
@@ -894,7 +907,7 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
894 | // Will call callbackHttpGet when curl request completes | 907 | // Will call callbackHttpGet when curl request completes |
895 | std::vector<std::string> headers; | 908 | std::vector<std::string> headers; |
896 | headers.push_back("Accept: image/x-j2c"); | 909 | headers.push_back("Accept: image/x-j2c"); |
897 | res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, | 910 | res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize + buggy_range_fudge, |
898 | new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset)); | 911 | new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset)); |
899 | } | 912 | } |
900 | if (!res) | 913 | if (!res) |
@@ -1301,7 +1314,9 @@ bool LLTextureFetchWorker::processSimulatorPackets() | |||
1301 | 1314 | ||
1302 | void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, | 1315 | void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, |
1303 | const LLIOPipe::buffer_ptr_t& buffer, | 1316 | const LLIOPipe::buffer_ptr_t& buffer, |
1304 | bool last_block, bool success) | 1317 | bool partial, |
1318 | bool unsatisfiable, | ||
1319 | bool success) | ||
1305 | { | 1320 | { |
1306 | LLMutexLock lock(&mWorkMutex); | 1321 | LLMutexLock lock(&mWorkMutex); |
1307 | 1322 | ||
@@ -1316,56 +1331,91 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, | |||
1316 | llwarns << "Duplicate callback for " << mID.asString() << llendl; | 1331 | llwarns << "Duplicate callback for " << mID.asString() << llendl; |
1317 | return; // ignore duplicate callback | 1332 | return; // ignore duplicate callback |
1318 | } | 1333 | } |
1334 | |||
1335 | S32 data_size = 0; | ||
1319 | if (success) | 1336 | if (success) |
1320 | { | 1337 | { |
1321 | // get length of stream: | 1338 | // get length of stream: |
1322 | S32 data_size = buffer->countAfter(channels.in(), NULL); | 1339 | data_size = buffer->countAfter(channels.in(), NULL); |
1323 | 1340 | ||
1324 | gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits | 1341 | gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits |
1325 | 1342 | ||
1326 | //llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; | 1343 | LL_DEBUGS("TextureFetch") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << " mRequestedSize: " << mRequestedSize << LL_ENDL; |
1344 | |||
1327 | if (data_size > 0) | 1345 | if (data_size > 0) |
1328 | { | 1346 | { |
1329 | // *TODO: set the formatted image data here directly to avoid the copy | 1347 | bool clean_data = false; |
1330 | mBuffer = new U8[data_size]; | 1348 | bool done = false; |
1331 | buffer->readAfter(channels.in(), NULL, mBuffer, data_size); | 1349 | if (!partial) |
1332 | mBufferSize += data_size; | ||
1333 | if (data_size < mRequestedSize && | ||
1334 | (mRequestedDiscard == 0 || mRequestedSize >= MAX_IMAGE_DATA_SIZE) ) | ||
1335 | { | 1350 | { |
1336 | // We requested whole image (by discard or by size,) so assume we got it | 1351 | // we got the whole image in one go |
1337 | mHaveAllData = TRUE; | 1352 | done = true; |
1353 | clean_data = true; | ||
1354 | } | ||
1355 | else if (data_size < mRequestedSize) | ||
1356 | { | ||
1357 | // we have the whole image | ||
1358 | done = true; | ||
1359 | } | ||
1360 | else if (data_size == mRequestedSize) | ||
1361 | { | ||
1362 | if (mRequestedDiscard <= 0) | ||
1363 | { | ||
1364 | done = true; | ||
1365 | } | ||
1366 | else | ||
1367 | { | ||
1368 | // this is the normal case where we get the data we requested, | ||
1369 | // but still need to request more data. | ||
1370 | } | ||
1338 | } | 1371 | } |
1339 | else if (data_size > mRequestedSize) | 1372 | else if (data_size > mRequestedSize) |
1340 | { | 1373 | { |
1341 | // *TODO: This shouldn't be happening any more | 1374 | // *TODO: This shouldn't be happening any more |
1342 | llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; | 1375 | llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; |
1343 | mHaveAllData = TRUE; | 1376 | done = true; |
1377 | clean_data = true; | ||
1344 | llassert_always(mDecodeHandle == 0); | 1378 | llassert_always(mDecodeHandle == 0); |
1345 | mFormattedImage = NULL; // discard any previous data we had | ||
1346 | mBufferSize = data_size; | ||
1347 | } | 1379 | } |
1348 | mRequestedSize = data_size; | 1380 | |
1349 | } | 1381 | if (clean_data) |
1350 | else | ||
1351 | { | ||
1352 | // We requested data but received none (and no error), | ||
1353 | if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0) | ||
1354 | { | 1382 | { |
1355 | // but have earlier data, so presumably we have it all. | 1383 | resetFormattedData(); // discard any previous data we had |
1356 | mRequestedSize = 0; | 1384 | llassert(mBufferSize == 0); |
1357 | mHaveAllData = TRUE; | ||
1358 | } | 1385 | } |
1359 | else | 1386 | if (done) |
1360 | { | 1387 | { |
1361 | mRequestedSize = -1; // treat this fetch as if it failed. | 1388 | mHaveAllData = TRUE; |
1389 | mRequestedDiscard = 0; | ||
1362 | } | 1390 | } |
1391 | |||
1392 | // *TODO: set the formatted image data here directly to avoid the copy | ||
1393 | mBuffer = new U8[data_size]; | ||
1394 | buffer->readAfter(channels.in(), NULL, mBuffer, data_size); | ||
1395 | mBufferSize += data_size; | ||
1396 | mRequestedSize = data_size; | ||
1363 | } | 1397 | } |
1364 | } | 1398 | } |
1365 | else | 1399 | else |
1366 | { | 1400 | { |
1367 | mRequestedSize = -1; // error | 1401 | mRequestedSize = -1; // error |
1368 | } | 1402 | } |
1403 | |||
1404 | if ((success && (data_size == 0)) || unsatisfiable) | ||
1405 | { | ||
1406 | if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0) | ||
1407 | { | ||
1408 | // we already have some data, so we'll assume we have it all | ||
1409 | mRequestedSize = 0; | ||
1410 | mRequestedDiscard = 0; | ||
1411 | mHaveAllData = TRUE; | ||
1412 | } | ||
1413 | else | ||
1414 | { | ||
1415 | mRequestedSize = -1; // treat this fetch as if it failed. | ||
1416 | } | ||
1417 | } | ||
1418 | |||
1369 | mLoaded = TRUE; | 1419 | mLoaded = TRUE; |
1370 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | 1420 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); |
1371 | } | 1421 | } |
@@ -2220,3 +2270,44 @@ void LLTextureFetch::dump() | |||
2220 | } | 2270 | } |
2221 | } | 2271 | } |
2222 | 2272 | ||
2273 | // This tries to detect if the sim has this bug: | ||
2274 | // http://opensimulator.org/mantis/view.php?id=5081 | ||
2275 | // | ||
2276 | // *TODO: This is a *HACK and may not work if the grid is heterogenous. | ||
2277 | // Remove it once OpenSim versions in the wild are > 0.7.0.2! | ||
2278 | #include "hippoGridManager.h" | ||
2279 | #include <boost/regex.hpp> | ||
2280 | //static | ||
2281 | bool LLTextureFetch::hasBuggyHTTPRange() | ||
2282 | { | ||
2283 | static std::string s_version; | ||
2284 | static bool buggy = false; | ||
2285 | if ((s_version != gLastVersionChannel) && !gLastVersionChannel.empty()) | ||
2286 | { | ||
2287 | s_version = gLastVersionChannel; | ||
2288 | buggy = false; | ||
2289 | if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_OPENSIM) | ||
2290 | { | ||
2291 | std::string ver_string; | ||
2292 | try | ||
2293 | { | ||
2294 | const boost::regex re(".*OpenSim.*?([0-9.]+).+"); | ||
2295 | ver_string = regex_replace(s_version, re, "\\1", boost::match_default); | ||
2296 | } | ||
2297 | catch(std::runtime_error) | ||
2298 | { | ||
2299 | ver_string = "0.0"; | ||
2300 | } | ||
2301 | LLStringUtil::replaceChar(ver_string, '.', '0'); | ||
2302 | ver_string = "0." + ver_string; | ||
2303 | F64 version = atof(ver_string.c_str()); | ||
2304 | // we look for "0.6.8" < version < "0.7.0.3" | ||
2305 | if ((version > 0.00608) && (version < 0.0070003)) | ||
2306 | { | ||
2307 | buggy = true; | ||
2308 | llwarns << "Setting buggy http ranges mode for current sim, because we're on " << s_version << llendl; | ||
2309 | } | ||
2310 | } | ||
2311 | } | ||
2312 | return buggy; | ||
2313 | } | ||
diff --git a/linden/indra/newview/lltexturefetch.h b/linden/indra/newview/lltexturefetch.h index 6c6bb52..5fa2d1c 100644 --- a/linden/indra/newview/lltexturefetch.h +++ b/linden/indra/newview/lltexturefetch.h | |||
@@ -86,6 +86,8 @@ public: | |||
86 | 86 | ||
87 | LLTextureInfo* getTextureInfo() { return &mTextureInfo; } | 87 | LLTextureInfo* getTextureInfo() { return &mTextureInfo; } |
88 | 88 | ||
89 | static bool hasBuggyHTTPRange(); // *TODO: remove this *HACK once buggy OpenSim versions are gone | ||
90 | |||
89 | protected: | 91 | protected: |
90 | void addToNetworkQueue(LLTextureFetchWorker* worker); | 92 | void addToNetworkQueue(LLTextureFetchWorker* worker); |
91 | void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); | 93 | void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); |
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index 7bbaf48..9937ed9 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp | |||
@@ -5129,12 +5129,6 @@ void LLVOAvatar::updateTextures() | |||
5129 | if (texture_dict->mIsLocalTexture) | 5129 | if (texture_dict->mIsLocalTexture) |
5130 | { | 5130 | { |
5131 | addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); | 5131 | addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); |
5132 | // SNOW-8 : temporary snowglobe1.0 fix for baked textures | ||
5133 | if (render_avatar && !gGLManager.mIsDisabled ) | ||
5134 | { | ||
5135 | // bind the texture so that its boost level won't be slammed | ||
5136 | gGL.getTexUnit(0)->bind(imagep); | ||
5137 | } | ||
5138 | } | 5132 | } |
5139 | else if (texture_dict->mIsBakedTexture) | 5133 | else if (texture_dict->mIsBakedTexture) |
5140 | { | 5134 | { |
@@ -5171,8 +5165,14 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep, | |||
5171 | F32 desired_pixels; | 5165 | F32 desired_pixels; |
5172 | if( mIsSelf ) | 5166 | if( mIsSelf ) |
5173 | { | 5167 | { |
5174 | desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); | 5168 | desired_pixels = llmax(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); |
5175 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_AVATAR_SELF); | 5169 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_AVATAR_SELF); |
5170 | // SNOW-8 : temporary snowglobe1.0 fix for baked textures | ||
5171 | if (render_avatar && !gGLManager.mIsDisabled ) | ||
5172 | { | ||
5173 | // bind the texture so that its boost level won't be slammed | ||
5174 | gGL.getTexUnit(0)->bind(imagep); | ||
5175 | } | ||
5176 | } | 5176 | } |
5177 | else | 5177 | else |
5178 | { | 5178 | { |