Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

624 lines
18 KiB

  1. // stb_dxt.h - v1.04 - DXT1/DXT5 compressor - public domain
  2. // original by fabian "ryg" giesen - ported to C by stb
  3. // use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation
  4. //
  5. // USAGE:
  6. // call stb_compress_dxt_block() for every block (you must pad)
  7. // source should be a 4x4 block of RGBA data in row-major order;
  8. // A is ignored if you specify alpha=0; you can turn on dithering
  9. // and "high quality" using mode.
  10. //
  11. // version history:
  12. // v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec);
  13. // single color match fix (allow for inexact color interpolation);
  14. // optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps.
  15. // v1.03 - (stb) endianness support
  16. // v1.02 - (stb) fix alpha encoding bug
  17. // v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom
  18. // v1.00 - (stb) first release
  19. #ifndef STB_INCLUDE_STB_DXT_H
  20. #define STB_INCLUDE_STB_DXT_H
  21. // compression mode (bitflags)
  22. #define STB_DXT_NORMAL 0
  23. #define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like!
  24. #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower.
  25. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode);
  26. #define STB_COMPRESS_DXT_BLOCK
  27. #ifdef STB_DXT_IMPLEMENTATION
  28. // configuration options for DXT encoder. set them in the project/makefile or just define
  29. // them at the top.
  30. // STB_DXT_USE_ROUNDING_BIAS
  31. // use a rounding bias during color interpolation. this is closer to what "ideal"
  32. // interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03)
  33. // implicitly had this turned on.
  34. //
  35. // in case you're targeting a specific type of hardware (e.g. console programmers):
  36. // NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer
  37. // to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias.
  38. // you also see "(a*5 + b*3) / 8" on some old GPU designs.
  39. // #define STB_DXT_USE_ROUNDING_BIAS
  40. #include <stdlib.h>
  41. #include <math.h>
  42. #include <string.h> // memset
  43. static unsigned char stb__Expand5[32];
  44. static unsigned char stb__Expand6[64];
  45. static unsigned char stb__OMatch5[256][2];
  46. static unsigned char stb__OMatch6[256][2];
  47. static unsigned char stb__QuantRBTab[256+16];
  48. static unsigned char stb__QuantGTab[256+16];
  49. static int stb__Mul8Bit(int a, int b)
  50. {
  51. int t = a*b + 128;
  52. return (t + (t >> 8)) >> 8;
  53. }
  54. static void stb__From16Bit(unsigned char *out, unsigned short v)
  55. {
  56. int rv = (v & 0xf800) >> 11;
  57. int gv = (v & 0x07e0) >> 5;
  58. int bv = (v & 0x001f) >> 0;
  59. out[0] = stb__Expand5[rv];
  60. out[1] = stb__Expand6[gv];
  61. out[2] = stb__Expand5[bv];
  62. out[3] = 0;
  63. }
  64. static unsigned short stb__As16Bit(int r, int g, int b)
  65. {
  66. return (stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31);
  67. }
  68. // linear interpolation at 1/3 point between a and b, using desired rounding type
  69. static int stb__Lerp13(int a, int b)
  70. {
  71. #ifdef STB_DXT_USE_ROUNDING_BIAS
  72. // with rounding bias
  73. return a + stb__Mul8Bit(b-a, 0x55);
  74. #else
  75. // without rounding bias
  76. // replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed.
  77. return (2*a + b) / 3;
  78. #endif
  79. }
  80. // lerp RGB color
  81. static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2)
  82. {
  83. out[0] = stb__Lerp13(p1[0], p2[0]);
  84. out[1] = stb__Lerp13(p1[1], p2[1]);
  85. out[2] = stb__Lerp13(p1[2], p2[2]);
  86. }
  87. /****************************************************************************/
  88. // compute table to reproduce constant colors as accurately as possible
  89. static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size)
  90. {
  91. int i,mn,mx;
  92. for (i=0;i<256;i++) {
  93. int bestErr = 256;
  94. for (mn=0;mn<size;mn++) {
  95. for (mx=0;mx<size;mx++) {
  96. int mine = expand[mn];
  97. int maxe = expand[mx];
  98. int err = abs(stb__Lerp13(maxe, mine) - i);
  99. // DX10 spec says that interpolation must be within 3% of "correct" result,
  100. // add this as error term. (normally we'd expect a random distribution of
  101. // +-1.5% error, but nowhere in the spec does it say that the error has to be
  102. // unbiased - better safe than sorry).
  103. err += abs(maxe - mine) * 3 / 100;
  104. if(err < bestErr)
  105. {
  106. Table[i*2+0] = mx;
  107. Table[i*2+1] = mn;
  108. bestErr = err;
  109. }
  110. }
  111. }
  112. }
  113. }
  114. static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
  115. {
  116. stb__From16Bit(color+ 0, c0);
  117. stb__From16Bit(color+ 4, c1);
  118. stb__Lerp13RGB(color+ 8, color+0, color+4);
  119. stb__Lerp13RGB(color+12, color+4, color+0);
  120. }
  121. // Block dithering function. Simply dithers a block to 565 RGB.
  122. // (Floyd-Steinberg)
  123. static void stb__DitherBlock(unsigned char *dest, unsigned char *block)
  124. {
  125. int err[8],*ep1 = err,*ep2 = err+4, *et;
  126. int ch,y;
  127. // process channels seperately
  128. for (ch=0; ch<3; ++ch) {
  129. unsigned char *bp = block+ch, *dp = dest+ch;
  130. unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
  131. memset(err, 0, sizeof(err));
  132. for(y=0; y<4; ++y) {
  133. dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
  134. ep1[0] = bp[ 0] - dp[ 0];
  135. dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)];
  136. ep1[1] = bp[ 4] - dp[ 4];
  137. dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)];
  138. ep1[2] = bp[ 8] - dp[ 8];
  139. dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)];
  140. ep1[3] = bp[12] - dp[12];
  141. bp += 16;
  142. dp += 16;
  143. et = ep1, ep1 = ep2, ep2 = et; // swap
  144. }
  145. }
  146. }
  147. // The color matching function
  148. static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither)
  149. {
  150. unsigned int mask = 0;
  151. int dirr = color[0*4+0] - color[1*4+0];
  152. int dirg = color[0*4+1] - color[1*4+1];
  153. int dirb = color[0*4+2] - color[1*4+2];
  154. int dots[16];
  155. int stops[4];
  156. int i;
  157. int c0Point, halfPoint, c3Point;
  158. for(i=0;i<16;i++)
  159. dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb;
  160. for(i=0;i<4;i++)
  161. stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb;
  162. // think of the colors as arranged on a line; project point onto that line, then choose
  163. // next color out of available ones. we compute the crossover points for "best color in top
  164. // half"/"best in bottom half" and then the same inside that subinterval.
  165. //
  166. // relying on this 1d approximation isn't always optimal in terms of euclidean distance,
  167. // but it's very close and a lot faster.
  168. // http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html
  169. c0Point = (stops[1] + stops[3]) >> 1;
  170. halfPoint = (stops[3] + stops[2]) >> 1;
  171. c3Point = (stops[2] + stops[0]) >> 1;
  172. if(!dither) {
  173. // the version without dithering is straightforward
  174. for (i=15;i>=0;i--) {
  175. int dot = dots[i];
  176. mask <<= 2;
  177. if(dot < halfPoint)
  178. mask |= (dot < c0Point) ? 1 : 3;
  179. else
  180. mask |= (dot < c3Point) ? 2 : 0;
  181. }
  182. } else {
  183. // with floyd-steinberg dithering
  184. int err[8],*ep1 = err,*ep2 = err+4;
  185. int *dp = dots, y;
  186. c0Point <<= 4;
  187. halfPoint <<= 4;
  188. c3Point <<= 4;
  189. for(i=0;i<8;i++)
  190. err[i] = 0;
  191. for(y=0;y<4;y++)
  192. {
  193. int dot,lmask,step;
  194. dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]);
  195. if(dot < halfPoint)
  196. step = (dot < c0Point) ? 1 : 3;
  197. else
  198. step = (dot < c3Point) ? 2 : 0;
  199. ep1[0] = dp[0] - stops[step];
  200. lmask = step;
  201. dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]);
  202. if(dot < halfPoint)
  203. step = (dot < c0Point) ? 1 : 3;
  204. else
  205. step = (dot < c3Point) ? 2 : 0;
  206. ep1[1] = dp[1] - stops[step];
  207. lmask |= step<<2;
  208. dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]);
  209. if(dot < halfPoint)
  210. step = (dot < c0Point) ? 1 : 3;
  211. else
  212. step = (dot < c3Point) ? 2 : 0;
  213. ep1[2] = dp[2] - stops[step];
  214. lmask |= step<<4;
  215. dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]);
  216. if(dot < halfPoint)
  217. step = (dot < c0Point) ? 1 : 3;
  218. else
  219. step = (dot < c3Point) ? 2 : 0;
  220. ep1[3] = dp[3] - stops[step];
  221. lmask |= step<<6;
  222. dp += 4;
  223. mask |= lmask << (y*8);
  224. { int *et = ep1; ep1 = ep2; ep2 = et; } // swap
  225. }
  226. }
  227. return mask;
  228. }
  229. // The color optimization function. (Clever code, part 1)
  230. static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
  231. {
  232. int mind = 0x7fffffff,maxd = -0x7fffffff;
  233. unsigned char *minp, *maxp;
  234. double magn;
  235. int v_r,v_g,v_b;
  236. static const int nIterPower = 4;
  237. float covf[6],vfr,vfg,vfb;
  238. // determine color distribution
  239. int cov[6];
  240. int mu[3],min[3],max[3];
  241. int ch,i,iter;
  242. for(ch=0;ch<3;ch++)
  243. {
  244. const unsigned char *bp = ((const unsigned char *) block) + ch;
  245. int muv,minv,maxv;
  246. muv = minv = maxv = bp[0];
  247. for(i=4;i<64;i+=4)
  248. {
  249. muv += bp[i];
  250. if (bp[i] < minv) minv = bp[i];
  251. else if (bp[i] > maxv) maxv = bp[i];
  252. }
  253. mu[ch] = (muv + 8) >> 4;
  254. min[ch] = minv;
  255. max[ch] = maxv;
  256. }
  257. // determine covariance matrix
  258. for (i=0;i<6;i++)
  259. cov[i] = 0;
  260. for (i=0;i<16;i++)
  261. {
  262. int r = block[i*4+0] - mu[0];
  263. int g = block[i*4+1] - mu[1];
  264. int b = block[i*4+2] - mu[2];
  265. cov[0] += r*r;
  266. cov[1] += r*g;
  267. cov[2] += r*b;
  268. cov[3] += g*g;
  269. cov[4] += g*b;
  270. cov[5] += b*b;
  271. }
  272. // convert covariance matrix to float, find principal axis via power iter
  273. for(i=0;i<6;i++)
  274. covf[i] = cov[i] / 255.0f;
  275. vfr = (float) (max[0] - min[0]);
  276. vfg = (float) (max[1] - min[1]);
  277. vfb = (float) (max[2] - min[2]);
  278. for(iter=0;iter<nIterPower;iter++)
  279. {
  280. float r = vfr*covf[0] + vfg*covf[1] + vfb*covf[2];
  281. float g = vfr*covf[1] + vfg*covf[3] + vfb*covf[4];
  282. float b = vfr*covf[2] + vfg*covf[4] + vfb*covf[5];
  283. vfr = r;
  284. vfg = g;
  285. vfb = b;
  286. }
  287. magn = fabs(vfr);
  288. if (fabs(vfg) > magn) magn = fabs(vfg);
  289. if (fabs(vfb) > magn) magn = fabs(vfb);
  290. if(magn < 4.0f) { // too small, default to luminance
  291. v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000.
  292. v_g = 587;
  293. v_b = 114;
  294. } else {
  295. magn = 512.0 / magn;
  296. v_r = (int) (vfr * magn);
  297. v_g = (int) (vfg * magn);
  298. v_b = (int) (vfb * magn);
  299. }
  300. // Pick colors at extreme points
  301. for(i=0;i<16;i++)
  302. {
  303. int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
  304. if (dot < mind) {
  305. mind = dot;
  306. minp = block+i*4;
  307. }
  308. if (dot > maxd) {
  309. maxd = dot;
  310. maxp = block+i*4;
  311. }
  312. }
  313. *pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]);
  314. *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
  315. }
  316. static int stb__sclamp(float y, int p0, int p1)
  317. {
  318. int x = (int) y;
  319. if (x < p0) return p0;
  320. if (x > p1) return p1;
  321. return x;
  322. }
  323. // The refinement function. (Clever code, part 2)
  324. // Tries to optimize colors to suit block contents better.
  325. // (By solving a least squares system via normal equations+Cramer's rule)
  326. static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask)
  327. {
  328. static const int w1Tab[4] = { 3,0,2,1 };
  329. static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 };
  330. // ^some magic to save a lot of multiplies in the accumulating loop...
  331. // (precomputed products of weights for least squares system, accumulated inside one 32-bit register)
  332. float frb,fg;
  333. unsigned short oldMin, oldMax, min16, max16;
  334. int i, akku = 0, xx,xy,yy;
  335. int At1_r,At1_g,At1_b;
  336. int At2_r,At2_g,At2_b;
  337. unsigned int cm = mask;
  338. oldMin = *pmin16;
  339. oldMax = *pmax16;
  340. if((mask ^ (mask<<2)) < 4) // all pixels have the same index?
  341. {
  342. // yes, linear system would be singular; solve using optimal
  343. // single-color match on average color
  344. int r = 8, g = 8, b = 8;
  345. for (i=0;i<16;++i) {
  346. r += block[i*4+0];
  347. g += block[i*4+1];
  348. b += block[i*4+2];
  349. }
  350. r >>= 4; g >>= 4; b >>= 4;
  351. max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
  352. min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
  353. } else {
  354. At1_r = At1_g = At1_b = 0;
  355. At2_r = At2_g = At2_b = 0;
  356. for (i=0;i<16;++i,cm>>=2) {
  357. int step = cm&3;
  358. int w1 = w1Tab[step];
  359. int r = block[i*4+0];
  360. int g = block[i*4+1];
  361. int b = block[i*4+2];
  362. akku += prods[step];
  363. At1_r += w1*r;
  364. At1_g += w1*g;
  365. At1_b += w1*b;
  366. At2_r += r;
  367. At2_g += g;
  368. At2_b += b;
  369. }
  370. At2_r = 3*At2_r - At1_r;
  371. At2_g = 3*At2_g - At1_g;
  372. At2_b = 3*At2_b - At1_b;
  373. // extract solutions and decide solvability
  374. xx = akku >> 16;
  375. yy = (akku >> 8) & 0xff;
  376. xy = (akku >> 0) & 0xff;
  377. frb = 3.0f * 31.0f / 255.0f / (xx*yy - xy*xy);
  378. fg = frb * 63.0f / 31.0f;
  379. // solve.
  380. max16 = stb__sclamp((At1_r*yy - At2_r*xy)*frb+0.5f,0,31) << 11;
  381. max16 |= stb__sclamp((At1_g*yy - At2_g*xy)*fg +0.5f,0,63) << 5;
  382. max16 |= stb__sclamp((At1_b*yy - At2_b*xy)*frb+0.5f,0,31) << 0;
  383. min16 = stb__sclamp((At2_r*xx - At1_r*xy)*frb+0.5f,0,31) << 11;
  384. min16 |= stb__sclamp((At2_g*xx - At1_g*xy)*fg +0.5f,0,63) << 5;
  385. min16 |= stb__sclamp((At2_b*xx - At1_b*xy)*frb+0.5f,0,31) << 0;
  386. }
  387. *pmin16 = min16;
  388. *pmax16 = max16;
  389. return oldMin != min16 || oldMax != max16;
  390. }
  391. // Color block compression
  392. static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode)
  393. {
  394. unsigned int mask;
  395. int i;
  396. int dither;
  397. int refinecount;
  398. unsigned short max16, min16;
  399. unsigned char dblock[16*4],color[4*4];
  400. dither = mode & STB_DXT_DITHER;
  401. refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1;
  402. // check if block is constant
  403. for (i=1;i<16;i++)
  404. if (((unsigned int *) block)[i] != ((unsigned int *) block)[0])
  405. break;
  406. if(i == 16) { // constant color
  407. int r = block[0], g = block[1], b = block[2];
  408. mask = 0xaaaaaaaa;
  409. max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
  410. min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
  411. } else {
  412. // first step: compute dithered version for PCA if desired
  413. if(dither)
  414. stb__DitherBlock(dblock,block);
  415. // second step: pca+map along principal axis
  416. stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16);
  417. if (max16 != min16) {
  418. stb__EvalColors(color,max16,min16);
  419. mask = stb__MatchColorsBlock(block,color,dither);
  420. } else
  421. mask = 0;
  422. // third step: refine (multiple times if requested)
  423. for (i=0;i<refinecount;i++) {
  424. unsigned int lastmask = mask;
  425. if (stb__RefineBlock(dither ? dblock : block,&max16,&min16,mask)) {
  426. if (max16 != min16) {
  427. stb__EvalColors(color,max16,min16);
  428. mask = stb__MatchColorsBlock(block,color,dither);
  429. } else {
  430. mask = 0;
  431. break;
  432. }
  433. }
  434. if(mask == lastmask)
  435. break;
  436. }
  437. }
  438. // write the color block
  439. if(max16 < min16)
  440. {
  441. unsigned short t = min16;
  442. min16 = max16;
  443. max16 = t;
  444. mask ^= 0x55555555;
  445. }
  446. dest[0] = (unsigned char) (max16);
  447. dest[1] = (unsigned char) (max16 >> 8);
  448. dest[2] = (unsigned char) (min16);
  449. dest[3] = (unsigned char) (min16 >> 8);
  450. dest[4] = (unsigned char) (mask);
  451. dest[5] = (unsigned char) (mask >> 8);
  452. dest[6] = (unsigned char) (mask >> 16);
  453. dest[7] = (unsigned char) (mask >> 24);
  454. }
  455. // Alpha block compression (this is easy for a change)
  456. static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src,int mode)
  457. {
  458. int i,dist,bias,dist4,dist2,bits,mask;
  459. // find min/max color
  460. int mn,mx;
  461. mn = mx = src[3];
  462. for (i=1;i<16;i++)
  463. {
  464. if (src[i*4+3] < mn) mn = src[i*4+3];
  465. else if (src[i*4+3] > mx) mx = src[i*4+3];
  466. }
  467. // encode them
  468. ((unsigned char *)dest)[0] = mx;
  469. ((unsigned char *)dest)[1] = mn;
  470. dest += 2;
  471. // determine bias and emit color indices
  472. // given the choice of mx/mn, these indices are optimal:
  473. // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/
  474. dist = mx-mn;
  475. dist4 = dist*4;
  476. dist2 = dist*2;
  477. bias = (dist < 8) ? (dist - 1) : (dist/2 + 2);
  478. bias -= mn * 7;
  479. bits = 0,mask=0;
  480. for (i=0;i<16;i++) {
  481. int a = src[i*4+3]*7 + bias;
  482. int ind,t;
  483. // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max).
  484. t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t;
  485. t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t;
  486. ind += (a >= dist);
  487. // turn linear scale into DXT index (0/1 are extremal pts)
  488. ind = -ind & 7;
  489. ind ^= (2 > ind);
  490. // write index
  491. mask |= ind << bits;
  492. if((bits += 3) >= 8) {
  493. *dest++ = mask;
  494. mask >>= 8;
  495. bits -= 8;
  496. }
  497. }
  498. }
  499. static void stb__InitDXT()
  500. {
  501. int i;
  502. for(i=0;i<32;i++)
  503. stb__Expand5[i] = (i<<3)|(i>>2);
  504. for(i=0;i<64;i++)
  505. stb__Expand6[i] = (i<<2)|(i>>4);
  506. for(i=0;i<256+16;i++)
  507. {
  508. int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8;
  509. stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)];
  510. stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)];
  511. }
  512. stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32);
  513. stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64);
  514. }
  515. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
  516. {
  517. static int init=1;
  518. if (init) {
  519. stb__InitDXT();
  520. init=0;
  521. }
  522. if (alpha) {
  523. stb__CompressAlphaBlock(dest,(unsigned char*) src,mode);
  524. dest += 8;
  525. }
  526. stb__CompressColorBlock(dest,(unsigned char*) src,mode);
  527. }
  528. #endif // STB_DXT_IMPLEMENTATION
  529. #endif // STB_INCLUDE_STB_DXT_H