llimagej2c.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llimagej2c.cpp
  3.  *
  4.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2001-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #include "linden_common.h"
  32. #include "apr_pools.h"
  33. #include "apr_dso.h"
  34. #include "lldir.h"
  35. #include "llimagej2c.h"
  36. #include "llmemtype.h"
  37. typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
  38. typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
  39. typedef const char* (*EngineInfoLLImageJ2CFunction)();
  40. //some "private static" variables so we only attempt to load
  41. //dynamic libaries once
  42. CreateLLImageJ2CFunction j2cimpl_create_func;
  43. DestroyLLImageJ2CFunction j2cimpl_destroy_func;
  44. EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
  45. apr_pool_t *j2cimpl_dso_memory_pool;
  46. apr_dso_handle_t *j2cimpl_dso_handle;
  47. //Declare the prototype for theses functions here, their functionality
  48. //will be implemented in other files which define a derived LLImageJ2CImpl
  49. //but only ONE static library which has the implementation for this
  50. //function should ever be included
  51. LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
  52. void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
  53. const char* fallbackEngineInfoLLImageJ2CImpl();
  54. //static
  55. //Loads the required "create", "destroy" and "engineinfo" functions needed
  56. void LLImageJ2C::openDSO()
  57. {
  58. //attempt to load a DSO and get some functions from it
  59. std::string dso_name;
  60. std::string dso_path;
  61. bool all_functions_loaded = false;
  62. apr_status_t rv;
  63. #if LL_WINDOWS
  64. dso_name = "llkdu.dll";
  65. #elif LL_DARWIN
  66. dso_name = "libllkdu.dylib";
  67. #else
  68. dso_name = "libllkdu.so";
  69. #endif
  70. dso_path = gDirUtilp->findFile(dso_name,
  71.        gDirUtilp->getAppRODataDir(),
  72.        gDirUtilp->getExecutableDir());
  73. j2cimpl_dso_handle      = NULL;
  74. j2cimpl_dso_memory_pool = NULL;
  75. //attempt to load the shared library
  76. apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
  77. rv = apr_dso_load(&j2cimpl_dso_handle,
  78.   dso_path.c_str(),
  79.   j2cimpl_dso_memory_pool);
  80. //now, check for success
  81. if ( rv == APR_SUCCESS )
  82. {
  83. //found the dynamic library
  84. //now we want to load the functions we're interested in
  85. CreateLLImageJ2CFunction  create_func = NULL;
  86. DestroyLLImageJ2CFunction dest_func = NULL;
  87. EngineInfoLLImageJ2CFunction engineinfo_func = NULL;
  88. rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
  89.  j2cimpl_dso_handle,
  90.  "createLLImageJ2CKDU");
  91. if ( rv == APR_SUCCESS )
  92. {
  93. //we've loaded the create function ok
  94. //we need to delete via the DSO too
  95. //so lets check for a destruction function
  96. rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
  97.  j2cimpl_dso_handle,
  98.        "destroyLLImageJ2CKDU");
  99. if ( rv == APR_SUCCESS )
  100. {
  101. //we've loaded the destroy function ok
  102. rv = apr_dso_sym((apr_dso_handle_sym_t*)&engineinfo_func,
  103.  j2cimpl_dso_handle,
  104.  "engineInfoLLImageJ2CKDU");
  105. if ( rv == APR_SUCCESS )
  106. {
  107. //ok, everything is loaded alright
  108. j2cimpl_create_func  = create_func;
  109. j2cimpl_destroy_func = dest_func;
  110. j2cimpl_engineinfo_func = engineinfo_func;
  111. all_functions_loaded = true;
  112. }
  113. }
  114. }
  115. }
  116. if ( !all_functions_loaded )
  117. {
  118. //something went wrong with the DSO or function loading..
  119. //fall back onto our satefy impl creation function
  120. #if 0
  121. // precious verbose debugging, sadly we can't use our
  122. // 'llinfos' stream etc. this early in the initialisation seq.
  123. char errbuf[256];
  124. fprintf(stderr, "failed to load syms from DSO %s (%s)n",
  125. dso_name.c_str(), dso_path.c_str());
  126. apr_strerror(rv, errbuf, sizeof(errbuf));
  127. fprintf(stderr, "error: %d, %sn", rv, errbuf);
  128. apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
  129. fprintf(stderr, "dso-error: %d, %sn", rv, errbuf);
  130. #endif
  131. if ( j2cimpl_dso_handle )
  132. {
  133. apr_dso_unload(j2cimpl_dso_handle);
  134. j2cimpl_dso_handle = NULL;
  135. }
  136. if ( j2cimpl_dso_memory_pool )
  137. {
  138. apr_pool_destroy(j2cimpl_dso_memory_pool);
  139. j2cimpl_dso_memory_pool = NULL;
  140. }
  141. }
  142. }
  143. //static
  144. void LLImageJ2C::closeDSO()
  145. {
  146. if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
  147. if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
  148. }
  149. //static
  150. std::string LLImageJ2C::getEngineInfo()
  151. {
  152. if (!j2cimpl_engineinfo_func)
  153. j2cimpl_engineinfo_func = fallbackEngineInfoLLImageJ2CImpl;
  154. return j2cimpl_engineinfo_func();
  155. }
  156. LLImageJ2C::LLImageJ2C() :  LLImageFormatted(IMG_CODEC_J2C),
  157. mMaxBytes(0),
  158. mRawDiscardLevel(-1),
  159. mRate(0.0f),
  160. mReversible(FALSE),
  161. mAreaUsedForDataSizeCalcs(0)
  162. {
  163. //We assume here that if we wanted to create via
  164. //a dynamic library that the approriate open calls were made
  165. //before any calls to this constructor.
  166. //Therefore, a NULL creation function pointer here means
  167. //we either did not want to create using functions from the dynamic
  168. //library or there were issues loading it, either way
  169. //use our fall back
  170. if ( !j2cimpl_create_func )
  171. {
  172. j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
  173. }
  174. mImpl = j2cimpl_create_func();
  175. // Clear data size table
  176. for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
  177. { // Array size is MAX_DISCARD_LEVEL+1
  178. mDataSizes[i] = 0;
  179. }
  180. }
  181. // virtual
  182. LLImageJ2C::~LLImageJ2C()
  183. {
  184. //We assume here that if we wanted to destroy via
  185. //a dynamic library that the approriate open calls were made
  186. //before any calls to this destructor.
  187. //Therefore, a NULL creation function pointer here means
  188. //we either did not want to destroy using functions from the dynamic
  189. //library or there were issues loading it, either way
  190. //use our fall back
  191. if ( !j2cimpl_destroy_func )
  192. {
  193. j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
  194. }
  195. if ( mImpl )
  196. {
  197. j2cimpl_destroy_func(mImpl);
  198. }
  199. }
  200. // virtual
  201. void LLImageJ2C::resetLastError()
  202. {
  203. mLastError.clear();
  204. }
  205. //virtual
  206. void LLImageJ2C::setLastError(const std::string& message, const std::string& filename)
  207. {
  208. mLastError = message;
  209. if (!filename.empty())
  210. mLastError += std::string(" FILE: ") + filename;
  211. }
  212. // virtual
  213. S8  LLImageJ2C::getRawDiscardLevel()
  214. {
  215. return mRawDiscardLevel;
  216. }
  217. BOOL LLImageJ2C::updateData()
  218. {
  219. BOOL res = TRUE;
  220. resetLastError();
  221. // Check to make sure that this instance has been initialized with data
  222. if (!getData() || (getDataSize() < 16))
  223. {
  224. setLastError("LLImageJ2C uninitialized");
  225. res = FALSE;
  226. }
  227. else 
  228. {
  229. res = mImpl->getMetadata(*this);
  230. }
  231. if (res)
  232. {
  233. // SJB: override discard based on mMaxBytes elsewhere
  234. S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
  235. S32 discard = calcDiscardLevelBytes(max_bytes);
  236. setDiscardLevel(discard);
  237. }
  238. if (!mLastError.empty())
  239. {
  240. LLImage::setLastError(mLastError);
  241. }
  242. return res;
  243. }
  244. BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
  245. {
  246. return decodeChannels(raw_imagep, decode_time, 0, 4);
  247. }
  248. // Returns TRUE to mean done, whether successful or not.
  249. BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
  250. {
  251. LLMemType mt1(mMemType);
  252. BOOL res = TRUE;
  253. resetLastError();
  254. // Check to make sure that this instance has been initialized with data
  255. if (!getData() || (getDataSize() < 16))
  256. {
  257. setLastError("LLImageJ2C uninitialized");
  258. res = TRUE; // done
  259. }
  260. else
  261. {
  262. // Update the raw discard level
  263. updateRawDiscardLevel();
  264. mDecoding = TRUE;
  265. res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
  266. }
  267. if (res)
  268. {
  269. if (!mDecoding)
  270. {
  271. // Failed
  272. raw_imagep->deleteData();
  273. }
  274. else
  275. {
  276. mDecoding = FALSE;
  277. }
  278. }
  279. if (!mLastError.empty())
  280. {
  281. LLImage::setLastError(mLastError);
  282. }
  283. return res;
  284. }
  285. BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
  286. {
  287. return encode(raw_imagep, NULL, encode_time);
  288. }
  289. BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
  290. {
  291. LLMemType mt1(mMemType);
  292. resetLastError();
  293. BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
  294. if (!mLastError.empty())
  295. {
  296. LLImage::setLastError(mLastError);
  297. }
  298. return res;
  299. }
  300. //static
  301. S32 LLImageJ2C::calcHeaderSizeJ2C()
  302. {
  303. return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size...
  304. }
  305. //static
  306. S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
  307. {
  308. if (rate <= 0.f) rate = .125f;
  309. while (discard_level > 0)
  310. {
  311. if (w < 1 || h < 1)
  312. break;
  313. w >>= 1;
  314. h >>= 1;
  315. discard_level--;
  316. }
  317. S32 bytes = (S32)((F32)(w*h*comp)*rate);
  318. bytes = llmax(bytes, calcHeaderSizeJ2C());
  319. return bytes;
  320. }
  321. S32 LLImageJ2C::calcHeaderSize()
  322. {
  323. return calcHeaderSizeJ2C();
  324. }
  325. // calcDataSize() returns how many bytes to read 
  326. // to load discard_level (including header and higher discard levels)
  327. S32 LLImageJ2C::calcDataSize(S32 discard_level)
  328. {
  329. discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
  330. if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth()) 
  331. || mDataSizes[0] == 0)
  332. {
  333. mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
  334. S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
  335. while ( level >= 0 )
  336. {
  337. mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
  338. level--;
  339. }
  340. /* This is technically a more correct way to calculate the size required
  341.    for each discard level, since they should include the size needed for
  342.    lower levels.   Unfortunately, this doesn't work well and will lead to 
  343.    download stalls.  The true correct way is to parse the header.  This will
  344.    all go away with http textures at some point.
  345. // Calculate the size for each discard level.   Lower levels (higher quality)
  346. // contain the cumulative size of higher levels
  347. S32 total_size = calcHeaderSizeJ2C();
  348. S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
  349. while ( level >= 0 )
  350. { // Add in this discard level and all before it
  351. total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
  352. mDataSizes[level] = total_size;
  353. level--;
  354. }
  355. */
  356. }
  357. return mDataSizes[discard_level];
  358. }
  359. S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
  360. {
  361. llassert(bytes >= 0);
  362. S32 discard_level = 0;
  363. if (bytes == 0)
  364. {
  365. return MAX_DISCARD_LEVEL;
  366. }
  367. while (1)
  368. {
  369. S32 bytes_needed = calcDataSize(discard_level); // virtual
  370. if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes
  371. {
  372. break;
  373. }
  374. discard_level++;
  375. if (discard_level >= MAX_DISCARD_LEVEL)
  376. {
  377. break;
  378. }
  379. }
  380. return discard_level;
  381. }
  382. void LLImageJ2C::setRate(F32 rate)
  383. {
  384. mRate = rate;
  385. }
  386. void LLImageJ2C::setMaxBytes(S32 max_bytes)
  387. {
  388. mMaxBytes = max_bytes;
  389. }
  390. void LLImageJ2C::setReversible(const BOOL reversible)
  391. {
  392.   mReversible = reversible;
  393. }
  394. BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
  395. {
  396. BOOL res = TRUE;
  397. resetLastError();
  398. S32 file_size = 0;
  399. LLAPRFile infile ;
  400. infile.open(filename, LL_APR_RB, NULL, &file_size);
  401. apr_file_t* apr_file = infile.getFileHandle() ;
  402. if (!apr_file)
  403. {
  404. setLastError("Unable to open file for reading", filename);
  405. res = FALSE;
  406. }
  407. else if (file_size == 0)
  408. {
  409. setLastError("File is empty",filename);
  410. res = FALSE;
  411. }
  412. else
  413. {
  414. U8 *data = new U8[file_size];
  415. apr_size_t bytes_read = file_size;
  416. apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
  417. infile.close() ;
  418. if (s != APR_SUCCESS || (S32)bytes_read != file_size)
  419. {
  420. delete[] data;
  421. setLastError("Unable to read entire file");
  422. res = FALSE;
  423. }
  424. else
  425. {
  426. res = validate(data, file_size);
  427. }
  428. }
  429. if (!mLastError.empty())
  430. {
  431. LLImage::setLastError(mLastError);
  432. }
  433. return res;
  434. }
  435. BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
  436. {
  437. LLMemType mt1(mMemType);
  438. resetLastError();
  439. setData(data, file_size);
  440. BOOL res = updateData();
  441. if ( res )
  442. {
  443. // Check to make sure that this instance has been initialized with data
  444. if (!getData() || (0 == getDataSize()))
  445. {
  446. setLastError("LLImageJ2C uninitialized");
  447. res = FALSE;
  448. }
  449. else
  450. {
  451. res = mImpl->getMetadata(*this);
  452. }
  453. }
  454. if (!mLastError.empty())
  455. {
  456. LLImage::setLastError(mLastError);
  457. }
  458. return res;
  459. }
  460. void LLImageJ2C::decodeFailed()
  461. {
  462. mDecoding = FALSE;
  463. }
  464. void LLImageJ2C::updateRawDiscardLevel()
  465. {
  466. mRawDiscardLevel = mMaxBytes ? calcDiscardLevelBytes(mMaxBytes) : mDiscardLevel;
  467. }
  468. LLImageJ2CImpl::~LLImageJ2CImpl()
  469. {
  470. }