2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * \file texcompress_fxt1.c
28 * GL_EXT_texture_compression_fxt1 support.
39 #include "texcompress.h"
40 #include "texcompress_fxt1.h"
44 #if FEATURE_texture_fxt1
48 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
49 const void *source
, GLint srcRowStride
,
50 void *dest
, GLint destRowStride
);
53 fxt1_decode_1 (const void *texture
, GLint stride
,
54 GLint i
, GLint j
, GLchan
*rgba
);
58 * Store user's image in rgb_fxt1 format.
61 _mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS
)
66 const GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
67 const GLchan
*tempImage
= NULL
;
69 ASSERT(dstFormat
== MESA_FORMAT_RGB_FXT1
);
70 ASSERT(dstXoffset
% 8 == 0);
71 ASSERT(dstYoffset
% 4 == 0);
72 ASSERT(dstZoffset
== 0);
74 (void) dstImageOffsets
;
76 if (srcFormat
!= GL_RGB
||
77 srcType
!= CHAN_TYPE
||
78 ctx
->_ImageTransferState
||
79 srcPacking
->SwapBytes
) {
80 /* convert image to RGB/GLchan */
81 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
83 _mesa_get_format_base_format(dstFormat
),
84 srcWidth
, srcHeight
, srcDepth
,
85 srcFormat
, srcType
, srcAddr
,
88 return GL_FALSE
; /* out of memory */
89 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
91 srcRowStride
= 3 * srcWidth
;
95 pixels
= (const GLchan
*) srcAddr
;
96 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
97 srcType
) / sizeof(GLchan
);
100 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
102 texWidth
, (GLubyte
*) dstAddr
);
104 fxt1_encode(srcWidth
, srcHeight
, 3, pixels
, srcRowStride
,
108 free((void*) tempImage
);
115 * Store user's image in rgba_fxt1 format.
118 _mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS
)
120 const GLchan
*pixels
;
123 GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
124 const GLchan
*tempImage
= NULL
;
126 ASSERT(dstFormat
== MESA_FORMAT_RGBA_FXT1
);
127 ASSERT(dstXoffset
% 8 == 0);
128 ASSERT(dstYoffset
% 4 == 0);
129 ASSERT(dstZoffset
== 0);
131 (void) dstImageOffsets
;
133 if (srcFormat
!= GL_RGBA
||
134 srcType
!= CHAN_TYPE
||
135 ctx
->_ImageTransferState
||
136 srcPacking
->SwapBytes
) {
137 /* convert image to RGBA/GLchan */
138 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
140 _mesa_get_format_base_format(dstFormat
),
141 srcWidth
, srcHeight
, srcDepth
,
142 srcFormat
, srcType
, srcAddr
,
145 return GL_FALSE
; /* out of memory */
146 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
148 srcRowStride
= 4 * srcWidth
;
152 pixels
= (const GLchan
*) srcAddr
;
153 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
154 srcType
) / sizeof(GLchan
);
157 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
159 texWidth
, (GLubyte
*) dstAddr
);
161 fxt1_encode(srcWidth
, srcHeight
, 4, pixels
, srcRowStride
,
165 free((void*) tempImage
);
172 _mesa_fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image
*texImage
,
173 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
175 /* just sample as GLchan and convert to float here */
178 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
179 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
180 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
181 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
182 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
187 _mesa_fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image
*texImage
,
188 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
190 /* just sample as GLchan and convert to float here */
193 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
194 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
195 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
196 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
202 /***************************************************************************\
205 * The encoder was built by reversing the decoder,
206 * and is vaguely based on Texus2 by 3dfx. Note that this code
207 * is merely a proof of concept, since it is highly UNoptimized;
208 * moreover, it is sub-optimal due to initial conditions passed
209 * to Lloyd's algorithm (the interpolation modes are even worse).
210 \***************************************************************************/
213 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
214 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
215 #define N_TEXELS 32 /* number of texels in a block (always 32) */
216 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
217 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
218 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
219 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
220 #define ISTBLACK(v) (*((GLuint *)(v)) == 0)
224 * Define a 64-bit unsigned integer type and macros
228 #define FX64_NATIVE 1
230 typedef uint64_t Fx64
;
232 #define FX64_MOV32(a, b) a = b
233 #define FX64_OR32(a, b) a |= b
234 #define FX64_SHL(a, c) a <<= c
238 #define FX64_NATIVE 0
244 #define FX64_MOV32(a, b) a.lo = b
245 #define FX64_OR32(a, b) a.lo |= b
247 #define FX64_SHL(a, c) \
250 a.hi = a.lo << ((c) - 32); \
253 a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
261 #define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
262 #define SAFECDOT 1 /* for paranoids */
264 #define MAKEIVEC(NV, NC, IV, B, V0, V1) \
266 /* compute interpolation vector */ \
270 for (i = 0; i < NC; i++) { \
271 IV[i] = (V1[i] - V0[i]) * F(i); \
272 d2 += IV[i] * IV[i]; \
274 rd2 = (GLfloat)NV / d2; \
276 for (i = 0; i < NC; i++) { \
278 B -= IV[i] * V0[i]; \
281 B = B * rd2 + 0.5f; \
284 #define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
286 GLfloat dot = 0.0F; \
287 for (i = 0; i < NC; i++) { \
288 dot += V[i] * IV[i]; \
290 TEXEL = (GLint)(dot + B); \
294 } else if (TEXEL > NV) { \
302 fxt1_bestcol (GLfloat vec
[][MAX_COMP
], GLint nv
,
303 GLubyte input
[MAX_COMP
], GLint nc
)
305 GLint i
, j
, best
= -1;
306 GLfloat err
= 1e9
; /* big enough */
308 for (j
= 0; j
< nv
; j
++) {
310 for (i
= 0; i
< nc
; i
++) {
311 e
+= (vec
[j
][i
] - input
[i
]) * (vec
[j
][i
] - input
[i
]);
324 fxt1_worst (GLfloat vec
[MAX_COMP
],
325 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
327 GLint i
, k
, worst
= -1;
328 GLfloat err
= -1.0F
; /* small enough */
330 for (k
= 0; k
< n
; k
++) {
332 for (i
= 0; i
< nc
; i
++) {
333 e
+= (vec
[i
] - input
[k
][i
]) * (vec
[i
] - input
[k
][i
]);
346 fxt1_variance (GLdouble variance
[MAX_COMP
],
347 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
349 GLint i
, k
, best
= 0;
351 GLdouble var
, maxvar
= -1; /* small enough */
352 GLdouble teenth
= 1.0 / n
;
354 for (i
= 0; i
< nc
; i
++) {
356 for (k
= 0; k
< n
; k
++) {
357 GLint t
= input
[k
][i
];
361 var
= sx2
* teenth
- sx
* sx
* teenth
* teenth
;
376 fxt1_choose (GLfloat vec
[][MAX_COMP
], GLint nv
,
377 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
380 /* Choose colors from a grid.
384 for (j
= 0; j
< nv
; j
++) {
385 GLint m
= j
* (n
- 1) / (nv
- 1);
386 for (i
= 0; i
< nc
; i
++) {
387 vec
[j
][i
] = input
[m
][i
];
391 /* Our solution here is to find the darkest and brightest colors in
392 * the 8x4 tile and use those as the two representative colors.
393 * There are probably better algorithms to use (histogram-based).
396 GLint minSum
= 2000; /* big enough */
397 GLint maxSum
= -1; /* small enough */
398 GLint minCol
= 0; /* phoudoin: silent compiler! */
399 GLint maxCol
= 0; /* phoudoin: silent compiler! */
409 memset(hist
, 0, sizeof(hist
));
411 for (k
= 0; k
< n
; k
++) {
415 for (i
= 0; i
< nc
; i
++) {
420 for (l
= 0; l
< n
; l
++) {
429 } else if (hist
[l
].key
== key
) {
445 for (j
= 0; j
< lenh
; j
++) {
446 for (i
= 0; i
< nc
; i
++) {
447 vec
[j
][i
] = (GLfloat
)input
[hist
[j
].idx
][i
];
450 for (; j
< nv
; j
++) {
451 for (i
= 0; i
< nc
; i
++) {
452 vec
[j
][i
] = vec
[0][i
];
458 for (j
= 0; j
< nv
; j
++) {
459 for (i
= 0; i
< nc
; i
++) {
460 vec
[j
][i
] = ((nv
- 1 - j
) * input
[minCol
][i
] + j
* input
[maxCol
][i
] + (nv
- 1) / 2) / (GLfloat
)(nv
- 1);
470 fxt1_lloyd (GLfloat vec
[][MAX_COMP
], GLint nv
,
471 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
473 /* Use the generalized lloyd's algorithm for VQ:
474 * find 4 color vectors.
476 * for each sample color
477 * sort to nearest vector.
479 * replace each vector with the centroid of its matching colors.
481 * repeat until RMS doesn't improve.
483 * if a color vector has no samples, or becomes the same as another
484 * vector, replace it with the color which is farthest from a sample.
486 * vec[][MAX_COMP] initial vectors and resulting colors
487 * nv number of resulting colors required
488 * input[N_TEXELS][MAX_COMP] input texels
489 * nc number of components in input / vec
490 * n number of input samples
493 GLint sum
[MAX_VECT
][MAX_COMP
]; /* used to accumulate closest texels */
494 GLint cnt
[MAX_VECT
]; /* how many times a certain vector was chosen */
495 GLfloat error
, lasterror
= 1e9
;
500 for (rep
= 0; rep
< LL_N_REP
; rep
++) {
501 /* reset sums & counters */
502 for (j
= 0; j
< nv
; j
++) {
503 for (i
= 0; i
< nc
; i
++) {
510 /* scan whole block */
511 for (k
= 0; k
< n
; k
++) {
514 GLfloat err
= 1e9
; /* big enough */
515 /* determine best vector */
516 for (j
= 0; j
< nv
; j
++) {
517 GLfloat e
= (vec
[j
][0] - input
[k
][0]) * (vec
[j
][0] - input
[k
][0]) +
518 (vec
[j
][1] - input
[k
][1]) * (vec
[j
][1] - input
[k
][1]) +
519 (vec
[j
][2] - input
[k
][2]) * (vec
[j
][2] - input
[k
][2]);
521 e
+= (vec
[j
][3] - input
[k
][3]) * (vec
[j
][3] - input
[k
][3]);
529 GLint best
= fxt1_bestcol(vec
, nv
, input
[k
], nc
, &err
);
532 /* add in closest color */
533 for (i
= 0; i
< nc
; i
++) {
534 sum
[best
][i
] += input
[k
][i
];
536 /* mark this vector as used */
538 /* accumulate error */
543 if ((error
< LL_RMS_E
) ||
544 ((error
< lasterror
) && ((lasterror
- error
) < LL_RMS_D
))) {
545 return !0; /* good match */
549 /* move each vector to the barycenter of its closest colors */
550 for (j
= 0; j
< nv
; j
++) {
552 GLfloat div
= 1.0F
/ cnt
[j
];
553 for (i
= 0; i
< nc
; i
++) {
554 vec
[j
][i
] = div
* sum
[j
][i
];
557 /* this vec has no samples or is identical with a previous vec */
558 GLint worst
= fxt1_worst(vec
[j
], input
, nc
, n
);
559 for (i
= 0; i
< nc
; i
++) {
560 vec
[j
][i
] = input
[worst
][i
];
566 return 0; /* could not converge fast enough */
571 fxt1_quantize_CHROMA (GLuint
*cc
,
572 GLubyte input
[N_TEXELS
][MAX_COMP
])
574 const GLint n_vect
= 4; /* 4 base vectors to find */
575 const GLint n_comp
= 3; /* 3 components: R, G, B */
576 GLfloat vec
[MAX_VECT
][MAX_COMP
];
578 Fx64 hi
; /* high quadword */
579 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
581 if (fxt1_choose(vec
, n_vect
, input
, n_comp
, N_TEXELS
) != 0) {
582 fxt1_lloyd(vec
, n_vect
, input
, n_comp
, N_TEXELS
);
585 FX64_MOV32(hi
, 4); /* cc-chroma = "010" + unused bit */
586 for (j
= n_vect
- 1; j
>= 0; j
--) {
587 for (i
= 0; i
< n_comp
; i
++) {
590 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
593 ((Fx64
*)cc
)[1] = hi
;
596 /* right microtile */
597 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
599 lohi
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
602 for (; k
>= 0; k
--) {
604 lolo
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
612 fxt1_quantize_ALPHA0 (GLuint
*cc
,
613 GLubyte input
[N_TEXELS
][MAX_COMP
],
614 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
616 const GLint n_vect
= 3; /* 3 base vectors to find */
617 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
618 GLfloat vec
[MAX_VECT
][MAX_COMP
];
620 Fx64 hi
; /* high quadword */
621 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
623 /* the last vector indicates zero */
624 for (i
= 0; i
< n_comp
; i
++) {
628 /* the first n texels in reord are guaranteed to be non-zero */
629 if (fxt1_choose(vec
, n_vect
, reord
, n_comp
, n
) != 0) {
630 fxt1_lloyd(vec
, n_vect
, reord
, n_comp
, n
);
633 FX64_MOV32(hi
, 6); /* alpha = "011" + lerp = 0 */
634 for (j
= n_vect
- 1; j
>= 0; j
--) {
637 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
639 for (j
= n_vect
- 1; j
>= 0; j
--) {
640 for (i
= 0; i
< n_comp
- 1; i
++) {
643 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
646 ((Fx64
*)cc
)[1] = hi
;
649 /* right microtile */
650 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
652 lohi
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
655 for (; k
>= 0; k
--) {
657 lolo
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
665 fxt1_quantize_ALPHA1 (GLuint
*cc
,
666 GLubyte input
[N_TEXELS
][MAX_COMP
])
668 const GLint n_vect
= 3; /* highest vector number in each microtile */
669 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
670 GLfloat vec
[1 + 1 + 1][MAX_COMP
]; /* 1.5 extrema for each sub-block */
671 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
673 Fx64 hi
; /* high quadword */
674 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
678 GLint minColL
= 0, maxColL
= 0;
679 GLint minColR
= 0, maxColR
= 0;
680 GLint sumL
= 0, sumR
= 0;
682 /* Our solution here is to find the darkest and brightest colors in
683 * the 4x4 tile and use those as the two representative colors.
684 * There are probably better algorithms to use (histogram-based).
687 while ((minColL
== maxColL
) && nn_comp
) {
688 minSum
= 2000; /* big enough */
689 maxSum
= -1; /* small enough */
690 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
692 for (i
= 0; i
< nn_comp
; i
++) {
710 while ((minColR
== maxColR
) && nn_comp
) {
711 minSum
= 2000; /* big enough */
712 maxSum
= -1; /* small enough */
713 for (k
= N_TEXELS
/ 2; k
< N_TEXELS
; k
++) {
715 for (i
= 0; i
< nn_comp
; i
++) {
732 /* choose the common vector (yuck!) */
735 GLint v1
= 0, v2
= 0;
736 GLfloat err
= 1e9
; /* big enough */
737 GLfloat tv
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
738 for (i
= 0; i
< n_comp
; i
++) {
739 tv
[0][i
] = input
[minColL
][i
];
740 tv
[1][i
] = input
[maxColL
][i
];
741 tv
[2][i
] = input
[minColR
][i
];
742 tv
[3][i
] = input
[maxColR
][i
];
744 for (j1
= 0; j1
< 2; j1
++) {
745 for (j2
= 2; j2
< 4; j2
++) {
747 for (i
= 0; i
< n_comp
; i
++) {
748 e
+= (tv
[j1
][i
] - tv
[j2
][i
]) * (tv
[j1
][i
] - tv
[j2
][i
]);
757 for (i
= 0; i
< n_comp
; i
++) {
758 vec
[0][i
] = tv
[1 - v1
][i
];
759 vec
[1][i
] = (tv
[v1
][i
] * sumL
+ tv
[v2
][i
] * sumR
) / (sumL
+ sumR
);
760 vec
[2][i
] = tv
[5 - v2
][i
];
766 if (minColL
!= maxColL
) {
767 /* compute interpolation vector */
768 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
772 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
774 /* interpolate color */
775 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
784 /* right microtile */
786 if (minColR
!= maxColR
) {
787 /* compute interpolation vector */
788 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[1]);
792 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
794 /* interpolate color */
795 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
804 FX64_MOV32(hi
, 7); /* alpha = "011" + lerp = 1 */
805 for (j
= n_vect
- 1; j
>= 0; j
--) {
808 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
810 for (j
= n_vect
- 1; j
>= 0; j
--) {
811 for (i
= 0; i
< n_comp
- 1; i
++) {
814 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
817 ((Fx64
*)cc
)[1] = hi
;
822 fxt1_quantize_HI (GLuint
*cc
,
823 GLubyte input
[N_TEXELS
][MAX_COMP
],
824 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
826 const GLint n_vect
= 6; /* highest vector number */
827 const GLint n_comp
= 3; /* 3 components: R, G, B */
828 GLfloat b
= 0.0F
; /* phoudoin: silent compiler! */
829 GLfloat iv
[MAX_COMP
]; /* interpolation vector */
831 GLuint hihi
; /* high quadword: hi dword */
833 GLint minSum
= 2000; /* big enough */
834 GLint maxSum
= -1; /* small enough */
835 GLint minCol
= 0; /* phoudoin: silent compiler! */
836 GLint maxCol
= 0; /* phoudoin: silent compiler! */
838 /* Our solution here is to find the darkest and brightest colors in
839 * the 8x4 tile and use those as the two representative colors.
840 * There are probably better algorithms to use (histogram-based).
842 for (k
= 0; k
< n
; k
++) {
844 for (i
= 0; i
< n_comp
; i
++) {
857 hihi
= 0; /* cc-hi = "00" */
858 for (i
= 0; i
< n_comp
; i
++) {
861 hihi
|= reord
[maxCol
][i
] >> 3;
863 for (i
= 0; i
< n_comp
; i
++) {
866 hihi
|= reord
[minCol
][i
] >> 3;
869 cc
[0] = cc
[1] = cc
[2] = 0;
871 /* compute interpolation vector */
872 if (minCol
!= maxCol
) {
873 MAKEIVEC(n_vect
, n_comp
, iv
, b
, reord
[minCol
], reord
[maxCol
]);
877 for (k
= N_TEXELS
- 1; k
>= 0; k
--) {
879 GLuint
*kk
= (GLuint
*)((char *)cc
+ t
/ 8);
880 GLint texel
= n_vect
+ 1; /* transparent black */
882 if (!ISTBLACK(input
[k
])) {
883 if (minCol
!= maxCol
) {
884 /* interpolate color */
885 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
887 kk
[0] |= texel
<< (t
& 7);
891 kk
[0] |= texel
<< (t
& 7);
898 fxt1_quantize_MIXED1 (GLuint
*cc
,
899 GLubyte input
[N_TEXELS
][MAX_COMP
])
901 const GLint n_vect
= 2; /* highest vector number in each microtile */
902 const GLint n_comp
= 3; /* 3 components: R, G, B */
903 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
904 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
906 Fx64 hi
; /* high quadword */
907 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
911 GLint minColL
= 0, maxColL
= -1;
912 GLint minColR
= 0, maxColR
= -1;
914 /* Our solution here is to find the darkest and brightest colors in
915 * the 4x4 tile and use those as the two representative colors.
916 * There are probably better algorithms to use (histogram-based).
918 minSum
= 2000; /* big enough */
919 maxSum
= -1; /* small enough */
920 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
921 if (!ISTBLACK(input
[k
])) {
923 for (i
= 0; i
< n_comp
; i
++) {
936 minSum
= 2000; /* big enough */
937 maxSum
= -1; /* small enough */
938 for (; k
< N_TEXELS
; k
++) {
939 if (!ISTBLACK(input
[k
])) {
941 for (i
= 0; i
< n_comp
; i
++) {
957 /* all transparent black */
959 for (i
= 0; i
< n_comp
; i
++) {
965 for (i
= 0; i
< n_comp
; i
++) {
966 vec
[0][i
] = input
[minColL
][i
];
967 vec
[1][i
] = input
[maxColL
][i
];
969 if (minColL
!= maxColL
) {
970 /* compute interpolation vector */
971 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
975 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
976 GLint texel
= n_vect
+ 1; /* transparent black */
977 if (!ISTBLACK(input
[k
])) {
978 /* interpolate color */
979 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
989 /* right microtile */
991 /* all transparent black */
993 for (i
= 0; i
< n_comp
; i
++) {
999 for (i
= 0; i
< n_comp
; i
++) {
1000 vec
[2][i
] = input
[minColR
][i
];
1001 vec
[3][i
] = input
[maxColR
][i
];
1003 if (minColR
!= maxColR
) {
1004 /* compute interpolation vector */
1005 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1009 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1010 GLint texel
= n_vect
+ 1; /* transparent black */
1011 if (!ISTBLACK(input
[k
])) {
1012 /* interpolate color */
1013 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1023 FX64_MOV32(hi
, 9 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1024 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1025 for (i
= 0; i
< n_comp
; i
++) {
1028 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1031 ((Fx64
*)cc
)[1] = hi
;
1036 fxt1_quantize_MIXED0 (GLuint
*cc
,
1037 GLubyte input
[N_TEXELS
][MAX_COMP
])
1039 const GLint n_vect
= 3; /* highest vector number in each microtile */
1040 const GLint n_comp
= 3; /* 3 components: R, G, B */
1041 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
1042 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
1044 Fx64 hi
; /* high quadword */
1045 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
1047 GLint minColL
= 0, maxColL
= 0;
1048 GLint minColR
= 0, maxColR
= 0;
1053 /* Our solution here is to find the darkest and brightest colors in
1054 * the 4x4 tile and use those as the two representative colors.
1055 * There are probably better algorithms to use (histogram-based).
1057 minSum
= 2000; /* big enough */
1058 maxSum
= -1; /* small enough */
1059 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1061 for (i
= 0; i
< n_comp
; i
++) {
1073 minSum
= 2000; /* big enough */
1074 maxSum
= -1; /* small enough */
1075 for (; k
< N_TEXELS
; k
++) {
1077 for (i
= 0; i
< n_comp
; i
++) {
1092 GLint maxVarL
= fxt1_variance(NULL
, input
, n_comp
, N_TEXELS
/ 2);
1093 GLint maxVarR
= fxt1_variance(NULL
, &input
[N_TEXELS
/ 2], n_comp
, N_TEXELS
/ 2);
1095 /* Scan the channel with max variance for lo & hi
1096 * and use those as the two representative colors.
1098 minVal
= 2000; /* big enough */
1099 maxVal
= -1; /* small enough */
1100 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1101 GLint t
= input
[k
][maxVarL
];
1111 minVal
= 2000; /* big enough */
1112 maxVal
= -1; /* small enough */
1113 for (; k
< N_TEXELS
; k
++) {
1114 GLint t
= input
[k
][maxVarR
];
1126 /* left microtile */
1128 for (i
= 0; i
< n_comp
; i
++) {
1129 vec
[0][i
] = input
[minColL
][i
];
1130 vec
[1][i
] = input
[maxColL
][i
];
1132 if (minColL
!= maxColL
) {
1133 /* compute interpolation vector */
1134 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1138 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1140 /* interpolate color */
1141 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1147 /* funky encoding for LSB of green */
1148 if ((GLint
)((lolo
>> 1) & 1) != (((vec
[1][GCOMP
] ^ vec
[0][GCOMP
]) >> 2) & 1)) {
1149 for (i
= 0; i
< n_comp
; i
++) {
1150 vec
[1][i
] = input
[minColL
][i
];
1151 vec
[0][i
] = input
[maxColL
][i
];
1159 /* right microtile */
1161 for (i
= 0; i
< n_comp
; i
++) {
1162 vec
[2][i
] = input
[minColR
][i
];
1163 vec
[3][i
] = input
[maxColR
][i
];
1165 if (minColR
!= maxColR
) {
1166 /* compute interpolation vector */
1167 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1171 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1173 /* interpolate color */
1174 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1180 /* funky encoding for LSB of green */
1181 if ((GLint
)((lohi
>> 1) & 1) != (((vec
[3][GCOMP
] ^ vec
[2][GCOMP
]) >> 2) & 1)) {
1182 for (i
= 0; i
< n_comp
; i
++) {
1183 vec
[3][i
] = input
[minColR
][i
];
1184 vec
[2][i
] = input
[maxColR
][i
];
1192 FX64_MOV32(hi
, 8 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1193 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1194 for (i
= 0; i
< n_comp
; i
++) {
1197 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1200 ((Fx64
*)cc
)[1] = hi
;
1205 fxt1_quantize (GLuint
*cc
, const GLubyte
*lines
[], GLint comps
)
1208 GLubyte reord
[N_TEXELS
][MAX_COMP
];
1210 GLubyte input
[N_TEXELS
][MAX_COMP
];
1214 /* make the whole block opaque */
1215 memset(input
, -1, sizeof(input
));
1218 /* 8 texels each line */
1219 for (l
= 0; l
< 4; l
++) {
1220 for (k
= 0; k
< 4; k
++) {
1221 for (i
= 0; i
< comps
; i
++) {
1222 input
[k
+ l
* 4][i
] = *lines
[l
]++;
1225 for (; k
< 8; k
++) {
1226 for (i
= 0; i
< comps
; i
++) {
1227 input
[k
+ l
* 4 + 12][i
] = *lines
[l
]++;
1233 * 00, 01, 02, 03, 08, 09, 0a, 0b
1234 * 10, 11, 12, 13, 18, 19, 1a, 1b
1235 * 04, 05, 06, 07, 0c, 0d, 0e, 0f
1236 * 14, 15, 16, 17, 1c, 1d, 1e, 1f
1240 * stupidity flows forth from this
1245 /* skip all transparent black texels */
1247 for (k
= 0; k
< N_TEXELS
; k
++) {
1248 /* test all components against 0 */
1249 if (!ISTBLACK(input
[k
])) {
1250 /* texel is not transparent black */
1251 COPY_4UBV(reord
[l
], input
[k
]);
1252 if (reord
[l
][ACOMP
] < (255 - ALPHA_TS
)) {
1253 /* non-opaque texel */
1263 fxt1_quantize_ALPHA0(cc
, input
, reord
, l
);
1264 } else if (l
== 0) {
1265 cc
[0] = cc
[1] = cc
[2] = -1;
1267 } else if (l
< N_TEXELS
) {
1268 fxt1_quantize_HI(cc
, input
, reord
, l
);
1270 fxt1_quantize_CHROMA(cc
, input
);
1272 (void)fxt1_quantize_ALPHA1
;
1273 (void)fxt1_quantize_MIXED1
;
1274 (void)fxt1_quantize_MIXED0
;
1277 fxt1_quantize_ALPHA1(cc
, input
);
1278 } else if (l
== 0) {
1279 cc
[0] = cc
[1] = cc
[2] = ~0u;
1281 } else if (l
< N_TEXELS
) {
1282 fxt1_quantize_MIXED1(cc
, input
);
1284 fxt1_quantize_MIXED0(cc
, input
);
1286 (void)fxt1_quantize_ALPHA0
;
1287 (void)fxt1_quantize_HI
;
1288 (void)fxt1_quantize_CHROMA
;
1294 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
1295 const void *source
, GLint srcRowStride
,
1296 void *dest
, GLint destRowStride
)
1299 const GLubyte
*data
;
1300 GLuint
*encoded
= (GLuint
*)dest
;
1301 void *newSource
= NULL
;
1303 assert(comps
== 3 || comps
== 4);
1305 /* Replicate image if width is not M8 or height is not M4 */
1306 if ((width
& 7) | (height
& 3)) {
1307 GLint newWidth
= (width
+ 7) & ~7;
1308 GLint newHeight
= (height
+ 3) & ~3;
1309 newSource
= malloc(comps
* newWidth
* newHeight
* sizeof(GLchan
));
1311 GET_CURRENT_CONTEXT(ctx
);
1312 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1315 _mesa_upscale_teximage2d(width
, height
, newWidth
, newHeight
,
1316 comps
, (const GLchan
*) source
,
1317 srcRowStride
, (GLchan
*) newSource
);
1321 srcRowStride
= comps
* newWidth
;
1324 /* convert from 16/32-bit channels to GLubyte if needed */
1325 if (CHAN_TYPE
!= GL_UNSIGNED_BYTE
) {
1326 const GLuint n
= width
* height
* comps
;
1327 const GLchan
*src
= (const GLchan
*) source
;
1328 GLubyte
*dest
= (GLubyte
*) malloc(n
* sizeof(GLubyte
));
1331 GET_CURRENT_CONTEXT(ctx
);
1332 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1335 for (i
= 0; i
< n
; i
++) {
1336 dest
[i
] = CHAN_TO_UBYTE(src
[i
]);
1338 if (newSource
!= NULL
) {
1341 newSource
= dest
; /* we'll free this buffer before returning */
1342 source
= dest
; /* the new, GLubyte incoming image */
1345 data
= (const GLubyte
*) source
;
1346 destRowStride
= (destRowStride
- width
* 2) / 4;
1347 for (y
= 0; y
< height
; y
+= 4) {
1348 GLuint offs
= 0 + (y
+ 0) * srcRowStride
;
1349 for (x
= 0; x
< width
; x
+= 8) {
1350 const GLubyte
*lines
[4];
1351 lines
[0] = &data
[offs
];
1352 lines
[1] = lines
[0] + srcRowStride
;
1353 lines
[2] = lines
[1] + srcRowStride
;
1354 lines
[3] = lines
[2] + srcRowStride
;
1356 fxt1_quantize(encoded
, lines
, comps
);
1357 /* 128 bits per 8x4 block */
1360 encoded
+= destRowStride
;
1364 if (newSource
!= NULL
) {
1370 /***************************************************************************\
1373 * The decoder is based on GL_3DFX_texture_compression_FXT1
1374 * specification and serves as a concept for the encoder.
1375 \***************************************************************************/
1378 /* lookup table for scaling 5 bit colors up to 8 bits */
1379 static const GLubyte _rgb_scale_5
[] = {
1380 0, 8, 16, 25, 33, 41, 49, 58,
1381 66, 74, 82, 90, 99, 107, 115, 123,
1382 132, 140, 148, 156, 165, 173, 181, 189,
1383 197, 206, 214, 222, 230, 239, 247, 255
1386 /* lookup table for scaling 6 bit colors up to 8 bits */
1387 static const GLubyte _rgb_scale_6
[] = {
1388 0, 4, 8, 12, 16, 20, 24, 28,
1389 32, 36, 40, 45, 49, 53, 57, 61,
1390 65, 69, 73, 77, 81, 85, 89, 93,
1391 97, 101, 105, 109, 113, 117, 121, 125,
1392 130, 134, 138, 142, 146, 150, 154, 158,
1393 162, 166, 170, 174, 178, 182, 186, 190,
1394 194, 198, 202, 206, 210, 215, 219, 223,
1395 227, 231, 235, 239, 243, 247, 251, 255
1399 #define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
1400 #define UP5(c) _rgb_scale_5[(c) & 31]
1401 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
1402 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
1406 fxt1_decode_1HI (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1411 cc
= (const GLuint
*)(code
+ t
/ 8);
1412 t
= (cc
[0] >> (t
& 7)) & 7;
1415 rgba
[RCOMP
] = rgba
[GCOMP
] = rgba
[BCOMP
] = rgba
[ACOMP
] = 0;
1418 cc
= (const GLuint
*)(code
+ 12);
1420 b
= UP5(CC_SEL(cc
, 0));
1421 g
= UP5(CC_SEL(cc
, 5));
1422 r
= UP5(CC_SEL(cc
, 10));
1423 } else if (t
== 6) {
1424 b
= UP5(CC_SEL(cc
, 15));
1425 g
= UP5(CC_SEL(cc
, 20));
1426 r
= UP5(CC_SEL(cc
, 25));
1428 b
= LERP(6, t
, UP5(CC_SEL(cc
, 0)), UP5(CC_SEL(cc
, 15)));
1429 g
= LERP(6, t
, UP5(CC_SEL(cc
, 5)), UP5(CC_SEL(cc
, 20)));
1430 r
= LERP(6, t
, UP5(CC_SEL(cc
, 10)), UP5(CC_SEL(cc
, 25)));
1432 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1433 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1434 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1435 rgba
[ACOMP
] = CHAN_MAX
;
1441 fxt1_decode_1CHROMA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1446 cc
= (const GLuint
*)code
;
1451 t
= (cc
[0] >> (t
* 2)) & 3;
1454 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1455 kk
= cc
[0] >> (t
& 7);
1456 rgba
[BCOMP
] = UBYTE_TO_CHAN( UP5(kk
) );
1457 rgba
[GCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 5) );
1458 rgba
[RCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 10) );
1459 rgba
[ACOMP
] = CHAN_MAX
;
1464 fxt1_decode_1MIXED (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1470 cc
= (const GLuint
*)code
;
1473 t
= (cc
[1] >> (t
* 2)) & 3;
1475 col
[0][BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1476 col
[0][GCOMP
] = CC_SEL(cc
, 99);
1477 col
[0][RCOMP
] = CC_SEL(cc
, 104);
1479 col
[1][BCOMP
] = CC_SEL(cc
, 109);
1480 col
[1][GCOMP
] = CC_SEL(cc
, 114);
1481 col
[1][RCOMP
] = CC_SEL(cc
, 119);
1482 glsb
= CC_SEL(cc
, 126);
1483 selb
= CC_SEL(cc
, 33);
1485 t
= (cc
[0] >> (t
* 2)) & 3;
1487 col
[0][BCOMP
] = CC_SEL(cc
, 64);
1488 col
[0][GCOMP
] = CC_SEL(cc
, 69);
1489 col
[0][RCOMP
] = CC_SEL(cc
, 74);
1491 col
[1][BCOMP
] = CC_SEL(cc
, 79);
1492 col
[1][GCOMP
] = CC_SEL(cc
, 84);
1493 col
[1][RCOMP
] = CC_SEL(cc
, 89);
1494 glsb
= CC_SEL(cc
, 125);
1495 selb
= CC_SEL(cc
, 1);
1498 if (CC_SEL(cc
, 124) & 1) {
1503 rgba
[RCOMP
] = rgba
[BCOMP
] = rgba
[GCOMP
] = rgba
[ACOMP
] = 0;
1507 b
= UP5(col
[0][BCOMP
]);
1508 g
= UP5(col
[0][GCOMP
]);
1509 r
= UP5(col
[0][RCOMP
]);
1510 } else if (t
== 2) {
1511 b
= UP5(col
[1][BCOMP
]);
1512 g
= UP6(col
[1][GCOMP
], glsb
);
1513 r
= UP5(col
[1][RCOMP
]);
1515 b
= (UP5(col
[0][BCOMP
]) + UP5(col
[1][BCOMP
])) / 2;
1516 g
= (UP5(col
[0][GCOMP
]) + UP6(col
[1][GCOMP
], glsb
)) / 2;
1517 r
= (UP5(col
[0][RCOMP
]) + UP5(col
[1][RCOMP
])) / 2;
1519 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1520 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1521 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1522 rgba
[ACOMP
] = CHAN_MAX
;
1528 b
= UP5(col
[0][BCOMP
]);
1529 g
= UP6(col
[0][GCOMP
], glsb
^ selb
);
1530 r
= UP5(col
[0][RCOMP
]);
1531 } else if (t
== 3) {
1532 b
= UP5(col
[1][BCOMP
]);
1533 g
= UP6(col
[1][GCOMP
], glsb
);
1534 r
= UP5(col
[1][RCOMP
]);
1536 b
= LERP(3, t
, UP5(col
[0][BCOMP
]), UP5(col
[1][BCOMP
]));
1537 g
= LERP(3, t
, UP6(col
[0][GCOMP
], glsb
^ selb
),
1538 UP6(col
[1][GCOMP
], glsb
));
1539 r
= LERP(3, t
, UP5(col
[0][RCOMP
]), UP5(col
[1][RCOMP
]));
1541 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1542 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1543 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1544 rgba
[ACOMP
] = CHAN_MAX
;
1550 fxt1_decode_1ALPHA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1555 cc
= (const GLuint
*)code
;
1556 if (CC_SEL(cc
, 124) & 1) {
1562 t
= (cc
[1] >> (t
* 2)) & 3;
1564 col0
[BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1565 col0
[GCOMP
] = CC_SEL(cc
, 99);
1566 col0
[RCOMP
] = CC_SEL(cc
, 104);
1567 col0
[ACOMP
] = CC_SEL(cc
, 119);
1569 t
= (cc
[0] >> (t
* 2)) & 3;
1571 col0
[BCOMP
] = CC_SEL(cc
, 64);
1572 col0
[GCOMP
] = CC_SEL(cc
, 69);
1573 col0
[RCOMP
] = CC_SEL(cc
, 74);
1574 col0
[ACOMP
] = CC_SEL(cc
, 109);
1578 b
= UP5(col0
[BCOMP
]);
1579 g
= UP5(col0
[GCOMP
]);
1580 r
= UP5(col0
[RCOMP
]);
1581 a
= UP5(col0
[ACOMP
]);
1582 } else if (t
== 3) {
1583 b
= UP5(CC_SEL(cc
, 79));
1584 g
= UP5(CC_SEL(cc
, 84));
1585 r
= UP5(CC_SEL(cc
, 89));
1586 a
= UP5(CC_SEL(cc
, 114));
1588 b
= LERP(3, t
, UP5(col0
[BCOMP
]), UP5(CC_SEL(cc
, 79)));
1589 g
= LERP(3, t
, UP5(col0
[GCOMP
]), UP5(CC_SEL(cc
, 84)));
1590 r
= LERP(3, t
, UP5(col0
[RCOMP
]), UP5(CC_SEL(cc
, 89)));
1591 a
= LERP(3, t
, UP5(col0
[ACOMP
]), UP5(CC_SEL(cc
, 114)));
1600 t
= (cc
[0] >> (t
* 2)) & 3;
1607 cc
= (const GLuint
*)code
;
1608 a
= UP5(cc
[3] >> (t
* 5 + 13));
1610 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1611 kk
= cc
[0] >> (t
& 7);
1617 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1618 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1619 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1620 rgba
[ACOMP
] = UBYTE_TO_CHAN(a
);
1625 fxt1_decode_1 (const void *texture
, GLint stride
, /* in pixels */
1626 GLint i
, GLint j
, GLchan
*rgba
)
1628 static void (*decode_1
[]) (const GLubyte
*, GLint
, GLchan
*) = {
1629 fxt1_decode_1HI
, /* cc-high = "00?" */
1630 fxt1_decode_1HI
, /* cc-high = "00?" */
1631 fxt1_decode_1CHROMA
, /* cc-chroma = "010" */
1632 fxt1_decode_1ALPHA
, /* alpha = "011" */
1633 fxt1_decode_1MIXED
, /* mixed = "1??" */
1634 fxt1_decode_1MIXED
, /* mixed = "1??" */
1635 fxt1_decode_1MIXED
, /* mixed = "1??" */
1636 fxt1_decode_1MIXED
/* mixed = "1??" */
1639 const GLubyte
*code
= (const GLubyte
*)texture
+
1640 ((j
/ 4) * (stride
/ 8) + (i
/ 8)) * 16;
1641 GLint mode
= CC_SEL(code
, 125);
1649 decode_1
[mode
](code
, t
, rgba
);
1653 #endif /* FEATURE_texture_fxt1 */