diff options
author | Jacek Antonelli | 2010-02-09 21:11:42 -0600 |
---|---|---|
committer | Jacek Antonelli | 2010-02-16 18:50:15 -0600 |
commit | e6247fbe78c4d3dacb74f3b2359aba2b6538133b (patch) | |
tree | 10c42d670a2c635b4339f7f68809c221756774f8 /linden/indra/llimage | |
parent | Ported some cURL and HTTP-related changes from Snowglobe. (diff) | |
download | meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.zip meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.gz meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.bz2 meta-impy-e6247fbe78c4d3dacb74f3b2359aba2b6538133b.tar.xz |
Ported many texture engine changes from Snowglobe.
Diffstat (limited to 'linden/indra/llimage')
-rw-r--r-- | linden/indra/llimage/llimage.cpp | 38 | ||||
-rw-r--r-- | linden/indra/llimage/llimage.h | 8 | ||||
-rw-r--r-- | linden/indra/llimage/llimagedxt.cpp | 19 | ||||
-rw-r--r-- | linden/indra/llimage/llimagej2c.cpp | 5 | ||||
-rw-r--r-- | linden/indra/llimage/llimagejpeg.cpp | 9 | ||||
-rw-r--r-- | linden/indra/llimage/llimageworker.cpp | 202 | ||||
-rw-r--r-- | linden/indra/llimage/llimageworker.h | 97 |
7 files changed, 198 insertions, 180 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 |