aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llimage')
-rw-r--r--linden/indra/llimage/CMakeLists.txt7
-rw-r--r--linden/indra/llimage/llimage.cpp75
-rw-r--r--linden/indra/llimage/llimage.h33
-rw-r--r--linden/indra/llimage/llimagej2c.cpp141
-rw-r--r--linden/indra/llimage/llimagej2c.h5
-rw-r--r--linden/indra/llimage/llimageworker.cpp4
-rw-r--r--linden/indra/llimage/llimageworker.h6
7 files changed, 202 insertions, 69 deletions
diff --git a/linden/indra/llimage/CMakeLists.txt b/linden/indra/llimage/CMakeLists.txt
index 5593b4a..1a4d92b 100644
--- a/linden/indra/llimage/CMakeLists.txt
+++ b/linden/indra/llimage/CMakeLists.txt
@@ -7,6 +7,7 @@ include(LLCommon)
7include(LLImage) 7include(LLImage)
8include(LLMath) 8include(LLMath)
9include(LLVFS) 9include(LLVFS)
10include(ZLIB)
10 11
11include_directories( 12include_directories(
12 ${LLCOMMON_INCLUDE_DIRS} 13 ${LLCOMMON_INCLUDE_DIRS}
@@ -48,3 +49,9 @@ set_source_files_properties(${llimage_HEADER_FILES}
48list(APPEND llimage_SOURCE_FILES ${llimage_HEADER_FILES}) 49list(APPEND llimage_SOURCE_FILES ${llimage_HEADER_FILES})
49 50
50add_library (llimage ${llimage_SOURCE_FILES}) 51add_library (llimage ${llimage_SOURCE_FILES})
52target_link_libraries(
53 llimage
54 ${JPEG_LIBRARIES}
55 ${PNG_LIBRARIES}
56 ${ZLIB_LIBRARIES}
57 )
diff --git a/linden/indra/llimage/llimage.cpp b/linden/indra/llimage/llimage.cpp
index 814e82f..71e7b41 100644
--- a/linden/indra/llimage/llimage.cpp
+++ b/linden/indra/llimage/llimage.cpp
@@ -43,6 +43,49 @@
43#include "llimagejpeg.h" 43#include "llimagejpeg.h"
44#include "llimagepng.h" 44#include "llimagepng.h"
45#include "llimagedxt.h" 45#include "llimagedxt.h"
46#include "llimageworker.h"
47
48//---------------------------------------------------------------------------
49// LLImage
50//---------------------------------------------------------------------------
51
52//static
53std::string LLImage::sLastErrorMessage;
54LLMutex* LLImage::sMutex = NULL;
55
56//static
57void LLImage::initClass(LLWorkerThread* workerthread)
58{
59 sMutex = new LLMutex(NULL);
60 if (workerthread)
61 {
62 LLImageWorker::initImageWorker(workerthread);
63 }
64 LLImageJ2C::openDSO();
65}
66
67//static
68void LLImage::cleanupClass()
69{
70 LLImageJ2C::closeDSO();
71 LLImageWorker::cleanupImageWorker();
72 delete sMutex;
73 sMutex = NULL;
74}
75
76//static
77const std::string& LLImage::getLastError()
78{
79 static const std::string noerr("No Error");
80 return sLastErrorMessage.empty() ? noerr : sLastErrorMessage;
81}
82
83//static
84void LLImage::setLastError(const std::string& message)
85{
86 LLMutexLock m(sMutex);
87 sLastErrorMessage = message;
88}
46 89
47//--------------------------------------------------------------------------- 90//---------------------------------------------------------------------------
48// LLImageBase 91// LLImageBase
@@ -95,21 +138,8 @@ void LLImageBase::sanityCheck()
95 } 138 }
96} 139}
97 140
98std::string LLImageBase::sLastErrorMessage;
99BOOL LLImageBase::sSizeOverride = FALSE; 141BOOL LLImageBase::sSizeOverride = FALSE;
100 142
101BOOL LLImageBase::setLastError(const std::string& message, const std::string& filename)
102{
103 sLastErrorMessage = message;
104 if (!filename.empty())
105 {
106 sLastErrorMessage += " FILE:";
107 sLastErrorMessage += filename;
108 }
109 llwarns << sLastErrorMessage << llendl;
110 return FALSE;
111}
112
113// virtual 143// virtual
114void LLImageBase::deleteData() 144void LLImageBase::deleteData()
115{ 145{
@@ -136,8 +166,6 @@ U8* LLImageBase::allocateData(S32 size)
136 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl; 166 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
137 } 167 }
138 168
139 resetLastError();
140
141 if (!mData || size != mDataSize) 169 if (!mData || size != mDataSize)
142 { 170 {
143 deleteData(); // virtual 171 deleteData(); // virtual
@@ -1269,6 +1297,23 @@ LLImageFormatted::~LLImageFormatted()
1269 1297
1270//---------------------------------------------------------------------------- 1298//----------------------------------------------------------------------------
1271 1299
1300//virtual
1301void LLImageFormatted::resetLastError()
1302{
1303 LLImage::setLastError("");
1304}
1305
1306//virtual
1307void LLImageFormatted::setLastError(const std::string& message, const std::string& filename)
1308{
1309 std::string error = message;
1310 if (!filename.empty())
1311 error += std::string(" FILE: ") + filename;
1312 LLImage::setLastError(error);
1313}
1314
1315//----------------------------------------------------------------------------
1316
1272// static 1317// static
1273LLImageFormatted* LLImageFormatted::createFromType(S8 codec) 1318LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
1274{ 1319{
diff --git a/linden/indra/llimage/llimage.h b/linden/indra/llimage/llimage.h
index 98a98c2..8a08c89 100644
--- a/linden/indra/llimage/llimage.h
+++ b/linden/indra/llimage/llimage.h
@@ -59,6 +59,7 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
59class LLImageFormatted; 59class LLImageFormatted;
60class LLImageRaw; 60class LLImageRaw;
61class LLColor4U; 61class LLColor4U;
62class LLWorkerThread;
62 63
63typedef enum e_image_codec 64typedef enum e_image_codec
64{ 65{
@@ -74,6 +75,24 @@ typedef enum e_image_codec
74} EImageCodec; 75} EImageCodec;
75 76
76//============================================================================ 77//============================================================================
78// library initialization class
79
80class LLImage
81{
82public:
83 static void initClass(LLWorkerThread* workerthread);
84 static void cleanupClass();
85
86 static const std::string& getLastError();
87 static void setLastError(const std::string& message);
88
89protected:
90 static LLMutex* sMutex;
91 static std::string sLastErrorMessage;
92};
93
94//============================================================================
95// Image base class
77 96
78class LLImageBase : public LLThreadSafeRefCount 97class LLImageBase : public LLThreadSafeRefCount
79{ 98{
@@ -113,10 +132,6 @@ protected:
113 void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }; 132 void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; };
114 133
115public: 134public:
116 static const std::string& getLastError() {return sLastErrorMessage;};
117 static void resetLastError() {sLastErrorMessage = "No Error"; };
118 static BOOL setLastError(const std::string& message, const std::string& filename = std::string()); // returns FALSE
119
120 static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); 135 static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
121 136
122 // Function for calculating the download priority for textures 137 // Function for calculating the download priority for textures
@@ -141,8 +156,6 @@ private:
141public: 156public:
142 S16 mMemType; // debug 157 S16 mMemType; // debug
143 158
144 static std::string sLastErrorMessage;
145
146 static BOOL sSizeOverride; 159 static BOOL sSizeOverride;
147}; 160};
148 161
@@ -245,7 +258,6 @@ public:
245 LLImageFormatted(S8 codec); 258 LLImageFormatted(S8 codec);
246 259
247 // LLImageBase 260 // LLImageBase
248public:
249 /*virtual*/ void deleteData(); 261 /*virtual*/ void deleteData();
250 /*virtual*/ U8* allocateData(S32 size = -1); 262 /*virtual*/ U8* allocateData(S32 size = -1);
251 /*virtual*/ U8* reallocateData(S32 size); 263 /*virtual*/ U8* reallocateData(S32 size);
@@ -254,7 +266,6 @@ public:
254 /*virtual*/ void sanityCheck(); 266 /*virtual*/ void sanityCheck();
255 267
256 // New methods 268 // New methods
257public:
258 // subclasses must return a prefered file extension (lowercase without a leading dot) 269 // subclasses must return a prefered file extension (lowercase without a leading dot)
259 virtual std::string getExtension() = 0; 270 virtual std::string getExtension() = 0;
260 // calcHeaderSize() returns the maximum size of header; 271 // calcHeaderSize() returns the maximum size of header;
@@ -287,6 +298,10 @@ public:
287 void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; } 298 void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
288 S8 getDiscardLevel() const { return mDiscardLevel; } 299 S8 getDiscardLevel() const { return mDiscardLevel; }
289 300
301 // setLastError needs to be deferred for J2C images since it may be called from a DLL
302 virtual void resetLastError();
303 virtual void setLastError(const std::string& message, const std::string& filename = std::string());
304
290protected: 305protected:
291 BOOL copyData(U8 *data, S32 size); // calls updateData() 306 BOOL copyData(U8 *data, S32 size); // calls updateData()
292 307
@@ -295,7 +310,7 @@ protected:
295 S8 mDecoding; 310 S8 mDecoding;
296 S8 mDecoded; 311 S8 mDecoded;
297 S8 mDiscardLevel; 312 S8 mDiscardLevel;
298 313
299public: 314public:
300 static S32 sGlobalFormattedMemory; 315 static S32 sGlobalFormattedMemory;
301}; 316};
diff --git a/linden/indra/llimage/llimagej2c.cpp b/linden/indra/llimage/llimagej2c.cpp
index 510b303..95abbae 100644
--- a/linden/indra/llimage/llimagej2c.cpp
+++ b/linden/indra/llimage/llimagej2c.cpp
@@ -219,32 +219,54 @@ LLImageJ2C::~LLImageJ2C()
219} 219}
220 220
221// virtual 221// virtual
222void LLImageJ2C::resetLastError()
223{
224 mLastError.clear();
225}
226
227//virtual
228void LLImageJ2C::setLastError(const std::string& message, const std::string& filename)
229{
230 mLastError = message;
231 if (!filename.empty())
232 mLastError += std::string(" FILE: ") + filename;
233}
234
235// virtual
222S8 LLImageJ2C::getRawDiscardLevel() 236S8 LLImageJ2C::getRawDiscardLevel()
223{ 237{
224 return mRawDiscardLevel; 238 return mRawDiscardLevel;
225} 239}
226 240
227BOOL LLImageJ2C::updateData() 241BOOL LLImageJ2C::updateData()
228{ 242{
243 BOOL res = TRUE;
229 resetLastError(); 244 resetLastError();
230 245
231 // Check to make sure that this instance has been initialized with data 246 // Check to make sure that this instance has been initialized with data
232 if (!getData() || (getDataSize() < 16)) 247 if (!getData() || (getDataSize() < 16))
233 { 248 {
234 setLastError("LLImageJ2C uninitialized"); 249 setLastError("LLImageJ2C uninitialized");
235 return FALSE; 250 res = FALSE;
251 }
252 else
253 {
254 res = mImpl->getMetadata(*this);
236 } 255 }
237 256
238 if (!mImpl->getMetadata(*this)) 257 if (res)
239 { 258 {
240 return FALSE; 259 // SJB: override discard based on mMaxBytes elsewhere
260 S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
261 S32 discard = calcDiscardLevelBytes(max_bytes);
262 setDiscardLevel(discard);
241 } 263 }
242 // SJB: override discard based on mMaxBytes elsewhere
243 S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
244 S32 discard = calcDiscardLevelBytes(max_bytes);
245 setDiscardLevel(discard);
246 264
247 return TRUE; 265 if (!mLastError.empty())
266 {
267 LLImage::setLastError(mLastError);
268 }
269 return res;
248} 270}
249 271
250 272
@@ -258,20 +280,24 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
258{ 280{
259 LLMemType mt1((LLMemType::EMemType)mMemType); 281 LLMemType mt1((LLMemType::EMemType)mMemType);
260 282
283 BOOL res = TRUE;
284
261 resetLastError(); 285 resetLastError();
262 286
263 // Check to make sure that this instance has been initialized with data 287 // Check to make sure that this instance has been initialized with data
264 if (!getData() || (getDataSize() < 16)) 288 if (!getData() || (getDataSize() < 16))
265 { 289 {
266 setLastError("LLImageJ2C uninitialized"); 290 setLastError("LLImageJ2C uninitialized");
267 return FALSE; 291 res = FALSE;
268 } 292 }
269 293 else
270 // Update the raw discard level 294 {
271 updateRawDiscardLevel(); 295 // Update the raw discard level
272 296 updateRawDiscardLevel();
273 mDecoding = TRUE; 297 mDecoding = TRUE;
274 BOOL res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count); 298 res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
299 }
300
275 if (res) 301 if (res)
276 { 302 {
277 if (!mDecoding) 303 if (!mDecoding)
@@ -283,9 +309,14 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
283 { 309 {
284 mDecoding = FALSE; 310 mDecoding = FALSE;
285 } 311 }
286 return TRUE; // done
287 } 312 }
288 return FALSE; 313
314 if (!mLastError.empty())
315 {
316 LLImage::setLastError(mLastError);
317 }
318
319 return res;
289} 320}
290 321
291 322
@@ -298,7 +329,13 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
298BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time) 329BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
299{ 330{
300 LLMemType mt1((LLMemType::EMemType)mMemType); 331 LLMemType mt1((LLMemType::EMemType)mMemType);
301 return mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible); 332 resetLastError();
333 BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
334 if (!mLastError.empty())
335 {
336 LLImage::setLastError(mLastError);
337 }
338 return res;
302} 339}
303 340
304//static 341//static
@@ -376,6 +413,8 @@ void LLImageJ2C::setReversible(const BOOL reversible)
376 413
377BOOL LLImageJ2C::loadAndValidate(const std::string &filename) 414BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
378{ 415{
416 BOOL res = TRUE;
417
379 resetLastError(); 418 resetLastError();
380 419
381 S32 file_size = 0; 420 S32 file_size = 0;
@@ -383,27 +422,38 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
383 if (!apr_file) 422 if (!apr_file)
384 { 423 {
385 setLastError("Unable to open file for reading", filename); 424 setLastError("Unable to open file for reading", filename);
386 return FALSE; 425 res = FALSE;
387 } 426 }
388 if (file_size == 0) 427 else if (file_size == 0)
389 { 428 {
390 setLastError("File is empty",filename); 429 setLastError("File is empty",filename);
391 apr_file_close(apr_file); 430 apr_file_close(apr_file);
392 return FALSE; 431 res = FALSE;
393 } 432 }
394 433 else
395 U8 *data = new U8[file_size];
396 apr_size_t bytes_read = file_size;
397 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
398 if (s != APR_SUCCESS || (S32)bytes_read != file_size)
399 { 434 {
400 delete[] data; 435 U8 *data = new U8[file_size];
401 setLastError("Unable to read entire file"); 436 apr_size_t bytes_read = file_size;
402 return FALSE; 437 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
438 apr_file_close(apr_file);
439 if (s != APR_SUCCESS || (S32)bytes_read != file_size)
440 {
441 delete[] data;
442 setLastError("Unable to read entire file");
443 res = FALSE;
444 }
445 else
446 {
447 res = validate(data, file_size);
448 }
403 } 449 }
404 apr_file_close(apr_file);
405 450
406 return validate(data, file_size); 451 if (!mLastError.empty())
452 {
453 LLImage::setLastError(mLastError);
454 }
455
456 return res;
407} 457}
408 458
409 459
@@ -411,21 +461,30 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
411{ 461{
412 LLMemType mt1((LLMemType::EMemType)mMemType); 462 LLMemType mt1((LLMemType::EMemType)mMemType);
413 463
464 resetLastError();
465
414 setData(data, file_size); 466 setData(data, file_size);
467
415 BOOL res = updateData(); 468 BOOL res = updateData();
416 if ( !res ) 469 if ( res )
417 { 470 {
418 return FALSE; 471 // Check to make sure that this instance has been initialized with data
472 if (!getData() || (0 == getDataSize()))
473 {
474 setLastError("LLImageJ2C uninitialized");
475 res = FALSE;
476 }
477 else
478 {
479 res = mImpl->getMetadata(*this);
480 }
419 } 481 }
420 482
421 // Check to make sure that this instance has been initialized with data 483 if (!mLastError.empty())
422 if (!getData() || (0 == getDataSize()))
423 { 484 {
424 setLastError("LLImageJ2C uninitialized"); 485 LLImage::setLastError(mLastError);
425 return FALSE;
426 } 486 }
427 487 return res;
428 return mImpl->getMetadata(*this);
429} 488}
430 489
431void LLImageJ2C::decodeFailed() 490void LLImageJ2C::decodeFailed()
diff --git a/linden/indra/llimage/llimagej2c.h b/linden/indra/llimage/llimagej2c.h
index 2b4a3ec..f4d651f 100644
--- a/linden/indra/llimage/llimagej2c.h
+++ b/linden/indra/llimage/llimagej2c.h
@@ -54,6 +54,10 @@ public:
54 /*virtual*/ S32 calcDataSize(S32 discard_level = 0); 54 /*virtual*/ S32 calcDataSize(S32 discard_level = 0);
55 /*virtual*/ S32 calcDiscardLevelBytes(S32 bytes); 55 /*virtual*/ S32 calcDiscardLevelBytes(S32 bytes);
56 /*virtual*/ S8 getRawDiscardLevel(); 56 /*virtual*/ S8 getRawDiscardLevel();
57 // Override these so that we don't try to set a global variable from a DLL
58 /*virtual*/ void resetLastError();
59 /*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string());
60
57 61
58 // Encode with comment text 62 // Encode with comment text
59 BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0); 63 BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
@@ -86,6 +90,7 @@ protected:
86 F32 mRate; 90 F32 mRate;
87 BOOL mReversible; 91 BOOL mReversible;
88 LLImageJ2CImpl *mImpl; 92 LLImageJ2CImpl *mImpl;
93 std::string mLastError;
89}; 94};
90 95
91// Derive from this class to implement JPEG2000 decoding 96// Derive from this class to implement JPEG2000 decoding
diff --git a/linden/indra/llimage/llimageworker.cpp b/linden/indra/llimage/llimageworker.cpp
index dc6f2e4..93ce19b 100644
--- a/linden/indra/llimage/llimageworker.cpp
+++ b/linden/indra/llimage/llimageworker.cpp
@@ -41,13 +41,13 @@ LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
41S32 LLImageWorker::sCount = 0; 41S32 LLImageWorker::sCount = 0;
42 42
43//static 43//static
44void LLImageWorker::initClass(LLWorkerThread* workerthread) 44void LLImageWorker::initImageWorker(LLWorkerThread* workerthread)
45{ 45{
46 sWorkerThread = workerthread; 46 sWorkerThread = workerthread;
47} 47}
48 48
49//static 49//static
50void LLImageWorker::cleanupClass() 50void LLImageWorker::cleanupImageWorker()
51{ 51{
52} 52}
53 53
diff --git a/linden/indra/llimage/llimageworker.h b/linden/indra/llimage/llimageworker.h
index bf6c3f2..3ee6b8e 100644
--- a/linden/indra/llimage/llimageworker.h
+++ b/linden/indra/llimage/llimageworker.h
@@ -38,8 +38,10 @@
38class LLImageWorker : public LLWorkerClass 38class LLImageWorker : public LLWorkerClass
39{ 39{
40public: 40public:
41 static void initClass(LLWorkerThread* workerthread); 41 static void initImageWorker(LLWorkerThread* workerthread);
42 static void cleanupClass(); 42 static void cleanupImageWorker();
43
44public:
43 static LLWorkerThread* getWorkerThread() { return sWorkerThread; } 45 static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
44 46
45 // LLWorkerThread 47 // LLWorkerThread