diff options
Diffstat (limited to 'linden/indra/newview/lltexturecache.cpp')
-rw-r--r-- | linden/indra/newview/lltexturecache.cpp | 214 |
1 files changed, 182 insertions, 32 deletions
diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp index 11fd348..c31fbba 100644 --- a/linden/indra/newview/lltexturecache.cpp +++ b/linden/indra/newview/lltexturecache.cpp | |||
@@ -50,15 +50,6 @@ class LLTextureCacheWorker : public LLWorkerClass | |||
50 | friend class LLTextureCache; | 50 | friend class LLTextureCache; |
51 | 51 | ||
52 | private: | 52 | private: |
53 | enum e_state | ||
54 | { | ||
55 | INIT = 0, | ||
56 | LOCAL = 1, | ||
57 | CACHE = 2, | ||
58 | HEADER = 3, | ||
59 | BODY = 4 | ||
60 | }; | ||
61 | |||
62 | class ReadResponder : public LLLFSThread::Responder | 53 | class ReadResponder : public LLLFSThread::Responder |
63 | { | 54 | { |
64 | public: | 55 | public: |
@@ -97,10 +88,9 @@ public: | |||
97 | S32 imagesize, // for writes | 88 | S32 imagesize, // for writes |
98 | LLTextureCache::Responder* responder) | 89 | LLTextureCache::Responder* responder) |
99 | : LLWorkerClass(cache, "LLTextureCacheWorker"), | 90 | : LLWorkerClass(cache, "LLTextureCacheWorker"), |
91 | mID(id), | ||
100 | mCache(cache), | 92 | mCache(cache), |
101 | mPriority(priority), | 93 | mPriority(priority), |
102 | mID(id), | ||
103 | mState(INIT), | ||
104 | mReadData(NULL), | 94 | mReadData(NULL), |
105 | mWriteData(data), | 95 | mWriteData(data), |
106 | mDataSize(datasize), | 96 | mDataSize(datasize), |
@@ -121,8 +111,10 @@ public: | |||
121 | delete[] mReadData; | 111 | delete[] mReadData; |
122 | } | 112 | } |
123 | 113 | ||
124 | bool doRead(); | 114 | // override this interface |
125 | bool doWrite(); | 115 | virtual bool doRead() = 0; |
116 | virtual bool doWrite() = 0; | ||
117 | |||
126 | virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() | 118 | virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() |
127 | 119 | ||
128 | handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } | 120 | handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } |
@@ -133,24 +125,23 @@ public: | |||
133 | mBytesRead = bytes; | 125 | mBytesRead = bytes; |
134 | setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority); | 126 | setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority); |
135 | } | 127 | } |
136 | 128 | ||
137 | private: | 129 | private: |
138 | virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) | 130 | virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) |
139 | virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) | 131 | virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) |
140 | virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) | 132 | virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) |
141 | 133 | ||
142 | private: | 134 | protected: |
143 | LLTextureCache* mCache; | 135 | LLTextureCache* mCache; |
144 | U32 mPriority; | 136 | U32 mPriority; |
145 | LLUUID mID; | 137 | LLUUID mID; |
146 | e_state mState; | ||
147 | 138 | ||
148 | U8* mReadData; | 139 | U8* mReadData; |
149 | U8* mWriteData; | 140 | U8* mWriteData; |
150 | S32 mDataSize; | 141 | S32 mDataSize; |
151 | S32 mOffset; | 142 | S32 mOffset; |
152 | S32 mImageSize; | 143 | S32 mImageSize; |
153 | S32 mImageFormat; | 144 | EImageCodec mImageFormat; |
154 | BOOL mImageLocal; | 145 | BOOL mImageLocal; |
155 | LLPointer<LLTextureCache::Responder> mResponder; | 146 | LLPointer<LLTextureCache::Responder> mResponder; |
156 | LLLFSThread::handle_t mFileHandle; | 147 | LLLFSThread::handle_t mFileHandle; |
@@ -158,19 +149,169 @@ private: | |||
158 | LLAtomicS32 mBytesRead; | 149 | LLAtomicS32 mBytesRead; |
159 | }; | 150 | }; |
160 | 151 | ||
152 | class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker | ||
153 | { | ||
154 | public: | ||
155 | LLTextureCacheLocalFileWorker(LLTextureCache* cache, U32 priority, const LLString& filename, const LLUUID& id, | ||
156 | U8* data, S32 datasize, S32 offset, | ||
157 | S32 imagesize, // for writes | ||
158 | LLTextureCache::Responder* responder) | ||
159 | : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), | ||
160 | mFileName(filename) | ||
161 | |||
162 | { | ||
163 | } | ||
164 | |||
165 | virtual bool doRead(); | ||
166 | virtual bool doWrite(); | ||
167 | |||
168 | private: | ||
169 | LLString mFileName; | ||
170 | }; | ||
171 | |||
172 | bool LLTextureCacheLocalFileWorker::doRead() | ||
173 | { | ||
174 | S32 local_size = ll_apr_file_size(mFileName, mCache->getFileAPRPool()); | ||
175 | |||
176 | if (local_size > 0 && mFileName.size() > 4) | ||
177 | { | ||
178 | mDataSize = local_size; // Only a complete file is valid | ||
179 | |||
180 | LLString extension = mFileName.substr(mFileName.size() - 3, 3); | ||
181 | |||
182 | mImageFormat = LLImageBase::getCodecFromExtension(extension); | ||
183 | |||
184 | if (mImageFormat == IMG_CODEC_INVALID) | ||
185 | { | ||
186 | llwarns << "Unrecognized file extension " << extension << " for local texture " << mFileName << llendl; | ||
187 | mDataSize = 0; // no data | ||
188 | return true; | ||
189 | } | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | // file doesn't exist | ||
194 | mDataSize = 0; // no data | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | #if USE_LFS_READ | ||
199 | if (mFileHandle == LLLFSThread::nullHandle()) | ||
200 | { | ||
201 | mImageLocal = TRUE; | ||
202 | mImageSize = local_size; | ||
203 | if (!mDataSize || mDataSize + mOffset > local_size) | ||
204 | { | ||
205 | mDataSize = local_size - mOffset; | ||
206 | } | ||
207 | if (mDataSize <= 0) | ||
208 | { | ||
209 | // no more data to read | ||
210 | mDataSize = 0; | ||
211 | return true; | ||
212 | } | ||
213 | mReadData = new U8[mDataSize]; | ||
214 | mBytesRead = -1; | ||
215 | mBytesToRead = mDataSize; | ||
216 | setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); | ||
217 | mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, | ||
218 | new ReadResponder(mCache, mRequestHandle)); | ||
219 | return false; | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | if (mBytesRead >= 0) | ||
224 | { | ||
225 | if (mBytesRead != mBytesToRead) | ||
226 | { | ||
227 | llwarns << "Error reading file from local cache: " << local_filename | ||
228 | << " Bytes: " << mDataSize << " Offset: " << mOffset | ||
229 | << " / " << mDataSize << llendl; | ||
230 | mDataSize = 0; // failed | ||
231 | delete[] mReadData; | ||
232 | mReadData = NULL; | ||
233 | } | ||
234 | return true; | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | return false; | ||
239 | } | ||
240 | } | ||
241 | #else | ||
242 | if (!mDataSize || mDataSize > local_size) | ||
243 | { | ||
244 | mDataSize = local_size; | ||
245 | } | ||
246 | mReadData = new U8[mDataSize]; | ||
247 | S32 bytes_read = ll_apr_file_read_ex(mFileName, mCache->getFileAPRPool(), | ||
248 | mReadData, mOffset, mDataSize); | ||
249 | if (bytes_read != mDataSize) | ||
250 | { | ||
251 | llwarns << "Error reading file from local cache: " << mFileName | ||
252 | << " Bytes: " << mDataSize << " Offset: " << mOffset | ||
253 | << " / " << mDataSize << llendl; | ||
254 | mDataSize = 0; | ||
255 | delete[] mReadData; | ||
256 | mReadData = NULL; | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | mImageSize = local_size; | ||
261 | mImageLocal = TRUE; | ||
262 | } | ||
263 | return true; | ||
264 | #endif | ||
265 | } | ||
266 | |||
267 | bool LLTextureCacheLocalFileWorker::doWrite() | ||
268 | { | ||
269 | // no writes for local files | ||
270 | return false; | ||
271 | } | ||
272 | |||
273 | class LLTextureCacheRemoteWorker : public LLTextureCacheWorker | ||
274 | { | ||
275 | public: | ||
276 | LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, | ||
277 | U8* data, S32 datasize, S32 offset, | ||
278 | S32 imagesize, // for writes | ||
279 | LLTextureCache::Responder* responder) | ||
280 | : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), | ||
281 | mState(INIT) | ||
282 | { | ||
283 | } | ||
284 | |||
285 | virtual bool doRead(); | ||
286 | virtual bool doWrite(); | ||
287 | |||
288 | private: | ||
289 | enum e_state | ||
290 | { | ||
291 | INIT = 0, | ||
292 | LOCAL = 1, | ||
293 | CACHE = 2, | ||
294 | HEADER = 3, | ||
295 | BODY = 4 | ||
296 | }; | ||
297 | |||
298 | e_state mState; | ||
299 | }; | ||
300 | |||
301 | |||
161 | //virtual | 302 | //virtual |
162 | void LLTextureCacheWorker::startWork(S32 param) | 303 | void LLTextureCacheWorker::startWork(S32 param) |
163 | { | 304 | { |
164 | } | 305 | } |
165 | 306 | ||
166 | bool LLTextureCacheWorker::doRead() | 307 | bool LLTextureCacheRemoteWorker::doRead() |
167 | { | 308 | { |
168 | S32 local_size = 0; | 309 | S32 local_size = 0; |
169 | std::string local_filename; | 310 | std::string local_filename; |
170 | 311 | ||
171 | if (mState == INIT) | 312 | if (mState == INIT) |
172 | { | 313 | { |
173 | std::string filename = mCache->getLocalFileName(mID); | 314 | std::string filename = mCache->getLocalFileName(mID); |
174 | local_filename = filename + ".j2c"; | 315 | local_filename = filename + ".j2c"; |
175 | local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); | 316 | local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); |
176 | if (local_size == 0) | 317 | if (local_size == 0) |
@@ -468,19 +609,13 @@ bool LLTextureCacheWorker::doRead() | |||
468 | return false; | 609 | return false; |
469 | } | 610 | } |
470 | 611 | ||
471 | bool LLTextureCacheWorker::doWrite() | 612 | bool LLTextureCacheRemoteWorker::doWrite() |
472 | { | 613 | { |
473 | S32 idx = -1; | 614 | S32 idx = -1; |
474 | 615 | ||
475 | if (mState == INIT) | ||
476 | { | ||
477 | llassert_always(mOffset == 0); // Currently don't support offsets | ||
478 | mState = CACHE; | ||
479 | } | ||
480 | |||
481 | // No LOCAL state for write() | 616 | // No LOCAL state for write() |
482 | 617 | ||
483 | if (mState == CACHE) | 618 | if (mState == INIT) |
484 | { | 619 | { |
485 | S32 cur_imagesize = 0; | 620 | S32 cur_imagesize = 0; |
486 | S32 offset = mOffset; | 621 | S32 offset = mOffset; |
@@ -921,9 +1056,9 @@ struct lru_data | |||
921 | typedef const lru_data* lru_data_ptr; | 1056 | typedef const lru_data* lru_data_ptr; |
922 | bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const | 1057 | bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const |
923 | { | 1058 | { |
924 | if (!(a->time < b->time)) | 1059 | if (a->time > b->time) |
925 | return true; | 1060 | return true; |
926 | else if (!(b->time < a->time)) | 1061 | else if (b->time > a->time) |
927 | return false; | 1062 | return false; |
928 | else | 1063 | else |
929 | return a->index < b->index; | 1064 | return a->index < b->index; |
@@ -1250,13 +1385,27 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image | |||
1250 | 1385 | ||
1251 | // Calls from texture pipeline thread (i.e. LLTextureFetch) | 1386 | // Calls from texture pipeline thread (i.e. LLTextureFetch) |
1252 | 1387 | ||
1388 | LLTextureCache::handle_t LLTextureCache::readFromCache(const LLString& filename, const LLUUID& id, U32 priority, | ||
1389 | S32 offset, S32 size, ReadResponder* responder) | ||
1390 | { | ||
1391 | // Note: checking to see if an entry exists can cause a stall, | ||
1392 | // so let the thread handle it | ||
1393 | LLMutexLock lock(&mWorkersMutex); | ||
1394 | LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, | ||
1395 | NULL, size, offset, 0, | ||
1396 | responder); | ||
1397 | handle_t handle = worker->read(); | ||
1398 | mReaders[handle] = worker; | ||
1399 | return handle; | ||
1400 | } | ||
1401 | |||
1253 | LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, | 1402 | LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, |
1254 | S32 offset, S32 size, ReadResponder* responder) | 1403 | S32 offset, S32 size, ReadResponder* responder) |
1255 | { | 1404 | { |
1256 | // Note: checking to see if an entry exists can cause a stall, | 1405 | // Note: checking to see if an entry exists can cause a stall, |
1257 | // so let the thread handle it | 1406 | // so let the thread handle it |
1258 | LLMutexLock lock(&mWorkersMutex); | 1407 | LLMutexLock lock(&mWorkersMutex); |
1259 | LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, | 1408 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, |
1260 | NULL, size, offset, 0, | 1409 | NULL, size, offset, 0, |
1261 | responder); | 1410 | responder); |
1262 | handle_t handle = worker->read(); | 1411 | handle_t handle = worker->read(); |
@@ -1264,6 +1413,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri | |||
1264 | return handle; | 1413 | return handle; |
1265 | } | 1414 | } |
1266 | 1415 | ||
1416 | |||
1267 | bool LLTextureCache::readComplete(handle_t handle, bool abort) | 1417 | bool LLTextureCache::readComplete(handle_t handle, bool abort) |
1268 | { | 1418 | { |
1269 | lockWorkers(); | 1419 | lockWorkers(); |
@@ -1306,7 +1456,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio | |||
1306 | { | 1456 | { |
1307 | LLMutexLock lock(&mWorkersMutex); | 1457 | LLMutexLock lock(&mWorkersMutex); |
1308 | llassert_always(imagesize > 0); | 1458 | llassert_always(imagesize > 0); |
1309 | LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, | 1459 | LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, |
1310 | data, datasize, 0, | 1460 | data, datasize, 0, |
1311 | imagesize, responder); | 1461 | imagesize, responder); |
1312 | handle_t handle = worker->write(); | 1462 | handle_t handle = worker->write(); |