1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * libtxc_dxtn
3bf215546Sopenharmony_ci * Version:  1.0
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Copyright (C) 2004  Roland Scheidegger   All Rights Reserved.
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
15bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20bf215546Sopenharmony_ci * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21bf215546Sopenharmony_ci * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#ifndef TEXCOMPRESS_S3TC_TMP_H
26bf215546Sopenharmony_ci#define TEXCOMPRESS_S3TC_TMP_H
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#ifdef __APPLE__
29bf215546Sopenharmony_ci#include <OpenGL/gl.h>
30bf215546Sopenharmony_ci#else
31bf215546Sopenharmony_ci#include <GL/gl.h>
32bf215546Sopenharmony_ci#endif
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_citypedef GLubyte GLchan;
35bf215546Sopenharmony_ci#define UBYTE_TO_CHAN(b)  (b)
36bf215546Sopenharmony_ci#define CHAN_MAX 255
37bf215546Sopenharmony_ci#define RCOMP 0
38bf215546Sopenharmony_ci#define GCOMP 1
39bf215546Sopenharmony_ci#define BCOMP 2
40bf215546Sopenharmony_ci#define ACOMP 3
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#define EXP5TO8R(packedcol)					\
43bf215546Sopenharmony_ci   ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7))
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#define EXP6TO8G(packedcol)					\
46bf215546Sopenharmony_ci   ((((packedcol) >> 3) & 0xfc) | (((packedcol) >>  9) & 0x3))
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci#define EXP5TO8B(packedcol)					\
49bf215546Sopenharmony_ci   ((((packedcol) << 3) & 0xf8) | (((packedcol) >>  2) & 0x7))
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#define EXP4TO8(col)						\
52bf215546Sopenharmony_ci   ((col) | ((col) << 4))
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci/* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistatic void dxt135_decode_imageblock ( const GLubyte *img_block_src,
57bf215546Sopenharmony_ci                         GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) {
58bf215546Sopenharmony_ci   GLchan *rgba = (GLchan *) texel;
59bf215546Sopenharmony_ci   const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8);
60bf215546Sopenharmony_ci   const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8);
61bf215546Sopenharmony_ci   const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) |
62bf215546Sopenharmony_ci      (img_block_src[6] << 16) | ((GLuint)img_block_src[7] << 24);
63bf215546Sopenharmony_ci   /* What about big/little endian? */
64bf215546Sopenharmony_ci   GLubyte bit_pos = 2 * (j * 4 + i) ;
65bf215546Sopenharmony_ci   GLubyte code = (GLubyte) ((bits >> bit_pos) & 3);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   rgba[ACOMP] = CHAN_MAX;
68bf215546Sopenharmony_ci   switch (code) {
69bf215546Sopenharmony_ci   case 0:
70bf215546Sopenharmony_ci      rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) );
71bf215546Sopenharmony_ci      rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) );
72bf215546Sopenharmony_ci      rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) );
73bf215546Sopenharmony_ci      break;
74bf215546Sopenharmony_ci   case 1:
75bf215546Sopenharmony_ci      rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) );
76bf215546Sopenharmony_ci      rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) );
77bf215546Sopenharmony_ci      rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) );
78bf215546Sopenharmony_ci      break;
79bf215546Sopenharmony_ci   case 2:
80bf215546Sopenharmony_ci      if ((dxt_type > 1) || (color0 > color1)) {
81bf215546Sopenharmony_ci         rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) );
82bf215546Sopenharmony_ci         rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) );
83bf215546Sopenharmony_ci         rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) );
84bf215546Sopenharmony_ci      }
85bf215546Sopenharmony_ci      else {
86bf215546Sopenharmony_ci         rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) );
87bf215546Sopenharmony_ci         rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) );
88bf215546Sopenharmony_ci         rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) );
89bf215546Sopenharmony_ci      }
90bf215546Sopenharmony_ci      break;
91bf215546Sopenharmony_ci   case 3:
92bf215546Sopenharmony_ci      if ((dxt_type > 1) || (color0 > color1)) {
93bf215546Sopenharmony_ci         rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) );
94bf215546Sopenharmony_ci         rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) );
95bf215546Sopenharmony_ci         rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) );
96bf215546Sopenharmony_ci      }
97bf215546Sopenharmony_ci      else {
98bf215546Sopenharmony_ci         rgba[RCOMP] = 0;
99bf215546Sopenharmony_ci         rgba[GCOMP] = 0;
100bf215546Sopenharmony_ci         rgba[BCOMP] = 0;
101bf215546Sopenharmony_ci         if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0);
102bf215546Sopenharmony_ci      }
103bf215546Sopenharmony_ci      break;
104bf215546Sopenharmony_ci   default:
105bf215546Sopenharmony_ci   /* CANNOT happen (I hope) */
106bf215546Sopenharmony_ci      break;
107bf215546Sopenharmony_ci   }
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_cistatic void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
112bf215546Sopenharmony_ci                         GLint i, GLint j, GLvoid *texel)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   /* Extract the (i,j) pixel from pixdata and return it
115bf215546Sopenharmony_ci    * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
116bf215546Sopenharmony_ci    */
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
119bf215546Sopenharmony_ci   dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
124bf215546Sopenharmony_ci                         GLint i, GLint j, GLvoid *texel)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   /* Extract the (i,j) pixel from pixdata and return it
127bf215546Sopenharmony_ci    * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
128bf215546Sopenharmony_ci    */
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
131bf215546Sopenharmony_ci   dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel);
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
135bf215546Sopenharmony_ci                         GLint i, GLint j, GLvoid *texel) {
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   /* Extract the (i,j) pixel from pixdata and return it
138bf215546Sopenharmony_ci    * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
139bf215546Sopenharmony_ci    */
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   GLchan *rgba = (GLchan *) texel;
142bf215546Sopenharmony_ci   const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
143bf215546Sopenharmony_ci   const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf;
144bf215546Sopenharmony_ci   dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
145bf215546Sopenharmony_ci   rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) );
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
149bf215546Sopenharmony_ci                         GLint i, GLint j, GLvoid *texel) {
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   /* Extract the (i,j) pixel from pixdata and return it
152bf215546Sopenharmony_ci    * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
153bf215546Sopenharmony_ci    */
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   GLchan *rgba = (GLchan *) texel;
156bf215546Sopenharmony_ci   const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
157bf215546Sopenharmony_ci   const GLubyte alpha0 = blksrc[0];
158bf215546Sopenharmony_ci   const GLubyte alpha1 = blksrc[1];
159bf215546Sopenharmony_ci   const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3;
160bf215546Sopenharmony_ci   const GLubyte acodelow = blksrc[2 + bit_pos / 8];
161bf215546Sopenharmony_ci   const GLubyte acodehigh = blksrc[3 + bit_pos / 8];
162bf215546Sopenharmony_ci   const GLubyte code = (acodelow >> (bit_pos & 0x7) |
163bf215546Sopenharmony_ci      (acodehigh  << (8 - (bit_pos & 0x7)))) & 0x7;
164bf215546Sopenharmony_ci   dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
165bf215546Sopenharmony_ci   if (code == 0)
166bf215546Sopenharmony_ci      rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 );
167bf215546Sopenharmony_ci   else if (code == 1)
168bf215546Sopenharmony_ci      rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 );
169bf215546Sopenharmony_ci   else if (alpha0 > alpha1)
170bf215546Sopenharmony_ci      rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) );
171bf215546Sopenharmony_ci   else if (code < 6)
172bf215546Sopenharmony_ci      rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) );
173bf215546Sopenharmony_ci   else if (code == 6)
174bf215546Sopenharmony_ci      rgba[ACOMP] = 0;
175bf215546Sopenharmony_ci   else
176bf215546Sopenharmony_ci      rgba[ACOMP] = CHAN_MAX;
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci/* weights used for error function, basically weights (unsquared 2/4/1) according to rgb->luminance conversion
181bf215546Sopenharmony_ci   not sure if this really reflects visual perception */
182bf215546Sopenharmony_ci#define REDWEIGHT 4
183bf215546Sopenharmony_ci#define GREENWEIGHT 16
184bf215546Sopenharmony_ci#define BLUEWEIGHT 1
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci#define ALPHACUT 127
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_cistatic void fancybasecolorsearch( UNUSED GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2],
189bf215546Sopenharmony_ci                           GLint numxpixels, GLint numypixels, UNUSED GLint type, UNUSED GLboolean haveAlpha)
190bf215546Sopenharmony_ci{
191bf215546Sopenharmony_ci   /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   /* TODO could also try to find a better encoding for the 3-color-encoding type, this really should be done
194bf215546Sopenharmony_ci      if it's rgba_dxt1 and we have alpha in the block, currently even values which will be mapped to black
195bf215546Sopenharmony_ci      due to their alpha value will influence the result */
196bf215546Sopenharmony_ci   GLint i, j, colors, z;
197bf215546Sopenharmony_ci   GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest;
198bf215546Sopenharmony_ci   GLint colordist, blockerrlin[2][3];
199bf215546Sopenharmony_ci   GLubyte nrcolor[2];
200bf215546Sopenharmony_ci   GLint pixerrorcolorbest[3] = {0};
201bf215546Sopenharmony_ci   GLubyte enc = 0;
202bf215546Sopenharmony_ci   GLubyte cv[4][4];
203bf215546Sopenharmony_ci   GLubyte testcolor[2][3];
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci/*   fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
206bf215546Sopenharmony_ci      bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/
207bf215546Sopenharmony_ci   if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) <
208bf215546Sopenharmony_ci      ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3)) {
209bf215546Sopenharmony_ci      testcolor[0][0] = bestcolor[0][0];
210bf215546Sopenharmony_ci      testcolor[0][1] = bestcolor[0][1];
211bf215546Sopenharmony_ci      testcolor[0][2] = bestcolor[0][2];
212bf215546Sopenharmony_ci      testcolor[1][0] = bestcolor[1][0];
213bf215546Sopenharmony_ci      testcolor[1][1] = bestcolor[1][1];
214bf215546Sopenharmony_ci      testcolor[1][2] = bestcolor[1][2];
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci   else {
217bf215546Sopenharmony_ci      testcolor[1][0] = bestcolor[0][0];
218bf215546Sopenharmony_ci      testcolor[1][1] = bestcolor[0][1];
219bf215546Sopenharmony_ci      testcolor[1][2] = bestcolor[0][2];
220bf215546Sopenharmony_ci      testcolor[0][0] = bestcolor[1][0];
221bf215546Sopenharmony_ci      testcolor[0][1] = bestcolor[1][1];
222bf215546Sopenharmony_ci      testcolor[0][2] = bestcolor[1][2];
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   for (i = 0; i < 3; i ++) {
226bf215546Sopenharmony_ci      cv[0][i] = testcolor[0][i];
227bf215546Sopenharmony_ci      cv[1][i] = testcolor[1][i];
228bf215546Sopenharmony_ci      cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3;
229bf215546Sopenharmony_ci      cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3;
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   blockerrlin[0][0] = 0;
233bf215546Sopenharmony_ci   blockerrlin[0][1] = 0;
234bf215546Sopenharmony_ci   blockerrlin[0][2] = 0;
235bf215546Sopenharmony_ci   blockerrlin[1][0] = 0;
236bf215546Sopenharmony_ci   blockerrlin[1][1] = 0;
237bf215546Sopenharmony_ci   blockerrlin[1][2] = 0;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   nrcolor[0] = 0;
240bf215546Sopenharmony_ci   nrcolor[1] = 0;
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
243bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
244bf215546Sopenharmony_ci         pixerrorbest = 0xffffffff;
245bf215546Sopenharmony_ci         for (colors = 0; colors < 4; colors++) {
246bf215546Sopenharmony_ci            colordist = srccolors[j][i][0] - (cv[colors][0]);
247bf215546Sopenharmony_ci            pixerror = colordist * colordist * REDWEIGHT;
248bf215546Sopenharmony_ci            pixerrorred = colordist;
249bf215546Sopenharmony_ci            colordist = srccolors[j][i][1] - (cv[colors][1]);
250bf215546Sopenharmony_ci            pixerror += colordist * colordist * GREENWEIGHT;
251bf215546Sopenharmony_ci            pixerrorgreen = colordist;
252bf215546Sopenharmony_ci            colordist = srccolors[j][i][2] - (cv[colors][2]);
253bf215546Sopenharmony_ci            pixerror += colordist * colordist * BLUEWEIGHT;
254bf215546Sopenharmony_ci            pixerrorblue = colordist;
255bf215546Sopenharmony_ci            if (pixerror < pixerrorbest) {
256bf215546Sopenharmony_ci               enc = colors;
257bf215546Sopenharmony_ci               pixerrorbest = pixerror;
258bf215546Sopenharmony_ci               pixerrorcolorbest[0] = pixerrorred;
259bf215546Sopenharmony_ci               pixerrorcolorbest[1] = pixerrorgreen;
260bf215546Sopenharmony_ci               pixerrorcolorbest[2] = pixerrorblue;
261bf215546Sopenharmony_ci            }
262bf215546Sopenharmony_ci         }
263bf215546Sopenharmony_ci         if (enc == 0) {
264bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
265bf215546Sopenharmony_ci               blockerrlin[0][z] += 3 * pixerrorcolorbest[z];
266bf215546Sopenharmony_ci            }
267bf215546Sopenharmony_ci            nrcolor[0] += 3;
268bf215546Sopenharmony_ci         }
269bf215546Sopenharmony_ci         else if (enc == 2) {
270bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
271bf215546Sopenharmony_ci               blockerrlin[0][z] += 2 * pixerrorcolorbest[z];
272bf215546Sopenharmony_ci            }
273bf215546Sopenharmony_ci            nrcolor[0] += 2;
274bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
275bf215546Sopenharmony_ci               blockerrlin[1][z] += 1 * pixerrorcolorbest[z];
276bf215546Sopenharmony_ci            }
277bf215546Sopenharmony_ci            nrcolor[1] += 1;
278bf215546Sopenharmony_ci         }
279bf215546Sopenharmony_ci         else if (enc == 3) {
280bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
281bf215546Sopenharmony_ci               blockerrlin[0][z] += 1 * pixerrorcolorbest[z];
282bf215546Sopenharmony_ci            }
283bf215546Sopenharmony_ci            nrcolor[0] += 1;
284bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
285bf215546Sopenharmony_ci               blockerrlin[1][z] += 2 * pixerrorcolorbest[z];
286bf215546Sopenharmony_ci            }
287bf215546Sopenharmony_ci            nrcolor[1] += 2;
288bf215546Sopenharmony_ci         }
289bf215546Sopenharmony_ci         else if (enc == 1) {
290bf215546Sopenharmony_ci            for (z = 0; z < 3; z++) {
291bf215546Sopenharmony_ci               blockerrlin[1][z] += 3 * pixerrorcolorbest[z];
292bf215546Sopenharmony_ci            }
293bf215546Sopenharmony_ci            nrcolor[1] += 3;
294bf215546Sopenharmony_ci         }
295bf215546Sopenharmony_ci      }
296bf215546Sopenharmony_ci   }
297bf215546Sopenharmony_ci   if (nrcolor[0] == 0) nrcolor[0] = 1;
298bf215546Sopenharmony_ci   if (nrcolor[1] == 0) nrcolor[1] = 1;
299bf215546Sopenharmony_ci   for (j = 0; j < 2; j++) {
300bf215546Sopenharmony_ci      for (i = 0; i < 3; i++) {
301bf215546Sopenharmony_ci	 GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j];
302bf215546Sopenharmony_ci	 if (newvalue <= 0)
303bf215546Sopenharmony_ci	    testcolor[j][i] = 0;
304bf215546Sopenharmony_ci	 else if (newvalue >= 255)
305bf215546Sopenharmony_ci	    testcolor[j][i] = 255;
306bf215546Sopenharmony_ci	 else testcolor[j][i] = newvalue;
307bf215546Sopenharmony_ci      }
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) &&
311bf215546Sopenharmony_ci       (abs(testcolor[0][1] - testcolor[1][1]) < 4) &&
312bf215546Sopenharmony_ci       (abs(testcolor[0][2] - testcolor[1][2]) < 8)) {
313bf215546Sopenharmony_ci       /* both colors are so close they might get encoded as the same 16bit values */
314bf215546Sopenharmony_ci      GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1;
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci      coldiffred = abs(testcolor[0][0] - testcolor[1][0]);
317bf215546Sopenharmony_ci      coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]);
318bf215546Sopenharmony_ci      coldiffblue = abs(testcolor[0][2] - testcolor[1][2]);
319bf215546Sopenharmony_ci      coldiffmax = coldiffred;
320bf215546Sopenharmony_ci      if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen;
321bf215546Sopenharmony_ci      if (coldiffmax < coldiffblue) coldiffmax = coldiffblue;
322bf215546Sopenharmony_ci      if (coldiffmax > 0) {
323bf215546Sopenharmony_ci         if (coldiffmax > 4) factor = 2;
324bf215546Sopenharmony_ci         else if (coldiffmax > 2) factor = 3;
325bf215546Sopenharmony_ci         else factor = 4;
326bf215546Sopenharmony_ci         /* Won't do much if the color value is near 255... */
327bf215546Sopenharmony_ci         /* argh so many ifs */
328bf215546Sopenharmony_ci         if (testcolor[1][1] >= testcolor[0][1]) {
329bf215546Sopenharmony_ci            ind1 = 1; ind0 = 0;
330bf215546Sopenharmony_ci         }
331bf215546Sopenharmony_ci         else {
332bf215546Sopenharmony_ci            ind1 = 0; ind0 = 1;
333bf215546Sopenharmony_ci         }
334bf215546Sopenharmony_ci         if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255)
335bf215546Sopenharmony_ci            testcolor[ind1][1] += factor * coldiffgreen;
336bf215546Sopenharmony_ci         else testcolor[ind1][1] = 255;
337bf215546Sopenharmony_ci         if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) {
338bf215546Sopenharmony_ci            if ((testcolor[ind1][0] + factor * coldiffred) <= 255)
339bf215546Sopenharmony_ci               testcolor[ind1][0] += factor * coldiffred;
340bf215546Sopenharmony_ci            else testcolor[ind1][0] = 255;
341bf215546Sopenharmony_ci         }
342bf215546Sopenharmony_ci         else {
343bf215546Sopenharmony_ci            if ((testcolor[ind0][0] + factor * coldiffred) <= 255)
344bf215546Sopenharmony_ci               testcolor[ind0][0] += factor * coldiffred;
345bf215546Sopenharmony_ci            else testcolor[ind0][0] = 255;
346bf215546Sopenharmony_ci         }
347bf215546Sopenharmony_ci         if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) {
348bf215546Sopenharmony_ci            if ((testcolor[ind1][2] + factor * coldiffblue) <= 255)
349bf215546Sopenharmony_ci               testcolor[ind1][2] += factor * coldiffblue;
350bf215546Sopenharmony_ci            else testcolor[ind1][2] = 255;
351bf215546Sopenharmony_ci         }
352bf215546Sopenharmony_ci         else {
353bf215546Sopenharmony_ci            if ((testcolor[ind0][2] + factor * coldiffblue) <= 255)
354bf215546Sopenharmony_ci               testcolor[ind0][2] += factor * coldiffblue;
355bf215546Sopenharmony_ci            else testcolor[ind0][2] = 255;
356bf215546Sopenharmony_ci         }
357bf215546Sopenharmony_ci      }
358bf215546Sopenharmony_ci   }
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) <
361bf215546Sopenharmony_ci      ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3) {
362bf215546Sopenharmony_ci      for (i = 0; i < 3; i++) {
363bf215546Sopenharmony_ci         bestcolor[0][i] = testcolor[0][i];
364bf215546Sopenharmony_ci         bestcolor[1][i] = testcolor[1][i];
365bf215546Sopenharmony_ci      }
366bf215546Sopenharmony_ci   }
367bf215546Sopenharmony_ci   else {
368bf215546Sopenharmony_ci      for (i = 0; i < 3; i++) {
369bf215546Sopenharmony_ci         bestcolor[0][i] = testcolor[1][i];
370bf215546Sopenharmony_ci         bestcolor[1][i] = testcolor[0][i];
371bf215546Sopenharmony_ci      }
372bf215546Sopenharmony_ci   }
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci/*     fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
375bf215546Sopenharmony_ci     bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/
376bf215546Sopenharmony_ci}
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_cistatic void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2],
381bf215546Sopenharmony_ci                           GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha)
382bf215546Sopenharmony_ci{
383bf215546Sopenharmony_ci   /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   GLint i, j, colors;
386bf215546Sopenharmony_ci   GLuint testerror, testerror2, pixerror, pixerrorbest;
387bf215546Sopenharmony_ci   GLint colordist;
388bf215546Sopenharmony_ci   GLushort color0, color1, tempcolor;
389bf215546Sopenharmony_ci   GLuint bits = 0, bits2 = 0;
390bf215546Sopenharmony_ci   GLubyte *colorptr;
391bf215546Sopenharmony_ci   GLubyte enc = 0;
392bf215546Sopenharmony_ci   GLubyte cv[4][4];
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   bestcolor[0][0] = bestcolor[0][0] & 0xf8;
395bf215546Sopenharmony_ci   bestcolor[0][1] = bestcolor[0][1] & 0xfc;
396bf215546Sopenharmony_ci   bestcolor[0][2] = bestcolor[0][2] & 0xf8;
397bf215546Sopenharmony_ci   bestcolor[1][0] = bestcolor[1][0] & 0xf8;
398bf215546Sopenharmony_ci   bestcolor[1][1] = bestcolor[1][1] & 0xfc;
399bf215546Sopenharmony_ci   bestcolor[1][2] = bestcolor[1][2] & 0xf8;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3;
402bf215546Sopenharmony_ci   color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3;
403bf215546Sopenharmony_ci   if (color0 < color1) {
404bf215546Sopenharmony_ci      tempcolor = color0; color0 = color1; color1 = tempcolor;
405bf215546Sopenharmony_ci      colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr;
406bf215546Sopenharmony_ci   }
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   for (i = 0; i < 3; i++) {
410bf215546Sopenharmony_ci      cv[0][i] = bestcolor[0][i];
411bf215546Sopenharmony_ci      cv[1][i] = bestcolor[1][i];
412bf215546Sopenharmony_ci      cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3;
413bf215546Sopenharmony_ci      cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3;
414bf215546Sopenharmony_ci   }
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   testerror = 0;
417bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
418bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
419bf215546Sopenharmony_ci         pixerrorbest = 0xffffffff;
420bf215546Sopenharmony_ci         for (colors = 0; colors < 4; colors++) {
421bf215546Sopenharmony_ci            colordist = srccolors[j][i][0] - cv[colors][0];
422bf215546Sopenharmony_ci            pixerror = colordist * colordist * REDWEIGHT;
423bf215546Sopenharmony_ci            colordist = srccolors[j][i][1] - cv[colors][1];
424bf215546Sopenharmony_ci            pixerror += colordist * colordist * GREENWEIGHT;
425bf215546Sopenharmony_ci            colordist = srccolors[j][i][2] - cv[colors][2];
426bf215546Sopenharmony_ci            pixerror += colordist * colordist * BLUEWEIGHT;
427bf215546Sopenharmony_ci            if (pixerror < pixerrorbest) {
428bf215546Sopenharmony_ci               pixerrorbest = pixerror;
429bf215546Sopenharmony_ci               enc = colors;
430bf215546Sopenharmony_ci            }
431bf215546Sopenharmony_ci         }
432bf215546Sopenharmony_ci         testerror += pixerrorbest;
433bf215546Sopenharmony_ci         bits |= (uint32_t)enc << (2 * (j * 4 + i));
434bf215546Sopenharmony_ci      }
435bf215546Sopenharmony_ci   }
436bf215546Sopenharmony_ci   /* some hw might disagree but actually decoding should always use 4-color encoding
437bf215546Sopenharmony_ci      for non-dxt1 formats */
438bf215546Sopenharmony_ci   if (type == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
439bf215546Sopenharmony_ci      for (i = 0; i < 3; i++) {
440bf215546Sopenharmony_ci         cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2;
441bf215546Sopenharmony_ci         /* this isn't used. Looks like the black color constant can only be used
442bf215546Sopenharmony_ci            with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees,
443bf215546Sopenharmony_ci            it will decode 3 to black even with DXT3/5), and due to how the color searching works
444bf215546Sopenharmony_ci            it won't get used even then */
445bf215546Sopenharmony_ci         cv[3][i] = 0;
446bf215546Sopenharmony_ci      }
447bf215546Sopenharmony_ci      testerror2 = 0;
448bf215546Sopenharmony_ci      for (j = 0; j < numypixels; j++) {
449bf215546Sopenharmony_ci         for (i = 0; i < numxpixels; i++) {
450bf215546Sopenharmony_ci            pixerrorbest = 0xffffffff;
451bf215546Sopenharmony_ci            if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3] <= ALPHACUT)) {
452bf215546Sopenharmony_ci               enc = 3;
453bf215546Sopenharmony_ci               pixerrorbest = 0; /* don't calculate error */
454bf215546Sopenharmony_ci            }
455bf215546Sopenharmony_ci            else {
456bf215546Sopenharmony_ci               /* we're calculating the same what we have done already for colors 0-1 above... */
457bf215546Sopenharmony_ci               for (colors = 0; colors < 3; colors++) {
458bf215546Sopenharmony_ci                  colordist = srccolors[j][i][0] - cv[colors][0];
459bf215546Sopenharmony_ci                  pixerror = colordist * colordist * REDWEIGHT;
460bf215546Sopenharmony_ci                  colordist = srccolors[j][i][1] - cv[colors][1];
461bf215546Sopenharmony_ci                  pixerror += colordist * colordist * GREENWEIGHT;
462bf215546Sopenharmony_ci                  colordist = srccolors[j][i][2] - cv[colors][2];
463bf215546Sopenharmony_ci                  pixerror += colordist * colordist * BLUEWEIGHT;
464bf215546Sopenharmony_ci                  if (pixerror < pixerrorbest) {
465bf215546Sopenharmony_ci                     pixerrorbest = pixerror;
466bf215546Sopenharmony_ci                     /* need to exchange colors later */
467bf215546Sopenharmony_ci                     if (colors > 1) enc = colors;
468bf215546Sopenharmony_ci                     else enc = colors ^ 1;
469bf215546Sopenharmony_ci                  }
470bf215546Sopenharmony_ci               }
471bf215546Sopenharmony_ci            }
472bf215546Sopenharmony_ci            testerror2 += pixerrorbest;
473bf215546Sopenharmony_ci            bits2 |= (uint32_t)enc << (2 * (j * 4 + i));
474bf215546Sopenharmony_ci         }
475bf215546Sopenharmony_ci      }
476bf215546Sopenharmony_ci   } else {
477bf215546Sopenharmony_ci      testerror2 = 0xffffffff;
478bf215546Sopenharmony_ci   }
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   /* finally we're finished, write back colors and bits */
481bf215546Sopenharmony_ci   if ((testerror > testerror2) || (haveAlpha)) {
482bf215546Sopenharmony_ci      *blkaddr++ = color1 & 0xff;
483bf215546Sopenharmony_ci      *blkaddr++ = color1 >> 8;
484bf215546Sopenharmony_ci      *blkaddr++ = color0 & 0xff;
485bf215546Sopenharmony_ci      *blkaddr++ = color0 >> 8;
486bf215546Sopenharmony_ci      *blkaddr++ = bits2 & 0xff;
487bf215546Sopenharmony_ci      *blkaddr++ = ( bits2 >> 8) & 0xff;
488bf215546Sopenharmony_ci      *blkaddr++ = ( bits2 >> 16) & 0xff;
489bf215546Sopenharmony_ci      *blkaddr = bits2 >> 24;
490bf215546Sopenharmony_ci   }
491bf215546Sopenharmony_ci   else {
492bf215546Sopenharmony_ci      *blkaddr++ = color0 & 0xff;
493bf215546Sopenharmony_ci      *blkaddr++ = color0 >> 8;
494bf215546Sopenharmony_ci      *blkaddr++ = color1 & 0xff;
495bf215546Sopenharmony_ci      *blkaddr++ = color1 >> 8;
496bf215546Sopenharmony_ci      *blkaddr++ = bits & 0xff;
497bf215546Sopenharmony_ci      *blkaddr++ = ( bits >> 8) & 0xff;
498bf215546Sopenharmony_ci      *blkaddr++ = ( bits >> 16) & 0xff;
499bf215546Sopenharmony_ci      *blkaddr = bits >> 24;
500bf215546Sopenharmony_ci   }
501bf215546Sopenharmony_ci}
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_cistatic void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4],
504bf215546Sopenharmony_ci                         GLint numxpixels, GLint numypixels, GLuint type )
505bf215546Sopenharmony_ci{
506bf215546Sopenharmony_ci/* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color
507bf215546Sopenharmony_ci   present in the picture as base colors */
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   /* define lowest and highest color as shortest and longest vector to 0/0/0, though the
510bf215546Sopenharmony_ci      vectors are weighted similar to their importance in rgb-luminance conversion
511bf215546Sopenharmony_ci      doesn't work too well though...
512bf215546Sopenharmony_ci      This seems to be a rather difficult problem */
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   GLubyte *bestcolor[2];
515bf215546Sopenharmony_ci   GLubyte basecolors[2][3];
516bf215546Sopenharmony_ci   GLubyte i, j;
517bf215546Sopenharmony_ci   GLuint lowcv, highcv, testcv;
518bf215546Sopenharmony_ci   GLboolean haveAlpha = GL_FALSE;
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT +
521bf215546Sopenharmony_ci                          srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT +
522bf215546Sopenharmony_ci                          srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT;
523bf215546Sopenharmony_ci   bestcolor[0] = bestcolor[1] = srccolors[0][0];
524bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
525bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
526bf215546Sopenharmony_ci         /* don't use this as a base color if the pixel will get black/transparent anyway */
527bf215546Sopenharmony_ci         if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] > ALPHACUT)) {
528bf215546Sopenharmony_ci            testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT +
529bf215546Sopenharmony_ci                     srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT +
530bf215546Sopenharmony_ci                     srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT;
531bf215546Sopenharmony_ci            if (testcv > highcv) {
532bf215546Sopenharmony_ci               highcv = testcv;
533bf215546Sopenharmony_ci               bestcolor[1] = srccolors[j][i];
534bf215546Sopenharmony_ci            }
535bf215546Sopenharmony_ci            else if (testcv < lowcv) {
536bf215546Sopenharmony_ci               lowcv = testcv;
537bf215546Sopenharmony_ci               bestcolor[0] = srccolors[j][i];
538bf215546Sopenharmony_ci            }
539bf215546Sopenharmony_ci         }
540bf215546Sopenharmony_ci         else haveAlpha = GL_TRUE;
541bf215546Sopenharmony_ci      }
542bf215546Sopenharmony_ci   }
543bf215546Sopenharmony_ci   /* make sure the original color values won't get touched... */
544bf215546Sopenharmony_ci   for (j = 0; j < 2; j++) {
545bf215546Sopenharmony_ci      for (i = 0; i < 3; i++) {
546bf215546Sopenharmony_ci         basecolors[j][i] = bestcolor[j][i];
547bf215546Sopenharmony_ci      }
548bf215546Sopenharmony_ci   }
549bf215546Sopenharmony_ci   bestcolor[0] = basecolors[0];
550bf215546Sopenharmony_ci   bestcolor[1] = basecolors[1];
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   /* try to find better base colors */
553bf215546Sopenharmony_ci   fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha);
554bf215546Sopenharmony_ci   /* find the best encoding for these colors, and store the result */
555bf215546Sopenharmony_ci   storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha);
556bf215546Sopenharmony_ci}
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_cistatic void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2,
559bf215546Sopenharmony_ci                         GLubyte alphaenc[16])
560bf215546Sopenharmony_ci{
561bf215546Sopenharmony_ci   *blkaddr++ = alphabase1;
562bf215546Sopenharmony_ci   *blkaddr++ = alphabase2;
563bf215546Sopenharmony_ci   *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
564bf215546Sopenharmony_ci   *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
565bf215546Sopenharmony_ci   *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
566bf215546Sopenharmony_ci   *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
567bf215546Sopenharmony_ci   *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
568bf215546Sopenharmony_ci   *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
569bf215546Sopenharmony_ci}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_cistatic void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4],
572bf215546Sopenharmony_ci                            GLint numxpixels, GLint numypixels)
573bf215546Sopenharmony_ci{
574bf215546Sopenharmony_ci   GLubyte alphabase[2], alphause[2];
575bf215546Sopenharmony_ci   GLshort alphatest[2];
576bf215546Sopenharmony_ci   GLuint alphablockerror1, alphablockerror2, alphablockerror3;
577bf215546Sopenharmony_ci   GLubyte i, j, aindex, acutValues[7];
578bf215546Sopenharmony_ci   GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16];
579bf215546Sopenharmony_ci   GLboolean alphaabsmin = GL_FALSE;
580bf215546Sopenharmony_ci   GLboolean alphaabsmax = GL_FALSE;
581bf215546Sopenharmony_ci   GLshort alphadist;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
584bf215546Sopenharmony_ci   alphabase[0] = 0xff; alphabase[1] = 0x0;
585bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
586bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
587bf215546Sopenharmony_ci         if (srccolors[j][i][3] == 0)
588bf215546Sopenharmony_ci            alphaabsmin = GL_TRUE;
589bf215546Sopenharmony_ci         else if (srccolors[j][i][3] == 255)
590bf215546Sopenharmony_ci            alphaabsmax = GL_TRUE;
591bf215546Sopenharmony_ci         else {
592bf215546Sopenharmony_ci            if (srccolors[j][i][3] > alphabase[1])
593bf215546Sopenharmony_ci               alphabase[1] = srccolors[j][i][3];
594bf215546Sopenharmony_ci            if (srccolors[j][i][3] < alphabase[0])
595bf215546Sopenharmony_ci               alphabase[0] = srccolors[j][i][3];
596bf215546Sopenharmony_ci         }
597bf215546Sopenharmony_ci      }
598bf215546Sopenharmony_ci   }
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */
602bf215546Sopenharmony_ci      /* shortcut here since it is a very common case (and also avoids later problems) */
603bf215546Sopenharmony_ci      /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */
604bf215546Sopenharmony_ci      /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ci      *blkaddr++ = srccolors[0][0][3];
607bf215546Sopenharmony_ci      blkaddr++;
608bf215546Sopenharmony_ci      *blkaddr++ = 0;
609bf215546Sopenharmony_ci      *blkaddr++ = 0;
610bf215546Sopenharmony_ci      *blkaddr++ = 0;
611bf215546Sopenharmony_ci      *blkaddr++ = 0;
612bf215546Sopenharmony_ci      *blkaddr++ = 0;
613bf215546Sopenharmony_ci      *blkaddr++ = 0;
614bf215546Sopenharmony_ci/*      fprintf(stderr, "enc0 used\n");*/
615bf215546Sopenharmony_ci      return;
616bf215546Sopenharmony_ci   }
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   /* find best encoding for alpha0 > alpha1 */
619bf215546Sopenharmony_ci   /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
620bf215546Sopenharmony_ci   alphablockerror1 = 0x0;
621bf215546Sopenharmony_ci   alphablockerror2 = 0xffffffff;
622bf215546Sopenharmony_ci   alphablockerror3 = 0xffffffff;
623bf215546Sopenharmony_ci   if (alphaabsmin) alphause[0] = 0;
624bf215546Sopenharmony_ci   else alphause[0] = alphabase[0];
625bf215546Sopenharmony_ci   if (alphaabsmax) alphause[1] = 255;
626bf215546Sopenharmony_ci   else alphause[1] = alphabase[1];
627bf215546Sopenharmony_ci   /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
628bf215546Sopenharmony_ci   for (aindex = 0; aindex < 7; aindex++) {
629bf215546Sopenharmony_ci      /* don't forget here is always rounded down */
630bf215546Sopenharmony_ci      acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
631bf215546Sopenharmony_ci   }
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
634bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
635bf215546Sopenharmony_ci         /* maybe it's overkill to have the most complicated calculation just for the error
636bf215546Sopenharmony_ci            calculation which we only need to figure out if encoding1 or encoding2 is better... */
637bf215546Sopenharmony_ci         if (srccolors[j][i][3] > acutValues[0]) {
638bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 0;
639bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - alphause[1];
640bf215546Sopenharmony_ci         }
641bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[1]) {
642bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 2;
643bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7;
644bf215546Sopenharmony_ci         }
645bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[2]) {
646bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 3;
647bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7;
648bf215546Sopenharmony_ci         }
649bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[3]) {
650bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 4;
651bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7;
652bf215546Sopenharmony_ci         }
653bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[4]) {
654bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 5;
655bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7;
656bf215546Sopenharmony_ci         }
657bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[5]) {
658bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 6;
659bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7;
660bf215546Sopenharmony_ci         }
661bf215546Sopenharmony_ci         else if (srccolors[j][i][3] > acutValues[6]) {
662bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 7;
663bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7;
664bf215546Sopenharmony_ci         }
665bf215546Sopenharmony_ci         else {
666bf215546Sopenharmony_ci            alphaenc1[4*j + i] = 1;
667bf215546Sopenharmony_ci            alphadist = srccolors[j][i][3] - alphause[0];
668bf215546Sopenharmony_ci         }
669bf215546Sopenharmony_ci         alphablockerror1 += alphadist * alphadist;
670bf215546Sopenharmony_ci      }
671bf215546Sopenharmony_ci   }
672bf215546Sopenharmony_ci/*      for (i = 0; i < 16; i++) {
673bf215546Sopenharmony_ci         fprintf(stderr, "%d ", alphaenc1[i]);
674bf215546Sopenharmony_ci      }
675bf215546Sopenharmony_ci      fprintf(stderr, "cutVals ");
676bf215546Sopenharmony_ci      for (i = 0; i < 8; i++) {
677bf215546Sopenharmony_ci         fprintf(stderr, "%d ", acutValues[i]);
678bf215546Sopenharmony_ci      }
679bf215546Sopenharmony_ci      fprintf(stderr, "srcVals ");
680bf215546Sopenharmony_ci      for (j = 0; j < numypixels; j++)
681bf215546Sopenharmony_ci         for (i = 0; i < numxpixels; i++) {
682bf215546Sopenharmony_ci            fprintf(stderr, "%d ", srccolors[j][i][3]);
683bf215546Sopenharmony_ci         }
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_ci      fprintf(stderr, "\n");
686bf215546Sopenharmony_ci   }*/
687bf215546Sopenharmony_ci   /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
688bf215546Sopenharmony_ci      are false but try it anyway */
689bf215546Sopenharmony_ci   if (alphablockerror1 >= 32) {
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci      /* don't bother if encoding is already very good, this condition should also imply
692bf215546Sopenharmony_ci      we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
693bf215546Sopenharmony_ci      alphablockerror2 = 0;
694bf215546Sopenharmony_ci      for (aindex = 0; aindex < 5; aindex++) {
695bf215546Sopenharmony_ci         /* don't forget here is always rounded down */
696bf215546Sopenharmony_ci         acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
697bf215546Sopenharmony_ci      }
698bf215546Sopenharmony_ci      for (j = 0; j < numypixels; j++) {
699bf215546Sopenharmony_ci         for (i = 0; i < numxpixels; i++) {
700bf215546Sopenharmony_ci             /* maybe it's overkill to have the most complicated calculation just for the error
701bf215546Sopenharmony_ci               calculation which we only need to figure out if encoding1 or encoding2 is better... */
702bf215546Sopenharmony_ci            if (srccolors[j][i][3] == 0) {
703bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 6;
704bf215546Sopenharmony_ci               alphadist = 0;
705bf215546Sopenharmony_ci            }
706bf215546Sopenharmony_ci            else if (srccolors[j][i][3] == 255) {
707bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 7;
708bf215546Sopenharmony_ci               alphadist = 0;
709bf215546Sopenharmony_ci            }
710bf215546Sopenharmony_ci            else if (srccolors[j][i][3] <= acutValues[0]) {
711bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 0;
712bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - alphabase[0];
713bf215546Sopenharmony_ci            }
714bf215546Sopenharmony_ci            else if (srccolors[j][i][3] <= acutValues[1]) {
715bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 2;
716bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
717bf215546Sopenharmony_ci            }
718bf215546Sopenharmony_ci            else if (srccolors[j][i][3] <= acutValues[2]) {
719bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 3;
720bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
721bf215546Sopenharmony_ci            }
722bf215546Sopenharmony_ci            else if (srccolors[j][i][3] <= acutValues[3]) {
723bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 4;
724bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
725bf215546Sopenharmony_ci            }
726bf215546Sopenharmony_ci            else if (srccolors[j][i][3] <= acutValues[4]) {
727bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 5;
728bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
729bf215546Sopenharmony_ci            }
730bf215546Sopenharmony_ci            else {
731bf215546Sopenharmony_ci               alphaenc2[4*j + i] = 1;
732bf215546Sopenharmony_ci               alphadist = srccolors[j][i][3] - alphabase[1];
733bf215546Sopenharmony_ci            }
734bf215546Sopenharmony_ci            alphablockerror2 += alphadist * alphadist;
735bf215546Sopenharmony_ci         }
736bf215546Sopenharmony_ci      }
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci      /* skip this if the error is already very small
740bf215546Sopenharmony_ci         this encoding is MUCH better on average than #2 though, but expensive! */
741bf215546Sopenharmony_ci      if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
742bf215546Sopenharmony_ci         GLshort blockerrlin1 = 0;
743bf215546Sopenharmony_ci         GLshort blockerrlin2 = 0;
744bf215546Sopenharmony_ci         GLubyte nralphainrangelow = 0;
745bf215546Sopenharmony_ci         GLubyte nralphainrangehigh = 0;
746bf215546Sopenharmony_ci         alphatest[0] = 0xff;
747bf215546Sopenharmony_ci         alphatest[1] = 0x0;
748bf215546Sopenharmony_ci         /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
749bf215546Sopenharmony_ci         for (j = 0; j < numypixels; j++) {
750bf215546Sopenharmony_ci            for (i = 0; i < numxpixels; i++) {
751bf215546Sopenharmony_ci               if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3] < (255 -(alphabase[1] - alphabase[0]) / 28)))
752bf215546Sopenharmony_ci                  alphatest[1] = srccolors[j][i][3];
753bf215546Sopenharmony_ci               if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28))
754bf215546Sopenharmony_ci                  alphatest[0] = srccolors[j][i][3];
755bf215546Sopenharmony_ci            }
756bf215546Sopenharmony_ci         }
757bf215546Sopenharmony_ci          /* shouldn't happen too often, don't really care about those degenerated cases */
758bf215546Sopenharmony_ci          if (alphatest[1] <= alphatest[0]) {
759bf215546Sopenharmony_ci             alphatest[0] = 1;
760bf215546Sopenharmony_ci             alphatest[1] = 254;
761bf215546Sopenharmony_ci/*             fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/
762bf215546Sopenharmony_ci         }
763bf215546Sopenharmony_ci         for (aindex = 0; aindex < 5; aindex++) {
764bf215546Sopenharmony_ci         /* don't forget here is always rounded down */
765bf215546Sopenharmony_ci            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
766bf215546Sopenharmony_ci         }
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci         /* find the "average" difference between the alpha values and the next encoded value.
769bf215546Sopenharmony_ci            This is then used to calculate new base values.
770bf215546Sopenharmony_ci            Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
771bf215546Sopenharmony_ci            since they will see more improvement, and also because the values in the middle are somewhat
772bf215546Sopenharmony_ci            likely to get no improvement at all (because the base values might move in different directions)?
773bf215546Sopenharmony_ci            OTOH it would mean the values in the middle are even less likely to get an improvement
774bf215546Sopenharmony_ci         */
775bf215546Sopenharmony_ci         for (j = 0; j < numypixels; j++) {
776bf215546Sopenharmony_ci            for (i = 0; i < numxpixels; i++) {
777bf215546Sopenharmony_ci               if (srccolors[j][i][3] <= alphatest[0] / 2) {
778bf215546Sopenharmony_ci               }
779bf215546Sopenharmony_ci               else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
780bf215546Sopenharmony_ci               }
781bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[0]) {
782bf215546Sopenharmony_ci                  blockerrlin1 += (srccolors[j][i][3] - alphatest[0]);
783bf215546Sopenharmony_ci                  nralphainrangelow += 1;
784bf215546Sopenharmony_ci               }
785bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[1]) {
786bf215546Sopenharmony_ci                  blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
787bf215546Sopenharmony_ci                  blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
788bf215546Sopenharmony_ci                  nralphainrangelow += 1;
789bf215546Sopenharmony_ci                  nralphainrangehigh += 1;
790bf215546Sopenharmony_ci               }
791bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[2]) {
792bf215546Sopenharmony_ci                  blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
793bf215546Sopenharmony_ci                  blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
794bf215546Sopenharmony_ci                  nralphainrangelow += 1;
795bf215546Sopenharmony_ci                  nralphainrangehigh += 1;
796bf215546Sopenharmony_ci               }
797bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[3]) {
798bf215546Sopenharmony_ci                  blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
799bf215546Sopenharmony_ci                  blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
800bf215546Sopenharmony_ci                  nralphainrangelow += 1;
801bf215546Sopenharmony_ci                  nralphainrangehigh += 1;
802bf215546Sopenharmony_ci               }
803bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[4]) {
804bf215546Sopenharmony_ci                  blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
805bf215546Sopenharmony_ci                  blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
806bf215546Sopenharmony_ci                  nralphainrangelow += 1;
807bf215546Sopenharmony_ci                  nralphainrangehigh += 1;
808bf215546Sopenharmony_ci                  }
809bf215546Sopenharmony_ci               else {
810bf215546Sopenharmony_ci                  blockerrlin2 += (srccolors[j][i][3] - alphatest[1]);
811bf215546Sopenharmony_ci                  nralphainrangehigh += 1;
812bf215546Sopenharmony_ci               }
813bf215546Sopenharmony_ci            }
814bf215546Sopenharmony_ci         }
815bf215546Sopenharmony_ci         /* shouldn't happen often, needed to avoid div by zero */
816bf215546Sopenharmony_ci         if (nralphainrangelow == 0) nralphainrangelow = 1;
817bf215546Sopenharmony_ci         if (nralphainrangehigh == 0) nralphainrangehigh = 1;
818bf215546Sopenharmony_ci         alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
819bf215546Sopenharmony_ci/*         fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
820bf215546Sopenharmony_ci         fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);*/
821bf215546Sopenharmony_ci         /* again shouldn't really happen often... */
822bf215546Sopenharmony_ci         if (alphatest[0] < 0) {
823bf215546Sopenharmony_ci            alphatest[0] = 0;
824bf215546Sopenharmony_ci/*            fprintf(stderr, "adj alpha base val to 0\n");*/
825bf215546Sopenharmony_ci         }
826bf215546Sopenharmony_ci         alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
827bf215546Sopenharmony_ci         if (alphatest[1] > 255) {
828bf215546Sopenharmony_ci            alphatest[1] = 255;
829bf215546Sopenharmony_ci/*            fprintf(stderr, "adj alpha base val to 255\n");*/
830bf215546Sopenharmony_ci         }
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci         alphablockerror3 = 0;
833bf215546Sopenharmony_ci         for (aindex = 0; aindex < 5; aindex++) {
834bf215546Sopenharmony_ci         /* don't forget here is always rounded down */
835bf215546Sopenharmony_ci            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
836bf215546Sopenharmony_ci         }
837bf215546Sopenharmony_ci         for (j = 0; j < numypixels; j++) {
838bf215546Sopenharmony_ci            for (i = 0; i < numxpixels; i++) {
839bf215546Sopenharmony_ci                /* maybe it's overkill to have the most complicated calculation just for the error
840bf215546Sopenharmony_ci                  calculation which we only need to figure out if encoding1 or encoding2 is better... */
841bf215546Sopenharmony_ci               if (srccolors[j][i][3] <= alphatest[0] / 2) {
842bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 6;
843bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3];
844bf215546Sopenharmony_ci               }
845bf215546Sopenharmony_ci               else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
846bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 7;
847bf215546Sopenharmony_ci                  alphadist = 255 - srccolors[j][i][3];
848bf215546Sopenharmony_ci               }
849bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[0]) {
850bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 0;
851bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3] - alphatest[0];
852bf215546Sopenharmony_ci               }
853bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[1]) {
854bf215546Sopenharmony_ci                 alphaenc3[4*j + i] = 2;
855bf215546Sopenharmony_ci                 alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
856bf215546Sopenharmony_ci               }
857bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[2]) {
858bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 3;
859bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
860bf215546Sopenharmony_ci               }
861bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[3]) {
862bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 4;
863bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
864bf215546Sopenharmony_ci               }
865bf215546Sopenharmony_ci               else if (srccolors[j][i][3] <= acutValues[4]) {
866bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 5;
867bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
868bf215546Sopenharmony_ci               }
869bf215546Sopenharmony_ci               else {
870bf215546Sopenharmony_ci                  alphaenc3[4*j + i] = 1;
871bf215546Sopenharmony_ci                  alphadist = srccolors[j][i][3] - alphatest[1];
872bf215546Sopenharmony_ci               }
873bf215546Sopenharmony_ci               alphablockerror3 += alphadist * alphadist;
874bf215546Sopenharmony_ci            }
875bf215546Sopenharmony_ci         }
876bf215546Sopenharmony_ci      }
877bf215546Sopenharmony_ci   }
878bf215546Sopenharmony_ci  /* write the alpha values and encoding back. */
879bf215546Sopenharmony_ci   if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
880bf215546Sopenharmony_ci/*      if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);*/
881bf215546Sopenharmony_ci      writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 );
882bf215546Sopenharmony_ci   }
883bf215546Sopenharmony_ci   else if (alphablockerror2 <= alphablockerror3) {
884bf215546Sopenharmony_ci/*      if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);*/
885bf215546Sopenharmony_ci      writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
886bf215546Sopenharmony_ci   }
887bf215546Sopenharmony_ci   else {
888bf215546Sopenharmony_ci/*      fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/
889bf215546Sopenharmony_ci      writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 );
890bf215546Sopenharmony_ci   }
891bf215546Sopenharmony_ci}
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_cistatic void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr,
894bf215546Sopenharmony_ci                         GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
895bf215546Sopenharmony_ci{
896bf215546Sopenharmony_ci   GLubyte i, j, c;
897bf215546Sopenharmony_ci   const GLchan *curaddr;
898bf215546Sopenharmony_ci   for (j = 0; j < numypixels; j++) {
899bf215546Sopenharmony_ci      curaddr = srcaddr + j * srcRowStride * comps;
900bf215546Sopenharmony_ci      for (i = 0; i < numxpixels; i++) {
901bf215546Sopenharmony_ci         for (c = 0; c < comps; c++) {
902bf215546Sopenharmony_ci            srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255);
903bf215546Sopenharmony_ci         }
904bf215546Sopenharmony_ci      }
905bf215546Sopenharmony_ci   }
906bf215546Sopenharmony_ci}
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci
909bf215546Sopenharmony_cistatic void
910bf215546Sopenharmony_citx_compress_dxt1(int srccomps, int width, int height,
911bf215546Sopenharmony_ci                 const GLubyte *srcPixData, GLubyte *dest, int dstRowStride,
912bf215546Sopenharmony_ci                 unsigned dstComps)
913bf215546Sopenharmony_ci{
914bf215546Sopenharmony_ci   GLenum destFormat = dstComps == 3 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT
915bf215546Sopenharmony_ci                                     : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
916bf215546Sopenharmony_ci   GLubyte *blkaddr = dest;
917bf215546Sopenharmony_ci   GLubyte srcpixels[4][4][4];
918bf215546Sopenharmony_ci   const GLchan *srcaddr = srcPixData;
919bf215546Sopenharmony_ci   int numxpixels, numypixels;
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci   /* hmm we used to get called without dstRowStride... */
922bf215546Sopenharmony_ci   int dstRowDiff = dstRowStride >= (width * 2) ?
923bf215546Sopenharmony_ci                    dstRowStride - (((width + 3) & ~3) * 2) : 0;
924bf215546Sopenharmony_ci   /* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
925bf215546Sopenharmony_ci              width, height, dstRowStride); */
926bf215546Sopenharmony_ci   for (int j = 0; j < height; j += 4) {
927bf215546Sopenharmony_ci      if (height > j + 3) numypixels = 4;
928bf215546Sopenharmony_ci      else numypixels = height - j;
929bf215546Sopenharmony_ci      srcaddr = srcPixData + j * width * srccomps;
930bf215546Sopenharmony_ci      for (int i = 0; i < width; i += 4) {
931bf215546Sopenharmony_ci         if (width > i + 3) numxpixels = 4;
932bf215546Sopenharmony_ci         else numxpixels = width - i;
933bf215546Sopenharmony_ci         extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
934bf215546Sopenharmony_ci         encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
935bf215546Sopenharmony_ci         srcaddr += srccomps * numxpixels;
936bf215546Sopenharmony_ci         blkaddr += 8;
937bf215546Sopenharmony_ci      }
938bf215546Sopenharmony_ci      blkaddr += dstRowDiff;
939bf215546Sopenharmony_ci   }
940bf215546Sopenharmony_ci}
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_cistatic void
943bf215546Sopenharmony_citx_compress_dxt3(int srccomps, int width, int height,
944bf215546Sopenharmony_ci                 const GLubyte *srcPixData, GLubyte *dest, int dstRowStride)
945bf215546Sopenharmony_ci{
946bf215546Sopenharmony_ci   GLenum destFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
947bf215546Sopenharmony_ci   GLubyte *blkaddr = dest;
948bf215546Sopenharmony_ci   GLubyte srcpixels[4][4][4];
949bf215546Sopenharmony_ci   const GLchan *srcaddr = srcPixData;
950bf215546Sopenharmony_ci   int numxpixels, numypixels;
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci   int dstRowDiff = dstRowStride >= (width * 4) ?
953bf215546Sopenharmony_ci                    dstRowStride - (((width + 3) & ~3) * 4) : 0;
954bf215546Sopenharmony_ci   /* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
955bf215546Sopenharmony_ci              width, height, dstRowStride); */
956bf215546Sopenharmony_ci   for (int j = 0; j < height; j += 4) {
957bf215546Sopenharmony_ci      if (height > j + 3) numypixels = 4;
958bf215546Sopenharmony_ci      else numypixels = height - j;
959bf215546Sopenharmony_ci      srcaddr = srcPixData + j * width * srccomps;
960bf215546Sopenharmony_ci      for (int i = 0; i < width; i += 4) {
961bf215546Sopenharmony_ci         if (width > i + 3) numxpixels = 4;
962bf215546Sopenharmony_ci         else numxpixels = width - i;
963bf215546Sopenharmony_ci         extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
964bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0);
965bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0);
966bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0);
967bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0);
968bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0);
969bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0);
970bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0);
971bf215546Sopenharmony_ci         *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0);
972bf215546Sopenharmony_ci         encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
973bf215546Sopenharmony_ci         srcaddr += srccomps * numxpixels;
974bf215546Sopenharmony_ci         blkaddr += 8;
975bf215546Sopenharmony_ci      }
976bf215546Sopenharmony_ci      blkaddr += dstRowDiff;
977bf215546Sopenharmony_ci   }
978bf215546Sopenharmony_ci}
979bf215546Sopenharmony_ci
980bf215546Sopenharmony_cistatic void
981bf215546Sopenharmony_citx_compress_dxt5(int srccomps, int width, int height,
982bf215546Sopenharmony_ci                 const GLubyte *srcPixData, GLubyte *dest, int dstRowStride)
983bf215546Sopenharmony_ci{
984bf215546Sopenharmony_ci   GLenum destFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
985bf215546Sopenharmony_ci   GLubyte *blkaddr = dest;
986bf215546Sopenharmony_ci   GLubyte srcpixels[4][4][4];
987bf215546Sopenharmony_ci   const GLchan *srcaddr = srcPixData;
988bf215546Sopenharmony_ci   int numxpixels, numypixels;
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci   int dstRowDiff = dstRowStride >= (width * 4) ?
991bf215546Sopenharmony_ci                    dstRowStride - (((width + 3) & ~3) * 4) : 0;
992bf215546Sopenharmony_ci   /* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
993bf215546Sopenharmony_ci              width, height, dstRowStride); */
994bf215546Sopenharmony_ci   for (int j = 0; j < height; j += 4) {
995bf215546Sopenharmony_ci      if (height > j + 3) numypixels = 4;
996bf215546Sopenharmony_ci      else numypixels = height - j;
997bf215546Sopenharmony_ci      srcaddr = srcPixData + j * width * srccomps;
998bf215546Sopenharmony_ci      for (int i = 0; i < width; i += 4) {
999bf215546Sopenharmony_ci         if (width > i + 3) numxpixels = 4;
1000bf215546Sopenharmony_ci         else numxpixels = width - i;
1001bf215546Sopenharmony_ci         extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
1002bf215546Sopenharmony_ci         encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels);
1003bf215546Sopenharmony_ci         encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat);
1004bf215546Sopenharmony_ci         srcaddr += srccomps * numxpixels;
1005bf215546Sopenharmony_ci         blkaddr += 16;
1006bf215546Sopenharmony_ci      }
1007bf215546Sopenharmony_ci      blkaddr += dstRowDiff;
1008bf215546Sopenharmony_ci   }
1009bf215546Sopenharmony_ci}
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_cistatic void
1012bf215546Sopenharmony_citx_compress_dxtn(GLint srccomps, GLint width, GLint height,
1013bf215546Sopenharmony_ci                 const GLubyte *srcPixData, GLenum destFormat,
1014bf215546Sopenharmony_ci                 GLubyte *dest, GLint dstRowStride)
1015bf215546Sopenharmony_ci{
1016bf215546Sopenharmony_ci   switch (destFormat) {
1017bf215546Sopenharmony_ci   case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1018bf215546Sopenharmony_ci      tx_compress_dxt1(srccomps, width, height, srcPixData,
1019bf215546Sopenharmony_ci                       dest, dstRowStride, 3);
1020bf215546Sopenharmony_ci      break;
1021bf215546Sopenharmony_ci   case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1022bf215546Sopenharmony_ci      tx_compress_dxt1(srccomps, width, height, srcPixData,
1023bf215546Sopenharmony_ci                       dest, dstRowStride, 4);
1024bf215546Sopenharmony_ci      break;
1025bf215546Sopenharmony_ci   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1026bf215546Sopenharmony_ci      tx_compress_dxt3(srccomps, width, height, srcPixData,
1027bf215546Sopenharmony_ci                       dest, dstRowStride);
1028bf215546Sopenharmony_ci      break;
1029bf215546Sopenharmony_ci   case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1030bf215546Sopenharmony_ci      tx_compress_dxt5(srccomps, width, height, srcPixData,
1031bf215546Sopenharmony_ci                       dest, dstRowStride);
1032bf215546Sopenharmony_ci      break;
1033bf215546Sopenharmony_ci   default:
1034bf215546Sopenharmony_ci      unreachable("unknown DXTn format");
1035bf215546Sopenharmony_ci   }
1036bf215546Sopenharmony_ci}
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci#endif
1039