diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lltexturefetch.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/lltexturefetch.cpp')
-rw-r--r-- | linden/indra/newview/lltexturefetch.cpp | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp new file mode 100644 index 0000000..9344bbf --- /dev/null +++ b/linden/indra/newview/lltexturefetch.cpp | |||
@@ -0,0 +1,763 @@ | |||
1 | /** | ||
2 | * @file llviewerimage.cpp | ||
3 | * @brief Object which handles a received image (and associated texture(s)) | ||
4 | * | ||
5 | * Copyright (c) 2000-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llstl.h" | ||
31 | |||
32 | #include "lltexturefetch.h" | ||
33 | |||
34 | #include "llworkerthread.h" | ||
35 | #include "llimage.h" | ||
36 | #include "llvfs.h" | ||
37 | |||
38 | #include "llviewerimage.h" | ||
39 | #include "viewer.h" | ||
40 | |||
41 | ////////////////////////////////////////////////////////////////////////////// | ||
42 | |||
43 | class LLTextureFetchWorker : public LLWorkerClass | ||
44 | { | ||
45 | friend class LLTextureFetchImpl; | ||
46 | |||
47 | public: | ||
48 | // From LLWorkerClass | ||
49 | static void initClass(bool threaded, bool runalways); | ||
50 | static void updateClass(); | ||
51 | static void cleanupClass(); | ||
52 | |||
53 | // New methods | ||
54 | static LLTextureFetchWorker* getWorker(const LLUUID& id, const LLHost& host, | ||
55 | F32 mPriority, S32 discard, | ||
56 | BOOL needs_aux = FALSE); | ||
57 | static LLTextureFetchWorker* getActiveWorker(const LLUUID& id); | ||
58 | |||
59 | private: | ||
60 | static void sendRequestListToSimulators(); | ||
61 | |||
62 | public: | ||
63 | virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() | ||
64 | |||
65 | ~LLTextureFetchWorker(); | ||
66 | void relese() { --mActiveCount; } | ||
67 | |||
68 | |||
69 | protected: | ||
70 | LLTextureFetchWorker(const LLUUID& id, const LLHost& host, F32 mPriority, S32 discard); | ||
71 | |||
72 | private: | ||
73 | virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) | ||
74 | virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) | ||
75 | |||
76 | void setImagePriority(F32 priority); | ||
77 | void setDesiredDiscard(S32 discard); | ||
78 | void insertPacket(S32 index, U8* data, S32 size); | ||
79 | void clearPackets(); | ||
80 | U32 calcWorkPriority(); | ||
81 | bool startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type); | ||
82 | bool loadFromVFS(); | ||
83 | bool processSimulatorPackets(); | ||
84 | void startDecode(); | ||
85 | bool decodeImage(); | ||
86 | |||
87 | void lockWorkData() { mWorkMutex.lock(); } | ||
88 | void unlockWorkData() { mWorkMutex.unlock(); } | ||
89 | |||
90 | static void lockQueue() { sDataMutex->lock(); } | ||
91 | static void unlockQueue() { sDataMutex->unlock(); } | ||
92 | |||
93 | private: | ||
94 | enum e_state | ||
95 | { | ||
96 | INIT = 1, | ||
97 | LOAD_FROM_CACHE, | ||
98 | LOAD_FROM_SIMULATOR, | ||
99 | WRITE_TO_VFS, | ||
100 | DECODE_IMAGE, | ||
101 | DECODE_IMAGE_UPDATE, | ||
102 | DONE | ||
103 | }; | ||
104 | e_state mState; | ||
105 | LLPointer<LLImageFormatted> mFormattedImage; | ||
106 | LLPointer<LLImageRaw> mRawImage; | ||
107 | LLPointer<LLImageRaw> mAuxImage; | ||
108 | LLUUID mID; | ||
109 | LLHost mHost; | ||
110 | F32 mPriority; | ||
111 | S32 mDesiredDiscard; | ||
112 | S32 mRequestedDiscard; | ||
113 | S32 mDecodedDiscard; | ||
114 | LLFrameTimer mRequestedTimer; | ||
115 | LLFrameTimer mIdleTimer; | ||
116 | LLVFSThread::handle_t mFileHandle; | ||
117 | U8* mBuffer; | ||
118 | S32 mBufferSize; | ||
119 | S32 mRequestedSize; | ||
120 | BOOL mLoaded; | ||
121 | BOOL mRequested; | ||
122 | BOOL mDecoded; | ||
123 | BOOL mNeedsAux; | ||
124 | S32 mActiveCount; | ||
125 | |||
126 | // Work Data | ||
127 | LLMutex mWorkMutex; | ||
128 | struct PacketData | ||
129 | { | ||
130 | PacketData(U8* data, S32 size) { mData = data; mSize = size; } | ||
131 | ~PacketData() { clearData(); } | ||
132 | void clearData() { delete mData; mData = NULL; } | ||
133 | U8* mData; | ||
134 | U32 mSize; | ||
135 | }; | ||
136 | std::vector<PacketData*> mPackets; | ||
137 | S32 mLastPacket; | ||
138 | S32 mTotalPackets; | ||
139 | S32 mTotalBytes; | ||
140 | |||
141 | // Class variables (statics) | ||
142 | |||
143 | static LLWorkerThread* sWorkerThread; | ||
144 | static LLMutex* sDataMutex; | ||
145 | |||
146 | // Map of all requests by UUID | ||
147 | typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; | ||
148 | static map_t sRequests; | ||
149 | |||
150 | // Set of requests that require network data | ||
151 | typedef std::set<LLTextureFetchWorker*> queue_t ; | ||
152 | static queue_t sNetworkQueue; | ||
153 | |||
154 | static LLFrameTimer sNetworkTimer; | ||
155 | }; | ||
156 | |||
157 | //statics | ||
158 | LLTextureFetchWorker::map_t LLTextureFetchWorker::sRequests; | ||
159 | LLTextureFetchWorker::queue_t LLTextureFetchWorker::sNetworkQueue; | ||
160 | LLFrameTimer LLTextureFetchWorker::sNetworkTimer; | ||
161 | LLWorkerThread* LLTextureFetchWorker::sWorkerThread = NULL; | ||
162 | LLMutex* LLTextureFetchWorker::sDataMutex = NULL; | ||
163 | |||
164 | // called from MAIN THREAD | ||
165 | //static | ||
166 | void LLTextureFetchWorker::initClass(bool threaded, bool runalways) | ||
167 | { | ||
168 | sWorkerThread = new LLWorkerThread(threaded, runalways); | ||
169 | sDataMutex = new LLMutex(sWorkerThread->getAPRPool()); | ||
170 | } | ||
171 | |||
172 | // called from MAIN THREAD | ||
173 | //static | ||
174 | void LLTextureFetchWorker::updateClass() | ||
175 | { | ||
176 | const F32 REQUEST_TIME = 1.f; | ||
177 | const F32 MIN_IDLE_TIME = 1.f * 60.f; // 1 minute | ||
178 | const F32 MAX_IDLE_TIME = 5.f * 60.f; // 5 minutes | ||
179 | const S32 MIN_IDLE_COUNT = 16; // always keep last 16 idle requests | ||
180 | const F32 MAX_IDLE_COUNT = 1024; // max number of idle requests | ||
181 | |||
182 | // Periodically, gather the list of textures that need data from the network | ||
183 | // And send the requests out to the simulators | ||
184 | if (sNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME) | ||
185 | { | ||
186 | sNetworkTimer.reset(); | ||
187 | sendRequestListToSimulators(); | ||
188 | } | ||
189 | // Remove any old requests (releasing their raw data) | ||
190 | typedef std::pair<F32, LLTextureFetchWorker*> idle_pair; | ||
191 | typedef std::set<idle_pair, compare_pair_greater<F32,LLTextureFetchWorker*> > idle_set; | ||
192 | idle_set remove_set; | ||
193 | for (map_t::iterator iter = sRequests.begin(); iter != sRequests.end(); ++iter) | ||
194 | { | ||
195 | LLTextureFetchWorker* worker = iter->second; | ||
196 | if (worker->mActiveCount > 0) | ||
197 | continue; | ||
198 | if (worker->haveWork()) | ||
199 | continue; | ||
200 | F32 idletime = worker->mIdleTimer.getElapsedTimeF32(); | ||
201 | if (idletime < MIN_IDLE_TIME) | ||
202 | continue; | ||
203 | remove_set.insert(std::make_pair(idletime, worker)); | ||
204 | } | ||
205 | S32 num_left = remove_set.size(); | ||
206 | for (idle_set::iterator iter = remove_set.begin(); iter != remove_set.end(); ++iter) | ||
207 | { | ||
208 | if (num_left <= MIN_IDLE_COUNT) | ||
209 | break; | ||
210 | if (iter->first < MAX_IDLE_TIME && | ||
211 | num_left < MAX_IDLE_COUNT) | ||
212 | break; | ||
213 | num_left--; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | // called from MAIN THREAD | ||
218 | //static | ||
219 | void LLTextureFetchWorker::sendRequestListToSimulators() | ||
220 | { | ||
221 | const F32 LAZY_FLUSH_TIMEOUT = 60.f; | ||
222 | const S32 IMAGES_PER_REQUEST = 50; | ||
223 | // Send requests | ||
224 | typedef std::map< LLHost, std::vector<LLTextureFetchWorker*> > work_request_map_t; | ||
225 | work_request_map_t requests; | ||
226 | for (queue_t::iterator iter = sNetworkQueue.begin(); iter != sNetworkQueue.end(); ++iter) | ||
227 | { | ||
228 | LLTextureFetchWorker* req = *iter; | ||
229 | if (req->haveWork()) | ||
230 | { | ||
231 | continue; // busy | ||
232 | } | ||
233 | if ((req->mRequestedDiscard == req->mDesiredDiscard) && | ||
234 | (req->mRequestedTimer.getElapsedTimeF32() < LAZY_FLUSH_TIMEOUT)) | ||
235 | { | ||
236 | continue; | ||
237 | } | ||
238 | req->mRequestedDiscard = req->mDesiredDiscard; | ||
239 | req->mRequestedTimer.reset(); | ||
240 | requests[req->mHost].push_back(req); | ||
241 | } | ||
242 | for (work_request_map_t::iterator iter1 = requests.begin(); | ||
243 | iter1 != requests.end(); ++iter1) | ||
244 | { | ||
245 | LLHost host = iter1->first; | ||
246 | // invalid host = load from static VFS | ||
247 | if (host != LLHost::invalid) | ||
248 | { | ||
249 | S32 request_count = 0; | ||
250 | for (std::vector<LLTextureFetchWorker*>::iterator iter2 = iter1->second.begin(); | ||
251 | iter2 != iter1->second.end(); ++iter2) | ||
252 | { | ||
253 | LLTextureFetchWorker* req = *iter2; | ||
254 | if (0 == request_count) | ||
255 | { | ||
256 | gMessageSystem->newMessageFast(_PREHASH_RequestImage); | ||
257 | } | ||
258 | S32 packet = req->mLastPacket + 1; | ||
259 | gMessageSystem->nextBlockFast(_PREHASH_RequestImage); | ||
260 | gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID); | ||
261 | gMessageSystem->addS32Fast(_PREHASH_DiscardLevel, req->mDesiredDiscard); | ||
262 | gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mPriority); | ||
263 | gMessageSystem->addU32Fast(_PREHASH_Packet, packet); | ||
264 | |||
265 | request_count++; | ||
266 | if (request_count >= IMAGES_PER_REQUEST) | ||
267 | { | ||
268 | gMessageSystem->sendSemiReliable(host, NULL, NULL); | ||
269 | request_count = 0; | ||
270 | } | ||
271 | } | ||
272 | if (request_count >= IMAGES_PER_REQUEST) | ||
273 | { | ||
274 | gMessageSystem->sendSemiReliable(host, NULL, NULL); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | //static | ||
281 | LLTextureFetchWorker* LLTextureFetchWorker::getWorker(const LLUUID& id, | ||
282 | const LLHost& host, | ||
283 | F32 priority, | ||
284 | S32 discard, | ||
285 | BOOL needs_aux) | ||
286 | { | ||
287 | LLTextureFetchWorker* res; | ||
288 | lockQueue(); | ||
289 | map_t::iterator iter = sRequests.find(id); | ||
290 | if (iter != sRequests.end()) | ||
291 | { | ||
292 | res = iter->second; | ||
293 | if (res->mHost != host) | ||
294 | { | ||
295 | llerrs << "LLTextureFetchWorker::getWorker called with multiple hosts" << llendl; | ||
296 | } | ||
297 | res->setImagePriority(priority); | ||
298 | res->setDesiredDiscard(discard); | ||
299 | |||
300 | } | ||
301 | else | ||
302 | { | ||
303 | res = new LLTextureFetchWorker(id, host, priority, discard); | ||
304 | } | ||
305 | unlockQueue(); | ||
306 | res->mActiveCount++; | ||
307 | res->mNeedsAux = needs_aux; | ||
308 | return res; | ||
309 | } | ||
310 | |||
311 | LLTextureFetchWorker* LLTextureFetchWorker::getActiveWorker(const LLUUID& id) | ||
312 | { | ||
313 | LLTextureFetchWorker* res = NULL; | ||
314 | lockQueue(); | ||
315 | map_t::iterator iter = sRequests.find(id); | ||
316 | if (iter != sRequests.end()) | ||
317 | { | ||
318 | res = iter->second; | ||
319 | } | ||
320 | unlockQueue(); | ||
321 | return res; | ||
322 | } | ||
323 | |||
324 | LLTextureFetchWorker::LLTextureFetchWorker(const LLUUID& id, // Image UUID | ||
325 | const LLHost& host, // Simulator host | ||
326 | F32 priority, // Priority | ||
327 | S32 discard) // Desired discard level | ||
328 | : LLWorkerClass(sWorkerThread, "TextureFetch"), | ||
329 | mState(INIT), | ||
330 | mID(id), | ||
331 | mHost(host), | ||
332 | mPriority(priority), | ||
333 | mDesiredDiscard(discard), | ||
334 | mRequestedDiscard(-1), | ||
335 | mDecodedDiscard(-1), | ||
336 | mFileHandle(LLVFSThread::nullHandle()), | ||
337 | mBuffer(NULL), | ||
338 | mBufferSize(0), | ||
339 | mRequestedSize(0), | ||
340 | mLoaded(FALSE), | ||
341 | mRequested(FALSE), | ||
342 | mDecoded(FALSE), | ||
343 | mActiveCount(0), | ||
344 | mWorkMutex(sWorkerThread->getAPRPool()), | ||
345 | mLastPacket(-1), | ||
346 | mTotalPackets(0), | ||
347 | mTotalBytes(0) | ||
348 | { | ||
349 | lockQueue(); | ||
350 | sRequests[mID] = this; | ||
351 | unlockQueue(); | ||
352 | addWork(0, calcWorkPriority()); | ||
353 | } | ||
354 | |||
355 | LLTextureFetchWorker::~LLTextureFetchWorker() | ||
356 | { | ||
357 | lockQueue(); | ||
358 | mFormattedImage = NULL; | ||
359 | map_t::iterator iter = sRequests.find(mID); | ||
360 | if (iter != sRequests.end() && iter->second == this) | ||
361 | { | ||
362 | sRequests.erase(iter); | ||
363 | } | ||
364 | sNetworkQueue.erase(this); | ||
365 | unlockQueue(); | ||
366 | clearPackets(); | ||
367 | } | ||
368 | |||
369 | void LLTextureFetchWorker::clearPackets() | ||
370 | { | ||
371 | lockWorkData(); | ||
372 | for_each(mPackets.begin(), mPackets.end(), DeletePointer()); | ||
373 | mPackets.clear(); | ||
374 | unlockWorkData(); | ||
375 | } | ||
376 | |||
377 | U32 LLTextureFetchWorker::calcWorkPriority() | ||
378 | { | ||
379 | F32 priority_scale = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerImage::maxDecodePriority(); | ||
380 | U32 priority = (U32)(mPriority * priority_scale); | ||
381 | return LLWorkerThread::PRIORITY_NORMAL | priority; | ||
382 | } | ||
383 | |||
384 | void LLTextureFetchWorker::setDesiredDiscard(S32 discard) | ||
385 | { | ||
386 | if (mDesiredDiscard != discard) | ||
387 | { | ||
388 | mDesiredDiscard = discard; | ||
389 | if (!haveWork()) | ||
390 | { | ||
391 | addWork(0, calcWorkPriority()); | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | void LLTextureFetchWorker::setImagePriority(F32 priority) | ||
397 | { | ||
398 | if (priority != mPriority) | ||
399 | { | ||
400 | mPriority = priority; | ||
401 | setPriority(calcWorkPriority()); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | void LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) | ||
406 | { | ||
407 | PacketData* packet = new PacketData(data, size); | ||
408 | |||
409 | lockWorkData(); | ||
410 | if (index >= (S32)mPackets.size()) | ||
411 | { | ||
412 | mPackets.resize(index+1, (PacketData*)NULL); // initializes v to NULL pointers | ||
413 | } | ||
414 | if (mPackets[index] != NULL) | ||
415 | { | ||
416 | llwarns << "LLTextureFetchWorker::insertPacket called for duplicate packet: " << index << llendl; | ||
417 | } | ||
418 | mPackets[index] = packet; | ||
419 | while (mLastPacket+1 < (S32)mPackets.size() && mPackets[mLastPacket+1] != NULL) | ||
420 | { | ||
421 | ++mLastPacket; | ||
422 | } | ||
423 | unlockWorkData(); | ||
424 | } | ||
425 | |||
426 | // Called from LLWorkerThread::processRequest() | ||
427 | bool LLTextureFetchWorker::doWork(S32 param) | ||
428 | { | ||
429 | switch(mState) | ||
430 | { | ||
431 | case INIT: | ||
432 | { | ||
433 | // fall through | ||
434 | } | ||
435 | case LOAD_FROM_CACHE: | ||
436 | { | ||
437 | // Load any existing data from the cache | ||
438 | if (mFileHandle == LLVFSThread::nullHandle()) | ||
439 | { | ||
440 | bool res = startVFSLoad(gVFS, LLAssetType::AT_TEXTURE); | ||
441 | if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE_TGA); | ||
442 | if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE); | ||
443 | if (!res) | ||
444 | { | ||
445 | // Didn't load from VFS | ||
446 | mFormattedImage = new LLImageJ2C; | ||
447 | mState = LOAD_FROM_SIMULATOR; | ||
448 | } | ||
449 | } | ||
450 | if (mFileHandle != LLVFSThread::nullHandle()) | ||
451 | { | ||
452 | if (!loadFromVFS()) | ||
453 | { | ||
454 | return false; // not done | ||
455 | } | ||
456 | if (!mLoaded) | ||
457 | { | ||
458 | llwarns << "Load from VFS failed on: " << mID << llendl; | ||
459 | return true; | ||
460 | } | ||
461 | bool res = mFormattedImage->setData(mBuffer, mBufferSize); | ||
462 | if (!res) | ||
463 | { | ||
464 | llwarns << "loadLocalImage() - setData() failed" << llendl; | ||
465 | mFormattedImage->deleteData(); | ||
466 | return true; | ||
467 | } | ||
468 | // Successfully loaded | ||
469 | if (mFormattedImage->getDiscardLevel() <= mRequestedDiscard) | ||
470 | { | ||
471 | // we have enough data, decode it | ||
472 | mState = DECODE_IMAGE; | ||
473 | mRequestedSize = mBufferSize; | ||
474 | } | ||
475 | else | ||
476 | { | ||
477 | // need more data | ||
478 | mState = LOAD_FROM_SIMULATOR; | ||
479 | mRequestedSize = mFormattedImage->calcDataSize(mRequestedDiscard); | ||
480 | } | ||
481 | } | ||
482 | return false; | ||
483 | } | ||
484 | case LOAD_FROM_SIMULATOR: | ||
485 | { | ||
486 | if (!mRequested) | ||
487 | { | ||
488 | lockQueue(); | ||
489 | sNetworkQueue.insert(this); | ||
490 | unlockQueue(); | ||
491 | mRequested = TRUE; | ||
492 | } | ||
493 | if (processSimulatorPackets()) | ||
494 | { | ||
495 | mState = WRITE_TO_VFS; | ||
496 | } | ||
497 | return false; | ||
498 | } | ||
499 | case WRITE_TO_VFS: | ||
500 | { | ||
501 | mState = DECODE_IMAGE; | ||
502 | // fall through | ||
503 | } | ||
504 | case DECODE_IMAGE: | ||
505 | { | ||
506 | startDecode(); | ||
507 | mState = DECODE_IMAGE_UPDATE; | ||
508 | // fall through | ||
509 | } | ||
510 | case DECODE_IMAGE_UPDATE: | ||
511 | { | ||
512 | if (decodeImage()) | ||
513 | { | ||
514 | mState = DONE; | ||
515 | } | ||
516 | return false; | ||
517 | } | ||
518 | case DONE: | ||
519 | { | ||
520 | // Do any cleanup here | ||
521 | // Destroy the formatted image, we don't need it any more (raw image is still valid) | ||
522 | mFormattedImage = NULL; | ||
523 | mIdleTimer.reset(); | ||
524 | return true; | ||
525 | } | ||
526 | default: | ||
527 | { | ||
528 | llerrs << "LLTextureFetchWorker::doWork() has illegal state" << llendl; | ||
529 | return true; | ||
530 | } | ||
531 | } | ||
532 | } | ||
533 | |||
534 | // Called from MAIN thread | ||
535 | void LLTextureFetchWorker::startWork(S32 param) | ||
536 | { | ||
537 | } | ||
538 | |||
539 | void LLTextureFetchWorker::endWork(S32 param, bool aborted) | ||
540 | { | ||
541 | } | ||
542 | |||
543 | ////////////////////////////////////////////////////////////////////////////// | ||
544 | |||
545 | bool LLTextureFetchWorker::startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type) | ||
546 | { | ||
547 | // Start load from VFS if it's there | ||
548 | if (vfs->getExists(mID, asset_type)) | ||
549 | { | ||
550 | mBufferSize = vfs->getSize(mID, asset_type); | ||
551 | mBuffer = new U8[mBufferSize]; | ||
552 | mFileHandle = LLVFSThread::sLocal->read(vfs, mID, asset_type, mBuffer, 0, mBufferSize); | ||
553 | if (mFileHandle == LLVFSThread::nullHandle()) | ||
554 | { | ||
555 | llwarns << "loadLocalImage() - vfs read failed in static VFS: " << mID << llendl; | ||
556 | delete mBuffer; | ||
557 | mBuffer = NULL; | ||
558 | return false; | ||
559 | } | ||
560 | if (asset_type == LLAssetType::AT_TEXTURE_TGA) | ||
561 | { | ||
562 | mFormattedImage = new LLImageTGA; | ||
563 | } | ||
564 | else if (asset_type == LLAssetType::AT_TEXTURE) | ||
565 | { | ||
566 | mFormattedImage = new LLImageJ2C; | ||
567 | } | ||
568 | else | ||
569 | { | ||
570 | llerrs << "LLTextureFetchWorker::startVFSLoad called with bad asset type: " << asset_type << llendl; | ||
571 | } | ||
572 | return true; | ||
573 | } | ||
574 | return false; | ||
575 | } | ||
576 | |||
577 | bool LLTextureFetchWorker::loadFromVFS() | ||
578 | { | ||
579 | LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); | ||
580 | |||
581 | llassert(mLoaded == FALSE); | ||
582 | |||
583 | // Check loading status | ||
584 | LLVFSThread::status_t status = LLVFSThread::sLocal->getRequestStatus(mFileHandle); | ||
585 | if (status == LLVFSThread::STATUS_QUEUED || status == LLVFSThread::STATUS_INPROGRESS) | ||
586 | { | ||
587 | return false; | ||
588 | } | ||
589 | else if (status == LLVFSThread::STATUS_COMPLETE) | ||
590 | { | ||
591 | mLoaded = TRUE; | ||
592 | return true; | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | llwarns << "loadLocalImage() - vfs read failed" << llendl; | ||
597 | LLVFSThread::Request* req = (LLVFSThread::Request*)LLVFSThread::sLocal->getRequest(mFileHandle); | ||
598 | if (req && mFormattedImage.notNull()) | ||
599 | { | ||
600 | LLVFS* vfs = req->getVFS(); | ||
601 | LLAssetType::EType asset_type = mFormattedImage->getCodec() == IMG_CODEC_TGA ? LLAssetType::AT_TEXTURE_TGA : LLAssetType::AT_TEXTURE; | ||
602 | vfs->removeFile(mID, asset_type); | ||
603 | } | ||
604 | return true; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | |||
609 | ////////////////////////////////////////////////////////////////////////////// | ||
610 | |||
611 | bool LLTextureFetchWorker::processSimulatorPackets() | ||
612 | { | ||
613 | bool res = false; | ||
614 | lockWorkData(); | ||
615 | if (mLastPacket >= 0) | ||
616 | { | ||
617 | S32 data_size = 0; | ||
618 | for (S32 i = 0; i<=mLastPacket; i++) | ||
619 | { | ||
620 | data_size += mPackets[i]->mSize; | ||
621 | } | ||
622 | if (data_size >= mRequestedSize || mLastPacket == mTotalPackets) | ||
623 | { | ||
624 | /// We have enough (or all) data, copy it into mBuffer | ||
625 | if (mBufferSize < data_size) | ||
626 | { | ||
627 | delete mBuffer; | ||
628 | mBuffer = new U8[data_size]; | ||
629 | mBufferSize = data_size; | ||
630 | } | ||
631 | S32 offset = 0; | ||
632 | for (S32 i = 0; i<=mLastPacket; i++) | ||
633 | { | ||
634 | memcpy(mBuffer + offset, mPackets[i]->mData, mPackets[i]->mSize); | ||
635 | offset += mPackets[i]->mSize; | ||
636 | } | ||
637 | res = true; | ||
638 | } | ||
639 | } | ||
640 | unlockWorkData(); | ||
641 | return res; | ||
642 | } | ||
643 | |||
644 | ////////////////////////////////////////////////////////////////////////////// | ||
645 | |||
646 | void LLTextureFetchWorker::startDecode() | ||
647 | { | ||
648 | mRawImage = NULL; | ||
649 | mAuxImage = NULL; | ||
650 | } | ||
651 | |||
652 | bool LLTextureFetchWorker::decodeImage() | ||
653 | { | ||
654 | const F32 MAX_DECODE_TIME = .001f; // 1 ms | ||
655 | if (mRawImage->getDataSize() == 0) | ||
656 | { | ||
657 | if (!mFormattedImage->requestDecodedData(mRawImage, -1, MAX_DECODE_TIME)) | ||
658 | { | ||
659 | return false; | ||
660 | } | ||
661 | mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image | ||
662 | } | ||
663 | if (mNeedsAux && mAuxImage->getDataSize() == 0) | ||
664 | { | ||
665 | if (!mFormattedImage->requestDecodedAuxData(mAuxImage, 4, -1, MAX_DECODE_TIME )) | ||
666 | { | ||
667 | return false; | ||
668 | } | ||
669 | mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image | ||
670 | } | ||
671 | mDecodedDiscard = mFormattedImage->getDiscardLevel(); | ||
672 | return true; | ||
673 | } | ||
674 | |||
675 | ////////////////////////////////////////////////////////////////////////////// | ||
676 | |||
677 | #if 0 | ||
678 | // static | ||
679 | void LLTextureFetchWorker::receiveImageHeader(LLMessageSystem *msg, void **user_data) | ||
680 | { | ||
681 | LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); | ||
682 | |||
683 | // Receive image header, copy into image object and decompresses | ||
684 | // if this is a one-packet image. | ||
685 | |||
686 | gImageList.sTextureBits += msg->getReceiveBytes(); | ||
687 | gImageList.sTexturePackets++; | ||
688 | |||
689 | LLUUID id; | ||
690 | msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); | ||
691 | // LLString ip_string(u32_to_ip_string(msg->getSenderIP())); | ||
692 | |||
693 | LLTextureFetchWorker* worker = getActiveWorker(id); | ||
694 | if (!worker) | ||
695 | { | ||
696 | llwarns << "receiveImageHeader for non active worker: " << id << llendl; | ||
697 | return; | ||
698 | } | ||
699 | worker->mRequestedTimer.reset(); | ||
700 | |||
701 | // check to see if we've gotten this packet before | ||
702 | if (worker->mLastPacket != -1) | ||
703 | { | ||
704 | llwarns << "Img: " << id << ":" << " Duplicate Image Header" << llendl; | ||
705 | return; | ||
706 | } | ||
707 | |||
708 | // Copy header data into image object | ||
709 | worker->lockWorkData(); | ||
710 | msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, image->mDataCodec); | ||
711 | msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, image->mTotalPackets); | ||
712 | msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, image->mTotalBytes); | ||
713 | if (0 == image->mTotalPackets) | ||
714 | { | ||
715 | llwarns << "Img: " << id << ":" << " Number of packets is 0" << llendl; | ||
716 | } | ||
717 | worker->unlockWorkData(); | ||
718 | |||
719 | U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); | ||
720 | if (data_size) | ||
721 | { | ||
722 | U8 *data = new U8[data_size]; | ||
723 | msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); | ||
724 | worker->insertPacket(0, data, data_size) | ||
725 | } | ||
726 | } | ||
727 | |||
728 | /////////////////////////////////////////////////////////////////////////////// | ||
729 | // static | ||
730 | void LLTextureFetchWorker::receiveImagePacket(LLMessageSystem *msg, void **user_data) | ||
731 | { | ||
732 | LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); | ||
733 | LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); | ||
734 | |||
735 | gImageList.sTextureBits += msg->getReceiveBytes(); | ||
736 | gImageList.sTexturePackets++; | ||
737 | |||
738 | LLUUID id; | ||
739 | msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); | ||
740 | // LLString ip_string(u32_to_ip_string(msg->getSenderIP())); | ||
741 | |||
742 | U16 packet_num; | ||
743 | msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num); | ||
744 | |||
745 | LLTextureFetchWorker* worker = getActiveWorker(id); | ||
746 | if (!worker) | ||
747 | { | ||
748 | llwarns << "receiveImageHeader for non active worker: " << id << llendl; | ||
749 | return; | ||
750 | } | ||
751 | worker->mRequestedTimer.reset(); | ||
752 | |||
753 | U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); | ||
754 | if (data_size) | ||
755 | { | ||
756 | U8 *data = new U8[data_size]; | ||
757 | msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); | ||
758 | worker->insertPacket(0, data, data_size) | ||
759 | } | ||
760 | } | ||
761 | #endif | ||
762 | |||
763 | ////////////////////////////////////////////////////////////////////////////// | ||