rgtc: fix issues with compressor and signed types.
[mesa.git] / src / mesa / main / texcompress_rgtc_tmp.h
1 /*
2 * Copyright (C) 2011 Red Hat Inc.
3 *
4 * block compression parts are:
5 * Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Author:
27 * Dave Airlie
28 */
29
30 /* included by texcompress_rgtc to define byte/ubyte compressors */
31
32 static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
33 TYPE alphabase1,
34 TYPE alphabase2,
35 TYPE alphaenc[16])
36 {
37 *blkaddr++ = alphabase1;
38 *blkaddr++ = alphabase2;
39 *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
40 *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
41 *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
42 *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
43 *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
44 *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
45 }
46 static void TAG(encode_rgtc_chan)(TYPE *blkaddr, TYPE srccolors[4][4],
47 GLint numxpixels, GLint numypixels)
48 {
49 TYPE alphabase[2], alphause[2];
50 GLshort alphatest[2] = { 0 };
51 GLuint alphablockerror1, alphablockerror2, alphablockerror3;
52 TYPE i, j, aindex, acutValues[7];
53 TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
54 GLboolean alphaabsmin = GL_FALSE;
55 GLboolean alphaabsmax = GL_FALSE;
56 GLshort alphadist;
57
58 /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
59 alphabase[0] = T_MAX; alphabase[1] = T_MIN;
60 for (j = 0; j < numypixels; j++) {
61 for (i = 0; i < numxpixels; i++) {
62 if (srccolors[j][i] == T_MIN)
63 alphaabsmin = GL_TRUE;
64 else if (srccolors[j][i] == T_MAX)
65 alphaabsmax = GL_TRUE;
66 else {
67 if (srccolors[j][i] > alphabase[1])
68 alphabase[1] = srccolors[j][i];
69 if (srccolors[j][i] < alphabase[0])
70 alphabase[0] = srccolors[j][i];
71 }
72 }
73 }
74
75
76 if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
77 || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */
78 /* shortcut here since it is a very common case (and also avoids later problems) */
79 /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
80
81 *blkaddr++ = srccolors[0][0];
82 blkaddr++;
83 *blkaddr++ = 0;
84 *blkaddr++ = 0;
85 *blkaddr++ = 0;
86 *blkaddr++ = 0;
87 *blkaddr++ = 0;
88 *blkaddr++ = 0;
89 #if RGTC_DEBUG
90 fprintf(stderr, "enc0 used\n");
91 #endif
92 return;
93 }
94
95 /* find best encoding for alpha0 > alpha1 */
96 /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
97 alphablockerror1 = 0x0;
98 alphablockerror2 = 0xffffffff;
99 alphablockerror3 = 0xffffffff;
100 if (alphaabsmin) alphause[0] = T_MIN;
101 else alphause[0] = alphabase[0];
102 if (alphaabsmax) alphause[1] = T_MAX;
103 else alphause[1] = alphabase[1];
104 /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
105 for (aindex = 0; aindex < 7; aindex++) {
106 /* don't forget here is always rounded down */
107 acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
108 }
109
110 for (j = 0; j < numypixels; j++) {
111 for (i = 0; i < numxpixels; i++) {
112 /* maybe it's overkill to have the most complicated calculation just for the error
113 calculation which we only need to figure out if encoding1 or encoding2 is better... */
114 if (srccolors[j][i] > acutValues[0]) {
115 alphaenc1[4*j + i] = 0;
116 alphadist = srccolors[j][i] - alphause[1];
117 }
118 else if (srccolors[j][i] > acutValues[1]) {
119 alphaenc1[4*j + i] = 2;
120 alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
121 }
122 else if (srccolors[j][i] > acutValues[2]) {
123 alphaenc1[4*j + i] = 3;
124 alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
125 }
126 else if (srccolors[j][i] > acutValues[3]) {
127 alphaenc1[4*j + i] = 4;
128 alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
129 }
130 else if (srccolors[j][i] > acutValues[4]) {
131 alphaenc1[4*j + i] = 5;
132 alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
133 }
134 else if (srccolors[j][i] > acutValues[5]) {
135 alphaenc1[4*j + i] = 6;
136 alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
137 }
138 else if (srccolors[j][i] > acutValues[6]) {
139 alphaenc1[4*j + i] = 7;
140 alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
141 }
142 else {
143 alphaenc1[4*j + i] = 1;
144 alphadist = srccolors[j][i] - alphause[0];
145 }
146 alphablockerror1 += alphadist * alphadist;
147 }
148 }
149
150 #if RGTC_DEBUG
151 for (i = 0; i < 16; i++) {
152 fprintf(stderr, "%d ", alphaenc1[i]);
153 }
154 fprintf(stderr, "cutVals ");
155 for (i = 0; i < 8; i++) {
156 fprintf(stderr, "%d ", acutValues[i]);
157 }
158 fprintf(stderr, "srcVals ");
159 for (j = 0; j < numypixels; j++) {
160 for (i = 0; i < numxpixels; i++) {
161 fprintf(stderr, "%d ", srccolors[j][i]);
162 }
163 }
164 fprintf(stderr, "\n");
165 #endif
166
167 /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
168 are false but try it anyway */
169 if (alphablockerror1 >= 32) {
170
171 /* don't bother if encoding is already very good, this condition should also imply
172 we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
173 alphablockerror2 = 0;
174 for (aindex = 0; aindex < 5; aindex++) {
175 /* don't forget here is always rounded down */
176 acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
177 }
178 for (j = 0; j < numypixels; j++) {
179 for (i = 0; i < numxpixels; i++) {
180 /* maybe it's overkill to have the most complicated calculation just for the error
181 calculation which we only need to figure out if encoding1 or encoding2 is better... */
182 if (srccolors[j][i] == T_MIN) {
183 alphaenc2[4*j + i] = 6;
184 alphadist = 0;
185 }
186 else if (srccolors[j][i] == T_MAX) {
187 alphaenc2[4*j + i] = 7;
188 alphadist = 0;
189 }
190 else if (srccolors[j][i] <= acutValues[0]) {
191 alphaenc2[4*j + i] = 0;
192 alphadist = srccolors[j][i] - alphabase[0];
193 }
194 else if (srccolors[j][i] <= acutValues[1]) {
195 alphaenc2[4*j + i] = 2;
196 alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
197 }
198 else if (srccolors[j][i] <= acutValues[2]) {
199 alphaenc2[4*j + i] = 3;
200 alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
201 }
202 else if (srccolors[j][i] <= acutValues[3]) {
203 alphaenc2[4*j + i] = 4;
204 alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
205 }
206 else if (srccolors[j][i] <= acutValues[4]) {
207 alphaenc2[4*j + i] = 5;
208 alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
209 }
210 else {
211 alphaenc2[4*j + i] = 1;
212 alphadist = srccolors[j][i] - alphabase[1];
213 }
214 alphablockerror2 += alphadist * alphadist;
215 }
216 }
217
218
219 /* skip this if the error is already very small
220 this encoding is MUCH better on average than #2 though, but expensive! */
221 if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
222 GLshort blockerrlin1 = 0;
223 GLshort blockerrlin2 = 0;
224 TYPE nralphainrangelow = 0;
225 TYPE nralphainrangehigh = 0;
226 alphatest[0] = T_MAX;
227 alphatest[1] = T_MIN;
228 /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
229 for (j = 0; j < numypixels; j++) {
230 for (i = 0; i < numxpixels; i++) {
231 if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
232 alphatest[1] = srccolors[j][i];
233 if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
234 alphatest[0] = srccolors[j][i];
235 }
236 }
237 /* shouldn't happen too often, don't really care about those degenerated cases */
238 if (alphatest[1] <= alphatest[0]) {
239 alphatest[0] = T_MIN+1;
240 alphatest[1] = T_MAX-1;
241 }
242 for (aindex = 0; aindex < 5; aindex++) {
243 /* don't forget here is always rounded down */
244 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
245 }
246
247 /* find the "average" difference between the alpha values and the next encoded value.
248 This is then used to calculate new base values.
249 Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
250 since they will see more improvement, and also because the values in the middle are somewhat
251 likely to get no improvement at all (because the base values might move in different directions)?
252 OTOH it would mean the values in the middle are even less likely to get an improvement
253 */
254 for (j = 0; j < numypixels; j++) {
255 for (i = 0; i < numxpixels; i++) {
256 if (srccolors[j][i] <= alphatest[0] / 2) {
257 }
258 else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
259 }
260 else if (srccolors[j][i] <= acutValues[0]) {
261 blockerrlin1 += (srccolors[j][i] - alphatest[0]);
262 nralphainrangelow += 1;
263 }
264 else if (srccolors[j][i] <= acutValues[1]) {
265 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
266 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
267 nralphainrangelow += 1;
268 nralphainrangehigh += 1;
269 }
270 else if (srccolors[j][i] <= acutValues[2]) {
271 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
272 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
273 nralphainrangelow += 1;
274 nralphainrangehigh += 1;
275 }
276 else if (srccolors[j][i] <= acutValues[3]) {
277 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
278 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
279 nralphainrangelow += 1;
280 nralphainrangehigh += 1;
281 }
282 else if (srccolors[j][i] <= acutValues[4]) {
283 blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
284 blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
285 nralphainrangelow += 1;
286 nralphainrangehigh += 1;
287 }
288 else {
289 blockerrlin2 += (srccolors[j][i] - alphatest[1]);
290 nralphainrangehigh += 1;
291 }
292 }
293 }
294 /* shouldn't happen often, needed to avoid div by zero */
295 if (nralphainrangelow == 0) nralphainrangelow = 1;
296 if (nralphainrangehigh == 0) nralphainrangehigh = 1;
297 alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
298 #if RGTC_DEBUG
299 fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
300 fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
301 #endif
302 /* again shouldn't really happen often... */
303 if (alphatest[0] < T_MIN) {
304 alphatest[0] = T_MIN;
305 }
306 alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
307 if (alphatest[1] > T_MAX) {
308 alphatest[1] = T_MAX;
309 }
310
311 alphablockerror3 = 0;
312 for (aindex = 0; aindex < 5; aindex++) {
313 /* don't forget here is always rounded down */
314 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
315 }
316 for (j = 0; j < numypixels; j++) {
317 for (i = 0; i < numxpixels; i++) {
318 /* maybe it's overkill to have the most complicated calculation just for the error
319 calculation which we only need to figure out if encoding1 or encoding2 is better... */
320 if (srccolors[j][i] <= alphatest[0] / 2) {
321 alphaenc3[4*j + i] = 6;
322 alphadist = srccolors[j][i];
323 }
324 else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
325 alphaenc3[4*j + i] = 7;
326 alphadist = T_MAX - srccolors[j][i];
327 }
328 else if (srccolors[j][i] <= acutValues[0]) {
329 alphaenc3[4*j + i] = 0;
330 alphadist = srccolors[j][i] - alphatest[0];
331 }
332 else if (srccolors[j][i] <= acutValues[1]) {
333 alphaenc3[4*j + i] = 2;
334 alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
335 }
336 else if (srccolors[j][i] <= acutValues[2]) {
337 alphaenc3[4*j + i] = 3;
338 alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
339 }
340 else if (srccolors[j][i] <= acutValues[3]) {
341 alphaenc3[4*j + i] = 4;
342 alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
343 }
344 else if (srccolors[j][i] <= acutValues[4]) {
345 alphaenc3[4*j + i] = 5;
346 alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
347 }
348 else {
349 alphaenc3[4*j + i] = 1;
350 alphadist = srccolors[j][i] - alphatest[1];
351 }
352 alphablockerror3 += alphadist * alphadist;
353 }
354 }
355 }
356 }
357
358 /* write the alpha values and encoding back. */
359 if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
360 #if RGTC_DEBUG
361 if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
362 fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n",
363 T_MIN, T_MAX,
364 alphause[1], alphause[0]);
365 #endif
366
367 TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
368 }
369 else if (alphablockerror2 <= alphablockerror3) {
370 #if RGTC_DEBUG
371 if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
372 fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n",
373 T_MIN, T_MAX,
374 alphabase[0], alphabase[1]);
375 #endif
376
377 TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
378 }
379 else {
380 #if RGTC_DEBUG
381 fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
382 fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n",
383 T_MIN, T_MAX,
384 alphatest[0], alphatest[1]);
385 #endif
386
387 TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
388 }
389 }