PVRTDecompress.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /******************************************************************************
  2. @File PVRTDecompress.cpp
  3. @Title PVRTDecompress
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description PVRTC Texture Decompression.
  8. ******************************************************************************/
  9. /*****************************************************************************
  10. * INCLUDES
  11. *****************************************************************************/
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <limits.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include "PVRTDecompress.h"
  18. #include "PVRTTexture.h"
  19. #include "PVRTGlobal.h"
  20. /*****************************************************************************
  21. * defines and consts
  22. *****************************************************************************/
  23. #define PT_INDEX (2) // The Punch-through index
  24. #define BLK_Y_SIZE (4) // always 4 for all 2D block types
  25. #define BLK_X_MAX (8) // Max X dimension for blocks
  26. #define BLK_X_2BPP (8) // dimensions for the two formats
  27. #define BLK_X_4BPP (4)
  28. #define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))
  29. #define POWER_OF_2(X) util_number_is_power_2(X)
  30. /*
  31. Define an expression to either wrap or clamp large or small vals to the
  32. legal coordinate range
  33. */
  34. #define LIMIT_COORD(Val, Size, AssumeImageTiles) \
  35. ((AssumeImageTiles)? WRAP_COORD((Val), (Size)): PVRT_CLAMP((Val), 0, (Size)-1))
  36. /*****************************************************************************
  37. * Useful typedefs
  38. *****************************************************************************/
  39. typedef PVRTuint32 U32;
  40. typedef PVRTuint8 U8;
  41. /***********************************************************
  42. DECOMPRESSION ROUTINES
  43. ************************************************************/
  44. /*!***********************************************************************
  45. @Struct AMTC_BLOCK_STRUCT
  46. @Brief
  47. *************************************************************************/
  48. typedef struct
  49. {
  50. // Uses 64 bits pre block
  51. U32 PackedData[2];
  52. }AMTC_BLOCK_STRUCT;
  53. static void Decompress(AMTC_BLOCK_STRUCT *pCompressedData,
  54. const int Do2bitMode,
  55. const int XDim,
  56. const int YDim,
  57. const int AssumeImageTiles,
  58. unsigned char* pResultImage);
  59. /*!***********************************************************************
  60. @Function PVRTDecompressPVRTC
  61. @Input pCompressedData The PVRTC texture data to decompress
  62. @Input Do2bitMode Signifies whether the data is PVRTC2 or PVRTC4
  63. @Input XDim X dimension of the texture
  64. @Input YDim Y dimension of the texture
  65. @Modified pResultImage The decompressed texture data
  66. @Description Decompresses PVRTC to RGBA 8888
  67. *************************************************************************/
  68. void PVRTDecompressPVRTC(const void *pCompressedData,
  69. const int Do2bitMode,
  70. const int XDim,
  71. const int YDim,
  72. unsigned char* pResultImage)
  73. {
  74. Decompress((AMTC_BLOCK_STRUCT*)pCompressedData,Do2bitMode,XDim,YDim,1,pResultImage);
  75. }
  76. /*!***********************************************************************
  77. @Function util_number_is_power_2
  78. @Input input A number
  79. @Returns TRUE if the number is an integer power of two, else FALSE.
  80. @Description Check that a number is an integer power of two, i.e.
  81. 1, 2, 4, 8, ... etc.
  82. Returns FALSE for zero.
  83. *************************************************************************/
  84. int util_number_is_power_2( unsigned input )
  85. {
  86. unsigned minus1;
  87. if( !input ) return 0;
  88. minus1 = input - 1;
  89. return ( (input | minus1) == (input ^ minus1) ) ? 1 : 0;
  90. }
  91. /*!***********************************************************************
  92. @Function Unpack5554Colour
  93. @Input pBlock
  94. @Input ABColours
  95. @Description Given a block, extract the colour information and convert
  96. to 5554 formats
  97. *************************************************************************/
  98. static void Unpack5554Colour(const AMTC_BLOCK_STRUCT *pBlock,
  99. int ABColours[2][4])
  100. {
  101. U32 RawBits[2];
  102. int i;
  103. // Extract A and B
  104. RawBits[0] = pBlock->PackedData[1] & (0xFFFE); // 15 bits (shifted up by one)
  105. RawBits[1] = pBlock->PackedData[1] >> 16; // 16 bits
  106. // step through both colours
  107. for(i = 0; i < 2; i++)
  108. {
  109. // If completely opaque
  110. if(RawBits[i] & (1<<15))
  111. {
  112. // Extract R and G (both 5 bit)
  113. ABColours[i][0] = (RawBits[i] >> 10) & 0x1F;
  114. ABColours[i][1] = (RawBits[i] >> 5) & 0x1F;
  115. /*
  116. The precision of Blue depends on A or B. If A then we need to
  117. replicate the top bit to get 5 bits in total
  118. */
  119. ABColours[i][2] = RawBits[i] & 0x1F;
  120. if(i==0)
  121. {
  122. ABColours[0][2] |= ABColours[0][2] >> 4;
  123. }
  124. // set 4bit alpha fully on...
  125. ABColours[i][3] = 0xF;
  126. }
  127. else // Else if colour has variable translucency
  128. {
  129. /*
  130. Extract R and G (both 4 bit).
  131. (Leave a space on the end for the replication of bits
  132. */
  133. ABColours[i][0] = (RawBits[i] >> (8-1)) & 0x1E;
  134. ABColours[i][1] = (RawBits[i] >> (4-1)) & 0x1E;
  135. // replicate bits to truly expand to 5 bits
  136. ABColours[i][0] |= ABColours[i][0] >> 4;
  137. ABColours[i][1] |= ABColours[i][1] >> 4;
  138. // grab the 3(+padding) or 4 bits of blue and add an extra padding bit
  139. ABColours[i][2] = (RawBits[i] & 0xF) << 1;
  140. /*
  141. expand from 3 to 5 bits if this is from colour A, or 4 to 5 bits if from
  142. colour B
  143. */
  144. if(i==0)
  145. {
  146. ABColours[0][2] |= ABColours[0][2] >> 3;
  147. }
  148. else
  149. {
  150. ABColours[0][2] |= ABColours[0][2] >> 4;
  151. }
  152. // Set the alpha bits to be 3 + a zero on the end
  153. ABColours[i][3] = (RawBits[i] >> 11) & 0xE;
  154. }
  155. }
  156. }
  157. /*!***********************************************************************
  158. @Function UnpackModulations
  159. @Input pBlock
  160. @Input Do2bitMode
  161. @Input ModulationVals
  162. @Input ModulationModes
  163. @Input StartX
  164. @Input StartY
  165. @Description Given the block and the texture type and it's relative
  166. position in the 2x2 group of blocks, extract the bit
  167. patterns for the fully defined pixels.
  168. *************************************************************************/
  169. static void UnpackModulations(const AMTC_BLOCK_STRUCT *pBlock,
  170. const int Do2bitMode,
  171. int ModulationVals[8][16],
  172. int ModulationModes[8][16],
  173. int StartX,
  174. int StartY)
  175. {
  176. int BlockModMode;
  177. U32 ModulationBits;
  178. int x, y;
  179. BlockModMode= pBlock->PackedData[1] & 1;
  180. ModulationBits = pBlock->PackedData[0];
  181. // if it's in an interpolated mode
  182. if(Do2bitMode && BlockModMode)
  183. {
  184. /*
  185. run through all the pixels in the block. Note we can now treat all the
  186. "stored" values as if they have 2bits (even when they didn't!)
  187. */
  188. for(y = 0; y < BLK_Y_SIZE; y++)
  189. {
  190. for(x = 0; x < BLK_X_2BPP; x++)
  191. {
  192. ModulationModes[y+StartY][x+StartX] = BlockModMode;
  193. // if this is a stored value...
  194. if(((x^y)&1) == 0)
  195. {
  196. ModulationVals[y+StartY][x+StartX] = ModulationBits & 3;
  197. ModulationBits >>= 2;
  198. }
  199. }
  200. }
  201. }
  202. else if(Do2bitMode) // else if direct encoded 2bit mode - i.e. 1 mode bit per pixel
  203. {
  204. for(y = 0; y < BLK_Y_SIZE; y++)
  205. {
  206. for(x = 0; x < BLK_X_2BPP; x++)
  207. {
  208. ModulationModes[y+StartY][x+StartX] = BlockModMode;
  209. // double the bits so 0=> 00, and 1=>11
  210. if(ModulationBits & 1)
  211. {
  212. ModulationVals[y+StartY][x+StartX] = 0x3;
  213. }
  214. else
  215. {
  216. ModulationVals[y+StartY][x+StartX] = 0x0;
  217. }
  218. ModulationBits >>= 1;
  219. }
  220. }
  221. }
  222. else // else its the 4bpp mode so each value has 2 bits
  223. {
  224. for(y = 0; y < BLK_Y_SIZE; y++)
  225. {
  226. for(x = 0; x < BLK_X_4BPP; x++)
  227. {
  228. ModulationModes[y+StartY][x+StartX] = BlockModMode;
  229. ModulationVals[y+StartY][x+StartX] = ModulationBits & 3;
  230. ModulationBits >>= 2;
  231. }
  232. }
  233. }
  234. // make sure nothing is left over
  235. _ASSERT(ModulationBits==0);
  236. }
  237. /*!***********************************************************************
  238. @Function InterpolateColours
  239. @Input ColourP
  240. @Input ColourQ
  241. @Input ColourR
  242. @Input ColourS
  243. @Input Do2bitMode
  244. @Input x
  245. @Input y
  246. @Modified Result
  247. @Description This performs a HW bit accurate interpolation of either the
  248. A or B colours for a particular pixel.
  249. NOTE: It is assumed that the source colours are in ARGB 5554
  250. format - This means that some "preparation" of the values will
  251. be necessary.
  252. *************************************************************************/
  253. static void InterpolateColours(const int ColourP[4],
  254. const int ColourQ[4],
  255. const int ColourR[4],
  256. const int ColourS[4],
  257. const int Do2bitMode,
  258. const int x,
  259. const int y,
  260. int Result[4])
  261. {
  262. int u, v, uscale;
  263. int k;
  264. int tmp1, tmp2;
  265. int P[4], Q[4], R[4], S[4];
  266. // Copy the colours
  267. for(k = 0; k < 4; k++)
  268. {
  269. P[k] = ColourP[k];
  270. Q[k] = ColourQ[k];
  271. R[k] = ColourR[k];
  272. S[k] = ColourS[k];
  273. }
  274. // put the x and y values into the right range
  275. v = (y & 0x3) | ((~y & 0x2) << 1);
  276. if(Do2bitMode)
  277. u = (x & 0x7) | ((~x & 0x4) << 1);
  278. else
  279. u = (x & 0x3) | ((~x & 0x2) << 1);
  280. // get the u and v scale amounts
  281. v = v - BLK_Y_SIZE/2;
  282. if(Do2bitMode)
  283. {
  284. u = u - BLK_X_2BPP/2;
  285. uscale = 8;
  286. }
  287. else
  288. {
  289. u = u - BLK_X_4BPP/2;
  290. uscale = 4;
  291. }
  292. for(k = 0; k < 4; k++)
  293. {
  294. tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
  295. tmp2 = R[k] * uscale + u * (S[k] - R[k]);
  296. tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
  297. Result[k] = tmp1;
  298. }
  299. // Lop off the appropriate number of bits to get us to 8 bit precision
  300. if(Do2bitMode)
  301. {
  302. // do RGB
  303. for(k = 0; k < 3; k++)
  304. {
  305. Result[k] >>= 2;
  306. }
  307. Result[3] >>= 1;
  308. }
  309. else
  310. {
  311. // do RGB (A is ok)
  312. for(k = 0; k < 3; k++)
  313. {
  314. Result[k] >>= 1;
  315. }
  316. }
  317. // sanity check
  318. for(k = 0; k < 4; k++)
  319. {
  320. _ASSERT(Result[k] < 256);
  321. }
  322. /*
  323. Convert from 5554 to 8888
  324. do RGB 5.3 => 8
  325. */
  326. for(k = 0; k < 3; k++)
  327. {
  328. Result[k] += Result[k] >> 5;
  329. }
  330. Result[3] += Result[3] >> 4;
  331. // 2nd sanity check
  332. for(k = 0; k < 4; k++)
  333. {
  334. _ASSERT(Result[k] < 256);
  335. }
  336. }
  337. /*!***********************************************************************
  338. @Function GetModulationValue
  339. @Input x
  340. @Input y
  341. @Input Do2bitMode
  342. @Input ModulationVals
  343. @Input ModulationModes
  344. @Input Mod
  345. @Input DoPT
  346. @Description Get the modulation value as a numerator of a fraction of 8ths
  347. *************************************************************************/
  348. static void GetModulationValue(int x,
  349. int y,
  350. const int Do2bitMode,
  351. const int ModulationVals[8][16],
  352. const int ModulationModes[8][16],
  353. int *Mod,
  354. int *DoPT)
  355. {
  356. static const int RepVals0[4] = {0, 3, 5, 8};
  357. static const int RepVals1[4] = {0, 4, 4, 8};
  358. int ModVal;
  359. // Map X and Y into the local 2x2 block
  360. y = (y & 0x3) | ((~y & 0x2) << 1);
  361. if(Do2bitMode)
  362. x = (x & 0x7) | ((~x & 0x4) << 1);
  363. else
  364. x = (x & 0x3) | ((~x & 0x2) << 1);
  365. // assume no PT for now
  366. *DoPT = 0;
  367. // extract the modulation value. If a simple encoding
  368. if(ModulationModes[y][x]==0)
  369. {
  370. ModVal = RepVals0[ModulationVals[y][x]];
  371. }
  372. else if(Do2bitMode)
  373. {
  374. // if this is a stored value
  375. if(((x^y)&1)==0)
  376. ModVal = RepVals0[ModulationVals[y][x]];
  377. else if(ModulationModes[y][x] == 1) // else average from the neighbours if H&V interpolation..
  378. {
  379. ModVal = (RepVals0[ModulationVals[y-1][x]] +
  380. RepVals0[ModulationVals[y+1][x]] +
  381. RepVals0[ModulationVals[y][x-1]] +
  382. RepVals0[ModulationVals[y][x+1]] + 2) / 4;
  383. }
  384. else if(ModulationModes[y][x] == 2) // else if H-Only
  385. {
  386. ModVal = (RepVals0[ModulationVals[y][x-1]] +
  387. RepVals0[ModulationVals[y][x+1]] + 1) / 2;
  388. }
  389. else // else it's V-Only
  390. {
  391. ModVal = (RepVals0[ModulationVals[y-1][x]] +
  392. RepVals0[ModulationVals[y+1][x]] + 1) / 2;
  393. }
  394. }
  395. else // else it's 4BPP and PT encoding
  396. {
  397. ModVal = RepVals1[ModulationVals[y][x]];
  398. *DoPT = ModulationVals[y][x] == PT_INDEX;
  399. }
  400. *Mod =ModVal;
  401. }
  402. /*!***********************************************************************
  403. @Function TwiddleUV
  404. @Input YSize Y dimension of the texture in pixels
  405. @Input XSize X dimension of the texture in pixels
  406. @Input YPos Pixel Y position
  407. @Input XPos Pixel X position
  408. @Returns The twiddled offset of the pixel
  409. @Description Given the Block (or pixel) coordinates and the dimension of
  410. the texture in blocks (or pixels) this returns the twiddled
  411. offset of the block (or pixel) from the start of the map.
  412. NOTE the dimensions of the texture must be a power of 2
  413. *************************************************************************/
  414. static int DisableTwiddlingRoutine = 0;
  415. static U32 TwiddleUV(U32 YSize, U32 XSize, U32 YPos, U32 XPos)
  416. {
  417. U32 Twiddled;
  418. U32 MinDimension;
  419. U32 MaxValue;
  420. U32 SrcBitPos;
  421. U32 DstBitPos;
  422. int ShiftCount;
  423. _ASSERT(YPos < YSize);
  424. _ASSERT(XPos < XSize);
  425. _ASSERT(POWER_OF_2(YSize));
  426. _ASSERT(POWER_OF_2(XSize));
  427. if(YSize < XSize)
  428. {
  429. MinDimension = YSize;
  430. MaxValue = XPos;
  431. }
  432. else
  433. {
  434. MinDimension = XSize;
  435. MaxValue = YPos;
  436. }
  437. // Nasty hack to disable twiddling
  438. if(DisableTwiddlingRoutine)
  439. return (YPos* XSize + XPos);
  440. // Step through all the bits in the "minimum" dimension
  441. SrcBitPos = 1;
  442. DstBitPos = 1;
  443. Twiddled = 0;
  444. ShiftCount = 0;
  445. while(SrcBitPos < MinDimension)
  446. {
  447. if(YPos & SrcBitPos)
  448. {
  449. Twiddled |= DstBitPos;
  450. }
  451. if(XPos & SrcBitPos)
  452. {
  453. Twiddled |= (DstBitPos << 1);
  454. }
  455. SrcBitPos <<= 1;
  456. DstBitPos <<= 2;
  457. ShiftCount += 1;
  458. }
  459. // prepend any unused bits
  460. MaxValue >>= ShiftCount;
  461. Twiddled |= (MaxValue << (2*ShiftCount));
  462. return Twiddled;
  463. }
  464. /*!***********************************************************************
  465. @Function Decompress
  466. @Input pCompressedData The PVRTC texture data to decompress
  467. @Input Do2BitMode Signifies whether the data is PVRTC2 or PVRTC4
  468. @Input XDim X dimension of the texture
  469. @Input YDim Y dimension of the texture
  470. @Input AssumeImageTiles Assume the texture data tiles
  471. @Modified pResultImage The decompressed texture data
  472. @Description Decompresses PVRTC to RGBA 8888
  473. *************************************************************************/
  474. static void Decompress(AMTC_BLOCK_STRUCT *pCompressedData,
  475. const int Do2bitMode,
  476. const int XDim,
  477. const int YDim,
  478. const int AssumeImageTiles,
  479. unsigned char* pResultImage)
  480. {
  481. int x, y;
  482. int i, j;
  483. int BlkX, BlkY;
  484. int BlkXp1, BlkYp1;
  485. int XBlockSize;
  486. int BlkXDim, BlkYDim;
  487. int StartX, StartY;
  488. int ModulationVals[8][16];
  489. int ModulationModes[8][16];
  490. int Mod, DoPT;
  491. unsigned int uPosition;
  492. // local neighbourhood of blocks
  493. AMTC_BLOCK_STRUCT *pBlocks[2][2];
  494. AMTC_BLOCK_STRUCT *pPrevious[2][2] = {{NULL, NULL}, {NULL, NULL}};
  495. // Low precision colours extracted from the blocks
  496. struct
  497. {
  498. int Reps[2][4];
  499. }Colours5554[2][2];
  500. // Interpolated A and B colours for the pixel
  501. int ASig[4], BSig[4];
  502. int Result[4];
  503. if(Do2bitMode)
  504. XBlockSize = BLK_X_2BPP;
  505. else
  506. XBlockSize = BLK_X_4BPP;
  507. // For MBX don't allow the sizes to get too small
  508. BlkXDim = PVRT_MAX(2, XDim / XBlockSize);
  509. BlkYDim = PVRT_MAX(2, YDim / BLK_Y_SIZE);
  510. /*
  511. Step through the pixels of the image decompressing each one in turn
  512. Note that this is a hideously inefficient way to do this!
  513. */
  514. for(y = 0; y < YDim; y++)
  515. {
  516. for(x = 0; x < XDim; x++)
  517. {
  518. // map this pixel to the top left neighbourhood of blocks
  519. BlkX = (x - XBlockSize/2);
  520. BlkY = (y - BLK_Y_SIZE/2);
  521. BlkX = LIMIT_COORD(BlkX, XDim, AssumeImageTiles);
  522. BlkY = LIMIT_COORD(BlkY, YDim, AssumeImageTiles);
  523. BlkX /= XBlockSize;
  524. BlkY /= BLK_Y_SIZE;
  525. // compute the positions of the other 3 blocks
  526. BlkXp1 = LIMIT_COORD(BlkX+1, BlkXDim, AssumeImageTiles);
  527. BlkYp1 = LIMIT_COORD(BlkY+1, BlkYDim, AssumeImageTiles);
  528. // Map to block memory locations
  529. pBlocks[0][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkX);
  530. pBlocks[0][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkY, BlkXp1);
  531. pBlocks[1][0] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkX);
  532. pBlocks[1][1] = pCompressedData +TwiddleUV(BlkYDim, BlkXDim, BlkYp1, BlkXp1);
  533. /*
  534. extract the colours and the modulation information IF the previous values
  535. have changed.
  536. */
  537. if(memcmp(pPrevious, pBlocks, 4*sizeof(void*)) != 0)
  538. {
  539. StartY = 0;
  540. for(i = 0; i < 2; i++)
  541. {
  542. StartX = 0;
  543. for(j = 0; j < 2; j++)
  544. {
  545. Unpack5554Colour(pBlocks[i][j], Colours5554[i][j].Reps);
  546. UnpackModulations(pBlocks[i][j],
  547. Do2bitMode,
  548. ModulationVals,
  549. ModulationModes,
  550. StartX, StartY);
  551. StartX += XBlockSize;
  552. }
  553. StartY += BLK_Y_SIZE;
  554. }
  555. // make a copy of the new pointers
  556. memcpy(pPrevious, pBlocks, 4*sizeof(void*));
  557. }
  558. // decompress the pixel. First compute the interpolated A and B signals
  559. InterpolateColours(Colours5554[0][0].Reps[0],
  560. Colours5554[0][1].Reps[0],
  561. Colours5554[1][0].Reps[0],
  562. Colours5554[1][1].Reps[0],
  563. Do2bitMode, x, y,
  564. ASig);
  565. InterpolateColours(Colours5554[0][0].Reps[1],
  566. Colours5554[0][1].Reps[1],
  567. Colours5554[1][0].Reps[1],
  568. Colours5554[1][1].Reps[1],
  569. Do2bitMode, x, y,
  570. BSig);
  571. GetModulationValue(x,y, Do2bitMode, (const int (*)[16])ModulationVals, (const int (*)[16])ModulationModes,
  572. &Mod, &DoPT);
  573. // compute the modulated colour
  574. for(i = 0; i < 4; i++)
  575. {
  576. Result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
  577. Result[i] >>= 3;
  578. }
  579. if(DoPT)
  580. Result[3] = 0;
  581. // Store the result in the output image
  582. uPosition = (x+y*XDim)<<2;
  583. pResultImage[uPosition+0] = (U8)Result[0];
  584. pResultImage[uPosition+1] = (U8)Result[1];
  585. pResultImage[uPosition+2] = (U8)Result[2];
  586. pResultImage[uPosition+3] = (U8)Result[3];
  587. }
  588. }
  589. }
  590. /****************************
  591. ** ETC Compression
  592. ****************************/
  593. /*****************************************************************************
  594. Macros
  595. *****************************************************************************/
  596. #define _CLAMP_(X,Xmin,Xmax) ( (X)<(Xmax) ? ( (X)<(Xmin)?(Xmin):(X) ) : (Xmax) )
  597. /*****************************************************************************
  598. Constants
  599. ******************************************************************************/
  600. unsigned int ETC_FLIP = 0x01000000;
  601. unsigned int ETC_DIFF = 0x02000000;
  602. const int mod[8][4]={{2, 8,-2,-8},
  603. {5, 17, -5, -17},
  604. {9, 29, -9, -29},
  605. {13, 42, -13, -42},
  606. {18, 60, -18, -60},
  607. {24, 80, -24, -80},
  608. {33, 106, -33, -106},
  609. {47, 183, -47, -183}};
  610. /*!***********************************************************************
  611. @Function modifyPixel
  612. @Input red Red value of pixel
  613. @Input green Green value of pixel
  614. @Input blue Blue value of pixel
  615. @Input x Pixel x position in block
  616. @Input y Pixel y position in block
  617. @Input modBlock Values for the current block
  618. @Input modTable Modulation values
  619. @Returns Returns actual pixel colour
  620. @Description Used by ETCTextureDecompress
  621. *************************************************************************/
  622. unsigned long modifyPixel(int red, int green, int blue, int x, int y, unsigned long modBlock, int modTable)
  623. {
  624. int index = x*4+y, pixelMod;
  625. unsigned long mostSig = modBlock<<1;
  626. if (index<8)
  627. pixelMod = mod[modTable][((modBlock>>(index+24))&0x1)+((mostSig>>(index+8))&0x2)];
  628. else
  629. pixelMod = mod[modTable][((modBlock>>(index+8))&0x1)+((mostSig>>(index-8))&0x2)];
  630. red = _CLAMP_(red+pixelMod,0,255);
  631. green = _CLAMP_(green+pixelMod,0,255);
  632. blue = _CLAMP_(blue+pixelMod,0,255);
  633. return ((red<<16) + (green<<8) + blue)|0xff000000;
  634. }
  635. /*!***********************************************************************
  636. @Function ETCTextureDecompress
  637. @Input pSrcData The ETC texture data to decompress
  638. @Input x X dimension of the texture
  639. @Input y Y dimension of the texture
  640. @Modified pDestData The decompressed texture data
  641. @Input nMode The format of the data
  642. @Returns The number of bytes of ETC data decompressed
  643. @Description Decompresses ETC to RGBA 8888
  644. *************************************************************************/
  645. int ETCTextureDecompress(const void * const pSrcData, const int &x, const int &y, const void *pDestData,const int &/*nMode*/)
  646. {
  647. unsigned long blockTop, blockBot, *input = (unsigned long*)pSrcData, *output;
  648. unsigned char red1, green1, blue1, red2, green2, blue2;
  649. bool bFlip, bDiff;
  650. int modtable1,modtable2;
  651. for(int i=0;i<y;i+=4)
  652. {
  653. for(int m=0;m<x;m+=4)
  654. {
  655. blockTop = *(input++);
  656. blockBot = *(input++);
  657. output = (unsigned long*)pDestData + i*x +m;
  658. // check flipbit
  659. bFlip = (blockTop & ETC_FLIP) != 0;
  660. bDiff = (blockTop & ETC_DIFF) != 0;
  661. if(bDiff)
  662. { // differential mode 5 colour bits + 3 difference bits
  663. // get base colour for subblock 1
  664. blue1 = (unsigned char)((blockTop&0xf80000)>>16);
  665. green1 = (unsigned char)((blockTop&0xf800)>>8);
  666. red1 = (unsigned char)(blockTop&0xf8);
  667. // get differential colour for subblock 2
  668. signed char blues = (signed char)(blue1>>3) + ((signed char) ((blockTop & 0x70000) >> 11)>>5);
  669. signed char greens = (signed char)(green1>>3) + ((signed char)((blockTop & 0x700) >>3)>>5);
  670. signed char reds = (signed char)(red1>>3) + ((signed char)((blockTop & 0x7)<<5)>>5);
  671. blue2 = (unsigned char)blues;
  672. green2 = (unsigned char)greens;
  673. red2 = (unsigned char)reds;
  674. red1 = red1 +(red1>>5); // copy bits to lower sig
  675. green1 = green1 + (green1>>5); // copy bits to lower sig
  676. blue1 = blue1 + (blue1>>5); // copy bits to lower sig
  677. red2 = (red2<<3) +(red2>>2); // copy bits to lower sig
  678. green2 = (green2<<3) + (green2>>2); // copy bits to lower sig
  679. blue2 = (blue2<<3) + (blue2>>2); // copy bits to lower sig
  680. }
  681. else
  682. { // individual mode 4 + 4 colour bits
  683. // get base colour for subblock 1
  684. blue1 = (unsigned char)((blockTop&0xf00000)>>16);
  685. blue1 = blue1 +(blue1>>4); // copy bits to lower sig
  686. green1 = (unsigned char)((blockTop&0xf000)>>8);
  687. green1 = green1 + (green1>>4); // copy bits to lower sig
  688. red1 = (unsigned char)(blockTop&0xf0);
  689. red1 = red1 + (red1>>4); // copy bits to lower sig
  690. // get base colour for subblock 2
  691. blue2 = (unsigned char)((blockTop&0xf0000)>>12);
  692. blue2 = blue2 +(blue2>>4); // copy bits to lower sig
  693. green2 = (unsigned char)((blockTop&0xf00)>>4);
  694. green2 = green2 + (green2>>4); // copy bits to lower sig
  695. red2 = (unsigned char)((blockTop&0xf)<<4);
  696. red2 = red2 + (red2>>4); // copy bits to lower sig
  697. }
  698. // get the modtables for each subblock
  699. modtable1 = (blockTop>>29)&0x7;
  700. modtable2 = (blockTop>>26)&0x7;
  701. if(!bFlip)
  702. { // 2 2x4 blocks side by side
  703. for(int j=0;j<4;j++) // vertical
  704. {
  705. for(int k=0;k<2;k++) // horizontal
  706. {
  707. *(output+j*x+k) = modifyPixel(red1,green1,blue1,k,j,blockBot,modtable1);
  708. *(output+j*x+k+2) = modifyPixel(red2,green2,blue2,k+2,j,blockBot,modtable2);
  709. }
  710. }
  711. }
  712. else
  713. { // 2 4x2 blocks on top of each other
  714. for(int j=0;j<2;j++)
  715. {
  716. for(int k=0;k<4;k++)
  717. {
  718. *(output+j*x+k) = modifyPixel(red1,green1,blue1,k,j,blockBot,modtable1);
  719. *(output+(j+2)*x+k) = modifyPixel(red2,green2,blue2,k,j+2,blockBot,modtable2);
  720. }
  721. }
  722. }
  723. }
  724. }
  725. return x*y/2;
  726. }
  727. /*!***********************************************************************
  728. @Function PVRTDecompressETC
  729. @Input pSrcData The ETC texture data to decompress
  730. @Input x X dimension of the texture
  731. @Input y Y dimension of the texture
  732. @Modified pDestData The decompressed texture data
  733. @Input nMode The format of the data
  734. @Returns The number of bytes of ETC data decompressed
  735. @Description Decompresses ETC to RGBA 8888
  736. *************************************************************************/
  737. int PVRTDecompressETC(const void * const pSrcData,
  738. const unsigned int &x,
  739. const unsigned int &y,
  740. void *pDestData,
  741. const int &nMode)
  742. {
  743. int i32read;
  744. if(x<ETC_MIN_TEXWIDTH || y<ETC_MIN_TEXHEIGHT)
  745. { // decompress into a buffer big enough to take the minimum size
  746. char* pTempBuffer = (char*)malloc(PVRT_MAX(x,ETC_MIN_TEXWIDTH)*PVRT_MAX(y,ETC_MIN_TEXHEIGHT)*4);
  747. i32read = ETCTextureDecompress(pSrcData,PVRT_MAX(x,ETC_MIN_TEXWIDTH),PVRT_MAX(y,ETC_MIN_TEXHEIGHT),pTempBuffer,nMode);
  748. for(unsigned int i=0;i<y;i++)
  749. { // copy from larger temp buffer to output data
  750. memcpy((char*)(pDestData)+i*x*4,pTempBuffer+PVRT_MAX(x,ETC_MIN_TEXWIDTH)*4*i,x*4);
  751. }
  752. if(pTempBuffer) free(pTempBuffer);
  753. }
  754. else // decompress larger MIP levels straight into the output data
  755. i32read = ETCTextureDecompress(pSrcData,x,y,pDestData,nMode);
  756. // swap r and b channels
  757. unsigned char* pSwap = (unsigned char*)pDestData, swap;
  758. for(unsigned int i=0;i<y;i++)
  759. for(unsigned int j=0;j<x;j++)
  760. {
  761. swap = pSwap[0];
  762. pSwap[0] = pSwap[2];
  763. pSwap[2] = swap;
  764. pSwap+=4;
  765. }
  766. return i32read;
  767. }
  768. /*****************************************************************************
  769. End of file (PVRTDecompress.cpp)
  770. *****************************************************************************/