diff options
Diffstat (limited to 'linden/indra')
88 files changed, 3836 insertions, 1838 deletions
diff --git a/linden/indra/llimage/llimage.cpp b/linden/indra/llimage/llimage.cpp index 4b0076e..32891e7 100644 --- a/linden/indra/llimage/llimage.cpp +++ b/linden/indra/llimage/llimage.cpp | |||
@@ -55,13 +55,9 @@ std::string LLImage::sLastErrorMessage; | |||
55 | LLMutex* LLImage::sMutex = NULL; | 55 | LLMutex* LLImage::sMutex = NULL; |
56 | 56 | ||
57 | //static | 57 | //static |
58 | void LLImage::initClass(LLWorkerThread* workerthread) | 58 | void LLImage::initClass() |
59 | { | 59 | { |
60 | sMutex = new LLMutex(NULL); | 60 | sMutex = new LLMutex(NULL); |
61 | if (workerthread) | ||
62 | { | ||
63 | LLImageWorker::initImageWorker(workerthread); | ||
64 | } | ||
65 | LLImageJ2C::openDSO(); | 61 | LLImageJ2C::openDSO(); |
66 | } | 62 | } |
67 | 63 | ||
@@ -69,7 +65,6 @@ void LLImage::initClass(LLWorkerThread* workerthread) | |||
69 | void LLImage::cleanupClass() | 65 | void LLImage::cleanupClass() |
70 | { | 66 | { |
71 | LLImageJ2C::closeDSO(); | 67 | LLImageJ2C::closeDSO(); |
72 | LLImageWorker::cleanupImageWorker(); | ||
73 | delete sMutex; | 68 | delete sMutex; |
74 | sMutex = NULL; | 69 | sMutex = NULL; |
75 | } | 70 | } |
@@ -1242,25 +1237,28 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip | |||
1242 | ifs.read ((char*)buffer, length); /* Flawfinder: ignore */ | 1237 | ifs.read ((char*)buffer, length); /* Flawfinder: ignore */ |
1243 | ifs.close(); | 1238 | ifs.close(); |
1244 | 1239 | ||
1245 | image->updateData(); | 1240 | BOOL success; |
1246 | 1241 | ||
1247 | if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) | 1242 | success = image->updateData(); |
1243 | if (success) | ||
1248 | { | 1244 | { |
1249 | S32 width = image->getWidth(); | 1245 | if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) |
1250 | S32 height = image->getHeight(); | ||
1251 | S32 discard_level = 0; | ||
1252 | while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) | ||
1253 | { | 1246 | { |
1254 | width >>= 1; | 1247 | S32 width = image->getWidth(); |
1255 | height >>= 1; | 1248 | S32 height = image->getHeight(); |
1256 | discard_level++; | 1249 | S32 discard_level = 0; |
1250 | while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) | ||
1251 | { | ||
1252 | width >>= 1; | ||
1253 | height >>= 1; | ||
1254 | discard_level++; | ||
1255 | } | ||
1256 | ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); | ||
1257 | } | 1257 | } |
1258 | ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); | 1258 | success = image->decode(this, 100000.0f); |
1259 | } | 1259 | } |
1260 | |||
1261 | BOOL success = image->decode(this, 100000.0f); | ||
1262 | image = NULL; // deletes image | ||
1263 | 1260 | ||
1261 | image = NULL; // deletes image | ||
1264 | if (!success) | 1262 | if (!success) |
1265 | { | 1263 | { |
1266 | deleteData(); | 1264 | deleteData(); |
diff --git a/linden/indra/llimage/llimage.h b/linden/indra/llimage/llimage.h index bd609b6..be2eb08 100644 --- a/linden/indra/llimage/llimage.h +++ b/linden/indra/llimage/llimage.h | |||
@@ -49,7 +49,8 @@ const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE; | |||
49 | const S32 MAX_IMAGE_COMPONENTS = 8; | 49 | const S32 MAX_IMAGE_COMPONENTS = 8; |
50 | const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; | 50 | const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; |
51 | 51 | ||
52 | // Note! These CANNOT be changed without invalidating the viewer VFS files, I think? | 52 | // Note! These CANNOT be changed without modifying simulator code |
53 | // *TODO: change both to 1024 when SIM texture fetching is deprecated | ||
53 | const S32 FIRST_PACKET_SIZE = 600; | 54 | const S32 FIRST_PACKET_SIZE = 600; |
54 | const S32 MAX_IMG_PACKET_SIZE = 1000; | 55 | const S32 MAX_IMG_PACKET_SIZE = 1000; |
55 | 56 | ||
@@ -60,7 +61,6 @@ const S32 MAX_IMG_PACKET_SIZE = 1000; | |||
60 | class LLImageFormatted; | 61 | class LLImageFormatted; |
61 | class LLImageRaw; | 62 | class LLImageRaw; |
62 | class LLColor4U; | 63 | class LLColor4U; |
63 | class LLWorkerThread; | ||
64 | 64 | ||
65 | typedef enum e_image_codec | 65 | typedef enum e_image_codec |
66 | { | 66 | { |
@@ -81,7 +81,7 @@ typedef enum e_image_codec | |||
81 | class LLImage | 81 | class LLImage |
82 | { | 82 | { |
83 | public: | 83 | public: |
84 | static void initClass(LLWorkerThread* workerthread); | 84 | static void initClass(); |
85 | static void cleanupClass(); | 85 | static void cleanupClass(); |
86 | 86 | ||
87 | static const std::string& getLastError(); | 87 | static const std::string& getLastError(); |
@@ -309,7 +309,7 @@ protected: | |||
309 | protected: | 309 | protected: |
310 | S8 mCodec; | 310 | S8 mCodec; |
311 | S8 mDecoding; | 311 | S8 mDecoding; |
312 | S8 mDecoded; | 312 | S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC |
313 | S8 mDiscardLevel; | 313 | S8 mDiscardLevel; |
314 | 314 | ||
315 | public: | 315 | public: |
diff --git a/linden/indra/llimage/llimagedxt.cpp b/linden/indra/llimage/llimagedxt.cpp index 1ce4517..0aa6840 100644 --- a/linden/indra/llimage/llimagedxt.cpp +++ b/linden/indra/llimage/llimagedxt.cpp | |||
@@ -264,6 +264,8 @@ void LLImageDXT::setFormat() | |||
264 | // virtual | 264 | // virtual |
265 | BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) | 265 | BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) |
266 | { | 266 | { |
267 | // *TODO: Test! This has been tweaked since its intial inception, | ||
268 | // but we don't use it any more! | ||
267 | llassert_always(raw_image); | 269 | llassert_always(raw_image); |
268 | 270 | ||
269 | if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5) | 271 | if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5) |
@@ -274,8 +276,17 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) | |||
274 | 276 | ||
275 | S32 width = getWidth(), height = getHeight(); | 277 | S32 width = getWidth(), height = getHeight(); |
276 | S32 ncomponents = getComponents(); | 278 | S32 ncomponents = getComponents(); |
279 | U8* data = NULL; | ||
280 | if (mDiscardLevel >= 0) | ||
281 | { | ||
282 | data = getData() + getMipOffset(mDiscardLevel); | ||
283 | calcDiscardWidthHeight(mDiscardLevel, mFileFormat, width, height); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | data = getData() + getMipOffset(0); | ||
288 | } | ||
277 | S32 image_size = formatBytes(mFileFormat, width, height); | 289 | S32 image_size = formatBytes(mFileFormat, width, height); |
278 | U8* data = getData() + getMipOffset(0); | ||
279 | 290 | ||
280 | if ((!getData()) || (data + image_size > getData() + getDataSize())) | 291 | if ((!getData()) || (data + image_size > getData() + getDataSize())) |
281 | { | 292 | { |
@@ -300,10 +311,8 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard) | |||
300 | llerrs << "Request for invalid discard level" << llendl; | 311 | llerrs << "Request for invalid discard level" << llendl; |
301 | } | 312 | } |
302 | U8* data = getData() + getMipOffset(discard); | 313 | U8* data = getData() + getMipOffset(discard); |
303 | // I'm not sure these are the correct initial values for height and width, | 314 | S32 width = 0; |
304 | // but previously they were being used uninitialized. JC | 315 | S32 height = 0; |
305 | S32 width = raw->getWidth(); | ||
306 | S32 height = raw->getHeight(); | ||
307 | calcDiscardWidthHeight(discard, mFileFormat, width, height); | 316 | calcDiscardWidthHeight(discard, mFileFormat, width, height); |
308 | raw = new LLImageRaw(data, width, height, getComponents()); | 317 | raw = new LLImageRaw(data, width, height, getComponents()); |
309 | return TRUE; | 318 | return TRUE; |
diff --git a/linden/indra/llimage/llimagej2c.cpp b/linden/indra/llimage/llimagej2c.cpp index ed58f85..1aae83e 100644 --- a/linden/indra/llimage/llimagej2c.cpp +++ b/linden/indra/llimage/llimagej2c.cpp | |||
@@ -277,6 +277,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) | |||
277 | } | 277 | } |
278 | 278 | ||
279 | 279 | ||
280 | // Returns TRUE to mean done, whether successful or not. | ||
280 | BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count ) | 281 | BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count ) |
281 | { | 282 | { |
282 | LLMemType mt1((LLMemType::EMemType)mMemType); | 283 | LLMemType mt1((LLMemType::EMemType)mMemType); |
@@ -289,7 +290,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir | |||
289 | if (!getData() || (getDataSize() < 16)) | 290 | if (!getData() || (getDataSize() < 16)) |
290 | { | 291 | { |
291 | setLastError("LLImageJ2C uninitialized"); | 292 | setLastError("LLImageJ2C uninitialized"); |
292 | res = FALSE; | 293 | res = TRUE; // done |
293 | } | 294 | } |
294 | else | 295 | else |
295 | { | 296 | { |
@@ -342,7 +343,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, | |||
342 | //static | 343 | //static |
343 | S32 LLImageJ2C::calcHeaderSizeJ2C() | 344 | S32 LLImageJ2C::calcHeaderSizeJ2C() |
344 | { | 345 | { |
345 | return 600; //2048; // ??? hack... just needs to be >= actual header size... | 346 | return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size... |
346 | } | 347 | } |
347 | 348 | ||
348 | //static | 349 | //static |
diff --git a/linden/indra/llimage/llimagejpeg.cpp b/linden/indra/llimage/llimagejpeg.cpp index fa0dd3f..79ea79c 100644 --- a/linden/indra/llimage/llimagejpeg.cpp +++ b/linden/indra/llimage/llimagejpeg.cpp | |||
@@ -188,6 +188,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo) | |||
188 | } | 188 | } |
189 | 189 | ||
190 | 190 | ||
191 | // Returns true when done, whether or not decode was successful. | ||
191 | BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) | 192 | BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) |
192 | { | 193 | { |
193 | llassert_always(raw_image); | 194 | llassert_always(raw_image); |
@@ -198,7 +199,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) | |||
198 | if (!getData() || (0 == getDataSize())) | 199 | if (!getData() || (0 == getDataSize())) |
199 | { | 200 | { |
200 | setLastError("LLImageJPEG trying to decode an image with no data!"); | 201 | setLastError("LLImageJPEG trying to decode an image with no data!"); |
201 | return FALSE; | 202 | return TRUE; // done |
202 | } | 203 | } |
203 | 204 | ||
204 | S32 row_stride = 0; | 205 | S32 row_stride = 0; |
@@ -226,7 +227,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) | |||
226 | if(setjmp(sSetjmpBuffer)) | 227 | if(setjmp(sSetjmpBuffer)) |
227 | { | 228 | { |
228 | jpeg_destroy_decompress(&cinfo); | 229 | jpeg_destroy_decompress(&cinfo); |
229 | return FALSE; | 230 | return TRUE; // done |
230 | } | 231 | } |
231 | try | 232 | try |
232 | { | 233 | { |
@@ -320,7 +321,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) | |||
320 | catch (int) | 321 | catch (int) |
321 | { | 322 | { |
322 | jpeg_destroy_decompress(&cinfo); | 323 | jpeg_destroy_decompress(&cinfo); |
323 | return FALSE; | 324 | return TRUE; // done |
324 | } | 325 | } |
325 | 326 | ||
326 | // Check to see whether any corrupt-data warnings occurred | 327 | // Check to see whether any corrupt-data warnings occurred |
@@ -328,7 +329,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) | |||
328 | { | 329 | { |
329 | // TODO: extract the warning to find out what went wrong. | 330 | // TODO: extract the warning to find out what went wrong. |
330 | setLastError( "Unable to decode JPEG image."); | 331 | setLastError( "Unable to decode JPEG image."); |
331 | return FALSE; | 332 | return TRUE; // done |
332 | } | 333 | } |
333 | 334 | ||
334 | return TRUE; | 335 | return TRUE; |
diff --git a/linden/indra/llimage/llimageworker.cpp b/linden/indra/llimage/llimageworker.cpp index 532e996..86d4151 100644 --- a/linden/indra/llimage/llimageworker.cpp +++ b/linden/indra/llimage/llimageworker.cpp | |||
@@ -37,152 +37,138 @@ | |||
37 | 37 | ||
38 | //---------------------------------------------------------------------------- | 38 | //---------------------------------------------------------------------------- |
39 | 39 | ||
40 | //static | 40 | // MAIN THREAD |
41 | LLWorkerThread* LLImageWorker::sWorkerThread = NULL; | 41 | LLImageDecodeThread::LLImageDecodeThread(bool threaded) |
42 | S32 LLImageWorker::sCount = 0; | 42 | : LLQueuedThread("imagedecode", threaded) |
43 | { | ||
44 | mCreationMutex = new LLMutex(getAPRPool()); | ||
45 | } | ||
43 | 46 | ||
44 | //static | 47 | // MAIN THREAD |
45 | void LLImageWorker::initImageWorker(LLWorkerThread* workerthread) | 48 | // virtual |
49 | S32 LLImageDecodeThread::update(U32 max_time_ms) | ||
46 | { | 50 | { |
47 | sWorkerThread = workerthread; | 51 | LLMutexLock lock(mCreationMutex); |
52 | for (creation_list_t::iterator iter = mCreationList.begin(); | ||
53 | iter != mCreationList.end(); ++iter) | ||
54 | { | ||
55 | creation_info& info = *iter; | ||
56 | ImageRequest* req = new ImageRequest(info.handle, info.image, | ||
57 | info.priority, info.discard, info.needs_aux, | ||
58 | info.responder); | ||
59 | addRequest(req); | ||
60 | } | ||
61 | mCreationList.clear(); | ||
62 | S32 res = LLQueuedThread::update(max_time_ms); | ||
63 | return res; | ||
48 | } | 64 | } |
49 | 65 | ||
50 | //static | 66 | LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, |
51 | void LLImageWorker::cleanupImageWorker() | 67 | U32 priority, S32 discard, BOOL needs_aux, Responder* responder) |
68 | { | ||
69 | LLMutexLock lock(mCreationMutex); | ||
70 | handle_t handle = generateHandle(); | ||
71 | mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); | ||
72 | return handle; | ||
73 | } | ||
74 | |||
75 | // Used by unit test only | ||
76 | // Returns the size of the mutex guarded list as an indication of sanity | ||
77 | S32 LLImageDecodeThread::tut_size() | ||
78 | { | ||
79 | LLMutexLock lock(mCreationMutex); | ||
80 | S32 res = mCreationList.size(); | ||
81 | return res; | ||
82 | } | ||
83 | |||
84 | LLImageDecodeThread::Responder::~Responder() | ||
52 | { | 85 | { |
53 | } | 86 | } |
54 | 87 | ||
55 | //---------------------------------------------------------------------------- | 88 | //---------------------------------------------------------------------------- |
56 | 89 | ||
57 | LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, | 90 | LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image, |
58 | S32 discard, | 91 | U32 priority, S32 discard, BOOL needs_aux, |
59 | LLPointer<LLResponder> responder) | 92 | LLImageDecodeThread::Responder* responder) |
60 | : LLWorkerClass(sWorkerThread, "Image"), | 93 | : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), |
61 | mFormattedImage(image), | 94 | mFormattedImage(image), |
62 | mDecodedType(-1), | ||
63 | mDiscardLevel(discard), | 95 | mDiscardLevel(discard), |
64 | mPriority(priority), | 96 | mNeedsAux(needs_aux), |
97 | mDecodedRaw(FALSE), | ||
98 | mDecodedAux(FALSE), | ||
65 | mResponder(responder) | 99 | mResponder(responder) |
66 | { | 100 | { |
67 | ++sCount; | ||
68 | } | 101 | } |
69 | 102 | ||
70 | LLImageWorker::~LLImageWorker() | 103 | LLImageDecodeThread::ImageRequest::~ImageRequest() |
71 | { | 104 | { |
72 | mDecodedImage = NULL; | 105 | mDecodedImageRaw = NULL; |
106 | mDecodedImageAux = NULL; | ||
73 | mFormattedImage = NULL; | 107 | mFormattedImage = NULL; |
74 | --sCount; | ||
75 | } | 108 | } |
76 | 109 | ||
77 | //---------------------------------------------------------------------------- | 110 | //---------------------------------------------------------------------------- |
78 | 111 | ||
79 | //virtual, main thread | ||
80 | void LLImageWorker::startWork(S32 param) | ||
81 | { | ||
82 | llassert_always(mDecodedImage.isNull()); | ||
83 | mDecodedType = -1; | ||
84 | } | ||
85 | 112 | ||
86 | bool LLImageWorker::doWork(S32 param) | 113 | // Returns true when done, whether or not decode was successful. |
114 | bool LLImageDecodeThread::ImageRequest::processRequest() | ||
87 | { | 115 | { |
88 | bool decoded = false; | 116 | const F32 decode_time_slice = .1f; |
89 | if(mDecodedImage.isNull()) | 117 | bool done = true; |
118 | if (!mDecodedRaw && mFormattedImage.notNull()) | ||
90 | { | 119 | { |
91 | if (!mFormattedImage->updateData()) | 120 | // Decode primary channels |
92 | { | 121 | if (mDecodedImageRaw.isNull()) |
93 | mDecodedType = -2; // failed | ||
94 | return true; | ||
95 | } | ||
96 | if (mDiscardLevel >= 0) | ||
97 | { | 122 | { |
98 | mFormattedImage->setDiscardLevel(mDiscardLevel); | 123 | // parse formatted header |
99 | } | 124 | if (!mFormattedImage->updateData()) |
100 | if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents())) | 125 | { |
101 | { | 126 | return true; // done (failed) |
102 | decoded = true; // failed | 127 | } |
103 | } | 128 | if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents())) |
104 | else | 129 | { |
105 | { | 130 | return true; // done (failed) |
106 | mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding | 131 | } |
132 | if (mDiscardLevel >= 0) | ||
133 | { | ||
134 | mFormattedImage->setDiscardLevel(mDiscardLevel); | ||
135 | } | ||
136 | mDecodedImageRaw = new LLImageRaw(mFormattedImage->getWidth(), | ||
137 | mFormattedImage->getHeight(), | ||
138 | mFormattedImage->getComponents()); | ||
107 | } | 139 | } |
140 | done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms | ||
141 | mDecodedRaw = done; | ||
108 | } | 142 | } |
109 | if (!decoded) | 143 | if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull()) |
110 | { | 144 | { |
111 | if (param == 0) | 145 | // Decode aux channel |
112 | { | 146 | if (!mDecodedImageAux) |
113 | // Decode primary channels | ||
114 | decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms | ||
115 | } | ||
116 | else | ||
117 | { | 147 | { |
118 | // Decode aux channel | 148 | mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(), |
119 | decoded = mFormattedImage->decodeChannels(mDecodedImage, .1f, param, param); // 1ms | 149 | mFormattedImage->getHeight(), |
150 | 1); | ||
120 | } | 151 | } |
152 | done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms | ||
153 | mDecodedAux = done; | ||
121 | } | 154 | } |
122 | if (decoded) | ||
123 | { | ||
124 | // Call the callback immediately; endWork doesn't get called until ckeckWork | ||
125 | if (mResponder.notNull()) | ||
126 | { | ||
127 | bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0); | ||
128 | mResponder->completed(success); | ||
129 | } | ||
130 | } | ||
131 | return decoded; | ||
132 | } | ||
133 | 155 | ||
134 | void LLImageWorker::endWork(S32 param, bool aborted) | 156 | return done; |
135 | { | ||
136 | if (mDecodedType != -2) | ||
137 | { | ||
138 | mDecodedType = aborted ? -2 : param; | ||
139 | } | ||
140 | } | 157 | } |
141 | 158 | ||
142 | //---------------------------------------------------------------------------- | 159 | void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) |
143 | |||
144 | |||
145 | BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard) | ||
146 | { | 160 | { |
147 | // For most codecs, only mDiscardLevel data is available. | 161 | if (mResponder.notNull()) |
148 | // (see LLImageDXT for exception) | ||
149 | if (discard >= 0 && discard != mFormattedImage->getDiscardLevel()) | ||
150 | { | ||
151 | llerrs << "Request for invalid discard level" << llendl; | ||
152 | } | ||
153 | checkWork(); | ||
154 | if (mDecodedType == -2) | ||
155 | { | 162 | { |
156 | return TRUE; // aborted, done | 163 | bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); |
157 | } | 164 | mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); |
158 | if (mDecodedType != channel) | ||
159 | { | ||
160 | if (!haveWork()) | ||
161 | { | ||
162 | addWork(channel, mPriority); | ||
163 | } | ||
164 | return FALSE; | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | llassert_always(!haveWork()); | ||
169 | llassert_always(mDecodedType == channel); | ||
170 | raw = mDecodedImage; // smart pointer acquires ownership of data | ||
171 | mDecodedImage = NULL; | ||
172 | return TRUE; | ||
173 | } | 165 | } |
166 | // Will automatically be deleted | ||
174 | } | 167 | } |
175 | 168 | ||
176 | BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard) | 169 | // Used by unit test only |
170 | // Checks that a responder exists for this instance so that something can happen when completion is reached | ||
171 | bool LLImageDecodeThread::ImageRequest::tut_isOK() | ||
177 | { | 172 | { |
178 | if (mFormattedImage->getCodec() == IMG_CODEC_DXT) | 173 | return mResponder.notNull(); |
179 | { | ||
180 | // special case | ||
181 | LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage); | ||
182 | return imagedxt->getMipData(raw, discard); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | return requestDecodedAuxData(raw, 0, discard); | ||
187 | } | ||
188 | } | 174 | } |
diff --git a/linden/indra/llimage/llimageworker.h b/linden/indra/llimage/llimageworker.h index 879fcf5..fcd3039 100644 --- a/linden/indra/llimage/llimageworker.h +++ b/linden/indra/llimage/llimageworker.h | |||
@@ -34,51 +34,74 @@ | |||
34 | #define LL_LLIMAGEWORKER_H | 34 | #define LL_LLIMAGEWORKER_H |
35 | 35 | ||
36 | #include "llimage.h" | 36 | #include "llimage.h" |
37 | #include "llworkerthread.h" | 37 | #include "llqueuedthread.h" |
38 | 38 | ||
39 | class LLImageWorker : public LLWorkerClass | 39 | class LLImageDecodeThread : public LLQueuedThread |
40 | { | 40 | { |
41 | public: | 41 | public: |
42 | static void initImageWorker(LLWorkerThread* workerthread); | 42 | class Responder : public LLThreadSafeRefCount |
43 | static void cleanupImageWorker(); | 43 | { |
44 | 44 | protected: | |
45 | public: | 45 | virtual ~Responder(); |
46 | static LLWorkerThread* getWorkerThread() { return sWorkerThread; } | 46 | public: |
47 | 47 | virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; | |
48 | // LLWorkerThread | 48 | }; |
49 | public: | ||
50 | LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, | ||
51 | LLPointer<LLResponder> responder); | ||
52 | ~LLImageWorker(); | ||
53 | |||
54 | // called from WORKER THREAD, returns TRUE if done | ||
55 | /*virtual*/ bool doWork(S32 param); | ||
56 | |||
57 | BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1); | ||
58 | BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1); | ||
59 | void releaseDecodedData(); | ||
60 | void cancelDecode(); | ||
61 | 49 | ||
62 | private: | 50 | class ImageRequest : public LLQueuedThread::QueuedRequest |
63 | // called from MAIN THREAD | 51 | { |
64 | /*virtual*/ void startWork(S32 param); // called from addWork() | 52 | protected: |
65 | /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() | 53 | virtual ~ImageRequest(); // use deleteRequest() |
54 | |||
55 | public: | ||
56 | ImageRequest(handle_t handle, LLImageFormatted* image, | ||
57 | U32 priority, S32 discard, BOOL needs_aux, | ||
58 | LLImageDecodeThread::Responder* responder); | ||
66 | 59 | ||
67 | protected: | 60 | /*virtual*/ bool processRequest(); |
68 | LLPointer<LLImageFormatted> mFormattedImage; | 61 | /*virtual*/ void finishRequest(bool completed); |
69 | LLPointer<LLImageRaw> mDecodedImage; | ||
70 | S32 mDecodedType; | ||
71 | S32 mDiscardLevel; | ||
72 | 62 | ||
73 | private: | 63 | // Used by unit tests to check the consitency of the request instance |
74 | U32 mPriority; | 64 | bool tut_isOK(); |
75 | LLPointer<LLResponder> mResponder; | 65 | |
66 | private: | ||
67 | // input | ||
68 | LLPointer<LLImageFormatted> mFormattedImage; | ||
69 | S32 mDiscardLevel; | ||
70 | BOOL mNeedsAux; | ||
71 | // output | ||
72 | LLPointer<LLImageRaw> mDecodedImageRaw; | ||
73 | LLPointer<LLImageRaw> mDecodedImageAux; | ||
74 | BOOL mDecodedRaw; | ||
75 | BOOL mDecodedAux; | ||
76 | LLPointer<LLImageDecodeThread::Responder> mResponder; | ||
77 | }; | ||
76 | 78 | ||
77 | protected: | ||
78 | static LLWorkerThread* sWorkerThread; | ||
79 | |||
80 | public: | 79 | public: |
81 | static S32 sCount; | 80 | LLImageDecodeThread(bool threaded = true); |
81 | handle_t decodeImage(LLImageFormatted* image, | ||
82 | U32 priority, S32 discard, BOOL needs_aux, | ||
83 | Responder* responder); | ||
84 | S32 update(U32 max_time_ms); | ||
85 | |||
86 | // Used by unit tests to check the consistency of the thread instance | ||
87 | S32 tut_size(); | ||
88 | |||
89 | private: | ||
90 | struct creation_info | ||
91 | { | ||
92 | handle_t handle; | ||
93 | LLImageFormatted* image; | ||
94 | U32 priority; | ||
95 | S32 discard; | ||
96 | BOOL needs_aux; | ||
97 | LLPointer<Responder> responder; | ||
98 | creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r) | ||
99 | : handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r) | ||
100 | {} | ||
101 | }; | ||
102 | typedef std::list<creation_info> creation_list_t; | ||
103 | creation_list_t mCreationList; | ||
104 | LLMutex* mCreationMutex; | ||
82 | }; | 105 | }; |
83 | 106 | ||
84 | #endif | 107 | #endif |
diff --git a/linden/indra/llrender/llcubemap.cpp b/linden/indra/llrender/llcubemap.cpp index 754d90c..a5c677d 100644 --- a/linden/indra/llrender/llcubemap.cpp +++ b/linden/indra/llrender/llcubemap.cpp | |||
@@ -94,7 +94,7 @@ void LLCubeMap::initGL() | |||
94 | mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); | 94 | mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); |
95 | mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); | 95 | mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); |
96 | mRawImages[i] = new LLImageRaw(64, 64, 4); | 96 | mRawImages[i] = new LLImageRaw(64, 64, 4); |
97 | mImages[i]->createGLTexture(0, mRawImages[i], texname); | 97 | mImages[i]->createGLTexture(0, mRawImages[i], texname, TRUE); |
98 | 98 | ||
99 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); | 99 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); |
100 | mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); | 100 | mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); |
@@ -106,7 +106,7 @@ void LLCubeMap::initGL() | |||
106 | } | 106 | } |
107 | else | 107 | else |
108 | { | 108 | { |
109 | llwarns << "Using cube map without extension!" << llendl | 109 | llwarns << "Using cube map without extension!" << llendl; |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp index d1efb11..27b1d55 100644 --- a/linden/indra/llrender/llimagegl.cpp +++ b/linden/indra/llrender/llimagegl.cpp | |||
@@ -43,8 +43,6 @@ | |||
43 | #include "llmath.h" | 43 | #include "llmath.h" |
44 | #include "llgl.h" | 44 | #include "llgl.h" |
45 | #include "llrender.h" | 45 | #include "llrender.h" |
46 | |||
47 | |||
48 | //---------------------------------------------------------------------------- | 46 | //---------------------------------------------------------------------------- |
49 | 47 | ||
50 | const F32 MIN_TEXTURE_LIFETIME = 10.f; | 48 | const F32 MIN_TEXTURE_LIFETIME = 10.f; |
@@ -61,8 +59,33 @@ S32 LLImageGL::sCount = 0; | |||
61 | 59 | ||
62 | BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; | 60 | BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; |
63 | F32 LLImageGL::sLastFrameTime = 0.f; | 61 | F32 LLImageGL::sLastFrameTime = 0.f; |
62 | BOOL LLImageGL::sAllowReadBackRaw = FALSE ; | ||
64 | 63 | ||
65 | std::set<LLImageGL*> LLImageGL::sImageList; | 64 | std::set<LLImageGL*> LLImageGL::sImageList; |
65 | |||
66 | //**************************************************************************************************** | ||
67 | //The below for texture auditing use only | ||
68 | //**************************************************************************************************** | ||
69 | //----------------------- | ||
70 | //debug use | ||
71 | BOOL gAuditTexture = FALSE ; | ||
72 | #define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 | ||
73 | std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; | ||
74 | std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; | ||
75 | std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; | ||
76 | S32 LLImageGL::sCurTexSizeBar = -1 ; | ||
77 | S32 LLImageGL::sCurTexPickSize = -1 ; | ||
78 | LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL; | ||
79 | S32 LLImageGL::sMaxCatagories = 1 ; | ||
80 | |||
81 | std::vector<S32> LLImageGL::sTextureMemByCategory; | ||
82 | std::vector<S32> LLImageGL::sTextureMemByCategoryBound ; | ||
83 | std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ; | ||
84 | //------------------------ | ||
85 | //**************************************************************************************************** | ||
86 | //End for texture auditing use only | ||
87 | //**************************************************************************************************** | ||
88 | |||
66 | //************************************************************************************** | 89 | //************************************************************************************** |
67 | //below are functions for debug use | 90 | //below are functions for debug use |
68 | //do not delete them even though they are not currently being used. | 91 | //do not delete them even though they are not currently being used. |
@@ -110,6 +133,20 @@ void LLImageGL::checkTexSize() const | |||
110 | //************************************************************************************** | 133 | //************************************************************************************** |
111 | 134 | ||
112 | //---------------------------------------------------------------------------- | 135 | //---------------------------------------------------------------------------- |
136 | //static | ||
137 | void LLImageGL::initClass(S32 num_catagories) | ||
138 | { | ||
139 | sMaxCatagories = num_catagories ; | ||
140 | |||
141 | sTextureMemByCategory.resize(sMaxCatagories); | ||
142 | sTextureMemByCategoryBound.resize(sMaxCatagories) ; | ||
143 | sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; | ||
144 | } | ||
145 | |||
146 | //static | ||
147 | void LLImageGL::cleanupClass() | ||
148 | { | ||
149 | } | ||
113 | 150 | ||
114 | //static | 151 | //static |
115 | S32 LLImageGL::dataFormatBits(S32 dataformat) | 152 | S32 LLImageGL::dataFormatBits(S32 dataformat) |
@@ -176,12 +213,44 @@ void LLImageGL::updateStats(F32 current_time) | |||
176 | sLastFrameTime = current_time; | 213 | sLastFrameTime = current_time; |
177 | sBoundTextureMemoryInBytes = sCurBoundTextureMemory; | 214 | sBoundTextureMemoryInBytes = sCurBoundTextureMemory; |
178 | sCurBoundTextureMemory = 0; | 215 | sCurBoundTextureMemory = 0; |
216 | |||
217 | if(gAuditTexture) | ||
218 | { | ||
219 | for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) | ||
220 | { | ||
221 | sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; | ||
222 | sTextureCurBoundCounter[i] = 0 ; | ||
223 | } | ||
224 | for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) | ||
225 | { | ||
226 | sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; | ||
227 | sTextureCurMemByCategoryBound[i] = 0 ; | ||
228 | } | ||
229 | } | ||
179 | } | 230 | } |
180 | 231 | ||
181 | //static | 232 | //static |
182 | S32 LLImageGL::updateBoundTexMem(const S32 delta) | 233 | S32 LLImageGL::updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) |
234 | { | ||
235 | if(gAuditTexture) | ||
236 | { | ||
237 | sTextureCurBoundCounter[getTextureCounterIndex(size)]++ ; | ||
238 | sTextureCurMemByCategoryBound[category] += delta ; | ||
239 | } | ||
240 | |||
241 | LLImageGL::sCurBoundTextureMemory += delta ; | ||
242 | return LLImageGL::sCurBoundTextureMemory; | ||
243 | } | ||
244 | |||
245 | S32 LLImageGL::updateBoundTexMem()const | ||
183 | { | 246 | { |
184 | LLImageGL::sCurBoundTextureMemory += delta; | 247 | if(gAuditTexture) |
248 | { | ||
249 | sTextureCurBoundCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; | ||
250 | sTextureCurMemByCategoryBound[mCategory] += mTextureMemory ; | ||
251 | } | ||
252 | |||
253 | LLImageGL::sCurBoundTextureMemory += mTextureMemory ; | ||
185 | return LLImageGL::sCurBoundTextureMemory; | 254 | return LLImageGL::sCurBoundTextureMemory; |
186 | } | 255 | } |
187 | 256 | ||
@@ -195,6 +264,7 @@ void LLImageGL::destroyGL(BOOL save_state) | |||
195 | gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); | 264 | gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); |
196 | } | 265 | } |
197 | 266 | ||
267 | sAllowReadBackRaw = true ; | ||
198 | for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); | 268 | for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); |
199 | iter != sImageList.end(); iter++) | 269 | iter != sImageList.end(); iter++) |
200 | { | 270 | { |
@@ -204,7 +274,7 @@ void LLImageGL::destroyGL(BOOL save_state) | |||
204 | if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) | 274 | if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) |
205 | { | 275 | { |
206 | glimage->mSaveData = new LLImageRaw; | 276 | glimage->mSaveData = new LLImageRaw; |
207 | if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) | 277 | if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it. |
208 | { | 278 | { |
209 | glimage->mSaveData = NULL ; | 279 | glimage->mSaveData = NULL ; |
210 | } | 280 | } |
@@ -214,6 +284,7 @@ void LLImageGL::destroyGL(BOOL save_state) | |||
214 | stop_glerror(); | 284 | stop_glerror(); |
215 | } | 285 | } |
216 | } | 286 | } |
287 | sAllowReadBackRaw = false ; | ||
217 | } | 288 | } |
218 | 289 | ||
219 | //static | 290 | //static |
@@ -231,7 +302,7 @@ void LLImageGL::restoreGL() | |||
231 | { | 302 | { |
232 | if (glimage->getComponents() && glimage->mSaveData->getComponents()) | 303 | if (glimage->getComponents() && glimage->mSaveData->getComponents()) |
233 | { | 304 | { |
234 | glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); | 305 | glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); |
235 | stop_glerror(); | 306 | stop_glerror(); |
236 | } | 307 | } |
237 | glimage->mSaveData = NULL; // deletes data | 308 | glimage->mSaveData = NULL; // deletes data |
@@ -311,7 +382,7 @@ void LLImageGL::init(BOOL usemipmaps) | |||
311 | mTextureState = NO_DELETE ; | 382 | mTextureState = NO_DELETE ; |
312 | mTextureMemory = 0; | 383 | mTextureMemory = 0; |
313 | mLastBindTime = 0.f; | 384 | mLastBindTime = 0.f; |
314 | 385 | ||
315 | mTarget = GL_TEXTURE_2D; | 386 | mTarget = GL_TEXTURE_2D; |
316 | mBindTarget = LLTexUnit::TT_TEXTURE; | 387 | mBindTarget = LLTexUnit::TT_TEXTURE; |
317 | mUseMipMaps = usemipmaps; | 388 | mUseMipMaps = usemipmaps; |
@@ -338,7 +409,9 @@ void LLImageGL::init(BOOL usemipmaps) | |||
338 | mHasExplicitFormat = FALSE; | 409 | mHasExplicitFormat = FALSE; |
339 | 410 | ||
340 | mGLTextureCreated = FALSE ; | 411 | mGLTextureCreated = FALSE ; |
412 | |||
341 | mIsMask = FALSE; | 413 | mIsMask = FALSE; |
414 | mCategory = -1 ; | ||
342 | } | 415 | } |
343 | 416 | ||
344 | void LLImageGL::cleanup() | 417 | void LLImageGL::cleanup() |
@@ -438,6 +511,10 @@ void LLImageGL::dump() | |||
438 | } | 511 | } |
439 | 512 | ||
440 | //---------------------------------------------------------------------------- | 513 | //---------------------------------------------------------------------------- |
514 | void LLImageGL::forceUpdateBindStats(void) const | ||
515 | { | ||
516 | mLastBindTime = sLastFrameTime; | ||
517 | } | ||
441 | 518 | ||
442 | void LLImageGL::updateBindStats(void) const | 519 | void LLImageGL::updateBindStats(void) const |
443 | { | 520 | { |
@@ -451,7 +528,8 @@ void LLImageGL::updateBindStats(void) const | |||
451 | { | 528 | { |
452 | // we haven't accounted for this texture yet this frame | 529 | // we haven't accounted for this texture yet this frame |
453 | sUniqueCount++; | 530 | sUniqueCount++; |
454 | updateBoundTexMem(mTextureMemory); | 531 | |
532 | updateBoundTexMem(); | ||
455 | mLastBindTime = sLastFrameTime; | 533 | mLastBindTime = sLastFrameTime; |
456 | } | 534 | } |
457 | } | 535 | } |
@@ -464,7 +542,7 @@ bool LLImageGL::bindError(const S32 stage) const | |||
464 | } | 542 | } |
465 | 543 | ||
466 | //virtual | 544 | //virtual |
467 | bool LLImageGL::bindDefaultImage(const S32 stage) const | 545 | bool LLImageGL::bindDefaultImage(const S32 stage) |
468 | { | 546 | { |
469 | return false; | 547 | return false; |
470 | } | 548 | } |
@@ -503,7 +581,6 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) | |||
503 | void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | 581 | void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) |
504 | { | 582 | { |
505 | // LLFastTimer t1(LLFastTimer::FTM_TEMP1); | 583 | // LLFastTimer t1(LLFastTimer::FTM_TEMP1); |
506 | llpushcallstacks ; | ||
507 | bool is_compressed = false; | 584 | bool is_compressed = false; |
508 | if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) | 585 | if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) |
509 | { | 586 | { |
@@ -716,12 +793,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
716 | } | 793 | } |
717 | stop_glerror(); | 794 | stop_glerror(); |
718 | mGLTextureCreated = true; | 795 | mGLTextureCreated = true; |
719 | llpushcallstacks ; | ||
720 | } | 796 | } |
721 | 797 | ||
722 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) | 798 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) |
723 | { | 799 | { |
724 | llpushcallstacks ; | ||
725 | if (!width || !height) | 800 | if (!width || !height) |
726 | { | 801 | { |
727 | return TRUE; | 802 | return TRUE; |
@@ -737,7 +812,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 | |||
737 | return FALSE; | 812 | return FALSE; |
738 | } | 813 | } |
739 | 814 | ||
740 | if (x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) | 815 | // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. |
816 | if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) | ||
741 | { | 817 | { |
742 | setImage(datap, FALSE); | 818 | setImage(datap, FALSE); |
743 | } | 819 | } |
@@ -810,20 +886,20 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 | |||
810 | stop_glerror(); | 886 | stop_glerror(); |
811 | mGLTextureCreated = true; | 887 | mGLTextureCreated = true; |
812 | } | 888 | } |
813 | llpushcallstacks ; | ||
814 | return TRUE; | 889 | return TRUE; |
815 | } | 890 | } |
816 | 891 | ||
817 | BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) | 892 | BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) |
818 | { | 893 | { |
819 | return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height); | 894 | return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); |
820 | } | 895 | } |
821 | 896 | ||
822 | // Copy sub image from frame buffer | 897 | // Copy sub image from frame buffer |
823 | BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height) | 898 | BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height) |
824 | { | 899 | { |
825 | if (gGL.getTexUnit(0)->bind(this, true)) | 900 | if (gGL.getTexUnit(0)->bind(this, false, true)) |
826 | { | 901 | { |
902 | //checkTexSize() ; | ||
827 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); | 903 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); |
828 | mGLTextureCreated = true; | 904 | mGLTextureCreated = true; |
829 | stop_glerror(); | 905 | stop_glerror(); |
@@ -883,14 +959,14 @@ BOOL LLImageGL::createGLTexture() | |||
883 | return TRUE ; | 959 | return TRUE ; |
884 | } | 960 | } |
885 | 961 | ||
886 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) | 962 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) |
887 | { | 963 | { |
888 | llpushcallstacks ; | ||
889 | if (gGLManager.mIsDisabled) | 964 | if (gGLManager.mIsDisabled) |
890 | { | 965 | { |
891 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; | 966 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; |
892 | return FALSE; | 967 | return FALSE; |
893 | } | 968 | } |
969 | |||
894 | mGLTextureCreated = false ; | 970 | mGLTextureCreated = false ; |
895 | llassert(gGLManager.mInited); | 971 | llassert(gGLManager.mInited); |
896 | stop_glerror(); | 972 | stop_glerror(); |
@@ -903,8 +979,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S | |||
903 | discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); | 979 | discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); |
904 | 980 | ||
905 | // Actual image width/height = raw image width/height * 2^discard_level | 981 | // Actual image width/height = raw image width/height * 2^discard_level |
906 | S32 w = imageraw->getWidth() << discard_level; | 982 | S32 raw_w = imageraw->getWidth() ; |
907 | S32 h = imageraw->getHeight() << discard_level; | 983 | S32 raw_h = imageraw->getHeight() ; |
984 | S32 w = raw_w << discard_level; | ||
985 | S32 h = raw_h << discard_level; | ||
908 | 986 | ||
909 | // setSize may call destroyGLTexture if the size does not match | 987 | // setSize may call destroyGLTexture if the size does not match |
910 | setSize(w, h, imageraw->getComponents()); | 988 | setSize(w, h, imageraw->getComponents()); |
@@ -940,13 +1018,21 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S | |||
940 | } | 1018 | } |
941 | } | 1019 | } |
942 | 1020 | ||
1021 | if(!to_create) //not create a gl texture | ||
1022 | { | ||
1023 | destroyGLTexture(); | ||
1024 | mCurrentDiscardLevel = discard_level; | ||
1025 | mLastBindTime = sLastFrameTime; | ||
1026 | return TRUE ; | ||
1027 | } | ||
1028 | |||
1029 | mCategory = category ; | ||
943 | const U8* rawdata = imageraw->getData(); | 1030 | const U8* rawdata = imageraw->getData(); |
944 | return createGLTexture(discard_level, rawdata, FALSE, usename); | 1031 | return createGLTexture(discard_level, rawdata, FALSE, usename); |
945 | } | 1032 | } |
946 | 1033 | ||
947 | BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) | 1034 | BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) |
948 | { | 1035 | { |
949 | llpushcallstacks ; | ||
950 | llassert(data_in); | 1036 | llassert(data_in); |
951 | 1037 | ||
952 | if (discard_level < 0) | 1038 | if (discard_level < 0) |
@@ -1014,7 +1100,14 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
1014 | if (old_name != 0) | 1100 | if (old_name != 0) |
1015 | { | 1101 | { |
1016 | sGlobalTextureMemoryInBytes -= mTextureMemory; | 1102 | sGlobalTextureMemoryInBytes -= mTextureMemory; |
1103 | |||
1104 | if(gAuditTexture) | ||
1105 | { | ||
1106 | decTextureCounter() ; | ||
1107 | } | ||
1108 | |||
1017 | LLImageGL::deleteTextures(1, &old_name); | 1109 | LLImageGL::deleteTextures(1, &old_name); |
1110 | |||
1018 | stop_glerror(); | 1111 | stop_glerror(); |
1019 | } | 1112 | } |
1020 | 1113 | ||
@@ -1022,13 +1115,15 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
1022 | sGlobalTextureMemoryInBytes += mTextureMemory; | 1115 | sGlobalTextureMemoryInBytes += mTextureMemory; |
1023 | setActive() ; | 1116 | setActive() ; |
1024 | 1117 | ||
1118 | if(gAuditTexture) | ||
1119 | { | ||
1120 | incTextureCounter() ; | ||
1121 | } | ||
1025 | // mark this as bound at this point, so we don't throw it out immediately | 1122 | // mark this as bound at this point, so we don't throw it out immediately |
1026 | mLastBindTime = sLastFrameTime; | 1123 | mLastBindTime = sLastFrameTime; |
1027 | |||
1028 | llpushcallstacks ; | ||
1029 | return TRUE; | 1124 | return TRUE; |
1030 | } | 1125 | } |
1031 | 1126 | #if 0 | |
1032 | BOOL LLImageGL::setDiscardLevel(S32 discard_level) | 1127 | BOOL LLImageGL::setDiscardLevel(S32 discard_level) |
1033 | { | 1128 | { |
1034 | llassert(discard_level >= 0); | 1129 | llassert(discard_level >= 0); |
@@ -1080,25 +1175,14 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level) | |||
1080 | return FALSE; | 1175 | return FALSE; |
1081 | } | 1176 | } |
1082 | } | 1177 | } |
1083 | 1178 | #endif | |
1084 | BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) | ||
1085 | { | ||
1086 | assert_glerror(); | ||
1087 | S32 gl_discard = discard_level - mCurrentDiscardLevel; | ||
1088 | LLGLint glwidth = 0; | ||
1089 | glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); | ||
1090 | LLGLint glheight = 0; | ||
1091 | glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight); | ||
1092 | LLGLint glcomponents = 0 ; | ||
1093 | glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents); | ||
1094 | assert_glerror(); | ||
1095 | |||
1096 | return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ; | ||
1097 | } | ||
1098 | 1179 | ||
1099 | BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) | 1180 | BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) |
1100 | { | 1181 | { |
1101 | llpushcallstacks ; | 1182 | // VWR-13505 : Merov : Allow gl texture read back so save texture works again (temporary) |
1183 | //llassert_always(sAllowReadBackRaw) ; | ||
1184 | //llerrs << "should not call this function!" << llendl ; | ||
1185 | |||
1102 | if (discard_level < 0) | 1186 | if (discard_level < 0) |
1103 | { | 1187 | { |
1104 | discard_level = mCurrentDiscardLevel; | 1188 | discard_level = mCurrentDiscardLevel; |
@@ -1201,7 +1285,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
1201 | return FALSE ; | 1285 | return FALSE ; |
1202 | } | 1286 | } |
1203 | //----------------------------------------------------------------------------------------------- | 1287 | //----------------------------------------------------------------------------------------------- |
1204 | llpushcallstacks ; | 1288 | |
1205 | return TRUE ; | 1289 | return TRUE ; |
1206 | } | 1290 | } |
1207 | 1291 | ||
@@ -1219,12 +1303,19 @@ void LLImageGL::destroyGLTexture() | |||
1219 | stop_glerror(); | 1303 | stop_glerror(); |
1220 | } | 1304 | } |
1221 | } | 1305 | } |
1222 | 1306 | ||
1223 | sGlobalTextureMemoryInBytes -= mTextureMemory; | 1307 | if(mTextureMemory) |
1224 | mTextureMemory = 0; | 1308 | { |
1225 | 1309 | if(gAuditTexture) | |
1310 | { | ||
1311 | decTextureCounter() ; | ||
1312 | } | ||
1313 | sGlobalTextureMemoryInBytes -= mTextureMemory; | ||
1314 | mTextureMemory = 0; | ||
1315 | } | ||
1316 | |||
1226 | LLImageGL::deleteTextures(1, &mTexName); | 1317 | LLImageGL::deleteTextures(1, &mTexName); |
1227 | mTextureState = DELETED ; | 1318 | mTextureState = DELETED ; |
1228 | mTexName = 0; | 1319 | mTexName = 0; |
1229 | mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. | 1320 | mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. |
1230 | mGLTextureCreated = FALSE ; | 1321 | mGLTextureCreated = FALSE ; |
@@ -1338,6 +1429,11 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const | |||
1338 | return res; | 1429 | return res; |
1339 | } | 1430 | } |
1340 | 1431 | ||
1432 | BOOL LLImageGL::isJustBound() const | ||
1433 | { | ||
1434 | return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f); | ||
1435 | } | ||
1436 | |||
1341 | BOOL LLImageGL::getBoundRecently() const | 1437 | BOOL LLImageGL::getBoundRecently() const |
1342 | { | 1438 | { |
1343 | return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); | 1439 | return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); |
@@ -1539,6 +1635,87 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) | |||
1539 | return res; | 1635 | return res; |
1540 | } | 1636 | } |
1541 | 1637 | ||
1638 | void LLImageGL::setCategory(S32 category) | ||
1639 | { | ||
1640 | if(!gAuditTexture) | ||
1641 | { | ||
1642 | return ; | ||
1643 | } | ||
1644 | if(mCategory != category) | ||
1645 | { | ||
1646 | if(mCategory > -1) | ||
1647 | { | ||
1648 | sTextureMemByCategory[mCategory] -= mTextureMemory ; | ||
1649 | } | ||
1650 | sTextureMemByCategory[category] += mTextureMemory ; | ||
1651 | |||
1652 | mCategory = category; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | //for debug use | ||
1657 | //val is a "power of two" number | ||
1658 | S32 LLImageGL::getTextureCounterIndex(U32 val) | ||
1659 | { | ||
1660 | //index range is [0, MAX_TEXTURE_LOG_SIZE]. | ||
1661 | if(val < 2) | ||
1662 | { | ||
1663 | return 0 ; | ||
1664 | } | ||
1665 | else if(val >= (1 << MAX_TEXTURE_LOG_SIZE)) | ||
1666 | { | ||
1667 | return MAX_TEXTURE_LOG_SIZE ; | ||
1668 | } | ||
1669 | else | ||
1670 | { | ||
1671 | S32 ret = 0 ; | ||
1672 | while(val >>= 1) | ||
1673 | { | ||
1674 | ++ret; | ||
1675 | } | ||
1676 | return ret ; | ||
1677 | } | ||
1678 | } | ||
1679 | void LLImageGL::incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) | ||
1680 | { | ||
1681 | sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; | ||
1682 | sTextureMemByCategory[category] += (S32)val * ncomponents ; | ||
1683 | } | ||
1684 | void LLImageGL::decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) | ||
1685 | { | ||
1686 | sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; | ||
1687 | sTextureMemByCategory[category] += (S32)val * ncomponents ; | ||
1688 | } | ||
1689 | void LLImageGL::incTextureCounter() | ||
1690 | { | ||
1691 | sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; | ||
1692 | sTextureMemByCategory[mCategory] += mTextureMemory ; | ||
1693 | } | ||
1694 | void LLImageGL::decTextureCounter() | ||
1695 | { | ||
1696 | sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]-- ; | ||
1697 | sTextureMemByCategory[mCategory] -= mTextureMemory ; | ||
1698 | } | ||
1699 | void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) | ||
1700 | { | ||
1701 | sCurTexSizeBar = index ; | ||
1702 | |||
1703 | if(set_pick_size) | ||
1704 | { | ||
1705 | sCurTexPickSize = (1 << index) ; | ||
1706 | } | ||
1707 | else | ||
1708 | { | ||
1709 | sCurTexPickSize = -1 ; | ||
1710 | } | ||
1711 | } | ||
1712 | void LLImageGL::resetCurTexSizebar() | ||
1713 | { | ||
1714 | sCurTexSizeBar = -1 ; | ||
1715 | sCurTexPickSize = -1 ; | ||
1716 | } | ||
1717 | //---------------------------------------------------------------------------- | ||
1718 | |||
1542 | //---------------------------------------------------------------------------- | 1719 | //---------------------------------------------------------------------------- |
1543 | 1720 | ||
1544 | 1721 | ||
diff --git a/linden/indra/llrender/llimagegl.h b/linden/indra/llrender/llimagegl.h index 2f08a5a..c8df101 100644 --- a/linden/indra/llrender/llimagegl.h +++ b/linden/indra/llrender/llimagegl.h | |||
@@ -46,7 +46,6 @@ | |||
46 | #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) | 46 | #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) |
47 | 47 | ||
48 | //============================================================================ | 48 | //============================================================================ |
49 | |||
50 | class LLImageGL : public LLRefCount | 49 | class LLImageGL : public LLRefCount |
51 | { | 50 | { |
52 | friend class LLTexUnit; | 51 | friend class LLTexUnit; |
@@ -57,6 +56,7 @@ public: | |||
57 | static S32 dataFormatComponents(S32 dataformat); | 56 | static S32 dataFormatComponents(S32 dataformat); |
58 | 57 | ||
59 | void updateBindStats(void) const; | 58 | void updateBindStats(void) const; |
59 | void forceUpdateBindStats(void) const; | ||
60 | 60 | ||
61 | // needs to be called every frame | 61 | // needs to be called every frame |
62 | static void updateStats(F32 current_time); | 62 | static void updateStats(F32 current_time); |
@@ -65,9 +65,10 @@ public: | |||
65 | static void destroyGL(BOOL save_state = TRUE); | 65 | static void destroyGL(BOOL save_state = TRUE); |
66 | static void restoreGL(); | 66 | static void restoreGL(); |
67 | 67 | ||
68 | // Sometimes called externally for textures not using LLImageGL (should go away...) | 68 | // Sometimes called externally for textures not using LLImageGL (should go away...) |
69 | static S32 updateBoundTexMem(const S32 delta); | 69 | static S32 updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) ; |
70 | 70 | S32 updateBoundTexMem()const; | |
71 | |||
71 | static bool checkSize(S32 width, S32 height); | 72 | static bool checkSize(S32 width, S32 height); |
72 | 73 | ||
73 | // Not currently necessary for LLImageGL, but required in some derived classes, | 74 | // Not currently necessary for LLImageGL, but required in some derived classes, |
@@ -89,7 +90,7 @@ protected: | |||
89 | public: | 90 | public: |
90 | virtual void dump(); // debugging info to llinfos | 91 | virtual void dump(); // debugging info to llinfos |
91 | virtual bool bindError(const S32 stage = 0) const; | 92 | virtual bool bindError(const S32 stage = 0) const; |
92 | virtual bool bindDefaultImage(const S32 stage = 0) const; | 93 | virtual bool bindDefaultImage(const S32 stage = 0) ; |
93 | virtual void forceImmediateUpdate() ; | 94 | virtual void forceImmediateUpdate() ; |
94 | 95 | ||
95 | void setSize(S32 width, S32 height, S32 ncomponents); | 96 | void setSize(S32 width, S32 height, S32 ncomponents); |
@@ -101,20 +102,22 @@ public: | |||
101 | static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); | 102 | static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); |
102 | 103 | ||
103 | BOOL createGLTexture() ; | 104 | BOOL createGLTexture() ; |
104 | BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); | 105 | BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, |
106 | S32 category = sMaxCatagories - 1); | ||
105 | BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); | 107 | BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); |
106 | void setImage(const LLImageRaw* imageraw); | 108 | void setImage(const LLImageRaw* imageraw); |
107 | void setImage(const U8* data_in, BOOL data_hasmips = FALSE); | 109 | void setImage(const U8* data_in, BOOL data_hasmips = FALSE); |
108 | BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); | 110 | BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); |
109 | BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); | 111 | BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); |
110 | BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); | 112 | BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); |
111 | BOOL setDiscardLevel(S32 discard_level); | 113 | |
112 | // Read back a raw image for this discard level, if it exists | 114 | // Read back a raw image for this discard level, if it exists |
113 | BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); | 115 | BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); |
114 | void destroyGLTexture(); | 116 | void destroyGLTexture(); |
115 | 117 | ||
116 | void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); | 118 | void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); |
117 | void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } | 119 | void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } |
120 | void setComponents(S8 ncomponents) { mComponents = ncomponents; } | ||
118 | 121 | ||
119 | S32 getDiscardLevel() const { return mCurrentDiscardLevel; } | 122 | S32 getDiscardLevel() const { return mCurrentDiscardLevel; } |
120 | S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } | 123 | S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } |
@@ -127,6 +130,7 @@ public: | |||
127 | S32 getBytes(S32 discard_level = -1) const; | 130 | S32 getBytes(S32 discard_level = -1) const; |
128 | S32 getMipBytes(S32 discard_level = -1) const; | 131 | S32 getMipBytes(S32 discard_level = -1) const; |
129 | BOOL getBoundRecently() const; | 132 | BOOL getBoundRecently() const; |
133 | BOOL isJustBound() const; | ||
130 | LLGLenum getPrimaryFormat() const { return mFormatPrimary; } | 134 | LLGLenum getPrimaryFormat() const { return mFormatPrimary; } |
131 | 135 | ||
132 | BOOL getHasGLTexture() const { return mTexName != 0; } | 136 | BOOL getHasGLTexture() const { return mTexName != 0; } |
@@ -147,8 +151,6 @@ public: | |||
147 | BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } | 151 | BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } |
148 | BOOL getDontDiscard() const { return mDontDiscard; } | 152 | BOOL getDontDiscard() const { return mDontDiscard; } |
149 | 153 | ||
150 | BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; | ||
151 | |||
152 | void updatePickMask(S32 width, S32 height, const U8* data_in); | 154 | void updatePickMask(S32 width, S32 height, const U8* data_in); |
153 | BOOL getMask(const LLVector2 &tc); | 155 | BOOL getMask(const LLVector2 &tc); |
154 | 156 | ||
@@ -175,6 +177,7 @@ public: | |||
175 | void forceActive() ; | 177 | void forceActive() ; |
176 | void setNoDelete() ; | 178 | void setNoDelete() ; |
177 | 179 | ||
180 | void setTextureSize(S32 size) {mTextureMemory = size;} | ||
178 | protected: | 181 | protected: |
179 | void init(BOOL usemipmaps); | 182 | void init(BOOL usemipmaps); |
180 | virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors | 183 | virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors |
@@ -183,7 +186,7 @@ public: | |||
183 | // Various GL/Rendering options | 186 | // Various GL/Rendering options |
184 | S32 mTextureMemory; | 187 | S32 mTextureMemory; |
185 | mutable F32 mLastBindTime; // last time this was bound, by discard level | 188 | mutable F32 mLastBindTime; // last time this was bound, by discard level |
186 | 189 | ||
187 | private: | 190 | private: |
188 | LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL | 191 | LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL |
189 | U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel | 192 | U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel |
@@ -198,7 +201,7 @@ private: | |||
198 | U16 mWidth; | 201 | U16 mWidth; |
199 | U16 mHeight; | 202 | U16 mHeight; |
200 | S8 mCurrentDiscardLevel; | 203 | S8 mCurrentDiscardLevel; |
201 | 204 | ||
202 | protected: | 205 | protected: |
203 | LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) | 206 | LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) |
204 | LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) | 207 | LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) |
@@ -237,7 +240,7 @@ public: | |||
237 | static S32 sCount; | 240 | static S32 sCount; |
238 | 241 | ||
239 | static F32 sLastFrameTime; | 242 | static F32 sLastFrameTime; |
240 | 243 | ||
241 | static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID | 244 | static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID |
242 | 245 | ||
243 | // Global memory statistics | 246 | // Global memory statistics |
@@ -253,6 +256,57 @@ public: | |||
253 | #else | 256 | #else |
254 | BOOL getMissed() const { return FALSE; }; | 257 | BOOL getMissed() const { return FALSE; }; |
255 | #endif | 258 | #endif |
259 | |||
260 | public: | ||
261 | static void initClass(S32 num_catagories) ; | ||
262 | static void cleanupClass() ; | ||
263 | private: | ||
264 | static S32 sMaxCatagories ; | ||
265 | |||
266 | //the flag to allow to call readBackRaw(...). | ||
267 | //can be removed if we do not use that function at all. | ||
268 | static BOOL sAllowReadBackRaw ; | ||
269 | // | ||
270 | //**************************************************************************************************** | ||
271 | //The below for texture auditing use only | ||
272 | //**************************************************************************************************** | ||
273 | private: | ||
274 | S32 mCategory ; | ||
275 | public: | ||
276 | void setCategory(S32 category) ; | ||
277 | S32 getCategory()const {return mCategory ;} | ||
278 | |||
279 | //for debug use: show texture size distribution | ||
280 | //---------------------------------------- | ||
281 | static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures | ||
282 | static std::vector<S32> sTextureLoadedCounter ; | ||
283 | static std::vector<S32> sTextureBoundCounter ; | ||
284 | static std::vector<S32> sTextureCurBoundCounter ; | ||
285 | static S32 sCurTexSizeBar ; | ||
286 | static S32 sCurTexPickSize ; | ||
287 | |||
288 | static S32 getTextureCounterIndex(U32 val) ; | ||
289 | static void incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; | ||
290 | static void decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; | ||
291 | static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; | ||
292 | static void resetCurTexSizebar(); | ||
293 | |||
294 | void incTextureCounter() ; | ||
295 | void decTextureCounter() ; | ||
296 | //---------------------------------------- | ||
297 | |||
298 | //for debug use: show texture category distribution | ||
299 | //---------------------------------------- | ||
300 | |||
301 | static std::vector<S32> sTextureMemByCategory; | ||
302 | static std::vector<S32> sTextureMemByCategoryBound ; | ||
303 | static std::vector<S32> sTextureCurMemByCategoryBound ; | ||
304 | //---------------------------------------- | ||
305 | //**************************************************************************************************** | ||
306 | //End of definitions for texture auditing use only | ||
307 | //**************************************************************************************************** | ||
308 | |||
256 | }; | 309 | }; |
257 | 310 | ||
311 | extern BOOL gAuditTexture; | ||
258 | #endif // LL_LLIMAGEGL_H | 312 | #endif // LL_LLIMAGEGL_H |
diff --git a/linden/indra/llrender/llrender.cpp b/linden/indra/llrender/llrender.cpp index ba95a19..93ff822 100644 --- a/linden/indra/llrender/llrender.cpp +++ b/linden/indra/llrender/llrender.cpp | |||
@@ -177,7 +177,7 @@ void LLTexUnit::disable(void) | |||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) | 180 | bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) |
181 | { | 181 | { |
182 | stop_glerror(); | 182 | stop_glerror(); |
183 | if (mIndex < 0) return false; | 183 | if (mIndex < 0) return false; |
@@ -192,12 +192,25 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) | |||
192 | 192 | ||
193 | if (!texture->getTexName()) //if texture does not exist | 193 | if (!texture->getTexName()) //if texture does not exist |
194 | { | 194 | { |
195 | //if deleted, will re-generate it immediately | 195 | if (texture->isDeleted()) |
196 | texture->forceImmediateUpdate() ; | 196 | { |
197 | // This will re-generate the texture immediately. | ||
198 | texture->forceImmediateUpdate() ; | ||
199 | } | ||
197 | 200 | ||
201 | texture->forceUpdateBindStats() ; | ||
198 | return texture->bindDefaultImage(mIndex); | 202 | return texture->bindDefaultImage(mIndex); |
199 | } | 203 | } |
200 | 204 | ||
205 | if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) | ||
206 | { | ||
207 | if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) | ||
208 | { | ||
209 | texture->updateBindStats(); | ||
210 | return bind(LLImageGL::sDefaultTexturep.get()); | ||
211 | } | ||
212 | } | ||
213 | |||
201 | if ((mCurrTexture != texture->getTexName()) || forceBind) | 214 | if ((mCurrTexture != texture->getTexName()) || forceBind) |
202 | { | 215 | { |
203 | activate(); | 216 | activate(); |
@@ -214,6 +227,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) | |||
214 | setTextureFilteringOption(texture->mFilterOption); | 227 | setTextureFilteringOption(texture->mFilterOption); |
215 | } | 228 | } |
216 | } | 229 | } |
230 | |||
217 | return true; | 231 | return true; |
218 | } | 232 | } |
219 | 233 | ||
diff --git a/linden/indra/llrender/llrender.h b/linden/indra/llrender/llrender.h index 437c715..ce84e74 100644 --- a/linden/indra/llrender/llrender.h +++ b/linden/indra/llrender/llrender.h | |||
@@ -148,7 +148,7 @@ public: | |||
148 | 148 | ||
149 | // Binds the LLImageGL to this texture unit | 149 | // Binds the LLImageGL to this texture unit |
150 | // (automatically enables the unit for the LLImageGL's texture type) | 150 | // (automatically enables the unit for the LLImageGL's texture type) |
151 | bool bind(LLImageGL* texture, bool forceBind = false); | 151 | bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false); |
152 | 152 | ||
153 | // Binds a cubemap to this texture unit | 153 | // Binds a cubemap to this texture unit |
154 | // (automatically enables the texture unit for cubemaps) | 154 | // (automatically enables the texture unit for cubemaps) |
diff --git a/linden/indra/llrender/llrendertarget.cpp b/linden/indra/llrender/llrendertarget.cpp index b7f3177..4cf8451 100644 --- a/linden/indra/llrender/llrendertarget.cpp +++ b/linden/indra/llrender/llrendertarget.cpp | |||
@@ -139,7 +139,7 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) | |||
139 | 139 | ||
140 | U32 offset = mTex.size(); | 140 | U32 offset = mTex.size(); |
141 | if (offset >= 4 || | 141 | if (offset >= 4 || |
142 | offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) | 142 | (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) |
143 | { | 143 | { |
144 | llerrs << "Too many color attachments!" << llendl; | 144 | llerrs << "Too many color attachments!" << llendl; |
145 | } | 145 | } |
@@ -608,7 +608,7 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) | |||
608 | 608 | ||
609 | U32 offset = mTex.size(); | 609 | U32 offset = mTex.size(); |
610 | if (offset >= 4 || | 610 | if (offset >= 4 || |
611 | offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) | 611 | (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) |
612 | { | 612 | { |
613 | llerrs << "Too many color attachments!" << llendl; | 613 | llerrs << "Too many color attachments!" << llendl; |
614 | } | 614 | } |
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index e451465..d5b50cf 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt | |||
@@ -340,6 +340,10 @@ set(viewer_SOURCE_FILES | |||
340 | lltexturecache.cpp | 340 | lltexturecache.cpp |
341 | lltexturectrl.cpp | 341 | lltexturectrl.cpp |
342 | lltexturefetch.cpp | 342 | lltexturefetch.cpp |
343 | lltextureinfo.cpp | ||
344 | lltextureinfodetails.cpp | ||
345 | lltexturestats.cpp | ||
346 | lltexturestatsuploader.cpp | ||
343 | lltextureview.cpp | 347 | lltextureview.cpp |
344 | lltoolbar.cpp | 348 | lltoolbar.cpp |
345 | lltoolbrush.cpp | 349 | lltoolbrush.cpp |
@@ -760,6 +764,10 @@ set(viewer_HEADER_FILES | |||
760 | lltexturecache.h | 764 | lltexturecache.h |
761 | lltexturectrl.h | 765 | lltexturectrl.h |
762 | lltexturefetch.h | 766 | lltexturefetch.h |
767 | lltextureinfo.h | ||
768 | lltextureinfodetails.h | ||
769 | lltexturestats.h | ||
770 | lltexturestatsuploader.h | ||
763 | lltextureview.h | 771 | lltextureview.h |
764 | lltool.h | 772 | lltool.h |
765 | lltoolbar.h | 773 | lltoolbar.h |
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index f8594ad..9fea0d8 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml | |||
@@ -523,6 +523,17 @@ | |||
523 | <key>Value</key> | 523 | <key>Value</key> |
524 | <integer>1</integer> | 524 | <integer>1</integer> |
525 | </map> | 525 | </map> |
526 | <key>AuditTexture</key> | ||
527 | <map> | ||
528 | <key>Comment</key> | ||
529 | <string>Enable texture auditting.</string> | ||
530 | <key>Persist</key> | ||
531 | <integer>1</integer> | ||
532 | <key>Type</key> | ||
533 | <string>Boolean</string> | ||
534 | <key>Value</key> | ||
535 | <integer>0</integer> | ||
536 | </map> | ||
526 | <key>AutoAcceptNewInventory</key> | 537 | <key>AutoAcceptNewInventory</key> |
527 | <map> | 538 | <map> |
528 | <key>Comment</key> | 539 | <key>Comment</key> |
@@ -5811,6 +5822,28 @@ | |||
5811 | <key>Value</key> | 5822 | <key>Value</key> |
5812 | <string>http://imprudenceviewer.org/splash/</string> | 5823 | <string>http://imprudenceviewer.org/splash/</string> |
5813 | </map> | 5824 | </map> |
5825 | <key>LogTextureDownloadsToViewerLog</key> | ||
5826 | <map> | ||
5827 | <key>Comment</key> | ||
5828 | <string>Send texture download details to the viewer log</string> | ||
5829 | <key>Persist</key> | ||
5830 | <integer>1</integer> | ||
5831 | <key>Type</key> | ||
5832 | <string>Boolean</string> | ||
5833 | <key>Value</key> | ||
5834 | <integer>0</integer> | ||
5835 | </map> | ||
5836 | <key>LogTextureDownloadsToSimulator</key> | ||
5837 | <map> | ||
5838 | <key>Comment</key> | ||
5839 | <string>Send a digest of texture info to the sim</string> | ||
5840 | <key>Persist</key> | ||
5841 | <integer>1</integer> | ||
5842 | <key>Type</key> | ||
5843 | <string>Boolean</string> | ||
5844 | <key>Value</key> | ||
5845 | <integer>0</integer> | ||
5846 | </map> | ||
5814 | <key>LosslessJ2CUpload</key> | 5847 | <key>LosslessJ2CUpload</key> |
5815 | <map> | 5848 | <map> |
5816 | <key>Comment</key> | 5849 | <key>Comment</key> |
@@ -9776,6 +9809,17 @@ | |||
9776 | <key>Value</key> | 9809 | <key>Value</key> |
9777 | <real>20.0</real> | 9810 | <real>20.0</real> |
9778 | </map> | 9811 | </map> |
9812 | <key>TextureLoggingThreshold</key> | ||
9813 | <map> | ||
9814 | <key>Comment</key> | ||
9815 | <string>Specifies the byte threshold at which texture download data should be sent to the sim.</string> | ||
9816 | <key>Persist</key> | ||
9817 | <integer>1</integer> | ||
9818 | <key>Type</key> | ||
9819 | <string>U32</string> | ||
9820 | <key>Value</key> | ||
9821 | <integer>1</integer> | ||
9822 | </map> | ||
9779 | <key>TextureMemory</key> | 9823 | <key>TextureMemory</key> |
9780 | <map> | 9824 | <map> |
9781 | <key>Comment</key> | 9825 | <key>Comment</key> |
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index cdecaf4..a630beb 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp | |||
@@ -57,9 +57,12 @@ | |||
57 | #include "llares.h" | 57 | #include "llares.h" |
58 | #include "llcurl.h" | 58 | #include "llcurl.h" |
59 | #include "llfloatersnapshot.h" | 59 | #include "llfloatersnapshot.h" |
60 | #include "lltexturestats.h" | ||
60 | #include "llviewerwindow.h" | 61 | #include "llviewerwindow.h" |
61 | #include "llviewerdisplay.h" | 62 | #include "llviewerdisplay.h" |
62 | #include "llviewermedia.h" | 63 | #include "llviewermedia.h" |
64 | |||
65 | |||
63 | #include "llviewermessage.h" | 66 | #include "llviewermessage.h" |
64 | #include "llviewerobjectlist.h" | 67 | #include "llviewerobjectlist.h" |
65 | #include "llworldmap.h" | 68 | #include "llworldmap.h" |
@@ -435,7 +438,7 @@ static void settings_modify() | |||
435 | LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] | 438 | LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] |
436 | gDebugGL = gSavedSettings.getBOOL("RenderDebugGL"); | 439 | gDebugGL = gSavedSettings.getBOOL("RenderDebugGL"); |
437 | gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); | 440 | gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); |
438 | 441 | gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); | |
439 | #if LL_VECTORIZE | 442 | #if LL_VECTORIZE |
440 | if (gSysCPU.hasAltivec()) | 443 | if (gSysCPU.hasAltivec()) |
441 | { | 444 | { |
@@ -527,7 +530,7 @@ const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount"; | |||
527 | const std::string LLAppViewer::sCrashSettingsName = "CrashSettings"; | 530 | const std::string LLAppViewer::sCrashSettingsName = "CrashSettings"; |
528 | 531 | ||
529 | LLTextureCache* LLAppViewer::sTextureCache = NULL; | 532 | LLTextureCache* LLAppViewer::sTextureCache = NULL; |
530 | LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL; | 533 | LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; |
531 | LLTextureFetch* LLAppViewer::sTextureFetch = NULL; | 534 | LLTextureFetch* LLAppViewer::sTextureFetch = NULL; |
532 | 535 | ||
533 | LLAppViewer::LLAppViewer() : | 536 | LLAppViewer::LLAppViewer() : |
@@ -1512,14 +1515,14 @@ bool LLAppViewer::initThreads() | |||
1512 | LLWatchdog::getInstance()->init(watchdog_killer_callback); | 1515 | LLWatchdog::getInstance()->init(watchdog_killer_callback); |
1513 | } | 1516 | } |
1514 | 1517 | ||
1515 | LLVFSThread::initClass(enable_threads && true); | 1518 | LLVFSThread::initClass(enable_threads && false); |
1516 | LLLFSThread::initClass(enable_threads && true); | 1519 | LLLFSThread::initClass(enable_threads && false); |
1517 | 1520 | ||
1518 | // Image decoding | 1521 | // Image decoding |
1519 | LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true); | 1522 | LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); |
1520 | LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); | 1523 | LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); |
1521 | LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false); | 1524 | LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true); |
1522 | LLImage::initClass(LLAppViewer::getImageDecodeThread()); | 1525 | LLImage::initClass(); |
1523 | 1526 | ||
1524 | // *FIX: no error handling here! | 1527 | // *FIX: no error handling here! |
1525 | return true; | 1528 | return true; |
diff --git a/linden/indra/newview/llappviewer.h b/linden/indra/newview/llappviewer.h index ada5557..9d72457 100644 --- a/linden/indra/newview/llappviewer.h +++ b/linden/indra/newview/llappviewer.h | |||
@@ -34,7 +34,7 @@ | |||
34 | #define LL_LLAPPVIEWER_H | 34 | #define LL_LLAPPVIEWER_H |
35 | 35 | ||
36 | class LLTextureCache; | 36 | class LLTextureCache; |
37 | class LLWorkerThread; | 37 | class LLImageDecodeThread; |
38 | class LLTextureFetch; | 38 | class LLTextureFetch; |
39 | class LLWatchdogTimeout; | 39 | class LLWatchdogTimeout; |
40 | class LLCommandLineParser; | 40 | class LLCommandLineParser; |
@@ -91,7 +91,7 @@ public: | |||
91 | 91 | ||
92 | // Thread accessors | 92 | // Thread accessors |
93 | static LLTextureCache* getTextureCache() { return sTextureCache; } | 93 | static LLTextureCache* getTextureCache() { return sTextureCache; } |
94 | static LLWorkerThread* getImageDecodeThread() { return sImageDecodeThread; } | 94 | static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; } |
95 | static LLTextureFetch* getTextureFetch() { return sTextureFetch; } | 95 | static LLTextureFetch* getTextureFetch() { return sTextureFetch; } |
96 | 96 | ||
97 | const std::string& getSerialNumber() { return mSerialNumber; } | 97 | const std::string& getSerialNumber() { return mSerialNumber; } |
@@ -213,7 +213,7 @@ private: | |||
213 | 213 | ||
214 | // Thread objects. | 214 | // Thread objects. |
215 | static LLTextureCache* sTextureCache; | 215 | static LLTextureCache* sTextureCache; |
216 | static LLWorkerThread* sImageDecodeThread; | 216 | static LLImageDecodeThread* sImageDecodeThread; |
217 | static LLTextureFetch* sTextureFetch; | 217 | static LLTextureFetch* sTextureFetch; |
218 | 218 | ||
219 | S32 mNumSessions; | 219 | S32 mNumSessions; |
diff --git a/linden/indra/newview/llassetuploadresponders.cpp b/linden/indra/newview/llassetuploadresponders.cpp index dfd7403..700edb5 100644 --- a/linden/indra/newview/llassetuploadresponders.cpp +++ b/linden/indra/newview/llassetuploadresponders.cpp | |||
@@ -378,6 +378,14 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) | |||
378 | } | 378 | } |
379 | } | 379 | } |
380 | 380 | ||
381 | void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason) | ||
382 | { | ||
383 | llinfos << "status: " << statusNum << " reason: " << reason << llendl; | ||
384 | |||
385 | // Invoke the original callback with an error result | ||
386 | LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); | ||
387 | mBakedUploadData = NULL; // deleted in onTextureUploadComplete() | ||
388 | } | ||
381 | 389 | ||
382 | LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, | 390 | LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, |
383 | const LLUUID& vfile_id, | 391 | const LLUUID& vfile_id, |
diff --git a/linden/indra/newview/llassetuploadresponders.h b/linden/indra/newview/llassetuploadresponders.h index 9ab571a..c08f299 100644 --- a/linden/indra/newview/llassetuploadresponders.h +++ b/linden/indra/newview/llassetuploadresponders.h | |||
@@ -83,6 +83,7 @@ public: | |||
83 | ~LLSendTexLayerResponder(); | 83 | ~LLSendTexLayerResponder(); |
84 | 84 | ||
85 | virtual void uploadComplete(const LLSD& content); | 85 | virtual void uploadComplete(const LLSD& content); |
86 | virtual void error(U32 statusNum, const std::string& reason); | ||
86 | 87 | ||
87 | LLBakedUploadData * mBakedUploadData; | 88 | LLBakedUploadData * mBakedUploadData; |
88 | }; | 89 | }; |
diff --git a/linden/indra/newview/lldrawable.cpp b/linden/indra/newview/lldrawable.cpp index 44a5de9..14aa38a 100644 --- a/linden/indra/newview/lldrawable.cpp +++ b/linden/indra/newview/lldrawable.cpp | |||
@@ -102,7 +102,7 @@ void LLDrawable::init() | |||
102 | mVObjp = NULL; | 102 | mVObjp = NULL; |
103 | // mFaces | 103 | // mFaces |
104 | mSpatialGroupp = NULL; | 104 | mSpatialGroupp = NULL; |
105 | mVisible = 0; | 105 | mVisible = sCurVisible - 2;//invisible for the current frame and the last frame. |
106 | mRadius = 0.f; | 106 | mRadius = 0.f; |
107 | 107 | ||
108 | mGeneration = -1; | 108 | mGeneration = -1; |
@@ -949,7 +949,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() | |||
949 | return retval; | 949 | return retval; |
950 | } | 950 | } |
951 | 951 | ||
952 | 952 | BOOL LLDrawable::isRecentlyVisible() const | |
953 | { | ||
954 | //currently visible or visible in the previous frame. | ||
955 | return isVisible() || (mVisible == sCurVisible - 1) ; | ||
956 | } | ||
953 | BOOL LLDrawable::isVisible() const | 957 | BOOL LLDrawable::isVisible() const |
954 | { | 958 | { |
955 | if (mVisible == sCurVisible) | 959 | if (mVisible == sCurVisible) |
diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h index 21cc0c5..71b75dc 100644 --- a/linden/indra/newview/lldrawable.h +++ b/linden/indra/newview/lldrawable.h | |||
@@ -50,7 +50,6 @@ | |||
50 | #include "llviewerobject.h" | 50 | #include "llviewerobject.h" |
51 | #include "llrect.h" | 51 | #include "llrect.h" |
52 | #include "llappviewer.h" // for gFrameTimeSeconds | 52 | #include "llappviewer.h" // for gFrameTimeSeconds |
53 | #include "llimagej2c.h" | ||
54 | 53 | ||
55 | class LLCamera; | 54 | class LLCamera; |
56 | class LLDrawPool; | 55 | class LLDrawPool; |
@@ -81,7 +80,8 @@ public: | |||
81 | 80 | ||
82 | BOOL isLight() const; | 81 | BOOL isLight() const; |
83 | 82 | ||
84 | BOOL isVisible() const; | 83 | BOOL isVisible() const; |
84 | BOOL isRecentlyVisible() const; | ||
85 | virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE); | 85 | virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE); |
86 | 86 | ||
87 | 87 | ||
diff --git a/linden/indra/newview/lldrawpool.cpp b/linden/indra/newview/lldrawpool.cpp index 9f05ce3..e1bf1ed 100644 --- a/linden/indra/newview/lldrawpool.cpp +++ b/linden/indra/newview/lldrawpool.cpp | |||
@@ -279,7 +279,7 @@ S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) | |||
279 | iter != face_list.end(); iter++) | 279 | iter != face_list.end(); iter++) |
280 | { | 280 | { |
281 | LLFace *facep = *iter; | 281 | LLFace *facep = *iter; |
282 | gGL.getTexUnit(stage)->bind(facep->getTexture()); | 282 | gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE); |
283 | gGL.getTexUnit(0)->activate(); | 283 | gGL.getTexUnit(0)->activate(); |
284 | res += facep->renderIndexed(); | 284 | res += facep->renderIndexed(); |
285 | } | 285 | } |
@@ -481,14 +481,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) | |||
481 | { | 481 | { |
482 | if (params.mTexture.notNull()) | 482 | if (params.mTexture.notNull()) |
483 | { | 483 | { |
484 | gGL.getTexUnit(0)->bind(params.mTexture.get()); | 484 | gGL.getTexUnit(0)->bind(params.mTexture.get(), TRUE); |
485 | if (params.mTextureMatrix) | 485 | if (params.mTextureMatrix) |
486 | { | 486 | { |
487 | glMatrixMode(GL_TEXTURE); | 487 | glMatrixMode(GL_TEXTURE); |
488 | glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); | 488 | glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); |
489 | gPipeline.mTextureMatrixOps++; | 489 | gPipeline.mTextureMatrixOps++; |
490 | } | 490 | } |
491 | params.mTexture->addTextureStats(params.mVSize); | ||
492 | } | 491 | } |
493 | else | 492 | else |
494 | { | 493 | { |
diff --git a/linden/indra/newview/lldrawpoolalpha.cpp b/linden/indra/newview/lldrawpoolalpha.cpp index 7e470bd..4b552ac 100644 --- a/linden/indra/newview/lldrawpoolalpha.cpp +++ b/linden/indra/newview/lldrawpoolalpha.cpp | |||
@@ -219,7 +219,7 @@ void LLDrawPoolAlpha::render(S32 pass) | |||
219 | gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); | 219 | gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); |
220 | glColor4f(1,0,0,1); | 220 | glColor4f(1,0,0,1); |
221 | LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f); | 221 | LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f); |
222 | gGL.getTexUnit(0)->bind(LLViewerImage::sSmokeImagep.get()); | 222 | gGL.getTexUnit(0)->bind(LLViewerImage::sSmokeImagep.get(), TRUE); |
223 | renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | | 223 | renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | |
224 | LLVertexBuffer::MAP_TEXCOORD0); | 224 | LLVertexBuffer::MAP_TEXCOORD0); |
225 | } | 225 | } |
@@ -295,7 +295,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) | |||
295 | { | 295 | { |
296 | gGL.getTexUnit(0)->activate(); | 296 | gGL.getTexUnit(0)->activate(); |
297 | gGL.getTexUnit(0)->bind(params.mTexture.get()); | 297 | gGL.getTexUnit(0)->bind(params.mTexture.get()); |
298 | params.mTexture->addTextureStats(params.mVSize); | 298 | |
299 | if (params.mTextureMatrix) | 299 | if (params.mTextureMatrix) |
300 | { | 300 | { |
301 | glMatrixMode(GL_TEXTURE); | 301 | glMatrixMode(GL_TEXTURE); |
diff --git a/linden/indra/newview/lldrawpoolbump.cpp b/linden/indra/newview/lldrawpoolbump.cpp index 8f5858f..ff464f7 100644 --- a/linden/indra/newview/lldrawpoolbump.cpp +++ b/linden/indra/newview/lldrawpoolbump.cpp | |||
@@ -309,8 +309,8 @@ void LLDrawPoolBump::endRenderPass(S32 pass) | |||
309 | void LLDrawPoolBump::beginShiny(bool invisible) | 309 | void LLDrawPoolBump::beginShiny(bool invisible) |
310 | { | 310 | { |
311 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); | 311 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); |
312 | if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| | 312 | if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| |
313 | invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) | 313 | (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) |
314 | { | 314 | { |
315 | return; | 315 | return; |
316 | } | 316 | } |
@@ -384,8 +384,8 @@ void LLDrawPoolBump::beginShiny(bool invisible) | |||
384 | void LLDrawPoolBump::renderShiny(bool invisible) | 384 | void LLDrawPoolBump::renderShiny(bool invisible) |
385 | { | 385 | { |
386 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); | 386 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); |
387 | if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| | 387 | if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| |
388 | invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) | 388 | (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) |
389 | { | 389 | { |
390 | return; | 390 | return; |
391 | } | 391 | } |
@@ -411,8 +411,8 @@ void LLDrawPoolBump::renderShiny(bool invisible) | |||
411 | void LLDrawPoolBump::endShiny(bool invisible) | 411 | void LLDrawPoolBump::endShiny(bool invisible) |
412 | { | 412 | { |
413 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); | 413 | LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); |
414 | if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| | 414 | if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| |
415 | invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) | 415 | (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) |
416 | { | 416 | { |
417 | return; | 417 | return; |
418 | } | 418 | } |
@@ -1221,7 +1221,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) | |||
1221 | if (params.mTexture.notNull()) | 1221 | if (params.mTexture.notNull()) |
1222 | { | 1222 | { |
1223 | gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); | 1223 | gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); |
1224 | params.mTexture->addTextureStats(params.mVSize); | 1224 | //params.mTexture->addTextureStats(params.mVSize); |
1225 | } | 1225 | } |
1226 | else | 1226 | else |
1227 | { | 1227 | { |
diff --git a/linden/indra/newview/lldrawpoolterrain.cpp b/linden/indra/newview/lldrawpoolterrain.cpp index 2c644b0..cac5162 100644 --- a/linden/indra/newview/lldrawpoolterrain.cpp +++ b/linden/indra/newview/lldrawpoolterrain.cpp | |||
@@ -83,7 +83,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : | |||
83 | gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); | 83 | gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); |
84 | m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); | 84 | m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); |
85 | 85 | ||
86 | mTexturep->setBoostLevel(LLViewerImage::BOOST_TERRAIN); | 86 | mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); |
87 | 87 | ||
88 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); | 88 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); |
89 | } | 89 | } |
@@ -170,7 +170,7 @@ void LLDrawPoolTerrain::render(S32 pass) | |||
170 | LLVLComposition *compp = regionp->getComposition(); | 170 | LLVLComposition *compp = regionp->getComposition(); |
171 | for (S32 i = 0; i < 4; i++) | 171 | for (S32 i = 0; i < 4; i++) |
172 | { | 172 | { |
173 | compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); | 173 | compp->mDetailTextures[i]->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); |
174 | compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area | 174 | compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area |
175 | } | 175 | } |
176 | 176 | ||
diff --git a/linden/indra/newview/lldrawpooltree.cpp b/linden/indra/newview/lldrawpooltree.cpp index 2f2b072..46cd2d5 100644 --- a/linden/indra/newview/lldrawpooltree.cpp +++ b/linden/indra/newview/lldrawpooltree.cpp | |||
@@ -247,7 +247,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting) | |||
247 | LLGLState normalize(GL_NORMALIZE, TRUE); | 247 | LLGLState normalize(GL_NORMALIZE, TRUE); |
248 | 248 | ||
249 | // Bind the texture for this tree. | 249 | // Bind the texture for this tree. |
250 | gGL.getTexUnit(sDiffTex)->bind(mTexturep.get()); | 250 | gGL.getTexUnit(sDiffTex)->bind(mTexturep.get(), TRUE); |
251 | 251 | ||
252 | U32 indices_drawn = 0; | 252 | U32 indices_drawn = 0; |
253 | 253 | ||
diff --git a/linden/indra/newview/lldynamictexture.cpp b/linden/indra/newview/lldynamictexture.cpp index 62fcf60..61f5a89 100644 --- a/linden/indra/newview/lldynamictexture.cpp +++ b/linden/indra/newview/lldynamictexture.cpp | |||
@@ -111,7 +111,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima | |||
111 | mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); | 111 | mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); |
112 | } | 112 | } |
113 | // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; | 113 | // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; |
114 | mTexture->createGLTexture(0, raw_image); | 114 | mTexture->createGLTexture(0, raw_image, 0, TRUE, LLViewerImageBoostLevel::DYNAMIC_TEX); |
115 | mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); | 115 | mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); |
116 | mTexture->setGLTextureCreated(false); | 116 | mTexture->setGLTextureCreated(false); |
117 | } | 117 | } |
diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp index 69edcca..dab1dac 100644 --- a/linden/indra/newview/llface.cpp +++ b/linden/indra/newview/llface.cpp | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "llvovolume.h" | 52 | #include "llvovolume.h" |
53 | #include "pipeline.h" | 53 | #include "pipeline.h" |
54 | #include "llviewerregion.h" | 54 | #include "llviewerregion.h" |
55 | #include "llviewerwindow.h" | ||
55 | 56 | ||
56 | #define LL_MAX_INDICES_COUNT 1000000 | 57 | #define LL_MAX_INDICES_COUNT 1000000 |
57 | 58 | ||
@@ -174,11 +175,19 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) | |||
174 | mLastGeomIndex = mGeomIndex; | 175 | mLastGeomIndex = mGeomIndex; |
175 | mLastIndicesCount = mIndicesCount; | 176 | mLastIndicesCount = mIndicesCount; |
176 | mLastIndicesIndex = mIndicesIndex; | 177 | mLastIndicesIndex = mIndicesIndex; |
178 | |||
179 | mImportanceToCamera = 0.f ; | ||
180 | mBoundingSphereRadius = 0.0f ; | ||
177 | } | 181 | } |
178 | 182 | ||
179 | 183 | ||
180 | void LLFace::destroy() | 184 | void LLFace::destroy() |
181 | { | 185 | { |
186 | if(mTexture.notNull()) | ||
187 | { | ||
188 | mTexture->removeFace(this) ; | ||
189 | } | ||
190 | |||
182 | if (mDrawPoolp) | 191 | if (mDrawPoolp) |
183 | { | 192 | { |
184 | mDrawPoolp->removeFace(this); | 193 | mDrawPoolp->removeFace(this); |
@@ -199,7 +208,7 @@ void LLFace::destroy() | |||
199 | } | 208 | } |
200 | } | 209 | } |
201 | } | 210 | } |
202 | 211 | ||
203 | setDrawInfo(NULL); | 212 | setDrawInfo(NULL); |
204 | 213 | ||
205 | mDrawablep = NULL; | 214 | mDrawablep = NULL; |
@@ -247,9 +256,29 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) | |||
247 | } | 256 | } |
248 | mDrawPoolp = new_pool; | 257 | mDrawPoolp = new_pool; |
249 | } | 258 | } |
250 | mTexture = texturep; | 259 | |
260 | setTexture(texturep) ; | ||
251 | } | 261 | } |
252 | 262 | ||
263 | void LLFace::setTexture(LLViewerImage* tex) | ||
264 | { | ||
265 | if(mTexture == tex) | ||
266 | { | ||
267 | return ; | ||
268 | } | ||
269 | |||
270 | if(mTexture.notNull()) | ||
271 | { | ||
272 | mTexture->removeFace(this) ; | ||
273 | } | ||
274 | |||
275 | mTexture = tex ; | ||
276 | |||
277 | if(mTexture.notNull()) | ||
278 | { | ||
279 | mTexture->addFace(this) ; | ||
280 | } | ||
281 | } | ||
253 | 282 | ||
254 | void LLFace::setTEOffset(const S32 te_offset) | 283 | void LLFace::setTEOffset(const S32 te_offset) |
255 | { | 284 | { |
@@ -698,7 +727,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, | |||
698 | } | 727 | } |
699 | 728 | ||
700 | mCenterLocal = (newMin+newMax)*0.5f; | 729 | mCenterLocal = (newMin+newMax)*0.5f; |
701 | 730 | LLVector3 tmp = (newMin - newMax) ; | |
731 | mBoundingSphereRadius = tmp.length() * 0.5f ; | ||
732 | |||
702 | updateCenterAgent(); | 733 | updateCenterAgent(); |
703 | } | 734 | } |
704 | 735 | ||
@@ -865,6 +896,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
865 | { | 896 | { |
866 | mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); | 897 | mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); |
867 | } | 898 | } |
899 | |||
868 | if (rebuild_tcoord) | 900 | if (rebuild_tcoord) |
869 | { | 901 | { |
870 | mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); | 902 | mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); |
@@ -959,7 +991,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
959 | 0.75f | 991 | 0.75f |
960 | }; | 992 | }; |
961 | 993 | ||
962 | if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) | 994 | if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) |
963 | { | 995 | { |
964 | color.mV[3] = U8 (alpha[tep->getShiny()] * 255); | 996 | color.mV[3] = U8 (alpha[tep->getShiny()] * 255); |
965 | } | 997 | } |
@@ -1147,6 +1179,159 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, | |||
1147 | return TRUE; | 1179 | return TRUE; |
1148 | } | 1180 | } |
1149 | 1181 | ||
1182 | const F32 LEAST_IMPORTANCE = 0.05f ; | ||
1183 | const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; | ||
1184 | |||
1185 | F32 LLFace::getTextureVirtualSize() | ||
1186 | { | ||
1187 | F32 radius; | ||
1188 | F32 cos_angle_to_view_dir; | ||
1189 | mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius); | ||
1190 | |||
1191 | if (mPixelArea <= 0) | ||
1192 | { | ||
1193 | return 0.f; | ||
1194 | } | ||
1195 | |||
1196 | //get area of circle in texture space | ||
1197 | LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; | ||
1198 | F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; | ||
1199 | if (texel_area <= 0) | ||
1200 | { | ||
1201 | // Probably animated, use default | ||
1202 | texel_area = 1.f; | ||
1203 | } | ||
1204 | |||
1205 | F32 face_area; | ||
1206 | if (mVObjp->isSculpted() && texel_area > 1.f) | ||
1207 | { | ||
1208 | //sculpts can break assumptions about texel area | ||
1209 | face_area = mPixelArea; | ||
1210 | } | ||
1211 | else | ||
1212 | { | ||
1213 | //apply texel area to face area to get accurate ratio | ||
1214 | //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); | ||
1215 | face_area = mPixelArea / llclamp(texel_area, 0.015625f, 1024.f); | ||
1216 | } | ||
1217 | |||
1218 | if(face_area > LLViewerImage::sMaxSmallImageSize) | ||
1219 | { | ||
1220 | if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. | ||
1221 | { | ||
1222 | face_area = LLViewerImage::sMaxSmallImageSize ; | ||
1223 | } | ||
1224 | else if(face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. | ||
1225 | { | ||
1226 | if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. | ||
1227 | { | ||
1228 | face_area = LLViewerImage::sMinLargeImageSize ; | ||
1229 | } | ||
1230 | else if(mTexture.notNull() && mTexture->isLargeImage()) | ||
1231 | { | ||
1232 | face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); | ||
1233 | } | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | return face_area; | ||
1238 | } | ||
1239 | |||
1240 | F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) | ||
1241 | { | ||
1242 | //get area of circle around face | ||
1243 | LLVector3 center = getPositionAgent(); | ||
1244 | LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; | ||
1245 | |||
1246 | LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin(); | ||
1247 | F32 dist = lookAt.normVec() ; | ||
1248 | |||
1249 | //get area of circle around node | ||
1250 | F32 app_angle = atanf(size.length()/dist); | ||
1251 | radius = app_angle*LLDrawable::sCurPixelAngle; | ||
1252 | F32 face_area = radius*radius * 3.14159f; | ||
1253 | |||
1254 | if(dist < mBoundingSphereRadius) //camera is very close | ||
1255 | { | ||
1256 | cos_angle_to_view_dir = 1.0f ; | ||
1257 | mImportanceToCamera = 1.0f ; | ||
1258 | } | ||
1259 | else | ||
1260 | { | ||
1261 | cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; | ||
1262 | mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; | ||
1263 | } | ||
1264 | |||
1265 | return face_area ; | ||
1266 | } | ||
1267 | |||
1268 | //the projection of the face partially overlaps with the screen | ||
1269 | F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) | ||
1270 | { | ||
1271 | F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; | ||
1272 | F32 center_angle = acosf(cos_angle_to_view_dir) ; | ||
1273 | F32 d = center_angle * LLDrawable::sCurPixelAngle ; | ||
1274 | |||
1275 | if(d + radius > screen_radius + 5.f) | ||
1276 | { | ||
1277 | //---------------------------------------------- | ||
1278 | //calculate the intersection area of two circles | ||
1279 | //F32 radius_square = radius * radius ; | ||
1280 | //F32 d_square = d * d ; | ||
1281 | //F32 screen_radius_square = screen_radius * screen_radius ; | ||
1282 | //face_area = | ||
1283 | // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + | ||
1284 | // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - | ||
1285 | // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; | ||
1286 | //---------------------------------------------- | ||
1287 | |||
1288 | //the above calculation is too expensive | ||
1289 | //the below is a good estimation: bounding box of the bounding sphere: | ||
1290 | F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; | ||
1291 | alpha = llclamp(alpha, 0.f, 1.f) ; | ||
1292 | return alpha * alpha ; | ||
1293 | } | ||
1294 | return 1.0f ; | ||
1295 | } | ||
1296 | |||
1297 | const S8 FACE_IMPORTANCE_LEVEL = 4 ; | ||
1298 | const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} | ||
1299 | {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; | ||
1300 | const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} | ||
1301 | {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; | ||
1302 | |||
1303 | //static | ||
1304 | F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) | ||
1305 | { | ||
1306 | F32 importance = 0.f ; | ||
1307 | |||
1308 | if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && | ||
1309 | dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) | ||
1310 | { | ||
1311 | F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; | ||
1312 | F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); | ||
1313 | |||
1314 | if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) | ||
1315 | { | ||
1316 | //if camera moves or rotates too fast, ignore the importance factor | ||
1317 | return 0.f ; | ||
1318 | } | ||
1319 | |||
1320 | //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; | ||
1321 | |||
1322 | S32 i = 0 ; | ||
1323 | for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); | ||
1324 | i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; | ||
1325 | F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; | ||
1326 | |||
1327 | for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; | ||
1328 | i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; | ||
1329 | importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; | ||
1330 | } | ||
1331 | |||
1332 | return importance ; | ||
1333 | } | ||
1334 | |||
1150 | BOOL LLFace::verify(const U32* indices_array) const | 1335 | BOOL LLFace::verify(const U32* indices_array) const |
1151 | { | 1336 | { |
1152 | BOOL ok = TRUE; | 1337 | BOOL ok = TRUE; |
diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index 4a551ff..5e422b4 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h | |||
@@ -88,7 +88,7 @@ public: | |||
88 | U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool | 88 | U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool |
89 | U16 getGeomStart() const { return mGeomIndex; } // index into draw pool | 89 | U16 getGeomStart() const { return mGeomIndex; } // index into draw pool |
90 | LLViewerImage* getTexture() const { return mTexture; } | 90 | LLViewerImage* getTexture() const { return mTexture; } |
91 | void setTexture(LLViewerImage* tex) { mTexture = tex; } | 91 | void setTexture(LLViewerImage* tex) ; |
92 | LLXformMatrix* getXform() const { return mXform; } | 92 | LLXformMatrix* getXform() const { return mXform; } |
93 | BOOL hasGeometry() const { return mGeomCount > 0; } | 93 | BOOL hasGeometry() const { return mGeomCount > 0; } |
94 | LLVector3 getPositionAgent() const; | 94 | LLVector3 getPositionAgent() const; |
@@ -186,7 +186,14 @@ public: | |||
186 | void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } | 186 | void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } |
187 | void setDrawInfo(LLDrawInfo* draw_info); | 187 | void setDrawInfo(LLDrawInfo* draw_info); |
188 | 188 | ||
189 | protected: | 189 | F32 getTextureVirtualSize() ; |
190 | F32 getImportanceToCamera()const {return mImportanceToCamera ;} | ||
191 | |||
192 | private: | ||
193 | F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); | ||
194 | F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ; | ||
195 | public: | ||
196 | static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist); | ||
190 | 197 | ||
191 | public: | 198 | public: |
192 | 199 | ||
@@ -202,7 +209,7 @@ public: | |||
202 | LLMatrix4* mTextureMatrix; | 209 | LLMatrix4* mTextureMatrix; |
203 | LLDrawInfo* mDrawInfo; | 210 | LLDrawInfo* mDrawInfo; |
204 | 211 | ||
205 | protected: | 212 | private: |
206 | friend class LLGeometryManager; | 213 | friend class LLGeometryManager; |
207 | friend class LLVolumeGeometryManager; | 214 | friend class LLVolumeGeometryManager; |
208 | 215 | ||
@@ -231,7 +238,13 @@ protected: | |||
231 | S32 mReferenceIndex; | 238 | S32 mReferenceIndex; |
232 | F32 mVSize; | 239 | F32 mVSize; |
233 | F32 mPixelArea; | 240 | F32 mPixelArea; |
234 | 241 | ||
242 | //importance factor, in the range [0, 1.0]. | ||
243 | //1.0: the most important. | ||
244 | //based on the distance from the face to the view point and the angle from the face center to the view direction. | ||
245 | F32 mImportanceToCamera ; | ||
246 | F32 mBoundingSphereRadius ; | ||
247 | |||
235 | protected: | 248 | protected: |
236 | static BOOL sSafeRenderSelect; | 249 | static BOOL sSafeRenderSelect; |
237 | 250 | ||
diff --git a/linden/indra/newview/llfloaterassetbrowser.cpp b/linden/indra/newview/llfloaterassetbrowser.cpp index cb2412d..af81c4a 100644 --- a/linden/indra/newview/llfloaterassetbrowser.cpp +++ b/linden/indra/newview/llfloaterassetbrowser.cpp | |||
@@ -130,7 +130,7 @@ void LLFloaterAssetBrowser::createThumbnails() | |||
130 | for(S32 i = 0; i < items.count(); i++) | 130 | for(S32 i = 0; i < items.count(); i++) |
131 | { | 131 | { |
132 | mTextureAssets[i].mTexturep = gImageList.getImage(mTextureAssets[i].mAssetUUID, MIPMAP_YES, IMMEDIATE_NO); | 132 | mTextureAssets[i].mTexturep = gImageList.getImage(mTextureAssets[i].mAssetUUID, MIPMAP_YES, IMMEDIATE_NO); |
133 | mTextureAssets[i].mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 133 | mTextureAssets[i].mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
134 | //mTextureAssets[i].mTexturep->processTextureStats(); | 134 | //mTextureAssets[i].mTexturep->processTextureStats(); |
135 | } | 135 | } |
136 | 136 | ||
diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp index 31d658b..7a5f2ba 100644 --- a/linden/indra/newview/llfloaterreporter.cpp +++ b/linden/indra/newview/llfloaterreporter.cpp | |||
@@ -952,8 +952,8 @@ void LLFloaterReporter::takeScreenshot() | |||
952 | mResourceDatap->mAssetInfo.mType); | 952 | mResourceDatap->mAssetInfo.mType); |
953 | 953 | ||
954 | // store in the image list so it doesn't try to fetch from the server | 954 | // store in the image list so it doesn't try to fetch from the server |
955 | LLPointer<LLViewerImage> image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid, TRUE); | 955 | LLPointer<LLViewerImage> image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid); |
956 | image_in_list->createGLTexture(0, raw); | 956 | image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
957 | gImageList.addImage(image_in_list); | 957 | gImageList.addImage(image_in_list); |
958 | 958 | ||
959 | // the texture picker then uses that texture | 959 | // the texture picker then uses that texture |
diff --git a/linden/indra/newview/llpreviewtexture.cpp b/linden/indra/newview/llpreviewtexture.cpp index 13e7cca..dcbb669 100644 --- a/linden/indra/newview/llpreviewtexture.cpp +++ b/linden/indra/newview/llpreviewtexture.cpp | |||
@@ -224,6 +224,11 @@ void LLPreviewTexture::draw() | |||
224 | // Pump the texture priority | 224 | // Pump the texture priority |
225 | F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); | 225 | F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); |
226 | mImage->addTextureStats( pixel_area ); | 226 | mImage->addTextureStats( pixel_area ); |
227 | if(pixel_area > 0.f) | ||
228 | { | ||
229 | //boost the previewed image priority to the highest to make it to get loaded first. | ||
230 | mImage->setAdditionalDecodePriority(1.0f) ; | ||
231 | } | ||
227 | 232 | ||
228 | // Don't bother decoding more than we can display, unless | 233 | // Don't bother decoding more than we can display, unless |
229 | // we're loading the full image. | 234 | // we're loading the full image. |
@@ -482,7 +487,8 @@ void LLPreviewTexture::updateDimensions() | |||
482 | void LLPreviewTexture::loadAsset() | 487 | void LLPreviewTexture::loadAsset() |
483 | { | 488 | { |
484 | mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE); | 489 | mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE); |
485 | mImage->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 490 | mImage->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
491 | mImage->forceToSaveRawImage(0) ; | ||
486 | mAssetStatus = PREVIEW_ASSET_LOADING; | 492 | mAssetStatus = PREVIEW_ASSET_LOADING; |
487 | } | 493 | } |
488 | 494 | ||
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 143aa34..7a7e023 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp | |||
@@ -59,6 +59,7 @@ | |||
59 | #include "llfocusmgr.h" | 59 | #include "llfocusmgr.h" |
60 | #include "llhttpsender.h" | 60 | #include "llhttpsender.h" |
61 | #include "imageids.h" | 61 | #include "imageids.h" |
62 | #include "llimageworker.h" | ||
62 | #include "lllandmark.h" | 63 | #include "lllandmark.h" |
63 | #include "llloginflags.h" | 64 | #include "llloginflags.h" |
64 | #include "llmd5.h" | 65 | #include "llmd5.h" |
@@ -3468,7 +3469,7 @@ void init_start_screen(S32 location_id) | |||
3468 | } | 3469 | } |
3469 | 3470 | ||
3470 | raw->expandToPowerOfTwo(); | 3471 | raw->expandToPowerOfTwo(); |
3471 | gStartImageGL->createGLTexture(0, raw); | 3472 | gStartImageGL->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
3472 | } | 3473 | } |
3473 | 3474 | ||
3474 | 3475 | ||
diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp index 424c525..968c496 100644 --- a/linden/indra/newview/lltexlayer.cpp +++ b/linden/indra/newview/lltexlayer.cpp | |||
@@ -115,7 +115,6 @@ LLTexLayerSetBuffer::~LLTexLayerSetBuffer() | |||
115 | if( mBumpTex.notNull()) | 115 | if( mBumpTex.notNull()) |
116 | { | 116 | { |
117 | mBumpTex = NULL ; | 117 | mBumpTex = NULL ; |
118 | LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4; | ||
119 | LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; | 118 | LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; |
120 | } | 119 | } |
121 | } | 120 | } |
@@ -132,7 +131,7 @@ void LLTexLayerSetBuffer::destroyGLTexture() | |||
132 | if( mBumpTex.notNull() ) | 131 | if( mBumpTex.notNull() ) |
133 | { | 132 | { |
134 | mBumpTex = NULL ; | 133 | mBumpTex = NULL ; |
135 | LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4; | 134 | //LLImageGL::sGlobalTextureMemoryInBytes -= mWidth * mHeight * 4; |
136 | LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; | 135 | LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; |
137 | } | 136 | } |
138 | 137 | ||
@@ -165,6 +164,14 @@ void LLTexLayerSetBuffer::createBumpTexture() | |||
165 | 164 | ||
166 | LLImageGL::sGlobalTextureMemoryInBytes += mWidth * mHeight * 4; | 165 | LLImageGL::sGlobalTextureMemoryInBytes += mWidth * mHeight * 4; |
167 | LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4; | 166 | LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4; |
167 | |||
168 | if(gAuditTexture) | ||
169 | { | ||
170 | mBumpTex->setCategory(LLViewerImageBoostLevel::TEXLAYER_BUMP) ; | ||
171 | mBumpTex->setTextureSize(mWidth * mHeight * 4) ; | ||
172 | mBumpTex->setComponents(4) ; | ||
173 | mBumpTex->incTextureCounter() ; | ||
174 | } | ||
168 | } | 175 | } |
169 | } | 176 | } |
170 | 177 | ||
@@ -619,7 +626,7 @@ void LLTexLayerSetBuffer::bindBumpTexture( U32 stage ) | |||
619 | if( mLastBindTime != LLImageGL::sLastFrameTime ) | 626 | if( mLastBindTime != LLImageGL::sLastFrameTime ) |
620 | { | 627 | { |
621 | mLastBindTime = LLImageGL::sLastFrameTime; | 628 | mLastBindTime = LLImageGL::sLastFrameTime; |
622 | LLImageGL::updateBoundTexMem(mWidth * mHeight * 4); | 629 | mBumpTex->updateBoundTexMem(); |
623 | } | 630 | } |
624 | } | 631 | } |
625 | else | 632 | else |
@@ -833,7 +840,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) | |||
833 | if( image_gl ) | 840 | if( image_gl ) |
834 | { | 841 | { |
835 | LLGLSUIDefault gls_ui; | 842 | LLGLSUIDefault gls_ui; |
836 | gGL.getTexUnit(0)->bind(image_gl); | 843 | gGL.getTexUnit(0)->bind(image_gl, TRUE); |
837 | gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); | 844 | gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); |
838 | gl_rect_2d_simple_tex( width, height ); | 845 | gl_rect_2d_simple_tex( width, height ); |
839 | } | 846 | } |
@@ -1418,7 +1425,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) | |||
1418 | 1425 | ||
1419 | LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); | 1426 | LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); |
1420 | 1427 | ||
1421 | gGL.getTexUnit(0)->bind(image_gl); | 1428 | gGL.getTexUnit(0)->bind(image_gl, TRUE); |
1422 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); | 1429 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); |
1423 | 1430 | ||
1424 | gl_rect_2d_simple_tex( width, height ); | 1431 | gl_rect_2d_simple_tex( width, height ); |
@@ -1440,7 +1447,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) | |||
1440 | LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); | 1447 | LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); |
1441 | if( image_gl ) | 1448 | if( image_gl ) |
1442 | { | 1449 | { |
1443 | gGL.getTexUnit(0)->bind(image_gl); | 1450 | gGL.getTexUnit(0)->bind(image_gl, TRUE); |
1444 | gl_rect_2d_simple_tex( width, height ); | 1451 | gl_rect_2d_simple_tex( width, height ); |
1445 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); | 1452 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); |
1446 | } | 1453 | } |
@@ -1617,7 +1624,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 | |||
1617 | 1624 | ||
1618 | LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); | 1625 | LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); |
1619 | 1626 | ||
1620 | gGL.getTexUnit(0)->bind(image_gl); | 1627 | gGL.getTexUnit(0)->bind(image_gl, TRUE); |
1621 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); | 1628 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); |
1622 | 1629 | ||
1623 | gl_rect_2d_simple_tex( width, height ); | 1630 | gl_rect_2d_simple_tex( width, height ); |
@@ -1643,7 +1650,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 | |||
1643 | ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) | 1650 | ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) |
1644 | { | 1651 | { |
1645 | LLGLSNoAlphaTest gls_no_alpha_test; | 1652 | LLGLSNoAlphaTest gls_no_alpha_test; |
1646 | gGL.getTexUnit(0)->bind(image_gl); | 1653 | gGL.getTexUnit(0)->bind(image_gl, TRUE); |
1647 | gl_rect_2d_simple_tex( width, height ); | 1654 | gl_rect_2d_simple_tex( width, height ); |
1648 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); | 1655 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); |
1649 | } | 1656 | } |
@@ -2088,14 +2095,14 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) | |||
2088 | // Create the GL texture, and then hang onto it for future use. | 2095 | // Create the GL texture, and then hang onto it for future use. |
2089 | if( mNeedsCreateTexture ) | 2096 | if( mNeedsCreateTexture ) |
2090 | { | 2097 | { |
2091 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); | 2098 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw, 0, TRUE, LLViewerImageBoostLevel::TEXLAYER_CACHE); |
2092 | mNeedsCreateTexture = FALSE; | 2099 | mNeedsCreateTexture = FALSE; |
2093 | gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); | 2100 | gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); |
2094 | mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); | 2101 | mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); |
2095 | } | 2102 | } |
2096 | 2103 | ||
2097 | LLGLSNoAlphaTest gls_no_alpha_test; | 2104 | LLGLSNoAlphaTest gls_no_alpha_test; |
2098 | gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); | 2105 | gGL.getTexUnit(0)->bind(mCachedProcessedImageGL, TRUE); |
2099 | gl_rect_2d_simple_tex( width, height ); | 2106 | gl_rect_2d_simple_tex( width, height ); |
2100 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); | 2107 | gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); |
2101 | stop_glerror(); | 2108 | stop_glerror(); |
@@ -2543,7 +2550,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i | |||
2543 | // that once an image is a mask it's always a mask. | 2550 | // that once an image is a mask it's always a mask. |
2544 | image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); | 2551 | image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); |
2545 | } | 2552 | } |
2546 | image_gl->createGLTexture(0, image_raw); | 2553 | image_gl->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
2547 | 2554 | ||
2548 | gGL.getTexUnit(0)->bind(image_gl); | 2555 | gGL.getTexUnit(0)->bind(image_gl); |
2549 | image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); | 2556 | image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); |
diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp index 9c3bed2..e0bef61 100644 --- a/linden/indra/newview/lltexturecache.cpp +++ b/linden/indra/newview/lltexturecache.cpp | |||
@@ -43,11 +43,18 @@ | |||
43 | // Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout | 43 | // Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout |
44 | #include "llappviewer.h" | 44 | #include "llappviewer.h" |
45 | 45 | ||
46 | #define USE_LFS_READ 0 | 46 | // Cache organization: |
47 | #define USE_LFS_WRITE 0 | 47 | // cache/texture.entries |
48 | 48 | // Unordered array of Entry structs | |
49 | // Note: first 4 bytes store file size, rest is j2c data | 49 | // cache/texture.cache |
50 | const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024; | 50 | // First TEXTURE_CACHE_ENTRY_SIZE bytes of each texture in texture.entries in same order |
51 | // Entry size same as header packet, so we're not 0-padding unless whole image is contained in header. | ||
52 | // cache/textures/[0-F]/UUID.texture | ||
53 | // Actual texture body files | ||
54 | |||
55 | const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; | ||
56 | const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit | ||
57 | const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate) | ||
51 | 58 | ||
52 | class LLTextureCacheWorker : public LLWorkerClass | 59 | class LLTextureCacheWorker : public LLWorkerClass |
53 | { | 60 | { |
@@ -309,93 +316,74 @@ void LLTextureCacheWorker::startWork(S32 param) | |||
309 | { | 316 | { |
310 | } | 317 | } |
311 | 318 | ||
319 | // This is where a texture is read from the cache system (header and body) | ||
320 | // Current assumption are: | ||
321 | // - the whole data are in a raw form, will be stored at mReadData | ||
322 | // - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache) | ||
323 | // - the code supports offset reading but this is actually never exercised in the viewer | ||
312 | bool LLTextureCacheRemoteWorker::doRead() | 324 | bool LLTextureCacheRemoteWorker::doRead() |
313 | { | 325 | { |
326 | bool done = false; | ||
327 | S32 idx = -1; | ||
328 | |||
314 | S32 local_size = 0; | 329 | S32 local_size = 0; |
315 | std::string local_filename; | 330 | std::string local_filename; |
316 | 331 | ||
332 | // First state / stage : find out if the file is local | ||
317 | if (mState == INIT) | 333 | if (mState == INIT) |
318 | { | 334 | { |
319 | std::string filename = mCache->getLocalFileName(mID); | 335 | std::string filename = mCache->getLocalFileName(mID); |
320 | local_filename = filename + ".j2c"; | 336 | // Is it a JPEG2000 file? |
321 | local_size = LLAPRFile::size(local_filename); | ||
322 | if (local_size == 0) | ||
323 | { | 337 | { |
324 | local_filename = filename + ".tga"; | 338 | local_filename = filename + ".j2c"; |
325 | local_size = LLAPRFile::size(local_filename); | 339 | local_size = LLAPRFile::size(local_filename); |
326 | if (local_size > 0) | 340 | if (local_size > 0) |
327 | { | 341 | { |
328 | mImageFormat = IMG_CODEC_TGA; | 342 | mImageFormat = IMG_CODEC_J2C; |
329 | mDataSize = local_size; // Only a complete .tga file is valid | ||
330 | } | 343 | } |
331 | } | 344 | } |
332 | if (local_size > 0) | 345 | // If not, is it a jpeg file? |
333 | { | 346 | if (local_size == 0) |
334 | mState = LOCAL; | ||
335 | } | ||
336 | else | ||
337 | { | ||
338 | mState = CACHE; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | if (mState == LOCAL) | ||
343 | { | ||
344 | #if USE_LFS_READ | ||
345 | if (mFileHandle == LLLFSThread::nullHandle()) | ||
346 | { | 347 | { |
347 | mImageLocal = TRUE; | 348 | local_filename = filename + ".jpg"; |
348 | mImageSize = local_size; | 349 | local_size = LLAPRFile::size(local_filename); |
349 | if (!mDataSize || mDataSize + mOffset > local_size) | 350 | if (local_size > 0) |
350 | { | ||
351 | mDataSize = local_size - mOffset; | ||
352 | } | ||
353 | if (mDataSize <= 0) | ||
354 | { | 351 | { |
355 | // no more data to read | 352 | mImageFormat = IMG_CODEC_JPEG; |
356 | mDataSize = 0; | 353 | mDataSize = local_size; // Only a complete .jpg file is valid |
357 | return true; | ||
358 | } | 354 | } |
359 | mReadData = new U8[mDataSize]; | ||
360 | mBytesRead = -1; | ||
361 | mBytesToRead = mDataSize; | ||
362 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | ||
363 | mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, | ||
364 | new ReadResponder(mCache, mRequestHandle)); | ||
365 | return false; | ||
366 | } | 355 | } |
367 | else | 356 | // Hmm... What about a targa file? (used for UI texture mostly) |
357 | if (local_size == 0) | ||
368 | { | 358 | { |
369 | if (mBytesRead >= 0) | 359 | local_filename = filename + ".tga"; |
370 | { | 360 | local_size = LLAPRFile::size(local_filename); |
371 | if (mBytesRead != mBytesToRead) | 361 | if (local_size > 0) |
372 | { | ||
373 | // llwarns << "Error reading file from local cache: " << local_filename | ||
374 | // << " Bytes: " << mDataSize << " Offset: " << mOffset | ||
375 | // << " / " << mDataSize << llendl; | ||
376 | mDataSize = 0; // failed | ||
377 | delete[] mReadData; | ||
378 | mReadData = NULL; | ||
379 | } | ||
380 | return true; | ||
381 | } | ||
382 | else | ||
383 | { | 362 | { |
384 | return false; | 363 | mImageFormat = IMG_CODEC_TGA; |
364 | mDataSize = local_size; // Only a complete .tga file is valid | ||
385 | } | 365 | } |
386 | } | 366 | } |
387 | #else | 367 | // Determine the next stage: if we found a file, then LOCAL else CACHE |
368 | mState = (local_size > 0 ? LOCAL : CACHE); | ||
369 | } | ||
370 | |||
371 | // Second state / stage : if the file is local, load it and leave | ||
372 | if (!done && (mState == LOCAL)) | ||
373 | { | ||
374 | llassert(local_size != 0); // we're assuming there is a non empty local file here... | ||
388 | if (!mDataSize || mDataSize > local_size) | 375 | if (!mDataSize || mDataSize > local_size) |
389 | { | 376 | { |
390 | mDataSize = local_size; | 377 | mDataSize = local_size; |
391 | } | 378 | } |
379 | // Allocate read buffer | ||
392 | mReadData = new U8[mDataSize]; | 380 | mReadData = new U8[mDataSize]; |
393 | S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize); | 381 | S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize); |
394 | if (bytes_read != mDataSize) | 382 | if (bytes_read != mDataSize) |
395 | { | 383 | { |
396 | // llwarns << "Error reading file from local cache: " << local_filename | 384 | llwarns << "Error reading file from local cache: " << local_filename |
397 | // << " Bytes: " << mDataSize << " Offset: " << mOffset | 385 | << " Bytes: " << mDataSize << " Offset: " << mOffset |
398 | // << " / " << mDataSize << llendl; | 386 | << " / " << mDataSize << llendl; |
399 | mDataSize = 0; | 387 | mDataSize = 0; |
400 | delete[] mReadData; | 388 | delete[] mReadData; |
401 | mReadData = NULL; | 389 | mReadData = NULL; |
@@ -405,403 +393,273 @@ bool LLTextureCacheRemoteWorker::doRead() | |||
405 | mImageSize = local_size; | 393 | mImageSize = local_size; |
406 | mImageLocal = TRUE; | 394 | mImageLocal = TRUE; |
407 | } | 395 | } |
408 | return true; | 396 | // We're done... |
409 | #endif | 397 | done = true; |
410 | } | 398 | } |
411 | 399 | ||
412 | S32 idx = -1; | 400 | // Second state / stage : identify the cache or not... |
413 | 401 | if (!done && (mState == CACHE)) | |
414 | if (mState == CACHE) | ||
415 | { | 402 | { |
416 | llassert_always(mImageSize == 0); | 403 | idx = mCache->getHeaderCacheEntry(mID, mImageSize); |
417 | idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize); | 404 | if (idx < 0) |
418 | if (idx >= 0 && mImageSize > mOffset) | ||
419 | { | 405 | { |
420 | llassert_always(mImageSize > 0); | 406 | // The texture is *not* cached. We're done here... |
421 | if (!mDataSize || mDataSize > mImageSize) | 407 | mDataSize = 0; // no data |
422 | { | 408 | done = true; |
423 | mDataSize = mImageSize; | ||
424 | } | ||
425 | mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; | ||
426 | } | 409 | } |
427 | else | 410 | else |
428 | { | 411 | { |
429 | mDataSize = 0; // no data | 412 | // If the read offset is bigger than the header cache, we read directly from the body |
430 | return true; | 413 | // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER |
414 | mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; | ||
431 | } | 415 | } |
432 | } | 416 | } |
433 | 417 | ||
434 | if (mState == HEADER) | 418 | // Third state / stage : read data from the header cache (texture.entries) file |
419 | if (!done && (mState == HEADER)) | ||
435 | { | 420 | { |
436 | #if USE_LFS_READ | 421 | llassert_always(idx >= 0); // we need an entry here or reading the header makes no sense |
437 | if (mFileHandle == LLLFSThread::nullHandle()) | ||
438 | { | ||
439 | llassert_always(idx >= 0); | ||
440 | llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); | ||
441 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; | ||
442 | S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | ||
443 | llassert_always(mReadData == NULL); | ||
444 | mReadData = new U8[size]; | ||
445 | mBytesRead = -1; | ||
446 | mBytesToRead = size; | ||
447 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | ||
448 | mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName, | ||
449 | mReadData, offset, mBytesToRead, | ||
450 | new ReadResponder(mCache, mRequestHandle)); | ||
451 | return false; | ||
452 | } | ||
453 | else | ||
454 | { | ||
455 | if (mBytesRead >= 0) | ||
456 | { | ||
457 | if (mBytesRead != mBytesToRead) | ||
458 | { | ||
459 | // llwarns << "LLTextureCacheWorker: " << mID | ||
460 | // << " incorrect number of bytes read from header: " << mBytesRead | ||
461 | // << " != " << mBytesToRead << llendl; | ||
462 | mDataSize = -1; // failed | ||
463 | return true; | ||
464 | } | ||
465 | if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) | ||
466 | { | ||
467 | return true; // done | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | mFileHandle = LLLFSThread::nullHandle(); | ||
472 | mState = BODY; | ||
473 | } | ||
474 | } | ||
475 | else | ||
476 | { | ||
477 | return false; | ||
478 | } | ||
479 | } | ||
480 | #else | ||
481 | llassert_always(idx >= 0); | ||
482 | llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); | 422 | llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); |
483 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; | 423 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; |
424 | // Compute the size we need to read (in bytes) | ||
484 | S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | 425 | S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; |
426 | size = llmin(size, mDataSize); | ||
427 | // Allocate the read buffer | ||
485 | mReadData = new U8[size]; | 428 | mReadData = new U8[size]; |
486 | S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, | 429 | S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, |
487 | mReadData, offset, size); | 430 | mReadData, offset, size); |
488 | if (bytes_read != size) | 431 | if (bytes_read != size) |
489 | { | 432 | { |
490 | // llwarns << "LLTextureCacheWorker: " << mID | 433 | llwarns << "LLTextureCacheWorker: " << mID |
491 | // << " incorrect number of bytes read from header: " << bytes_read | 434 | << " incorrect number of bytes read from header: " << bytes_read |
492 | // << " / " << size << llendl; | 435 | << " / " << size << llendl; |
436 | delete[] mReadData; | ||
437 | mReadData = NULL; | ||
493 | mDataSize = -1; // failed | 438 | mDataSize = -1; // failed |
494 | return true; | 439 | done = true; |
495 | } | 440 | } |
496 | if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) | 441 | // If we already read all we expected, we're actually done |
442 | if (mDataSize <= bytes_read) | ||
497 | { | 443 | { |
498 | return true; // done | 444 | done = true; |
499 | } | 445 | } |
500 | else | 446 | else |
501 | { | 447 | { |
502 | mState = BODY; | 448 | mState = BODY; |
503 | } | 449 | } |
504 | #endif | ||
505 | } | 450 | } |
506 | 451 | ||
507 | if (mState == BODY) | 452 | // Fourth state / stage : read the rest of the data from the UUID based cached file |
453 | if (!done && (mState == BODY)) | ||
508 | { | 454 | { |
509 | #if USE_LFS_READ | ||
510 | if (mFileHandle == LLLFSThread::nullHandle()) | ||
511 | { | ||
512 | std::string filename = mCache->getTextureFileName(mID); | ||
513 | S32 filesize = LLAPRFile::size(filename); | ||
514 | if (filesize > mOffset) | ||
515 | { | ||
516 | S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; | ||
517 | mDataSize = llmin(datasize, mDataSize); | ||
518 | S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | ||
519 | data_offset = llmax(data_offset, 0); | ||
520 | S32 file_size = mDataSize - data_offset; | ||
521 | S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; | ||
522 | file_offset = llmax(file_offset, 0); | ||
523 | |||
524 | llassert_always(mDataSize > 0); | ||
525 | U8* data = new U8[mDataSize]; | ||
526 | if (data_offset > 0) | ||
527 | { | ||
528 | llassert_always(mReadData); | ||
529 | llassert_always(data_offset <= mDataSize); | ||
530 | memcpy(data, mReadData, data_offset); | ||
531 | delete[] mReadData; | ||
532 | mReadData = NULL; | ||
533 | } | ||
534 | llassert_always(mReadData == NULL); | ||
535 | mReadData = data; | ||
536 | |||
537 | mBytesRead = -1; | ||
538 | mBytesToRead = file_size; | ||
539 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | ||
540 | llassert_always(data_offset + mBytesToRead <= mDataSize); | ||
541 | mFileHandle = LLLFSThread::sLocal->read(filename, | ||
542 | mReadData + data_offset, file_offset, mBytesToRead, | ||
543 | new ReadResponder(mCache, mRequestHandle)); | ||
544 | return false; | ||
545 | } | ||
546 | else | ||
547 | { | ||
548 | mDataSize = TEXTURE_CACHE_ENTRY_SIZE; | ||
549 | return true; // done | ||
550 | } | ||
551 | } | ||
552 | else | ||
553 | { | ||
554 | if (mBytesRead >= 0) | ||
555 | { | ||
556 | if (mBytesRead != mBytesToRead) | ||
557 | { | ||
558 | // llwarns << "LLTextureCacheWorker: " << mID | ||
559 | // << " incorrect number of bytes read from body: " << mBytesRead | ||
560 | // << " != " << mBytesToRead << llendl; | ||
561 | mDataSize = -1; // failed | ||
562 | } | ||
563 | return true; | ||
564 | } | ||
565 | else | ||
566 | { | ||
567 | return false; | ||
568 | } | ||
569 | } | ||
570 | #else | ||
571 | std::string filename = mCache->getTextureFileName(mID); | 455 | std::string filename = mCache->getTextureFileName(mID); |
572 | S32 filesize = LLAPRFile::size(filename); | 456 | S32 filesize = LLAPRFile::size(filename); |
573 | S32 bytes_read = 0; | 457 | |
574 | if (filesize > mOffset) | 458 | if (filesize && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset) |
575 | { | 459 | { |
576 | S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; | 460 | S32 max_datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize - mOffset; |
577 | mDataSize = llmin(datasize, mDataSize); | 461 | mDataSize = llmin(max_datasize, mDataSize); |
578 | S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | 462 | |
579 | data_offset = llmax(data_offset, 0); | 463 | S32 data_offset, file_size, file_offset; |
580 | S32 file_size = mDataSize - data_offset; | ||
581 | S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; | ||
582 | file_offset = llmax(file_offset, 0); | ||
583 | 464 | ||
465 | // Reserve the whole data buffer first | ||
584 | U8* data = new U8[mDataSize]; | 466 | U8* data = new U8[mDataSize]; |
585 | if (data_offset > 0) | 467 | |
468 | // Set the data file pointers taking the read offset into account. 2 cases: | ||
469 | if (mOffset < TEXTURE_CACHE_ENTRY_SIZE) | ||
586 | { | 470 | { |
471 | // Offset within the header record. That means we read something from the header cache. | ||
472 | // Note: most common case is (mOffset = 0), so this is the "normal" code path. | ||
473 | data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; // i.e. TEXTURE_CACHE_ENTRY_SIZE if mOffset nul (common case) | ||
474 | file_offset = 0; | ||
475 | file_size = mDataSize - data_offset; | ||
476 | // Copy the raw data we've been holding from the header cache into the new sized buffer | ||
587 | llassert_always(mReadData); | 477 | llassert_always(mReadData); |
588 | memcpy(data, mReadData, data_offset); | 478 | memcpy(data, mReadData, data_offset); |
589 | delete[] mReadData; | 479 | delete[] mReadData; |
480 | mReadData = NULL; | ||
481 | } | ||
482 | else | ||
483 | { | ||
484 | // Offset bigger than the header record. That means we haven't read anything yet. | ||
485 | data_offset = 0; | ||
486 | file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; | ||
487 | file_size = mDataSize; | ||
488 | // No data from header cache to copy in that case, we skipped it all | ||
590 | } | 489 | } |
490 | |||
491 | // Now use that buffer as the object read buffer | ||
492 | llassert_always(mReadData == NULL); | ||
591 | mReadData = data; | 493 | mReadData = data; |
592 | bytes_read = LLAPRFile::readEx(filename, | 494 | |
495 | // Read the data at last | ||
496 | S32 bytes_read = LLAPRFile::readEx(filename, | ||
593 | mReadData + data_offset, | 497 | mReadData + data_offset, |
594 | file_offset, file_size); | 498 | file_offset, file_size); |
595 | if (bytes_read != file_size) | 499 | if (bytes_read != file_size) |
596 | { | 500 | { |
597 | // llwarns << "LLTextureCacheWorker: " << mID | 501 | llwarns << "LLTextureCacheWorker: " << mID |
598 | // << " incorrect number of bytes read from body: " << bytes_read | 502 | << " incorrect number of bytes read from body: " << bytes_read |
599 | // << " / " << file_size << llendl; | 503 | << " / " << file_size << llendl; |
504 | delete[] mReadData; | ||
505 | mReadData = NULL; | ||
600 | mDataSize = -1; // failed | 506 | mDataSize = -1; // failed |
601 | return true; | 507 | done = true; |
602 | } | 508 | } |
603 | } | 509 | } |
604 | else | 510 | else |
605 | { | 511 | { |
606 | mDataSize = TEXTURE_CACHE_ENTRY_SIZE; | 512 | // No body, we're done. |
607 | } | 513 | mDataSize = llmax(TEXTURE_CACHE_ENTRY_SIZE - mOffset, 0); |
608 | 514 | lldebugs << "No body file for: " << filename << llendl; | |
609 | return true; | 515 | } |
610 | #endif | 516 | // Nothing else to do at that point... |
517 | done = true; | ||
611 | } | 518 | } |
612 | 519 | ||
613 | return false; | 520 | // Clean up and exit |
521 | return done; | ||
614 | } | 522 | } |
615 | 523 | ||
524 | // This is where *everything* about a texture is written down in the cache system (entry map, header and body) | ||
525 | // Current assumption are: | ||
526 | // - the whole data are in a raw form, starting at mWriteData | ||
527 | // - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache) | ||
528 | // - the code *does not* support offset writing so there are no difference between buffer addresses and start of data | ||
616 | bool LLTextureCacheRemoteWorker::doWrite() | 529 | bool LLTextureCacheRemoteWorker::doWrite() |
617 | { | 530 | { |
531 | bool done = false; | ||
618 | S32 idx = -1; | 532 | S32 idx = -1; |
619 | 533 | ||
620 | // No LOCAL state for write() | 534 | // First state / stage : check that what we're trying to cache is in an OK shape |
621 | |||
622 | if (mState == INIT) | 535 | if (mState == INIT) |
623 | { | 536 | { |
537 | llassert_always(mOffset == 0); // We currently do not support write offsets | ||
538 | llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... | ||
539 | mState = CACHE; | ||
540 | } | ||
541 | |||
542 | // No LOCAL state for write(): because it doesn't make much sense to cache a local file... | ||
543 | |||
544 | // Second state / stage : set an entry in the headers entry (texture.entries) file | ||
545 | if (!done && (mState == CACHE)) | ||
546 | { | ||
547 | bool alreadyCached = false; | ||
624 | S32 cur_imagesize = 0; | 548 | S32 cur_imagesize = 0; |
625 | S32 offset = mOffset; | 549 | // Checks if this image is already in the entry list |
626 | idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize); | 550 | idx = mCache->getHeaderCacheEntry(mID, cur_imagesize); |
627 | if (idx >= 0 && cur_imagesize > 0) | 551 | if (idx >= 0 && (cur_imagesize >= 0)) |
628 | { | 552 | { |
629 | offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header | 553 | alreadyCached = true; // already there and non empty |
630 | } | 554 | } |
631 | idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry | 555 | idx = mCache->setHeaderCacheEntry(mID, mImageSize); // create or touch the entry |
632 | if (idx >= 0) | 556 | if (idx < 0) |
633 | { | 557 | { |
634 | if(cur_imagesize > 0 && mImageSize != cur_imagesize) | 558 | llwarns << "LLTextureCacheWorker: " << mID |
635 | { | 559 | << " Unable to create header entry for writing!" << llendl; |
636 | // llwarns << "Header cache entry size: " << cur_imagesize << " != mImageSize: " << mImageSize << llendl; | 560 | mDataSize = -1; // failed |
637 | offset = 0; // re-write header | 561 | done = true; |
638 | } | ||
639 | mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; | ||
640 | } | 562 | } |
641 | else | 563 | else |
642 | { | 564 | { |
643 | mDataSize = -1; // failed | 565 | if (cur_imagesize > 0 && (mImageSize != cur_imagesize)) |
644 | return true; | 566 | { |
567 | alreadyCached = false; // re-write the header if the size changed in all cases | ||
568 | } | ||
569 | if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) | ||
570 | { | ||
571 | // Small texture already cached case: we're done with writing | ||
572 | done = true; | ||
573 | } | ||
574 | else | ||
575 | { | ||
576 | // If the texture has already been cached, we don't resave the header and go directly to the body part | ||
577 | mState = alreadyCached ? BODY : HEADER; | ||
578 | } | ||
645 | } | 579 | } |
646 | } | 580 | } |
647 | 581 | ||
648 | if (mState == HEADER) | 582 | // Third stage / state : write the header record in the header file (texture.cache) |
583 | if (!done && (mState == HEADER)) | ||
649 | { | 584 | { |
650 | #if USE_LFS_WRITE | 585 | llassert_always(idx >= 0); // we need an entry here or storing the header makes no sense |
651 | if (mFileHandle == LLLFSThread::nullHandle()) | 586 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file |
587 | S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header | ||
588 | S32 bytes_written; | ||
589 | |||
590 | if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) | ||
652 | { | 591 | { |
653 | llassert_always(idx >= 0); | 592 | // We need to write a full record in the header cache so, if the amount of data is smaller |
654 | llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); | 593 | // than a record, we need to transfer the data to a buffer padded with 0 and write that |
655 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; | 594 | U8* padBuffer = new U8[TEXTURE_CACHE_ENTRY_SIZE]; |
656 | S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | 595 | memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros |
657 | mBytesRead = -1; | 596 | memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer |
658 | mBytesToRead = size; | 597 | bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size); |
659 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | 598 | delete [] padBuffer; |
660 | mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName, | ||
661 | mWriteData, offset, mBytesToRead, | ||
662 | new WriteResponder(mCache, mRequestHandle)); | ||
663 | return false; | ||
664 | } | 599 | } |
665 | else | 600 | else |
666 | { | 601 | { |
667 | if (mBytesRead >= 0) | 602 | // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file |
668 | { | 603 | bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size); |
669 | if (mBytesRead != mBytesToRead) | ||
670 | { | ||
671 | // llwarns << "LLTextureCacheWorker: " << mID | ||
672 | // << " incorrect number of bytes written to header: " << mBytesRead | ||
673 | // << " != " << mBytesToRead << llendl; | ||
674 | mDataSize = -1; // failed | ||
675 | return true; | ||
676 | } | ||
677 | if (mDataSize <= mBytesToRead) | ||
678 | { | ||
679 | return true; // done | ||
680 | } | ||
681 | else | ||
682 | { | ||
683 | mFileHandle = LLLFSThread::nullHandle(); | ||
684 | mState = BODY; | ||
685 | } | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | return false; | ||
690 | } | ||
691 | } | 604 | } |
692 | #else | ||
693 | llassert_always(idx >= 0); | ||
694 | llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); | ||
695 | S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; | ||
696 | S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | ||
697 | S32 bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size); | ||
698 | 605 | ||
699 | if (bytes_written <= 0) | 606 | if (bytes_written <= 0) |
700 | { | 607 | { |
701 | // llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl; | 608 | llwarns << "LLTextureCacheWorker: " << mID |
609 | << " Unable to write header entry!" << llendl; | ||
702 | mDataSize = -1; // failed | 610 | mDataSize = -1; // failed |
703 | return true; | 611 | done = true; |
704 | } | 612 | } |
705 | 613 | ||
706 | if (mDataSize <= size) | 614 | // If we wrote everything (may be more with padding) in the header cache, |
615 | // we're done so we don't have a body to store | ||
616 | if (mDataSize <= bytes_written) | ||
707 | { | 617 | { |
708 | return true; // done | 618 | done = true; |
709 | } | 619 | } |
710 | else | 620 | else |
711 | { | 621 | { |
712 | mState = BODY; | 622 | mState = BODY; |
713 | } | 623 | } |
714 | #endif | ||
715 | } | 624 | } |
716 | 625 | ||
717 | if (mState == BODY) | 626 | // Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name |
627 | if (!done && (mState == BODY)) | ||
718 | { | 628 | { |
719 | #if USE_LFS_WRITE | 629 | llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise... |
720 | if (mFileHandle == LLLFSThread::nullHandle()) | 630 | S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; |
631 | if ((file_size > 0) && mCache->updateTextureEntryList(mID, file_size)) | ||
721 | { | 632 | { |
722 | S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | 633 | // build the cache file name from the UUID |
723 | data_offset = llmax(data_offset, 0); | 634 | std::string filename = mCache->getTextureFileName(mID); |
724 | S32 file_size = mDataSize - data_offset; | 635 | // llinfos << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << llendl; |
725 | S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; | 636 | S32 bytes_written = LLAPRFile::writeEx( filename, |
726 | file_offset = llmax(file_offset, 0); | 637 | mWriteData + TEXTURE_CACHE_ENTRY_SIZE, |
727 | if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) | 638 | 0, file_size); |
728 | { | ||
729 | std::string filename = mCache->getTextureFileName(mID); | ||
730 | mBytesRead = -1; | ||
731 | mBytesToRead = file_size; | ||
732 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | ||
733 | mFileHandle = LLLFSThread::sLocal->write(filename, | ||
734 | mWriteData + data_offset, file_offset, mBytesToRead, | ||
735 | new WriteResponder(mCache, mRequestHandle)); | ||
736 | return false; | ||
737 | } | ||
738 | else | ||
739 | { | ||
740 | mDataSize = 0; // no data written | ||
741 | return true; // done | ||
742 | } | ||
743 | } | ||
744 | else | ||
745 | { | ||
746 | if (mBytesRead >= 0) | ||
747 | { | ||
748 | if (mBytesRead != mBytesToRead) | ||
749 | { | ||
750 | // llwarns << "LLTextureCacheWorker: " << mID | ||
751 | // << " incorrect number of bytes written to body: " << mBytesRead | ||
752 | // << " != " << mBytesToRead << llendl; | ||
753 | mDataSize = -1; // failed | ||
754 | } | ||
755 | return true; | ||
756 | } | ||
757 | else | ||
758 | { | ||
759 | return false; | ||
760 | } | ||
761 | } | ||
762 | #else | ||
763 | S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; | ||
764 | data_offset = llmax(data_offset, 0); | ||
765 | S32 file_size = mDataSize - data_offset; | ||
766 | S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; | ||
767 | file_offset = llmax(file_offset, 0); | ||
768 | S32 bytes_written = 0; | ||
769 | if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) | ||
770 | { | ||
771 | std::string filename = mCache->getTextureFileName(mID); | ||
772 | |||
773 | bytes_written = LLAPRFile::writeEx(filename, | ||
774 | mWriteData + data_offset, | ||
775 | file_offset, file_size); | ||
776 | if (bytes_written <= 0) | 639 | if (bytes_written <= 0) |
777 | { | 640 | { |
641 | llwarns << "LLTextureCacheWorker: " << mID | ||
642 | << " incorrect number of bytes written to body: " << bytes_written | ||
643 | << " / " << file_size << llendl; | ||
778 | mDataSize = -1; // failed | 644 | mDataSize = -1; // failed |
645 | done = true; | ||
779 | } | 646 | } |
780 | } | 647 | } |
781 | else | 648 | else |
782 | { | 649 | { |
783 | mDataSize = 0; // no data written | 650 | mDataSize = 0; // no data written |
784 | } | 651 | } |
785 | 652 | // Nothing else to do at that point... | |
786 | return true; | 653 | done = true; |
787 | #endif | ||
788 | } | 654 | } |
789 | 655 | ||
790 | return false; | 656 | // Clean up and exit |
657 | return done; | ||
791 | } | 658 | } |
792 | 659 | ||
793 | //virtual | 660 | //virtual |
794 | bool LLTextureCacheWorker::doWork(S32 param) | 661 | bool LLTextureCacheWorker::doWork(S32 param) |
795 | { | 662 | { |
796 | // *TODO reenable disabled apr_pool usage disabled due to maint-render-9 merge breakage -brad | ||
797 | //allocate a new local apr_pool | ||
798 | // LLAPRPool pool ; | ||
799 | |||
800 | //save the current mFileAPRPool to avoid breaking anything. | ||
801 | // apr_pool_t* old_pool = mCache->getFileAPRPool() ; | ||
802 | //make mFileAPRPool to point to the local one | ||
803 | // mCache->setFileAPRPool(pool.getAPRPool()) ; | ||
804 | |||
805 | bool res = false; | 663 | bool res = false; |
806 | if (param == 0) // read | 664 | if (param == 0) // read |
807 | { | 665 | { |
@@ -815,10 +673,6 @@ bool LLTextureCacheWorker::doWork(S32 param) | |||
815 | { | 673 | { |
816 | llassert_always(0); | 674 | llassert_always(0); |
817 | } | 675 | } |
818 | |||
819 | //set mFileAPRPool back, the local one will be released automatically. | ||
820 | // mCache->setFileAPRPool(old_pool) ; | ||
821 | |||
822 | return res; | 676 | return res; |
823 | } | 677 | } |
824 | 678 | ||
@@ -884,6 +738,7 @@ LLTextureCache::LLTextureCache(bool threaded) | |||
884 | mWorkersMutex(NULL), | 738 | mWorkersMutex(NULL), |
885 | mHeaderMutex(NULL), | 739 | mHeaderMutex(NULL), |
886 | mListMutex(NULL), | 740 | mListMutex(NULL), |
741 | mHeaderAPRFile(NULL), | ||
887 | mReadOnly(FALSE), | 742 | mReadOnly(FALSE), |
888 | mTexturesSizeTotal(0), | 743 | mTexturesSizeTotal(0), |
889 | mDoPurge(FALSE) | 744 | mDoPurge(FALSE) |
@@ -892,9 +747,6 @@ LLTextureCache::LLTextureCache(bool threaded) | |||
892 | 747 | ||
893 | LLTextureCache::~LLTextureCache() | 748 | LLTextureCache::~LLTextureCache() |
894 | { | 749 | { |
895 | purgeTextureFilesTimeSliced(TRUE); // force-flush all pending file deletes | ||
896 | |||
897 | // apr_pool_destroy(mFileAPRPool); | ||
898 | } | 750 | } |
899 | 751 | ||
900 | ////////////////////////////////////////////////////////////////////////////// | 752 | ////////////////////////////////////////////////////////////////////////////// |
@@ -926,6 +778,9 @@ S32 LLTextureCache::update(U32 max_time_ms) | |||
926 | } | 778 | } |
927 | } | 779 | } |
928 | 780 | ||
781 | unlockWorkers(); | ||
782 | |||
783 | // call 'completed' with workers list unlocked (may call readComplete() or writeComplete() | ||
929 | for (responder_list_t::iterator iter1 = completed_list.begin(); | 784 | for (responder_list_t::iterator iter1 = completed_list.begin(); |
930 | iter1 != completed_list.end(); ++iter1) | 785 | iter1 != completed_list.end(); ++iter1) |
931 | { | 786 | { |
@@ -934,8 +789,6 @@ S32 LLTextureCache::update(U32 max_time_ms) | |||
934 | responder->completed(success); | 789 | responder->completed(success); |
935 | } | 790 | } |
936 | 791 | ||
937 | unlockWorkers(); | ||
938 | |||
939 | return res; | 792 | return res; |
940 | } | 793 | } |
941 | 794 | ||
@@ -954,32 +807,48 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id) | |||
954 | { | 807 | { |
955 | std::string idstr = id.asString(); | 808 | std::string idstr = id.asString(); |
956 | std::string delem = gDirUtilp->getDirDelimiter(); | 809 | std::string delem = gDirUtilp->getDirDelimiter(); |
957 | std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr; | 810 | std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture"; |
958 | return filename; | 811 | return filename; |
959 | } | 812 | } |
960 | 813 | ||
961 | bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) | 814 | bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) |
962 | { | 815 | { |
963 | bool res = false; | 816 | bool res = false; |
964 | bool purge = false; | 817 | bool purge = false; |
965 | // Append UUID to end of texture entries | ||
966 | { | 818 | { |
967 | LLMutexLock lock(&mHeaderMutex); | 819 | LLMutexLock lock(&mHeaderMutex); |
968 | size_map_t::iterator iter = mTexturesSizeMap.find(id); | 820 | size_map_t::iterator iter1 = mTexturesSizeMap.find(id); |
969 | if (iter == mTexturesSizeMap.end() || iter->second < bodysize) | 821 | if (iter1 == mTexturesSizeMap.end() || iter1->second < bodysize) |
970 | { | 822 | { |
971 | llassert_always(bodysize > 0); | 823 | llassert_always(bodysize > 0); |
972 | Entry* entry = new Entry(id, bodysize, time(NULL)); | ||
973 | 824 | ||
974 | LLAPRFile::writeEx(mTexturesDirEntriesFileName, | 825 | S32 oldbodysize = 0; |
975 | (U8*)entry, -1, 1*sizeof(Entry)); | 826 | if (iter1 != mTexturesSizeMap.end()) |
976 | delete entry; | ||
977 | if (iter != mTexturesSizeMap.end()) | ||
978 | { | 827 | { |
979 | mTexturesSizeTotal -= iter->second; | 828 | oldbodysize = iter1->second; |
980 | } | 829 | } |
830 | |||
831 | Entry entry; | ||
832 | S32 idx = openAndReadEntry(id, entry, false); | ||
833 | if (idx < 0) | ||
834 | { | ||
835 | // TODO: change to llwarns | ||
836 | llerrs << "Failed to open entry: " << id << llendl; | ||
837 | removeFromCache(id); | ||
838 | return false; | ||
839 | } | ||
840 | else if (oldbodysize != entry.mBodySize) | ||
841 | { | ||
842 | // TODO: change to llwarns | ||
843 | llerrs << "Entry mismatch in mTextureSizeMap / mHeaderIDMap" | ||
844 | << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl; | ||
845 | } | ||
846 | entry.mBodySize = bodysize; | ||
847 | writeEntryAndClose(idx, entry); | ||
848 | |||
849 | mTexturesSizeTotal -= oldbodysize; | ||
981 | mTexturesSizeTotal += bodysize; | 850 | mTexturesSizeTotal += bodysize; |
982 | mTexturesSizeMap[id] = bodysize; | 851 | |
983 | if (mTexturesSizeTotal > sCacheMaxTexturesSize) | 852 | if (mTexturesSizeTotal > sCacheMaxTexturesSize) |
984 | { | 853 | { |
985 | purge = true; | 854 | purge = true; |
@@ -998,7 +867,7 @@ bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) | |||
998 | 867 | ||
999 | //static | 868 | //static |
1000 | const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB | 869 | const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB |
1001 | F32 LLTextureCache::sHeaderCacheVersion = 1.0f; | 870 | F32 LLTextureCache::sHeaderCacheVersion = 1.2f; |
1002 | U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE; | 871 | U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE; |
1003 | S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit | 872 | S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit |
1004 | const char* entries_filename = "texture.entries"; | 873 | const char* entries_filename = "texture.entries"; |
@@ -1011,7 +880,6 @@ void LLTextureCache::setDirNames(ELLPath location) | |||
1011 | mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename); | 880 | mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename); |
1012 | mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename); | 881 | mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename); |
1013 | mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); | 882 | mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); |
1014 | mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename; | ||
1015 | } | 883 | } |
1016 | 884 | ||
1017 | void LLTextureCache::purgeCache(ELLPath location) | 885 | void LLTextureCache::purgeCache(ELLPath location) |
@@ -1019,7 +887,7 @@ void LLTextureCache::purgeCache(ELLPath location) | |||
1019 | if (!mReadOnly) | 887 | if (!mReadOnly) |
1020 | { | 888 | { |
1021 | setDirNames(location); | 889 | setDirNames(location); |
1022 | 890 | llassert_always(mHeaderAPRFile == NULL); | |
1023 | LLAPRFile::remove(mHeaderEntriesFileName); | 891 | LLAPRFile::remove(mHeaderEntriesFileName); |
1024 | LLAPRFile::remove(mHeaderDataFileName); | 892 | LLAPRFile::remove(mHeaderDataFileName); |
1025 | } | 893 | } |
@@ -1062,80 +930,315 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) | |||
1062 | return max_size; // unused cache space | 930 | return max_size; // unused cache space |
1063 | } | 931 | } |
1064 | 932 | ||
1065 | struct lru_data | 933 | //---------------------------------------------------------------------------- |
934 | // mHeaderMutex must be locked for the following functions! | ||
935 | |||
936 | LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) | ||
937 | { | ||
938 | llassert_always(mHeaderAPRFile == NULL); | ||
939 | apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; | ||
940 | mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, LLAPRFile::local); | ||
941 | mHeaderAPRFile->seek(APR_SET, offset); | ||
942 | return mHeaderAPRFile; | ||
943 | } | ||
944 | |||
945 | void LLTextureCache::closeHeaderEntriesFile() | ||
946 | { | ||
947 | llassert_always(mHeaderAPRFile != NULL); | ||
948 | delete mHeaderAPRFile; | ||
949 | mHeaderAPRFile = NULL; | ||
950 | } | ||
951 | |||
952 | void LLTextureCache::readEntriesHeader() | ||
953 | { | ||
954 | // mHeaderEntriesInfo initializes to default values so safe not to read it | ||
955 | llassert_always(mHeaderAPRFile == NULL); | ||
956 | if (LLAPRFile::isExist(mHeaderEntriesFileName)) | ||
957 | { | ||
958 | LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); | ||
959 | } | ||
960 | } | ||
961 | |||
962 | void LLTextureCache::writeEntriesHeader() | ||
1066 | { | 963 | { |
1067 | lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; } | 964 | llassert_always(mHeaderAPRFile == NULL); |
1068 | U32 time; | 965 | if (!mReadOnly) |
1069 | S32 index; | 966 | { |
1070 | LLUUID uuid; | 967 | LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); |
1071 | struct Compare | 968 | } |
1072 | { | 969 | } |
1073 | // lhs < rhs | 970 | |
1074 | typedef const lru_data* lru_data_ptr; | 971 | static S32 mHeaderEntriesMaxWriteIdx = 0; |
1075 | bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const | 972 | |
973 | S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) | ||
974 | { | ||
975 | S32 idx = -1; | ||
976 | |||
977 | id_map_t::iterator iter1 = mHeaderIDMap.find(id); | ||
978 | if (iter1 != mHeaderIDMap.end()) | ||
979 | { | ||
980 | idx = iter1->second; | ||
981 | } | ||
982 | |||
983 | if (idx < 0) | ||
984 | { | ||
985 | if (create && !mReadOnly) | ||
1076 | { | 986 | { |
1077 | if(a->time == b->time) | 987 | if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) |
1078 | return (a->index < b->index); | 988 | { |
989 | // Add an entry to the end of the list | ||
990 | idx = mHeaderEntriesInfo.mEntries++; | ||
991 | |||
992 | } | ||
993 | else if (!mFreeList.empty()) | ||
994 | { | ||
995 | idx = *(mFreeList.begin()); | ||
996 | mFreeList.erase(mFreeList.begin()); | ||
997 | } | ||
1079 | else | 998 | else |
1080 | return (a->time >= b->time); | 999 | { |
1000 | // Look for a still valid entry in the LRU | ||
1001 | for (std::set<LLUUID>::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();) | ||
1002 | { | ||
1003 | std::set<LLUUID>::iterator curiter2 = iter2++; | ||
1004 | LLUUID oldid = *curiter2; | ||
1005 | // Erase entry from LRU regardless | ||
1006 | mLRU.erase(curiter2); | ||
1007 | // Look up entry and use it if it is valid | ||
1008 | id_map_t::iterator iter3 = mHeaderIDMap.find(oldid); | ||
1009 | if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) | ||
1010 | { | ||
1011 | idx = iter3->second; | ||
1012 | mHeaderIDMap.erase(oldid); | ||
1013 | mTexturesSizeMap.erase(oldid); | ||
1014 | break; | ||
1015 | } | ||
1016 | } | ||
1017 | // if (idx < 0) at this point, we will rebuild the LRU | ||
1018 | // and retry if called from setHeaderCacheEntry(), | ||
1019 | // otherwise this shouldn't happen and will trigger an error | ||
1020 | } | ||
1021 | if (idx >= 0) | ||
1022 | { | ||
1023 | // Set the header index | ||
1024 | mHeaderIDMap[id] = idx; | ||
1025 | llassert_always(mTexturesSizeMap.erase(id) == 0); | ||
1026 | // Initialize the entry (will get written later) | ||
1027 | entry.init(id, time(NULL)); | ||
1028 | // Update Header | ||
1029 | writeEntriesHeader(); | ||
1030 | // Write Entry | ||
1031 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | ||
1032 | LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); | ||
1033 | S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); | ||
1034 | llassert_always(bytes_written == sizeof(Entry)); | ||
1035 | mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); | ||
1036 | closeHeaderEntriesFile(); | ||
1037 | } | ||
1081 | } | 1038 | } |
1082 | }; | 1039 | } |
1083 | }; | 1040 | else |
1041 | { | ||
1042 | // Remove this entry from the LRU if it exists | ||
1043 | mLRU.erase(id); | ||
1044 | // Read the entry | ||
1045 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | ||
1046 | LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); | ||
1047 | S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); | ||
1048 | llassert_always(bytes_read == sizeof(Entry)); | ||
1049 | llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); | ||
1050 | closeHeaderEntriesFile(); | ||
1051 | } | ||
1052 | return idx; | ||
1053 | } | ||
1054 | |||
1055 | void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) | ||
1056 | { | ||
1057 | if (idx >= 0) | ||
1058 | { | ||
1059 | if (!mReadOnly) | ||
1060 | { | ||
1061 | entry.mTime = time(NULL); | ||
1062 | llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); | ||
1063 | if (entry.mBodySize > 0) | ||
1064 | { | ||
1065 | mTexturesSizeMap[entry.mID] = entry.mBodySize; | ||
1066 | } | ||
1067 | // llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; | ||
1068 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | ||
1069 | LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); | ||
1070 | S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); | ||
1071 | llassert_always(bytes_written == sizeof(Entry)); | ||
1072 | mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); | ||
1073 | closeHeaderEntriesFile(); | ||
1074 | } | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) | ||
1079 | { | ||
1080 | U32 num_entries = mHeaderEntriesInfo.mEntries; | ||
1081 | |||
1082 | mHeaderIDMap.clear(); | ||
1083 | mTexturesSizeMap.clear(); | ||
1084 | mFreeList.clear(); | ||
1085 | mTexturesSizeTotal = 0; | ||
1086 | |||
1087 | LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); | ||
1088 | for (U32 idx=0; idx<num_entries; idx++) | ||
1089 | { | ||
1090 | Entry entry; | ||
1091 | S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry)); | ||
1092 | if (bytes_read < sizeof(Entry)) | ||
1093 | { | ||
1094 | llwarns << "Corrupted header entries, failed at " << idx << " / " << num_entries << llendl; | ||
1095 | closeHeaderEntriesFile(); | ||
1096 | purgeAllTextures(false); | ||
1097 | return 0; | ||
1098 | } | ||
1099 | entries.push_back(entry); | ||
1100 | // llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; | ||
1101 | if (entry.mImageSize < 0) | ||
1102 | { | ||
1103 | mFreeList.insert(idx); | ||
1104 | } | ||
1105 | else | ||
1106 | { | ||
1107 | mHeaderIDMap[entry.mID] = idx; | ||
1108 | if (entry.mBodySize > 0) | ||
1109 | { | ||
1110 | mTexturesSizeMap[entry.mID] = entry.mBodySize; | ||
1111 | mTexturesSizeTotal += entry.mBodySize; | ||
1112 | } | ||
1113 | llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize); | ||
1114 | } | ||
1115 | } | ||
1116 | closeHeaderEntriesFile(); | ||
1117 | return num_entries; | ||
1118 | } | ||
1119 | |||
1120 | void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries) | ||
1121 | { | ||
1122 | S32 num_entries = entries.size(); | ||
1123 | llassert_always(num_entries == mHeaderEntriesInfo.mEntries); | ||
1124 | |||
1125 | if (!mReadOnly) | ||
1126 | { | ||
1127 | LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); | ||
1128 | for (S32 idx=0; idx<num_entries; idx++) | ||
1129 | { | ||
1130 | S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); | ||
1131 | llassert_always(bytes_written == sizeof(Entry)); | ||
1132 | } | ||
1133 | mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1); | ||
1134 | closeHeaderEntriesFile(); | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | //---------------------------------------------------------------------------- | ||
1084 | 1139 | ||
1085 | // Called from either the main thread or the worker thread | 1140 | // Called from either the main thread or the worker thread |
1086 | void LLTextureCache::readHeaderCache() | 1141 | void LLTextureCache::readHeaderCache() |
1087 | { | 1142 | { |
1088 | LLMutexLock lock(&mHeaderMutex); | 1143 | LLMutexLock lock(&mHeaderMutex); |
1089 | mHeaderEntriesInfo.mVersion = 0.f; | 1144 | |
1090 | mHeaderEntriesInfo.mEntries = 0; | 1145 | mLRU.clear(); // always clear the LRU |
1091 | if (LLAPRFile::isExist(mHeaderEntriesFileName)) | 1146 | |
1092 | { | 1147 | readEntriesHeader(); |
1093 | LLAPRFile::readEx(mHeaderEntriesFileName, | 1148 | |
1094 | (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); | ||
1095 | } | ||
1096 | if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) | 1149 | if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) |
1097 | { | 1150 | { |
1098 | if (!mReadOnly) | 1151 | if (!mReadOnly) |
1099 | { | 1152 | { |
1100 | // Info with 0 entries | 1153 | purgeAllTextures(false); |
1101 | mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; | ||
1102 | |||
1103 | LLAPRFile::writeEx(mHeaderEntriesFileName, | ||
1104 | (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); | ||
1105 | } | 1154 | } |
1106 | } | 1155 | } |
1107 | else | 1156 | else |
1108 | { | 1157 | { |
1109 | S32 num_entries = mHeaderEntriesInfo.mEntries; | 1158 | std::vector<Entry> entries; |
1159 | U32 num_entries = openAndReadEntries(entries); | ||
1110 | if (num_entries) | 1160 | if (num_entries) |
1111 | { | 1161 | { |
1112 | Entry* entries = new Entry[num_entries]; | 1162 | U32 empty_entries = 0; |
1163 | typedef std::pair<U32, LLUUID> lru_data_t; | ||
1164 | std::set<lru_data_t> lru; | ||
1165 | std::vector<LLUUID> purge_list; | ||
1166 | for (U32 i=0; i<num_entries; i++) | ||
1113 | { | 1167 | { |
1114 | LLAPRFile::readEx(mHeaderEntriesFileName, | 1168 | Entry& entry = entries[i]; |
1115 | (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry)); | 1169 | const LLUUID& id = entry.mID; |
1170 | if (entry.mImageSize < 0) | ||
1171 | { | ||
1172 | // This will be in the Free List, don't put it in the LRY | ||
1173 | ++empty_entries; | ||
1174 | } | ||
1175 | else | ||
1176 | { | ||
1177 | lru.insert(std::make_pair(entry.mTime, id)); | ||
1178 | if (entry.mBodySize > 0) | ||
1179 | { | ||
1180 | if (entry.mBodySize > entry.mImageSize) | ||
1181 | { | ||
1182 | // Shouldn't happen, failsafe only | ||
1183 | llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl; | ||
1184 | purge_list.push_back(id); | ||
1185 | } | ||
1186 | } | ||
1187 | } | ||
1116 | } | 1188 | } |
1117 | typedef std::set<lru_data*, lru_data::Compare> lru_set_t; | 1189 | if (num_entries > sCacheMaxEntries) |
1118 | lru_set_t lru; | ||
1119 | for (S32 i=0; i<num_entries; i++) | ||
1120 | { | 1190 | { |
1121 | if (entries[i].mSize >= 0) // -1 indicates erased entry, skip | 1191 | // Special case: cache size was reduced, need to remove entries |
1192 | // Note: After we prune entries, we will call this again and create the LRU | ||
1193 | U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; | ||
1194 | if (entries_to_purge > 0) | ||
1122 | { | 1195 | { |
1123 | const LLUUID& id = entries[i].mID; | 1196 | for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) |
1124 | lru.insert(new lru_data(entries[i].mTime, i, id)); | 1197 | { |
1125 | mHeaderIDMap[id] = i; | 1198 | purge_list.push_back(iter->second); |
1199 | if (--entries_to_purge <= 0) | ||
1200 | break; | ||
1201 | } | ||
1126 | } | 1202 | } |
1127 | } | 1203 | } |
1128 | mLRU.clear(); | 1204 | else |
1129 | S32 lru_entries = sCacheMaxEntries / 10; | ||
1130 | for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter) | ||
1131 | { | 1205 | { |
1132 | lru_data* data = *iter; | 1206 | S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); |
1133 | mLRU[data->index] = data->uuid; | 1207 | for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) |
1134 | if (--lru_entries <= 0) | 1208 | { |
1135 | break; | 1209 | mLRU.insert(iter->second); |
1210 | // llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; | ||
1211 | if (--lru_entries <= 0) | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | |||
1216 | if (purge_list.size() > 0) | ||
1217 | { | ||
1218 | for (std::vector<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) | ||
1219 | { | ||
1220 | removeFromCache(*iter); | ||
1221 | } | ||
1222 | // If we removed any entries, we need to rebuild the entries list, | ||
1223 | // write the header, and call this again | ||
1224 | std::vector<Entry> new_entries; | ||
1225 | for (U32 i=0; i<num_entries; i++) | ||
1226 | { | ||
1227 | const Entry& entry = entries[i]; | ||
1228 | if (entry.mImageSize >=0) | ||
1229 | { | ||
1230 | new_entries.push_back(entry); | ||
1231 | } | ||
1232 | } | ||
1233 | llassert_always(new_entries.size() <= sCacheMaxEntries); | ||
1234 | mHeaderEntriesInfo.mEntries = new_entries.size(); | ||
1235 | writeEntriesAndClose(new_entries); | ||
1236 | readHeaderCache(); // repeat with new entries file | ||
1237 | } | ||
1238 | else | ||
1239 | { | ||
1240 | writeEntriesAndClose(entries); | ||
1136 | } | 1241 | } |
1137 | for_each(lru.begin(), lru.end(), DeletePointer()); | ||
1138 | delete[] entries; | ||
1139 | } | 1242 | } |
1140 | } | 1243 | } |
1141 | } | 1244 | } |
@@ -1158,13 +1261,21 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) | |||
1158 | LLFile::rmdir(dirname); | 1261 | LLFile::rmdir(dirname); |
1159 | } | 1262 | } |
1160 | } | 1263 | } |
1161 | LLAPRFile::remove(mTexturesDirEntriesFileName); | ||
1162 | if (purge_directories) | 1264 | if (purge_directories) |
1163 | { | 1265 | { |
1164 | LLFile::rmdir(mTexturesDirName); | 1266 | LLFile::rmdir(mTexturesDirName); |
1165 | } | 1267 | } |
1166 | } | 1268 | } |
1269 | mHeaderIDMap.clear(); | ||
1167 | mTexturesSizeMap.clear(); | 1270 | mTexturesSizeMap.clear(); |
1271 | mTexturesSizeTotal = 0; | ||
1272 | mFreeList.clear(); | ||
1273 | mTexturesSizeTotal = 0; | ||
1274 | |||
1275 | // Info with 0 entries | ||
1276 | mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; | ||
1277 | mHeaderEntriesInfo.mEntries = 0; | ||
1278 | writeEntriesHeader(); | ||
1168 | } | 1279 | } |
1169 | 1280 | ||
1170 | void LLTextureCache::purgeTextures(bool validate) | 1281 | void LLTextureCache::purgeTextures(bool validate) |
@@ -1178,50 +1289,37 @@ void LLTextureCache::purgeTextures(bool validate) | |||
1178 | LLAppViewer::instance()->pauseMainloopTimeout(); | 1289 | LLAppViewer::instance()->pauseMainloopTimeout(); |
1179 | 1290 | ||
1180 | LLMutexLock lock(&mHeaderMutex); | 1291 | LLMutexLock lock(&mHeaderMutex); |
1181 | 1292 | ||
1182 | S32 filesize = LLAPRFile::size(mTexturesDirEntriesFileName); | 1293 | llinfos << "TEXTURE CACHE: Purging." << llendl; |
1183 | S32 num_entries = filesize / sizeof(Entry); | 1294 | |
1184 | if (num_entries * (S32)sizeof(Entry) != filesize) | 1295 | // Read the entries list |
1185 | { | 1296 | std::vector<Entry> entries; |
1186 | LL_WARNS("TextureCache") << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; | 1297 | U32 num_entries = openAndReadEntries(entries); |
1187 | purgeAllTextures(false); | 1298 | if (!num_entries) |
1188 | return; | ||
1189 | } | ||
1190 | if (num_entries == 0) | ||
1191 | { | 1299 | { |
1192 | return; // nothing to do | 1300 | writeEntriesAndClose(entries); |
1301 | return; // nothing to purge | ||
1193 | } | 1302 | } |
1194 | 1303 | ||
1195 | Entry* entries = new Entry[num_entries]; | 1304 | // Use mTexturesSizeMap to collect UUIDs of textures with bodies |
1196 | S32 bytes_read = LLAPRFile::readEx(mTexturesDirEntriesFileName, | 1305 | typedef std::set<std::pair<U32,S32> > time_idx_set_t; |
1197 | (U8*)entries, 0, num_entries*sizeof(Entry)); | 1306 | std::set<std::pair<U32,S32> > time_idx_set; |
1198 | if (bytes_read != filesize) | 1307 | for (size_map_t::iterator iter1 = mTexturesSizeMap.begin(); |
1308 | iter1 != mTexturesSizeMap.end(); ++iter1) | ||
1199 | { | 1309 | { |
1200 | LL_WARNS("TextureCache") << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; | 1310 | if (iter1->second > 0) |
1201 | purgeAllTextures(false); | ||
1202 | return; | ||
1203 | } | ||
1204 | |||
1205 | LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Reading " << num_entries << " Entries from " << mTexturesDirEntriesFileName << LL_ENDL; | ||
1206 | |||
1207 | std::map<LLUUID, S32> entry_idx_map; | ||
1208 | S64 total_size = 0; | ||
1209 | for (S32 idx=0; idx<num_entries; idx++) | ||
1210 | { | ||
1211 | const LLUUID& id = entries[idx].mID; | ||
1212 | LL_DEBUGS("TextureCache") << "Entry: " << id << " Size: " << entries[idx].mSize << " Time: " << entries[idx].mTime << LL_ENDL; | ||
1213 | std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id); | ||
1214 | if (iter != entry_idx_map.end()) | ||
1215 | { | 1311 | { |
1216 | // Newer entry replacing older entry | 1312 | id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first); |
1217 | S32 pidx = iter->second; | 1313 | if (iter2 != mHeaderIDMap.end()) |
1218 | total_size -= entries[pidx].mSize; | 1314 | { |
1219 | entries[pidx].mSize = 0; // flag: skip older entry | 1315 | S32 idx = iter2->second; |
1316 | time_idx_set.insert(std::make_pair(entries[idx].mTime, idx)); | ||
1317 | // llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl; | ||
1318 | } | ||
1220 | } | 1319 | } |
1221 | entry_idx_map[id] = idx; | ||
1222 | total_size += entries[idx].mSize; | ||
1223 | } | 1320 | } |
1224 | 1321 | ||
1322 | // Validate 1/256th of the files on startup | ||
1225 | U32 validate_idx = 0; | 1323 | U32 validate_idx = 0; |
1226 | if (validate) | 1324 | if (validate) |
1227 | { | 1325 | { |
@@ -1230,19 +1328,17 @@ void LLTextureCache::purgeTextures(bool validate) | |||
1230 | gSavedSettings.setU32("CacheValidateCounter", next_idx); | 1328 | gSavedSettings.setU32("CacheValidateCounter", next_idx); |
1231 | LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL; | 1329 | LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL; |
1232 | } | 1330 | } |
1233 | 1331 | ||
1234 | S64 min_cache_size = sCacheMaxTexturesSize / 100 * 95; | 1332 | S64 cache_size = mTexturesSizeTotal; |
1333 | S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f-TEXTURE_CACHE_PURGE_AMOUNT)*100)) / 100; | ||
1235 | S32 purge_count = 0; | 1334 | S32 purge_count = 0; |
1236 | S32 next_idx = 0; | 1335 | for (time_idx_set_t::iterator iter = time_idx_set.begin(); |
1237 | for (S32 idx=0; idx<num_entries; idx++) | 1336 | iter != time_idx_set.end(); ++iter) |
1238 | { | 1337 | { |
1239 | if (entries[idx].mSize == 0) | 1338 | S32 idx = iter->second; |
1240 | { | ||
1241 | continue; | ||
1242 | } | ||
1243 | bool purge_entry = false; | 1339 | bool purge_entry = false; |
1244 | std::string filename = getTextureFileName(entries[idx].mID); | 1340 | std::string filename = getTextureFileName(entries[idx].mID); |
1245 | if (total_size >= min_cache_size) | 1341 | if (cache_size >= purged_cache_size) |
1246 | { | 1342 | { |
1247 | purge_entry = true; | 1343 | purge_entry = true; |
1248 | } | 1344 | } |
@@ -1252,112 +1348,47 @@ void LLTextureCache::purgeTextures(bool validate) | |||
1252 | S32 uuididx = entries[idx].mID.mData[0]; | 1348 | S32 uuididx = entries[idx].mID.mData[0]; |
1253 | if (uuididx == validate_idx) | 1349 | if (uuididx == validate_idx) |
1254 | { | 1350 | { |
1255 | LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mSize << LL_ENDL; | 1351 | LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL; |
1256 | S32 bodysize = LLAPRFile::size(filename); | 1352 | S32 bodysize = LLAPRFile::size(filename); |
1257 | if (bodysize != entries[idx].mSize) | 1353 | if (bodysize != entries[idx].mBodySize) |
1258 | { | 1354 | { |
1259 | LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize | 1355 | LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize |
1260 | << filename << LL_ENDL; | 1356 | << filename << LL_ENDL; |
1261 | purge_entry = true; | 1357 | purge_entry = true; |
1262 | } | 1358 | } |
1263 | } | 1359 | } |
1264 | } | 1360 | } |
1265 | if (purge_entry) | 1361 | else |
1266 | { | 1362 | { |
1267 | purge_count++; | 1363 | break; |
1268 | LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; | ||
1269 | mFilesToDelete.push_back(filename); | ||
1270 | total_size -= entries[idx].mSize; | ||
1271 | entries[idx].mSize = 0; | ||
1272 | } | 1364 | } |
1273 | else | 1365 | |
1366 | if (purge_entry) | ||
1274 | { | 1367 | { |
1275 | if (next_idx != idx) | 1368 | purge_count++; |
1276 | { | 1369 | LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; |
1277 | entries[next_idx] = entries[idx]; | 1370 | LLAPRFile::remove(filename); |
1278 | } | 1371 | cache_size -= entries[idx].mBodySize; |
1279 | ++next_idx; | 1372 | mTexturesSizeTotal -= entries[idx].mBodySize; |
1373 | entries[idx].mBodySize = 0; | ||
1374 | mTexturesSizeMap.erase(entries[idx].mID); | ||
1280 | } | 1375 | } |
1281 | } | 1376 | } |
1282 | num_entries = next_idx; | ||
1283 | 1377 | ||
1284 | mTimeLastFileDelete.reset(); | 1378 | LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL; |
1285 | 1379 | ||
1286 | LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " | 1380 | writeEntriesAndClose(entries); |
1287 | << num_entries << " (" << num_entries*sizeof(Entry)/1024 << "KB)" | ||
1288 | << LL_ENDL; | ||
1289 | |||
1290 | LLAPRFile::remove(mTexturesDirEntriesFileName); | ||
1291 | LLAPRFile::writeEx(mTexturesDirEntriesFileName, | ||
1292 | (U8*)&entries[0], 0, num_entries*sizeof(Entry)); | ||
1293 | |||
1294 | mTexturesSizeTotal = 0; | ||
1295 | mTexturesSizeMap.clear(); | ||
1296 | for (S32 idx=0; idx<num_entries; idx++) | ||
1297 | { | ||
1298 | mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize; | ||
1299 | mTexturesSizeTotal += entries[idx].mSize; | ||
1300 | } | ||
1301 | llassert(mTexturesSizeTotal == total_size); | ||
1302 | 1381 | ||
1303 | delete[] entries; | ||
1304 | |||
1305 | // *FIX:Mani - watchdog back on. | 1382 | // *FIX:Mani - watchdog back on. |
1306 | LLAppViewer::instance()->resumeMainloopTimeout(); | 1383 | LLAppViewer::instance()->resumeMainloopTimeout(); |
1307 | 1384 | ||
1308 | LL_INFOS("TextureCache") << "TEXTURE CACHE:" | 1385 | LL_INFOS("TextureCache") << "TEXTURE CACHE:" |
1309 | << " PURGED: " << purge_count | 1386 | << " PURGED: " << purge_count |
1310 | << " ENTRIES: " << num_entries | 1387 | << " ENTRIES: " << num_entries |
1311 | << " CACHE SIZE: " << total_size/1024/1024 << " MB" | 1388 | << " CACHE SIZE: " << mTexturesSizeTotal / 1024*1024 << " MB" |
1312 | << llendl; | 1389 | << llendl; |
1313 | } | 1390 | } |
1314 | 1391 | ||
1315 | |||
1316 | void LLTextureCache::purgeTextureFilesTimeSliced(BOOL force_all) | ||
1317 | { | ||
1318 | LLMutexLock lock(&mHeaderMutex); | ||
1319 | |||
1320 | F32 delay_between_passes = 1.0f; // seconds | ||
1321 | F32 max_time_per_pass = 0.1f; // seconds | ||
1322 | |||
1323 | if (!force_all && mTimeLastFileDelete.getElapsedTimeF32() <= delay_between_passes) | ||
1324 | { | ||
1325 | return; | ||
1326 | } | ||
1327 | |||
1328 | LLTimer timer; | ||
1329 | S32 howmany = 0; | ||
1330 | |||
1331 | if (mFilesToDelete.size() > 0) | ||
1332 | { | ||
1333 | llinfos << "TEXTURE CACHE: " << mFilesToDelete.size() << " files scheduled for deletion" << llendl; | ||
1334 | } | ||
1335 | |||
1336 | for (LLTextureCache::filename_list_t::iterator iter = mFilesToDelete.begin(); iter!=mFilesToDelete.end(); ) | ||
1337 | { | ||
1338 | LLTextureCache::filename_list_t::iterator iter2 = iter++; | ||
1339 | LLAPRFile::remove(*iter2); | ||
1340 | mFilesToDelete.erase(iter2); | ||
1341 | howmany++; | ||
1342 | |||
1343 | if (!force_all && timer.getElapsedTimeF32() > max_time_per_pass) | ||
1344 | { | ||
1345 | break; | ||
1346 | } | ||
1347 | } | ||
1348 | |||
1349 | if (!mFilesToDelete.empty()) | ||
1350 | { | ||
1351 | llinfos << "TEXTURE CACHE: "<< howmany << " files deleted (" | ||
1352 | << mFilesToDelete.size() << " files left for next pass)" | ||
1353 | << llendl; | ||
1354 | } | ||
1355 | |||
1356 | mTimeLastFileDelete.reset(); | ||
1357 | } | ||
1358 | |||
1359 | |||
1360 | |||
1361 | ////////////////////////////////////////////////////////////////////////////// | 1392 | ////////////////////////////////////////////////////////////////////////////// |
1362 | 1393 | ||
1363 | // call lockWorkers() first! | 1394 | // call lockWorkers() first! |
@@ -1384,75 +1415,39 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) | |||
1384 | } | 1415 | } |
1385 | 1416 | ||
1386 | ////////////////////////////////////////////////////////////////////////////// | 1417 | ////////////////////////////////////////////////////////////////////////////// |
1387 | |||
1388 | // Called from work thread | 1418 | // Called from work thread |
1389 | S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize) | ||
1390 | { | ||
1391 | bool retry = false; | ||
1392 | S32 idx = -1; | ||
1393 | 1419 | ||
1420 | // Reads imagesize from the header, updates timestamp | ||
1421 | S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize) | ||
1422 | { | ||
1423 | LLMutexLock lock(&mHeaderMutex); | ||
1424 | Entry entry; | ||
1425 | S32 idx = openAndReadEntry(id, entry, false); | ||
1426 | if (idx >= 0) | ||
1394 | { | 1427 | { |
1395 | LLMutexLock lock(&mHeaderMutex); | 1428 | imagesize = entry.mImageSize; |
1396 | id_map_t::iterator iter = mHeaderIDMap.find(id); | 1429 | writeEntryAndClose(idx, entry); // updates time |
1397 | if (iter != mHeaderIDMap.end()) | 1430 | } |
1398 | { | 1431 | return idx; |
1399 | idx = iter->second; | 1432 | } |
1400 | } | ||
1401 | else if (touch && !mReadOnly) | ||
1402 | { | ||
1403 | if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) | ||
1404 | { | ||
1405 | // Add an entry | ||
1406 | idx = mHeaderEntriesInfo.mEntries++; | ||
1407 | mHeaderIDMap[id] = idx; | ||
1408 | // Update Info | ||
1409 | LLAPRFile::writeEx(mHeaderEntriesFileName, | ||
1410 | (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); | ||
1411 | } | ||
1412 | else if (!mLRU.empty()) | ||
1413 | { | ||
1414 | idx = mLRU.begin()->first; // will be erased below | ||
1415 | const LLUUID& oldid = mLRU.begin()->second; | ||
1416 | mHeaderIDMap.erase(oldid); | ||
1417 | mTexturesSizeMap.erase(oldid); | ||
1418 | mHeaderIDMap[id] = idx; | ||
1419 | } | ||
1420 | else | ||
1421 | { | ||
1422 | idx = -1; | ||
1423 | retry = true; | ||
1424 | } | ||
1425 | } | ||
1426 | if (idx >= 0) | ||
1427 | { | ||
1428 | if (touch && !mReadOnly) | ||
1429 | { | ||
1430 | // Update the lru entry | ||
1431 | mLRU.erase(idx); | ||
1432 | llassert_always(imagesize && *imagesize > 0); | ||
1433 | Entry* entry = new Entry(id, *imagesize, time(NULL)); | ||
1434 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | ||
1435 | LLAPRFile::writeEx(mHeaderEntriesFileName, | ||
1436 | (U8*)entry, offset, sizeof(Entry)); | ||
1437 | delete entry; | ||
1438 | } | ||
1439 | else if (imagesize) | ||
1440 | { | ||
1441 | // Get the image size | ||
1442 | Entry entry; | ||
1443 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | ||
1444 | 1433 | ||
1445 | LLAPRFile::readEx(mHeaderEntriesFileName, | 1434 | // Writes imagesize to the header, updates timestamp |
1446 | (U8*)&entry, offset, sizeof(Entry)); | 1435 | S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize) |
1447 | *imagesize = entry.mSize; | 1436 | { |
1448 | } | 1437 | LLMutexLock lock(&mHeaderMutex); |
1449 | } | 1438 | llassert_always(imagesize >= 0); |
1439 | Entry entry; | ||
1440 | S32 idx = openAndReadEntry(id, entry, true); | ||
1441 | if (idx >= 0) | ||
1442 | { | ||
1443 | entry.mImageSize = imagesize; | ||
1444 | writeEntryAndClose(idx, entry); | ||
1450 | } | 1445 | } |
1451 | if (retry) | 1446 | else // retry |
1452 | { | 1447 | { |
1453 | readHeaderCache(); // updates the lru | 1448 | readHeaderCache(); // We couldn't write an entry, so refresh the LRU |
1454 | llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); | 1449 | llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); |
1455 | idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion | 1450 | idx = setHeaderCacheEntry(id, imagesize); // assert above ensures no inf. recursion |
1456 | } | 1451 | } |
1457 | return idx; | 1452 | return idx; |
1458 | } | 1453 | } |
@@ -1468,8 +1463,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena | |||
1468 | // so let the thread handle it | 1463 | // so let the thread handle it |
1469 | LLMutexLock lock(&mWorkersMutex); | 1464 | LLMutexLock lock(&mWorkersMutex); |
1470 | LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, | 1465 | LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, |
1471 | NULL, size, offset, 0, | 1466 | NULL, size, offset, 0, |
1472 | responder); | 1467 | responder); |
1473 | handle_t handle = worker->read(); | 1468 | handle_t handle = worker->read(); |
1474 | mReaders[handle] = worker; | 1469 | mReaders[handle] = worker; |
1475 | return handle; | 1470 | return handle; |
@@ -1482,8 +1477,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri | |||
1482 | // so let the thread handle it | 1477 | // so let the thread handle it |
1483 | LLMutexLock lock(&mWorkersMutex); | 1478 | LLMutexLock lock(&mWorkersMutex); |
1484 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, | 1479 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, |
1485 | NULL, size, offset, 0, | 1480 | NULL, size, offset, |
1486 | responder); | 1481 | 0, responder); |
1487 | handle_t handle = worker->read(); | 1482 | handle_t handle = worker->read(); |
1488 | mReaders[handle] = worker; | 1483 | mReaders[handle] = worker; |
1489 | return handle; | 1484 | return handle; |
@@ -1494,7 +1489,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort) | |||
1494 | { | 1489 | { |
1495 | lockWorkers(); | 1490 | lockWorkers(); |
1496 | handle_map_t::iterator iter = mReaders.find(handle); | 1491 | handle_map_t::iterator iter = mReaders.find(handle); |
1497 | llassert_always(iter != mReaders.end()); | 1492 | llassert_always(iter != mReaders.end() || abort); |
1498 | LLTextureCacheWorker* worker = iter->second; | 1493 | LLTextureCacheWorker* worker = iter->second; |
1499 | bool res = worker->complete(); | 1494 | bool res = worker->complete(); |
1500 | if (res || abort) | 1495 | if (res || abort) |
@@ -1528,14 +1523,10 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio | |||
1528 | purgeTextures(false); | 1523 | purgeTextures(false); |
1529 | mDoPurge = FALSE; | 1524 | mDoPurge = FALSE; |
1530 | } | 1525 | } |
1531 | |||
1532 | purgeTextureFilesTimeSliced(); // purge textures from cache in a non-hiccup-way | ||
1533 | |||
1534 | |||
1535 | LLMutexLock lock(&mWorkersMutex); | 1526 | LLMutexLock lock(&mWorkersMutex); |
1536 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, | 1527 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, |
1537 | data, datasize, 0, | 1528 | data, datasize, 0, |
1538 | imagesize, responder); | 1529 | imagesize, responder); |
1539 | handle_t handle = worker->write(); | 1530 | handle_t handle = worker->write(); |
1540 | mWriters[handle] = worker; | 1531 | mWriters[handle] = worker; |
1541 | return handle; | 1532 | return handle; |
@@ -1581,24 +1572,17 @@ void LLTextureCache::addCompleted(Responder* responder, bool success) | |||
1581 | 1572 | ||
1582 | bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) | 1573 | bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) |
1583 | { | 1574 | { |
1584 | if (mReadOnly) | 1575 | if (!mReadOnly) |
1585 | { | ||
1586 | return false; | ||
1587 | } | ||
1588 | LLMutexLock lock(&mHeaderMutex); | ||
1589 | id_map_t::iterator iter = mHeaderIDMap.find(id); | ||
1590 | if (iter != mHeaderIDMap.end()) | ||
1591 | { | 1576 | { |
1592 | S32 idx = iter->second; | 1577 | LLMutexLock lock(&mHeaderMutex); |
1578 | Entry entry; | ||
1579 | S32 idx = openAndReadEntry(id, entry, false); | ||
1593 | if (idx >= 0) | 1580 | if (idx >= 0) |
1594 | { | 1581 | { |
1595 | Entry* entry = new Entry(id, -1, time(NULL)); | 1582 | entry.mImageSize = -1; |
1596 | S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); | 1583 | entry.mBodySize = 0; |
1597 | 1584 | writeEntryAndClose(idx, entry); | |
1598 | LLAPRFile::writeEx(mHeaderEntriesFileName, | 1585 | mFreeList.insert(idx); |
1599 | (U8*)entry, offset, sizeof(Entry)); | ||
1600 | delete entry; | ||
1601 | mLRU[idx] = id; | ||
1602 | mHeaderIDMap.erase(id); | 1586 | mHeaderIDMap.erase(id); |
1603 | mTexturesSizeMap.erase(id); | 1587 | mTexturesSizeMap.erase(id); |
1604 | return true; | 1588 | return true; |
diff --git a/linden/indra/newview/lltexturecache.h b/linden/indra/newview/lltexturecache.h index 1e3ed5b..e4f6934 100644 --- a/linden/indra/newview/lltexturecache.h +++ b/linden/indra/newview/lltexturecache.h | |||
@@ -48,6 +48,27 @@ class LLTextureCache : public LLWorkerThread | |||
48 | friend class LLTextureCacheRemoteWorker; | 48 | friend class LLTextureCacheRemoteWorker; |
49 | friend class LLTextureCacheLocalFileWorker; | 49 | friend class LLTextureCacheLocalFileWorker; |
50 | 50 | ||
51 | private: | ||
52 | // Entries | ||
53 | struct EntriesInfo | ||
54 | { | ||
55 | EntriesInfo() : mVersion(0.f), mEntries(0) {} | ||
56 | F32 mVersion; | ||
57 | U32 mEntries; | ||
58 | }; | ||
59 | struct Entry | ||
60 | { | ||
61 | Entry() {} | ||
62 | Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) : | ||
63 | mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {} | ||
64 | void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; } | ||
65 | LLUUID mID; // 16 bytes | ||
66 | S32 mImageSize; // total size of image if known | ||
67 | S32 mBodySize; // size of body file in body cache | ||
68 | U32 mTime; // seconds since 1/1/1970 | ||
69 | }; | ||
70 | |||
71 | |||
51 | public: | 72 | public: |
52 | 73 | ||
53 | class Responder : public LLResponder | 74 | class Responder : public LLResponder |
@@ -106,10 +127,14 @@ public: | |||
106 | // debug | 127 | // debug |
107 | S32 getNumReads() { return mReaders.size(); } | 128 | S32 getNumReads() { return mReaders.size(); } |
108 | S32 getNumWrites() { return mWriters.size(); } | 129 | S32 getNumWrites() { return mWriters.size(); } |
130 | S64 getUsage() { return mTexturesSizeTotal; } | ||
131 | S64 getMaxUsage() { return sCacheMaxTexturesSize; } | ||
132 | U32 getEntries() { return mHeaderEntriesInfo.mEntries; } | ||
133 | U32 getMaxEntries() { return sCacheMaxEntries; }; | ||
109 | 134 | ||
110 | protected: | 135 | protected: |
111 | // Accessed by LLTextureCacheWorker | 136 | // Accessed by LLTextureCacheWorker |
112 | bool appendToTextureEntryList(const LLUUID& id, S32 size); | 137 | bool updateTextureEntryList(const LLUUID& id, S32 size); |
113 | std::string getLocalFileName(const LLUUID& id); | 138 | std::string getLocalFileName(const LLUUID& id); |
114 | std::string getTextureFileName(const LLUUID& id); | 139 | std::string getTextureFileName(const LLUUID& id); |
115 | void addCompleted(Responder* responder, bool success); | 140 | void addCompleted(Responder* responder, bool success); |
@@ -122,8 +147,16 @@ private: | |||
122 | void readHeaderCache(); | 147 | void readHeaderCache(); |
123 | void purgeAllTextures(bool purge_directories); | 148 | void purgeAllTextures(bool purge_directories); |
124 | void purgeTextures(bool validate); | 149 | void purgeTextures(bool validate); |
125 | void purgeTextureFilesTimeSliced(BOOL force_all = FALSE); | 150 | LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset); |
126 | S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); | 151 | void closeHeaderEntriesFile(); |
152 | void readEntriesHeader(); | ||
153 | void writeEntriesHeader(); | ||
154 | S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create); | ||
155 | void writeEntryAndClose(S32 idx, Entry& entry); | ||
156 | U32 openAndReadEntries(std::vector<Entry>& entries); | ||
157 | void writeEntriesAndClose(const std::vector<Entry>& entries); | ||
158 | S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize); | ||
159 | S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize); | ||
127 | bool removeHeaderCacheEntry(const LLUUID& id); | 160 | bool removeHeaderCacheEntry(const LLUUID& id); |
128 | void lockHeaders() { mHeaderMutex.lock(); } | 161 | void lockHeaders() { mHeaderMutex.lock(); } |
129 | void unlockHeaders() { mHeaderMutex.unlock(); } | 162 | void unlockHeaders() { mHeaderMutex.unlock(); } |
@@ -133,6 +166,7 @@ private: | |||
133 | LLMutex mWorkersMutex; | 166 | LLMutex mWorkersMutex; |
134 | LLMutex mHeaderMutex; | 167 | LLMutex mHeaderMutex; |
135 | LLMutex mListMutex; | 168 | LLMutex mListMutex; |
169 | LLAPRFile* mHeaderAPRFile; | ||
136 | 170 | ||
137 | typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; | 171 | typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; |
138 | handle_map_t mReaders; | 172 | handle_map_t mReaders; |
@@ -143,49 +177,31 @@ private: | |||
143 | 177 | ||
144 | typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t; | 178 | typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t; |
145 | responder_list_t mCompletedList; | 179 | responder_list_t mCompletedList; |
146 | |||
147 | typedef std::list<std::string> filename_list_t; | ||
148 | filename_list_t mFilesToDelete; | ||
149 | LLTimer mTimeLastFileDelete; | ||
150 | 180 | ||
151 | BOOL mReadOnly; | 181 | BOOL mReadOnly; |
152 | 182 | ||
153 | // Entries | ||
154 | struct EntriesInfo | ||
155 | { | ||
156 | F32 mVersion; | ||
157 | U32 mEntries; | ||
158 | }; | ||
159 | struct Entry | ||
160 | { | ||
161 | Entry() {} | ||
162 | Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {} | ||
163 | LLUUID mID; // 128 bits | ||
164 | S32 mSize; // total size of image if known (NOT size cached) | ||
165 | U32 mTime; // seconds since 1/1/1970 | ||
166 | }; | ||
167 | |||
168 | // HEADERS (Include first mip) | 183 | // HEADERS (Include first mip) |
169 | std::string mHeaderEntriesFileName; | 184 | std::string mHeaderEntriesFileName; |
170 | std::string mHeaderDataFileName; | 185 | std::string mHeaderDataFileName; |
171 | EntriesInfo mHeaderEntriesInfo; | 186 | EntriesInfo mHeaderEntriesInfo; |
172 | typedef std::map<S32,LLUUID> index_map_t; | 187 | std::set<S32> mFreeList; // deleted entries |
173 | index_map_t mLRU; // index, id; stored as a map for fast removal | 188 | std::set<LLUUID> mLRU; |
174 | typedef std::map<LLUUID,S32> id_map_t; | 189 | typedef std::map<LLUUID,S32> id_map_t; |
175 | id_map_t mHeaderIDMap; | 190 | id_map_t mHeaderIDMap; |
176 | 191 | ||
177 | // BODIES (TEXTURES minus headers) | 192 | // BODIES (TEXTURES minus headers) |
178 | std::string mTexturesDirName; | 193 | std::string mTexturesDirName; |
179 | std::string mTexturesDirEntriesFileName; | ||
180 | typedef std::map<LLUUID,S32> size_map_t; | 194 | typedef std::map<LLUUID,S32> size_map_t; |
181 | size_map_t mTexturesSizeMap; | 195 | size_map_t mTexturesSizeMap; |
182 | S64 mTexturesSizeTotal; | 196 | S64 mTexturesSizeTotal; |
183 | LLAtomic32<BOOL> mDoPurge; | 197 | LLAtomic32<BOOL> mDoPurge; |
184 | 198 | ||
185 | // Statics | 199 | // Statics |
186 | static F32 sHeaderCacheVersion; | 200 | static F32 sHeaderCacheVersion; |
187 | static U32 sCacheMaxEntries; | 201 | static U32 sCacheMaxEntries; |
188 | static S64 sCacheMaxTexturesSize; | 202 | static S64 sCacheMaxTexturesSize; |
189 | }; | 203 | }; |
190 | 204 | ||
205 | extern const S32 TEXTURE_CACHE_ENTRY_SIZE; | ||
206 | |||
191 | #endif // LL_LLTEXTURECACHE_H | 207 | #endif // LL_LLTEXTURECACHE_H |
diff --git a/linden/indra/newview/lltexturectrl.cpp b/linden/indra/newview/lltexturectrl.cpp index 5500973..f4476fb 100644 --- a/linden/indra/newview/lltexturectrl.cpp +++ b/linden/indra/newview/lltexturectrl.cpp | |||
@@ -556,12 +556,12 @@ void LLFloaterTexturePicker::draw() | |||
556 | if(mImageAssetID.notNull()) | 556 | if(mImageAssetID.notNull()) |
557 | { | 557 | { |
558 | mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); | 558 | mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); |
559 | mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 559 | mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
560 | } | 560 | } |
561 | else if (!mFallbackImageName.empty()) | 561 | else if (!mFallbackImageName.empty()) |
562 | { | 562 | { |
563 | mTexturep = gImageList.getImageFromFile(mFallbackImageName); | 563 | mTexturep = gImageList.getImageFromFile(mFallbackImageName); |
564 | mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 564 | mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
565 | } | 565 | } |
566 | 566 | ||
567 | if (mTentativeLabel) | 567 | if (mTentativeLabel) |
@@ -1314,13 +1314,13 @@ void LLTextureCtrl::draw() | |||
1314 | else if (!mImageAssetID.isNull()) | 1314 | else if (!mImageAssetID.isNull()) |
1315 | { | 1315 | { |
1316 | mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); | 1316 | mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); |
1317 | mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 1317 | mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
1318 | } | 1318 | } |
1319 | else if (!mFallbackImageName.empty()) | 1319 | else if (!mFallbackImageName.empty()) |
1320 | { | 1320 | { |
1321 | // Show fallback image. | 1321 | // Show fallback image. |
1322 | mTexturep = gImageList.getImageFromFile(mFallbackImageName); | 1322 | mTexturep = gImageList.getImageFromFile(mFallbackImageName); |
1323 | mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); | 1323 | mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | // Border | 1326 | // Border |
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 | ////////////////////////////////////////////////////////////////////////////// | ||
diff --git a/linden/indra/newview/lltexturefetch.h b/linden/indra/newview/lltexturefetch.h index 56650e7..c48f609 100644 --- a/linden/indra/newview/lltexturefetch.h +++ b/linden/indra/newview/lltexturefetch.h | |||
@@ -37,26 +37,29 @@ | |||
37 | #include "llimage.h" | 37 | #include "llimage.h" |
38 | #include "lluuid.h" | 38 | #include "lluuid.h" |
39 | #include "llworkerthread.h" | 39 | #include "llworkerthread.h" |
40 | #include "llcurl.h" | ||
41 | #include "lltextureinfo.h" | ||
40 | 42 | ||
41 | class LLViewerImage; | 43 | class LLViewerImage; |
42 | class LLTextureFetchWorker; | 44 | class LLTextureFetchWorker; |
45 | class HTTPGetResponder; | ||
43 | class LLTextureCache; | 46 | class LLTextureCache; |
47 | class LLImageDecodeThread; | ||
44 | class LLHost; | 48 | class LLHost; |
45 | 49 | ||
46 | // Interface class | 50 | // Interface class |
47 | class LLTextureFetch : public LLWorkerThread | 51 | class LLTextureFetch : public LLWorkerThread |
48 | { | 52 | { |
49 | friend class LLTextureFetchWorker; | 53 | friend class LLTextureFetchWorker; |
54 | friend class HTTPGetResponder; | ||
50 | 55 | ||
51 | public: | 56 | public: |
52 | LLTextureFetch(LLTextureCache* cache, bool threaded); | 57 | LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded); |
53 | ~LLTextureFetch(); | 58 | ~LLTextureFetch(); |
54 | 59 | ||
55 | /*virtual*/ S32 update(U32 max_time_ms); | 60 | /*virtual*/ S32 update(U32 max_time_ms); |
56 | 61 | ||
57 | bool createRequest(const LLUUID& id, const LLHost& host, F32 priority, | 62 | bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, |
58 | S32 w, S32 h, S32 c, S32 discard, bool needs_aux); | ||
59 | bool createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority, | ||
60 | S32 w, S32 h, S32 c, S32 discard, bool needs_aux); | 63 | S32 w, S32 h, S32 c, S32 discard, bool needs_aux); |
61 | void deleteRequest(const LLUUID& id, bool cancel); | 64 | void deleteRequest(const LLUUID& id, bool cancel); |
62 | bool getRequestFinished(const LLUUID& id, S32& discard_level, | 65 | bool getRequestFinished(const LLUUID& id, S32& discard_level, |
@@ -66,24 +69,38 @@ public: | |||
66 | bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); | 69 | bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); |
67 | bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); | 70 | bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); |
68 | 71 | ||
72 | void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; } | ||
73 | F32 getTextureBandwidth() { return mTextureBandwidth; } | ||
74 | |||
69 | // Debug | 75 | // Debug |
70 | S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, | 76 | S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, |
71 | U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p); | 77 | U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p); |
72 | void dump(); | 78 | void dump(); |
73 | S32 getNumRequests() { return mRequestMap.size(); } | 79 | S32 getNumRequests() { return mRequestMap.size(); } |
80 | S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); } | ||
74 | 81 | ||
75 | // Public for access by callbacks | 82 | // Public for access by callbacks |
76 | void lockQueue() { mQueueMutex.lock(); } | 83 | void lockQueue() { mQueueMutex.lock(); } |
77 | void unlockQueue() { mQueueMutex.unlock(); } | 84 | void unlockQueue() { mQueueMutex.unlock(); } |
78 | LLTextureFetchWorker* getWorker(const LLUUID& id); | 85 | LLTextureFetchWorker* getWorker(const LLUUID& id); |
86 | |||
87 | LLTextureInfo* getTextureInfo() { return &mTextureInfo; } | ||
79 | 88 | ||
80 | protected: | 89 | protected: |
81 | void addToNetworkQueue(LLTextureFetchWorker* worker); | 90 | void addToNetworkQueue(LLTextureFetchWorker* worker); |
82 | void removeFromNetworkQueue(LLTextureFetchWorker* worker); | 91 | void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); |
92 | void addToHTTPQueue(const LLUUID& id); | ||
93 | void removeFromHTTPQueue(const LLUUID& id); | ||
94 | S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); } | ||
83 | void removeRequest(LLTextureFetchWorker* worker, bool cancel); | 95 | void removeRequest(LLTextureFetchWorker* worker, bool cancel); |
96 | // Called from worker thread (during doWork) | ||
97 | void processCurlRequests(); | ||
84 | 98 | ||
85 | private: | 99 | private: |
86 | void sendRequestListToSimulators(); | 100 | void sendRequestListToSimulators(); |
101 | /*virtual*/ void startThread(void); | ||
102 | /*virtual*/ void endThread(void); | ||
103 | /*virtual*/ void threadedUpdate(void); | ||
87 | 104 | ||
88 | public: | 105 | public: |
89 | LLUUID mDebugID; | 106 | LLUUID mDebugID; |
@@ -94,8 +111,11 @@ public: | |||
94 | 111 | ||
95 | private: | 112 | private: |
96 | LLMutex mQueueMutex; | 113 | LLMutex mQueueMutex; |
114 | LLMutex mNetworkQueueMutex; | ||
97 | 115 | ||
98 | LLTextureCache* mTextureCache; | 116 | LLTextureCache* mTextureCache; |
117 | LLImageDecodeThread* mImageDecodeThread; | ||
118 | LLCurlRequest* mCurlGetRequest; | ||
99 | 119 | ||
100 | // Map of all requests by UUID | 120 | // Map of all requests by UUID |
101 | typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; | 121 | typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; |
@@ -104,10 +124,13 @@ private: | |||
104 | // Set of requests that require network data | 124 | // Set of requests that require network data |
105 | typedef std::set<LLUUID> queue_t; | 125 | typedef std::set<LLUUID> queue_t; |
106 | queue_t mNetworkQueue; | 126 | queue_t mNetworkQueue; |
127 | queue_t mHTTPTextureQueue; | ||
107 | typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t; | 128 | typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t; |
108 | cancel_queue_t mCancelQueue; | 129 | cancel_queue_t mCancelQueue; |
109 | 130 | F32 mTextureBandwidth; | |
110 | LLFrameTimer mNetworkTimer; | 131 | F32 mMaxBandwidth; |
132 | LLTextureInfo mTextureInfo; | ||
111 | }; | 133 | }; |
112 | 134 | ||
113 | #endif // LL_LLTEXTUREFETCH_H | 135 | #endif // LL_LLTEXTUREFETCH_H |
136 | |||
diff --git a/linden/indra/newview/lltextureinfo.cpp b/linden/indra/newview/lltextureinfo.cpp new file mode 100644 index 0000000..672a36a --- /dev/null +++ b/linden/indra/newview/lltextureinfo.cpp | |||
@@ -0,0 +1,290 @@ | |||
1 | /** | ||
2 | * @file lltextureinfo.cpp | ||
3 | * @brief Object which handles local texture info | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "llviewerprecompiledheaders.h" | ||
34 | |||
35 | #include "lltextureinfo.h" | ||
36 | #include "lltexturestats.h" | ||
37 | #include "llviewercontrol.h" | ||
38 | |||
39 | LLTextureInfo::LLTextureInfo() : | ||
40 | mLogTextureDownloadsToViewerLog(false), | ||
41 | mLogTextureDownloadsToSimulator(false), | ||
42 | mTotalBytes(0), | ||
43 | mTotalMilliseconds(0), | ||
44 | mTextureDownloadsStarted(0), | ||
45 | mTextureDownloadsCompleted(0), | ||
46 | mTextureDownloadProtocol("NONE"), | ||
47 | mTextureLogThreshold(100 * 1024), | ||
48 | mCurrentStatsBundleStartTime(0) | ||
49 | { | ||
50 | mTextures.clear(); | ||
51 | } | ||
52 | |||
53 | void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold) | ||
54 | { | ||
55 | mLogTextureDownloadsToViewerLog = writeToViewerLog; | ||
56 | mLogTextureDownloadsToSimulator = sendToSim; | ||
57 | mTextureLogThreshold = textureLogThreshold; | ||
58 | } | ||
59 | |||
60 | LLTextureInfo::~LLTextureInfo() | ||
61 | { | ||
62 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator; | ||
63 | for (iterator = mTextures.begin(); iterator != mTextures.end(); iterator++) | ||
64 | { | ||
65 | LLTextureInfoDetails *info = (*iterator).second; | ||
66 | delete info; | ||
67 | } | ||
68 | |||
69 | mTextures.clear(); | ||
70 | } | ||
71 | |||
72 | void LLTextureInfo::addRequest(const LLUUID& id) | ||
73 | { | ||
74 | LLTextureInfoDetails *info = new LLTextureInfoDetails(); | ||
75 | mTextures[id] = info; | ||
76 | } | ||
77 | |||
78 | U32 LLTextureInfo::getTextureInfoMapSize() | ||
79 | { | ||
80 | return mTextures.size(); | ||
81 | } | ||
82 | |||
83 | bool LLTextureInfo::has(const LLUUID& id) | ||
84 | { | ||
85 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
86 | if (iterator == mTextures.end()) | ||
87 | { | ||
88 | return false; | ||
89 | } | ||
90 | else | ||
91 | { | ||
92 | return true; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) | ||
97 | { | ||
98 | if (!has(id)) | ||
99 | { | ||
100 | addRequest(id); | ||
101 | } | ||
102 | mTextures[id]->mStartTime = startTime; | ||
103 | mTextureDownloadsStarted++; | ||
104 | } | ||
105 | |||
106 | void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size) | ||
107 | { | ||
108 | if (!has(id)) | ||
109 | { | ||
110 | addRequest(id); | ||
111 | } | ||
112 | mTextures[id]->mSize = size; | ||
113 | } | ||
114 | |||
115 | void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset) | ||
116 | { | ||
117 | if (!has(id)) | ||
118 | { | ||
119 | addRequest(id); | ||
120 | } | ||
121 | mTextures[id]->mOffset = offset; | ||
122 | } | ||
123 | |||
124 | void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type) | ||
125 | { | ||
126 | if (!has(id)) | ||
127 | { | ||
128 | addRequest(id); | ||
129 | } | ||
130 | mTextures[id]->mType = type; | ||
131 | } | ||
132 | |||
133 | void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime) | ||
134 | { | ||
135 | if (!has(id)) | ||
136 | { | ||
137 | addRequest(id); | ||
138 | } | ||
139 | mTextures[id]->mCompleteTime = completeTime; | ||
140 | |||
141 | std::string protocol = "NONE"; | ||
142 | switch(mTextures[id]->mType) | ||
143 | { | ||
144 | case LLTextureInfoDetails::REQUEST_TYPE_HTTP: | ||
145 | protocol = "HTTP"; | ||
146 | break; | ||
147 | |||
148 | case LLTextureInfoDetails::REQUEST_TYPE_UDP: | ||
149 | protocol = "UDP"; | ||
150 | break; | ||
151 | |||
152 | case LLTextureInfoDetails::REQUEST_TYPE_NONE: | ||
153 | default: | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | if (mLogTextureDownloadsToViewerLog) | ||
158 | { | ||
159 | llinfos << "texture=" << id | ||
160 | << " start=" << mTextures[id]->mStartTime | ||
161 | << " end=" << mTextures[id]->mCompleteTime | ||
162 | << " size=" << mTextures[id]->mSize | ||
163 | << " offset=" << mTextures[id]->mOffset | ||
164 | << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000 | ||
165 | << " protocol=" << protocol | ||
166 | << llendl; | ||
167 | } | ||
168 | |||
169 | if(mLogTextureDownloadsToSimulator) | ||
170 | { | ||
171 | S32 texture_stats_upload_threshold = mTextureLogThreshold; | ||
172 | mTotalBytes += mTextures[id]->mSize; | ||
173 | mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime; | ||
174 | mTextureDownloadsCompleted++; | ||
175 | mTextureDownloadProtocol = protocol; | ||
176 | if (mTotalBytes >= texture_stats_upload_threshold) | ||
177 | { | ||
178 | LLSD texture_data; | ||
179 | std::stringstream startTime; | ||
180 | startTime << mCurrentStatsBundleStartTime; | ||
181 | texture_data["start_time"] = startTime.str(); | ||
182 | std::stringstream endTime; | ||
183 | endTime << completeTime; | ||
184 | texture_data["end_time"] = endTime.str(); | ||
185 | texture_data["averages"] = getAverages(); | ||
186 | send_texture_stats_to_sim(texture_data); | ||
187 | resetTextureStatistics(); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | mTextures.erase(id); | ||
192 | } | ||
193 | |||
194 | LLSD LLTextureInfo::getAverages() | ||
195 | { | ||
196 | LLSD averagedTextureData; | ||
197 | S32 averageDownloadRate; | ||
198 | if(mTotalMilliseconds == 0) | ||
199 | { | ||
200 | averageDownloadRate = 0; | ||
201 | } | ||
202 | else | ||
203 | { | ||
204 | averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds; | ||
205 | } | ||
206 | |||
207 | averagedTextureData["bits_per_second"] = averageDownloadRate; | ||
208 | averagedTextureData["bytes_downloaded"] = mTotalBytes; | ||
209 | averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted; | ||
210 | averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted; | ||
211 | averagedTextureData["transport"] = mTextureDownloadProtocol; | ||
212 | |||
213 | return averagedTextureData; | ||
214 | } | ||
215 | |||
216 | void LLTextureInfo::resetTextureStatistics() | ||
217 | { | ||
218 | mTotalMilliseconds = 0; | ||
219 | mTotalBytes = 0; | ||
220 | mTextureDownloadsStarted = 0; | ||
221 | mTextureDownloadsCompleted = 0; | ||
222 | mTextureDownloadProtocol = "NONE"; | ||
223 | mCurrentStatsBundleStartTime = LLTimer::getTotalTime(); | ||
224 | } | ||
225 | |||
226 | U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) | ||
227 | { | ||
228 | if (!has(id)) | ||
229 | { | ||
230 | return 0; | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
235 | return (*iterator).second->mStartTime; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | U32 LLTextureInfo::getRequestSize(const LLUUID& id) | ||
240 | { | ||
241 | if (!has(id)) | ||
242 | { | ||
243 | return 0; | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
248 | return (*iterator).second->mSize; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | U32 LLTextureInfo::getRequestOffset(const LLUUID& id) | ||
253 | { | ||
254 | if (!has(id)) | ||
255 | { | ||
256 | return 0; | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
261 | return (*iterator).second->mOffset; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& id) | ||
266 | { | ||
267 | if (!has(id)) | ||
268 | { | ||
269 | return LLTextureInfoDetails::REQUEST_TYPE_NONE; | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
274 | return (*iterator).second->mType; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id) | ||
279 | { | ||
280 | if (!has(id)) | ||
281 | { | ||
282 | return 0; | ||
283 | } | ||
284 | else | ||
285 | { | ||
286 | std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); | ||
287 | return (*iterator).second->mCompleteTime; | ||
288 | } | ||
289 | } | ||
290 | |||
diff --git a/linden/indra/newview/lltextureinfo.h b/linden/indra/newview/lltextureinfo.h new file mode 100644 index 0000000..71b0ea4 --- /dev/null +++ b/linden/indra/newview/lltextureinfo.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /** | ||
2 | * @file lltextureinfo.h | ||
3 | * @brief Object for managing texture information. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLTEXTUREINFO_H | ||
34 | #define LL_LLTEXTUREINFO_H | ||
35 | |||
36 | #include "lluuid.h" | ||
37 | #include "lltextureinfodetails.h" | ||
38 | #include <map> | ||
39 | |||
40 | class LLTextureInfo | ||
41 | { | ||
42 | public: | ||
43 | LLTextureInfo(); | ||
44 | ~LLTextureInfo(); | ||
45 | |||
46 | void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold); | ||
47 | bool has(const LLUUID& id); | ||
48 | void setRequestStartTime(const LLUUID& id, U64 startTime); | ||
49 | void setRequestSize(const LLUUID& id, U32 size); | ||
50 | void setRequestOffset(const LLUUID& id, U32 offset); | ||
51 | void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type); | ||
52 | void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime); | ||
53 | U32 getRequestStartTime(const LLUUID& id); | ||
54 | U32 getRequestSize(const LLUUID& id); | ||
55 | U32 getRequestOffset(const LLUUID& id); | ||
56 | LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id); | ||
57 | U32 getRequestCompleteTime(const LLUUID& id); | ||
58 | void resetTextureStatistics(); | ||
59 | U32 getTextureInfoMapSize(); | ||
60 | LLSD getAverages(); | ||
61 | |||
62 | private: | ||
63 | void addRequest(const LLUUID& id); | ||
64 | |||
65 | std::map<LLUUID, LLTextureInfoDetails *> mTextures; | ||
66 | |||
67 | LLSD mAverages; | ||
68 | |||
69 | bool mLogTextureDownloadsToViewerLog; | ||
70 | bool mLogTextureDownloadsToSimulator; | ||
71 | S32 mTotalBytes; | ||
72 | S32 mTotalMilliseconds; | ||
73 | S32 mTextureDownloadsStarted; | ||
74 | S32 mTextureDownloadsCompleted; | ||
75 | std::string mTextureDownloadProtocol; | ||
76 | U32 mTextureLogThreshold; // in bytes | ||
77 | U64 mCurrentStatsBundleStartTime; | ||
78 | }; | ||
79 | |||
80 | #endif // LL_LLTEXTUREINFO_H | ||
diff --git a/linden/indra/newview/lltextureinfodetails.cpp b/linden/indra/newview/lltextureinfodetails.cpp new file mode 100644 index 0000000..f6ef47a --- /dev/null +++ b/linden/indra/newview/lltextureinfodetails.cpp | |||
@@ -0,0 +1,40 @@ | |||
1 | /** | ||
2 | * @file lltextureinfodetails.cpp | ||
3 | * @brief Object which handles details of any individual texture | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "llviewerprecompiledheaders.h" | ||
34 | |||
35 | #include "lltextureinfodetails.h" | ||
36 | |||
37 | LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0) | ||
38 | { | ||
39 | } | ||
40 | |||
diff --git a/linden/indra/newview/lltextureinfodetails.h b/linden/indra/newview/lltextureinfodetails.h new file mode 100644 index 0000000..091fa01 --- /dev/null +++ b/linden/indra/newview/lltextureinfodetails.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /** | ||
2 | * @file lltextureinfo.h | ||
3 | * @brief Object for managing texture information. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLTEXTUREINFODETAILS_H | ||
34 | #define LL_LLTEXTUREINFODETAILS_H | ||
35 | |||
36 | #include "lluuid.h" | ||
37 | |||
38 | class LLTextureInfoDetails | ||
39 | { | ||
40 | public: | ||
41 | enum LLRequestType | ||
42 | { | ||
43 | REQUEST_TYPE_NONE, | ||
44 | REQUEST_TYPE_HTTP, | ||
45 | REQUEST_TYPE_UDP | ||
46 | }; | ||
47 | |||
48 | U32 mStartTime; | ||
49 | U32 mCompleteTime; | ||
50 | U32 mOffset; | ||
51 | U32 mSize; | ||
52 | LLRequestType mType; | ||
53 | |||
54 | LLTextureInfoDetails(); | ||
55 | }; | ||
56 | |||
57 | #endif // LL_LLTEXTUREINFODETAILS_H | ||
58 | |||
diff --git a/linden/indra/newview/lltexturestats.cpp b/linden/indra/newview/lltexturestats.cpp new file mode 100644 index 0000000..c91bfd4 --- /dev/null +++ b/linden/indra/newview/lltexturestats.cpp | |||
@@ -0,0 +1,61 @@ | |||
1 | /** | ||
2 | * @file lltexturerstats.cpp | ||
3 | * @brief texture stats helper methods | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "llviewerprecompiledheaders.h" | ||
34 | |||
35 | #include "pipeline.h" | ||
36 | #include "llagent.h" | ||
37 | #include "lltexturefetch.h" | ||
38 | #include "lltexturestats.h" | ||
39 | #include "lltexturestatsuploader.h" | ||
40 | #include "llviewerregion.h" | ||
41 | |||
42 | void send_texture_stats_to_sim(const LLSD &texture_stats) | ||
43 | { | ||
44 | LLSD texture_stats_report; | ||
45 | // Only send stats if the agent is connected to a region. | ||
46 | if (!gAgent.getRegion() || gNoRender) | ||
47 | { | ||
48 | return; | ||
49 | } | ||
50 | |||
51 | LLUUID agent_id = gAgent.getID(); | ||
52 | texture_stats_report["agent_id"] = agent_id; | ||
53 | texture_stats_report["region_id"] = gAgent.getRegion()->getRegionID(); | ||
54 | texture_stats_report["stats_data"] = texture_stats; | ||
55 | |||
56 | std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats"); | ||
57 | LLTextureStatsUploader tsu; | ||
58 | llinfos << "uploading texture stats data to simulator" << llendl; | ||
59 | tsu.uploadStatsToSimulator(texture_cap_url, texture_stats); | ||
60 | } | ||
61 | |||
diff --git a/linden/indra/newview/lltexturestats.h b/linden/indra/newview/lltexturestats.h new file mode 100644 index 0000000..2deb377 --- /dev/null +++ b/linden/indra/newview/lltexturestats.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /** | ||
2 | * @file lltexturestats.h | ||
3 | * @brief texture stats utilities | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2009&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLTEXTURESTATS_H | ||
34 | #define LL_LLTEXTURESTATS_H | ||
35 | |||
36 | #include "llappviewer.h" | ||
37 | |||
38 | // utility functions to capture data on texture download speeds and send to simulator periodically | ||
39 | void send_texture_stats_to_sim(const LLSD &texture_stats); | ||
40 | |||
41 | #endif // LL_LLTEXTURESTATS_H | ||
diff --git a/linden/indra/newview/lltexturestatsuploader.cpp b/linden/indra/newview/lltexturestatsuploader.cpp new file mode 100644 index 0000000..e0358e1 --- /dev/null +++ b/linden/indra/newview/lltexturestatsuploader.cpp | |||
@@ -0,0 +1,59 @@ | |||
1 | /** | ||
2 | * @file lltexturerstats.cpp | ||
3 | * @brief texture stats upload class | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "llviewerprecompiledheaders.h" | ||
34 | |||
35 | #include "lltexturestatsuploader.h" | ||
36 | |||
37 | LLTextureStatsUploader::LLTextureStatsUploader() | ||
38 | { | ||
39 | } | ||
40 | |||
41 | LLTextureStatsUploader::~LLTextureStatsUploader() | ||
42 | { | ||
43 | } | ||
44 | |||
45 | void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats) | ||
46 | { | ||
47 | if ( texture_cap_url != "" ) | ||
48 | { | ||
49 | LLHTTPClient::post(texture_cap_url, texture_stats, NULL); | ||
50 | } | ||
51 | else | ||
52 | { | ||
53 | llinfos << "Not sending texture stats: " | ||
54 | << texture_stats | ||
55 | << " as there is no cap url." | ||
56 | << llendl; | ||
57 | } | ||
58 | } | ||
59 | |||
diff --git a/linden/indra/newview/lltexturestatsuploader.h b/linden/indra/newview/lltexturestatsuploader.h new file mode 100644 index 0000000..f6cc8be --- /dev/null +++ b/linden/indra/newview/lltexturestatsuploader.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /** | ||
2 | * @file lltexturestatsuploader.h | ||
3 | * @brief Class to send the texture stats to the simulatore | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2009&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLTEXTURESTATSUPLOADER_H | ||
34 | #define LL_LLTEXTURESTATSUPLOADER_H | ||
35 | |||
36 | #include "llappviewer.h" | ||
37 | |||
38 | // utility functions to capture data on texture download speeds and send to simulator periodically | ||
39 | |||
40 | class LLTextureStatsUploader | ||
41 | { | ||
42 | public: | ||
43 | LLTextureStatsUploader(); | ||
44 | ~LLTextureStatsUploader(); | ||
45 | void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats); | ||
46 | }; | ||
47 | |||
48 | #endif // LL_LLTEXTURESTATSUPLOADER_H | ||
diff --git a/linden/indra/newview/lltextureview.cpp b/linden/indra/newview/lltextureview.cpp index d356bf9..b6159da 100644 --- a/linden/indra/newview/lltextureview.cpp +++ b/linden/indra/newview/lltextureview.cpp | |||
@@ -43,16 +43,17 @@ | |||
43 | #include "llimageworker.h" | 43 | #include "llimageworker.h" |
44 | #include "llrender.h" | 44 | #include "llrender.h" |
45 | 45 | ||
46 | #include "llappviewer.h" | ||
46 | #include "llhoverview.h" | 47 | #include "llhoverview.h" |
47 | #include "llselectmgr.h" | 48 | #include "llselectmgr.h" |
48 | #include "lltexlayer.h" | 49 | #include "lltexlayer.h" |
49 | #include "lltexturecache.h" | 50 | #include "lltexturecache.h" |
50 | #include "lltexturefetch.h" | 51 | #include "lltexturefetch.h" |
52 | #include "llviewercontrol.h" | ||
51 | #include "llviewerobject.h" | 53 | #include "llviewerobject.h" |
52 | #include "llviewerimage.h" | 54 | #include "llviewerimage.h" |
53 | #include "llviewerimagelist.h" | 55 | #include "llviewerimagelist.h" |
54 | #include "llappviewer.h" | 56 | #include "llvovolume.h" |
55 | |||
56 | extern F32 texmem_lower_bound_scale; | 57 | extern F32 texmem_lower_bound_scale; |
57 | 58 | ||
58 | LLTextureView *gTextureView = NULL; | 59 | LLTextureView *gTextureView = NULL; |
@@ -466,9 +467,9 @@ void LLGLTexMemBar::draw() | |||
466 | LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, | 467 | LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, |
467 | LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), | 468 | LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), |
468 | LLLFSThread::sLocal->getPending(), | 469 | LLLFSThread::sLocal->getPending(), |
469 | LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(), | 470 | LLAppViewer::getImageDecodeThread()->getPending(), |
470 | LLImageRaw::sRawImageCount, LLViewerImage::sRawCount, LLViewerImage::sAuxCount, | 471 | LLImageRaw::sRawImageCount, |
471 | gImageList.mCallbackList.size()); | 472 | LLAppViewer::getTextureFetch()->getNumHTTPRequests()); |
472 | 473 | ||
473 | LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*2, | 474 | LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*2, |
474 | text_color, LLFontGL::LEFT, LLFontGL::TOP); | 475 | text_color, LLFontGL::LEFT, LLFontGL::TOP); |
diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp index 72d1494..dade65f 100644 --- a/linden/indra/newview/llviewercamera.cpp +++ b/linden/indra/newview/llviewercamera.cpp | |||
@@ -102,10 +102,13 @@ LLViewerCamera::LLViewerCamera() : LLCamera() | |||
102 | { | 102 | { |
103 | calcProjection(getFar()); | 103 | calcProjection(getFar()); |
104 | mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; | 104 | mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; |
105 | mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); | ||
105 | mPixelMeterRatio = 0.f; | 106 | mPixelMeterRatio = 0.f; |
106 | mScreenPixelArea = 0; | 107 | mScreenPixelArea = 0; |
107 | mZoomFactor = 1.f; | 108 | mZoomFactor = 1.f; |
108 | mZoomSubregion = 1; | 109 | mZoomSubregion = 1; |
110 | mAverageSpeed = 0.f; | ||
111 | mAverageAngularSpeed = 0.f; | ||
109 | } | 112 | } |
110 | 113 | ||
111 | void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, | 114 | void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, |
@@ -144,15 +147,22 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, | |||
144 | 147 | ||
145 | setOriginAndLookAt(origin, up_direction, point_of_interest); | 148 | setOriginAndLookAt(origin, up_direction, point_of_interest); |
146 | 149 | ||
147 | F32 dpos = (center - last_position).magVec(); | 150 | mVelocityDir = center - last_position ; |
151 | F32 dpos = mVelocityDir.normVec() ; | ||
148 | LLQuaternion rotation; | 152 | LLQuaternion rotation; |
149 | rotation.shortestArc(last_axis, getAtAxis()); | 153 | rotation.shortestArc(last_axis, getAtAxis()); |
150 | 154 | ||
151 | F32 x, y, z; | 155 | F32 x, y, z; |
152 | F32 drot; | 156 | F32 drot; |
153 | rotation.getAngleAxis(&drot, &x, &y, &z); | 157 | rotation.getAngleAxis(&drot, &x, &y, &z); |
158 | |||
154 | mVelocityStat.addValue(dpos); | 159 | mVelocityStat.addValue(dpos); |
155 | mAngularVelocityStat.addValue(drot); | 160 | mAngularVelocityStat.addValue(drot); |
161 | |||
162 | mAverageSpeed = mVelocityStat.getMeanPerSec() ; | ||
163 | mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ; | ||
164 | mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect())); | ||
165 | |||
156 | // update pixel meter ratio using default fov, not modified one | 166 | // update pixel meter ratio using default fov, not modified one |
157 | mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); | 167 | mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); |
158 | // update screen pixel area | 168 | // update screen pixel area |
@@ -759,8 +769,8 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) | |||
759 | 769 | ||
760 | BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; | 770 | BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; |
761 | 771 | ||
762 | if ( !in_frustum && all_verts || | 772 | if (( !in_frustum && all_verts) || |
763 | in_frustum && !all_verts) | 773 | (in_frustum && !all_verts)) |
764 | { | 774 | { |
765 | return !all_verts; | 775 | return !all_verts; |
766 | } | 776 | } |
@@ -797,9 +807,11 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) | |||
797 | LLCamera::setView(vertical_fov_rads); // call base implementation | 807 | LLCamera::setView(vertical_fov_rads); // call base implementation |
798 | } | 808 | } |
799 | 809 | ||
800 | void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) { | 810 | void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) |
811 | { | ||
801 | vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); | 812 | vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); |
802 | setView(vertical_fov_rads); | 813 | setView(vertical_fov_rads); |
803 | mCameraFOVDefault = vertical_fov_rads; | 814 | mCameraFOVDefault = vertical_fov_rads; |
815 | mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); | ||
804 | } | 816 | } |
805 | 817 | ||
diff --git a/linden/indra/newview/llviewercamera.h b/linden/indra/newview/llviewercamera.h index 6a0c42b..d25d063 100644 --- a/linden/indra/newview/llviewercamera.h +++ b/linden/indra/newview/llviewercamera.h | |||
@@ -71,17 +71,20 @@ public: | |||
71 | BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const; | 71 | BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const; |
72 | BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const; | 72 | BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const; |
73 | 73 | ||
74 | 74 | const LLVector3* getVelocityDir() const {return &mVelocityDir;} | |
75 | LLStat *getVelocityStat() { return &mVelocityStat; } | 75 | LLStat *getVelocityStat() { return &mVelocityStat; } |
76 | LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; } | 76 | LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; } |
77 | F32 getCosHalfFov() {return mCosHalfCameraFOV;} | ||
78 | F32 getAverageSpeed() {return mAverageSpeed ;} | ||
79 | F32 getAverageAngularSpeed() {return mAverageAngularSpeed;} | ||
77 | 80 | ||
78 | void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right); | 81 | void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right); |
79 | LLVector3 roundToPixel(const LLVector3 &pos_agent); | 82 | LLVector3 roundToPixel(const LLVector3 &pos_agent); |
80 | 83 | ||
81 | // Sets the current matrix | 84 | // Sets the current matrix |
82 | /* virtual */ void setView(F32 vertical_fov_rads); | 85 | /* virtual */ void setView(F32 vertical_fov_rads); |
83 | // Sets the current matrix AND remembers result as default view | 86 | |
84 | void setDefaultFOV(F32 vertical_fov_rads); | 87 | void setDefaultFOV(F32 fov) ; |
85 | F32 getDefaultFOV() { return mCameraFOVDefault; } | 88 | F32 getDefaultFOV() { return mCameraFOVDefault; } |
86 | 89 | ||
87 | BOOL cameraUnderWater() const; | 90 | BOOL cameraUnderWater() const; |
@@ -100,9 +103,14 @@ protected: | |||
100 | 103 | ||
101 | LLStat mVelocityStat; | 104 | LLStat mVelocityStat; |
102 | LLStat mAngularVelocityStat; | 105 | LLStat mAngularVelocityStat; |
106 | LLVector3 mVelocityDir ; | ||
107 | F32 mAverageSpeed ; | ||
108 | F32 mAverageAngularSpeed ; | ||
109 | |||
103 | mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix | 110 | mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix |
104 | mutable LLMatrix4 mModelviewMatrix; | 111 | mutable LLMatrix4 mModelviewMatrix; |
105 | F32 mCameraFOVDefault; | 112 | F32 mCameraFOVDefault; |
113 | F32 mCosHalfCameraFOV; | ||
106 | LLVector3 mLastPointOfInterest; | 114 | LLVector3 mLastPointOfInterest; |
107 | F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance. | 115 | F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance. |
108 | S32 mScreenPixelArea; // Pixel area of entire window | 116 | S32 mScreenPixelArea; // Pixel area of entire window |
diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp index 08e9d45..6d62db5 100644 --- a/linden/indra/newview/llviewercontrol.cpp +++ b/linden/indra/newview/llviewercontrol.cpp | |||
@@ -91,6 +91,8 @@ std::string gCurrentVersion; | |||
91 | extern BOOL gResizeScreenTexture; | 91 | extern BOOL gResizeScreenTexture; |
92 | extern BOOL gDebugGL; | 92 | extern BOOL gDebugGL; |
93 | 93 | ||
94 | extern BOOL gAuditTexture; | ||
95 | |||
94 | //////////////////////////////////////////////////////////////////////////// | 96 | //////////////////////////////////////////////////////////////////////////// |
95 | // Listeners | 97 | // Listeners |
96 | 98 | ||
@@ -374,6 +376,12 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) | |||
374 | return true; | 376 | return true; |
375 | } | 377 | } |
376 | 378 | ||
379 | static bool handleAuditTextureChanged(const LLSD& newvalue) | ||
380 | { | ||
381 | gAuditTexture = newvalue.asBoolean(); | ||
382 | return true; | ||
383 | } | ||
384 | |||
377 | static bool handleRenderDebugGLChanged(const LLSD& newvalue) | 385 | static bool handleRenderDebugGLChanged(const LLSD& newvalue) |
378 | { | 386 | { |
379 | gDebugGL = newvalue.asBoolean(); | 387 | gDebugGL = newvalue.asBoolean(); |
@@ -527,6 +535,7 @@ void settings_setup_listeners() | |||
527 | gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); | 535 | gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); |
528 | gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); | 536 | gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); |
529 | gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1)); | 537 | gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1)); |
538 | gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); | ||
530 | gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); | 539 | gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); |
531 | gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); | 540 | gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); |
532 | gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); | 541 | gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); |
diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp index 272fcb5..3a14bf0 100644 --- a/linden/indra/newview/llviewerimage.cpp +++ b/linden/indra/newview/llviewerimage.cpp | |||
@@ -59,6 +59,8 @@ | |||
59 | #include "llviewercontrol.h" | 59 | #include "llviewercontrol.h" |
60 | #include "pipeline.h" | 60 | #include "pipeline.h" |
61 | #include "llappviewer.h" | 61 | #include "llappviewer.h" |
62 | #include "llface.h" | ||
63 | #include "llviewercamera.h" | ||
62 | /////////////////////////////////////////////////////////////////////////////// | 64 | /////////////////////////////////////////////////////////////////////////////// |
63 | 65 | ||
64 | // statics | 66 | // statics |
@@ -72,6 +74,7 @@ S32 LLViewerImage::sImageCount = 0; | |||
72 | S32 LLViewerImage::sRawCount = 0; | 74 | S32 LLViewerImage::sRawCount = 0; |
73 | S32 LLViewerImage::sAuxCount = 0; | 75 | S32 LLViewerImage::sAuxCount = 0; |
74 | LLTimer LLViewerImage::sEvaluationTimer; | 76 | LLTimer LLViewerImage::sEvaluationTimer; |
77 | S8 LLViewerImage::sCameraMovingDiscardBias = 0 ; | ||
75 | F32 LLViewerImage::sDesiredDiscardBias = 0.f; | 78 | F32 LLViewerImage::sDesiredDiscardBias = 0.f; |
76 | static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by | 79 | static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by |
77 | static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by | 80 | static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by |
@@ -83,16 +86,26 @@ S32 LLViewerImage::sMaxTotalTextureMemInMegaBytes = 0; | |||
83 | S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ; | 86 | S32 LLViewerImage::sMaxDesiredTextureMemInBytes = 0 ; |
84 | BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE; | 87 | BOOL LLViewerImage::sDontLoadVolumeTextures = FALSE; |
85 | 88 | ||
89 | S32 LLViewerImage::sMaxSculptRez = 128 ; //max sculpt image size | ||
90 | const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; | ||
91 | const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerImage::sMaxSculptRez * LLViewerImage::sMaxSculptRez ; | ||
92 | const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ; | ||
93 | S32 LLViewerImage::sMinLargeImageSize = 65536 ; //256 * 256. | ||
94 | S32 LLViewerImage::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; | ||
95 | BOOL LLViewerImage::sFreezeImageScalingDown = FALSE ; | ||
96 | //debug use | ||
97 | S32 LLViewerImage::sLLViewerImageCount = 0 ; | ||
98 | |||
86 | // static | 99 | // static |
87 | void LLViewerImage::initClass() | 100 | void LLViewerImage::initClass() |
88 | { | 101 | { |
89 | sNullImagep = new LLImageGL(1,1,3,TRUE); | 102 | sNullImagep = new LLImageGL(1,1,3,TRUE); |
90 | LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); | 103 | LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); |
91 | raw->clear(0x77, 0x77, 0x77, 0xFF); | 104 | raw->clear(0x77, 0x77, 0x77, 0xFF); |
92 | sNullImagep->createGLTexture(0, raw); | 105 | sNullImagep->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
93 | 106 | ||
94 | #if 1 | 107 | #if 1 |
95 | LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT, TRUE); | 108 | LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT); |
96 | sDefaultImagep = imagep; | 109 | sDefaultImagep = imagep; |
97 | const S32 dim = 128; | 110 | const S32 dim = 128; |
98 | LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); | 111 | LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); |
@@ -118,7 +131,7 @@ void LLViewerImage::initClass() | |||
118 | } | 131 | } |
119 | } | 132 | } |
120 | } | 133 | } |
121 | imagep->createGLTexture(0, image_raw); | 134 | imagep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
122 | image_raw = NULL; | 135 | image_raw = NULL; |
123 | gImageList.addImage(imagep); | 136 | gImageList.addImage(imagep); |
124 | imagep->dontDiscard(); | 137 | imagep->dontDiscard(); |
@@ -128,17 +141,48 @@ void LLViewerImage::initClass() | |||
128 | sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); | 141 | sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); |
129 | sSmokeImagep->setNoDelete() ; | 142 | sSmokeImagep->setNoDelete() ; |
130 | 143 | ||
144 | if(gAuditTexture) | ||
145 | { | ||
146 | sDefaultTexturep = new LLImageGL() ; | ||
147 | image_raw = new LLImageRaw(dim,dim,3); | ||
148 | data = image_raw->getData(); | ||
149 | for (S32 i = 0; i<dim; i++) | ||
150 | { | ||
151 | for (S32 j = 0; j<dim; j++) | ||
152 | { | ||
153 | const S32 border = 2; | ||
154 | if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) | ||
155 | { | ||
156 | *data++ = 0xff; | ||
157 | *data++ = 0xff; | ||
158 | *data++ = 0xff; | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | *data++ = 0xff; | ||
163 | *data++ = 0xff; | ||
164 | *data++ = 0x00; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | sDefaultTexturep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); | ||
169 | image_raw = NULL; | ||
170 | sDefaultTexturep->dontDiscard(); | ||
171 | } | ||
131 | } | 172 | } |
132 | 173 | ||
133 | // static | 174 | // static |
134 | void LLViewerImage::cleanupClass() | 175 | void LLViewerImage::cleanupClass() |
135 | { | 176 | { |
136 | stop_glerror(); | 177 | stop_glerror(); |
178 | LLImageGL::cleanupClass() ; | ||
179 | |||
137 | sNullImagep = NULL; | 180 | sNullImagep = NULL; |
138 | sDefaultImagep = NULL; | 181 | sDefaultImagep = NULL; |
139 | sSmokeImagep = NULL; | 182 | sSmokeImagep = NULL; |
140 | sMissingAssetImagep = NULL; | 183 | sMissingAssetImagep = NULL; |
141 | sWhiteImagep = NULL; | 184 | sWhiteImagep = NULL; |
185 | sDefaultTexturep = NULL ; | ||
142 | } | 186 | } |
143 | 187 | ||
144 | // tuning params | 188 | // tuning params |
@@ -186,6 +230,13 @@ void LLViewerImage::updateClass(const F32 velocity, const F32 angular_velocity) | |||
186 | } | 230 | } |
187 | } | 231 | } |
188 | sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); | 232 | sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); |
233 | |||
234 | F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; | ||
235 | F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); | ||
236 | sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; | ||
237 | |||
238 | LLViewerImage::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && | ||
239 | (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; | ||
189 | } | 240 | } |
190 | 241 | ||
191 | // static | 242 | // static |
@@ -198,18 +249,19 @@ LLViewerImage* LLViewerImage::getImage(const LLUUID& image_id) | |||
198 | 249 | ||
199 | const U32 LLViewerImage::sCurrentFileVersion = 1; | 250 | const U32 LLViewerImage::sCurrentFileVersion = 1; |
200 | 251 | ||
201 | LLViewerImage::LLViewerImage(const LLUUID& id, BOOL usemipmaps) | 252 | LLViewerImage::LLViewerImage(const LLUUID& id, const LLHost& host, BOOL usemipmaps) |
202 | : LLImageGL(usemipmaps), | 253 | : LLImageGL(usemipmaps), |
203 | mID(id) | 254 | mID(id), |
255 | mTargetHost(host) | ||
204 | { | 256 | { |
205 | init(true); | 257 | init(true); |
206 | sImageCount++; | 258 | sImageCount++; |
207 | } | 259 | } |
208 | 260 | ||
209 | LLViewerImage::LLViewerImage(const std::string& filename, const LLUUID& id, BOOL usemipmaps) | 261 | LLViewerImage::LLViewerImage(const std::string& url, const LLUUID& id, BOOL usemipmaps) |
210 | : LLImageGL(usemipmaps), | 262 | : LLImageGL(usemipmaps), |
211 | mID(id), | 263 | mID(id), |
212 | mLocalFileName(filename) | 264 | mUrl(url) |
213 | { | 265 | { |
214 | init(true); | 266 | init(true); |
215 | sImageCount++; | 267 | sImageCount++; |
@@ -265,7 +317,7 @@ void LLViewerImage::init(bool firstinit) | |||
265 | } | 317 | } |
266 | mIsMediaTexture = FALSE; | 318 | mIsMediaTexture = FALSE; |
267 | 319 | ||
268 | mBoostLevel = LLViewerImage::BOOST_NONE; | 320 | mBoostLevel = LLViewerImageBoostLevel::BOOST_NONE; |
269 | 321 | ||
270 | // Only set mIsMissingAsset true when we know for certain that the database | 322 | // Only set mIsMissingAsset true when we know for certain that the database |
271 | // does not contain this image. | 323 | // does not contain this image. |
@@ -277,8 +329,6 @@ void LLViewerImage::init(bool firstinit) | |||
277 | mRawDiscardLevel = INVALID_DISCARD_LEVEL; | 329 | mRawDiscardLevel = INVALID_DISCARD_LEVEL; |
278 | mMinDiscardLevel = 0; | 330 | mMinDiscardLevel = 0; |
279 | 331 | ||
280 | mTargetHost = LLHost::invalid; | ||
281 | |||
282 | mHasFetcher = FALSE; | 332 | mHasFetcher = FALSE; |
283 | mIsFetching = FALSE; | 333 | mIsFetching = FALSE; |
284 | mFetchState = 0; | 334 | mFetchState = 0; |
@@ -287,6 +337,15 @@ void LLViewerImage::init(bool firstinit) | |||
287 | mFetchDeltaTime = 999999.f; | 337 | mFetchDeltaTime = 999999.f; |
288 | mDecodeFrame = 0; | 338 | mDecodeFrame = 0; |
289 | mVisibleFrame = 0; | 339 | mVisibleFrame = 0; |
340 | mForSculpt = FALSE ; | ||
341 | mCachedRawImage = NULL ; | ||
342 | mCachedRawDiscardLevel = -1 ; | ||
343 | mCachedRawImageReady = FALSE ; | ||
344 | mNeedsResetMaxVirtualSize = FALSE ; | ||
345 | |||
346 | mForceToSaveRawImage = FALSE ; | ||
347 | mSavedRawDiscardLevel = -1 ; | ||
348 | mDesiredSavedRawDiscardLevel = -1 ; | ||
290 | } | 349 | } |
291 | 350 | ||
292 | // virtual | 351 | // virtual |
@@ -322,6 +381,7 @@ LLViewerImage::~LLViewerImage() | |||
322 | 381 | ||
323 | void LLViewerImage::cleanup() | 382 | void LLViewerImage::cleanup() |
324 | { | 383 | { |
384 | mFaceList.clear() ; | ||
325 | for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); | 385 | for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); |
326 | iter != mLoadedCallbackList.end(); ) | 386 | iter != mLoadedCallbackList.end(); ) |
327 | { | 387 | { |
@@ -336,7 +396,9 @@ void LLViewerImage::cleanup() | |||
336 | 396 | ||
337 | // Clean up image data | 397 | // Clean up image data |
338 | destroyRawImage(); | 398 | destroyRawImage(); |
339 | 399 | mCachedRawImage = NULL ; | |
400 | mCachedRawDiscardLevel = -1 ; | ||
401 | mCachedRawImageReady = FALSE ; | ||
340 | // LLImageGL::cleanup will get called more than once when this is used in the destructor. | 402 | // LLImageGL::cleanup will get called more than once when this is used in the destructor. |
341 | LLImageGL::cleanup(); | 403 | LLImageGL::cleanup(); |
342 | } | 404 | } |
@@ -365,6 +427,63 @@ void LLViewerImage::destroyTexture() | |||
365 | destroyGLTexture() ; | 427 | destroyGLTexture() ; |
366 | } | 428 | } |
367 | 429 | ||
430 | void LLViewerImage::addToCreateTexture() | ||
431 | { | ||
432 | if(isForSculptOnly()) | ||
433 | { | ||
434 | //just update some variables, not to create a real GL texture. | ||
435 | createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; | ||
436 | mNeedsCreateTexture = FALSE ; | ||
437 | destroyRawImage(); | ||
438 | } | ||
439 | else | ||
440 | { | ||
441 | #if 1 | ||
442 | // | ||
443 | //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, | ||
444 | //so do not scale down the over qualified image. | ||
445 | //Note: scaling down image is expensensive. Do it only when very necessary. | ||
446 | // | ||
447 | if(mRequestedDiscardLevel <= mDesiredDiscardLevel) | ||
448 | { | ||
449 | S32 w = mFullWidth >> mRawDiscardLevel; | ||
450 | S32 h = mFullHeight >> mRawDiscardLevel; | ||
451 | |||
452 | //if big image, do not load extra data | ||
453 | //scale it down to size >= LLViewerImage::sMinLargeImageSize | ||
454 | if(w * h > LLViewerImage::sMinLargeImageSize) | ||
455 | { | ||
456 | S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ; | ||
457 | |||
458 | if(d_level > 0) | ||
459 | { | ||
460 | S32 i = 0 ; | ||
461 | while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerImage::sMinLargeImageSize)) | ||
462 | { | ||
463 | i++; | ||
464 | d_level--; | ||
465 | } | ||
466 | if(i > 0) | ||
467 | { | ||
468 | mRawDiscardLevel += i ; | ||
469 | if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) | ||
470 | { | ||
471 | mNeedsCreateTexture = FALSE ; | ||
472 | destroyRawImage(); | ||
473 | return ; | ||
474 | } | ||
475 | mRawImage->scale(w >> i, h >> i) ; | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | #endif | ||
481 | mNeedsCreateTexture = TRUE; | ||
482 | gImageList.mCreateTextureList.insert(this); | ||
483 | } | ||
484 | return ; | ||
485 | } | ||
486 | |||
368 | // ONLY called from LLViewerImageList | 487 | // ONLY called from LLViewerImageList |
369 | BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) | 488 | BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) |
370 | { | 489 | { |
@@ -386,7 +505,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) | |||
386 | if (!gNoRender) | 505 | if (!gNoRender) |
387 | { | 506 | { |
388 | // store original size only for locally-sourced images | 507 | // store original size only for locally-sourced images |
389 | if (!mLocalFileName.empty()) | 508 | if (mUrl.compare(0, 7, "file://") == 0) |
390 | { | 509 | { |
391 | mOrigWidth = mRawImage->getWidth(); | 510 | mOrigWidth = mRawImage->getWidth(); |
392 | mOrigHeight = mRawImage->getHeight(); | 511 | mOrigHeight = mRawImage->getHeight(); |
@@ -457,29 +576,54 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) | |||
457 | 576 | ||
458 | //============================================================================ | 577 | //============================================================================ |
459 | 578 | ||
460 | void LLViewerImage::addTextureStats(F32 virtual_size) const // = 1.0 | 579 | void LLViewerImage::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const |
461 | { | 580 | { |
462 | if (virtual_size > mMaxVirtualSize) | 581 | if(needs_gltexture) |
463 | { | 582 | { |
464 | mMaxVirtualSize = virtual_size; | 583 | mNeedsGLTexture = TRUE ; |
465 | } | 584 | } |
466 | } | ||
467 | 585 | ||
468 | void LLViewerImage::resetTextureStats(BOOL zero) | 586 | if(mNeedsResetMaxVirtualSize) |
469 | { | ||
470 | if (zero) | ||
471 | { | 587 | { |
472 | mMaxVirtualSize = 0.0f; | 588 | //flag to reset the values because the old values are used. |
589 | mNeedsResetMaxVirtualSize = FALSE ; | ||
590 | mMaxVirtualSize = virtual_size; | ||
591 | mAdditionalDecodePriority = 0.f ; | ||
592 | mNeedsGLTexture = needs_gltexture ; | ||
473 | } | 593 | } |
474 | else | 594 | else if (virtual_size > mMaxVirtualSize) |
475 | { | 595 | { |
476 | mMaxVirtualSize -= mMaxVirtualSize * .10f; // decay by 5%/update | 596 | mMaxVirtualSize = virtual_size; |
477 | } | 597 | } |
598 | } | ||
599 | |||
600 | void LLViewerImage::resetTextureStats() | ||
601 | { | ||
602 | mMaxVirtualSize = 0.0f; | ||
603 | mAdditionalDecodePriority = 0.f ; | ||
604 | mNeedsResetMaxVirtualSize = FALSE ; | ||
605 | } | ||
606 | |||
607 | BOOL LLViewerImage::isUpdateFrozen() | ||
608 | { | ||
609 | return LLViewerImage::sFreezeImageScalingDown && !getDiscardLevel() ; | ||
610 | } | ||
611 | |||
612 | BOOL LLViewerImage::isLargeImage() | ||
613 | { | ||
614 | return mTexelsPerImage > LLViewerImage::sMinLargeImageSize ; | ||
478 | } | 615 | } |
479 | 616 | ||
480 | // This is gauranteed to get called periodically for every texture | 617 | // This is gauranteed to get called periodically for every texture |
481 | void LLViewerImage::processTextureStats() | 618 | void LLViewerImage::processTextureStats() |
482 | { | 619 | { |
620 | //no need to update if the texture reaches its highest res and the memory is sufficient. | ||
621 | //if(isUpdateFrozen()) | ||
622 | //{ | ||
623 | // return ; | ||
624 | //} | ||
625 | |||
626 | updateVirtualSize() ; | ||
483 | // Generate the request priority and render priority | 627 | // Generate the request priority and render priority |
484 | if (mDontDiscard || !getUseMipMaps()) | 628 | if (mDontDiscard || !getUseMipMaps()) |
485 | { | 629 | { |
@@ -487,7 +631,7 @@ void LLViewerImage::processTextureStats() | |||
487 | if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) | 631 | if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) |
488 | mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 | 632 | mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 |
489 | } | 633 | } |
490 | else if (mBoostLevel < LLViewerImage::BOOST_HIGH && mMaxVirtualSize <= 10.f) | 634 | else if (mBoostLevel < LLViewerImageBoostLevel::BOOST_HIGH && mMaxVirtualSize <= 10.f) |
491 | { | 635 | { |
492 | // If the image has not been significantly visible in a while, we don't want it | 636 | // If the image has not been significantly visible in a while, we don't want it |
493 | mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); | 637 | mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); |
@@ -504,15 +648,14 @@ void LLViewerImage::processTextureStats() | |||
504 | S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); | 648 | S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); |
505 | S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); | 649 | S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); |
506 | mTexelsPerImage = (F32)fullwidth * fullheight; | 650 | mTexelsPerImage = (F32)fullwidth * fullheight; |
507 | |||
508 | F32 discard_level = 0.f; | 651 | F32 discard_level = 0.f; |
509 | 652 | ||
510 | // If we know the output width and height, we can force the discard | 653 | // If we know the output width and height, we can force the discard |
511 | // level to the correct value, and thus not decode more texture | 654 | // level to the correct value, and thus not decode more texture |
512 | // data than we need to. | 655 | // data than we need to. |
513 | if (mBoostLevel == LLViewerImage::BOOST_UI || | 656 | if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI || |
514 | mBoostLevel == LLViewerImage::BOOST_PREVIEW || | 657 | mBoostLevel == LLViewerImageBoostLevel::BOOST_PREVIEW || |
515 | mBoostLevel == LLViewerImage::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? | 658 | mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? |
516 | { | 659 | { |
517 | discard_level = 0; // full res | 660 | discard_level = 0; // full res |
518 | } | 661 | } |
@@ -527,6 +670,12 @@ void LLViewerImage::processTextureStats() | |||
527 | } | 670 | } |
528 | else | 671 | else |
529 | { | 672 | { |
673 | if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f) | ||
674 | { | ||
675 | //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. | ||
676 | mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerImage::sMinLargeImageSize) ; | ||
677 | } | ||
678 | |||
530 | if ((mCalculatedDiscardLevel >= 0.f) && | 679 | if ((mCalculatedDiscardLevel >= 0.f) && |
531 | (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) | 680 | (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) |
532 | { | 681 | { |
@@ -541,15 +690,14 @@ void LLViewerImage::processTextureStats() | |||
541 | mCalculatedDiscardLevel = discard_level; | 690 | mCalculatedDiscardLevel = discard_level; |
542 | } | 691 | } |
543 | } | 692 | } |
544 | if (mBoostLevel < LLViewerImage::BOOST_HIGH) | 693 | if (mBoostLevel < LLViewerImageBoostLevel::BOOST_HIGH) |
545 | { | 694 | { |
546 | static const F32 discard_bias = -.5f; // Must be < 1 or highest discard will never load! | ||
547 | discard_level += discard_bias; | ||
548 | discard_level += sDesiredDiscardBias; | 695 | discard_level += sDesiredDiscardBias; |
549 | discard_level *= sDesiredDiscardScale; // scale | 696 | discard_level *= sDesiredDiscardScale; // scale |
697 | |||
698 | discard_level += sCameraMovingDiscardBias ; | ||
550 | } | 699 | } |
551 | discard_level = floorf(discard_level); | 700 | discard_level = floorf(discard_level); |
552 | // discard_level -= (gImageList.mVideoMemorySetting>>1); // more video ram = higher detail | ||
553 | 701 | ||
554 | F32 min_discard = 0.f; | 702 | F32 min_discard = 0.f; |
555 | if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) | 703 | if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) |
@@ -567,43 +715,76 @@ void LLViewerImage::processTextureStats() | |||
567 | // if possible. Now we check to see if we have it, and take the | 715 | // if possible. Now we check to see if we have it, and take the |
568 | // proper action if we don't. | 716 | // proper action if we don't. |
569 | // | 717 | // |
570 | |||
571 | BOOL increase_discard = FALSE; | ||
572 | S32 current_discard = getDiscardLevel(); | 718 | S32 current_discard = getDiscardLevel(); |
573 | if ((sDesiredDiscardBias > 0.0f) && | 719 | if ((sDesiredDiscardBias > 0.0f) && |
574 | (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) | 720 | (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) |
575 | { | 721 | { |
576 | if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) | 722 | // Limit the amount of GL memory bound each frame |
723 | if ( (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && | ||
724 | (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) | ||
577 | { | 725 | { |
578 | // Limit the amount of GL memory bound each frame | 726 | scaleDown() ; |
579 | if (mDesiredDiscardLevel > current_discard) | ||
580 | { | ||
581 | increase_discard = TRUE; | ||
582 | } | ||
583 | } | 727 | } |
584 | if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) | 728 | // Only allow GL to have 2x the video card memory |
729 | else if ( (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) && | ||
730 | (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) | ||
585 | { | 731 | { |
586 | // Only allow GL to have 2x the video card memory | 732 | scaleDown() ; |
587 | if (!getBoundRecently()) | ||
588 | { | ||
589 | increase_discard = TRUE; | ||
590 | } | ||
591 | } | 733 | } |
592 | if (increase_discard) | 734 | } |
735 | } | ||
736 | } | ||
737 | void LLViewerImage::updateVirtualSize() | ||
738 | { | ||
739 | #if 1 | ||
740 | if(mNeedsResetMaxVirtualSize) | ||
741 | { | ||
742 | addTextureStats(0.f, FALSE) ;//reset | ||
743 | } | ||
744 | if(mFaceList.size() > 0) | ||
745 | { | ||
746 | for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) | ||
747 | { | ||
748 | LLFace* facep = *iter ; | ||
749 | if(facep->getDrawable()->isRecentlyVisible()) | ||
593 | { | 750 | { |
594 | // llinfos << "DISCARDED: " << mID << " Discard: " << current_discard << llendl; | 751 | addTextureStats(facep->getVirtualSize()) ; |
595 | sBoundTextureMemoryInBytes -= mTextureMemory; | 752 | setAdditionalDecodePriority(facep->getImportanceToCamera()) ; |
596 | sTotalTextureMemoryInBytes -= mTextureMemory; | ||
597 | // Increase the discard level (reduce the texture res) | ||
598 | S32 new_discard = current_discard+1; | ||
599 | setDiscardLevel(new_discard); | ||
600 | sBoundTextureMemoryInBytes += mTextureMemory; | ||
601 | sTotalTextureMemoryInBytes += mTextureMemory; | ||
602 | } | 753 | } |
603 | } | 754 | } |
604 | } | 755 | } |
756 | mNeedsResetMaxVirtualSize = TRUE ; | ||
757 | #endif | ||
605 | } | 758 | } |
759 | void LLViewerImage::scaleDown() | ||
760 | { | ||
761 | if(getHasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) | ||
762 | { | ||
763 | switchToCachedImage() ; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | //use the mCachedRawImage to (re)generate the gl texture. | ||
768 | void LLViewerImage::switchToCachedImage() | ||
769 | { | ||
770 | if(mCachedRawImage.notNull()) | ||
771 | { | ||
772 | mRawImage = mCachedRawImage ; | ||
773 | |||
774 | if (getComponents() != mRawImage->getComponents()) | ||
775 | { | ||
776 | // We've changed the number of components, so we need to move any | ||
777 | // objects using this pool to a different pool. | ||
778 | mComponents = mRawImage->getComponents(); | ||
779 | gImageList.dirtyImage(this); | ||
780 | } | ||
606 | 781 | ||
782 | mIsRawImageValid = TRUE; | ||
783 | mRawDiscardLevel = mCachedRawDiscardLevel ; | ||
784 | gImageList.mCreateTextureList.insert(this); | ||
785 | mNeedsCreateTexture = TRUE; | ||
786 | } | ||
787 | } | ||
607 | //============================================================================ | 788 | //============================================================================ |
608 | 789 | ||
609 | F32 LLViewerImage::calcDecodePriority() | 790 | F32 LLViewerImage::calcDecodePriority() |
@@ -619,9 +800,19 @@ F32 LLViewerImage::calcDecodePriority() | |||
619 | { | 800 | { |
620 | return mDecodePriority; // no change while waiting to create | 801 | return mDecodePriority; // no change while waiting to create |
621 | } | 802 | } |
803 | if(mForceToSaveRawImage) | ||
804 | { | ||
805 | return maxDecodePriority() ; | ||
806 | } | ||
622 | 807 | ||
623 | F32 priority; | ||
624 | S32 cur_discard = getDiscardLevel(); | 808 | S32 cur_discard = getDiscardLevel(); |
809 | |||
810 | //no need to update if the texture reaches its highest res and the memory is sufficient. | ||
811 | //if(LLViewerImage::sFreezeImageScalingDown && !cur_discard) | ||
812 | //{ | ||
813 | // return -5.0f ; | ||
814 | //} | ||
815 | |||
625 | bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); | 816 | bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); |
626 | F32 pixel_priority = fsqrtf(mMaxVirtualSize); | 817 | F32 pixel_priority = fsqrtf(mMaxVirtualSize); |
627 | const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame | 818 | const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame |
@@ -631,23 +822,36 @@ F32 LLViewerImage::calcDecodePriority() | |||
631 | mVisibleFrame = mDecodeFrame; | 822 | mVisibleFrame = mDecodeFrame; |
632 | } | 823 | } |
633 | 824 | ||
825 | F32 priority = 0.f; | ||
634 | if (mIsMissingAsset) | 826 | if (mIsMissingAsset) |
635 | { | 827 | { |
636 | priority = 0.0f; | 828 | priority = 0.0f; |
829 | } | ||
830 | else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) | ||
831 | { | ||
832 | priority = -1.0f ; | ||
833 | } | ||
834 | else if (!isJustBound() && mCachedRawImageReady) | ||
835 | { | ||
836 | priority = -1.0f; | ||
837 | } | ||
838 | else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) | ||
839 | { | ||
840 | priority = -1.0f; | ||
637 | } | 841 | } |
638 | else if (mDesiredDiscardLevel > mMaxDiscardLevel) | 842 | else if (mDesiredDiscardLevel > mMaxDiscardLevel) |
639 | { | 843 | { |
640 | // Don't decode anything we don't need | 844 | // Don't decode anything we don't need |
641 | priority = -1.0f; | 845 | priority = -1.0f; |
642 | } | 846 | } |
643 | else if (mBoostLevel == LLViewerImage::BOOST_UI && !have_all_data) | 847 | else if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI && !have_all_data) |
644 | { | 848 | { |
645 | priority = 1.f; | 849 | priority = 1.f; |
646 | } | 850 | } |
647 | else if (pixel_priority <= 0.f && !have_all_data) | 851 | else if (pixel_priority <= 0.f && !have_all_data) |
648 | { | 852 | { |
649 | // Not on screen but we might want some data | 853 | // Not on screen but we might want some data |
650 | if (mBoostLevel > BOOST_HIGH) | 854 | if (mBoostLevel > LLViewerImageBoostLevel::BOOST_HIGH) |
651 | { | 855 | { |
652 | // Always want high boosted images | 856 | // Always want high boosted images |
653 | priority = 1.f; | 857 | priority = 1.f; |
@@ -695,12 +899,16 @@ F32 LLViewerImage::calcDecodePriority() | |||
695 | ddiscard-=2; | 899 | ddiscard-=2; |
696 | } | 900 | } |
697 | ddiscard = llclamp(ddiscard, 0, 4); | 901 | ddiscard = llclamp(ddiscard, 0, 4); |
902 | |||
698 | priority = ddiscard*100000.f; | 903 | priority = ddiscard*100000.f; |
699 | } | 904 | } |
700 | if (priority > 0.0f) | 905 | if (priority > 0.0f) |
701 | { | 906 | { |
702 | pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); // priority range = 100000-900000 | 907 | // priority range = 100000-900000 |
703 | if ( mBoostLevel > BOOST_HIGH) | 908 | pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); |
909 | |||
910 | // priority range = [100000.f, 2000000.f] | ||
911 | if ( mBoostLevel > LLViewerImageBoostLevel::BOOST_HIGH) | ||
704 | { | 912 | { |
705 | priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel; | 913 | priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel; |
706 | } | 914 | } |
@@ -708,7 +916,14 @@ F32 LLViewerImage::calcDecodePriority() | |||
708 | { | 916 | { |
709 | priority += 0.f + pixel_priority + 1000.f * mBoostLevel; | 917 | priority += 0.f + pixel_priority + 1000.f * mBoostLevel; |
710 | } | 918 | } |
919 | |||
920 | // priority range = [2100000.f, 5000000.f] if mAdditionalDecodePriority > 1.0 | ||
921 | if(mAdditionalDecodePriority > 1.0f) | ||
922 | { | ||
923 | priority += 2000000.f + mAdditionalDecodePriority ; | ||
924 | } | ||
711 | } | 925 | } |
926 | |||
712 | return priority; | 927 | return priority; |
713 | } | 928 | } |
714 | 929 | ||
@@ -716,7 +931,7 @@ F32 LLViewerImage::calcDecodePriority() | |||
716 | //static | 931 | //static |
717 | F32 LLViewerImage::maxDecodePriority() | 932 | F32 LLViewerImage::maxDecodePriority() |
718 | { | 933 | { |
719 | return 2000000.f; | 934 | return 6000000.f; |
720 | } | 935 | } |
721 | 936 | ||
722 | void LLViewerImage::setDecodePriority(F32 priority) | 937 | void LLViewerImage::setDecodePriority(F32 priority) |
@@ -725,15 +940,30 @@ void LLViewerImage::setDecodePriority(F32 priority) | |||
725 | mDecodePriority = priority; | 940 | mDecodePriority = priority; |
726 | } | 941 | } |
727 | 942 | ||
728 | void LLViewerImage::setBoostLevel(S32 level) | 943 | F32 LLViewerImage::maxAdditionalDecodePriority() |
944 | { | ||
945 | return 2000000.f; | ||
946 | } | ||
947 | void LLViewerImage::setAdditionalDecodePriority(F32 priority) | ||
729 | { | 948 | { |
949 | priority *= maxAdditionalDecodePriority(); | ||
950 | if(mAdditionalDecodePriority < priority) | ||
951 | { | ||
952 | mAdditionalDecodePriority = priority; | ||
953 | } | ||
954 | } | ||
955 | //------------------------------------------------------------ | ||
956 | |||
957 | void LLViewerImage::setBoostLevel(S32 level) | ||
958 | { | ||
730 | mBoostLevel = level; | 959 | mBoostLevel = level; |
731 | if (level >= LLViewerImage::BOOST_HIGH) | 960 | |
961 | if(gAuditTexture) | ||
732 | { | 962 | { |
733 | processTextureStats(); | 963 | setCategory(mBoostLevel); |
734 | } | 964 | } |
735 | 965 | ||
736 | if(mBoostLevel != LLViewerImage::BOOST_NONE) | 966 | if(mBoostLevel != LLViewerImageBoostLevel::BOOST_NONE) |
737 | { | 967 | { |
738 | setNoDelete() ; | 968 | setNoDelete() ; |
739 | } | 969 | } |
@@ -785,11 +1015,20 @@ bool LLViewerImage::updateFetch() | |||
785 | S32 desired_discard = getDesiredDiscardLevel(); | 1015 | S32 desired_discard = getDesiredDiscardLevel(); |
786 | F32 decode_priority = getDecodePriority(); | 1016 | F32 decode_priority = getDecodePriority(); |
787 | decode_priority = llmax(decode_priority, 0.0f); | 1017 | decode_priority = llmax(decode_priority, 0.0f); |
1018 | decode_priority = llmin(decode_priority, maxDecodePriority()); | ||
788 | 1019 | ||
789 | if (mIsFetching) | 1020 | if (mIsFetching) |
790 | { | 1021 | { |
791 | // Sets mRawDiscardLevel, mRawImage, mAuxRawImage | 1022 | // Sets mRawDiscardLevel, mRawImage, mAuxRawImage |
792 | S32 fetch_discard = current_discard; | 1023 | S32 fetch_discard = current_discard; |
1024 | if(mForceToSaveRawImage) | ||
1025 | { | ||
1026 | if(fetch_discard >= 0) | ||
1027 | { | ||
1028 | fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ; | ||
1029 | } | ||
1030 | } | ||
1031 | |||
793 | if (mRawImage.notNull()) sRawCount--; | 1032 | if (mRawImage.notNull()) sRawCount--; |
794 | if (mAuxRawImage.notNull()) sAuxCount--; | 1033 | if (mAuxRawImage.notNull()) sAuxCount--; |
795 | bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); | 1034 | bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); |
@@ -809,6 +1048,7 @@ bool LLViewerImage::updateFetch() | |||
809 | if (mRawImage.notNull()) | 1048 | if (mRawImage.notNull()) |
810 | { | 1049 | { |
811 | mRawDiscardLevel = fetch_discard; | 1050 | mRawDiscardLevel = fetch_discard; |
1051 | |||
812 | if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && | 1052 | if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && |
813 | (current_discard < 0 || mRawDiscardLevel < current_discard)) | 1053 | (current_discard < 0 || mRawDiscardLevel < current_discard)) |
814 | { | 1054 | { |
@@ -819,11 +1059,25 @@ bool LLViewerImage::updateFetch() | |||
819 | mComponents = mRawImage->getComponents(); | 1059 | mComponents = mRawImage->getComponents(); |
820 | gImageList.dirtyImage(this); | 1060 | gImageList.dirtyImage(this); |
821 | } | 1061 | } |
822 | mIsRawImageValid = TRUE; | 1062 | |
823 | gImageList.mCreateTextureList.insert(this); | ||
824 | mNeedsCreateTexture = TRUE; | ||
825 | mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; | 1063 | mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; |
826 | mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; | 1064 | mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; |
1065 | |||
1066 | if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) | ||
1067 | { | ||
1068 | //discard all oversized textures. | ||
1069 | destroyRawImage(); | ||
1070 | setIsMissingAsset(); | ||
1071 | mRawDiscardLevel = INVALID_DISCARD_LEVEL ; | ||
1072 | mIsFetching = FALSE ; | ||
1073 | } | ||
1074 | else | ||
1075 | { | ||
1076 | mIsRawImageValid = TRUE; | ||
1077 | addToCreateTexture() ; | ||
1078 | } | ||
1079 | |||
1080 | return TRUE ; | ||
827 | } | 1081 | } |
828 | else | 1082 | else |
829 | { | 1083 | { |
@@ -846,7 +1100,7 @@ bool LLViewerImage::updateFetch() | |||
846 | } | 1100 | } |
847 | else | 1101 | else |
848 | { | 1102 | { |
849 | llwarns << mID << ": Setting min discard to " << current_discard << llendl; | 1103 | //llwarns << mID << ": Setting min discard to " << current_discard << llendl; |
850 | mMinDiscardLevel = current_discard; | 1104 | mMinDiscardLevel = current_discard; |
851 | desired_discard = current_discard; | 1105 | desired_discard = current_discard; |
852 | } | 1106 | } |
@@ -865,8 +1119,19 @@ bool LLViewerImage::updateFetch() | |||
865 | } | 1119 | } |
866 | } | 1120 | } |
867 | 1121 | ||
868 | bool make_request = true; | 1122 | if (!mDontDiscard) |
869 | 1123 | { | |
1124 | if (mBoostLevel == 0) | ||
1125 | { | ||
1126 | desired_discard = llmax(desired_discard, current_discard-1); | ||
1127 | } | ||
1128 | else | ||
1129 | { | ||
1130 | desired_discard = llmax(desired_discard, current_discard-2); | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | bool make_request = true; | ||
870 | if (decode_priority <= 0) | 1135 | if (decode_priority <= 0) |
871 | { | 1136 | { |
872 | make_request = false; | 1137 | make_request = false; |
@@ -879,6 +1144,10 @@ bool LLViewerImage::updateFetch() | |||
879 | { | 1144 | { |
880 | make_request = false; | 1145 | make_request = false; |
881 | } | 1146 | } |
1147 | else if (!isJustBound() && mCachedRawImageReady) | ||
1148 | { | ||
1149 | make_request = false; | ||
1150 | } | ||
882 | else | 1151 | else |
883 | { | 1152 | { |
884 | if (mIsFetching) | 1153 | if (mIsFetching) |
@@ -906,41 +1175,21 @@ bool LLViewerImage::updateFetch() | |||
906 | h = getHeight(0); | 1175 | h = getHeight(0); |
907 | c = getComponents(); | 1176 | c = getComponents(); |
908 | } | 1177 | } |
909 | if (!mDontDiscard) | 1178 | |
910 | { | ||
911 | if (mBoostLevel == 0) | ||
912 | { | ||
913 | desired_discard = llmax(desired_discard, current_discard-1); | ||
914 | } | ||
915 | else | ||
916 | { | ||
917 | desired_discard = llmax(desired_discard, current_discard-2); | ||
918 | } | ||
919 | } | ||
920 | |||
921 | // bypass texturefetch directly by pulling from LLTextureCache | 1179 | // bypass texturefetch directly by pulling from LLTextureCache |
922 | bool fetch_request_created = false; | 1180 | bool fetch_request_created = false; |
923 | if (mLocalFileName.empty()) | 1181 | fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, |
924 | { | 1182 | w, h, c, desired_discard, needsAux()); |
925 | fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(getID(), getTargetHost(), decode_priority, | ||
926 | w, h, c, desired_discard, | ||
927 | needsAux()); | ||
928 | } | ||
929 | else | ||
930 | { | ||
931 | fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mLocalFileName, getID(),getTargetHost(), decode_priority, | ||
932 | w, h, c, desired_discard, | ||
933 | needsAux()); | ||
934 | } | ||
935 | 1183 | ||
936 | if (fetch_request_created) | 1184 | if (fetch_request_created) |
937 | { | 1185 | { |
938 | mHasFetcher = TRUE; | 1186 | mHasFetcher = TRUE; |
939 | mIsFetching = TRUE; | 1187 | mIsFetching = TRUE; |
940 | mRequestedDiscardLevel = desired_discard; | 1188 | mRequestedDiscardLevel = desired_discard; |
1189 | |||
941 | mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, | 1190 | mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, |
942 | mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); | 1191 | mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); |
943 | } | 1192 | } |
944 | 1193 | ||
945 | // if createRequest() failed, we're finishing up a request for this UUID, | 1194 | // if createRequest() failed, we're finishing up a request for this UUID, |
946 | // wait for it to complete | 1195 | // wait for it to complete |
@@ -962,9 +1211,81 @@ bool LLViewerImage::updateFetch() | |||
962 | return mIsFetching ? true : false; | 1211 | return mIsFetching ? true : false; |
963 | } | 1212 | } |
964 | 1213 | ||
1214 | // | ||
1215 | //force to fetch a new raw image for this texture | ||
1216 | //this function is to replace readBackRaw(). | ||
1217 | // | ||
1218 | BOOL LLViewerImage::forceFetch() | ||
1219 | { | ||
1220 | if(!mForceToSaveRawImage) | ||
1221 | { | ||
1222 | return false ; | ||
1223 | } | ||
1224 | if (mIsMediaTexture) | ||
1225 | { | ||
1226 | mForceToSaveRawImage = false ; | ||
1227 | llassert_always(!mHasFetcher); | ||
1228 | return false; // skip | ||
1229 | } | ||
1230 | if (mIsMissingAsset) | ||
1231 | { | ||
1232 | mForceToSaveRawImage = false ; | ||
1233 | llassert_always(!mHasFetcher); | ||
1234 | return false; // skip | ||
1235 | } | ||
1236 | if (!mLoadedCallbackList.empty() && mRawImage.notNull()) | ||
1237 | { | ||
1238 | return false; // process any raw image data in callbacks before replacing | ||
1239 | } | ||
1240 | if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel) | ||
1241 | { | ||
1242 | return false ; // mRawImage is enough | ||
1243 | } | ||
1244 | if(mIsFetching) | ||
1245 | { | ||
1246 | return false ; | ||
1247 | } | ||
1248 | |||
1249 | S32 desired_discard = mDesiredSavedRawDiscardLevel ; | ||
1250 | S32 current_discard = getDiscardLevel(); | ||
1251 | |||
1252 | bool fetch_request_created = false; | ||
1253 | S32 w=0, h=0, c=0; | ||
1254 | if (current_discard >= 0) | ||
1255 | { | ||
1256 | w = getWidth(0); | ||
1257 | h = getHeight(0); | ||
1258 | c = getComponents(); | ||
1259 | } | ||
1260 | fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), maxDecodePriority(), | ||
1261 | w, h, c, desired_discard, needsAux()); | ||
1262 | |||
1263 | if (fetch_request_created) | ||
1264 | { | ||
1265 | mHasFetcher = TRUE; | ||
1266 | mIsFetching = TRUE; | ||
1267 | // Set the image's decode priority to maxDecodePriority() too, or updateFetch() will set | ||
1268 | // the request priority to 0 and terminate the fetch before we even started (SNOW-203). | ||
1269 | gImageList.bumpToMaxDecodePriority(this); | ||
1270 | mRequestedDiscardLevel = desired_discard ; | ||
1271 | |||
1272 | mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, | ||
1273 | mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); | ||
1274 | } | ||
1275 | |||
1276 | return mIsFetching ? true : false; | ||
1277 | } | ||
1278 | |||
965 | void LLViewerImage::setIsMissingAsset() | 1279 | void LLViewerImage::setIsMissingAsset() |
966 | { | 1280 | { |
967 | llwarns << mLocalFileName << " " << mID << ": Marking image as missing" << llendl; | 1281 | if (mUrl.empty()) |
1282 | { | ||
1283 | llwarns << mID << ": Marking image as missing" << llendl; | ||
1284 | } | ||
1285 | else | ||
1286 | { | ||
1287 | llwarns << mUrl << ": Marking image as missing" << llendl; | ||
1288 | } | ||
968 | if (mHasFetcher) | 1289 | if (mHasFetcher) |
969 | { | 1290 | { |
970 | LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); | 1291 | LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); |
@@ -1252,7 +1573,7 @@ bool LLViewerImage::bindError(S32 stage) const | |||
1252 | return res; | 1573 | return res; |
1253 | } | 1574 | } |
1254 | 1575 | ||
1255 | bool LLViewerImage::bindDefaultImage(S32 stage) const | 1576 | bool LLViewerImage::bindDefaultImage(S32 stage) |
1256 | { | 1577 | { |
1257 | if (stage < 0) return false; | 1578 | if (stage < 0) return false; |
1258 | 1579 | ||
@@ -1271,24 +1592,17 @@ bool LLViewerImage::bindDefaultImage(S32 stage) const | |||
1271 | llwarns << "LLViewerImage::bindError failed." << llendl; | 1592 | llwarns << "LLViewerImage::bindError failed." << llendl; |
1272 | } | 1593 | } |
1273 | stop_glerror(); | 1594 | stop_glerror(); |
1595 | |||
1596 | //check if there is cached raw image and switch to it if possible | ||
1597 | switchToCachedImage() ; | ||
1598 | |||
1274 | return res; | 1599 | return res; |
1275 | } | 1600 | } |
1276 | 1601 | ||
1277 | //virtual | 1602 | //virtual |
1278 | void LLViewerImage::forceImmediateUpdate() | 1603 | void LLViewerImage::forceImmediateUpdate() |
1279 | { | 1604 | { |
1280 | //only immediately update a deleted texture which is now being re-used. | 1605 | gImageList.bumpToMaxDecodePriority(this) ; |
1281 | if(!isDeleted()) | ||
1282 | { | ||
1283 | return ; | ||
1284 | } | ||
1285 | //if already called forceImmediateUpdate() | ||
1286 | if(mInImageList && mDecodePriority == LLViewerImage::maxDecodePriority()) | ||
1287 | { | ||
1288 | return ; | ||
1289 | } | ||
1290 | |||
1291 | gImageList.forceImmediateUpdate(this) ; | ||
1292 | return ; | 1606 | return ; |
1293 | } | 1607 | } |
1294 | 1608 | ||
@@ -1302,21 +1616,165 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level) | |||
1302 | llerrs << "called with existing mRawImage" << llendl; | 1616 | llerrs << "called with existing mRawImage" << llendl; |
1303 | mRawImage = NULL; | 1617 | mRawImage = NULL; |
1304 | } | 1618 | } |
1305 | mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), mComponents); | ||
1306 | sRawCount++; | ||
1307 | mRawDiscardLevel = discard_level; | ||
1308 | readBackRaw(mRawDiscardLevel, mRawImage, false); | ||
1309 | mIsRawImageValid = TRUE; | ||
1310 | 1619 | ||
1620 | if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) | ||
1621 | { | ||
1622 | mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; | ||
1623 | mRawImage->copy(mSavedRawImage) ; | ||
1624 | mRawDiscardLevel = discard_level ; | ||
1625 | } | ||
1626 | else | ||
1627 | { | ||
1628 | mRawImage = mCachedRawImage ; | ||
1629 | mRawDiscardLevel = mCachedRawDiscardLevel; | ||
1630 | } | ||
1631 | |||
1632 | sRawCount++; | ||
1633 | mIsRawImageValid = TRUE; | ||
1634 | |||
1311 | return mRawImage; | 1635 | return mRawImage; |
1312 | } | 1636 | } |
1313 | 1637 | ||
1638 | void LLViewerImage::saveRawImage() | ||
1639 | { | ||
1640 | if(mRawImage.isNull() || mRawDiscardLevel > mDesiredSavedRawDiscardLevel) | ||
1641 | { | ||
1642 | forceFetch() ; | ||
1643 | } | ||
1644 | |||
1645 | if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel) | ||
1646 | { | ||
1647 | return ; | ||
1648 | } | ||
1649 | |||
1650 | mSavedRawDiscardLevel = mRawDiscardLevel ; | ||
1651 | mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; | ||
1652 | |||
1653 | if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) | ||
1654 | { | ||
1655 | mForceToSaveRawImage = FALSE ; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | void LLViewerImage::forceToSaveRawImage(S32 desired_discard) | ||
1660 | { | ||
1661 | mForceToSaveRawImage = TRUE ; | ||
1662 | mDesiredSavedRawDiscardLevel = desired_discard ; | ||
1663 | |||
1664 | forceFetch() ; | ||
1665 | } | ||
1666 | void LLViewerImage::destroySavedRawImage() | ||
1667 | { | ||
1668 | mSavedRawImage = NULL ; | ||
1669 | mForceToSaveRawImage = FALSE ; | ||
1670 | mSavedRawDiscardLevel = -1 ; | ||
1671 | mDesiredSavedRawDiscardLevel = -1 ; | ||
1672 | } | ||
1673 | |||
1314 | void LLViewerImage::destroyRawImage() | 1674 | void LLViewerImage::destroyRawImage() |
1315 | { | 1675 | { |
1316 | if (mRawImage.notNull()) sRawCount--; | 1676 | if (mRawImage.notNull()) sRawCount--; |
1317 | if (mAuxRawImage.notNull()) sAuxCount--; | 1677 | if (mAuxRawImage.notNull()) sAuxCount--; |
1678 | |||
1679 | if(mForceToSaveRawImage) | ||
1680 | { | ||
1681 | saveRawImage() ; | ||
1682 | } | ||
1683 | |||
1684 | setCachedRawImage() ; | ||
1685 | |||
1318 | mRawImage = NULL; | 1686 | mRawImage = NULL; |
1319 | mAuxRawImage = NULL; | 1687 | mAuxRawImage = NULL; |
1320 | mIsRawImageValid = FALSE; | 1688 | mIsRawImageValid = FALSE; |
1321 | mRawDiscardLevel = INVALID_DISCARD_LEVEL; | 1689 | mRawDiscardLevel = INVALID_DISCARD_LEVEL; |
1322 | } | 1690 | } |
1691 | |||
1692 | void LLViewerImage::setCachedRawImage() | ||
1693 | { | ||
1694 | if(mRawImage == mCachedRawImage) | ||
1695 | { | ||
1696 | return ; | ||
1697 | } | ||
1698 | if(!mIsRawImageValid) | ||
1699 | { | ||
1700 | return ; | ||
1701 | } | ||
1702 | |||
1703 | if(mCachedRawImageReady) | ||
1704 | { | ||
1705 | return ; | ||
1706 | } | ||
1707 | |||
1708 | if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) | ||
1709 | { | ||
1710 | S32 i = 0 ; | ||
1711 | S32 w = mRawImage->getWidth() ; | ||
1712 | S32 h = mRawImage->getHeight() ; | ||
1713 | |||
1714 | S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; | ||
1715 | if(LLViewerImageBoostLevel::BOOST_TERRAIN == mBoostLevel) | ||
1716 | { | ||
1717 | max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; | ||
1718 | } | ||
1719 | if(mForSculpt) | ||
1720 | { | ||
1721 | max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ; | ||
1722 | } | ||
1723 | |||
1724 | while(((w >> i) * (h >> i)) > max_size) | ||
1725 | { | ||
1726 | ++i ; | ||
1727 | } | ||
1728 | mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ; | ||
1729 | |||
1730 | if(i) | ||
1731 | { | ||
1732 | if(!(w >> i) || !(h >> i)) | ||
1733 | { | ||
1734 | --i ; | ||
1735 | } | ||
1736 | mRawImage->scale(w >> i, h >> i) ; | ||
1737 | } | ||
1738 | mCachedRawImage = mRawImage ; | ||
1739 | mCachedRawDiscardLevel = mRawDiscardLevel + i ; | ||
1740 | } | ||
1741 | } | ||
1742 | |||
1743 | void LLViewerImage::checkCachedRawSculptImage() | ||
1744 | { | ||
1745 | if(mCachedRawImageReady && mCachedRawDiscardLevel > 0) | ||
1746 | { | ||
1747 | if(mCachedRawImage->getWidth() * mCachedRawImage->getHeight() < MAX_CACHED_RAW_SCULPT_IMAGE_AREA) | ||
1748 | { | ||
1749 | mCachedRawImageReady = FALSE ; | ||
1750 | } | ||
1751 | else if(isForSculptOnly()) | ||
1752 | { | ||
1753 | resetTextureStats() ; //do not update this image any more. | ||
1754 | } | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1758 | BOOL LLViewerImage::isForSculptOnly() const | ||
1759 | { | ||
1760 | return mForSculpt && !mNeedsGLTexture ; | ||
1761 | } | ||
1762 | |||
1763 | void LLViewerImage::setForSculpt() | ||
1764 | { | ||
1765 | mForSculpt = TRUE ; | ||
1766 | if(isForSculptOnly() && !getBoundRecently()) | ||
1767 | { | ||
1768 | destroyGLTexture() ; //sculpt image does not need gl texture. | ||
1769 | } | ||
1770 | checkCachedRawSculptImage() ; | ||
1771 | } | ||
1772 | |||
1773 | void LLViewerImage::addFace(LLFace* facep) | ||
1774 | { | ||
1775 | mFaceList.push_back(facep) ; | ||
1776 | } | ||
1777 | void LLViewerImage::removeFace(LLFace* facep) | ||
1778 | { | ||
1779 | mFaceList.remove(facep) ; | ||
1780 | } | ||
diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index 980ff56..fdf8ff0 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <map> | 41 | #include <map> |
42 | #include <list> | 42 | #include <list> |
43 | 43 | ||
44 | class LLFace; | ||
44 | #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 | 45 | #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 |
45 | #define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. | 46 | #define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. |
46 | 47 | ||
@@ -75,6 +76,43 @@ public: | |||
75 | 76 | ||
76 | class LLTextureBar; | 77 | class LLTextureBar; |
77 | 78 | ||
79 | //===================================== | ||
80 | struct LLViewerImageBoostLevel | ||
81 | { | ||
82 | enum | ||
83 | { | ||
84 | BOOST_NONE = 0, | ||
85 | BOOST_AVATAR_BAKED = 1, | ||
86 | BOOST_AVATAR = 2, | ||
87 | BOOST_CLOUDS = 3, | ||
88 | BOOST_SCULPTED = 4, | ||
89 | |||
90 | BOOST_HIGH = 5, | ||
91 | BOOST_TERRAIN , // has to be high priority for minimap / low detail | ||
92 | BOOST_SELECTED , | ||
93 | BOOST_HUD , | ||
94 | BOOST_AVATAR_BAKED_SELF , | ||
95 | BOOST_UI , | ||
96 | BOOST_PREVIEW , | ||
97 | BOOST_MAP , | ||
98 | BOOST_MAP_VISIBLE , | ||
99 | BOOST_AVATAR_SELF ,// needed for baking avatar | ||
100 | BOOST_MAX_LEVEL, | ||
101 | |||
102 | //LLImageGLCategory | ||
103 | TEXLAYER_BUMP = BOOST_MAX_LEVEL, | ||
104 | AVATAR_SCRATCH_TEX, | ||
105 | FONT, | ||
106 | BUMP_IMAGE, | ||
107 | DYNAMIC_TEX, | ||
108 | TEXLAYER_CACHE, | ||
109 | MEDIA, | ||
110 | ATLAS, | ||
111 | OTHER, | ||
112 | MAX_GL_IMAGE_CATEGORY | ||
113 | }; | ||
114 | }; | ||
115 | //===================================== | ||
78 | class LLViewerImage : public LLImageGL | 116 | class LLViewerImage : public LLImageGL |
79 | { | 117 | { |
80 | LOG_CLASS(LLViewerImage); | 118 | LOG_CLASS(LLViewerImage); |
@@ -175,15 +213,15 @@ protected: | |||
175 | /*virtual*/ ~LLViewerImage(); | 213 | /*virtual*/ ~LLViewerImage(); |
176 | 214 | ||
177 | public: | 215 | public: |
178 | LLViewerImage(const std::string& filename, const LLUUID& id, BOOL usemipmaps = TRUE); | 216 | LLViewerImage(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); |
179 | LLViewerImage(const LLUUID& id, BOOL usemipmaps = TRUE); | 217 | LLViewerImage(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); |
180 | LLViewerImage(const U32 width, const U32 height, const U8 components, BOOL usemipmaps); | 218 | LLViewerImage(const U32 width, const U32 height, const U8 components, BOOL usemipmaps); |
181 | LLViewerImage(const LLImageRaw* raw, BOOL usemipmaps); | 219 | LLViewerImage(const LLImageRaw* raw, BOOL usemipmaps); |
182 | 220 | ||
183 | /*virtual*/ void dump(); // debug info to llinfos | 221 | /*virtual*/ void dump(); // debug info to llinfos |
184 | 222 | ||
185 | /*virtual*/ bool bindError(const S32 stage = 0) const; | 223 | /*virtual*/ bool bindError(const S32 stage = 0) const; |
186 | /*virtual*/ bool bindDefaultImage(const S32 stage = 0) const; | 224 | /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; |
187 | /*virtual*/ void forceImmediateUpdate() ; | 225 | /*virtual*/ void forceImmediateUpdate() ; |
188 | 226 | ||
189 | void reinit(BOOL usemipmaps = TRUE); | 227 | void reinit(BOOL usemipmaps = TRUE); |
@@ -192,8 +230,13 @@ public: | |||
192 | 230 | ||
193 | // New methods for determining image quality/priority | 231 | // New methods for determining image quality/priority |
194 | // texel_area_ratio is ("scaled" texel area)/(original texel area), approximately. | 232 | // texel_area_ratio is ("scaled" texel area)/(original texel area), approximately. |
195 | void addTextureStats(F32 virtual_size) const; | 233 | void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; |
196 | void resetTextureStats(BOOL zero = FALSE); | 234 | void resetTextureStats(); |
235 | void setAdditionalDecodePriority(F32 priority) ; | ||
236 | F32 maxAdditionalDecodePriority() ; | ||
237 | |||
238 | BOOL isLargeImage() ; | ||
239 | BOOL isUpdateFrozen() ; | ||
197 | 240 | ||
198 | // Process image stats to determine priority/quality requirements. | 241 | // Process image stats to determine priority/quality requirements. |
199 | void processTextureStats(); | 242 | void processTextureStats(); |
@@ -207,6 +250,7 @@ public: | |||
207 | // ONLY call from LLViewerImageList | 250 | // ONLY call from LLViewerImageList |
208 | BOOL createTexture(S32 usename = 0); | 251 | BOOL createTexture(S32 usename = 0); |
209 | void destroyTexture() ; | 252 | void destroyTexture() ; |
253 | void addToCreateTexture(); | ||
210 | 254 | ||
211 | BOOL needsAux() const { return mNeedsAux; } | 255 | BOOL needsAux() const { return mNeedsAux; } |
212 | 256 | ||
@@ -217,32 +261,12 @@ public: | |||
217 | void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } | 261 | void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } |
218 | 262 | ||
219 | // Host we think might have this image, used for baked av textures. | 263 | // Host we think might have this image, used for baked av textures. |
220 | void setTargetHost(LLHost host) { mTargetHost = host; } | ||
221 | LLHost getTargetHost() const { return mTargetHost; } | 264 | LLHost getTargetHost() const { return mTargetHost; } |
222 | 265 | ||
223 | enum | ||
224 | { | ||
225 | BOOST_NONE = 0, | ||
226 | BOOST_AVATAR_BAKED = 1, | ||
227 | BOOST_AVATAR = 2, | ||
228 | BOOST_CLOUDS = 3, | ||
229 | BOOST_SCULPTED = 4, | ||
230 | |||
231 | BOOST_HIGH = 10, | ||
232 | BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail | ||
233 | BOOST_SELECTED = 12, | ||
234 | BOOST_HUD = 13, | ||
235 | BOOST_AVATAR_BAKED_SELF = 14, | ||
236 | BOOST_UI = 15, | ||
237 | BOOST_PREVIEW = 16, | ||
238 | BOOST_MAP = 17, | ||
239 | BOOST_MAP_LAYER = 18, | ||
240 | BOOST_AVATAR_SELF = 19, // needed for baking avatar | ||
241 | BOOST_MAX_LEVEL | ||
242 | }; | ||
243 | void setBoostLevel(S32 level); | 266 | void setBoostLevel(S32 level); |
244 | S32 getBoostLevel() { return mBoostLevel; } | 267 | S32 getBoostLevel() { return mBoostLevel; } |
245 | 268 | ||
269 | void updateVirtualSize() ; | ||
246 | F32 getDecodePriority() const { return mDecodePriority; }; | 270 | F32 getDecodePriority() const { return mDecodePriority; }; |
247 | F32 calcDecodePriority(); | 271 | F32 calcDecodePriority(); |
248 | static F32 maxDecodePriority(); | 272 | static F32 maxDecodePriority(); |
@@ -271,6 +295,24 @@ public: | |||
271 | S32 getOriginalWidth() { return mOrigWidth; } | 295 | S32 getOriginalWidth() { return mOrigWidth; } |
272 | S32 getOriginalHeight() { return mOrigHeight; } | 296 | S32 getOriginalHeight() { return mOrigHeight; } |
273 | 297 | ||
298 | BOOL isForSculptOnly() const ; | ||
299 | void setForSculpt(); | ||
300 | |||
301 | void checkCachedRawSculptImage() ; | ||
302 | LLImageRaw* getRawImage()const { return mRawImage ;} | ||
303 | S32 getRawImageLevel() const {return mRawDiscardLevel;} | ||
304 | LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;} | ||
305 | S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} | ||
306 | BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} | ||
307 | BOOL isRawImageValid()const { return mIsRawImageValid ; } | ||
308 | |||
309 | void forceToSaveRawImage(S32 desired_discard = 0) ; | ||
310 | void destroySavedRawImage() ; | ||
311 | |||
312 | BOOL isSameTexture(const LLViewerImage* tex) const ; | ||
313 | |||
314 | void addFace(LLFace* facep) ; | ||
315 | void removeFace(LLFace* facep) ; | ||
274 | private: | 316 | private: |
275 | /*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it) | 317 | /*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it) |
276 | 318 | ||
@@ -279,14 +321,19 @@ private: | |||
279 | // Used to be in LLImageGL | 321 | // Used to be in LLImageGL |
280 | LLImageRaw* readBackRawImage(S8 discard_level = 0); | 322 | LLImageRaw* readBackRawImage(S8 discard_level = 0); |
281 | void destroyRawImage(); | 323 | void destroyRawImage(); |
282 | 324 | void saveRawImage() ; | |
325 | BOOL forceFetch() ; | ||
326 | |||
327 | void scaleDown() ; | ||
328 | void switchToCachedImage(); | ||
329 | void setCachedRawImage() ; | ||
283 | public: | 330 | public: |
284 | S32 mFullWidth; | 331 | S32 mFullWidth; |
285 | S32 mFullHeight; | 332 | S32 mFullHeight; |
286 | 333 | ||
287 | S32 mOrigWidth; | 334 | S32 mOrigWidth; |
288 | S32 mOrigHeight; | 335 | S32 mOrigHeight; |
289 | std::string mLocalFileName; | 336 | std::string mUrl; |
290 | 337 | ||
291 | // Data used for calculating required image priority/quality level/decimation | 338 | // Data used for calculating required image priority/quality level/decimation |
292 | mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? | 339 | mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? |
@@ -318,6 +365,7 @@ private: | |||
318 | S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space | 365 | S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space |
319 | S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have | 366 | S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have |
320 | S8 mNeedsCreateTexture; | 367 | S8 mNeedsCreateTexture; |
368 | mutable S8 mNeedsGLTexture; | ||
321 | S8 mNeedsAux; // We need to decode the auxiliary channels | 369 | S8 mNeedsAux; // We need to decode the auxiliary channels |
322 | S8 mDecodingAux; // Are we decoding high components | 370 | S8 mDecodingAux; // Are we decoding high components |
323 | S8 mIsRawImageValid; | 371 | S8 mIsRawImageValid; |
@@ -332,6 +380,7 @@ private: | |||
332 | S32 mKnownDrawHeight; | 380 | S32 mKnownDrawHeight; |
333 | 381 | ||
334 | F32 mDecodePriority; // The priority for decoding this image. | 382 | F32 mDecodePriority; // The priority for decoding this image. |
383 | mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. | ||
335 | S32 mBoostLevel; // enum describing priority level | 384 | S32 mBoostLevel; // enum describing priority level |
336 | 385 | ||
337 | typedef std::list<LLLoadedCallbackEntry*> callback_list_t; | 386 | typedef std::list<LLLoadedCallbackEntry*> callback_list_t; |
@@ -342,12 +391,30 @@ private: | |||
342 | S32 mMinDiscardLevel; | 391 | S32 mMinDiscardLevel; |
343 | F32 mCalculatedDiscardLevel; // Last calculated discard level | 392 | F32 mCalculatedDiscardLevel; // Last calculated discard level |
344 | 393 | ||
394 | //keep a copy of mRawImage for some special purposes | ||
395 | //when mForceToSaveRawImage is set. | ||
396 | BOOL mForceToSaveRawImage ; | ||
397 | LLPointer<LLImageRaw> mSavedRawImage; | ||
398 | S32 mSavedRawDiscardLevel; | ||
399 | S32 mDesiredSavedRawDiscardLevel; | ||
400 | |||
345 | // Used ONLY for cloth meshes right now. Make SURE you know what you're | 401 | // Used ONLY for cloth meshes right now. Make SURE you know what you're |
346 | // doing if you use it for anything else! - djs | 402 | // doing if you use it for anything else! - djs |
347 | LLPointer<LLImageRaw> mAuxRawImage; | 403 | LLPointer<LLImageRaw> mAuxRawImage; |
348 | 404 | ||
405 | //a small version of the copy of the raw image (<= 64 * 64) | ||
406 | LLPointer<LLImageRaw> mCachedRawImage; | ||
407 | S32 mCachedRawDiscardLevel; | ||
408 | BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. | ||
409 | |||
349 | LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator | 410 | LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator |
350 | 411 | ||
412 | BOOL mForSculpt ; //a flag if the texture is used for a sculpt data. | ||
413 | mutable BOOL mNeedsResetMaxVirtualSize ; | ||
414 | |||
415 | typedef std::list<LLFace*> ll_face_list_t ; | ||
416 | ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture | ||
417 | |||
351 | public: | 418 | public: |
352 | static const U32 sCurrentFileVersion; | 419 | static const U32 sCurrentFileVersion; |
353 | // Default textures | 420 | // Default textures |
@@ -361,6 +428,7 @@ public: | |||
361 | static S32 sRawCount; | 428 | static S32 sRawCount; |
362 | static S32 sAuxCount; | 429 | static S32 sAuxCount; |
363 | static LLTimer sEvaluationTimer; | 430 | static LLTimer sEvaluationTimer; |
431 | static S8 sCameraMovingDiscardBias; | ||
364 | static F32 sDesiredDiscardBias; | 432 | static F32 sDesiredDiscardBias; |
365 | static F32 sDesiredDiscardScale; | 433 | static F32 sDesiredDiscardScale; |
366 | static S32 sBoundTextureMemoryInBytes; | 434 | static S32 sBoundTextureMemoryInBytes; |
@@ -369,6 +437,12 @@ public: | |||
369 | static S32 sMaxTotalTextureMemInMegaBytes; | 437 | static S32 sMaxTotalTextureMemInMegaBytes; |
370 | static S32 sMaxDesiredTextureMemInBytes ; | 438 | static S32 sMaxDesiredTextureMemInBytes ; |
371 | static BOOL sDontLoadVolumeTextures; | 439 | static BOOL sDontLoadVolumeTextures; |
440 | |||
441 | static S32 sMaxSculptRez ; | ||
442 | static S32 sMinLargeImageSize ; | ||
443 | static S32 sMaxSmallImageSize ; | ||
444 | static BOOL sFreezeImageScalingDown ;//do not scale down image res if set. | ||
445 | static S32 sLLViewerImageCount ; | ||
372 | }; | 446 | }; |
373 | 447 | ||
374 | #endif | 448 | #endif |
diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index bd834a0..2280937 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "llimagetga.h" | 42 | #include "llimagetga.h" |
43 | #include "llimagejpeg.h" | 43 | #include "llimagejpeg.h" |
44 | #include "llimagepng.h" | 44 | #include "llimagepng.h" |
45 | #include "llimageworker.h" | ||
45 | 46 | ||
46 | #include "llsdserialize.h" | 47 | #include "llsdserialize.h" |
47 | #include "llsys.h" | 48 | #include "llsys.h" |
@@ -58,6 +59,7 @@ | |||
58 | #include "llviewerimage.h" | 59 | #include "llviewerimage.h" |
59 | #include "llviewermedia.h" | 60 | #include "llviewermedia.h" |
60 | #include "llviewerregion.h" | 61 | #include "llviewerregion.h" |
62 | #include "llviewerstats.h" | ||
61 | #include "pipeline.h" | 63 | #include "pipeline.h" |
62 | #include "llappviewer.h" | 64 | #include "llappviewer.h" |
63 | 65 | ||
@@ -70,11 +72,6 @@ void (*LLViewerImageList::sUUIDCallback)(void **, const LLUUID&) = NULL; | |||
70 | U32 LLViewerImageList::sTextureBits = 0; | 72 | U32 LLViewerImageList::sTextureBits = 0; |
71 | U32 LLViewerImageList::sTexturePackets = 0; | 73 | U32 LLViewerImageList::sTexturePackets = 0; |
72 | 74 | ||
73 | const S32 IMAGES_PER_REQUEST = 42; | ||
74 | const S32 IMAGES_MIN_UPDATES = 4; // Always update the highest N images each frame | ||
75 | const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_REQUEST in a frame | ||
76 | const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; // seconds | ||
77 | |||
78 | LLViewerImageList gImageList; | 75 | LLViewerImageList gImageList; |
79 | 76 | ||
80 | S32 LLViewerImageList::sNumImages = 0; | 77 | S32 LLViewerImageList::sNumImages = 0; |
@@ -182,6 +179,7 @@ static std::string get_texture_list_name() | |||
182 | 179 | ||
183 | void LLViewerImageList::doPrefetchImages() | 180 | void LLViewerImageList::doPrefetchImages() |
184 | { | 181 | { |
182 | #if 1 | ||
185 | if (LLAppViewer::instance()->getPurgeCache()) | 183 | if (LLAppViewer::instance()->getPurgeCache()) |
186 | { | 184 | { |
187 | // cache was purged, no point | 185 | // cache was purged, no point |
@@ -209,7 +207,7 @@ void LLViewerImageList::doPrefetchImages() | |||
209 | image->addTextureStats((F32)pixel_area); | 207 | image->addTextureStats((F32)pixel_area); |
210 | } | 208 | } |
211 | } | 209 | } |
212 | 210 | #endif | |
213 | 211 | ||
214 | } | 212 | } |
215 | 213 | ||
@@ -237,6 +235,10 @@ void LLViewerImageList::shutdown() | |||
237 | { | 235 | { |
238 | continue; // avoid UI, baked, and other special images | 236 | continue; // avoid UI, baked, and other special images |
239 | } | 237 | } |
238 | if(!image->getBoundRecently()) | ||
239 | { | ||
240 | continue ; | ||
241 | } | ||
240 | S32 desired = image->getDesiredDiscardLevel(); | 242 | S32 desired = image->getDesiredDiscardLevel(); |
241 | if (desired >= 0 && desired < MAX_DISCARD_LEVEL) | 243 | if (desired >= 0 && desired < MAX_DISCARD_LEVEL) |
242 | { | 244 | { |
@@ -323,17 +325,29 @@ LLViewerImage* LLViewerImageList::getImageFromFile(const std::string& filename, | |||
323 | LLGLenum primary_format, | 325 | LLGLenum primary_format, |
324 | const LLUUID& force_id) | 326 | const LLUUID& force_id) |
325 | { | 327 | { |
326 | if (gNoRender) | 328 | std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename); |
329 | if (full_path.empty()) | ||
327 | { | 330 | { |
328 | // Never mind that this ignores image_set_id; | 331 | llwarns << "Failed to find local image file: " << filename << llendl; |
329 | // getImage() will handle that later. | ||
330 | return getImage(IMG_DEFAULT, TRUE, TRUE); | 332 | return getImage(IMG_DEFAULT, TRUE, TRUE); |
331 | } | 333 | } |
332 | 334 | ||
333 | std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename); | 335 | std::string url = "file://" + full_path; |
334 | if (full_path.empty()) | 336 | |
337 | return getImageFromUrl(url, usemipmaps, level_immediate, internal_format, primary_format, force_id); | ||
338 | } | ||
339 | |||
340 | LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url, | ||
341 | BOOL usemipmaps, | ||
342 | BOOL level_immediate, | ||
343 | LLGLint internal_format, | ||
344 | LLGLenum primary_format, | ||
345 | const LLUUID& force_id) | ||
346 | { | ||
347 | if (gNoRender) | ||
335 | { | 348 | { |
336 | llwarns << "Failed to find local image file: " << filename << llendl; | 349 | // Never mind that this ignores image_set_id; |
350 | // getImage() will handle that later. | ||
337 | return getImage(IMG_DEFAULT, TRUE, TRUE); | 351 | return getImage(IMG_DEFAULT, TRUE, TRUE); |
338 | } | 352 | } |
339 | 353 | ||
@@ -345,14 +359,14 @@ LLViewerImage* LLViewerImageList::getImageFromFile(const std::string& filename, | |||
345 | } | 359 | } |
346 | else | 360 | else |
347 | { | 361 | { |
348 | new_id.generate(full_path); | 362 | new_id.generate(url); |
349 | } | 363 | } |
350 | 364 | ||
351 | LLPointer<LLViewerImage> imagep = hasImage(new_id); | 365 | LLPointer<LLViewerImage> imagep = hasImage(new_id); |
352 | 366 | ||
353 | if (imagep.isNull()) | 367 | if (imagep.isNull()) |
354 | { | 368 | { |
355 | imagep = new LLViewerImage(full_path, new_id, usemipmaps); | 369 | imagep = new LLViewerImage(url, new_id, usemipmaps); |
356 | 370 | ||
357 | if (internal_format && primary_format) | 371 | if (internal_format && primary_format) |
358 | { | 372 | { |
@@ -364,7 +378,7 @@ LLViewerImage* LLViewerImageList::getImageFromFile(const std::string& filename, | |||
364 | if (level_immediate) | 378 | if (level_immediate) |
365 | { | 379 | { |
366 | imagep->dontDiscard(); | 380 | imagep->dontDiscard(); |
367 | imagep->setBoostLevel(LLViewerImage::BOOST_UI); | 381 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_UI); |
368 | } | 382 | } |
369 | } | 383 | } |
370 | 384 | ||
@@ -394,9 +408,7 @@ LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id, | |||
394 | 408 | ||
395 | if (imagep.isNull()) | 409 | if (imagep.isNull()) |
396 | { | 410 | { |
397 | imagep = new LLViewerImage(image_id, usemipmaps); | 411 | imagep = new LLViewerImage(image_id, request_from_host, usemipmaps); |
398 | // Might want to request from host other than where the agent is. JC | ||
399 | imagep->setTargetHost(request_from_host); | ||
400 | 412 | ||
401 | if (internal_format && primary_format) | 413 | if (internal_format && primary_format) |
402 | { | 414 | { |
@@ -408,7 +420,7 @@ LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id, | |||
408 | if (level_immediate) | 420 | if (level_immediate) |
409 | { | 421 | { |
410 | imagep->dontDiscard(); | 422 | imagep->dontDiscard(); |
411 | imagep->setBoostLevel(LLViewerImage::BOOST_UI); | 423 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_UI); |
412 | } | 424 | } |
413 | else | 425 | else |
414 | { | 426 | { |
@@ -511,23 +523,29 @@ void LLViewerImageList::dirtyImage(LLViewerImage *image) | |||
511 | void LLViewerImageList::updateImages(F32 max_time) | 523 | void LLViewerImageList::updateImages(F32 max_time) |
512 | { | 524 | { |
513 | llpushcallstacks ; | 525 | llpushcallstacks ; |
526 | LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); | ||
527 | |||
514 | sNumImagesStat.addValue(sNumImages); | 528 | sNumImagesStat.addValue(sNumImages); |
515 | sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); | 529 | sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); |
516 | sGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); | 530 | sGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); |
517 | sGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); | 531 | sGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); |
518 | sRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); | 532 | sRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); |
519 | sFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); | 533 | sFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); |
520 | 534 | ||
521 | llpushcallstacks ; | 535 | llpushcallstacks ; |
536 | |||
522 | updateImagesDecodePriorities(); | 537 | updateImagesDecodePriorities(); |
538 | |||
523 | llpushcallstacks ; | 539 | llpushcallstacks ; |
540 | F32 total_max_time = max_time; | ||
524 | max_time -= updateImagesFetchTextures(max_time); | 541 | max_time -= updateImagesFetchTextures(max_time); |
542 | |||
525 | llpushcallstacks ; | 543 | llpushcallstacks ; |
526 | max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); | 544 | max_time = llmax(max_time, total_max_time*.25f); // at least 25% of max_time |
527 | max_time -= updateImagesCreateTextures(max_time); | 545 | max_time -= updateImagesCreateTextures(max_time); |
546 | |||
528 | llpushcallstacks ; | 547 | llpushcallstacks ; |
529 | max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); | 548 | |
530 | llpushcallstacks ; | ||
531 | if (!mDirtyTextureList.empty()) | 549 | if (!mDirtyTextureList.empty()) |
532 | { | 550 | { |
533 | LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); | 551 | LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); |
@@ -541,7 +559,7 @@ void LLViewerImageList::updateImages(F32 max_time) | |||
541 | { | 559 | { |
542 | //trigger loaded callbacks on local textures immediately | 560 | //trigger loaded callbacks on local textures immediately |
543 | LLViewerImage* image = *iter++; | 561 | LLViewerImage* image = *iter++; |
544 | if (!image->mLocalFileName.empty()) | 562 | if (!image->mUrl.empty()) |
545 | { | 563 | { |
546 | // Do stuff to handle callbacks, update priorities, etc. | 564 | // Do stuff to handle callbacks, update priorities, etc. |
547 | didone = image->doLoadedCallbacks(); | 565 | didone = image->doLoadedCallbacks(); |
@@ -627,7 +645,7 @@ void LLViewerImageList::updateImagesDecodePriorities() | |||
627 | imagep->setInactive() ; | 645 | imagep->setInactive() ; |
628 | } | 646 | } |
629 | } | 647 | } |
630 | 648 | ||
631 | imagep->processTextureStats(); | 649 | imagep->processTextureStats(); |
632 | F32 old_priority = imagep->getDecodePriority(); | 650 | F32 old_priority = imagep->getDecodePriority(); |
633 | F32 old_priority_test = llmax(old_priority, 0.0f); | 651 | F32 old_priority_test = llmax(old_priority, 0.0f); |
@@ -701,7 +719,7 @@ F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time) | |||
701 | return create_timer.getElapsedTimeF32(); | 719 | return create_timer.getElapsedTimeF32(); |
702 | } | 720 | } |
703 | 721 | ||
704 | void LLViewerImageList::forceImmediateUpdate(LLViewerImage* imagep) | 722 | void LLViewerImageList::bumpToMaxDecodePriority(LLViewerImage* imagep) |
705 | { | 723 | { |
706 | if(!imagep) | 724 | if(!imagep) |
707 | { | 725 | { |
@@ -709,6 +727,11 @@ void LLViewerImageList::forceImmediateUpdate(LLViewerImage* imagep) | |||
709 | } | 727 | } |
710 | if(imagep->mInImageList) | 728 | if(imagep->mInImageList) |
711 | { | 729 | { |
730 | if (imagep->getDecodePriority() == LLViewerImage::maxDecodePriority()) | ||
731 | { | ||
732 | // Already at maximum. | ||
733 | return; | ||
734 | } | ||
712 | removeImageFromList(imagep); | 735 | removeImageFromList(imagep); |
713 | } | 736 | } |
714 | 737 | ||
@@ -731,74 +754,76 @@ F32 LLViewerImageList::updateImagesFetchTextures(F32 max_time) | |||
731 | const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256); | 754 | const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256); |
732 | 755 | ||
733 | // 32 high priority entries | 756 | // 32 high priority entries |
734 | std::set<LLViewerImage*> entries; | 757 | typedef std::vector<LLViewerImage*> entries_list_t; |
758 | entries_list_t entries; | ||
735 | size_t update_counter = llmin(max_priority_count, mImageList.size()); | 759 | size_t update_counter = llmin(max_priority_count, mImageList.size()); |
736 | image_priority_list_t::iterator iter1 = mImageList.begin(); | 760 | image_priority_list_t::iterator iter1 = mImageList.begin(); |
737 | while(update_counter > 0) | 761 | while(update_counter > 0) |
738 | { | 762 | { |
739 | // added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad | 763 | entries.push_back(*iter1); |
740 | if(iter1 == mImageList.end()) | ||
741 | { | ||
742 | llerrs << "DEV-12002: update_counter not calculated correctly!" << llendl; | ||
743 | return 0.f; | ||
744 | } | ||
745 | |||
746 | LLPointer<LLViewerImage> const & ptr = *iter1; | ||
747 | |||
748 | LLViewerImage * img = ptr.get(); | ||
749 | |||
750 | // added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad | ||
751 | if(img == NULL) | ||
752 | { | ||
753 | llwarns << "DEV-12002: image is NULL!" << llendl; | ||
754 | } | ||
755 | |||
756 | entries.insert(img); | ||
757 | |||
758 | ++iter1; | 764 | ++iter1; |
759 | update_counter--; | 765 | update_counter--; |
760 | } | 766 | } |
761 | 767 | ||
762 | // 256 cycled entries | 768 | // 256 cycled entries |
763 | update_counter = llmin(max_update_count, mUUIDMap.size()); | 769 | update_counter = llmin(max_update_count, mUUIDMap.size()); |
764 | uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); | 770 | if (update_counter > 0) |
765 | while(update_counter > 0) | ||
766 | { | 771 | { |
767 | if (iter2 == mUUIDMap.end()) | 772 | uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); |
773 | uuid_map_t::iterator iter2p = iter2; | ||
774 | while(update_counter > 0) | ||
768 | { | 775 | { |
769 | iter2 = mUUIDMap.begin(); | 776 | if (iter2 == mUUIDMap.end()) |
777 | { | ||
778 | iter2 = mUUIDMap.begin(); | ||
779 | } | ||
780 | entries.push_back(iter2->second); | ||
781 | iter2p = iter2++; | ||
782 | update_counter--; | ||
770 | } | 783 | } |
771 | mLastFetchUUID = iter2->first; | 784 | mLastFetchUUID = iter2p->first; |
772 | entries.insert(iter2->second); | ||
773 | ++iter2; | ||
774 | update_counter--; | ||
775 | } | 785 | } |
776 | 786 | ||
787 | S32 fetch_count = 0; | ||
777 | S32 min_count = max_priority_count + max_update_count/4; | 788 | S32 min_count = max_priority_count + max_update_count/4; |
778 | for (std::set<LLViewerImage*>::iterator iter3 = entries.begin(); | 789 | for (entries_list_t::iterator iter3 = entries.begin(); |
779 | iter3 != entries.end(); ) | 790 | iter3 != entries.end(); ) |
780 | { | 791 | { |
781 | LLPointer<LLViewerImage> imagep = *iter3++; | 792 | LLPointer<LLViewerImage> imagep = *iter3++; |
782 | 793 | ||
783 | imagep->updateFetch(); | 794 | bool fetching = imagep->updateFetch(); |
795 | if (fetching) | ||
796 | { | ||
797 | fetch_count++; | ||
798 | } | ||
784 | if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time) | 799 | if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time) |
785 | { | 800 | { |
786 | break; | 801 | break; |
787 | } | 802 | } |
788 | min_count--; | 803 | min_count--; |
789 | } | 804 | } |
805 | if (fetch_count == 0) | ||
806 | { | ||
807 | gDebugTimers[0].pause(); | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | gDebugTimers[0].unpause(); | ||
812 | } | ||
813 | |||
814 | |||
790 | return image_op_timer.getElapsedTimeF32(); | 815 | return image_op_timer.getElapsedTimeF32(); |
791 | } | 816 | } |
792 | 817 | ||
793 | void LLViewerImageList::updateImagesUpdateStats() | 818 | void LLViewerImageList::updateImagesUpdateStats() |
794 | { | 819 | { |
795 | if (mUpdateStats) | 820 | if (mUpdateStats && mForceResetTextureStats) |
796 | { | 821 | { |
797 | for (image_priority_list_t::iterator iter = mImageList.begin(); | 822 | for (image_priority_list_t::iterator iter = mImageList.begin(); |
798 | iter != mImageList.end(); ) | 823 | iter != mImageList.end(); ) |
799 | { | 824 | { |
800 | LLViewerImage* imagep = *iter++; | 825 | LLViewerImage* imagep = *iter++; |
801 | imagep->resetTextureStats(mForceResetTextureStats); | 826 | imagep->resetTextureStats(); |
802 | } | 827 | } |
803 | mUpdateStats = FALSE; | 828 | mUpdateStats = FALSE; |
804 | mForceResetTextureStats = FALSE; | 829 | mForceResetTextureStats = FALSE; |
@@ -1348,7 +1373,7 @@ void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerImage *src_vi, LLImag | |||
1348 | 1373 | ||
1349 | // for images grabbed from local files, apply clipping rectangle to restore original dimensions | 1374 | // for images grabbed from local files, apply clipping rectangle to restore original dimensions |
1350 | // from power-of-2 gl image | 1375 | // from power-of-2 gl image |
1351 | if (success && imagep.notNull() && src_vi && !src_vi->mLocalFileName.empty()) | 1376 | if (success && imagep.notNull() && src_vi && (src_vi->mUrl.compare(0, 7, "file://")==0)) |
1352 | { | 1377 | { |
1353 | F32 clip_x = (F32)src_vi->getOriginalWidth() / (F32)src_vi->getWidth(0); | 1378 | F32 clip_x = (F32)src_vi->getOriginalWidth() / (F32)src_vi->getWidth(0); |
1354 | F32 clip_y = (F32)src_vi->getOriginalHeight() / (F32)src_vi->getHeight(0); | 1379 | F32 clip_y = (F32)src_vi->getOriginalHeight() / (F32)src_vi->getHeight(0); |
diff --git a/linden/indra/newview/llviewerimagelist.h b/linden/indra/newview/llviewerimagelist.h index 5fad0a2..561e8e5 100644 --- a/linden/indra/newview/llviewerimagelist.h +++ b/linden/indra/newview/llviewerimagelist.h | |||
@@ -97,7 +97,7 @@ public: | |||
97 | LLHost request_from_host = LLHost() | 97 | LLHost request_from_host = LLHost() |
98 | ); | 98 | ); |
99 | 99 | ||
100 | LLViewerImage * getImageFromFile(const std::string& filename, | 100 | LLViewerImage * getImageFromUrl(const std::string& url, |
101 | BOOL usemipmap = TRUE, | 101 | BOOL usemipmap = TRUE, |
102 | BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. | 102 | BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. |
103 | LLGLint internal_format = 0, | 103 | LLGLint internal_format = 0, |
@@ -105,6 +105,14 @@ public: | |||
105 | const LLUUID& force_id = LLUUID::null | 105 | const LLUUID& force_id = LLUUID::null |
106 | ); | 106 | ); |
107 | 107 | ||
108 | LLViewerImage * getImageFromFile(const std::string& filename, | ||
109 | BOOL usemipmap = TRUE, | ||
110 | BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. | ||
111 | LLGLint internal_format = 0, | ||
112 | LLGLenum primary_format = 0, | ||
113 | const LLUUID& force_id = LLUUID::null | ||
114 | ); | ||
115 | |||
108 | // Request image from a specific host, used for baked avatar textures. | 116 | // Request image from a specific host, used for baked avatar textures. |
109 | // Implemented in header in case someone changes default params above. JC | 117 | // Implemented in header in case someone changes default params above. JC |
110 | LLViewerImage* getImageFromHost(const LLUUID& image_id, LLHost host) | 118 | LLViewerImage* getImageFromHost(const LLUUID& image_id, LLHost host) |
@@ -121,7 +129,7 @@ public: | |||
121 | 129 | ||
122 | // Using image stats, determine what images are necessary, and perform image updates. | 130 | // Using image stats, determine what images are necessary, and perform image updates. |
123 | void updateImages(F32 max_time); | 131 | void updateImages(F32 max_time); |
124 | void forceImmediateUpdate(LLViewerImage* imagep) ; | 132 | void bumpToMaxDecodePriority(LLViewerImage* imagep) ; |
125 | 133 | ||
126 | // Decode and create textures for all images currently in list. | 134 | // Decode and create textures for all images currently in list. |
127 | void decodeAllImages(F32 max_decode_time); | 135 | void decodeAllImages(F32 max_decode_time); |
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 94ae3ab..8bdbc30 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp | |||
@@ -106,6 +106,7 @@ | |||
106 | #include "llstatenums.h" | 106 | #include "llstatenums.h" |
107 | #include "llstatusbar.h" | 107 | #include "llstatusbar.h" |
108 | #include "llimview.h" | 108 | #include "llimview.h" |
109 | #include "lltexturestats.h" | ||
109 | #include "lltool.h" | 110 | #include "lltool.h" |
110 | #include "lltoolbar.h" | 111 | #include "lltoolbar.h" |
111 | #include "lltoolmgr.h" | 112 | #include "lltoolmgr.h" |
diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index 51908a5..860052c 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp | |||
@@ -2900,7 +2900,7 @@ F32 LLViewerObject::getMidScale() const | |||
2900 | } | 2900 | } |
2901 | 2901 | ||
2902 | 2902 | ||
2903 | void LLViewerObject::updateTextures(LLAgent &agent) | 2903 | void LLViewerObject::updateTextures() |
2904 | { | 2904 | { |
2905 | } | 2905 | } |
2906 | 2906 | ||
@@ -2915,14 +2915,14 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) | |||
2915 | S32 tex_count = getNumTEs(); | 2915 | S32 tex_count = getNumTEs(); |
2916 | for (i = 0; i < tex_count; i++) | 2916 | for (i = 0; i < tex_count; i++) |
2917 | { | 2917 | { |
2918 | getTEImage(i)->setBoostLevel(LLViewerImage::BOOST_SELECTED); | 2918 | getTEImage(i)->setBoostLevel(LLViewerImageBoostLevel::BOOST_SELECTED); |
2919 | } | 2919 | } |
2920 | 2920 | ||
2921 | if (isSculpted()) | 2921 | if (isSculpted()) |
2922 | { | 2922 | { |
2923 | LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); | 2923 | LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); |
2924 | LLUUID sculpt_id = sculpt_params->getSculptTexture(); | 2924 | LLUUID sculpt_id = sculpt_params->getSculptTexture(); |
2925 | gImageList.getImage(sculpt_id)->setBoostLevel(LLViewerImage::BOOST_SELECTED); | 2925 | gImageList.getImage(sculpt_id)->setBoostLevel(LLViewerImageBoostLevel::BOOST_SELECTED); |
2926 | } | 2926 | } |
2927 | 2927 | ||
2928 | if (boost_children) | 2928 | if (boost_children) |
diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index 633e0eb..88f967f 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h | |||
@@ -190,7 +190,7 @@ public: | |||
190 | S32 getNumFaces() const { return mNumFaces; } | 190 | S32 getNumFaces() const { return mNumFaces; } |
191 | 191 | ||
192 | // Graphical stuff for objects - maybe broken out into render class later? | 192 | // Graphical stuff for objects - maybe broken out into render class later? |
193 | virtual void updateTextures(LLAgent &agent); | 193 | virtual void updateTextures(); |
194 | virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object | 194 | virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object |
195 | 195 | ||
196 | virtual LLDrawable* createDrawable(LLPipeline *pipeline); | 196 | virtual LLDrawable* createDrawable(LLPipeline *pipeline); |
diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index 059925e..3ac8fc4 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp | |||
@@ -612,7 +612,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) | |||
612 | 612 | ||
613 | // Update distance & gpw | 613 | // Update distance & gpw |
614 | objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area | 614 | objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area |
615 | objectp->updateTextures(agent); // Update the image levels of textures for this object. | 615 | objectp->updateTextures(); // Update the image levels of textures for this object. |
616 | } | 616 | } |
617 | } | 617 | } |
618 | 618 | ||
diff --git a/linden/indra/newview/llviewerparceloverlay.cpp b/linden/indra/newview/llviewerparceloverlay.cpp index 866c2a9..5cea9c2 100644 --- a/linden/indra/newview/llviewerparceloverlay.cpp +++ b/linden/indra/newview/llviewerparceloverlay.cpp | |||
@@ -71,7 +71,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ | |||
71 | // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges | 71 | // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges |
72 | mTexture = new LLImageGL(FALSE); | 72 | mTexture = new LLImageGL(FALSE); |
73 | mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS); | 73 | mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS); |
74 | mTexture->createGLTexture(0, mImageRaw); | 74 | mTexture->createGLTexture(0, mImageRaw, 0, TRUE, LLViewerImageBoostLevel::OTHER); |
75 | gGL.getTexUnit(0)->activate(); | 75 | gGL.getTexUnit(0)->activate(); |
76 | gGL.getTexUnit(0)->bind(mTexture); | 76 | gGL.getTexUnit(0)->bind(mTexture); |
77 | mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); | 77 | mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); |
diff --git a/linden/indra/newview/llviewerregion.cpp b/linden/indra/newview/llviewerregion.cpp index 19b646c..1d380d7 100644 --- a/linden/indra/newview/llviewerregion.cpp +++ b/linden/indra/newview/llviewerregion.cpp | |||
@@ -1408,9 +1408,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url) | |||
1408 | capabilityNames.append("EstateChangeInfo"); | 1408 | capabilityNames.append("EstateChangeInfo"); |
1409 | capabilityNames.append("EventQueueGet"); | 1409 | capabilityNames.append("EventQueueGet"); |
1410 | capabilityNames.append("FetchInventory"); | 1410 | capabilityNames.append("FetchInventory"); |
1411 | capabilityNames.append("WebFetchInventoryDescendents"); | ||
1412 | capabilityNames.append("FetchLib"); | 1411 | capabilityNames.append("FetchLib"); |
1413 | capabilityNames.append("FetchLibDescendents"); | 1412 | capabilityNames.append("FetchLibDescendents"); |
1413 | capabilityNames.append("GetTexture"); | ||
1414 | capabilityNames.append("GroupProposalBallot"); | 1414 | capabilityNames.append("GroupProposalBallot"); |
1415 | capabilityNames.append("HomeLocation"); | 1415 | capabilityNames.append("HomeLocation"); |
1416 | capabilityNames.append("MapLayer"); | 1416 | capabilityNames.append("MapLayer"); |
@@ -1429,6 +1429,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) | |||
1429 | capabilityNames.append("SendUserReportWithScreenshot"); | 1429 | capabilityNames.append("SendUserReportWithScreenshot"); |
1430 | capabilityNames.append("ServerReleaseNotes"); | 1430 | capabilityNames.append("ServerReleaseNotes"); |
1431 | capabilityNames.append("StartGroupProposal"); | 1431 | capabilityNames.append("StartGroupProposal"); |
1432 | capabilityNames.append("TextureStats"); | ||
1432 | capabilityNames.append("UntrustedSimulatorMessage"); | 1433 | capabilityNames.append("UntrustedSimulatorMessage"); |
1433 | capabilityNames.append("UpdateAgentInformation"); | 1434 | capabilityNames.append("UpdateAgentInformation"); |
1434 | capabilityNames.append("UpdateAgentLanguage"); | 1435 | capabilityNames.append("UpdateAgentLanguage"); |
@@ -1441,6 +1442,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) | |||
1441 | capabilityNames.append("UploadBakedTexture"); | 1442 | capabilityNames.append("UploadBakedTexture"); |
1442 | capabilityNames.append("ViewerStartAuction"); | 1443 | capabilityNames.append("ViewerStartAuction"); |
1443 | capabilityNames.append("ViewerStats"); | 1444 | capabilityNames.append("ViewerStats"); |
1445 | capabilityNames.append("WebFetchInventoryDescendents"); | ||
1444 | // Please add new capabilities alphabetically to reduce | 1446 | // Please add new capabilities alphabetically to reduce |
1445 | // merge conflicts. | 1447 | // merge conflicts. |
1446 | 1448 | ||
diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index ef4e728..3d884ad 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp | |||
@@ -115,6 +115,7 @@ | |||
115 | #include "llhudview.h" | 115 | #include "llhudview.h" |
116 | #include "llimagebmp.h" | 116 | #include "llimagebmp.h" |
117 | #include "llimagej2c.h" | 117 | #include "llimagej2c.h" |
118 | #include "llimageworker.h" | ||
118 | #include "llinventoryview.h" | 119 | #include "llinventoryview.h" |
119 | #include "llkeyboard.h" | 120 | #include "llkeyboard.h" |
120 | #include "lllineeditor.h" | 121 | #include "lllineeditor.h" |
@@ -1310,6 +1311,7 @@ LLViewerWindow::LLViewerWindow( | |||
1310 | 1311 | ||
1311 | // Init the image list. Must happen after GL is initialized and before the images that | 1312 | // Init the image list. Must happen after GL is initialized and before the images that |
1312 | // LLViewerWindow needs are requested. | 1313 | // LLViewerWindow needs are requested. |
1314 | LLImageGL::initClass(LLViewerImageBoostLevel::MAX_GL_IMAGE_CATEGORY) ; | ||
1313 | gImageList.init(); | 1315 | gImageList.init(); |
1314 | LLViewerImage::initClass(); | 1316 | LLViewerImage::initClass(); |
1315 | gBumpImageList.init(); | 1317 | gBumpImageList.init(); |
diff --git a/linden/indra/newview/llvlcomposition.cpp b/linden/indra/newview/llvlcomposition.cpp index a269225..9c383c7 100644 --- a/linden/indra/newview/llvlcomposition.cpp +++ b/linden/indra/newview/llvlcomposition.cpp | |||
@@ -234,7 +234,7 @@ BOOL LLVLComposition::generateComposition() | |||
234 | { | 234 | { |
235 | if (mDetailTextures[i]->getDiscardLevel() < 0) | 235 | if (mDetailTextures[i]->getDiscardLevel() < 0) |
236 | { | 236 | { |
237 | mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); // in case we are at low detail | 237 | mDetailTextures[i]->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); // in case we are at low detail |
238 | mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); | 238 | mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); |
239 | return FALSE; | 239 | return FALSE; |
240 | } | 240 | } |
@@ -251,7 +251,7 @@ BOOL LLVLComposition::generateComposition() | |||
251 | ddiscard++; | 251 | ddiscard++; |
252 | min_dim /= 2; | 252 | min_dim /= 2; |
253 | } | 253 | } |
254 | mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); // in case we are at low detail | 254 | mDetailTextures[i]->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); // in case we are at low detail |
255 | mDetailTextures[i]->setMinDiscardLevel(ddiscard); | 255 | mDetailTextures[i]->setMinDiscardLevel(ddiscard); |
256 | return FALSE; | 256 | return FALSE; |
257 | } | 257 | } |
@@ -292,10 +292,10 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, | |||
292 | ddiscard++; | 292 | ddiscard++; |
293 | min_dim /= 2; | 293 | min_dim /= 2; |
294 | } | 294 | } |
295 | if (!mDetailTextures[i]->readBackRaw(ddiscard, mRawImages[i], false)) | 295 | mRawImages[i] = mDetailTextures[i]->getCachedRawImage() ; |
296 | if (!mRawImages[i]) | ||
296 | { | 297 | { |
297 | llwarns << "Unable to read raw data for terrain detail texture: " << mDetailTextures[i]->getID() << llendl; | 298 | llwarns << "no cached raw data for terrain detail texture: " << mDetailTextures[i]->getID() << llendl; |
298 | mRawImages[i] = NULL; | ||
299 | return FALSE; | 299 | return FALSE; |
300 | } | 300 | } |
301 | if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || | 301 | if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || |
@@ -460,7 +460,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, | |||
460 | for (S32 i = 0; i < 4; i++) | 460 | for (S32 i = 0; i < 4; i++) |
461 | { | 461 | { |
462 | // Un-boost detatil textures (will get re-boosted if rendering in high detail) | 462 | // Un-boost detatil textures (will get re-boosted if rendering in high detail) |
463 | mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_NONE); | 463 | mDetailTextures[i]->setBoostLevel(LLViewerImageBoostLevel::BOOST_NONE); |
464 | mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); | 464 | mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); |
465 | } | 465 | } |
466 | 466 | ||
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index ab5d83e..d2f4a58 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp | |||
@@ -1272,6 +1272,49 @@ void LLVOAvatar::resetImpostors() | |||
1272 | // static | 1272 | // static |
1273 | void LLVOAvatar::deleteCachedImages(bool clearAll) | 1273 | void LLVOAvatar::deleteCachedImages(bool clearAll) |
1274 | { | 1274 | { |
1275 | if(gAuditTexture) | ||
1276 | { | ||
1277 | S32 total_tex_size = sScratchTexBytes ; | ||
1278 | S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; | ||
1279 | |||
1280 | if( LLVOAvatar::sScratchTexNames.checkData( GL_LUMINANCE ) ) | ||
1281 | { | ||
1282 | LLImageGL::decTextureCounterStatic(tex_size, 1, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1283 | total_tex_size -= tex_size ; | ||
1284 | } | ||
1285 | if( LLVOAvatar::sScratchTexNames.checkData( GL_ALPHA ) ) | ||
1286 | { | ||
1287 | LLImageGL::decTextureCounterStatic(tex_size, 1, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1288 | total_tex_size -= tex_size ; | ||
1289 | } | ||
1290 | if( LLVOAvatar::sScratchTexNames.checkData( GL_COLOR_INDEX ) ) | ||
1291 | { | ||
1292 | LLImageGL::decTextureCounterStatic(tex_size, 1, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1293 | total_tex_size -= tex_size ; | ||
1294 | } | ||
1295 | if( LLVOAvatar::sScratchTexNames.checkData( GL_LUMINANCE_ALPHA ) ) | ||
1296 | { | ||
1297 | LLImageGL::decTextureCounterStatic(tex_size, 2, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1298 | total_tex_size -= 2 * tex_size ; | ||
1299 | } | ||
1300 | if( LLVOAvatar::sScratchTexNames.checkData( GL_RGB ) ) | ||
1301 | { | ||
1302 | LLImageGL::decTextureCounterStatic(tex_size, 3, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1303 | total_tex_size -= 3 * tex_size ; | ||
1304 | } | ||
1305 | if( LLVOAvatar::sScratchTexNames.checkData( GL_RGBA ) ) | ||
1306 | { | ||
1307 | LLImageGL::decTextureCounterStatic(tex_size, 4, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1308 | total_tex_size -= 4 * tex_size ; | ||
1309 | } | ||
1310 | //others | ||
1311 | while(total_tex_size > 0) | ||
1312 | { | ||
1313 | LLImageGL::decTextureCounterStatic(tex_size, 4, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
1314 | total_tex_size -= 4 * tex_size ; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1275 | if (LLTexLayerSet::sHasCaches) | 1318 | if (LLTexLayerSet::sHasCaches) |
1276 | { | 1319 | { |
1277 | lldebugs << "Deleting layer set caches" << llendl; | 1320 | lldebugs << "Deleting layer set caches" << llendl; |
@@ -4701,7 +4744,7 @@ U32 LLVOAvatar::renderFootShadows() | |||
4701 | LLGLDepthTest test(GL_TRUE, GL_FALSE); | 4744 | LLGLDepthTest test(GL_TRUE, GL_FALSE); |
4702 | //render foot shadows | 4745 | //render foot shadows |
4703 | LLGLEnable blend(GL_BLEND); | 4746 | LLGLEnable blend(GL_BLEND); |
4704 | gGL.getTexUnit(0)->bind(mShadowImagep.get()); | 4747 | gGL.getTexUnit(0)->bind(mShadowImagep.get(), TRUE); |
4705 | glColor4fv(mShadow0Facep->getRenderColor().mV); | 4748 | glColor4fv(mShadow0Facep->getRenderColor().mV); |
4706 | mShadow0Facep->renderIndexed(foot_mask); | 4749 | mShadow0Facep->renderIndexed(foot_mask); |
4707 | glColor4fv(mShadow1Facep->getRenderColor().mV); | 4750 | glColor4fv(mShadow1Facep->getRenderColor().mV); |
@@ -4749,7 +4792,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) | |||
4749 | //------------------------------------------------------------------------ | 4792 | //------------------------------------------------------------------------ |
4750 | // LLVOAvatar::updateTextures() | 4793 | // LLVOAvatar::updateTextures() |
4751 | //------------------------------------------------------------------------ | 4794 | //------------------------------------------------------------------------ |
4752 | void LLVOAvatar::updateTextures(LLAgent &agent) | 4795 | void LLVOAvatar::updateTextures() |
4753 | { | 4796 | { |
4754 | BOOL render_avatar = TRUE; | 4797 | BOOL render_avatar = TRUE; |
4755 | 4798 | ||
@@ -4816,9 +4859,9 @@ void LLVOAvatar::updateTextures(LLAgent &agent) | |||
4816 | if (imagep) | 4859 | if (imagep) |
4817 | { | 4860 | { |
4818 | // Debugging code - maybe non-self avatars are downloading textures? | 4861 | // Debugging code - maybe non-self avatars are downloading textures? |
4819 | //llinfos << "avatar self " << mIsSelf << " tex " << i | 4862 | //llinfos << "avatar self " << mIsSelf << " tex " << index |
4820 | // << " decode " << imagep->getDecodePriority() | 4863 | // << " decode " << imagep->getDecodePriority() |
4821 | // << " boost " << boost_avatar | 4864 | // << " boost " << imagep->getBoostLevel() |
4822 | // << " size " << imagep->getWidth() << "x" << imagep->getHeight() | 4865 | // << " size " << imagep->getWidth() << "x" << imagep->getHeight() |
4823 | // << " discard " << imagep->getDiscardLevel() | 4866 | // << " discard " << imagep->getDiscardLevel() |
4824 | // << " desired " << imagep->getDesiredDiscardLevel() | 4867 | // << " desired " << imagep->getDesiredDiscardLevel() |
@@ -4826,7 +4869,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent) | |||
4826 | 4869 | ||
4827 | const LLTextureEntry *te = getTE(index); | 4870 | const LLTextureEntry *te = getTE(index); |
4828 | F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); | 4871 | F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); |
4829 | S32 boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_BAKED_SELF : LLViewerImage::BOOST_AVATAR_BAKED; | 4872 | S32 boost_level = mIsSelf ? LLViewerImageBoostLevel::BOOST_AVATAR_BAKED_SELF : LLViewerImageBoostLevel::BOOST_AVATAR_BAKED; |
4830 | 4873 | ||
4831 | // Spam if this is a baked texture, not set to default image, without valid host info | 4874 | // Spam if this is a baked texture, not set to default image, without valid host info |
4832 | if (isIndexBakedTexture((ETextureIndex)index) | 4875 | if (isIndexBakedTexture((ETextureIndex)index) |
@@ -4849,6 +4892,12 @@ void LLVOAvatar::updateTextures(LLAgent &agent) | |||
4849 | if (texture_dict->mIsLocalTexture) | 4892 | if (texture_dict->mIsLocalTexture) |
4850 | { | 4893 | { |
4851 | addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); | 4894 | addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); |
4895 | // SNOW-8 : temporary snowglobe1.0 fix for baked textures | ||
4896 | if (render_avatar && !gGLManager.mIsDisabled ) | ||
4897 | { | ||
4898 | // bind the texture so that its boost level won't be slammed | ||
4899 | gGL.getTexUnit(0)->bind(imagep); | ||
4900 | } | ||
4852 | } | 4901 | } |
4853 | else if (texture_dict->mIsBakedTexture) | 4902 | else if (texture_dict->mIsBakedTexture) |
4854 | { | 4903 | { |
@@ -4886,12 +4935,12 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep, | |||
4886 | if( mIsSelf ) | 4935 | if( mIsSelf ) |
4887 | { | 4936 | { |
4888 | desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); | 4937 | desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); |
4889 | imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF); | 4938 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_AVATAR_SELF); |
4890 | } | 4939 | } |
4891 | else | 4940 | else |
4892 | { | 4941 | { |
4893 | desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER ); | 4942 | desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER ); |
4894 | imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR); | 4943 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_AVATAR); |
4895 | } | 4944 | } |
4896 | imagep->addTextureStats( desired_pixels / texel_area_ratio ); | 4945 | imagep->addTextureStats( desired_pixels / texel_area_ratio ); |
4897 | if (imagep->getDiscardLevel() < 0) | 4946 | if (imagep->getDiscardLevel() < 0) |
@@ -7111,12 +7160,12 @@ BOOL LLVOAvatar::bindScratchTexture( LLGLenum format ) | |||
7111 | if( *last_bind_time != LLImageGL::sLastFrameTime ) | 7160 | if( *last_bind_time != LLImageGL::sLastFrameTime ) |
7112 | { | 7161 | { |
7113 | *last_bind_time = LLImageGL::sLastFrameTime; | 7162 | *last_bind_time = LLImageGL::sLastFrameTime; |
7114 | LLImageGL::updateBoundTexMem(texture_bytes); | 7163 | LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; |
7115 | } | 7164 | } |
7116 | } | 7165 | } |
7117 | else | 7166 | else |
7118 | { | 7167 | { |
7119 | LLImageGL::updateBoundTexMem(texture_bytes); | 7168 | LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; |
7120 | LLVOAvatar::sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) ); | 7169 | LLVOAvatar::sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) ); |
7121 | } | 7170 | } |
7122 | 7171 | ||
@@ -7138,7 +7187,8 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) | |||
7138 | { | 7187 | { |
7139 | case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break; | 7188 | case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break; |
7140 | case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break; | 7189 | case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break; |
7141 | case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; | 7190 | // Support for GL_EXT_paletted_texture is deprecated |
7191 | // case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; | ||
7142 | case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break; | 7192 | case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break; |
7143 | case GL_RGB: components = 3; internal_format = GL_RGB8; break; | 7193 | case GL_RGB: components = 3; internal_format = GL_RGB8; break; |
7144 | case GL_RGBA: components = 4; internal_format = GL_RGBA8; break; | 7194 | case GL_RGBA: components = 4; internal_format = GL_RGBA8; break; |
@@ -7180,6 +7230,12 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) | |||
7180 | 7230 | ||
7181 | LLVOAvatar::sScratchTexBytes += *texture_bytes; | 7231 | LLVOAvatar::sScratchTexBytes += *texture_bytes; |
7182 | LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes; | 7232 | LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes; |
7233 | |||
7234 | if(gAuditTexture) | ||
7235 | { | ||
7236 | LLImageGL::incTextureCounterStatic(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; | ||
7237 | } | ||
7238 | |||
7183 | return name; | 7239 | return name; |
7184 | } | 7240 | } |
7185 | } | 7241 | } |
@@ -7495,7 +7551,8 @@ void LLVOAvatar::clearChat() | |||
7495 | 7551 | ||
7496 | S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) | 7552 | S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) |
7497 | { | 7553 | { |
7498 | if (!isIndexLocalTexture(index)) return FALSE; | 7554 | // If the texture is not local, we don't care and treat it as fully loaded |
7555 | if (!isIndexLocalTexture(index)) return 0; | ||
7499 | 7556 | ||
7500 | LocalTextureData &local_tex_data = mLocalTextureData[index]; | 7557 | LocalTextureData &local_tex_data = mLocalTextureData[index]; |
7501 | if (index >= 0 | 7558 | if (index >= 0 |
diff --git a/linden/indra/newview/llvoavatar.h b/linden/indra/newview/llvoavatar.h index f759e15..33cec69 100644 --- a/linden/indra/newview/llvoavatar.h +++ b/linden/indra/newview/llvoavatar.h | |||
@@ -133,7 +133,7 @@ public: | |||
133 | LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point | 133 | LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point |
134 | ); | 134 | ); |
135 | 135 | ||
136 | /*virtual*/ void updateTextures(LLAgent &agent); | 136 | /*virtual*/ void updateTextures(); |
137 | // If setting a baked texture, need to request it from a non-local sim. | 137 | // If setting a baked texture, need to request it from a non-local sim. |
138 | /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); | 138 | /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); |
139 | /*virtual*/ void onShift(const LLVector3& shift_vector); | 139 | /*virtual*/ void onShift(const LLVector3& shift_vector); |
diff --git a/linden/indra/newview/llvoclouds.cpp b/linden/indra/newview/llvoclouds.cpp index 9095ee4..a489f91 100644 --- a/linden/indra/newview/llvoclouds.cpp +++ b/linden/indra/newview/llvoclouds.cpp | |||
@@ -62,7 +62,7 @@ LLVOClouds::LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re | |||
62 | mbCanSelect = FALSE; | 62 | mbCanSelect = FALSE; |
63 | setNumTEs(1); | 63 | setNumTEs(1); |
64 | LLViewerImage* image = gImageList.getImage(gCloudTextureID); | 64 | LLViewerImage* image = gImageList.getImage(gCloudTextureID); |
65 | image->setBoostLevel(LLViewerImage::BOOST_CLOUDS); | 65 | image->setBoostLevel(LLViewerImageBoostLevel::BOOST_CLOUDS); |
66 | setTEImage(0, image); | 66 | setTEImage(0, image); |
67 | } | 67 | } |
68 | 68 | ||
@@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent) | |||
101 | mPixelArea = 1500*100; | 101 | mPixelArea = 1500*100; |
102 | } | 102 | } |
103 | 103 | ||
104 | void LLVOClouds::updateTextures(LLAgent &agent) | 104 | void LLVOClouds::updateTextures() |
105 | { | 105 | { |
106 | getTEImage(0)->addTextureStats(mPixelArea); | 106 | getTEImage(0)->addTextureStats(mPixelArea); |
107 | } | 107 | } |
diff --git a/linden/indra/newview/llvoclouds.h b/linden/indra/newview/llvoclouds.h index f70ea5b..52e5a68 100644 --- a/linden/indra/newview/llvoclouds.h +++ b/linden/indra/newview/llvoclouds.h | |||
@@ -65,7 +65,7 @@ public: | |||
65 | /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. | 65 | /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. |
66 | F32 getPartSize(S32 idx); | 66 | F32 getPartSize(S32 idx); |
67 | 67 | ||
68 | /*virtual*/ void updateTextures(LLAgent &agent); | 68 | /*virtual*/ void updateTextures(); |
69 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area | 69 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area |
70 | 70 | ||
71 | void updateFaceSize(S32 idx) { } | 71 | void updateFaceSize(S32 idx) { } |
diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index dd4dabb..d0a36b0 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp | |||
@@ -339,7 +339,7 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent) | |||
339 | 339 | ||
340 | 340 | ||
341 | // BUG could speed this up by caching the relative_position and range calculations | 341 | // BUG could speed this up by caching the relative_position and range calculations |
342 | void LLVOGrass::updateTextures(LLAgent &agent) | 342 | void LLVOGrass::updateTextures() |
343 | { | 343 | { |
344 | if (getTEImage(0)) | 344 | if (getTEImage(0)) |
345 | { | 345 | { |
diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index b759488..abfc7e1 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h | |||
@@ -72,7 +72,7 @@ public: | |||
72 | LLStrider<U16>& indicesp); | 72 | LLStrider<U16>& indicesp); |
73 | 73 | ||
74 | void updateFaceSize(S32 idx) { } | 74 | void updateFaceSize(S32 idx) { } |
75 | /*virtual*/ void updateTextures(LLAgent &agent); | 75 | /*virtual*/ void updateTextures(); |
76 | /*virtual*/ BOOL updateLOD(); | 76 | /*virtual*/ BOOL updateLOD(); |
77 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area | 77 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area |
78 | 78 | ||
diff --git a/linden/indra/newview/llvoground.cpp b/linden/indra/newview/llvoground.cpp index fe19e18..0ef0196 100644 --- a/linden/indra/newview/llvoground.cpp +++ b/linden/indra/newview/llvoground.cpp | |||
@@ -71,7 +71,7 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | 73 | ||
74 | void LLVOGround::updateTextures(LLAgent &agent) | 74 | void LLVOGround::updateTextures() |
75 | { | 75 | { |
76 | } | 76 | } |
77 | 77 | ||
diff --git a/linden/indra/newview/llvoground.h b/linden/indra/newview/llvoground.h index f485bd0..b58ebae 100644 --- a/linden/indra/newview/llvoground.h +++ b/linden/indra/newview/llvoground.h | |||
@@ -51,7 +51,7 @@ public: | |||
51 | 51 | ||
52 | // Graphical stuff for objects - maybe broken out into render class | 52 | // Graphical stuff for objects - maybe broken out into render class |
53 | // later? | 53 | // later? |
54 | /*virtual*/ void updateTextures(LLAgent &agent); | 54 | /*virtual*/ void updateTextures(); |
55 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 55 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
56 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 56 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
57 | 57 | ||
diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp index 29036f4..a0f8068 100644 --- a/linden/indra/newview/llvopartgroup.cpp +++ b/linden/indra/newview/llvopartgroup.cpp | |||
@@ -108,7 +108,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) | |||
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | void LLVOPartGroup::updateTextures(LLAgent &agent) | 111 | void LLVOPartGroup::updateTextures() |
112 | { | 112 | { |
113 | // Texture stats for particles need to be updated in a different way... | 113 | // Texture stats for particles need to be updated in a different way... |
114 | } | 114 | } |
diff --git a/linden/indra/newview/llvopartgroup.h b/linden/indra/newview/llvopartgroup.h index 3dc3292..18583b4 100644 --- a/linden/indra/newview/llvopartgroup.h +++ b/linden/indra/newview/llvopartgroup.h | |||
@@ -61,7 +61,7 @@ public: | |||
61 | virtual U32 getPartitionType() const; | 61 | virtual U32 getPartitionType() const; |
62 | 62 | ||
63 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); | 63 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); |
64 | /*virtual*/ void updateTextures(LLAgent &agent); | 64 | /*virtual*/ void updateTextures(); |
65 | 65 | ||
66 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 66 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
67 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 67 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp index d4df141..1b9c7c0 100644 --- a/linden/indra/newview/llvosky.cpp +++ b/linden/indra/newview/llvosky.cpp | |||
@@ -289,7 +289,7 @@ void LLSkyTex::create(const F32 brightness) | |||
289 | 289 | ||
290 | void LLSkyTex::createGLImage(S32 which) | 290 | void LLSkyTex::createGLImage(S32 which) |
291 | { | 291 | { |
292 | mImageGL[which]->createGLTexture(0, mImageRaw[which]); | 292 | mImageGL[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerImageBoostLevel::OTHER); |
293 | mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); | 293 | mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); |
294 | } | 294 | } |
295 | 295 | ||
@@ -1180,7 +1180,7 @@ BOOL LLVOSky::updateSky() | |||
1180 | return TRUE; | 1180 | return TRUE; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | void LLVOSky::updateTextures(LLAgent &agent) | 1183 | void LLVOSky::updateTextures() |
1184 | { | 1184 | { |
1185 | if (mSunTexturep) | 1185 | if (mSunTexturep) |
1186 | { | 1186 | { |
diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h index 3cf454d..333e144 100644 --- a/linden/indra/newview/llvosky.h +++ b/linden/indra/newview/llvosky.h | |||
@@ -492,7 +492,7 @@ public: | |||
492 | 492 | ||
493 | // Graphical stuff for objects - maybe broken out into render class | 493 | // Graphical stuff for objects - maybe broken out into render class |
494 | // later? | 494 | // later? |
495 | /*virtual*/ void updateTextures(LLAgent &agent); | 495 | /*virtual*/ void updateTextures(); |
496 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 496 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
497 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 497 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
498 | 498 | ||
diff --git a/linden/indra/newview/llvosurfacepatch.cpp b/linden/indra/newview/llvosurfacepatch.cpp index 4980b50..d86f758 100644 --- a/linden/indra/newview/llvosurfacepatch.cpp +++ b/linden/indra/newview/llvosurfacepatch.cpp | |||
@@ -134,7 +134,7 @@ void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | 136 | ||
137 | void LLVOSurfacePatch::updateTextures(LLAgent &agent) | 137 | void LLVOSurfacePatch::updateTextures() |
138 | { | 138 | { |
139 | } | 139 | } |
140 | 140 | ||
diff --git a/linden/indra/newview/llvosurfacepatch.h b/linden/indra/newview/llvosurfacepatch.h index 2dd8651..d3b1447 100644 --- a/linden/indra/newview/llvosurfacepatch.h +++ b/linden/indra/newview/llvosurfacepatch.h | |||
@@ -74,7 +74,7 @@ public: | |||
74 | LLStrider<LLVector2> &texCoords1p, | 74 | LLStrider<LLVector2> &texCoords1p, |
75 | LLStrider<U16> &indicesp); | 75 | LLStrider<U16> &indicesp); |
76 | 76 | ||
77 | /*virtual*/ void updateTextures(LLAgent &agent); | 77 | /*virtual*/ void updateTextures(); |
78 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area | 78 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area |
79 | 79 | ||
80 | /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); | 80 | /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); |
diff --git a/linden/indra/newview/llvotextbubble.cpp b/linden/indra/newview/llvotextbubble.cpp index de69aac..5943f9b 100644 --- a/linden/indra/newview/llvotextbubble.cpp +++ b/linden/indra/newview/llvotextbubble.cpp | |||
@@ -116,7 +116,7 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | 118 | ||
119 | void LLVOTextBubble::updateTextures(LLAgent &agent) | 119 | void LLVOTextBubble::updateTextures() |
120 | { | 120 | { |
121 | // Update the image levels of all textures... | 121 | // Update the image levels of all textures... |
122 | 122 | ||
diff --git a/linden/indra/newview/llvotextbubble.h b/linden/indra/newview/llvotextbubble.h index 45d4df2..7f84dbf 100644 --- a/linden/indra/newview/llvotextbubble.h +++ b/linden/indra/newview/llvotextbubble.h | |||
@@ -44,7 +44,7 @@ public: | |||
44 | /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. | 44 | /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. |
45 | /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); | 45 | /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); |
46 | 46 | ||
47 | /*virtual*/ void updateTextures(LLAgent &agent); | 47 | /*virtual*/ void updateTextures(); |
48 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 48 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
49 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 49 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
50 | /*virtual*/ BOOL updateLOD(); | 50 | /*virtual*/ BOOL updateLOD(); |
diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 3523d87..237f581 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp | |||
@@ -475,7 +475,7 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) | |||
475 | #endif | 475 | #endif |
476 | } | 476 | } |
477 | 477 | ||
478 | void LLVOTree::updateTextures(LLAgent &agent) | 478 | void LLVOTree::updateTextures() |
479 | { | 479 | { |
480 | if (mTreeImagep) | 480 | if (mTreeImagep) |
481 | { | 481 | { |
diff --git a/linden/indra/newview/llvotree.h b/linden/indra/newview/llvotree.h index 748fc14..df0b5a9 100644 --- a/linden/indra/newview/llvotree.h +++ b/linden/indra/newview/llvotree.h | |||
@@ -69,7 +69,7 @@ public: | |||
69 | // Graphical stuff for objects - maybe broken out into render class later? | 69 | // Graphical stuff for objects - maybe broken out into render class later? |
70 | /*virtual*/ void render(LLAgent &agent); | 70 | /*virtual*/ void render(LLAgent &agent); |
71 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); | 71 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); |
72 | /*virtual*/ void updateTextures(LLAgent &agent); | 72 | /*virtual*/ void updateTextures(); |
73 | 73 | ||
74 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 74 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
75 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 75 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
diff --git a/linden/indra/newview/llvotreenew.h b/linden/indra/newview/llvotreenew.h index 02f6d3a..4960d90 100644 --- a/linden/indra/newview/llvotreenew.h +++ b/linden/indra/newview/llvotreenew.h | |||
@@ -156,7 +156,7 @@ public: | |||
156 | /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); | 156 | /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); |
157 | 157 | ||
158 | /*virtual*/ void render(LLAgent &agent); | 158 | /*virtual*/ void render(LLAgent &agent); |
159 | /*virtual*/ void updateTextures(LLAgent &agent); | 159 | /*virtual*/ void updateTextures(); |
160 | 160 | ||
161 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); | 161 | /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); |
162 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 162 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 607bb42..5f7327d 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp | |||
@@ -52,12 +52,10 @@ | |||
52 | #include "lldrawpoolbump.h" | 52 | #include "lldrawpoolbump.h" |
53 | #include "llface.h" | 53 | #include "llface.h" |
54 | #include "llspatialpartition.h" | 54 | #include "llspatialpartition.h" |
55 | |||
56 | // TEMP HACK ventrella | ||
57 | #include "llhudmanager.h" | 55 | #include "llhudmanager.h" |
58 | #include "llflexibleobject.h" | 56 | #include "llflexibleobject.h" |
59 | |||
60 | #include "llsky.h" | 57 | #include "llsky.h" |
58 | #include "lltexturefetch.h" | ||
61 | #include "llviewercamera.h" | 59 | #include "llviewercamera.h" |
62 | #include "llviewerimagelist.h" | 60 | #include "llviewerimagelist.h" |
63 | #include "llviewerregion.h" | 61 | #include "llviewerregion.h" |
@@ -69,7 +67,6 @@ | |||
69 | const S32 MIN_QUIET_FRAMES_COALESCE = 30; | 67 | const S32 MIN_QUIET_FRAMES_COALESCE = 30; |
70 | const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; | 68 | const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; |
71 | const F32 FORCE_CULL_AREA = 8.f; | 69 | const F32 FORCE_CULL_AREA = 8.f; |
72 | const S32 MAX_SCULPT_REZ = 128; | ||
73 | 70 | ||
74 | BOOL gAnimateTextures = TRUE; | 71 | BOOL gAnimateTextures = TRUE; |
75 | extern BOOL gHideSelectedObjects; | 72 | extern BOOL gHideSelectedObjects; |
@@ -406,28 +403,30 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | |||
406 | return TRUE; | 403 | return TRUE; |
407 | } | 404 | } |
408 | 405 | ||
409 | void LLVOVolume::updateTextures(LLAgent &agent) | 406 | void LLVOVolume::updateTextures() |
410 | { | 407 | { |
411 | const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds | 408 | const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds |
412 | if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) | 409 | if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) |
413 | { | 410 | { |
414 | if (mDrawable->isVisible()) | 411 | updateTextureVirtualSize(); |
415 | { | ||
416 | updateTextures(); | ||
417 | } | ||
418 | } | 412 | } |
419 | } | 413 | } |
420 | 414 | ||
421 | void LLVOVolume::updateTextures() | 415 | void LLVOVolume::updateTextureVirtualSize() |
422 | { | 416 | { |
423 | // Update the pixel area of all faces | 417 | // Update the pixel area of all faces |
424 | 418 | ||
419 | if(mDrawable.isNull() || !mDrawable->isVisible()) | ||
420 | { | ||
421 | return ; | ||
422 | } | ||
423 | |||
425 | if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) | 424 | if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) |
426 | { | 425 | { |
427 | return; | 426 | return; |
428 | } | 427 | } |
429 | 428 | ||
430 | if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) | 429 | if (LLViewerImage::sDontLoadVolumeTextures || LLAppViewer::getTextureFetch()->mDebugPause) |
431 | { | 430 | { |
432 | return; | 431 | return; |
433 | } | 432 | } |
@@ -444,53 +443,51 @@ void LLVOVolume::updateTextures() | |||
444 | LLFace* face = mDrawable->getFace(i); | 443 | LLFace* face = mDrawable->getFace(i); |
445 | const LLTextureEntry *te = face->getTextureEntry(); | 444 | const LLTextureEntry *te = face->getTextureEntry(); |
446 | LLViewerImage *imagep = face->getTexture(); | 445 | LLViewerImage *imagep = face->getTexture(); |
447 | if (!imagep || !te || | 446 | if (!imagep || !te || |
448 | face->mExtents[0] == face->mExtents[1]) | 447 | face->mExtents[0] == face->mExtents[1]) |
449 | { | 448 | { |
450 | continue; | 449 | continue; |
451 | } | 450 | } |
452 | 451 | ||
453 | F32 vsize; | 452 | F32 vsize; |
454 | 453 | F32 old_size = face->getVirtualSize(); | |
454 | |||
455 | if (isHUDAttachment()) | 455 | if (isHUDAttachment()) |
456 | { | 456 | { |
457 | F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); | 457 | F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); |
458 | vsize = area; | 458 | vsize = area; |
459 | imagep->setBoostLevel(LLViewerImage::BOOST_HUD); | 459 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_HUD); |
460 | face->setPixelArea(area); // treat as full screen | 460 | face->setPixelArea(area); // treat as full screen |
461 | } | 461 | } |
462 | else | 462 | else |
463 | { | 463 | { |
464 | vsize = getTextureVirtualSize(face); | 464 | vsize = face->getTextureVirtualSize(); |
465 | } | 465 | } |
466 | 466 | ||
467 | mPixelArea = llmax(mPixelArea, face->getPixelArea()); | 467 | mPixelArea = llmax(mPixelArea, face->getPixelArea()); |
468 | |||
469 | F32 old_size = face->getVirtualSize(); | ||
470 | 468 | ||
471 | if (face->mTextureMatrix != NULL) | 469 | if (face->mTextureMatrix != NULL) |
472 | { | 470 | { |
473 | if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || | 471 | if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || |
474 | vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE) | 472 | (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) |
475 | { | 473 | { |
476 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); | 474 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); |
477 | } | 475 | } |
478 | } | 476 | } |
479 | 477 | ||
480 | face->setVirtualSize(vsize); | 478 | face->setVirtualSize(vsize); |
481 | imagep->addTextureStats(vsize); | ||
482 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) | 479 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) |
483 | { | 480 | { |
484 | if (vsize < min_vsize) min_vsize = vsize; | 481 | if (vsize < min_vsize) min_vsize = vsize; |
485 | if (vsize > max_vsize) max_vsize = vsize; | 482 | if (vsize > max_vsize) max_vsize = vsize; |
486 | } | 483 | } |
487 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) | 484 | // else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) |
488 | { | 485 | // { |
489 | F32 pri = imagep->getDecodePriority(); | 486 | // F32 pri = imagep->getDecodePriority(); |
490 | pri = llmax(pri, 0.0f); | 487 | // pri = llmax(pri, 0.0f); |
491 | if (pri < min_vsize) min_vsize = pri; | 488 | // if (pri < min_vsize) min_vsize = pri; |
492 | if (pri > max_vsize) max_vsize = pri; | 489 | // if (pri > max_vsize) max_vsize = pri; |
493 | } | 490 | // } |
494 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) | 491 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) |
495 | { | 492 | { |
496 | F32 pri = mPixelArea; | 493 | F32 pri = mPixelArea; |
@@ -506,31 +503,44 @@ void LLVOVolume::updateTextures() | |||
506 | mSculptTexture = gImageList.getImage(id); | 503 | mSculptTexture = gImageList.getImage(id); |
507 | if (mSculptTexture.notNull()) | 504 | if (mSculptTexture.notNull()) |
508 | { | 505 | { |
509 | S32 lod = llmin(mLOD, 3); | ||
510 | F32 lodf = ((F32)(lod + 1.0f)/4.f); | ||
511 | F32 tex_size = lodf * MAX_SCULPT_REZ; | ||
512 | mSculptTexture->addTextureStats(2.f * tex_size * tex_size); | ||
513 | mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), | 506 | mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), |
514 | (S32)LLViewerImage::BOOST_SCULPTED)); | 507 | (S32)LLViewerImageBoostLevel::BOOST_SCULPTED)); |
515 | } | 508 | mSculptTexture->setForSculpt() ; |
516 | 509 | ||
517 | S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture | 510 | if(!mSculptTexture->isCachedRawImageReady()) |
518 | S32 current_discard = mSculptLevel; | 511 | { |
512 | S32 lod = llmin(mLOD, 3); | ||
513 | F32 lodf = ((F32)(lod + 1.0f)/4.f); | ||
514 | F32 tex_size = lodf * LLViewerImage::sMaxSculptRez ; | ||
515 | mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); | ||
516 | |||
517 | //if the sculpty very close to the view point, load first | ||
518 | { | ||
519 | LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin(); | ||
520 | F32 dist = lookAt.normVec() ; | ||
521 | F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; | ||
522 | mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture | ||
527 | S32 current_discard = mSculptLevel; | ||
519 | 528 | ||
520 | if (texture_discard >= 0 && //texture has some data available | 529 | if (texture_discard >= 0 && //texture has some data available |
521 | (texture_discard < current_discard || //texture has more data than last rebuild | 530 | (texture_discard < current_discard || //texture has more data than last rebuild |
522 | current_discard < 0)) //no previous rebuild | 531 | current_discard < 0)) //no previous rebuild |
523 | { | 532 | { |
524 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); | 533 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); |
525 | mSculptChanged = TRUE; | 534 | mSculptChanged = TRUE; |
526 | } | 535 | } |
527 | 536 | ||
528 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) | 537 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) |
529 | { | 538 | { |
530 | setDebugText(llformat("T%d C%d V%d\n%dx%d", | 539 | setDebugText(llformat("T%d C%d V%d\n%dx%d", |
531 | texture_discard, current_discard, getVolume()->getSculptLevel(), | 540 | texture_discard, current_discard, getVolume()->getSculptLevel(), |
532 | mSculptTexture->getHeight(), mSculptTexture->getWidth())); | 541 | mSculptTexture->getHeight(), mSculptTexture->getWidth())); |
533 | } | 542 | } |
543 | } | ||
534 | } | 544 | } |
535 | 545 | ||
536 | 546 | ||
@@ -538,10 +548,10 @@ void LLVOVolume::updateTextures() | |||
538 | { | 548 | { |
539 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | 549 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); |
540 | } | 550 | } |
541 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) | 551 | // else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) |
542 | { | 552 | // { |
543 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | 553 | // setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); |
544 | } | 554 | // } |
545 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) | 555 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) |
546 | { | 556 | { |
547 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | 557 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); |
@@ -553,36 +563,6 @@ void LLVOVolume::updateTextures() | |||
553 | } | 563 | } |
554 | } | 564 | } |
555 | 565 | ||
556 | F32 LLVOVolume::getTextureVirtualSize(LLFace* face) | ||
557 | { | ||
558 | //get area of circle around face | ||
559 | LLVector3 center = face->getPositionAgent(); | ||
560 | LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; | ||
561 | |||
562 | F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); | ||
563 | |||
564 | face->setPixelArea(face_area); | ||
565 | |||
566 | if (face_area <= 0) | ||
567 | { | ||
568 | return 0.f; | ||
569 | } | ||
570 | |||
571 | //get area of circle in texture space | ||
572 | LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; | ||
573 | F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; | ||
574 | if (texel_area <= 0) | ||
575 | { | ||
576 | // Probably animated, use default | ||
577 | texel_area = 1.f; | ||
578 | } | ||
579 | |||
580 | //apply texel area to face area to get accurate ratio | ||
581 | face_area /= llclamp(texel_area, 1.f/64.f, 16.f); | ||
582 | |||
583 | return face_area; | ||
584 | } | ||
585 | |||
586 | BOOL LLVOVolume::isActive() const | 566 | BOOL LLVOVolume::isActive() const |
587 | { | 567 | { |
588 | return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()); | 568 | return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()); |
@@ -719,31 +699,21 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail | |||
719 | 699 | ||
720 | // sculpt replaces generate() for sculpted surfaces | 700 | // sculpt replaces generate() for sculpted surfaces |
721 | void LLVOVolume::sculpt() | 701 | void LLVOVolume::sculpt() |
722 | { | 702 | { |
723 | U16 sculpt_height = 0; | ||
724 | U16 sculpt_width = 0; | ||
725 | S8 sculpt_components = 0; | ||
726 | const U8* sculpt_data = NULL; | ||
727 | |||
728 | if (mSculptTexture.notNull()) | 703 | if (mSculptTexture.notNull()) |
729 | { | 704 | { |
730 | S32 discard_level; | 705 | U16 sculpt_height = 0; |
731 | S32 desired_discard = 0; // lower discard levels have MUCH less resolution | 706 | U16 sculpt_width = 0; |
732 | 707 | S8 sculpt_components = 0; | |
733 | discard_level = desired_discard; | 708 | const U8* sculpt_data = NULL; |
709 | |||
710 | S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; | ||
711 | LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; | ||
734 | 712 | ||
735 | S32 max_discard = mSculptTexture->getMaxDiscardLevel(); | 713 | S32 max_discard = mSculptTexture->getMaxDiscardLevel(); |
736 | if (discard_level > max_discard) | 714 | if (discard_level > max_discard) |
737 | discard_level = max_discard; // clamp to the best we can do | 715 | discard_level = max_discard; // clamp to the best we can do |
738 | 716 | ||
739 | S32 best_discard = mSculptTexture->getDiscardLevel(); | ||
740 | if (discard_level < best_discard) | ||
741 | discard_level = best_discard; // clamp to what we have | ||
742 | |||
743 | if (best_discard == -1) | ||
744 | discard_level = -1; // and if we have nothing, set to nothing | ||
745 | |||
746 | |||
747 | S32 current_discard = getVolume()->getSculptLevel(); | 717 | S32 current_discard = getVolume()->getSculptLevel(); |
748 | if(current_discard < -2) | 718 | if(current_discard < -2) |
749 | { | 719 | { |
@@ -765,28 +735,17 @@ void LLVOVolume::sculpt() | |||
765 | if (current_discard == discard_level) // no work to do here | 735 | if (current_discard == discard_level) // no work to do here |
766 | return; | 736 | return; |
767 | 737 | ||
768 | LLPointer<LLImageRaw> raw_image = new LLImageRaw(); | 738 | if(!raw_image) |
769 | BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE); | ||
770 | |||
771 | sculpt_height = raw_image->getHeight(); | ||
772 | sculpt_width = raw_image->getWidth(); | ||
773 | sculpt_components = raw_image->getComponents(); | ||
774 | |||
775 | if(is_valid) | ||
776 | { | ||
777 | is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ; | ||
778 | } | ||
779 | if(!is_valid) | ||
780 | { | 739 | { |
781 | sculpt_width = 0; | 740 | sculpt_width = 0; |
782 | sculpt_height = 0; | 741 | sculpt_height = 0; |
783 | sculpt_data = NULL ; | 742 | sculpt_data = NULL ; |
784 | } | 743 | } |
785 | else | 744 | else |
786 | { | 745 | { |
787 | if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components) | 746 | sculpt_height = raw_image->getHeight(); |
788 | llerrs << "Sculpt: image data size = " << raw_image->getDataSize() | 747 | sculpt_width = raw_image->getWidth(); |
789 | << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl; | 748 | sculpt_components = raw_image->getComponents(); |
790 | 749 | ||
791 | sculpt_data = raw_image->getData(); | 750 | sculpt_data = raw_image->getData(); |
792 | } | 751 | } |
@@ -818,7 +777,7 @@ BOOL LLVOVolume::calcLOD() | |||
818 | } | 777 | } |
819 | 778 | ||
820 | //update face texture sizes on lod calculation | 779 | //update face texture sizes on lod calculation |
821 | updateTextures(); | 780 | updateTextureVirtualSize(); |
822 | 781 | ||
823 | S32 cur_detail = 0; | 782 | S32 cur_detail = 0; |
824 | 783 | ||
@@ -2295,7 +2254,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) | |||
2295 | 2254 | ||
2296 | LLVOVolume* vobj = drawablep->getVOVolume(); | 2255 | LLVOVolume* vobj = drawablep->getVOVolume(); |
2297 | llassert_always(vobj); | 2256 | llassert_always(vobj); |
2298 | vobj->updateTextures(); | 2257 | vobj->updateTextureVirtualSize(); |
2299 | vobj->preRebuild(); | 2258 | vobj->preRebuild(); |
2300 | 2259 | ||
2301 | //for each face | 2260 | //for each face |
@@ -2399,7 +2358,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) | |||
2399 | { //needs normal + binormal | 2358 | { //needs normal + binormal |
2400 | bump_faces.push_back(facep); | 2359 | bump_faces.push_back(facep); |
2401 | } | 2360 | } |
2402 | else if (te->getShiny() && LLPipeline::sRenderBump || | 2361 | else if ((te->getShiny() && LLPipeline::sRenderBump) || |
2403 | !te->getFullbright()) | 2362 | !te->getFullbright()) |
2404 | { //needs normal | 2363 | { //needs normal |
2405 | simple_faces.push_back(facep); | 2364 | simple_faces.push_back(facep); |
diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index 9b4e715..960f6da 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h | |||
@@ -130,7 +130,7 @@ public: | |||
130 | 130 | ||
131 | 131 | ||
132 | BOOL getVolumeChanged() const { return mVolumeChanged; } | 132 | BOOL getVolumeChanged() const { return mVolumeChanged; } |
133 | F32 getTextureVirtualSize(LLFace* face); | 133 | |
134 | /*virtual*/ F32 getRadius() const { return mVObjRadius; }; | 134 | /*virtual*/ F32 getRadius() const { return mVObjRadius; }; |
135 | const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; | 135 | const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; |
136 | 136 | ||
@@ -177,8 +177,8 @@ public: | |||
177 | /*virtual*/ void updateFaceSize(S32 idx); | 177 | /*virtual*/ void updateFaceSize(S32 idx); |
178 | /*virtual*/ BOOL updateLOD(); | 178 | /*virtual*/ BOOL updateLOD(); |
179 | void updateRadius(); | 179 | void updateRadius(); |
180 | /*virtual*/ void updateTextures(LLAgent &agent); | 180 | /*virtual*/ void updateTextures(); |
181 | void updateTextures(); | 181 | void updateTextureVirtualSize(); |
182 | 182 | ||
183 | void updateFaceFlags(); | 183 | void updateFaceFlags(); |
184 | void regenFaces(); | 184 | void regenFaces(); |
diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp index d23c746..5b6a949 100644 --- a/linden/indra/newview/llvowater.cpp +++ b/linden/indra/newview/llvowater.cpp | |||
@@ -101,7 +101,7 @@ void LLVOWater::setPixelAreaAndAngle(LLAgent &agent) | |||
101 | 101 | ||
102 | 102 | ||
103 | // virtual | 103 | // virtual |
104 | void LLVOWater::updateTextures(LLAgent &agent) | 104 | void LLVOWater::updateTextures() |
105 | { | 105 | { |
106 | } | 106 | } |
107 | 107 | ||
diff --git a/linden/indra/newview/llvowater.h b/linden/indra/newview/llvowater.h index cdda48f..9c33e74 100644 --- a/linden/indra/newview/llvowater.h +++ b/linden/indra/newview/llvowater.h | |||
@@ -68,7 +68,7 @@ public: | |||
68 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); | 68 | /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); |
69 | /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); | 69 | /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); |
70 | 70 | ||
71 | /*virtual*/ void updateTextures(LLAgent &agent); | 71 | /*virtual*/ void updateTextures(); |
72 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area | 72 | /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area |
73 | 73 | ||
74 | virtual U32 getPartitionType() const; | 74 | virtual U32 getPartitionType() const; |
diff --git a/linden/indra/newview/llworldmapview.cpp b/linden/indra/newview/llworldmapview.cpp index 64e84c5..c10faa5 100644 --- a/linden/indra/newview/llworldmapview.cpp +++ b/linden/indra/newview/llworldmapview.cpp | |||
@@ -378,7 +378,7 @@ void LLWorldMapView::draw() | |||
378 | continue; | 378 | continue; |
379 | } | 379 | } |
380 | 380 | ||
381 | current_image->setBoostLevel(LLViewerImage::BOOST_MAP_LAYER); | 381 | current_image->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE); |
382 | current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); | 382 | current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); |
383 | 383 | ||
384 | if (!current_image->getHasGLTexture()) | 384 | if (!current_image->getHasGLTexture()) |
@@ -557,13 +557,13 @@ void LLWorldMapView::draw() | |||
557 | S32 draw_size = llround(gMapScale); | 557 | S32 draw_size = llround(gMapScale); |
558 | if (simimage != NULL) | 558 | if (simimage != NULL) |
559 | { | 559 | { |
560 | simimage->setBoostLevel(LLViewerImage::BOOST_MAP); | 560 | simimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); |
561 | simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); | 561 | simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); |
562 | } | 562 | } |
563 | 563 | ||
564 | if (overlayimage != NULL) | 564 | if (overlayimage != NULL) |
565 | { | 565 | { |
566 | overlayimage->setBoostLevel(LLViewerImage::BOOST_MAP); | 566 | overlayimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP); |
567 | overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); | 567 | overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); |
568 | } | 568 | } |
569 | 569 | ||
diff --git a/linden/indra/newview/primbackup.cpp b/linden/indra/newview/primbackup.cpp index 4f93ddf..a9a8af7 100644 --- a/linden/indra/newview/primbackup.cpp +++ b/linden/indra/newview/primbackup.cpp | |||
@@ -590,8 +590,8 @@ void primbackup::export_next_texture() | |||
590 | S32 cur_discard = imagep->getDiscardLevel(); | 590 | S32 cur_discard = imagep->getDiscardLevel(); |
591 | if(cur_discard>0) | 591 | if(cur_discard>0) |
592 | { | 592 | { |
593 | if(imagep->getBoostLevel()!=LLViewerImage::BOOST_PREVIEW) | 593 | if(imagep->getBoostLevel()!=LLViewerImageBoostLevel::BOOST_PREVIEW) |
594 | imagep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); //we want to force discard 0 this one does this. | 594 | imagep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); //we want to force discard 0 this one does this. |
595 | } | 595 | } |
596 | else | 596 | else |
597 | { | 597 | { |