EtcBlock4x4Encoding_ETC1.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. /*
  2. * Copyright 2015 The Etc2Comp Authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. EtcBlock4x4Encoding_ETC1.cpp
  18. Block4x4Encoding_ETC1 is the encoder to use when targetting file format ETC1. This encoder is also
  19. used for the ETC1 subset of file format RGB8, RGBA8 and RGB8A1
  20. */
  21. #include "EtcConfig.h"
  22. #include "EtcBlock4x4Encoding_ETC1.h"
  23. #include "EtcBlock4x4.h"
  24. #include "EtcBlock4x4EncodingBits.h"
  25. #include "EtcDifferentialTrys.h"
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <assert.h>
  29. #include <float.h>
  30. #include <limits>
  31. namespace Etc
  32. {
  33. // pixel processing order if the flip bit = 0 (horizontal split)
  34. const unsigned int Block4x4Encoding_ETC1::s_auiPixelOrderFlip0[PIXELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
  35. // pixel processing order if the flip bit = 1 (vertical split)
  36. const unsigned int Block4x4Encoding_ETC1::s_auiPixelOrderFlip1[PIXELS] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 };
  37. // pixel processing order for horizontal scan (ETC normally does a vertical scan)
  38. const unsigned int Block4x4Encoding_ETC1::s_auiPixelOrderHScan[PIXELS] = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
  39. // pixel indices for different block halves
  40. const unsigned int Block4x4Encoding_ETC1::s_auiLeftPixelMapping[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
  41. const unsigned int Block4x4Encoding_ETC1::s_auiRightPixelMapping[8] = { 8, 9, 10, 11, 12, 13, 14, 15 };
  42. const unsigned int Block4x4Encoding_ETC1::s_auiTopPixelMapping[8] = { 0, 1, 4, 5, 8, 9, 12, 13 };
  43. const unsigned int Block4x4Encoding_ETC1::s_auiBottomPixelMapping[8] = { 2, 3, 6, 7, 10, 11, 14, 15 };
  44. // CW ranges that the ETC1 decoders use
  45. // CW is basically a contrast for the different selector bits, since these values are offsets to the base color
  46. // the first axis in the array is indexed by the CW in the encoding bits
  47. // the second axis in the array is indexed by the selector bits
  48. float Block4x4Encoding_ETC1::s_aafCwTable[CW_RANGES][SELECTORS] =
  49. {
  50. { 2.0f / 255.0f, 8.0f / 255.0f, -2.0f / 255.0f, -8.0f / 255.0f },
  51. { 5.0f / 255.0f, 17.0f / 255.0f, -5.0f / 255.0f, -17.0f / 255.0f },
  52. { 9.0f / 255.0f, 29.0f / 255.0f, -9.0f / 255.0f, -29.0f / 255.0f },
  53. { 13.0f / 255.0f, 42.0f / 255.0f, -13.0f / 255.0f, -42.0f / 255.0f },
  54. { 18.0f / 255.0f, 60.0f / 255.0f, -18.0f / 255.0f, -60.0f / 255.0f },
  55. { 24.0f / 255.0f, 80.0f / 255.0f, -24.0f / 255.0f, -80.0f / 255.0f },
  56. { 33.0f / 255.0f, 106.0f / 255.0f, -33.0f / 255.0f, -106.0f / 255.0f },
  57. { 47.0f / 255.0f, 183.0f / 255.0f, -47.0f / 255.0f, -183.0f / 255.0f }
  58. };
  59. // ----------------------------------------------------------------------------------------------------
  60. //
  61. Block4x4Encoding_ETC1::Block4x4Encoding_ETC1(void)
  62. {
  63. m_mode = MODE_ETC1;
  64. m_boolDiff = false;
  65. m_boolFlip = false;
  66. m_frgbaColor1 = ColorFloatRGBA();
  67. m_frgbaColor2 = ColorFloatRGBA();
  68. m_uiCW1 = 0;
  69. m_uiCW2 = 0;
  70. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  71. {
  72. m_auiSelectors[uiPixel] = 0;
  73. m_afDecodedAlphas[uiPixel] = 1.0f;
  74. }
  75. m_boolMostLikelyFlip = false;
  76. m_fError = -1.0f;
  77. m_fError1 = -1.0f;
  78. m_fError2 = -1.0f;
  79. m_boolSeverelyBentDifferentialColors = false;
  80. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  81. {
  82. m_afDecodedAlphas[uiPixel] = 1.0f;
  83. }
  84. }
  85. Block4x4Encoding_ETC1::~Block4x4Encoding_ETC1(void) {}
  86. // ----------------------------------------------------------------------------------------------------
  87. // initialization prior to encoding
  88. // a_pblockParent points to the block associated with this encoding
  89. // a_errormetric is used to choose the best encoding
  90. // a_pafrgbaSource points to a 4x4 block subset of the source image
  91. // a_paucEncodingBits points to the final encoding bits
  92. //
  93. void Block4x4Encoding_ETC1::InitFromSource(Block4x4 *a_pblockParent,
  94. ColorFloatRGBA *a_pafrgbaSource,
  95. unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric)
  96. {
  97. Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
  98. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  99. {
  100. m_afDecodedAlphas[uiPixel] = 1.0f;
  101. }
  102. m_fError = -1.0f;
  103. m_pencodingbitsRGB8 = (Block4x4EncodingBits_RGB8 *)(a_paucEncodingBits);
  104. }
  105. // ----------------------------------------------------------------------------------------------------
  106. // initialization from the encoding bits of a previous encoding
  107. // a_pblockParent points to the block associated with this encoding
  108. // a_errormetric is used to choose the best encoding
  109. // a_pafrgbaSource points to a 4x4 block subset of the source image
  110. // a_paucEncodingBits points to the final encoding bits of a previous encoding
  111. //
  112. void Block4x4Encoding_ETC1::InitFromEncodingBits(Block4x4 *a_pblockParent,
  113. unsigned char *a_paucEncodingBits,
  114. ColorFloatRGBA *a_pafrgbaSource,
  115. ErrorMetric a_errormetric)
  116. {
  117. Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
  118. m_fError = -1.0f;
  119. m_pencodingbitsRGB8 = (Block4x4EncodingBits_RGB8 *)a_paucEncodingBits;
  120. m_mode = MODE_ETC1;
  121. m_boolDiff = m_pencodingbitsRGB8->individual.diff;
  122. m_boolFlip = m_pencodingbitsRGB8->individual.flip;
  123. if (m_boolDiff)
  124. {
  125. int iR2 = (int)(m_pencodingbitsRGB8->differential.red1 + m_pencodingbitsRGB8->differential.dred2);
  126. if (iR2 < 0)
  127. {
  128. iR2 = 0;
  129. }
  130. else if (iR2 > 31)
  131. {
  132. iR2 = 31;
  133. }
  134. int iG2 = (int)(m_pencodingbitsRGB8->differential.green1 + m_pencodingbitsRGB8->differential.dgreen2);
  135. if (iG2 < 0)
  136. {
  137. iG2 = 0;
  138. }
  139. else if (iG2 > 31)
  140. {
  141. iG2 = 31;
  142. }
  143. int iB2 = (int)(m_pencodingbitsRGB8->differential.blue1 + m_pencodingbitsRGB8->differential.dblue2);
  144. if (iB2 < 0)
  145. {
  146. iB2 = 0;
  147. }
  148. else if (iB2 > 31)
  149. {
  150. iB2 = 31;
  151. }
  152. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB5(m_pencodingbitsRGB8->differential.red1, m_pencodingbitsRGB8->differential.green1, m_pencodingbitsRGB8->differential.blue1);
  153. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB5((unsigned char)iR2, (unsigned char)iG2, (unsigned char)iB2);
  154. }
  155. else
  156. {
  157. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4(m_pencodingbitsRGB8->individual.red1, m_pencodingbitsRGB8->individual.green1, m_pencodingbitsRGB8->individual.blue1);
  158. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4(m_pencodingbitsRGB8->individual.red2, m_pencodingbitsRGB8->individual.green2, m_pencodingbitsRGB8->individual.blue2);
  159. }
  160. m_uiCW1 = m_pencodingbitsRGB8->individual.cw1;
  161. m_uiCW2 = m_pencodingbitsRGB8->individual.cw2;
  162. InitFromEncodingBits_Selectors();
  163. Decode();
  164. CalcBlockError();
  165. }
  166. // ----------------------------------------------------------------------------------------------------
  167. // init the selectors from a prior encoding
  168. //
  169. void Block4x4Encoding_ETC1::InitFromEncodingBits_Selectors(void)
  170. {
  171. unsigned char *paucSelectors = (unsigned char *)&m_pencodingbitsRGB8->individual.selectors;
  172. for (unsigned int iPixel = 0; iPixel < PIXELS; iPixel++)
  173. {
  174. unsigned int uiByteMSB = (unsigned int)(1 - (iPixel / 8));
  175. unsigned int uiByteLSB = (unsigned int)(3 - (iPixel / 8));
  176. unsigned int uiShift = (unsigned int)(iPixel & 7);
  177. unsigned int uiSelectorMSB = (unsigned int)((paucSelectors[uiByteMSB] >> uiShift) & 1);
  178. unsigned int uiSelectorLSB = (unsigned int)((paucSelectors[uiByteLSB] >> uiShift) & 1);
  179. m_auiSelectors[iPixel] = (uiSelectorMSB << 1) + uiSelectorLSB;
  180. }
  181. }
  182. // ----------------------------------------------------------------------------------------------------
  183. // perform a single encoding iteration
  184. // replace the encoding if a better encoding was found
  185. // subsequent iterations generally take longer for each iteration
  186. // set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
  187. //
  188. void Block4x4Encoding_ETC1::PerformIteration(float a_fEffort)
  189. {
  190. assert(!m_boolDone);
  191. switch (m_uiEncodingIterations)
  192. {
  193. case 0:
  194. PerformFirstIteration();
  195. break;
  196. case 1:
  197. TryDifferential(m_boolMostLikelyFlip, 1, 0, 0);
  198. break;
  199. case 2:
  200. TryIndividual(m_boolMostLikelyFlip, 1);
  201. if (a_fEffort <= 49.5f)
  202. {
  203. m_boolDone = true;
  204. }
  205. break;
  206. case 3:
  207. TryDifferential(!m_boolMostLikelyFlip, 1, 0, 0);
  208. if (a_fEffort <= 59.5f)
  209. {
  210. m_boolDone = true;
  211. }
  212. break;
  213. case 4:
  214. TryIndividual(!m_boolMostLikelyFlip, 1);
  215. if (a_fEffort <= 69.5f)
  216. {
  217. m_boolDone = true;
  218. }
  219. break;
  220. case 5:
  221. TryDegenerates1();
  222. if (a_fEffort <= 79.5f)
  223. {
  224. m_boolDone = true;
  225. }
  226. break;
  227. case 6:
  228. TryDegenerates2();
  229. if (a_fEffort <= 89.5f)
  230. {
  231. m_boolDone = true;
  232. }
  233. break;
  234. case 7:
  235. TryDegenerates3();
  236. if (a_fEffort <= 99.5f)
  237. {
  238. m_boolDone = true;
  239. }
  240. break;
  241. case 8:
  242. TryDegenerates4();
  243. m_boolDone = true;
  244. break;
  245. default:
  246. assert(0);
  247. break;
  248. }
  249. m_uiEncodingIterations++;
  250. SetDoneIfPerfect();
  251. }
  252. // ----------------------------------------------------------------------------------------------------
  253. // find best initial encoding to ensure block has a valid encoding
  254. //
  255. void Block4x4Encoding_ETC1::PerformFirstIteration(void)
  256. {
  257. CalculateMostLikelyFlip();
  258. m_fError = FLT_MAX;
  259. TryDifferential(m_boolMostLikelyFlip, 0, 0, 0);
  260. SetDoneIfPerfect();
  261. if (m_boolDone)
  262. {
  263. return;
  264. }
  265. TryIndividual(m_boolMostLikelyFlip, 0);
  266. SetDoneIfPerfect();
  267. if (m_boolDone)
  268. {
  269. return;
  270. }
  271. TryDifferential(!m_boolMostLikelyFlip, 0, 0, 0);
  272. SetDoneIfPerfect();
  273. if (m_boolDone)
  274. {
  275. return;
  276. }
  277. TryIndividual(!m_boolMostLikelyFlip, 0);
  278. }
  279. // ----------------------------------------------------------------------------------------------------
  280. // algorithm:
  281. // create a source average color for the Left, Right, Top and Bottom halves using the 8 pixels in each half
  282. // note: the "gray line" is the line of equal delta RGB that goes thru the average color
  283. // for each half:
  284. // see how close each of the 8 pixels are to the "gray line" that goes thru the source average color
  285. // create an error value that is the sum of the distances from the gray line
  286. // h_error is the sum of Left and Right errors
  287. // v_error is the sum of Top and Bottom errors
  288. //
  289. void Block4x4Encoding_ETC1::CalculateMostLikelyFlip(void)
  290. {
  291. static const bool DEBUG_PRINT = false;
  292. CalculateSourceAverages();
  293. float fLeftGrayErrorSum = 0.0f;
  294. float fRightGrayErrorSum = 0.0f;
  295. float fTopGrayErrorSum = 0.0f;
  296. float fBottomGrayErrorSum = 0.0f;
  297. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  298. {
  299. ColorFloatRGBA *pfrgbaLeft = &m_pafrgbaSource[uiPixel];
  300. ColorFloatRGBA *pfrgbaRight = &m_pafrgbaSource[uiPixel + 8];
  301. ColorFloatRGBA *pfrgbaTop = &m_pafrgbaSource[s_auiTopPixelMapping[uiPixel]];
  302. ColorFloatRGBA *pfrgbaBottom = &m_pafrgbaSource[s_auiBottomPixelMapping[uiPixel]];
  303. float fLeftGrayError = CalcGrayDistance2(*pfrgbaLeft, m_frgbaSourceAverageLeft);
  304. float fRightGrayError = CalcGrayDistance2(*pfrgbaRight, m_frgbaSourceAverageRight);
  305. float fTopGrayError = CalcGrayDistance2(*pfrgbaTop, m_frgbaSourceAverageTop);
  306. float fBottomGrayError = CalcGrayDistance2(*pfrgbaBottom, m_frgbaSourceAverageBottom);
  307. fLeftGrayErrorSum += fLeftGrayError;
  308. fRightGrayErrorSum += fRightGrayError;
  309. fTopGrayErrorSum += fTopGrayError;
  310. fBottomGrayErrorSum += fBottomGrayError;
  311. }
  312. if (DEBUG_PRINT)
  313. {
  314. printf("\n%.2f %.2f\n", fLeftGrayErrorSum + fRightGrayErrorSum, fTopGrayErrorSum + fBottomGrayErrorSum);
  315. }
  316. m_boolMostLikelyFlip = (fTopGrayErrorSum + fBottomGrayErrorSum) < (fLeftGrayErrorSum + fRightGrayErrorSum);
  317. }
  318. // ----------------------------------------------------------------------------------------------------
  319. // calculate source pixel averages for each 2x2 quadrant in a 4x4 block
  320. // these are used to determine the averages for each of the 4 different halves (left, right, top, bottom)
  321. // ignore pixels that have alpha == NAN (these are border pixels outside of the source image)
  322. // weight the averages based on a pixel's alpha
  323. //
  324. void Block4x4Encoding_ETC1::CalculateSourceAverages(void)
  325. {
  326. static const bool DEBUG_PRINT = false;
  327. bool boolRGBX = m_pblockParent->GetImageSource()->GetErrorMetric() == ErrorMetric::RGBX;
  328. if (m_pblockParent->GetSourceAlphaMix() == Block4x4::SourceAlphaMix::OPAQUE || boolRGBX)
  329. {
  330. ColorFloatRGBA frgbaSumUL = m_pafrgbaSource[0] + m_pafrgbaSource[1] + m_pafrgbaSource[4] + m_pafrgbaSource[5];
  331. ColorFloatRGBA frgbaSumLL = m_pafrgbaSource[2] + m_pafrgbaSource[3] + m_pafrgbaSource[6] + m_pafrgbaSource[7];
  332. ColorFloatRGBA frgbaSumUR = m_pafrgbaSource[8] + m_pafrgbaSource[9] + m_pafrgbaSource[12] + m_pafrgbaSource[13];
  333. ColorFloatRGBA frgbaSumLR = m_pafrgbaSource[10] + m_pafrgbaSource[11] + m_pafrgbaSource[14] + m_pafrgbaSource[15];
  334. m_frgbaSourceAverageLeft = (frgbaSumUL + frgbaSumLL) * 0.125f;
  335. m_frgbaSourceAverageRight = (frgbaSumUR + frgbaSumLR) * 0.125f;
  336. m_frgbaSourceAverageTop = (frgbaSumUL + frgbaSumUR) * 0.125f;
  337. m_frgbaSourceAverageBottom = (frgbaSumLL + frgbaSumLR) * 0.125f;
  338. }
  339. else
  340. {
  341. float afSourceAlpha[PIXELS];
  342. // treat alpha NAN as 0.0f
  343. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  344. {
  345. afSourceAlpha[uiPixel] = isnan(m_pafrgbaSource[uiPixel].fA) ?
  346. 0.0f :
  347. m_pafrgbaSource[uiPixel].fA;
  348. }
  349. ColorFloatRGBA afrgbaAlphaWeightedSource[PIXELS];
  350. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  351. {
  352. afrgbaAlphaWeightedSource[uiPixel] = m_pafrgbaSource[uiPixel] * afSourceAlpha[uiPixel];
  353. }
  354. ColorFloatRGBA frgbaSumUL = afrgbaAlphaWeightedSource[0] +
  355. afrgbaAlphaWeightedSource[1] +
  356. afrgbaAlphaWeightedSource[4] +
  357. afrgbaAlphaWeightedSource[5];
  358. ColorFloatRGBA frgbaSumLL = afrgbaAlphaWeightedSource[2] +
  359. afrgbaAlphaWeightedSource[3] +
  360. afrgbaAlphaWeightedSource[6] +
  361. afrgbaAlphaWeightedSource[7];
  362. ColorFloatRGBA frgbaSumUR = afrgbaAlphaWeightedSource[8] +
  363. afrgbaAlphaWeightedSource[9] +
  364. afrgbaAlphaWeightedSource[12] +
  365. afrgbaAlphaWeightedSource[13];
  366. ColorFloatRGBA frgbaSumLR = afrgbaAlphaWeightedSource[10] +
  367. afrgbaAlphaWeightedSource[11] +
  368. afrgbaAlphaWeightedSource[14] +
  369. afrgbaAlphaWeightedSource[15];
  370. float fWeightSumUL = afSourceAlpha[0] +
  371. afSourceAlpha[1] +
  372. afSourceAlpha[4] +
  373. afSourceAlpha[5];
  374. float fWeightSumLL = afSourceAlpha[2] +
  375. afSourceAlpha[3] +
  376. afSourceAlpha[6] +
  377. afSourceAlpha[7];
  378. float fWeightSumUR = afSourceAlpha[8] +
  379. afSourceAlpha[9] +
  380. afSourceAlpha[12] +
  381. afSourceAlpha[13];
  382. float fWeightSumLR = afSourceAlpha[10] +
  383. afSourceAlpha[11] +
  384. afSourceAlpha[14] +
  385. afSourceAlpha[15];
  386. ColorFloatRGBA frgbaSumLeft = frgbaSumUL + frgbaSumLL;
  387. ColorFloatRGBA frgbaSumRight = frgbaSumUR + frgbaSumLR;
  388. ColorFloatRGBA frgbaSumTop = frgbaSumUL + frgbaSumUR;
  389. ColorFloatRGBA frgbaSumBottom = frgbaSumLL + frgbaSumLR;
  390. float fWeightSumLeft = fWeightSumUL + fWeightSumLL;
  391. float fWeightSumRight = fWeightSumUR + fWeightSumLR;
  392. float fWeightSumTop = fWeightSumUL + fWeightSumUR;
  393. float fWeightSumBottom = fWeightSumLL + fWeightSumLR;
  394. // check to see if there is at least 1 pixel with non-zero alpha
  395. // completely transparent block should not make it to this code
  396. assert((fWeightSumLeft + fWeightSumRight) > 0.0f);
  397. assert((fWeightSumTop + fWeightSumBottom) > 0.0f);
  398. if (fWeightSumLeft > 0.0f)
  399. {
  400. m_frgbaSourceAverageLeft = frgbaSumLeft * (1.0f/fWeightSumLeft);
  401. }
  402. if (fWeightSumRight > 0.0f)
  403. {
  404. m_frgbaSourceAverageRight = frgbaSumRight * (1.0f/fWeightSumRight);
  405. }
  406. if (fWeightSumTop > 0.0f)
  407. {
  408. m_frgbaSourceAverageTop = frgbaSumTop * (1.0f/fWeightSumTop);
  409. }
  410. if (fWeightSumBottom > 0.0f)
  411. {
  412. m_frgbaSourceAverageBottom = frgbaSumBottom * (1.0f/fWeightSumBottom);
  413. }
  414. if (fWeightSumLeft == 0.0f)
  415. {
  416. assert(fWeightSumRight > 0.0f);
  417. m_frgbaSourceAverageLeft = m_frgbaSourceAverageRight;
  418. }
  419. if (fWeightSumRight == 0.0f)
  420. {
  421. assert(fWeightSumLeft > 0.0f);
  422. m_frgbaSourceAverageRight = m_frgbaSourceAverageLeft;
  423. }
  424. if (fWeightSumTop == 0.0f)
  425. {
  426. assert(fWeightSumBottom > 0.0f);
  427. m_frgbaSourceAverageTop = m_frgbaSourceAverageBottom;
  428. }
  429. if (fWeightSumBottom == 0.0f)
  430. {
  431. assert(fWeightSumTop > 0.0f);
  432. m_frgbaSourceAverageBottom = m_frgbaSourceAverageTop;
  433. }
  434. }
  435. if (DEBUG_PRINT)
  436. {
  437. printf("\ntarget: [%.2f,%.2f,%.2f] [%.2f,%.2f,%.2f] [%.2f,%.2f,%.2f] [%.2f,%.2f,%.2f]\n",
  438. m_frgbaSourceAverageLeft.fR, m_frgbaSourceAverageLeft.fG, m_frgbaSourceAverageLeft.fB,
  439. m_frgbaSourceAverageRight.fR, m_frgbaSourceAverageRight.fG, m_frgbaSourceAverageRight.fB,
  440. m_frgbaSourceAverageTop.fR, m_frgbaSourceAverageTop.fG, m_frgbaSourceAverageTop.fB,
  441. m_frgbaSourceAverageBottom.fR, m_frgbaSourceAverageBottom.fG, m_frgbaSourceAverageBottom.fB);
  442. }
  443. }
  444. // ----------------------------------------------------------------------------------------------------
  445. // try an ETC1 differential mode encoding
  446. // use a_boolFlip to set the encoding F bit
  447. // use a_uiRadius to alter basecolor components in the range[-a_uiRadius:a_uiRadius]
  448. // use a_iGrayOffset1 and a_iGrayOffset2 to offset the basecolor to search for degenerate encodings
  449. // replace the encoding if the encoding error is less than previous encoding
  450. //
  451. void Block4x4Encoding_ETC1::TryDifferential(bool a_boolFlip, unsigned int a_uiRadius,
  452. int a_iGrayOffset1, int a_iGrayOffset2)
  453. {
  454. ColorFloatRGBA frgbaColor1;
  455. ColorFloatRGBA frgbaColor2;
  456. const unsigned int *pauiPixelMapping1;
  457. const unsigned int *pauiPixelMapping2;
  458. if (a_boolFlip)
  459. {
  460. frgbaColor1 = m_frgbaSourceAverageTop;
  461. frgbaColor2 = m_frgbaSourceAverageBottom;
  462. pauiPixelMapping1 = s_auiTopPixelMapping;
  463. pauiPixelMapping2 = s_auiBottomPixelMapping;
  464. }
  465. else
  466. {
  467. frgbaColor1 = m_frgbaSourceAverageLeft;
  468. frgbaColor2 = m_frgbaSourceAverageRight;
  469. pauiPixelMapping1 = s_auiLeftPixelMapping;
  470. pauiPixelMapping2 = s_auiRightPixelMapping;
  471. }
  472. DifferentialTrys trys(frgbaColor1, frgbaColor2, pauiPixelMapping1, pauiPixelMapping2,
  473. a_uiRadius, a_iGrayOffset1, a_iGrayOffset2);
  474. Block4x4Encoding_ETC1 encodingTry = *this;
  475. encodingTry.m_boolFlip = a_boolFlip;
  476. encodingTry.TryDifferentialHalf(&trys.m_half1);
  477. encodingTry.TryDifferentialHalf(&trys.m_half2);
  478. // find best halves that are within differential range
  479. DifferentialTrys::Try *ptryBest1 = nullptr;
  480. DifferentialTrys::Try *ptryBest2 = nullptr;
  481. encodingTry.m_fError = FLT_MAX;
  482. // see if the best of each half are in differential range
  483. int iDRed = trys.m_half2.m_ptryBest->m_iRed - trys.m_half1.m_ptryBest->m_iRed;
  484. int iDGreen = trys.m_half2.m_ptryBest->m_iGreen - trys.m_half1.m_ptryBest->m_iGreen;
  485. int iDBlue = trys.m_half2.m_ptryBest->m_iBlue - trys.m_half1.m_ptryBest->m_iBlue;
  486. if (iDRed >= -4 && iDRed <= 3 && iDGreen >= -4 && iDGreen <= 3 && iDBlue >= -4 && iDBlue <= 3)
  487. {
  488. ptryBest1 = trys.m_half1.m_ptryBest;
  489. ptryBest2 = trys.m_half2.m_ptryBest;
  490. encodingTry.m_fError = trys.m_half1.m_ptryBest->m_fError + trys.m_half2.m_ptryBest->m_fError;
  491. }
  492. else
  493. {
  494. // else, find the next best halves that are in differential range
  495. for (DifferentialTrys::Try *ptry1 = &trys.m_half1.m_atry[0];
  496. ptry1 < &trys.m_half1.m_atry[trys.m_half1.m_uiTrys];
  497. ptry1++)
  498. {
  499. for (DifferentialTrys::Try *ptry2 = &trys.m_half2.m_atry[0];
  500. ptry2 < &trys.m_half2.m_atry[trys.m_half2.m_uiTrys];
  501. ptry2++)
  502. {
  503. iDRed = ptry2->m_iRed - ptry1->m_iRed;
  504. bool boolValidRedDelta = iDRed <= 3 && iDRed >= -4;
  505. iDGreen = ptry2->m_iGreen - ptry1->m_iGreen;
  506. bool boolValidGreenDelta = iDGreen <= 3 && iDGreen >= -4;
  507. iDBlue = ptry2->m_iBlue - ptry1->m_iBlue;
  508. bool boolValidBlueDelta = iDBlue <= 3 && iDBlue >= -4;
  509. if (boolValidRedDelta && boolValidGreenDelta && boolValidBlueDelta)
  510. {
  511. float fError = ptry1->m_fError + ptry2->m_fError;
  512. if (fError < encodingTry.m_fError)
  513. {
  514. encodingTry.m_fError = fError;
  515. ptryBest1 = ptry1;
  516. ptryBest2 = ptry2;
  517. }
  518. }
  519. }
  520. }
  521. assert(encodingTry.m_fError < FLT_MAX);
  522. assert(ptryBest1 != nullptr);
  523. assert(ptryBest2 != nullptr);
  524. }
  525. if (encodingTry.m_fError < m_fError)
  526. {
  527. m_mode = MODE_ETC1;
  528. m_boolDiff = true;
  529. m_boolFlip = encodingTry.m_boolFlip;
  530. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB5((unsigned char)ptryBest1->m_iRed, (unsigned char)ptryBest1->m_iGreen, (unsigned char)ptryBest1->m_iBlue);
  531. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB5((unsigned char)ptryBest2->m_iRed, (unsigned char)ptryBest2->m_iGreen, (unsigned char)ptryBest2->m_iBlue);
  532. m_uiCW1 = ptryBest1->m_uiCW;
  533. m_uiCW2 = ptryBest2->m_uiCW;
  534. for (unsigned int uiPixelOrder = 0; uiPixelOrder < PIXELS / 2; uiPixelOrder++)
  535. {
  536. unsigned int uiPixel1 = pauiPixelMapping1[uiPixelOrder];
  537. unsigned int uiPixel2 = pauiPixelMapping2[uiPixelOrder];
  538. unsigned int uiSelector1 = ptryBest1->m_auiSelectors[uiPixelOrder];
  539. unsigned int uiSelector2 = ptryBest2->m_auiSelectors[uiPixelOrder];
  540. m_auiSelectors[uiPixel1] = uiSelector1;
  541. m_auiSelectors[uiPixel2] = ptryBest2->m_auiSelectors[uiPixelOrder];
  542. float fDeltaRGB1 = s_aafCwTable[m_uiCW1][uiSelector1];
  543. float fDeltaRGB2 = s_aafCwTable[m_uiCW2][uiSelector2];
  544. m_afrgbaDecodedColors[uiPixel1] = (m_frgbaColor1 + fDeltaRGB1).ClampRGB();
  545. m_afrgbaDecodedColors[uiPixel2] = (m_frgbaColor2 + fDeltaRGB2).ClampRGB();
  546. }
  547. m_fError1 = ptryBest1->m_fError;
  548. m_fError2 = ptryBest2->m_fError;
  549. m_boolSeverelyBentDifferentialColors = trys.m_boolSeverelyBentColors;
  550. m_fError = m_fError1 + m_fError2;
  551. // sanity check
  552. {
  553. int iRed1 = m_frgbaColor1.IntRed(31.0f);
  554. int iGreen1 = m_frgbaColor1.IntGreen(31.0f);
  555. int iBlue1 = m_frgbaColor1.IntBlue(31.0f);
  556. int iRed2 = m_frgbaColor2.IntRed(31.0f);
  557. int iGreen2 = m_frgbaColor2.IntGreen(31.0f);
  558. int iBlue2 = m_frgbaColor2.IntBlue(31.0f);
  559. iDRed = iRed2 - iRed1;
  560. iDGreen = iGreen2 - iGreen1;
  561. iDBlue = iBlue2 - iBlue1;
  562. assert(iDRed >= -4 && iDRed < 4);
  563. assert(iDGreen >= -4 && iDGreen < 4);
  564. assert(iDBlue >= -4 && iDBlue < 4);
  565. }
  566. }
  567. }
  568. // ----------------------------------------------------------------------------------------------------
  569. // try an ETC1 differential mode encoding for a half of a 4x4 block
  570. // vary the basecolor components using a radius
  571. //
  572. void Block4x4Encoding_ETC1::TryDifferentialHalf(DifferentialTrys::Half *a_phalf)
  573. {
  574. a_phalf->m_ptryBest = nullptr;
  575. float fBestTryError = FLT_MAX;
  576. a_phalf->m_uiTrys = 0;
  577. for (int iRed = a_phalf->m_iRed - (int)a_phalf->m_uiRadius;
  578. iRed <= a_phalf->m_iRed + (int)a_phalf->m_uiRadius;
  579. iRed++)
  580. {
  581. assert(iRed >= 0 && iRed <= 31);
  582. for (int iGreen = a_phalf->m_iGreen - (int)a_phalf->m_uiRadius;
  583. iGreen <= a_phalf->m_iGreen + (int)a_phalf->m_uiRadius;
  584. iGreen++)
  585. {
  586. assert(iGreen >= 0 && iGreen <= 31);
  587. for (int iBlue = a_phalf->m_iBlue - (int)a_phalf->m_uiRadius;
  588. iBlue <= a_phalf->m_iBlue + (int)a_phalf->m_uiRadius;
  589. iBlue++)
  590. {
  591. assert(iBlue >= 0 && iBlue <= 31);
  592. DifferentialTrys::Try *ptry = &a_phalf->m_atry[a_phalf->m_uiTrys];
  593. assert(ptry < &a_phalf->m_atry[DifferentialTrys::Half::MAX_TRYS]);
  594. ptry->m_iRed = iRed;
  595. ptry->m_iGreen = iGreen;
  596. ptry->m_iBlue = iBlue;
  597. ptry->m_fError = FLT_MAX;
  598. ColorFloatRGBA frgbaColor = ColorFloatRGBA::ConvertFromRGB5((unsigned char)iRed, (unsigned char)iGreen, (unsigned char)iBlue);
  599. // try each CW
  600. for (unsigned int uiCW = 0; uiCW < CW_RANGES; uiCW++)
  601. {
  602. unsigned int auiPixelSelectors[PIXELS / 2];
  603. ColorFloatRGBA afrgbaDecodedPixels[PIXELS / 2];
  604. float afPixelErrors[PIXELS / 2] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX,
  605. FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  606. // pre-compute decoded pixels for each selector
  607. ColorFloatRGBA afrgbaSelectors[SELECTORS];
  608. assert(SELECTORS == 4);
  609. afrgbaSelectors[0] = (frgbaColor + s_aafCwTable[uiCW][0]).ClampRGB();
  610. afrgbaSelectors[1] = (frgbaColor + s_aafCwTable[uiCW][1]).ClampRGB();
  611. afrgbaSelectors[2] = (frgbaColor + s_aafCwTable[uiCW][2]).ClampRGB();
  612. afrgbaSelectors[3] = (frgbaColor + s_aafCwTable[uiCW][3]).ClampRGB();
  613. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  614. {
  615. ColorFloatRGBA *pfrgbaSourcePixel = &m_pafrgbaSource[a_phalf->m_pauiPixelMapping[uiPixel]];
  616. ColorFloatRGBA frgbaDecodedPixel;
  617. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  618. {
  619. frgbaDecodedPixel = afrgbaSelectors[uiSelector];
  620. float fPixelError;
  621. fPixelError = CalcPixelError(frgbaDecodedPixel, m_afDecodedAlphas[a_phalf->m_pauiPixelMapping[uiPixel]],
  622. *pfrgbaSourcePixel);
  623. if (fPixelError < afPixelErrors[uiPixel])
  624. {
  625. auiPixelSelectors[uiPixel] = uiSelector;
  626. afrgbaDecodedPixels[uiPixel] = frgbaDecodedPixel;
  627. afPixelErrors[uiPixel] = fPixelError;
  628. }
  629. }
  630. }
  631. // add up all pixel errors
  632. float fCWError = 0.0f;
  633. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  634. {
  635. fCWError += afPixelErrors[uiPixel];
  636. }
  637. // if best CW so far
  638. if (fCWError < ptry->m_fError)
  639. {
  640. ptry->m_uiCW = uiCW;
  641. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  642. {
  643. ptry->m_auiSelectors[uiPixel] = auiPixelSelectors[uiPixel];
  644. }
  645. ptry->m_fError = fCWError;
  646. }
  647. }
  648. if (ptry->m_fError < fBestTryError)
  649. {
  650. a_phalf->m_ptryBest = ptry;
  651. fBestTryError = ptry->m_fError;
  652. }
  653. assert(ptry->m_fError < FLT_MAX);
  654. a_phalf->m_uiTrys++;
  655. }
  656. }
  657. }
  658. }
  659. // ----------------------------------------------------------------------------------------------------
  660. // try an ETC1 individual mode encoding
  661. // use a_boolFlip to set the encoding F bit
  662. // use a_uiRadius to alter basecolor components in the range[-a_uiRadius:a_uiRadius]
  663. // replace the encoding if the encoding error is less than previous encoding
  664. //
  665. void Block4x4Encoding_ETC1::TryIndividual(bool a_boolFlip, unsigned int a_uiRadius)
  666. {
  667. ColorFloatRGBA frgbaColor1;
  668. ColorFloatRGBA frgbaColor2;
  669. const unsigned int *pauiPixelMapping1;
  670. const unsigned int *pauiPixelMapping2;
  671. if (a_boolFlip)
  672. {
  673. frgbaColor1 = m_frgbaSourceAverageTop;
  674. frgbaColor2 = m_frgbaSourceAverageBottom;
  675. pauiPixelMapping1 = s_auiTopPixelMapping;
  676. pauiPixelMapping2 = s_auiBottomPixelMapping;
  677. }
  678. else
  679. {
  680. frgbaColor1 = m_frgbaSourceAverageLeft;
  681. frgbaColor2 = m_frgbaSourceAverageRight;
  682. pauiPixelMapping1 = s_auiLeftPixelMapping;
  683. pauiPixelMapping2 = s_auiRightPixelMapping;
  684. }
  685. IndividualTrys trys(frgbaColor1, frgbaColor2, pauiPixelMapping1, pauiPixelMapping2, a_uiRadius);
  686. Block4x4Encoding_ETC1 encodingTry = *this;
  687. encodingTry.m_boolFlip = a_boolFlip;
  688. encodingTry.TryIndividualHalf(&trys.m_half1);
  689. encodingTry.TryIndividualHalf(&trys.m_half2);
  690. // use the best of each half
  691. IndividualTrys::Try *ptryBest1 = trys.m_half1.m_ptryBest;
  692. IndividualTrys::Try *ptryBest2 = trys.m_half2.m_ptryBest;
  693. encodingTry.m_fError = trys.m_half1.m_ptryBest->m_fError + trys.m_half2.m_ptryBest->m_fError;
  694. if (encodingTry.m_fError < m_fError)
  695. {
  696. m_mode = MODE_ETC1;
  697. m_boolDiff = false;
  698. m_boolFlip = encodingTry.m_boolFlip;
  699. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)ptryBest1->m_iRed, (unsigned char)ptryBest1->m_iGreen, (unsigned char)ptryBest1->m_iBlue);
  700. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)ptryBest2->m_iRed, (unsigned char)ptryBest2->m_iGreen, (unsigned char)ptryBest2->m_iBlue);
  701. m_uiCW1 = ptryBest1->m_uiCW;
  702. m_uiCW2 = ptryBest2->m_uiCW;
  703. for (unsigned int uiPixelOrder = 0; uiPixelOrder < PIXELS / 2; uiPixelOrder++)
  704. {
  705. unsigned int uiPixel1 = pauiPixelMapping1[uiPixelOrder];
  706. unsigned int uiPixel2 = pauiPixelMapping2[uiPixelOrder];
  707. unsigned int uiSelector1 = ptryBest1->m_auiSelectors[uiPixelOrder];
  708. unsigned int uiSelector2 = ptryBest2->m_auiSelectors[uiPixelOrder];
  709. m_auiSelectors[uiPixel1] = uiSelector1;
  710. m_auiSelectors[uiPixel2] = ptryBest2->m_auiSelectors[uiPixelOrder];
  711. float fDeltaRGB1 = s_aafCwTable[m_uiCW1][uiSelector1];
  712. float fDeltaRGB2 = s_aafCwTable[m_uiCW2][uiSelector2];
  713. m_afrgbaDecodedColors[uiPixel1] = (m_frgbaColor1 + fDeltaRGB1).ClampRGB();
  714. m_afrgbaDecodedColors[uiPixel2] = (m_frgbaColor2 + fDeltaRGB2).ClampRGB();
  715. }
  716. m_fError1 = ptryBest1->m_fError;
  717. m_fError2 = ptryBest2->m_fError;
  718. m_fError = m_fError1 + m_fError2;
  719. }
  720. }
  721. // ----------------------------------------------------------------------------------------------------
  722. // try an ETC1 differential mode encoding for a half of a 4x4 block
  723. // vary the basecolor components using a radius
  724. //
  725. void Block4x4Encoding_ETC1::TryIndividualHalf(IndividualTrys::Half *a_phalf)
  726. {
  727. a_phalf->m_ptryBest = nullptr;
  728. float fBestTryError = FLT_MAX;
  729. a_phalf->m_uiTrys = 0;
  730. for (int iRed = a_phalf->m_iRed - (int)a_phalf->m_uiRadius;
  731. iRed <= a_phalf->m_iRed + (int)a_phalf->m_uiRadius;
  732. iRed++)
  733. {
  734. assert(iRed >= 0 && iRed <= 15);
  735. for (int iGreen = a_phalf->m_iGreen - (int)a_phalf->m_uiRadius;
  736. iGreen <= a_phalf->m_iGreen + (int)a_phalf->m_uiRadius;
  737. iGreen++)
  738. {
  739. assert(iGreen >= 0 && iGreen <= 15);
  740. for (int iBlue = a_phalf->m_iBlue - (int)a_phalf->m_uiRadius;
  741. iBlue <= a_phalf->m_iBlue + (int)a_phalf->m_uiRadius;
  742. iBlue++)
  743. {
  744. assert(iBlue >= 0 && iBlue <= 15);
  745. IndividualTrys::Try *ptry = &a_phalf->m_atry[a_phalf->m_uiTrys];
  746. assert(ptry < &a_phalf->m_atry[IndividualTrys::Half::MAX_TRYS]);
  747. ptry->m_iRed = iRed;
  748. ptry->m_iGreen = iGreen;
  749. ptry->m_iBlue = iBlue;
  750. ptry->m_fError = FLT_MAX;
  751. ColorFloatRGBA frgbaColor = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed, (unsigned char)iGreen, (unsigned char)iBlue);
  752. // try each CW
  753. for (unsigned int uiCW = 0; uiCW < CW_RANGES; uiCW++)
  754. {
  755. unsigned int auiPixelSelectors[PIXELS / 2];
  756. ColorFloatRGBA afrgbaDecodedPixels[PIXELS / 2];
  757. float afPixelErrors[PIXELS / 2] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX,
  758. FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  759. // pre-compute decoded pixels for each selector
  760. ColorFloatRGBA afrgbaSelectors[SELECTORS];
  761. assert(SELECTORS == 4);
  762. afrgbaSelectors[0] = (frgbaColor + s_aafCwTable[uiCW][0]).ClampRGB();
  763. afrgbaSelectors[1] = (frgbaColor + s_aafCwTable[uiCW][1]).ClampRGB();
  764. afrgbaSelectors[2] = (frgbaColor + s_aafCwTable[uiCW][2]).ClampRGB();
  765. afrgbaSelectors[3] = (frgbaColor + s_aafCwTable[uiCW][3]).ClampRGB();
  766. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  767. {
  768. ColorFloatRGBA *pfrgbaSourcePixel = &m_pafrgbaSource[a_phalf->m_pauiPixelMapping[uiPixel]];
  769. ColorFloatRGBA frgbaDecodedPixel;
  770. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  771. {
  772. frgbaDecodedPixel = afrgbaSelectors[uiSelector];
  773. float fPixelError;
  774. fPixelError = CalcPixelError(frgbaDecodedPixel, m_afDecodedAlphas[a_phalf->m_pauiPixelMapping[uiPixel]],
  775. *pfrgbaSourcePixel);
  776. if (fPixelError < afPixelErrors[uiPixel])
  777. {
  778. auiPixelSelectors[uiPixel] = uiSelector;
  779. afrgbaDecodedPixels[uiPixel] = frgbaDecodedPixel;
  780. afPixelErrors[uiPixel] = fPixelError;
  781. }
  782. }
  783. }
  784. // add up all pixel errors
  785. float fCWError = 0.0f;
  786. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  787. {
  788. fCWError += afPixelErrors[uiPixel];
  789. }
  790. // if best CW so far
  791. if (fCWError < ptry->m_fError)
  792. {
  793. ptry->m_uiCW = uiCW;
  794. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  795. {
  796. ptry->m_auiSelectors[uiPixel] = auiPixelSelectors[uiPixel];
  797. }
  798. ptry->m_fError = fCWError;
  799. }
  800. }
  801. if (ptry->m_fError < fBestTryError)
  802. {
  803. a_phalf->m_ptryBest = ptry;
  804. fBestTryError = ptry->m_fError;
  805. }
  806. assert(ptry->m_fError < FLT_MAX);
  807. a_phalf->m_uiTrys++;
  808. }
  809. }
  810. }
  811. }
  812. // ----------------------------------------------------------------------------------------------------
  813. // try version 1 of the degenerate search
  814. // degenerate encodings use basecolor movement and a subset of the selectors to find useful encodings
  815. // each subsequent version of the degenerate search uses more basecolor movement and is less likely to
  816. // be successfull
  817. //
  818. void Block4x4Encoding_ETC1::TryDegenerates1(void)
  819. {
  820. TryDifferential(m_boolMostLikelyFlip, 1, -2, 0);
  821. TryDifferential(m_boolMostLikelyFlip, 1, 2, 0);
  822. TryDifferential(m_boolMostLikelyFlip, 1, 0, 2);
  823. TryDifferential(m_boolMostLikelyFlip, 1, 0, -2);
  824. }
  825. // ----------------------------------------------------------------------------------------------------
  826. // try version 2 of the degenerate search
  827. // degenerate encodings use basecolor movement and a subset of the selectors to find useful encodings
  828. // each subsequent version of the degenerate search uses more basecolor movement and is less likely to
  829. // be successfull
  830. //
  831. void Block4x4Encoding_ETC1::TryDegenerates2(void)
  832. {
  833. TryDifferential(!m_boolMostLikelyFlip, 1, -2, 0);
  834. TryDifferential(!m_boolMostLikelyFlip, 1, 2, 0);
  835. TryDifferential(!m_boolMostLikelyFlip, 1, 0, 2);
  836. TryDifferential(!m_boolMostLikelyFlip, 1, 0, -2);
  837. }
  838. // ----------------------------------------------------------------------------------------------------
  839. // try version 3 of the degenerate search
  840. // degenerate encodings use basecolor movement and a subset of the selectors to find useful encodings
  841. // each subsequent version of the degenerate search uses more basecolor movement and is less likely to
  842. // be successfull
  843. //
  844. void Block4x4Encoding_ETC1::TryDegenerates3(void)
  845. {
  846. TryDifferential(m_boolMostLikelyFlip, 1, -2, -2);
  847. TryDifferential(m_boolMostLikelyFlip, 1, -2, 2);
  848. TryDifferential(m_boolMostLikelyFlip, 1, 2, -2);
  849. TryDifferential(m_boolMostLikelyFlip, 1, 2, 2);
  850. }
  851. // ----------------------------------------------------------------------------------------------------
  852. // try version 4 of the degenerate search
  853. // degenerate encodings use basecolor movement and a subset of the selectors to find useful encodings
  854. // each subsequent version of the degenerate search uses more basecolor movement and is less likely to
  855. // be successfull
  856. //
  857. void Block4x4Encoding_ETC1::TryDegenerates4(void)
  858. {
  859. TryDifferential(m_boolMostLikelyFlip, 1, -4, 0);
  860. TryDifferential(m_boolMostLikelyFlip, 1, 4, 0);
  861. TryDifferential(m_boolMostLikelyFlip, 1, 0, 4);
  862. TryDifferential(m_boolMostLikelyFlip, 1, 0, -4);
  863. }
  864. // ----------------------------------------------------------------------------------------------------
  865. // find the best selector for each pixel based on a particular basecolor and CW that have been previously set
  866. // calculate the selectors for each half of the block separately
  867. // set the block error as the sum of each half's error
  868. //
  869. void Block4x4Encoding_ETC1::CalculateSelectors()
  870. {
  871. if (m_boolFlip)
  872. {
  873. CalculateHalfOfTheSelectors(0, s_auiTopPixelMapping);
  874. CalculateHalfOfTheSelectors(1, s_auiBottomPixelMapping);
  875. }
  876. else
  877. {
  878. CalculateHalfOfTheSelectors(0, s_auiLeftPixelMapping);
  879. CalculateHalfOfTheSelectors(1, s_auiRightPixelMapping);
  880. }
  881. m_fError = m_fError1 + m_fError2;
  882. }
  883. // ----------------------------------------------------------------------------------------------------
  884. // choose best selectors for half of the block
  885. // calculate the error for half of the block
  886. //
  887. void Block4x4Encoding_ETC1::CalculateHalfOfTheSelectors(unsigned int a_uiHalf,
  888. const unsigned int *pauiPixelMapping)
  889. {
  890. static const bool DEBUG_PRINT = false;
  891. ColorFloatRGBA *pfrgbaColor = a_uiHalf ? &m_frgbaColor2 : &m_frgbaColor1;
  892. unsigned int *puiCW = a_uiHalf ? &m_uiCW2 : &m_uiCW1;
  893. float *pfHalfError = a_uiHalf ? &m_fError2 : &m_fError1;
  894. *pfHalfError = FLT_MAX;
  895. // try each CW
  896. for (unsigned int uiCW = 0; uiCW < CW_RANGES; uiCW++)
  897. {
  898. if (DEBUG_PRINT)
  899. {
  900. printf("\ncw=%u\n", uiCW);
  901. }
  902. unsigned int auiPixelSelectors[PIXELS / 2];
  903. ColorFloatRGBA afrgbaDecodedPixels[PIXELS / 2];
  904. float afPixelErrors[PIXELS / 2] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  905. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  906. {
  907. if (DEBUG_PRINT)
  908. {
  909. printf("\tsource [%.2f,%.2f,%.2f]\n", m_pafrgbaSource[pauiPixelMapping[uiPixel]].fR,
  910. m_pafrgbaSource[pauiPixelMapping[uiPixel]].fG, m_pafrgbaSource[pauiPixelMapping[uiPixel]].fB);
  911. }
  912. ColorFloatRGBA *pfrgbaSourcePixel = &m_pafrgbaSource[pauiPixelMapping[uiPixel]];
  913. ColorFloatRGBA frgbaDecodedPixel;
  914. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  915. {
  916. float fDeltaRGB = s_aafCwTable[uiCW][uiSelector];
  917. frgbaDecodedPixel = (*pfrgbaColor + fDeltaRGB).ClampRGB();
  918. float fPixelError;
  919. fPixelError = CalcPixelError(frgbaDecodedPixel, m_afDecodedAlphas[pauiPixelMapping[uiPixel]],
  920. *pfrgbaSourcePixel);
  921. if (DEBUG_PRINT)
  922. {
  923. printf("\tpixel %u, index %u [%.2f,%.2f,%.2f], error %.2f", uiPixel, uiSelector,
  924. frgbaDecodedPixel.fR,
  925. frgbaDecodedPixel.fG,
  926. frgbaDecodedPixel.fB,
  927. fPixelError);
  928. }
  929. if (fPixelError < afPixelErrors[uiPixel])
  930. {
  931. if (DEBUG_PRINT)
  932. {
  933. printf(" *");
  934. }
  935. auiPixelSelectors[uiPixel] = uiSelector;
  936. afrgbaDecodedPixels[uiPixel] = frgbaDecodedPixel;
  937. afPixelErrors[uiPixel] = fPixelError;
  938. }
  939. if (DEBUG_PRINT)
  940. {
  941. printf("\n");
  942. }
  943. }
  944. }
  945. // add up all pixel errors
  946. float fCWError = 0.0f;
  947. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  948. {
  949. fCWError += afPixelErrors[uiPixel];
  950. }
  951. if (DEBUG_PRINT)
  952. {
  953. printf("\terror %.2f\n", fCWError);
  954. }
  955. // if best CW so far
  956. if (fCWError < *pfHalfError)
  957. {
  958. *pfHalfError = fCWError;
  959. *puiCW = uiCW;
  960. for (unsigned int uiPixel = 0; uiPixel < 8; uiPixel++)
  961. {
  962. m_auiSelectors[pauiPixelMapping[uiPixel]] = auiPixelSelectors[uiPixel];
  963. m_afrgbaDecodedColors[pauiPixelMapping[uiPixel]] = afrgbaDecodedPixels[uiPixel];
  964. }
  965. }
  966. }
  967. }
  968. // ----------------------------------------------------------------------------------------------------
  969. // set the encoding bits based on encoding state
  970. //
  971. void Block4x4Encoding_ETC1::SetEncodingBits(void)
  972. {
  973. assert(m_mode == MODE_ETC1);
  974. if (m_boolDiff)
  975. {
  976. int iRed1 = m_frgbaColor1.IntRed(31.0f);
  977. int iGreen1 = m_frgbaColor1.IntGreen(31.0f);
  978. int iBlue1 = m_frgbaColor1.IntBlue(31.0f);
  979. int iRed2 = m_frgbaColor2.IntRed(31.0f);
  980. int iGreen2 = m_frgbaColor2.IntGreen(31.0f);
  981. int iBlue2 = m_frgbaColor2.IntBlue(31.0f);
  982. int iDRed2 = iRed2 - iRed1;
  983. int iDGreen2 = iGreen2 - iGreen1;
  984. int iDBlue2 = iBlue2 - iBlue1;
  985. assert(iDRed2 >= -4 && iDRed2 < 4);
  986. assert(iDGreen2 >= -4 && iDGreen2 < 4);
  987. assert(iDBlue2 >= -4 && iDBlue2 < 4);
  988. m_pencodingbitsRGB8->differential.red1 = (unsigned int)iRed1;
  989. m_pencodingbitsRGB8->differential.green1 = (unsigned int)iGreen1;
  990. m_pencodingbitsRGB8->differential.blue1 = (unsigned int)iBlue1;
  991. m_pencodingbitsRGB8->differential.dred2 = iDRed2;
  992. m_pencodingbitsRGB8->differential.dgreen2 = iDGreen2;
  993. m_pencodingbitsRGB8->differential.dblue2 = iDBlue2;
  994. }
  995. else
  996. {
  997. m_pencodingbitsRGB8->individual.red1 = (unsigned int)m_frgbaColor1.IntRed(15.0f);
  998. m_pencodingbitsRGB8->individual.green1 = (unsigned int)m_frgbaColor1.IntGreen(15.0f);
  999. m_pencodingbitsRGB8->individual.blue1 = (unsigned int)m_frgbaColor1.IntBlue(15.0f);
  1000. m_pencodingbitsRGB8->individual.red2 = (unsigned int)m_frgbaColor2.IntRed(15.0f);
  1001. m_pencodingbitsRGB8->individual.green2 = (unsigned int)m_frgbaColor2.IntGreen(15.0f);
  1002. m_pencodingbitsRGB8->individual.blue2 = (unsigned int)m_frgbaColor2.IntBlue(15.0f);
  1003. }
  1004. m_pencodingbitsRGB8->individual.cw1 = m_uiCW1;
  1005. m_pencodingbitsRGB8->individual.cw2 = m_uiCW2;
  1006. SetEncodingBits_Selectors();
  1007. m_pencodingbitsRGB8->individual.diff = (unsigned int)m_boolDiff;
  1008. m_pencodingbitsRGB8->individual.flip = (unsigned int)m_boolFlip;
  1009. }
  1010. // ----------------------------------------------------------------------------------------------------
  1011. // set the selectors in the encoding bits
  1012. //
  1013. void Block4x4Encoding_ETC1::SetEncodingBits_Selectors(void)
  1014. {
  1015. m_pencodingbitsRGB8->individual.selectors = 0;
  1016. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  1017. {
  1018. unsigned int uiSelector = m_auiSelectors[uiPixel];
  1019. // set index msb
  1020. m_pencodingbitsRGB8->individual.selectors |= (uiSelector >> 1) << (uiPixel ^ 8);
  1021. // set index lsb
  1022. m_pencodingbitsRGB8->individual.selectors |= (uiSelector & 1) << ((16 + uiPixel) ^ 8);
  1023. }
  1024. }
  1025. // ----------------------------------------------------------------------------------------------------
  1026. // set the decoded colors and decoded alpha based on the encoding state
  1027. //
  1028. void Block4x4Encoding_ETC1::Decode(void)
  1029. {
  1030. const unsigned int *pauiPixelOrder = m_boolFlip ? s_auiPixelOrderFlip1 : s_auiPixelOrderFlip0;
  1031. for (unsigned int uiPixelOrder = 0; uiPixelOrder < PIXELS; uiPixelOrder++)
  1032. {
  1033. ColorFloatRGBA *pfrgbaCenter = uiPixelOrder < 8 ? &m_frgbaColor1 : &m_frgbaColor2;
  1034. unsigned int uiCW = uiPixelOrder < 8 ? m_uiCW1 : m_uiCW2;
  1035. unsigned int uiPixel = pauiPixelOrder[uiPixelOrder];
  1036. float fDelta = s_aafCwTable[uiCW][m_auiSelectors[uiPixel]];
  1037. m_afrgbaDecodedColors[uiPixel] = (*pfrgbaCenter + fDelta).ClampRGB();
  1038. m_afDecodedAlphas[uiPixel] = 1.0f;
  1039. }
  1040. }
  1041. // ----------------------------------------------------------------------------------------------------
  1042. //
  1043. } // namespace Etc