aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lltexturefetch.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lltexturefetch.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp763
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
43class LLTextureFetchWorker : public LLWorkerClass
44{
45 friend class LLTextureFetchImpl;
46
47public:
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
59private:
60 static void sendRequestListToSimulators();
61
62public:
63 virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
64
65 ~LLTextureFetchWorker();
66 void relese() { --mActiveCount; }
67
68
69protected:
70 LLTextureFetchWorker(const LLUUID& id, const LLHost& host, F32 mPriority, S32 discard);
71
72private:
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
93private:
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
158LLTextureFetchWorker::map_t LLTextureFetchWorker::sRequests;
159LLTextureFetchWorker::queue_t LLTextureFetchWorker::sNetworkQueue;
160LLFrameTimer LLTextureFetchWorker::sNetworkTimer;
161LLWorkerThread* LLTextureFetchWorker::sWorkerThread = NULL;
162LLMutex* LLTextureFetchWorker::sDataMutex = NULL;
163
164// called from MAIN THREAD
165//static
166void 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
174void 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
219void 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
281LLTextureFetchWorker* 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
311LLTextureFetchWorker* 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
324LLTextureFetchWorker::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
355LLTextureFetchWorker::~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
369void LLTextureFetchWorker::clearPackets()
370{
371 lockWorkData();
372 for_each(mPackets.begin(), mPackets.end(), DeletePointer());
373 mPackets.clear();
374 unlockWorkData();
375}
376
377U32 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
384void 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
396void LLTextureFetchWorker::setImagePriority(F32 priority)
397{
398 if (priority != mPriority)
399 {
400 mPriority = priority;
401 setPriority(calcWorkPriority());
402 }
403}
404
405void 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()
427bool 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
535void LLTextureFetchWorker::startWork(S32 param)
536{
537}
538
539void LLTextureFetchWorker::endWork(S32 param, bool aborted)
540{
541}
542
543//////////////////////////////////////////////////////////////////////////////
544
545bool 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
577bool 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
611bool 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
646void LLTextureFetchWorker::startDecode()
647{
648 mRawImage = NULL;
649 mAuxImage = NULL;
650}
651
652bool 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
679void 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
730void 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 //////////////////////////////////////////////////////////////////////////////