[REACTOS]
[reactos.git] / reactos / dll / 3rdparty / dxtn / dxtn.c
1 /*
2 * DXTn codec
3 * Version: 1.1
4 *
5 * Copyright (C) 2004 Daniel Borca All Rights Reserved.
6 *
7 * this is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * this is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Make; see the file COPYING. If not, write to
19 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "types.h"
27 #include "internal.h"
28 #include "dxtn.h"
29
30
31 /***************************************************************************\
32 * DXTn encoder
33 *
34 * The encoder was built by reversing the decoder,
35 * and is vaguely based on FXT1 codec. Note that this code
36 * is merely a proof of concept, since it is highly UNoptimized!
37 \***************************************************************************/
38
39
40 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
41 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
42 #define N_TEXELS 16 /* number of texels in a block (always 16) */
43 #define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3))
44
45
46 static const int dxtn_color_tlat[2][4] = {
47 { 0, 2, 3, 1 },
48 { 0, 2, 1, 3 }
49 };
50
51 static const int dxtn_alpha_tlat[2][8] = {
52 { 0, 2, 3, 4, 5, 6, 7, 1 },
53 { 0, 2, 3, 4, 5, 1, 6, 7 }
54 };
55
56
57 static void
58 dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps)
59 {
60 float b, iv[MAX_COMP]; /* interpolation vector */
61
62 dword hi; /* high doubleword */
63 int color0, color1;
64 int n_vect;
65 const int n_comp = 3;
66 int black = 0;
67
68 int minSum = 2000; /* big enough */
69 int maxSum = -1; /* small enough */
70 int minCol = 0; /* phoudoin: silent compiler! */
71 int maxCol = 0; /* phoudoin: silent compiler! */
72
73 byte input[N_TEXELS][MAX_COMP];
74 int i, k, l;
75
76 /* make the whole block opaque */
77 /* we will NEVER reference ACOMP of any pixel */
78
79 /* 4 texels each line */
80 for (l = 0; l < 4; l++) {
81 for (k = 0; k < 4; k++) {
82 for (i = 0; i < comps; i++) {
83 input[k + l * 4][i] = *lines[l]++;
84 }
85 }
86 }
87
88 /* Our solution here is to find the darkest and brightest colors in
89 * the 4x4 tile and use those as the two representative colors.
90 * There are probably better algorithms to use (histogram-based).
91 */
92 for (k = 0; k < N_TEXELS; k++) {
93 int sum = 0;
94 for (i = 0; i < n_comp; i++) {
95 sum += input[k][i];
96 }
97 if (minSum > sum) {
98 minSum = sum;
99 minCol = k;
100 }
101 if (maxSum < sum) {
102 maxSum = sum;
103 maxCol = k;
104 }
105 if (sum == 0) {
106 black = 1;
107 }
108 }
109
110 color0 = COLOR565(input[minCol]);
111 color1 = COLOR565(input[maxCol]);
112
113 if (color0 == color1) {
114 /* we'll use 3-vector */
115 cc[0] = color0 | (color1 << 16);
116 hi = black ? -1 : 0;
117 } else {
118 if (black && ((color0 == 0) || (color1 == 0))) {
119 /* we still can use 4-vector */
120 black = 0;
121 }
122
123 if (black ^ (color0 <= color1)) {
124 int aux;
125 aux = color0;
126 color0 = color1;
127 color1 = aux;
128 aux = minCol;
129 minCol = maxCol;
130 maxCol = aux;
131 }
132 n_vect = (color0 <= color1) ? 2 : 3;
133
134 MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
135
136 /* add in texels */
137 cc[0] = color0 | (color1 << 16);
138 hi = 0;
139 for (k = N_TEXELS - 1; k >= 0; k--) {
140 int texel = 3;
141 int sum = 0;
142 if (black) {
143 for (i = 0; i < n_comp; i++) {
144 sum += input[k][i];
145 }
146 }
147 if (!black || sum) {
148 /* interpolate color */
149 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
150 texel = dxtn_color_tlat[black][texel];
151 }
152 /* add in texel */
153 hi <<= 2;
154 hi |= texel;
155 }
156 }
157 cc[1] = hi;
158 }
159
160
161 static void
162 dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps)
163 {
164 float b, iv[MAX_COMP]; /* interpolation vector */
165
166 dword hi; /* high doubleword */
167 int color0, color1;
168 int n_vect;
169 const int n_comp = 3;
170 int transparent = 0;
171
172 int minSum = 2000; /* big enough */
173 int maxSum = -1; /* small enough */
174 int minCol = 0; /* phoudoin: silent compiler! */
175 int maxCol = 0; /* phoudoin: silent compiler! */
176
177 byte input[N_TEXELS][MAX_COMP];
178 int i, k, l;
179
180 if (comps == 3) {
181 /* make the whole block opaque */
182 memset(input, -1, sizeof(input));
183 }
184
185 /* 4 texels each line */
186 for (l = 0; l < 4; l++) {
187 for (k = 0; k < 4; k++) {
188 for (i = 0; i < comps; i++) {
189 input[k + l * 4][i] = *lines[l]++;
190 }
191 }
192 }
193
194 /* Our solution here is to find the darkest and brightest colors in
195 * the 4x4 tile and use those as the two representative colors.
196 * There are probably better algorithms to use (histogram-based).
197 */
198 for (k = 0; k < N_TEXELS; k++) {
199 int sum = 0;
200 for (i = 0; i < n_comp; i++) {
201 sum += input[k][i];
202 }
203 if (minSum > sum) {
204 minSum = sum;
205 minCol = k;
206 }
207 if (maxSum < sum) {
208 maxSum = sum;
209 maxCol = k;
210 }
211 if (input[k][ACOMP] < 128) {
212 transparent = 1;
213 }
214 }
215
216 color0 = COLOR565(input[minCol]);
217 color1 = COLOR565(input[maxCol]);
218
219 if (color0 == color1) {
220 /* we'll use 3-vector */
221 cc[0] = color0 | (color1 << 16);
222 hi = transparent ? -1 : 0;
223 } else {
224 if (transparent ^ (color0 <= color1)) {
225 int aux;
226 aux = color0;
227 color0 = color1;
228 color1 = aux;
229 aux = minCol;
230 minCol = maxCol;
231 maxCol = aux;
232 }
233 n_vect = (color0 <= color1) ? 2 : 3;
234
235 MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
236
237 /* add in texels */
238 cc[0] = color0 | (color1 << 16);
239 hi = 0;
240 for (k = N_TEXELS - 1; k >= 0; k--) {
241 int texel = 3;
242 if (input[k][ACOMP] >= 128) {
243 /* interpolate color */
244 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
245 texel = dxtn_color_tlat[transparent][texel];
246 }
247 /* add in texel */
248 hi <<= 2;
249 hi |= texel;
250 }
251 }
252 cc[1] = hi;
253 }
254
255
256 static void
257 dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps)
258 {
259 float b, iv[MAX_COMP]; /* interpolation vector */
260
261 dword lolo, lohi; /* low quadword: lo dword, hi dword */
262 dword hihi; /* high quadword: high dword */
263 int color0, color1;
264 const int n_vect = 3;
265 const int n_comp = 3;
266
267 int minSum = 2000; /* big enough */
268 int maxSum = -1; /* small enough */
269 int minCol = 0; /* phoudoin: silent compiler! */
270 int maxCol = 0; /* phoudoin: silent compiler! */
271
272 byte input[N_TEXELS][MAX_COMP];
273 int i, k, l;
274
275 if (comps == 3) {
276 /* make the whole block opaque */
277 memset(input, -1, sizeof(input));
278 }
279
280 /* 4 texels each line */
281 for (l = 0; l < 4; l++) {
282 for (k = 0; k < 4; k++) {
283 for (i = 0; i < comps; i++) {
284 input[k + l * 4][i] = *lines[l]++;
285 }
286 }
287 }
288
289 /* Our solution here is to find the darkest and brightest colors in
290 * the 4x4 tile and use those as the two representative colors.
291 * There are probably better algorithms to use (histogram-based).
292 */
293 for (k = 0; k < N_TEXELS; k++) {
294 int sum = 0;
295 for (i = 0; i < n_comp; i++) {
296 sum += input[k][i];
297 }
298 if (minSum > sum) {
299 minSum = sum;
300 minCol = k;
301 }
302 if (maxSum < sum) {
303 maxSum = sum;
304 maxCol = k;
305 }
306 }
307
308 /* add in alphas */
309 lolo = lohi = 0;
310 for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
311 /* add in alpha */
312 lohi <<= 4;
313 lohi |= input[k][ACOMP] >> 4;
314 }
315 cc[1] = lohi;
316 for (; k >= 0; k--) {
317 /* add in alpha */
318 lolo <<= 4;
319 lolo |= input[k][ACOMP] >> 4;
320 }
321 cc[0] = lolo;
322
323 color0 = COLOR565(input[minCol]);
324 color1 = COLOR565(input[maxCol]);
325 cc[2] = color0 | (color1 << 16);
326
327 hihi = 0;
328 if (color0 != color1) {
329 MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
330
331 /* add in texels */
332 for (k = N_TEXELS - 1; k >= 0; k--) {
333 int texel;
334 /* interpolate color */
335 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
336 texel = dxtn_color_tlat[0][texel];
337 /* add in texel */
338 hihi <<= 2;
339 hihi |= texel;
340 }
341 }
342 cc[3] = hihi;
343 }
344
345
346 static void
347 dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps)
348 {
349 float b, iv[MAX_COMP]; /* interpolation vector */
350
351 qword lo; /* low quadword */
352 dword hihi; /* high quadword: high dword */
353 int color0, color1;
354 const int n_vect = 3;
355 const int n_comp = 3;
356
357 int minSum = 2000; /* big enough */
358 int maxSum = -1; /* small enough */
359 int minCol = 0; /* phoudoin: silent compiler! */
360 int maxCol = 0; /* phoudoin: silent compiler! */
361 int alpha0 = 2000; /* big enough */
362 int alpha1 = -1; /* small enough */
363 int anyZero = 0, anyOne = 0;
364 int a_vect;
365
366 byte input[N_TEXELS][MAX_COMP];
367 int i, k, l;
368
369 if (comps == 3) {
370 /* make the whole block opaque */
371 memset(input, -1, sizeof(input));
372 }
373
374 /* 4 texels each line */
375 for (l = 0; l < 4; l++) {
376 for (k = 0; k < 4; k++) {
377 for (i = 0; i < comps; i++) {
378 input[k + l * 4][i] = *lines[l]++;
379 }
380 }
381 }
382
383 /* Our solution here is to find the darkest and brightest colors in
384 * the 4x4 tile and use those as the two representative colors.
385 * There are probably better algorithms to use (histogram-based).
386 */
387 for (k = 0; k < N_TEXELS; k++) {
388 int sum = 0;
389 for (i = 0; i < n_comp; i++) {
390 sum += input[k][i];
391 }
392 if (minSum > sum) {
393 minSum = sum;
394 minCol = k;
395 }
396 if (maxSum < sum) {
397 maxSum = sum;
398 maxCol = k;
399 }
400 if (alpha0 > input[k][ACOMP]) {
401 alpha0 = input[k][ACOMP];
402 }
403 if (alpha1 < input[k][ACOMP]) {
404 alpha1 = input[k][ACOMP];
405 }
406 if (input[k][ACOMP] == 0) {
407 anyZero = 1;
408 }
409 if (input[k][ACOMP] == 255) {
410 anyOne = 1;
411 }
412 }
413
414 /* add in alphas */
415 if (alpha0 == alpha1) {
416 /* we'll use 6-vector */
417 cc[0] = alpha0 | (alpha1 << 8);
418 cc[1] = 0;
419 } else {
420 if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) {
421 /* we still might use 8-vector */
422 anyZero = 0;
423 }
424 if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) {
425 /* we still might use 8-vector */
426 anyOne = 0;
427 }
428 if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) {
429 int aux;
430 aux = alpha0;
431 alpha0 = alpha1;
432 alpha1 = aux;
433 }
434 a_vect = (alpha0 <= alpha1) ? 5 : 7;
435
436 /* compute interpolation vector */
437 iv[ACOMP] = (float)a_vect / (alpha1 - alpha0);
438 b = -iv[ACOMP] * alpha0 + 0.5F;
439
440 /* add in alphas */
441 Q_MOV32(lo, 0);
442 for (k = N_TEXELS - 1; k >= 0; k--) {
443 int texel = -1;
444 if (anyZero | anyOne) {
445 if (input[k][ACOMP] == 0) {
446 texel = 6;
447 } else if (input[k][ACOMP] == 255) {
448 texel = 7;
449 }
450 }
451 /* interpolate alpha */
452 if (texel == -1) {
453 float dot = input[k][ACOMP] * iv[ACOMP];
454 texel = (int)(dot + b);
455 #if SAFECDOT
456 if (texel < 0) {
457 texel = 0;
458 } else if (texel > a_vect) {
459 texel = a_vect;
460 }
461 #endif
462 texel = dxtn_alpha_tlat[anyZero | anyOne][texel];
463 }
464 /* add in texel */
465 Q_SHL(lo, 3);
466 Q_OR32(lo, texel);
467 }
468 Q_SHL(lo, 16);
469 Q_OR32(lo, alpha0 | (alpha1 << 8));
470 ((qword *)cc)[0] = lo;
471 }
472
473 color0 = COLOR565(input[minCol]);
474 color1 = COLOR565(input[maxCol]);
475 cc[2] = color0 | (color1 << 16);
476
477 hihi = 0;
478 if (color0 != color1) {
479 MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
480
481 /* add in texels */
482 for (k = N_TEXELS - 1; k >= 0; k--) {
483 int texel;
484 /* interpolate color */
485 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
486 texel = dxtn_color_tlat[0][texel];
487 /* add in texel */
488 hihi <<= 2;
489 hihi |= texel;
490 }
491 }
492 cc[3] = hihi;
493 }
494
495
496 #define ENCODER(dxtn, n) \
497 int TAPIENTRY \
498 dxtn##_encode (int width, int height, int comps, \
499 const void *source, int srcRowStride, \
500 void *dest, int destRowStride) \
501 { \
502 int x, y; \
503 const byte *data; \
504 dword *encoded = (dword *)dest; \
505 void *newSource = NULL; \
506 \
507 /* Replicate image if width is not M4 or height is not M4 */ \
508 if ((width & 3) | (height & 3)) { \
509 int newWidth = (width + 3) & ~3; \
510 int newHeight = (height + 3) & ~3; \
511 newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\
512 _mesa_upscale_teximage2d(width, height, newWidth, newHeight, \
513 comps, (const byte *)source, \
514 srcRowStride, (byte *)newSource); \
515 source = newSource; \
516 width = newWidth; \
517 height = newHeight; \
518 srcRowStride = comps * newWidth; \
519 } \
520 \
521 data = (const byte *)source; \
522 destRowStride = (destRowStride - width * n) / 4; \
523 for (y = 0; y < height; y += 4) { \
524 unsigned int offs = 0 + (y + 0) * srcRowStride; \
525 for (x = 0; x < width; x += 4) { \
526 const byte *lines[4]; \
527 lines[0] = &data[offs]; \
528 lines[1] = lines[0] + srcRowStride; \
529 lines[2] = lines[1] + srcRowStride; \
530 lines[3] = lines[2] + srcRowStride; \
531 offs += 4 * comps; \
532 dxtn##_quantize(encoded, lines, comps); \
533 /* 4x4 block */ \
534 encoded += n; \
535 } \
536 encoded += destRowStride; \
537 } \
538 \
539 if (newSource != NULL) { \
540 free(newSource); \
541 } \
542 \
543 return 0; \
544 }
545
546 ENCODER(dxt1_rgb, 2)
547 ENCODER(dxt1_rgba, 2)
548 ENCODER(dxt3_rgba, 4)
549 ENCODER(dxt5_rgba, 4)
550
551
552 /***************************************************************************\
553 * DXTn decoder
554 *
555 * The decoder is based on GL_EXT_texture_compression_s3tc
556 * specification and serves as a concept for the encoder.
557 \***************************************************************************/
558
559
560 /* lookup table for scaling 4 bit colors up to 8 bits */
561 static const byte _rgb_scale_4[] = {
562 0, 17, 34, 51, 68, 85, 102, 119,
563 136, 153, 170, 187, 204, 221, 238, 255
564 };
565
566 /* lookup table for scaling 5 bit colors up to 8 bits */
567 static const byte _rgb_scale_5[] = {
568 0, 8, 16, 25, 33, 41, 49, 58,
569 66, 74, 82, 90, 99, 107, 115, 123,
570 132, 140, 148, 156, 165, 173, 181, 189,
571 197, 206, 214, 222, 230, 239, 247, 255
572 };
573
574 /* lookup table for scaling 6 bit colors up to 8 bits */
575 static const byte _rgb_scale_6[] = {
576 0, 4, 8, 12, 16, 20, 24, 28,
577 32, 36, 40, 45, 49, 53, 57, 61,
578 65, 69, 73, 77, 81, 85, 89, 93,
579 97, 101, 105, 109, 113, 117, 121, 125,
580 130, 134, 138, 142, 146, 150, 154, 158,
581 162, 166, 170, 174, 178, 182, 186, 190,
582 194, 198, 202, 206, 210, 215, 219, 223,
583 227, 231, 235, 239, 243, 247, 251, 255
584 };
585
586
587 #define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
588 #define UP4(c) _rgb_scale_4[(c) & 15]
589 #define UP5(c) _rgb_scale_5[(c) & 31]
590 #define UP6(c) _rgb_scale_6[(c) & 63]
591 #define ZERO_4UBV(v) *((dword *)(v)) = 0
592
593
594 void TAPIENTRY
595 dxt1_rgb_decode_1 (const void *texture, int stride,
596 int i, int j, byte *rgba)
597 {
598 const byte *src = (const byte *)texture
599 + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
600 const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
601 if (code == 0) {
602 rgba[RCOMP] = UP5(CC_SEL(src, 11));
603 rgba[GCOMP] = UP6(CC_SEL(src, 5));
604 rgba[BCOMP] = UP5(CC_SEL(src, 0));
605 } else if (code == 1) {
606 rgba[RCOMP] = UP5(CC_SEL(src, 27));
607 rgba[GCOMP] = UP6(CC_SEL(src, 21));
608 rgba[BCOMP] = UP5(CC_SEL(src, 16));
609 } else {
610 const word col0 = src[0] | (src[1] << 8);
611 const word col1 = src[2] | (src[3] << 8);
612 if (col0 > col1) {
613 if (code == 2) {
614 rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
615 rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
616 rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
617 } else {
618 rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
619 rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
620 rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
621 }
622 } else {
623 if (code == 2) {
624 rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
625 rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
626 rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
627 } else {
628 ZERO_4UBV(rgba);
629 }
630 }
631 }
632 rgba[ACOMP] = 255;
633 }
634
635
636 void TAPIENTRY
637 dxt1_rgba_decode_1 (const void *texture, int stride,
638 int i, int j, byte *rgba)
639 {
640 /* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */
641 const byte *src = (const byte *)texture
642 + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
643 const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
644 if (code == 0) {
645 rgba[RCOMP] = UP5(CC_SEL(src, 11));
646 rgba[GCOMP] = UP6(CC_SEL(src, 5));
647 rgba[BCOMP] = UP5(CC_SEL(src, 0));
648 rgba[ACOMP] = 255;
649 } else if (code == 1) {
650 rgba[RCOMP] = UP5(CC_SEL(src, 27));
651 rgba[GCOMP] = UP6(CC_SEL(src, 21));
652 rgba[BCOMP] = UP5(CC_SEL(src, 16));
653 rgba[ACOMP] = 255;
654 } else {
655 const word col0 = src[0] | (src[1] << 8);
656 const word col1 = src[2] | (src[3] << 8);
657 if (col0 > col1) {
658 if (code == 2) {
659 rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
660 rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
661 rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
662 } else {
663 rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
664 rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
665 rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
666 }
667 rgba[ACOMP] = 255;
668 } else {
669 if (code == 2) {
670 rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
671 rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
672 rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
673 rgba[ACOMP] = 255;
674 } else {
675 ZERO_4UBV(rgba);
676 }
677 }
678 }
679 }
680
681
682 void TAPIENTRY
683 dxt3_rgba_decode_1 (const void *texture, int stride,
684 int i, int j, byte *rgba)
685 {
686 const byte *src = (const byte *)texture
687 + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
688 const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
689 const dword *cc = (const dword *)(src + 8);
690 if (code == 0) {
691 rgba[RCOMP] = UP5(CC_SEL(cc, 11));
692 rgba[GCOMP] = UP6(CC_SEL(cc, 5));
693 rgba[BCOMP] = UP5(CC_SEL(cc, 0));
694 } else if (code == 1) {
695 rgba[RCOMP] = UP5(CC_SEL(cc, 27));
696 rgba[GCOMP] = UP6(CC_SEL(cc, 21));
697 rgba[BCOMP] = UP5(CC_SEL(cc, 16));
698 } else if (code == 2) {
699 /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
700 rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
701 rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
702 rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
703 } else {
704 rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
705 rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
706 rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
707 }
708 rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4));
709 }
710
711
712 void TAPIENTRY
713 dxt5_rgba_decode_1 (const void *texture, int stride,
714 int i, int j, byte *rgba)
715 {
716 const byte *src = (const byte *)texture
717 + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
718 const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
719 const dword *cc = (const dword *)(src + 8);
720 const byte alpha0 = src[0];
721 const byte alpha1 = src[1];
722 const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16;
723 const int acode = ((alphaShift == 31)
724 ? CC_SEL(src + 2, alphaShift - 16)
725 : CC_SEL(src, alphaShift)) & 0x7;
726 if (code == 0) {
727 rgba[RCOMP] = UP5(CC_SEL(cc, 11));
728 rgba[GCOMP] = UP6(CC_SEL(cc, 5));
729 rgba[BCOMP] = UP5(CC_SEL(cc, 0));
730 } else if (code == 1) {
731 rgba[RCOMP] = UP5(CC_SEL(cc, 27));
732 rgba[GCOMP] = UP6(CC_SEL(cc, 21));
733 rgba[BCOMP] = UP5(CC_SEL(cc, 16));
734 } else if (code == 2) {
735 /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
736 rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
737 rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
738 rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
739 } else {
740 rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
741 rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
742 rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
743 }
744 if (acode == 0) {
745 rgba[ACOMP] = alpha0;
746 } else if (acode == 1) {
747 rgba[ACOMP] = alpha1;
748 } else if (alpha0 > alpha1) {
749 rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7;
750 } else if (acode == 6) {
751 rgba[ACOMP] = 0;
752 } else if (acode == 7) {
753 rgba[ACOMP] = 255;
754 } else {
755 rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5;
756 }
757 }