diff options
author | Jacek Antonelli | 2010-02-09 21:11:42 -0600 |
---|---|---|
committer | Jacek Antonelli | 2010-02-16 18:50:15 -0600 |
commit | e6247fbe78c4d3dacb74f3b2359aba2b6538133b (patch) | |
tree | 10c42d670a2c635b4339f7f68809c221756774f8 /linden/indra/newview/lltexturefetch.cpp | |
parent | Ported some cURL and HTTP-related changes from Snowglobe. (diff) | |
download | meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.zip meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.gz meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.bz2 meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.xz |
Ported many texture engine changes from Snowglobe.
Diffstat (limited to 'linden/indra/newview/lltexturefetch.cpp')
-rw-r--r-- | linden/indra/newview/lltexturefetch.cpp | 1058 |
1 files changed, 599 insertions, 459 deletions
diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp index e9dd792..935b8cc 100644 --- a/linden/indra/newview/lltexturefetch.cpp +++ b/linden/indra/newview/lltexturefetch.cpp | |||
@@ -32,108 +32,35 @@ | |||
32 | 32 | ||
33 | #include "llviewerprecompiledheaders.h" | 33 | #include "llviewerprecompiledheaders.h" |
34 | 34 | ||
35 | #include <iostream> | ||
36 | |||
35 | #include "llstl.h" | 37 | #include "llstl.h" |
36 | 38 | ||
37 | #include "lltexturefetch.h" | 39 | #include "lltexturefetch.h" |
38 | 40 | ||
39 | #include "llcurl.h" | 41 | #include "llcurl.h" |
42 | #include "lldir.h" | ||
40 | #include "llhttpclient.h" | 43 | #include "llhttpclient.h" |
44 | #include "llhttpstatuscodes.h" | ||
41 | #include "llimage.h" | 45 | #include "llimage.h" |
42 | #include "llimageworker.h" | 46 | #include "llimageworker.h" |
43 | #include "llworkerthread.h" | 47 | #include "llworkerthread.h" |
44 | 48 | ||
45 | #include "llagent.h" | 49 | #include "llagent.h" |
46 | #include "lltexturecache.h" | 50 | #include "lltexturecache.h" |
51 | #include "llviewercontrol.h" | ||
47 | #include "llviewerimagelist.h" | 52 | #include "llviewerimagelist.h" |
48 | #include "llviewerimage.h" | 53 | #include "llviewerimage.h" |
49 | #include "llviewerregion.h" | 54 | #include "llviewerregion.h" |
55 | #include "llworld.h" | ||
50 | 56 | ||
51 | ////////////////////////////////////////////////////////////////////////////// | 57 | ////////////////////////////////////////////////////////////////////////////// |
52 | //static | ||
53 | class LLTextureFetchWorker : public LLWorkerClass | 58 | class LLTextureFetchWorker : public LLWorkerClass |
54 | { | 59 | { |
55 | friend class LLTextureFetch; | 60 | friend class LLTextureFetch; |
56 | 61 | friend class HTTPGetResponder; | |
57 | private: | ||
58 | #if 0 | ||
59 | class URLResponder : public LLHTTPClient::Responder | ||
60 | { | ||
61 | public: | ||
62 | URLResponder(LLTextureFetch* fetcher, const LLUUID& id) | ||
63 | : mFetcher(fetcher), mID(id) | ||
64 | { | ||
65 | } | ||
66 | ~URLResponder() | ||
67 | { | ||
68 | } | ||
69 | virtual void error(U32 status, const std::string& reason) | ||
70 | { | ||
71 | mFetcher->lockQueue(); | ||
72 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | ||
73 | if (worker) | ||
74 | { | ||
75 | // llwarns << "LLTextureFetchWorker::URLResponder::error " << status << ": " << reason << llendl; | ||
76 | worker->callbackURLReceived(LLSD(), false); | ||
77 | } | ||
78 | mFetcher->unlockQueue(); | ||
79 | } | ||
80 | virtual void result(const LLSD& content) | ||
81 | { | ||
82 | mFetcher->lockQueue(); | ||
83 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | ||
84 | if (worker) | ||
85 | { | ||
86 | worker->callbackURLReceived(content, true); | ||
87 | } | ||
88 | mFetcher->unlockQueue(); | ||
89 | } | ||
90 | private: | ||
91 | LLTextureFetch* mFetcher; | ||
92 | LLUUID mID; | ||
93 | }; | ||
94 | |||
95 | class HTTPGetResponder : public LLHTTPClient::Responder | ||
96 | { | ||
97 | public: | ||
98 | HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id) | ||
99 | : mFetcher(fetcher), mID(id) | ||
100 | { | ||
101 | } | ||
102 | ~HTTPGetResponder() | ||
103 | { | ||
104 | } | ||
105 | virtual void completed(U32 status, const std::stringstream& content) | ||
106 | { | ||
107 | mFetcher->lockQueue(); | ||
108 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | ||
109 | if (worker) | ||
110 | { | ||
111 | const std::string& cstr = content.str(); | ||
112 | if (200 <= status && status < 300) | ||
113 | { | ||
114 | if (203 == status) // partial information (i.e. last block) | ||
115 | { | ||
116 | worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), true); | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), false); | ||
121 | } | ||
122 | } | ||
123 | else | ||
124 | { | ||
125 | // llinfos << "LLTextureFetchWorker::HTTPGetResponder::error " << status << ": " << cstr << llendl; | ||
126 | worker->callbackHttpGet(NULL, -1, true); | ||
127 | } | ||
128 | } | ||
129 | mFetcher->unlockQueue(); | ||
130 | } | ||
131 | private: | ||
132 | LLTextureFetch* mFetcher; | ||
133 | LLUUID mID; | ||
134 | }; | ||
135 | #endif | ||
136 | 62 | ||
63 | private: | ||
137 | class CacheReadResponder : public LLTextureCache::ReadResponder | 64 | class CacheReadResponder : public LLTextureCache::ReadResponder |
138 | { | 65 | { |
139 | public: | 66 | public: |
@@ -179,20 +106,20 @@ private: | |||
179 | LLUUID mID; | 106 | LLUUID mID; |
180 | }; | 107 | }; |
181 | 108 | ||
182 | class DecodeResponder : public LLResponder | 109 | class DecodeResponder : public LLImageDecodeThread::Responder |
183 | { | 110 | { |
184 | public: | 111 | public: |
185 | DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker) | 112 | DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker) |
186 | : mFetcher(fetcher), mID(id), mWorker(worker) | 113 | : mFetcher(fetcher), mID(id), mWorker(worker) |
187 | { | 114 | { |
188 | } | 115 | } |
189 | virtual void completed(bool success) | 116 | virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) |
190 | { | 117 | { |
191 | mFetcher->lockQueue(); | 118 | mFetcher->lockQueue(); |
192 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | 119 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); |
193 | if (worker) | 120 | if (worker) |
194 | { | 121 | { |
195 | worker->callbackDecoded(success); | 122 | worker->callbackDecoded(success, raw, aux); |
196 | } | 123 | } |
197 | mFetcher->unlockQueue(); | 124 | mFetcher->unlockQueue(); |
198 | } | 125 | } |
@@ -225,39 +152,47 @@ public: | |||
225 | /*virtual*/ bool deleteOK(); // called from update() (WORK THREAD) | 152 | /*virtual*/ bool deleteOK(); // called from update() (WORK THREAD) |
226 | 153 | ||
227 | ~LLTextureFetchWorker(); | 154 | ~LLTextureFetchWorker(); |
228 | void relese() { --mActiveCount; } | 155 | void release() { --mActiveCount; } |
156 | |||
157 | void callbackHttpGet(const LLChannelDescriptors& channels, | ||
158 | const LLIOPipe::buffer_ptr_t& buffer, | ||
159 | bool last_block, bool success); | ||
160 | void callbackCacheRead(bool success, LLImageFormatted* image, | ||
161 | S32 imagesize, BOOL islocal); | ||
162 | void callbackCacheWrite(bool success); | ||
163 | void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); | ||
164 | |||
165 | void setGetStatus(U32 status, const std::string& reason) | ||
166 | { | ||
167 | mGetStatus = status; | ||
168 | mGetReason = reason; | ||
169 | } | ||
229 | 170 | ||
230 | protected: | 171 | protected: |
231 | LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host, | 172 | LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host, |
232 | F32 priority, S32 discard, S32 size); | 173 | F32 priority, S32 discard, S32 size); |
174 | LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, | ||
175 | F32 priority, S32 discard, S32 size); | ||
233 | 176 | ||
234 | private: | 177 | private: |
235 | /*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD) | 178 | /*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD) |
236 | /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) | 179 | /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) |
237 | 180 | ||
238 | virtual std::string getName() { return LLStringUtil::null; } | ||
239 | void resetFormattedData(); | 181 | void resetFormattedData(); |
240 | 182 | ||
241 | void setImagePriority(F32 priority); | 183 | void setImagePriority(F32 priority); |
242 | void setDesiredDiscard(S32 discard, S32 size); | 184 | void setDesiredDiscard(S32 discard, S32 size); |
243 | bool insertPacket(S32 index, U8* data, S32 size); | 185 | bool insertPacket(S32 index, U8* data, S32 size); |
244 | void clearPackets(); | 186 | void clearPackets(); |
187 | void setupPacketData(); | ||
245 | U32 calcWorkPriority(); | 188 | U32 calcWorkPriority(); |
246 | void removeFromCache(); | 189 | void removeFromCache(); |
247 | bool processSimulatorPackets(); | 190 | bool processSimulatorPackets(); |
248 | bool decodeImage(); | ||
249 | bool writeToCacheComplete(); | 191 | bool writeToCacheComplete(); |
250 | 192 | ||
251 | void lockWorkData() { mWorkMutex.lock(); } | 193 | void lockWorkMutex() { mWorkMutex.lock(); } |
252 | void unlockWorkData() { mWorkMutex.unlock(); } | 194 | void unlockWorkMutex() { mWorkMutex.unlock(); } |
253 | 195 | ||
254 | void callbackURLReceived(const LLSD& data, bool success); | ||
255 | void callbackHttpGet(U8* data, S32 data_size, bool last_block); | ||
256 | void callbackCacheRead(bool success, LLImageFormatted* image, | ||
257 | S32 imagesize, BOOL islocal); | ||
258 | void callbackCacheWrite(bool success); | ||
259 | void callbackDecoded(bool success); | ||
260 | |||
261 | private: | 196 | private: |
262 | enum e_state // mState | 197 | enum e_state // mState |
263 | { | 198 | { |
@@ -268,8 +203,8 @@ private: | |||
268 | CACHE_POST, | 203 | CACHE_POST, |
269 | LOAD_FROM_NETWORK, | 204 | LOAD_FROM_NETWORK, |
270 | LOAD_FROM_SIMULATOR, | 205 | LOAD_FROM_SIMULATOR, |
271 | LOAD_FROM_HTTP_GET_URL, | 206 | SEND_HTTP_REQ, |
272 | LOAD_FROM_HTTP_GET_DATA, | 207 | WAIT_HTTP_REQ, |
273 | DECODE_IMAGE, | 208 | DECODE_IMAGE, |
274 | DECODE_IMAGE_UPDATE, | 209 | DECODE_IMAGE_UPDATE, |
275 | WRITE_TO_CACHE, | 210 | WRITE_TO_CACHE, |
@@ -280,19 +215,17 @@ private: | |||
280 | { | 215 | { |
281 | UNSENT = 0, | 216 | UNSENT = 0, |
282 | QUEUED = 1, | 217 | QUEUED = 1, |
283 | SENT_SIM = 2, | 218 | SENT_SIM = 2 |
284 | SENT_URL = 3, | ||
285 | SENT_HTTP = 4 | ||
286 | }; | 219 | }; |
287 | static const char* sStateDescs[]; | 220 | static const char* sStateDescs[]; |
288 | e_state mState; | 221 | e_state mState; |
289 | LLTextureFetch* mFetcher; | 222 | LLTextureFetch* mFetcher; |
290 | LLImageWorker* mImageWorker; | ||
291 | LLPointer<LLImageFormatted> mFormattedImage; | 223 | LLPointer<LLImageFormatted> mFormattedImage; |
292 | LLPointer<LLImageRaw> mRawImage; | 224 | LLPointer<LLImageRaw> mRawImage; |
293 | LLPointer<LLImageRaw> mAuxImage; | 225 | LLPointer<LLImageRaw> mAuxImage; |
294 | LLUUID mID; | 226 | LLUUID mID; |
295 | LLHost mHost; | 227 | LLHost mHost; |
228 | std::string mUrl; | ||
296 | U8 mType; | 229 | U8 mType; |
297 | F32 mImagePriority; | 230 | F32 mImagePriority; |
298 | U32 mWorkPriority; | 231 | U32 mWorkPriority; |
@@ -314,15 +247,18 @@ private: | |||
314 | S32 mCachedSize; | 247 | S32 mCachedSize; |
315 | BOOL mLoaded; | 248 | BOOL mLoaded; |
316 | e_request_state mSentRequest; | 249 | e_request_state mSentRequest; |
250 | handle_t mDecodeHandle; | ||
317 | BOOL mDecoded; | 251 | BOOL mDecoded; |
318 | BOOL mWritten; | 252 | BOOL mWritten; |
319 | BOOL mNeedsAux; | 253 | BOOL mNeedsAux; |
320 | BOOL mHaveAllData; | 254 | BOOL mHaveAllData; |
321 | BOOL mInLocalCache; | 255 | BOOL mInLocalCache; |
256 | S32 mHTTPFailCount; | ||
322 | S32 mRetryAttempt; | 257 | S32 mRetryAttempt; |
323 | std::string mURL; | ||
324 | S32 mActiveCount; | 258 | S32 mActiveCount; |
325 | 259 | U32 mGetStatus; | |
260 | std::string mGetReason; | ||
261 | |||
326 | // Work Data | 262 | // Work Data |
327 | LLMutex mWorkMutex; | 263 | LLMutex mWorkMutex; |
328 | struct PacketData | 264 | struct PacketData |
@@ -340,25 +276,79 @@ private: | |||
340 | U8 mImageCodec; | 276 | U8 mImageCodec; |
341 | }; | 277 | }; |
342 | 278 | ||
343 | class LLTextureFetchLocalFileWorker : public LLTextureFetchWorker | 279 | ////////////////////////////////////////////////////////////////////////////// |
344 | { | ||
345 | friend class LLTextureFetch; | ||
346 | |||
347 | protected: | ||
348 | LLTextureFetchLocalFileWorker(LLTextureFetch* fetcher, const std::string& filename, const LLUUID& id, const LLHost& host, | ||
349 | F32 priority, S32 discard, S32 size) | ||
350 | : LLTextureFetchWorker(fetcher, id, host, priority, discard, size), | ||
351 | mFileName(filename) | ||
352 | {} | ||
353 | 280 | ||
354 | private: | 281 | class HTTPGetResponder : public LLCurl::Responder |
355 | /*virtual*/ std::string getName() { return mFileName; } | 282 | { |
283 | LOG_CLASS(HTTPGetResponder); | ||
284 | public: | ||
285 | HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) | ||
286 | : mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset) | ||
287 | { | ||
288 | } | ||
289 | ~HTTPGetResponder() | ||
290 | { | ||
291 | } | ||
356 | 292 | ||
293 | virtual void completedRaw(U32 status, const std::string& reason, | ||
294 | const LLChannelDescriptors& channels, | ||
295 | const LLIOPipe::buffer_ptr_t& buffer) | ||
296 | { | ||
297 | if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) | ||
298 | { | ||
299 | mFetcher->mTextureInfo.setRequestStartTime(mID, mStartTime); | ||
300 | U64 timeNow = LLTimer::getTotalTime(); | ||
301 | mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); | ||
302 | mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); | ||
303 | mFetcher->mTextureInfo.setRequestOffset(mID, mOffset); | ||
304 | mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); | ||
305 | } | ||
357 | 306 | ||
307 | lldebugs << "HTTP COMPLETE: " << mID << llendl; | ||
308 | mFetcher->lockQueue(); | ||
309 | LLTextureFetchWorker* worker = mFetcher->getWorker(mID); | ||
310 | if (worker) | ||
311 | { | ||
312 | bool success = false; | ||
313 | bool partial = false; | ||
314 | if (200 <= status && status < 300) | ||
315 | { | ||
316 | success = true; | ||
317 | if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block) | ||
318 | { | ||
319 | partial = true; | ||
320 | } | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | worker->setGetStatus(status, reason); | ||
325 | // llwarns << status << ": " << reason << llendl; | ||
326 | } | ||
327 | if (!success) | ||
328 | { | ||
329 | worker->setGetStatus(status, reason); | ||
330 | // llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; | ||
331 | } | ||
332 | mFetcher->removeFromHTTPQueue(mID); | ||
333 | worker->callbackHttpGet(channels, buffer, partial, success); | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | mFetcher->removeFromHTTPQueue(mID); | ||
338 | llwarns << "Worker not found: " << mID << llendl; | ||
339 | } | ||
340 | mFetcher->unlockQueue(); | ||
341 | } | ||
342 | |||
358 | private: | 343 | private: |
359 | std::string mFileName; | 344 | LLTextureFetch* mFetcher; |
345 | LLUUID mID; | ||
346 | U64 mStartTime; | ||
347 | S32 mRequestedSize; | ||
348 | U32 mOffset; | ||
360 | }; | 349 | }; |
361 | 350 | ||
351 | ////////////////////////////////////////////////////////////////////////////// | ||
362 | 352 | ||
363 | //static | 353 | //static |
364 | const char* LLTextureFetchWorker::sStateDescs[] = { | 354 | const char* LLTextureFetchWorker::sStateDescs[] = { |
@@ -368,8 +358,8 @@ const char* LLTextureFetchWorker::sStateDescs[] = { | |||
368 | "CACHE_POST", | 358 | "CACHE_POST", |
369 | "LOAD_FROM_NETWORK", | 359 | "LOAD_FROM_NETWORK", |
370 | "LOAD_FROM_SIMULATOR", | 360 | "LOAD_FROM_SIMULATOR", |
371 | "LOAD_FROM_HTTP_URL", | 361 | "SEND_HTTP_REQ", |
372 | "LOAD_FROM_HTTP_DATA", | 362 | "WAIT_HTTP_REQ", |
373 | "DECODE_IMAGE", | 363 | "DECODE_IMAGE", |
374 | "DECODE_IMAGE_UPDATE", | 364 | "DECODE_IMAGE_UPDATE", |
375 | "WRITE_TO_CACHE", | 365 | "WRITE_TO_CACHE", |
@@ -380,6 +370,7 @@ const char* LLTextureFetchWorker::sStateDescs[] = { | |||
380 | // called from MAIN THREAD | 370 | // called from MAIN THREAD |
381 | 371 | ||
382 | LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, | 372 | LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, |
373 | const std::string& url, // Optional URL | ||
383 | const LLUUID& id, // Image UUID | 374 | const LLUUID& id, // Image UUID |
384 | const LLHost& host, // Simulator host | 375 | const LLHost& host, // Simulator host |
385 | F32 priority, // Priority | 376 | F32 priority, // Priority |
@@ -388,9 +379,9 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, | |||
388 | : LLWorkerClass(fetcher, "TextureFetch"), | 379 | : LLWorkerClass(fetcher, "TextureFetch"), |
389 | mState(INIT), | 380 | mState(INIT), |
390 | mFetcher(fetcher), | 381 | mFetcher(fetcher), |
391 | mImageWorker(NULL), | ||
392 | mID(id), | 382 | mID(id), |
393 | mHost(host), | 383 | mHost(host), |
384 | mUrl(url), | ||
394 | mImagePriority(priority), | 385 | mImagePriority(priority), |
395 | mWorkPriority(0), | 386 | mWorkPriority(0), |
396 | mRequestedPriority(0.f), | 387 | mRequestedPriority(0.f), |
@@ -409,13 +400,16 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, | |||
409 | mCachedSize(0), | 400 | mCachedSize(0), |
410 | mLoaded(FALSE), | 401 | mLoaded(FALSE), |
411 | mSentRequest(UNSENT), | 402 | mSentRequest(UNSENT), |
403 | mDecodeHandle(0), | ||
412 | mDecoded(FALSE), | 404 | mDecoded(FALSE), |
413 | mWritten(FALSE), | 405 | mWritten(FALSE), |
414 | mNeedsAux(FALSE), | 406 | mNeedsAux(FALSE), |
415 | mHaveAllData(FALSE), | 407 | mHaveAllData(FALSE), |
416 | mInLocalCache(FALSE), | 408 | mInLocalCache(FALSE), |
409 | mHTTPFailCount(0), | ||
417 | mRetryAttempt(0), | 410 | mRetryAttempt(0), |
418 | mActiveCount(0), | 411 | mActiveCount(0), |
412 | mGetStatus(0), | ||
419 | mWorkMutex(NULL), | 413 | mWorkMutex(NULL), |
420 | mFirstPacket(0), | 414 | mFirstPacket(0), |
421 | mLastPacket(-1), | 415 | mLastPacket(-1), |
@@ -425,12 +419,14 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, | |||
425 | calcWorkPriority(); | 419 | calcWorkPriority(); |
426 | mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; | 420 | mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; |
427 | // llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << llendl; | 421 | // llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << llendl; |
422 | lockWorkMutex(); | ||
428 | if (!mFetcher->mDebugPause) | 423 | if (!mFetcher->mDebugPause) |
429 | { | 424 | { |
430 | U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; | 425 | U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; |
431 | addWork(0, work_priority ); | 426 | addWork(0, work_priority ); |
432 | } | 427 | } |
433 | setDesiredDiscard(discard, size); | 428 | setDesiredDiscard(discard, size); |
429 | unlockWorkMutex(); | ||
434 | } | 430 | } |
435 | 431 | ||
436 | LLTextureFetchWorker::~LLTextureFetchWorker() | 432 | LLTextureFetchWorker::~LLTextureFetchWorker() |
@@ -440,7 +436,7 @@ LLTextureFetchWorker::~LLTextureFetchWorker() | |||
440 | // << " Requested=" << mRequestedDiscard | 436 | // << " Requested=" << mRequestedDiscard |
441 | // << " Desired=" << mDesiredDiscard << llendl; | 437 | // << " Desired=" << mDesiredDiscard << llendl; |
442 | llassert_always(!haveWork()); | 438 | llassert_always(!haveWork()); |
443 | lockWorkData(); | 439 | lockWorkMutex(); |
444 | if (mCacheReadHandle != LLTextureCache::nullHandle()) | 440 | if (mCacheReadHandle != LLTextureCache::nullHandle()) |
445 | { | 441 | { |
446 | mFetcher->mTextureCache->readComplete(mCacheReadHandle, true); | 442 | mFetcher->mTextureCache->readComplete(mCacheReadHandle, true); |
@@ -449,13 +445,9 @@ LLTextureFetchWorker::~LLTextureFetchWorker() | |||
449 | { | 445 | { |
450 | mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true); | 446 | mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true); |
451 | } | 447 | } |
452 | if (mImageWorker) | ||
453 | { | ||
454 | mImageWorker->scheduleDelete(); | ||
455 | } | ||
456 | mFormattedImage = NULL; | 448 | mFormattedImage = NULL; |
457 | clearPackets(); | 449 | clearPackets(); |
458 | unlockWorkData(); | 450 | unlockWorkMutex(); |
459 | } | 451 | } |
460 | 452 | ||
461 | void LLTextureFetchWorker::clearPackets() | 453 | void LLTextureFetchWorker::clearPackets() |
@@ -467,6 +459,38 @@ void LLTextureFetchWorker::clearPackets() | |||
467 | mFirstPacket = 0; | 459 | mFirstPacket = 0; |
468 | } | 460 | } |
469 | 461 | ||
462 | void LLTextureFetchWorker::setupPacketData() | ||
463 | { | ||
464 | S32 data_size = 0; | ||
465 | if (mFormattedImage.notNull()) | ||
466 | { | ||
467 | data_size = mFormattedImage->getDataSize(); | ||
468 | } | ||
469 | if (data_size > 0) | ||
470 | { | ||
471 | // Only used for simulator requests | ||
472 | mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; | ||
473 | if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) | ||
474 | { | ||
475 | llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl; | ||
476 | removeFromCache(); | ||
477 | resetFormattedData(); | ||
478 | clearPackets(); | ||
479 | } | ||
480 | else if (mFileSize > 0) | ||
481 | { | ||
482 | mLastPacket = mFirstPacket-1; | ||
483 | mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | // This file was cached using HTTP so we have to refetch the first packet | ||
488 | resetFormattedData(); | ||
489 | clearPackets(); | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
470 | U32 LLTextureFetchWorker::calcWorkPriority() | 494 | U32 LLTextureFetchWorker::calcWorkPriority() |
471 | { | 495 | { |
472 | // llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerImage::maxDecodePriority()); | 496 | // llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerImage::maxDecodePriority()); |
@@ -538,7 +562,6 @@ void LLTextureFetchWorker::resetFormattedData() | |||
538 | // Called from MAIN thread | 562 | // Called from MAIN thread |
539 | void LLTextureFetchWorker::startWork(S32 param) | 563 | void LLTextureFetchWorker::startWork(S32 param) |
540 | { | 564 | { |
541 | llassert(mImageWorker == NULL); | ||
542 | llassert(mFormattedImage.isNull()); | 565 | llassert(mFormattedImage.isNull()); |
543 | } | 566 | } |
544 | 567 | ||
@@ -549,6 +572,14 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
549 | { | 572 | { |
550 | LLMutexLock lock(&mWorkMutex); | 573 | LLMutexLock lock(&mWorkMutex); |
551 | 574 | ||
575 | if ((mFetcher->isQuitting() || (mImagePriority <= 0.0f) || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) | ||
576 | { | ||
577 | if (mState < WRITE_TO_CACHE) | ||
578 | { | ||
579 | return true; // abort | ||
580 | } | ||
581 | } | ||
582 | |||
552 | if (mFetcher->mDebugPause) | 583 | if (mFetcher->mDebugPause) |
553 | { | 584 | { |
554 | return false; // debug: don't do any work | 585 | return false; // debug: don't do any work |
@@ -563,14 +594,6 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
563 | mFetchTimer.reset(); | 594 | mFetchTimer.reset(); |
564 | } | 595 | } |
565 | 596 | ||
566 | if (mImagePriority <= 0.0f) | ||
567 | { | ||
568 | if (mState < WRITE_TO_CACHE) | ||
569 | { | ||
570 | return true; // cancel request | ||
571 | } | ||
572 | } | ||
573 | |||
574 | if (mState == INIT) | 597 | if (mState == INIT) |
575 | { | 598 | { |
576 | mRequestedDiscard = -1; | 599 | mRequestedDiscard = -1; |
@@ -590,7 +613,6 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
590 | clearPackets(); // TODO: Shouldn't be necessary | 613 | clearPackets(); // TODO: Shouldn't be necessary |
591 | mCacheReadHandle = LLTextureCache::nullHandle(); | 614 | mCacheReadHandle = LLTextureCache::nullHandle(); |
592 | mCacheWriteHandle = LLTextureCache::nullHandle(); | 615 | mCacheWriteHandle = LLTextureCache::nullHandle(); |
593 | mURL.clear(); | ||
594 | mState = LOAD_FROM_TEXTURE_CACHE; | 616 | mState = LOAD_FROM_TEXTURE_CACHE; |
595 | // fall through | 617 | // fall through |
596 | } | 618 | } |
@@ -612,16 +634,27 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
612 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it | 634 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it |
613 | 635 | ||
614 | CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); | 636 | CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); |
615 | if (getName().empty()) | 637 | if (mUrl.compare(0, 7, "file://") == 0) |
638 | { | ||
639 | // read file from local disk | ||
640 | std::string filename = mUrl.substr(7, std::string::npos); | ||
641 | mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, | ||
642 | offset, size, responder); | ||
643 | } | ||
644 | else if (mUrl.empty()) | ||
616 | { | 645 | { |
617 | mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, | 646 | mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, |
618 | offset, size, responder); | 647 | offset, size, responder); |
619 | } | 648 | } |
620 | else | 649 | else |
621 | { | 650 | { |
622 | // read file from local disk | 651 | if (!(mUrl.compare(0, 7, "http://") == 0)) |
623 | mCacheReadHandle = mFetcher->mTextureCache->readFromCache(getName(), mID, cache_priority, | 652 | { |
624 | offset, size, responder); | 653 | // *TODO:?remove this warning |
654 | llwarns << "Unknown URL Type: " << mUrl << llendl; | ||
655 | } | ||
656 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
657 | mState = SEND_HTTP_REQ; | ||
625 | } | 658 | } |
626 | } | 659 | } |
627 | 660 | ||
@@ -659,67 +692,92 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
659 | } | 692 | } |
660 | else | 693 | else |
661 | { | 694 | { |
662 | if (!getName().empty()) | 695 | if (mUrl.compare(0, 7, "file://") == 0) |
663 | { | 696 | { |
664 | // failed to load local file, we're done. | 697 | // failed to load local file, we're done. |
665 | return true; | 698 | return true; |
666 | } | 699 | } |
667 | // need more data | 700 | // need more data |
668 | mState = LOAD_FROM_NETWORK; | 701 | else |
702 | { | ||
703 | mState = LOAD_FROM_NETWORK; // CACHE_POST --> LOAD_FROM_NETWORK, or SEND_HTTP_REQ see below. | ||
704 | // This is true because mSentRequest is set to UNSENT in INIT and if we get here we went through | ||
705 | // the states INIT --> LOAD_FROM_TEXTURE_CACHE --> CACHE_POST. Therefore either | ||
706 | // mFetcher->addToNetworkQueue(this) is called below, or mState is set to SEND_HTTP_REQ. | ||
707 | llassert(mSentRequest == UNSENT); | ||
708 | } | ||
669 | // fall through | 709 | // fall through |
670 | } | 710 | } |
671 | } | 711 | } |
672 | 712 | ||
673 | if (mState == LOAD_FROM_NETWORK) | 713 | if (mState == LOAD_FROM_NETWORK) |
674 | { | 714 | { |
675 | if (mSentRequest == UNSENT) | 715 | bool get_url = gSavedSettings.getBOOL("ImagePipelineUseHTTP"); |
716 | if (!mUrl.empty()) get_url = false; | ||
717 | // if (mHost != LLHost::invalid) get_url = false; | ||
718 | if ( get_url ) | ||
676 | { | 719 | { |
677 | if (mFormattedImage.isNull()) | 720 | LLViewerRegion* region = NULL; |
678 | { | 721 | if (mHost == LLHost::invalid) |
679 | mFormattedImage = new LLImageJ2C; | 722 | region = gAgent.getRegion(); |
680 | } | 723 | else |
681 | // Add this to the network queue and sit here. | 724 | region = LLWorld::getInstance()->getRegion(mHost); |
682 | // LLTextureFetch::update() will send off a request which will change our state | 725 | |
683 | S32 data_size = mFormattedImage->getDataSize(); | 726 | if (region) |
684 | if (data_size > 0) | ||
685 | { | 727 | { |
686 | // Only used for simulator requests | 728 | std::string http_url = region->getCapability("GetTexture"); |
687 | mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; | 729 | if (!http_url.empty()) |
688 | if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) | ||
689 | { | ||
690 | // llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl; | ||
691 | removeFromCache(); | ||
692 | resetFormattedData(); | ||
693 | clearPackets(); | ||
694 | } | ||
695 | else | ||
696 | { | 730 | { |
697 | mLastPacket = mFirstPacket-1; | 731 | mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); |
698 | mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; | ||
699 | } | 732 | } |
700 | } | 733 | } |
734 | else | ||
735 | { | ||
736 | llwarns << "Region not found for host: " << mHost << llendl; | ||
737 | } | ||
738 | } | ||
739 | if (!mUrl.empty()) | ||
740 | { | ||
741 | mState = LLTextureFetchWorker::SEND_HTTP_REQ; | ||
742 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
743 | // don't return, fall through to next state | ||
744 | } | ||
745 | else if (mSentRequest == UNSENT) | ||
746 | { | ||
747 | // Add this to the network queue and sit here. | ||
748 | // LLTextureFetch::update() will send off a request which will change our state | ||
701 | mRequestedSize = mDesiredSize; | 749 | mRequestedSize = mDesiredSize; |
702 | mRequestedDiscard = mDesiredDiscard; | 750 | mRequestedDiscard = mDesiredDiscard; |
703 | mSentRequest = QUEUED; | 751 | mSentRequest = QUEUED; |
704 | mFetcher->lockQueue(); | ||
705 | mFetcher->addToNetworkQueue(this); | 752 | mFetcher->addToNetworkQueue(this); |
706 | mFetcher->unlockQueue(); | ||
707 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | 753 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); |
754 | return false; | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | // Shouldn't need to do anything here | ||
759 | //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); | ||
760 | // Make certain this is in the network queue | ||
761 | //mFetcher->addToNetworkQueue(this); | ||
762 | //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
763 | return false; | ||
708 | } | 764 | } |
709 | return false; | ||
710 | } | 765 | } |
711 | 766 | ||
712 | if (mState == LOAD_FROM_SIMULATOR) | 767 | if (mState == LOAD_FROM_SIMULATOR) |
713 | { | 768 | { |
769 | if (mFormattedImage.isNull()) | ||
770 | { | ||
771 | mFormattedImage = new LLImageJ2C; | ||
772 | } | ||
714 | if (processSimulatorPackets()) | 773 | if (processSimulatorPackets()) |
715 | { | 774 | { |
716 | mFetcher->lockQueue(); | 775 | mFetcher->removeFromNetworkQueue(this, false); |
717 | mFetcher->removeFromNetworkQueue(this); | ||
718 | mFetcher->unlockQueue(); | ||
719 | if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) | 776 | if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) |
720 | { | 777 | { |
721 | // processSimulatorPackets() failed | 778 | // processSimulatorPackets() failed |
722 | // llwarns << "processSimulatorPackets() failed to load buffer" << llendl; | 779 | // llwarns << "processSimulatorPackets() failed to load buffer" << llendl; |
780 | // FIXME: Don't we need a mState change? | ||
723 | return true; // failed | 781 | return true; // failed |
724 | } | 782 | } |
725 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | 783 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); |
@@ -732,103 +790,91 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
732 | return false; | 790 | return false; |
733 | } | 791 | } |
734 | 792 | ||
735 | #if 0 | 793 | if (mState == SEND_HTTP_REQ) |
736 | if (mState == LOAD_FROM_HTTP_GET_URL) | 794 | { |
737 | { | 795 | { |
738 | if (!mSentRequest) | 796 | const S32 HTTP_QUEUE_MAX_SIZE = 32; |
739 | { | 797 | // *TODO: Integrate this with llviewerthrottle |
740 | mSentRequest = TRUE; | 798 | // Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP, |
741 | mLoaded = FALSE; | 799 | // but probably not for Textures. |
742 | std::string url; | 800 | // Set the throttle to the entire bandwidth, assuming UDP packets will get priority |
743 | LLViewerRegion* region = gAgent.getRegion(); | 801 | // when they are needed |
744 | if (region) | 802 | F32 max_bandwidth = mFetcher->mMaxBandwidth; |
803 | if ((mFetcher->getHTTPQueueSize() >= HTTP_QUEUE_MAX_SIZE) || | ||
804 | (mFetcher->getTextureBandwidth() > max_bandwidth)) | ||
745 | { | 805 | { |
746 | url = region->getCapability("RequestTextureDownload"); | 806 | // Make normal priority and return (i.e. wait until there is room in the queue) |
747 | } | 807 | setPriority(LLWorkerThread::PRIORITY_NORMAL | mWorkPriority); |
748 | if (!url.empty()) | ||
749 | { | ||
750 | LLSD sd; | ||
751 | sd = mID.asString(); | ||
752 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
753 | LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID)); | ||
754 | return false; | 808 | return false; |
755 | } | 809 | } |
756 | else | 810 | |
811 | S32 cur_size = 0; | ||
812 | if (mFormattedImage.notNull()) | ||
757 | { | 813 | { |
758 | // llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl; | 814 | cur_size = mFormattedImage->getDataSize(); // amount of data we already have |
759 | mSentRequest = FALSE; | ||
760 | mState = LOAD_FROM_SIMULATOR; | ||
761 | return false; | ||
762 | } | 815 | } |
763 | } | ||
764 | else | ||
765 | { | ||
766 | if (mLoaded) | ||
767 | { | ||
768 | if (!mURL.empty()) | ||
769 | { | ||
770 | mState = LOAD_FROM_HTTP_GET_DATA; | ||
771 | mSentRequest = FALSE; // reset | ||
772 | mLoaded = FALSE; // reset | ||
773 | } | ||
774 | else | ||
775 | { | ||
776 | // llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl; | ||
777 | mSentRequest = FALSE; | ||
778 | mState = LOAD_FROM_SIMULATOR; | ||
779 | return false; | ||
780 | } | ||
781 | } | ||
782 | } | ||
783 | // fall through | ||
784 | } | ||
785 | |||
786 | if (mState == LOAD_FROM_HTTP_GET_DATA) | ||
787 | { | ||
788 | if (!mSentRequest) | ||
789 | { | ||
790 | mSentRequest = TRUE; | ||
791 | S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have | ||
792 | mRequestedSize = mDesiredSize; | 816 | mRequestedSize = mDesiredSize; |
793 | mRequestedDiscard = mDesiredDiscard; | 817 | mRequestedDiscard = mDesiredDiscard; |
794 | #if 1 // *TODO: LLCurl::getByteRange is broken (ignores range) | ||
795 | cur_size = 0; | ||
796 | mFormattedImage->deleteData(); | ||
797 | #endif | ||
798 | mRequestedSize -= cur_size; | 818 | mRequestedSize -= cur_size; |
799 | // F32 priority = mImagePriority / (F32)LLViewerImage::maxDecodePriority(); // 0-1 | 819 | // F32 priority = mImagePriority / (F32)LLViewerImage::maxDecodePriority(); // 0-1 |
800 | S32 offset = cur_size; | 820 | S32 offset = cur_size; |
801 | mBufferSize = cur_size; // This will get modified by callbackHttpGet() | 821 | mBufferSize = cur_size; // This will get modified by callbackHttpGet() |
802 | std::string url; | 822 | |
803 | if (mURL.empty()) | 823 | bool res = false; |
824 | if (!mUrl.empty()) | ||
804 | { | 825 | { |
805 | //url = "http://asset.agni/0000002f-38ae-0e17-8e72-712e58964e9c.texture"; | 826 | mLoaded = FALSE; |
806 | std::stringstream urlstr; | 827 | mGetStatus = 0; |
807 | urlstr << "http://asset.agni/" << mID.asString() << ".texture"; | 828 | mGetReason.clear(); |
808 | url = urlstr.str(); | 829 | lldebugs << "HTTP GET: " << mID << " Offset: " << offset |
830 | << " Bytes: " << mRequestedSize | ||
831 | << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth | ||
832 | << llendl; | ||
833 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
834 | mState = WAIT_HTTP_REQ; | ||
835 | |||
836 | mFetcher->addToHTTPQueue(mID); | ||
837 | // Will call callbackHttpGet when curl request completes | ||
838 | std::vector<std::string> headers; | ||
839 | headers.push_back("Accept: image/x-j2c"); | ||
840 | res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, | ||
841 | new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset)); | ||
809 | } | 842 | } |
810 | else | 843 | if (!res) |
811 | { | 844 | { |
812 | url = mURL; | 845 | llwarns << "HTTP GET request failed for " << mID << llendl; |
846 | resetFormattedData(); | ||
847 | ++mHTTPFailCount; | ||
848 | return true; // failed | ||
813 | } | 849 | } |
814 | mLoaded = FALSE; | 850 | // fall through |
815 | // llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl; | ||
816 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
817 | LLCurl::getByteRange(url, offset, mRequestedSize, | ||
818 | new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority | ||
819 | return false; // not done | ||
820 | } | 851 | } |
821 | 852 | } | |
853 | |||
854 | if (mState == WAIT_HTTP_REQ) | ||
855 | { | ||
822 | if (mLoaded) | 856 | if (mLoaded) |
823 | { | 857 | { |
824 | S32 cur_size = mFormattedImage->getDataSize(); | 858 | S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; |
825 | if (mRequestedSize < 0) | 859 | if (mRequestedSize < 0) |
826 | { | 860 | { |
827 | // llwarns << "http get failed for: " << mID << llendl; | 861 | const S32 HTTP_MAX_RETRY_COUNT = 4; |
862 | llinfos << "HTTP GET failed for: " << mUrl | ||
863 | << " Status: " << mGetStatus << " Reason: " << mGetReason | ||
864 | << " Try:" << mHTTPFailCount+1 << "/" << HTTP_MAX_RETRY_COUNT << llendl; | ||
828 | if (cur_size == 0) | 865 | if (cur_size == 0) |
829 | { | 866 | { |
830 | resetFormattedData(); | 867 | ++mHTTPFailCount; |
831 | return true; // failed | 868 | if (mGetStatus == HTTP_NOT_FOUND || mHTTPFailCount >= HTTP_MAX_RETRY_COUNT) |
869 | { | ||
870 | resetFormattedData(); | ||
871 | return true; // failed | ||
872 | } | ||
873 | else | ||
874 | { | ||
875 | mState = SEND_HTTP_REQ; | ||
876 | return false; // retry | ||
877 | } | ||
832 | } | 878 | } |
833 | else | 879 | else |
834 | { | 880 | { |
@@ -836,6 +882,18 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
836 | return false; // use what we have | 882 | return false; // use what we have |
837 | } | 883 | } |
838 | } | 884 | } |
885 | |||
886 | if (mFormattedImage.isNull()) | ||
887 | { | ||
888 | // For now, create formatted image based on extension | ||
889 | std::string extension = gDirUtilp->getExtension(mUrl); | ||
890 | mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); | ||
891 | if (mFormattedImage.isNull()) | ||
892 | { | ||
893 | mFormattedImage = new LLImageJ2C; // default | ||
894 | } | ||
895 | } | ||
896 | |||
839 | llassert_always(mBufferSize == cur_size + mRequestedSize); | 897 | llassert_always(mBufferSize == cur_size + mRequestedSize); |
840 | if (mHaveAllData) | 898 | if (mHaveAllData) |
841 | { | 899 | { |
@@ -854,16 +912,16 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
854 | mBuffer = NULL; | 912 | mBuffer = NULL; |
855 | mBufferSize = 0; | 913 | mBufferSize = 0; |
856 | mLoadedDiscard = mRequestedDiscard; | 914 | mLoadedDiscard = mRequestedDiscard; |
857 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
858 | mState = DECODE_IMAGE; | 915 | mState = DECODE_IMAGE; |
916 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
917 | return false; | ||
918 | } | ||
919 | else | ||
920 | { | ||
921 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
859 | return false; | 922 | return false; |
860 | } | 923 | } |
861 | |||
862 | // NOTE: Priority gets updated when the http get completes (in callbackHTTPGet()) | ||
863 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); | ||
864 | return false; | ||
865 | } | 924 | } |
866 | #endif | ||
867 | 925 | ||
868 | if (mState == DECODE_IMAGE) | 926 | if (mState == DECODE_IMAGE) |
869 | { | 927 | { |
@@ -871,19 +929,19 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
871 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it | 929 | setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it |
872 | mRawImage = NULL; | 930 | mRawImage = NULL; |
873 | mAuxImage = NULL; | 931 | mAuxImage = NULL; |
874 | llassert_always(mImageWorker == NULL); | ||
875 | llassert_always(mFormattedImage.notNull()); | 932 | llassert_always(mFormattedImage.notNull()); |
876 | S32 discard = mHaveAllData ? 0 : mLoadedDiscard; | 933 | S32 discard = mHaveAllData ? 0 : mLoadedDiscard; |
877 | U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; | 934 | U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; |
878 | mDecoded = FALSE; | 935 | mDecoded = FALSE; |
879 | mState = DECODE_IMAGE_UPDATE; | 936 | mState = DECODE_IMAGE_UPDATE; |
880 | mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this)); | 937 | mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, |
881 | // fall though (need to call requestDecodedData() to start work) | 938 | new DecodeResponder(mFetcher, mID, this)); |
939 | // fall though | ||
882 | } | 940 | } |
883 | 941 | ||
884 | if (mState == DECODE_IMAGE_UPDATE) | 942 | if (mState == DECODE_IMAGE_UPDATE) |
885 | { | 943 | { |
886 | if (decodeImage()) | 944 | if (mDecoded) |
887 | { | 945 | { |
888 | if (mDecodedDiscard < 0) | 946 | if (mDecodedDiscard < 0) |
889 | { | 947 | { |
@@ -891,6 +949,7 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
891 | { | 949 | { |
892 | // Cache file should be deleted, try again | 950 | // Cache file should be deleted, try again |
893 | // llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl; | 951 | // llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl; |
952 | llassert_always(mDecodeHandle == 0); | ||
894 | mFormattedImage = NULL; | 953 | mFormattedImage = NULL; |
895 | ++mRetryAttempt; | 954 | ++mRetryAttempt; |
896 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | 955 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); |
@@ -918,9 +977,10 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
918 | 977 | ||
919 | if (mState == WRITE_TO_CACHE) | 978 | if (mState == WRITE_TO_CACHE) |
920 | { | 979 | { |
921 | if (mInLocalCache || !mFileSize || mSentRequest == UNSENT) | 980 | if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull()) |
922 | { | 981 | { |
923 | // If we're in a local cache or we didn't actually receive any new data, skip | 982 | // If we're in a local cache or we didn't actually receive any new data, |
983 | // or we failed to load anything, skip | ||
924 | mState = DONE; | 984 | mState = DONE; |
925 | return false; | 985 | return false; |
926 | } | 986 | } |
@@ -979,10 +1039,10 @@ bool LLTextureFetchWorker::doWork(S32 param) | |||
979 | // Called from MAIN thread | 1039 | // Called from MAIN thread |
980 | void LLTextureFetchWorker::endWork(S32 param, bool aborted) | 1040 | void LLTextureFetchWorker::endWork(S32 param, bool aborted) |
981 | { | 1041 | { |
982 | if (mImageWorker) | 1042 | if (mDecodeHandle != 0) |
983 | { | 1043 | { |
984 | mImageWorker->scheduleDelete(); | 1044 | mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false); |
985 | mImageWorker = NULL; | 1045 | mDecodeHandle = 0; |
986 | } | 1046 | } |
987 | mFormattedImage = NULL; | 1047 | mFormattedImage = NULL; |
988 | } | 1048 | } |
@@ -1035,7 +1095,7 @@ bool LLTextureFetchWorker::deleteOK() | |||
1035 | 1095 | ||
1036 | if ((haveWork() && | 1096 | if ((haveWork() && |
1037 | // not ok to delete from these states | 1097 | // not ok to delete from these states |
1038 | ((mState >= LOAD_FROM_HTTP_GET_URL && mState <= LOAD_FROM_HTTP_GET_DATA) || | 1098 | ((mState >= SEND_HTTP_REQ && mState <= WAIT_HTTP_REQ) || |
1039 | (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) | 1099 | (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) |
1040 | { | 1100 | { |
1041 | delete_ok = false; | 1101 | delete_ok = false; |
@@ -1044,7 +1104,6 @@ bool LLTextureFetchWorker::deleteOK() | |||
1044 | return delete_ok; | 1104 | return delete_ok; |
1045 | } | 1105 | } |
1046 | 1106 | ||
1047 | |||
1048 | void LLTextureFetchWorker::removeFromCache() | 1107 | void LLTextureFetchWorker::removeFromCache() |
1049 | { | 1108 | { |
1050 | if (!mInLocalCache) | 1109 | if (!mInLocalCache) |
@@ -1061,6 +1120,7 @@ bool LLTextureFetchWorker::processSimulatorPackets() | |||
1061 | if (mFormattedImage.isNull() || mRequestedSize < 0) | 1120 | if (mFormattedImage.isNull() || mRequestedSize < 0) |
1062 | { | 1121 | { |
1063 | // not sure how we got here, but not a valid state, abort! | 1122 | // not sure how we got here, but not a valid state, abort! |
1123 | llassert_always(mDecodeHandle == 0); | ||
1064 | mFormattedImage = NULL; | 1124 | mFormattedImage = NULL; |
1065 | return true; | 1125 | return true; |
1066 | } | 1126 | } |
@@ -1074,6 +1134,12 @@ bool LLTextureFetchWorker::processSimulatorPackets() | |||
1074 | buffer_size += mPackets[i]->mSize; | 1134 | buffer_size += mPackets[i]->mSize; |
1075 | } | 1135 | } |
1076 | bool have_all_data = mLastPacket >= mTotalPackets-1; | 1136 | bool have_all_data = mLastPacket >= mTotalPackets-1; |
1137 | if (mRequestedSize <= 0) | ||
1138 | { | ||
1139 | // We received a packed but haven't requested anything yet (edge case) | ||
1140 | // Return true (we're "done") since we didn't request anything | ||
1141 | return true; | ||
1142 | } | ||
1077 | if (buffer_size >= mRequestedSize || have_all_data) | 1143 | if (buffer_size >= mRequestedSize || have_all_data) |
1078 | { | 1144 | { |
1079 | /// We have enough (or all) data | 1145 | /// We have enough (or all) data |
@@ -1109,50 +1175,36 @@ bool LLTextureFetchWorker::processSimulatorPackets() | |||
1109 | 1175 | ||
1110 | ////////////////////////////////////////////////////////////////////////////// | 1176 | ////////////////////////////////////////////////////////////////////////////// |
1111 | 1177 | ||
1112 | void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success) | 1178 | void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, |
1179 | const LLIOPipe::buffer_ptr_t& buffer, | ||
1180 | bool last_block, bool success) | ||
1113 | { | 1181 | { |
1114 | #if 0 | ||
1115 | LLMutexLock lock(&mWorkMutex); | 1182 | LLMutexLock lock(&mWorkMutex); |
1116 | if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_URL) | ||
1117 | { | ||
1118 | llwarns << "callbackURLReceived for unrequested fetch worker, req=" | ||
1119 | << mSentRequest << " state= " << mState << llendl; | ||
1120 | return; | ||
1121 | } | ||
1122 | if (success) | ||
1123 | { | ||
1124 | mURL = data.asString(); | ||
1125 | } | ||
1126 | mLoaded = TRUE; | ||
1127 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
1128 | #endif | ||
1129 | } | ||
1130 | 1183 | ||
1131 | ////////////////////////////////////////////////////////////////////////////// | 1184 | if (mState != WAIT_HTTP_REQ) |
1132 | |||
1133 | void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block) | ||
1134 | { | ||
1135 | #if 0 | ||
1136 | LLMutexLock lock(&mWorkMutex); | ||
1137 | if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_DATA) | ||
1138 | { | 1185 | { |
1139 | llwarns << "callbackHttpGet for unrequested fetch worker, req=" | 1186 | llwarns << "callbackHttpGet for unrequested fetch worker: " << mID |
1140 | << mSentRequest << " state= " << mState << llendl; | 1187 | << " req=" << mSentRequest << " state= " << mState << llendl; |
1141 | return; | 1188 | return; |
1142 | } | 1189 | } |
1143 | // llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; | ||
1144 | if (mLoaded) | 1190 | if (mLoaded) |
1145 | { | 1191 | { |
1146 | llwarns << "Duplicate callback for " << mID.asString() << llendl; | 1192 | llwarns << "Duplicate callback for " << mID.asString() << llendl; |
1147 | return; // ignore duplicate callback | 1193 | return; // ignore duplicate callback |
1148 | } | 1194 | } |
1149 | if (data_size >= 0) | 1195 | if (success) |
1150 | { | 1196 | { |
1197 | // get length of stream: | ||
1198 | S32 data_size = buffer->countAfter(channels.in(), NULL); | ||
1199 | |||
1200 | gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits | ||
1201 | |||
1202 | //llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; | ||
1151 | if (data_size > 0) | 1203 | if (data_size > 0) |
1152 | { | 1204 | { |
1205 | // *TODO: set the formatted image data here directly to avoid the copy | ||
1153 | mBuffer = new U8[data_size]; | 1206 | mBuffer = new U8[data_size]; |
1154 | // *TODO: set the formatted image data here | 1207 | buffer->readAfter(channels.in(), NULL, mBuffer, data_size); |
1155 | memcpy(mBuffer, data, data_size); | ||
1156 | mBufferSize += data_size; | 1208 | mBufferSize += data_size; |
1157 | if (data_size < mRequestedSize || last_block == true) | 1209 | if (data_size < mRequestedSize || last_block == true) |
1158 | { | 1210 | { |
@@ -1160,10 +1212,11 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl | |||
1160 | } | 1212 | } |
1161 | else if (data_size > mRequestedSize) | 1213 | else if (data_size > mRequestedSize) |
1162 | { | 1214 | { |
1163 | // *TODO: This will happen until we fix LLCurl::getByteRange() | 1215 | // *TODO: This shouldn't be happening any more |
1164 | // llinfos << "HUH?" << llendl; | 1216 | llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; |
1165 | mHaveAllData = TRUE; | 1217 | mHaveAllData = TRUE; |
1166 | mFormattedImage->deleteData(); | 1218 | llassert_always(mDecodeHandle == 0); |
1219 | mFormattedImage = NULL; // discard any previous data we had | ||
1167 | mBufferSize = data_size; | 1220 | mBufferSize = data_size; |
1168 | } | 1221 | } |
1169 | } | 1222 | } |
@@ -1181,7 +1234,6 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl | |||
1181 | } | 1234 | } |
1182 | mLoaded = TRUE; | 1235 | mLoaded = TRUE; |
1183 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | 1236 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); |
1184 | #endif | ||
1185 | } | 1237 | } |
1186 | 1238 | ||
1187 | ////////////////////////////////////////////////////////////////////////////// | 1239 | ////////////////////////////////////////////////////////////////////////////// |
@@ -1197,7 +1249,7 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima | |||
1197 | } | 1249 | } |
1198 | if (success) | 1250 | if (success) |
1199 | { | 1251 | { |
1200 | llassert_always(imagesize > 0); | 1252 | llassert_always(imagesize >= 0); |
1201 | mFileSize = imagesize; | 1253 | mFileSize = imagesize; |
1202 | mFormattedImage = image; | 1254 | mFormattedImage = image; |
1203 | mImageCodec = image->getCodec(); | 1255 | mImageCodec = image->getCodec(); |
@@ -1225,65 +1277,49 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) | |||
1225 | 1277 | ||
1226 | ////////////////////////////////////////////////////////////////////////////// | 1278 | ////////////////////////////////////////////////////////////////////////////// |
1227 | 1279 | ||
1228 | void LLTextureFetchWorker::callbackDecoded(bool success) | 1280 | void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) |
1229 | { | 1281 | { |
1282 | LLMutexLock lock(&mWorkMutex); | ||
1283 | if (mDecodeHandle == 0) | ||
1284 | { | ||
1285 | return; // aborted, ignore | ||
1286 | } | ||
1230 | if (mState != DECODE_IMAGE_UPDATE) | 1287 | if (mState != DECODE_IMAGE_UPDATE) |
1231 | { | 1288 | { |
1232 | // llwarns << "Decode callback for " << mID << " with state = " << mState << llendl; | 1289 | // llwarns << "Decode callback for " << mID << " with state = " << mState << llendl; |
1290 | mDecodeHandle = 0; | ||
1233 | return; | 1291 | return; |
1234 | } | 1292 | } |
1235 | // llinfos << mID << " : DECODE COMPLETE " << llendl; | 1293 | llassert_always(mFormattedImage.notNull()); |
1236 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | 1294 | |
1237 | } | 1295 | mDecodeHandle = 0; |
1238 | 1296 | if (success) | |
1239 | ////////////////////////////////////////////////////////////////////////////// | ||
1240 | |||
1241 | bool LLTextureFetchWorker::decodeImage() | ||
1242 | { | ||
1243 | if(!mImageWorker) | ||
1244 | { | ||
1245 | //LLTextureFetchWorker is aborted, skip image decoding. | ||
1246 | return true ; | ||
1247 | } | ||
1248 | |||
1249 | bool res = true; | ||
1250 | if (mRawImage.isNull()) | ||
1251 | { | ||
1252 | res = false; | ||
1253 | if (mImageWorker->requestDecodedData(mRawImage, -1)) | ||
1254 | { | ||
1255 | res = true; | ||
1256 | // llinfos << mID << " : BASE DECODE FINISHED" << llendl; | ||
1257 | } | ||
1258 | } | ||
1259 | if (res && | ||
1260 | (mRawImage.notNull() && mRawImage->getDataSize() > 0) && | ||
1261 | (mNeedsAux && mAuxImage.isNull())) | ||
1262 | { | 1297 | { |
1263 | res = false; | 1298 | mRawImage = raw; |
1264 | if (mImageWorker->requestDecodedAuxData(mAuxImage, 4, -1)) | 1299 | mAuxImage = aux; |
1265 | { | 1300 | mDecodedDiscard = mFormattedImage->getDiscardLevel(); |
1266 | res = true; | 1301 | // llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl; |
1267 | // llinfos << mID << " : AUX DECODE FINISHED" << llendl; | ||
1268 | } | ||
1269 | } | 1302 | } |
1270 | if (res) | 1303 | else |
1271 | { | 1304 | { |
1272 | if ((mRawImage.notNull() && mRawImage->getDataSize() > 0) && | 1305 | if (mFormattedImage.notNull()) |
1273 | (!mNeedsAux || (mAuxImage.notNull() && mAuxImage->getDataSize() > 0))) | ||
1274 | { | 1306 | { |
1275 | mDecodedDiscard = mFormattedImage->getDiscardLevel(); | 1307 | LL_WARNS("http-texture") << "DECODE FAILED: id = " << mID << ", Discard = " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; |
1276 | // llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl; | ||
1277 | } | 1308 | } |
1278 | else | 1309 | else |
1279 | { | 1310 | { |
1280 | // llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl; | 1311 | LL_WARNS("http-texture") << "DECODE FAILED: id = " << mID << ", mFormattedImage is Null!" << LL_ENDL; |
1281 | removeFromCache(); | ||
1282 | } | 1312 | } |
1283 | mImageWorker->scheduleDelete(); | 1313 | removeFromCache(); |
1284 | mImageWorker = NULL; | 1314 | mDecodedDiscard = -1; // Redundant, here for clarity and paranoia |
1285 | } | 1315 | } |
1286 | return res; | 1316 | mDecoded = TRUE; |
1317 | // llinfos << mID << " : DECODE COMPLETE " << llendl; | ||
1318 | setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); | ||
1319 | // Set the decode flag at the end of the callback or we trigger race conditions between the fetch thread and the | ||
1320 | // decode threads that's calling this callback. The fetch thread might set mFormattedImage to NULL before we | ||
1321 | // have time here to call getDiscardLevel() which causes crashes | ||
1322 | mDecoded = TRUE; | ||
1287 | } | 1323 | } |
1288 | 1324 | ||
1289 | ////////////////////////////////////////////////////////////////////////////// | 1325 | ////////////////////////////////////////////////////////////////////////////// |
@@ -1314,15 +1350,21 @@ bool LLTextureFetchWorker::writeToCacheComplete() | |||
1314 | ////////////////////////////////////////////////////////////////////////////// | 1350 | ////////////////////////////////////////////////////////////////////////////// |
1315 | // public | 1351 | // public |
1316 | 1352 | ||
1317 | LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded) | 1353 | LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded) |
1318 | : LLWorkerThread("TextureFetch", threaded), | 1354 | : LLWorkerThread("TextureFetch", threaded), |
1319 | mDebugCount(0), | 1355 | mDebugCount(0), |
1320 | mDebugPause(FALSE), | 1356 | mDebugPause(FALSE), |
1321 | mPacketCount(0), | 1357 | mPacketCount(0), |
1322 | mBadPacketCount(0), | 1358 | mBadPacketCount(0), |
1323 | mQueueMutex(getAPRPool()), | 1359 | mQueueMutex(getAPRPool()), |
1324 | mTextureCache(cache) | 1360 | mNetworkQueueMutex(getAPRPool()), |
1361 | mTextureCache(cache), | ||
1362 | mImageDecodeThread(imagedecodethread), | ||
1363 | mTextureBandwidth(0), | ||
1364 | mCurlGetRequest(NULL) | ||
1325 | { | 1365 | { |
1366 | mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); | ||
1367 | mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); | ||
1326 | } | 1368 | } |
1327 | 1369 | ||
1328 | LLTextureFetch::~LLTextureFetch() | 1370 | LLTextureFetch::~LLTextureFetch() |
@@ -1330,13 +1372,7 @@ LLTextureFetch::~LLTextureFetch() | |||
1330 | // ~LLQueuedThread() called here | 1372 | // ~LLQueuedThread() called here |
1331 | } | 1373 | } |
1332 | 1374 | ||
1333 | bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 priority, | 1375 | bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, |
1334 | S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) | ||
1335 | { | ||
1336 | return createRequest(LLStringUtil::null, id, host, priority, w, h, c, desired_discard, needs_aux); | ||
1337 | } | ||
1338 | |||
1339 | bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority, | ||
1340 | S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) | 1376 | S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) |
1341 | { | 1377 | { |
1342 | if (mDebugPause) | 1378 | if (mDebugPause) |
@@ -1361,7 +1397,14 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id | |||
1361 | } | 1397 | } |
1362 | 1398 | ||
1363 | S32 desired_size; | 1399 | S32 desired_size; |
1364 | if (desired_discard == 0) | 1400 | std::string exten = gDirUtilp->getExtension(url); |
1401 | if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) | ||
1402 | { | ||
1403 | // Only do partial requests for J2C at the moment | ||
1404 | //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl; | ||
1405 | desired_size = MAX_IMAGE_DATA_SIZE; | ||
1406 | } | ||
1407 | else if (desired_discard == 0) | ||
1365 | { | 1408 | { |
1366 | // if we want the entire image, and we know its size, then get it all | 1409 | // if we want the entire image, and we know its size, then get it all |
1367 | // (calcDataSizeJ2C() below makes assumptions about how the image | 1410 | // (calcDataSizeJ2C() below makes assumptions about how the image |
@@ -1389,28 +1432,25 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id | |||
1389 | { | 1432 | { |
1390 | return false; // need to wait for previous aborted request to complete | 1433 | return false; // need to wait for previous aborted request to complete |
1391 | } | 1434 | } |
1392 | worker->lockWorkData(); | 1435 | worker->lockWorkMutex(); |
1393 | worker->setImagePriority(priority); | 1436 | worker->setImagePriority(priority); |
1394 | worker->setDesiredDiscard(desired_discard, desired_size); | 1437 | worker->setDesiredDiscard(desired_discard, desired_size); |
1395 | worker->unlockWorkData(); | 1438 | worker->unlockWorkMutex(); |
1396 | if (!worker->haveWork()) | 1439 | if (!worker->haveWork()) |
1397 | { | 1440 | { |
1441 | worker->lockWorkMutex(); | ||
1442 | if (worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK || worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) | ||
1443 | { | ||
1444 | removeFromNetworkQueue(worker, true); | ||
1445 | } | ||
1398 | worker->mState = LLTextureFetchWorker::INIT; | 1446 | worker->mState = LLTextureFetchWorker::INIT; |
1447 | worker->unlockWorkMutex(); | ||
1399 | worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); | 1448 | worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); |
1400 | } | 1449 | } |
1401 | } | 1450 | } |
1402 | else | 1451 | else |
1403 | { | 1452 | { |
1404 | if (filename.empty()) | 1453 | worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size); |
1405 | { | ||
1406 | // do remote fetch | ||
1407 | worker = new LLTextureFetchWorker(this, id, host, priority, desired_discard, desired_size); | ||
1408 | } | ||
1409 | else | ||
1410 | { | ||
1411 | // do local file fetch | ||
1412 | worker = new LLTextureFetchLocalFileWorker(this, filename, id, host, priority, desired_discard, desired_size); | ||
1413 | } | ||
1414 | mRequestMap[id] = worker; | 1454 | mRequestMap[id] = worker; |
1415 | } | 1455 | } |
1416 | worker->mActiveCount++; | 1456 | worker->mActiveCount++; |
@@ -1430,10 +1470,9 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) | |||
1430 | } | 1470 | } |
1431 | 1471 | ||
1432 | // protected | 1472 | // protected |
1433 | |||
1434 | // call lockQueue() first! | ||
1435 | void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) | 1473 | void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) |
1436 | { | 1474 | { |
1475 | LLMutexLock lock(&mNetworkQueueMutex); | ||
1437 | if (mRequestMap.find(worker->mID) != mRequestMap.end()) | 1476 | if (mRequestMap.find(worker->mID) != mRequestMap.end()) |
1438 | { | 1477 | { |
1439 | // only add to the queue if in the request map | 1478 | // only add to the queue if in the request map |
@@ -1447,10 +1486,27 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) | |||
1447 | } | 1486 | } |
1448 | } | 1487 | } |
1449 | 1488 | ||
1450 | // call lockQueue() first! | 1489 | void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel) |
1451 | void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker) | 1490 | { |
1491 | LLMutexLock lock(&mNetworkQueueMutex); | ||
1492 | size_t erased = mNetworkQueue.erase(worker->mID); | ||
1493 | if (cancel && erased > 0) | ||
1494 | { | ||
1495 | mCancelQueue[worker->mHost].insert(worker->mID); | ||
1496 | } | ||
1497 | } | ||
1498 | |||
1499 | // protected | ||
1500 | void LLTextureFetch::addToHTTPQueue(const LLUUID& id) | ||
1501 | { | ||
1502 | LLMutexLock lock(&mNetworkQueueMutex); | ||
1503 | mHTTPTextureQueue.insert(id); | ||
1504 | } | ||
1505 | |||
1506 | void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id) | ||
1452 | { | 1507 | { |
1453 | mNetworkQueue.erase(worker->mID); | 1508 | LLMutexLock lock(&mNetworkQueueMutex); |
1509 | mHTTPTextureQueue.erase(id); | ||
1454 | } | 1510 | } |
1455 | 1511 | ||
1456 | // call lockQueue() first! | 1512 | // call lockQueue() first! |
@@ -1458,11 +1514,7 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) | |||
1458 | { | 1514 | { |
1459 | size_t erased_1 = mRequestMap.erase(worker->mID); | 1515 | size_t erased_1 = mRequestMap.erase(worker->mID); |
1460 | llassert_always(erased_1 > 0) ; | 1516 | llassert_always(erased_1 > 0) ; |
1461 | size_t erased = mNetworkQueue.erase(worker->mID); | 1517 | removeFromNetworkQueue(worker, cancel); |
1462 | if (cancel && erased > 0) | ||
1463 | { | ||
1464 | mCancelQueue[worker->mHost].insert(worker->mID); | ||
1465 | } | ||
1466 | llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; | 1518 | llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; |
1467 | 1519 | ||
1468 | worker->scheduleDelete(); | 1520 | worker->scheduleDelete(); |
@@ -1511,7 +1563,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, | |||
1511 | } | 1563 | } |
1512 | else | 1564 | else |
1513 | { | 1565 | { |
1514 | worker->lockWorkData(); | 1566 | worker->lockWorkMutex(); |
1515 | if ((worker->mDecodedDiscard >= 0) && | 1567 | if ((worker->mDecodedDiscard >= 0) && |
1516 | (worker->mDecodedDiscard < discard_level || discard_level < 0) && | 1568 | (worker->mDecodedDiscard < discard_level || discard_level < 0) && |
1517 | (worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE)) | 1569 | (worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE)) |
@@ -1521,7 +1573,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, | |||
1521 | if (worker->mRawImage) raw = worker->mRawImage; | 1573 | if (worker->mRawImage) raw = worker->mRawImage; |
1522 | if (worker->mAuxImage) aux = worker->mAuxImage; | 1574 | if (worker->mAuxImage) aux = worker->mAuxImage; |
1523 | } | 1575 | } |
1524 | worker->unlockWorkData(); | 1576 | worker->unlockWorkMutex(); |
1525 | } | 1577 | } |
1526 | } | 1578 | } |
1527 | else | 1579 | else |
@@ -1538,9 +1590,9 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) | |||
1538 | LLTextureFetchWorker* worker = getWorker(id); | 1590 | LLTextureFetchWorker* worker = getWorker(id); |
1539 | if (worker) | 1591 | if (worker) |
1540 | { | 1592 | { |
1541 | worker->lockWorkData(); | 1593 | worker->lockWorkMutex(); |
1542 | worker->setImagePriority(priority); | 1594 | worker->setImagePriority(priority); |
1543 | worker->unlockWorkData(); | 1595 | worker->unlockWorkMutex(); |
1544 | res = true; | 1596 | res = true; |
1545 | } | 1597 | } |
1546 | return res; | 1598 | return res; |
@@ -1548,40 +1600,106 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) | |||
1548 | 1600 | ||
1549 | ////////////////////////////////////////////////////////////////////////////// | 1601 | ////////////////////////////////////////////////////////////////////////////// |
1550 | 1602 | ||
1603 | // MAIN THREAD | ||
1551 | //virtual | 1604 | //virtual |
1552 | S32 LLTextureFetch::update(U32 max_time_ms) | 1605 | S32 LLTextureFetch::update(U32 max_time_ms) |
1553 | { | 1606 | { |
1554 | S32 res; | 1607 | S32 res; |
1608 | |||
1609 | mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); | ||
1610 | |||
1555 | res = LLWorkerThread::update(max_time_ms); | 1611 | res = LLWorkerThread::update(max_time_ms); |
1556 | 1612 | ||
1557 | const F32 REQUEST_TIME = 1.f; | 1613 | if (!mDebugPause) |
1558 | |||
1559 | // Periodically, gather the list of textures that need data from the network | ||
1560 | // And send the requests out to the simulators | ||
1561 | if (mNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME) | ||
1562 | { | 1614 | { |
1563 | mNetworkTimer.reset(); | ||
1564 | sendRequestListToSimulators(); | 1615 | sendRequestListToSimulators(); |
1565 | } | 1616 | } |
1566 | 1617 | ||
1567 | return res; | 1618 | return res; |
1568 | } | 1619 | } |
1569 | 1620 | ||
1621 | // WORKER THREAD | ||
1622 | void LLTextureFetch::startThread() | ||
1623 | { | ||
1624 | // Construct mCurlGetRequest from Worker Thread | ||
1625 | mCurlGetRequest = new LLCurlRequest(); | ||
1626 | } | ||
1627 | |||
1628 | // WORKER THREAD | ||
1629 | void LLTextureFetch::endThread() | ||
1630 | { | ||
1631 | // Destroy mCurlGetRequest from Worker Thread | ||
1632 | delete mCurlGetRequest; | ||
1633 | mCurlGetRequest = NULL; | ||
1634 | } | ||
1635 | |||
1636 | // WORKER THREAD | ||
1637 | void LLTextureFetch::threadedUpdate() | ||
1638 | { | ||
1639 | llassert_always(mCurlGetRequest); | ||
1640 | |||
1641 | // Limit update frequency | ||
1642 | const F32 PROCESS_TIME = 0.05f; | ||
1643 | static LLFrameTimer process_timer; | ||
1644 | if (process_timer.getElapsedTimeF32() < PROCESS_TIME) | ||
1645 | { | ||
1646 | return; | ||
1647 | } | ||
1648 | process_timer.reset(); | ||
1649 | |||
1650 | // Update Curl on same thread as mCurlGetRequest was constructed | ||
1651 | S32 processed = mCurlGetRequest->process(); | ||
1652 | if (processed > 0) | ||
1653 | { | ||
1654 | lldebugs << "processed: " << processed << " messages." << llendl; | ||
1655 | } | ||
1656 | |||
1657 | #if 0 | ||
1658 | const F32 INFO_TIME = 1.0f; | ||
1659 | static LLFrameTimer info_timer; | ||
1660 | if (info_timer.getElapsedTimeF32() >= INFO_TIME) | ||
1661 | { | ||
1662 | S32 q = mCurlGetRequest->getQueued(); | ||
1663 | if (q > 0) | ||
1664 | { | ||
1665 | llinfos << "Queued gets: " << q << llendl; | ||
1666 | info_timer.reset(); | ||
1667 | } | ||
1668 | } | ||
1669 | #endif | ||
1670 | |||
1671 | } | ||
1672 | |||
1570 | ////////////////////////////////////////////////////////////////////////////// | 1673 | ////////////////////////////////////////////////////////////////////////////// |
1571 | 1674 | ||
1572 | void LLTextureFetch::sendRequestListToSimulators() | 1675 | void LLTextureFetch::sendRequestListToSimulators() |
1573 | { | 1676 | { |
1677 | // All requests | ||
1678 | const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps | ||
1679 | |||
1680 | // Sim requests | ||
1574 | const S32 IMAGES_PER_REQUEST = 50; | 1681 | const S32 IMAGES_PER_REQUEST = 50; |
1575 | const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp | 1682 | const F32 SIM_LAZY_FLUSH_TIMEOUT = 10.0f; // temp |
1576 | const F32 MIN_REQUEST_TIME = 1.0f; | 1683 | const F32 MIN_REQUEST_TIME = 1.0f; |
1577 | const F32 MIN_DELTA_PRIORITY = 1000.f; | 1684 | const F32 MIN_DELTA_PRIORITY = 1000.f; |
1578 | 1685 | ||
1579 | LLMutexLock lock(&mQueueMutex); | 1686 | // Periodically, gather the list of textures that need data from the network |
1687 | // And send the requests out to the simulators | ||
1688 | static LLFrameTimer timer; | ||
1689 | if (timer.getElapsedTimeF32() < REQUEST_DELTA_TIME) | ||
1690 | { | ||
1691 | return; | ||
1692 | } | ||
1693 | timer.reset(); | ||
1580 | 1694 | ||
1695 | LLMutexLock lock(&mQueueMutex); | ||
1696 | |||
1581 | // Send requests | 1697 | // Send requests |
1582 | typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t; | 1698 | typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t; |
1583 | typedef std::map< LLHost, request_list_t > work_request_map_t; | 1699 | typedef std::map< LLHost, request_list_t > work_request_map_t; |
1584 | work_request_map_t requests; | 1700 | work_request_map_t requests; |
1701 | { | ||
1702 | LLMutexLock lock2(&mNetworkQueueMutex); | ||
1585 | for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ) | 1703 | for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ) |
1586 | { | 1704 | { |
1587 | queue_t::iterator curiter = iter++; | 1705 | queue_t::iterator curiter = iter++; |
@@ -1591,65 +1709,66 @@ void LLTextureFetch::sendRequestListToSimulators() | |||
1591 | mNetworkQueue.erase(curiter); | 1709 | mNetworkQueue.erase(curiter); |
1592 | continue; // paranoia | 1710 | continue; // paranoia |
1593 | } | 1711 | } |
1712 | llassert(req->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK || LLTextureFetchWorker::LOAD_FROM_SIMULATOR); | ||
1713 | if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) && | ||
1714 | (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR)) | ||
1715 | { | ||
1716 | // We really should never ever get here anymore. | ||
1717 | llwarns << "SNOW-119 failure: Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << llendl; | ||
1718 | mNetworkQueue.erase(curiter); | ||
1719 | continue; | ||
1720 | } | ||
1594 | if (req->mID == mDebugID) | 1721 | if (req->mID == mDebugID) |
1595 | { | 1722 | { |
1596 | mDebugCount++; // for setting breakpoints | 1723 | mDebugCount++; // for setting breakpoints |
1597 | } | 1724 | } |
1598 | if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1) | 1725 | if (req->mSentRequest == LLTextureFetchWorker::SENT_SIM && |
1726 | req->mTotalPackets > 0 && | ||
1727 | req->mLastPacket >= req->mTotalPackets-1) | ||
1599 | { | 1728 | { |
1600 | // We have all the packets... make sure this is high priority | 1729 | // We have all the packets... make sure this is high priority |
1601 | // req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); | 1730 | // req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); |
1602 | continue; | 1731 | continue; |
1603 | } | 1732 | } |
1604 | F32 elapsed = req->mRequestedTimer.getElapsedTimeF32(); | 1733 | F32 elapsed = req->mRequestedTimer.getElapsedTimeF32(); |
1605 | F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); | ||
1606 | if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || | ||
1607 | (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || | ||
1608 | (elapsed >= LAZY_FLUSH_TIMEOUT)) | ||
1609 | { | 1734 | { |
1610 | requests[req->mHost].insert(req); | 1735 | F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); |
1736 | if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || | ||
1737 | (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || | ||
1738 | (elapsed >= SIM_LAZY_FLUSH_TIMEOUT)) | ||
1739 | { | ||
1740 | requests[req->mHost].insert(req); | ||
1741 | } | ||
1611 | } | 1742 | } |
1612 | } | 1743 | } |
1613 | |||
1614 | std::string http_url; | ||
1615 | #if 0 | ||
1616 | if (gSavedSettings.getBOOL("ImagePipelineUseHTTP")) | ||
1617 | { | ||
1618 | LLViewerRegion* region = gAgent.getRegion(); | ||
1619 | if (region) | ||
1620 | { | ||
1621 | http_url = region->getCapability("RequestTextureDownload"); | ||
1622 | } | ||
1623 | } | 1744 | } |
1624 | #endif | 1745 | |
1625 | |||
1626 | for (work_request_map_t::iterator iter1 = requests.begin(); | 1746 | for (work_request_map_t::iterator iter1 = requests.begin(); |
1627 | iter1 != requests.end(); ++iter1) | 1747 | iter1 != requests.end(); ++iter1) |
1628 | { | 1748 | { |
1629 | bool use_http = http_url.empty() ? false : true; | ||
1630 | LLHost host = iter1->first; | 1749 | LLHost host = iter1->first; |
1631 | // invalid host = use agent host | 1750 | // invalid host = use agent host |
1632 | if (host == LLHost::invalid) | 1751 | if (host == LLHost::invalid) |
1633 | { | 1752 | { |
1634 | host = gAgent.getRegionHost(); | 1753 | host = gAgent.getRegionHost(); |
1635 | } | 1754 | } |
1636 | else | ||
1637 | { | ||
1638 | use_http = false; | ||
1639 | } | ||
1640 | 1755 | ||
1641 | if (use_http) | 1756 | S32 sim_request_count = 0; |
1642 | { | 1757 | |
1643 | } | 1758 | for (request_list_t::iterator iter2 = iter1->second.begin(); |
1644 | else | 1759 | iter2 != iter1->second.end(); ++iter2) |
1645 | { | 1760 | { |
1646 | S32 request_count = 0; | 1761 | LLTextureFetchWorker* req = *iter2; |
1647 | for (request_list_t::iterator iter2 = iter1->second.begin(); | 1762 | if (gMessageSystem) |
1648 | iter2 != iter1->second.end(); ++iter2) | ||
1649 | { | 1763 | { |
1650 | LLTextureFetchWorker* req = *iter2; | 1764 | if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM) |
1651 | req->mSentRequest = LLTextureFetchWorker::SENT_SIM; | 1765 | { |
1652 | if (0 == request_count) | 1766 | // Initialize packet data based on data read from cache |
1767 | req->lockWorkMutex(); | ||
1768 | req->setupPacketData(); | ||
1769 | req->unlockWorkMutex(); | ||
1770 | } | ||
1771 | if (0 == sim_request_count) | ||
1653 | { | 1772 | { |
1654 | gMessageSystem->newMessageFast(_PREHASH_RequestImage); | 1773 | gMessageSystem->newMessageFast(_PREHASH_RequestImage); |
1655 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | 1774 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); |
@@ -1666,30 +1785,42 @@ void LLTextureFetch::sendRequestListToSimulators() | |||
1666 | // llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard | 1785 | // llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard |
1667 | // << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; | 1786 | // << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; |
1668 | 1787 | ||
1669 | req->lockWorkData(); | 1788 | if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) |
1789 | { | ||
1790 | mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); | ||
1791 | mTextureInfo.setRequestOffset(req->mID, 0); | ||
1792 | mTextureInfo.setRequestSize(req->mID, 0); | ||
1793 | mTextureInfo.setRequestType(req->mID, LLTextureInfoDetails::REQUEST_TYPE_UDP); | ||
1794 | } | ||
1795 | |||
1796 | req->lockWorkMutex(); | ||
1797 | req->mSentRequest = LLTextureFetchWorker::SENT_SIM; | ||
1670 | req->mSimRequestedDiscard = req->mDesiredDiscard; | 1798 | req->mSimRequestedDiscard = req->mDesiredDiscard; |
1671 | req->mRequestedPriority = req->mImagePriority; | 1799 | req->mRequestedPriority = req->mImagePriority; |
1672 | req->mRequestedTimer.reset(); | 1800 | req->mRequestedTimer.reset(); |
1673 | req->unlockWorkData(); | 1801 | req->unlockWorkMutex(); |
1674 | request_count++; | 1802 | sim_request_count++; |
1675 | if (request_count >= IMAGES_PER_REQUEST) | 1803 | if (sim_request_count >= IMAGES_PER_REQUEST) |
1676 | { | 1804 | { |
1677 | // llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; | 1805 | // llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; |
1806 | |||
1678 | gMessageSystem->sendSemiReliable(host, NULL, NULL); | 1807 | gMessageSystem->sendSemiReliable(host, NULL, NULL); |
1679 | request_count = 0; | 1808 | sim_request_count = 0; |
1680 | } | 1809 | } |
1681 | } | 1810 | } |
1682 | if (request_count > 0 && request_count < IMAGES_PER_REQUEST) | 1811 | } |
1683 | { | 1812 | if (gMessageSystem && sim_request_count > 0 && sim_request_count < IMAGES_PER_REQUEST) |
1684 | // llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; | 1813 | { |
1685 | gMessageSystem->sendSemiReliable(host, NULL, NULL); | 1814 | // llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; |
1686 | request_count = 0; | 1815 | gMessageSystem->sendSemiReliable(host, NULL, NULL); |
1687 | } | 1816 | sim_request_count = 0; |
1688 | } | 1817 | } |
1689 | } | 1818 | } |
1690 | 1819 | ||
1691 | // Send cancelations | 1820 | // Send cancelations |
1692 | if (!mCancelQueue.empty()) | 1821 | { |
1822 | LLMutexLock lock2(&mNetworkQueueMutex); | ||
1823 | if (gMessageSystem && !mCancelQueue.empty()) | ||
1693 | { | 1824 | { |
1694 | for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); | 1825 | for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); |
1695 | iter1 != mCancelQueue.end(); ++iter1) | 1826 | iter1 != mCancelQueue.end(); ++iter1) |
@@ -1732,6 +1863,7 @@ void LLTextureFetch::sendRequestListToSimulators() | |||
1732 | } | 1863 | } |
1733 | mCancelQueue.clear(); | 1864 | mCancelQueue.clear(); |
1734 | } | 1865 | } |
1866 | } | ||
1735 | } | 1867 | } |
1736 | 1868 | ||
1737 | ////////////////////////////////////////////////////////////////////////////// | 1869 | ////////////////////////////////////////////////////////////////////////////// |
@@ -1773,16 +1905,20 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 | |||
1773 | { | 1905 | { |
1774 | LLMutexLock lock(&mQueueMutex); | 1906 | LLMutexLock lock(&mQueueMutex); |
1775 | LLTextureFetchWorker* worker = getWorker(id); | 1907 | LLTextureFetchWorker* worker = getWorker(id); |
1776 | bool res = true; | ||
1777 | 1908 | ||
1778 | ++mPacketCount; | 1909 | ++mPacketCount; |
1779 | 1910 | ||
1780 | if (!worker) | 1911 | if (!worker) |
1781 | { | 1912 | { |
1782 | // llwarns << "Received header for non active worker: " << id << llendl; | 1913 | // llwarns << "Received header for non active worker: " << id << llendl; |
1783 | res = false; | 1914 | ++mBadPacketCount; |
1915 | mCancelQueue[host].insert(id); | ||
1916 | return false; | ||
1784 | } | 1917 | } |
1785 | else if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK || | 1918 | |
1919 | bool res = true; | ||
1920 | worker->lockWorkMutex(); | ||
1921 | if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK || | ||
1786 | worker->mSentRequest != LLTextureFetchWorker::SENT_SIM) | 1922 | worker->mSentRequest != LLTextureFetchWorker::SENT_SIM) |
1787 | { | 1923 | { |
1788 | // llwarns << "receiveImageHeader for worker: " << id | 1924 | // llwarns << "receiveImageHeader for worker: " << id |
@@ -1805,21 +1941,20 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 | |||
1805 | { | 1941 | { |
1806 | ++mBadPacketCount; | 1942 | ++mBadPacketCount; |
1807 | mCancelQueue[host].insert(id); | 1943 | mCancelQueue[host].insert(id); |
1808 | return false; | ||
1809 | } | 1944 | } |
1810 | 1945 | else | |
1811 | worker->lockWorkData(); | 1946 | { |
1812 | 1947 | // Copy header data into image object | |
1813 | // Copy header data into image object | 1948 | worker->mImageCodec = codec; |
1814 | worker->mImageCodec = codec; | 1949 | worker->mTotalPackets = packets; |
1815 | worker->mTotalPackets = packets; | 1950 | worker->mFileSize = (S32)totalbytes; |
1816 | worker->mFileSize = (S32)totalbytes; | 1951 | llassert_always(totalbytes > 0); |
1817 | llassert_always(totalbytes > 0); | 1952 | llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); |
1818 | llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); | 1953 | res = worker->insertPacket(0, data, data_size); |
1819 | res = worker->insertPacket(0, data, data_size); | 1954 | worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); |
1820 | worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); | 1955 | worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; |
1821 | worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; | 1956 | } |
1822 | worker->unlockWorkData(); | 1957 | worker->unlockWorkMutex(); |
1823 | return res; | 1958 | return res; |
1824 | } | 1959 | } |
1825 | 1960 | ||
@@ -1853,7 +1988,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 | |||
1853 | return false; | 1988 | return false; |
1854 | } | 1989 | } |
1855 | 1990 | ||
1856 | worker->lockWorkData(); | 1991 | worker->lockWorkMutex(); |
1857 | 1992 | ||
1858 | res = worker->insertPacket(packet_num, data, data_size); | 1993 | res = worker->insertPacket(packet_num, data, data_size); |
1859 | 1994 | ||
@@ -1866,12 +2001,19 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 | |||
1866 | else | 2001 | else |
1867 | { | 2002 | { |
1868 | // llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id | 2003 | // llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id |
1869 | // << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl; | 2004 | // << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl; |
1870 | removeFromNetworkQueue(worker); // failsafe | ||
1871 | mCancelQueue[host].insert(id); | ||
1872 | } | 2005 | } |
1873 | 2006 | ||
1874 | worker->unlockWorkData(); | 2007 | if(packet_num >= (worker->mTotalPackets - 1)) |
2008 | { | ||
2009 | if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) | ||
2010 | { | ||
2011 | U64 timeNow = LLTimer::getTotalTime(); | ||
2012 | mTextureInfo.setRequestSize(id, worker->mFileSize); | ||
2013 | mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow); | ||
2014 | } | ||
2015 | } | ||
2016 | worker->unlockWorkMutex(); | ||
1875 | 2017 | ||
1876 | return res; | 2018 | return res; |
1877 | } | 2019 | } |
@@ -1892,7 +2034,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r | |||
1892 | LLTextureFetchWorker* worker = getWorker(id); | 2034 | LLTextureFetchWorker* worker = getWorker(id); |
1893 | if (worker && worker->haveWork()) | 2035 | if (worker && worker->haveWork()) |
1894 | { | 2036 | { |
1895 | worker->lockWorkData(); | 2037 | worker->lockWorkMutex(); |
1896 | state = worker->mState; | 2038 | state = worker->mState; |
1897 | fetch_dtime = worker->mFetchTimer.getElapsedTimeF32(); | 2039 | fetch_dtime = worker->mFetchTimer.getElapsedTimeF32(); |
1898 | request_dtime = worker->mRequestedTimer.getElapsedTimeF32(); | 2040 | request_dtime = worker->mRequestedTimer.getElapsedTimeF32(); |
@@ -1909,7 +2051,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r | |||
1909 | data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize; | 2051 | data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize; |
1910 | } | 2052 | } |
1911 | } | 2053 | } |
1912 | if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA) | 2054 | if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::WAIT_HTTP_REQ) |
1913 | { | 2055 | { |
1914 | requested_priority = worker->mRequestedPriority; | 2056 | requested_priority = worker->mRequestedPriority; |
1915 | } | 2057 | } |
@@ -1918,7 +2060,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r | |||
1918 | requested_priority = worker->mImagePriority; | 2060 | requested_priority = worker->mImagePriority; |
1919 | } | 2061 | } |
1920 | fetch_priority = worker->getPriority(); | 2062 | fetch_priority = worker->getPriority(); |
1921 | worker->unlockWorkData(); | 2063 | worker->unlockWorkMutex(); |
1922 | } | 2064 | } |
1923 | data_progress_p = data_progress; | 2065 | data_progress_p = data_progress; |
1924 | requested_priority_p = requested_priority; | 2066 | requested_priority_p = requested_priority; |
@@ -1944,5 +2086,3 @@ void LLTextureFetch::dump() | |||
1944 | } | 2086 | } |
1945 | } | 2087 | } |
1946 | 2088 | ||
1947 | |||
1948 | ////////////////////////////////////////////////////////////////////////////// | ||