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"
41 #include "texformat.h"
46 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
47 const void *source
, GLint srcRowStride
,
48 void *dest
, GLint destRowStride
);
51 fxt1_decode_1 (const void *texture
, GLint stride
,
52 GLint i
, GLint j
, GLchan
*rgba
);
56 * Called during context initialization.
59 _mesa_init_texture_fxt1( GLcontext
*ctx
)
66 * Store user's image in rgb_fxt1 format.
69 _mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS
)
74 const GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
75 const GLchan
*tempImage
= NULL
;
77 ASSERT(dstFormat
== MESA_FORMAT_RGB_FXT1
);
78 ASSERT(dstXoffset
% 8 == 0);
79 ASSERT(dstYoffset
% 4 == 0);
80 ASSERT(dstZoffset
== 0);
82 (void) dstImageOffsets
;
84 if (srcFormat
!= GL_RGB
||
85 srcType
!= CHAN_TYPE
||
86 ctx
->_ImageTransferState
||
87 srcPacking
->SwapBytes
) {
88 /* convert image to RGB/GLchan */
89 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
91 _mesa_get_format_base_format(dstFormat
),
92 srcWidth
, srcHeight
, srcDepth
,
93 srcFormat
, srcType
, srcAddr
,
96 return GL_FALSE
; /* out of memory */
97 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
99 srcRowStride
= 3 * srcWidth
;
103 pixels
= (const GLchan
*) srcAddr
;
104 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
105 srcType
) / sizeof(GLchan
);
108 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
110 texWidth
, (GLubyte
*) dstAddr
);
112 fxt1_encode(srcWidth
, srcHeight
, 3, pixels
, srcRowStride
,
116 _mesa_free((void*) tempImage
);
123 * Store user's image in rgba_fxt1 format.
126 _mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS
)
128 const GLchan
*pixels
;
131 GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
132 const GLchan
*tempImage
= NULL
;
134 ASSERT(dstFormat
== MESA_FORMAT_RGBA_FXT1
);
135 ASSERT(dstXoffset
% 8 == 0);
136 ASSERT(dstYoffset
% 4 == 0);
137 ASSERT(dstZoffset
== 0);
139 (void) dstImageOffsets
;
141 if (srcFormat
!= GL_RGBA
||
142 srcType
!= CHAN_TYPE
||
143 ctx
->_ImageTransferState
||
144 srcPacking
->SwapBytes
) {
145 /* convert image to RGBA/GLchan */
146 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
148 _mesa_get_format_base_format(dstFormat
),
149 srcWidth
, srcHeight
, srcDepth
,
150 srcFormat
, srcType
, srcAddr
,
153 return GL_FALSE
; /* out of memory */
154 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
156 srcRowStride
= 4 * srcWidth
;
160 pixels
= (const GLchan
*) srcAddr
;
161 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
162 srcType
) / sizeof(GLchan
);
165 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
167 texWidth
, (GLubyte
*) dstAddr
);
169 fxt1_encode(srcWidth
, srcHeight
, 4, pixels
, srcRowStride
,
173 _mesa_free((void*) tempImage
);
180 _mesa_fetch_texel_2d_rgba_fxt1( const struct gl_texture_image
*texImage
,
181 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
184 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, texel
);
189 _mesa_fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image
*texImage
,
190 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
192 /* just sample as GLchan and convert to float here */
195 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
196 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
197 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
198 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
199 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
204 _mesa_fetch_texel_2d_rgb_fxt1( const struct gl_texture_image
*texImage
,
205 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
208 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, texel
);
214 _mesa_fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image
*texImage
,
215 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
217 /* just sample as GLchan and convert to float here */
220 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
221 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
222 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
223 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
229 /***************************************************************************\
232 * The encoder was built by reversing the decoder,
233 * and is vaguely based on Texus2 by 3dfx. Note that this code
234 * is merely a proof of concept, since it is highly UNoptimized;
235 * moreover, it is sub-optimal due to initial conditions passed
236 * to Lloyd's algorithm (the interpolation modes are even worse).
237 \***************************************************************************/
240 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
241 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
242 #define N_TEXELS 32 /* number of texels in a block (always 32) */
243 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
244 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
245 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
246 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
247 #define ISTBLACK(v) (*((GLuint *)(v)) == 0)
251 * Define a 64-bit unsigned integer type and macros
255 #define FX64_NATIVE 1
257 typedef uint64_t Fx64
;
259 #define FX64_MOV32(a, b) a = b
260 #define FX64_OR32(a, b) a |= b
261 #define FX64_SHL(a, c) a <<= c
265 #define FX64_NATIVE 0
271 #define FX64_MOV32(a, b) a.lo = b
272 #define FX64_OR32(a, b) a.lo |= b
274 #define FX64_SHL(a, c) \
277 a.hi = a.lo << ((c) - 32); \
280 a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
288 #define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
289 #define SAFECDOT 1 /* for paranoids */
291 #define MAKEIVEC(NV, NC, IV, B, V0, V1) \
293 /* compute interpolation vector */ \
297 for (i = 0; i < NC; i++) { \
298 IV[i] = (V1[i] - V0[i]) * F(i); \
299 d2 += IV[i] * IV[i]; \
301 rd2 = (GLfloat)NV / d2; \
303 for (i = 0; i < NC; i++) { \
305 B -= IV[i] * V0[i]; \
308 B = B * rd2 + 0.5f; \
311 #define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
313 GLfloat dot = 0.0F; \
314 for (i = 0; i < NC; i++) { \
315 dot += V[i] * IV[i]; \
317 TEXEL = (GLint)(dot + B); \
321 } else if (TEXEL > NV) { \
329 fxt1_bestcol (GLfloat vec
[][MAX_COMP
], GLint nv
,
330 GLubyte input
[MAX_COMP
], GLint nc
)
332 GLint i
, j
, best
= -1;
333 GLfloat err
= 1e9
; /* big enough */
335 for (j
= 0; j
< nv
; j
++) {
337 for (i
= 0; i
< nc
; i
++) {
338 e
+= (vec
[j
][i
] - input
[i
]) * (vec
[j
][i
] - input
[i
]);
351 fxt1_worst (GLfloat vec
[MAX_COMP
],
352 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
354 GLint i
, k
, worst
= -1;
355 GLfloat err
= -1.0F
; /* small enough */
357 for (k
= 0; k
< n
; k
++) {
359 for (i
= 0; i
< nc
; i
++) {
360 e
+= (vec
[i
] - input
[k
][i
]) * (vec
[i
] - input
[k
][i
]);
373 fxt1_variance (GLdouble variance
[MAX_COMP
],
374 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
376 GLint i
, k
, best
= 0;
378 GLdouble var
, maxvar
= -1; /* small enough */
379 GLdouble teenth
= 1.0 / n
;
381 for (i
= 0; i
< nc
; i
++) {
383 for (k
= 0; k
< n
; k
++) {
384 GLint t
= input
[k
][i
];
388 var
= sx2
* teenth
- sx
* sx
* teenth
* teenth
;
403 fxt1_choose (GLfloat vec
[][MAX_COMP
], GLint nv
,
404 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
407 /* Choose colors from a grid.
411 for (j
= 0; j
< nv
; j
++) {
412 GLint m
= j
* (n
- 1) / (nv
- 1);
413 for (i
= 0; i
< nc
; i
++) {
414 vec
[j
][i
] = input
[m
][i
];
418 /* Our solution here is to find the darkest and brightest colors in
419 * the 8x4 tile and use those as the two representative colors.
420 * There are probably better algorithms to use (histogram-based).
423 GLint minSum
= 2000; /* big enough */
424 GLint maxSum
= -1; /* small enough */
425 GLint minCol
= 0; /* phoudoin: silent compiler! */
426 GLint maxCol
= 0; /* phoudoin: silent compiler! */
436 _mesa_memset(hist
, 0, sizeof(hist
));
438 for (k
= 0; k
< n
; k
++) {
442 for (i
= 0; i
< nc
; i
++) {
447 for (l
= 0; l
< n
; l
++) {
456 } else if (hist
[l
].key
== key
) {
472 for (j
= 0; j
< lenh
; j
++) {
473 for (i
= 0; i
< nc
; i
++) {
474 vec
[j
][i
] = (GLfloat
)input
[hist
[j
].idx
][i
];
477 for (; j
< nv
; j
++) {
478 for (i
= 0; i
< nc
; i
++) {
479 vec
[j
][i
] = vec
[0][i
];
485 for (j
= 0; j
< nv
; j
++) {
486 for (i
= 0; i
< nc
; i
++) {
487 vec
[j
][i
] = ((nv
- 1 - j
) * input
[minCol
][i
] + j
* input
[maxCol
][i
] + (nv
- 1) / 2) / (GLfloat
)(nv
- 1);
497 fxt1_lloyd (GLfloat vec
[][MAX_COMP
], GLint nv
,
498 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
500 /* Use the generalized lloyd's algorithm for VQ:
501 * find 4 color vectors.
503 * for each sample color
504 * sort to nearest vector.
506 * replace each vector with the centroid of it's matching colors.
508 * repeat until RMS doesn't improve.
510 * if a color vector has no samples, or becomes the same as another
511 * vector, replace it with the color which is farthest from a sample.
513 * vec[][MAX_COMP] initial vectors and resulting colors
514 * nv number of resulting colors required
515 * input[N_TEXELS][MAX_COMP] input texels
516 * nc number of components in input / vec
517 * n number of input samples
520 GLint sum
[MAX_VECT
][MAX_COMP
]; /* used to accumulate closest texels */
521 GLint cnt
[MAX_VECT
]; /* how many times a certain vector was chosen */
522 GLfloat error
, lasterror
= 1e9
;
527 for (rep
= 0; rep
< LL_N_REP
; rep
++) {
528 /* reset sums & counters */
529 for (j
= 0; j
< nv
; j
++) {
530 for (i
= 0; i
< nc
; i
++) {
537 /* scan whole block */
538 for (k
= 0; k
< n
; k
++) {
541 GLfloat err
= 1e9
; /* big enough */
542 /* determine best vector */
543 for (j
= 0; j
< nv
; j
++) {
544 GLfloat e
= (vec
[j
][0] - input
[k
][0]) * (vec
[j
][0] - input
[k
][0]) +
545 (vec
[j
][1] - input
[k
][1]) * (vec
[j
][1] - input
[k
][1]) +
546 (vec
[j
][2] - input
[k
][2]) * (vec
[j
][2] - input
[k
][2]);
548 e
+= (vec
[j
][3] - input
[k
][3]) * (vec
[j
][3] - input
[k
][3]);
556 GLint best
= fxt1_bestcol(vec
, nv
, input
[k
], nc
, &err
);
558 /* add in closest color */
559 for (i
= 0; i
< nc
; i
++) {
560 sum
[best
][i
] += input
[k
][i
];
562 /* mark this vector as used */
564 /* accumulate error */
569 if ((error
< LL_RMS_E
) ||
570 ((error
< lasterror
) && ((lasterror
- error
) < LL_RMS_D
))) {
571 return !0; /* good match */
575 /* move each vector to the barycenter of its closest colors */
576 for (j
= 0; j
< nv
; j
++) {
578 GLfloat div
= 1.0F
/ cnt
[j
];
579 for (i
= 0; i
< nc
; i
++) {
580 vec
[j
][i
] = div
* sum
[j
][i
];
583 /* this vec has no samples or is identical with a previous vec */
584 GLint worst
= fxt1_worst(vec
[j
], input
, nc
, n
);
585 for (i
= 0; i
< nc
; i
++) {
586 vec
[j
][i
] = input
[worst
][i
];
592 return 0; /* could not converge fast enough */
597 fxt1_quantize_CHROMA (GLuint
*cc
,
598 GLubyte input
[N_TEXELS
][MAX_COMP
])
600 const GLint n_vect
= 4; /* 4 base vectors to find */
601 const GLint n_comp
= 3; /* 3 components: R, G, B */
602 GLfloat vec
[MAX_VECT
][MAX_COMP
];
604 Fx64 hi
; /* high quadword */
605 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
607 if (fxt1_choose(vec
, n_vect
, input
, n_comp
, N_TEXELS
) != 0) {
608 fxt1_lloyd(vec
, n_vect
, input
, n_comp
, N_TEXELS
);
611 FX64_MOV32(hi
, 4); /* cc-chroma = "010" + unused bit */
612 for (j
= n_vect
- 1; j
>= 0; j
--) {
613 for (i
= 0; i
< n_comp
; i
++) {
616 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
619 ((Fx64
*)cc
)[1] = hi
;
622 /* right microtile */
623 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
625 lohi
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
628 for (; k
>= 0; k
--) {
630 lolo
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
638 fxt1_quantize_ALPHA0 (GLuint
*cc
,
639 GLubyte input
[N_TEXELS
][MAX_COMP
],
640 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
642 const GLint n_vect
= 3; /* 3 base vectors to find */
643 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
644 GLfloat vec
[MAX_VECT
][MAX_COMP
];
646 Fx64 hi
; /* high quadword */
647 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
649 /* the last vector indicates zero */
650 for (i
= 0; i
< n_comp
; i
++) {
654 /* the first n texels in reord are guaranteed to be non-zero */
655 if (fxt1_choose(vec
, n_vect
, reord
, n_comp
, n
) != 0) {
656 fxt1_lloyd(vec
, n_vect
, reord
, n_comp
, n
);
659 FX64_MOV32(hi
, 6); /* alpha = "011" + lerp = 0 */
660 for (j
= n_vect
- 1; j
>= 0; j
--) {
663 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
665 for (j
= n_vect
- 1; j
>= 0; j
--) {
666 for (i
= 0; i
< n_comp
- 1; i
++) {
669 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
672 ((Fx64
*)cc
)[1] = hi
;
675 /* right microtile */
676 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
678 lohi
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
681 for (; k
>= 0; k
--) {
683 lolo
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
691 fxt1_quantize_ALPHA1 (GLuint
*cc
,
692 GLubyte input
[N_TEXELS
][MAX_COMP
])
694 const GLint n_vect
= 3; /* highest vector number in each microtile */
695 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
696 GLfloat vec
[1 + 1 + 1][MAX_COMP
]; /* 1.5 extrema for each sub-block */
697 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
699 Fx64 hi
; /* high quadword */
700 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
704 GLint minColL
= 0, maxColL
= 0;
705 GLint minColR
= 0, maxColR
= 0;
706 GLint sumL
= 0, sumR
= 0;
708 /* Our solution here is to find the darkest and brightest colors in
709 * the 4x4 tile and use those as the two representative colors.
710 * There are probably better algorithms to use (histogram-based).
713 while ((minColL
== maxColL
) && nn_comp
) {
714 minSum
= 2000; /* big enough */
715 maxSum
= -1; /* small enough */
716 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
718 for (i
= 0; i
< nn_comp
; i
++) {
736 while ((minColR
== maxColR
) && nn_comp
) {
737 minSum
= 2000; /* big enough */
738 maxSum
= -1; /* small enough */
739 for (k
= N_TEXELS
/ 2; k
< N_TEXELS
; k
++) {
741 for (i
= 0; i
< nn_comp
; i
++) {
758 /* choose the common vector (yuck!) */
761 GLint v1
= 0, v2
= 0;
762 GLfloat err
= 1e9
; /* big enough */
763 GLfloat tv
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
764 for (i
= 0; i
< n_comp
; i
++) {
765 tv
[0][i
] = input
[minColL
][i
];
766 tv
[1][i
] = input
[maxColL
][i
];
767 tv
[2][i
] = input
[minColR
][i
];
768 tv
[3][i
] = input
[maxColR
][i
];
770 for (j1
= 0; j1
< 2; j1
++) {
771 for (j2
= 2; j2
< 4; j2
++) {
773 for (i
= 0; i
< n_comp
; i
++) {
774 e
+= (tv
[j1
][i
] - tv
[j2
][i
]) * (tv
[j1
][i
] - tv
[j2
][i
]);
783 for (i
= 0; i
< n_comp
; i
++) {
784 vec
[0][i
] = tv
[1 - v1
][i
];
785 vec
[1][i
] = (tv
[v1
][i
] * sumL
+ tv
[v2
][i
] * sumR
) / (sumL
+ sumR
);
786 vec
[2][i
] = tv
[5 - v2
][i
];
792 if (minColL
!= maxColL
) {
793 /* compute interpolation vector */
794 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
798 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
800 /* interpolate color */
801 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
810 /* right microtile */
812 if (minColR
!= maxColR
) {
813 /* compute interpolation vector */
814 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[1]);
818 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
820 /* interpolate color */
821 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
830 FX64_MOV32(hi
, 7); /* alpha = "011" + lerp = 1 */
831 for (j
= n_vect
- 1; j
>= 0; j
--) {
834 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
836 for (j
= n_vect
- 1; j
>= 0; j
--) {
837 for (i
= 0; i
< n_comp
- 1; i
++) {
840 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
843 ((Fx64
*)cc
)[1] = hi
;
848 fxt1_quantize_HI (GLuint
*cc
,
849 GLubyte input
[N_TEXELS
][MAX_COMP
],
850 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
852 const GLint n_vect
= 6; /* highest vector number */
853 const GLint n_comp
= 3; /* 3 components: R, G, B */
854 GLfloat b
= 0.0F
; /* phoudoin: silent compiler! */
855 GLfloat iv
[MAX_COMP
]; /* interpolation vector */
857 GLuint hihi
; /* high quadword: hi dword */
859 GLint minSum
= 2000; /* big enough */
860 GLint maxSum
= -1; /* small enough */
861 GLint minCol
= 0; /* phoudoin: silent compiler! */
862 GLint maxCol
= 0; /* phoudoin: silent compiler! */
864 /* Our solution here is to find the darkest and brightest colors in
865 * the 8x4 tile and use those as the two representative colors.
866 * There are probably better algorithms to use (histogram-based).
868 for (k
= 0; k
< n
; k
++) {
870 for (i
= 0; i
< n_comp
; i
++) {
883 hihi
= 0; /* cc-hi = "00" */
884 for (i
= 0; i
< n_comp
; i
++) {
887 hihi
|= reord
[maxCol
][i
] >> 3;
889 for (i
= 0; i
< n_comp
; i
++) {
892 hihi
|= reord
[minCol
][i
] >> 3;
895 cc
[0] = cc
[1] = cc
[2] = 0;
897 /* compute interpolation vector */
898 if (minCol
!= maxCol
) {
899 MAKEIVEC(n_vect
, n_comp
, iv
, b
, reord
[minCol
], reord
[maxCol
]);
903 for (k
= N_TEXELS
- 1; k
>= 0; k
--) {
905 GLuint
*kk
= (GLuint
*)((char *)cc
+ t
/ 8);
906 GLint texel
= n_vect
+ 1; /* transparent black */
908 if (!ISTBLACK(input
[k
])) {
909 if (minCol
!= maxCol
) {
910 /* interpolate color */
911 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
913 kk
[0] |= texel
<< (t
& 7);
917 kk
[0] |= texel
<< (t
& 7);
924 fxt1_quantize_MIXED1 (GLuint
*cc
,
925 GLubyte input
[N_TEXELS
][MAX_COMP
])
927 const GLint n_vect
= 2; /* highest vector number in each microtile */
928 const GLint n_comp
= 3; /* 3 components: R, G, B */
929 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
930 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
932 Fx64 hi
; /* high quadword */
933 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
937 GLint minColL
= 0, maxColL
= -1;
938 GLint minColR
= 0, maxColR
= -1;
940 /* Our solution here is to find the darkest and brightest colors in
941 * the 4x4 tile and use those as the two representative colors.
942 * There are probably better algorithms to use (histogram-based).
944 minSum
= 2000; /* big enough */
945 maxSum
= -1; /* small enough */
946 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
947 if (!ISTBLACK(input
[k
])) {
949 for (i
= 0; i
< n_comp
; i
++) {
962 minSum
= 2000; /* big enough */
963 maxSum
= -1; /* small enough */
964 for (; k
< N_TEXELS
; k
++) {
965 if (!ISTBLACK(input
[k
])) {
967 for (i
= 0; i
< n_comp
; i
++) {
983 /* all transparent black */
985 for (i
= 0; i
< n_comp
; i
++) {
991 for (i
= 0; i
< n_comp
; i
++) {
992 vec
[0][i
] = input
[minColL
][i
];
993 vec
[1][i
] = input
[maxColL
][i
];
995 if (minColL
!= maxColL
) {
996 /* compute interpolation vector */
997 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1001 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1002 GLint texel
= n_vect
+ 1; /* transparent black */
1003 if (!ISTBLACK(input
[k
])) {
1004 /* interpolate color */
1005 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1015 /* right microtile */
1016 if (maxColR
== -1) {
1017 /* all transparent black */
1019 for (i
= 0; i
< n_comp
; i
++) {
1025 for (i
= 0; i
< n_comp
; i
++) {
1026 vec
[2][i
] = input
[minColR
][i
];
1027 vec
[3][i
] = input
[maxColR
][i
];
1029 if (minColR
!= maxColR
) {
1030 /* compute interpolation vector */
1031 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1035 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1036 GLint texel
= n_vect
+ 1; /* transparent black */
1037 if (!ISTBLACK(input
[k
])) {
1038 /* interpolate color */
1039 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1049 FX64_MOV32(hi
, 9 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1050 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1051 for (i
= 0; i
< n_comp
; i
++) {
1054 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1057 ((Fx64
*)cc
)[1] = hi
;
1062 fxt1_quantize_MIXED0 (GLuint
*cc
,
1063 GLubyte input
[N_TEXELS
][MAX_COMP
])
1065 const GLint n_vect
= 3; /* highest vector number in each microtile */
1066 const GLint n_comp
= 3; /* 3 components: R, G, B */
1067 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
1068 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
1070 Fx64 hi
; /* high quadword */
1071 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
1073 GLint minColL
= 0, maxColL
= 0;
1074 GLint minColR
= 0, maxColR
= 0;
1079 /* Our solution here is to find the darkest and brightest colors in
1080 * the 4x4 tile and use those as the two representative colors.
1081 * There are probably better algorithms to use (histogram-based).
1083 minSum
= 2000; /* big enough */
1084 maxSum
= -1; /* small enough */
1085 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1087 for (i
= 0; i
< n_comp
; i
++) {
1099 minSum
= 2000; /* big enough */
1100 maxSum
= -1; /* small enough */
1101 for (; k
< N_TEXELS
; k
++) {
1103 for (i
= 0; i
< n_comp
; i
++) {
1118 GLint maxVarL
= fxt1_variance(NULL
, input
, n_comp
, N_TEXELS
/ 2);
1119 GLint maxVarR
= fxt1_variance(NULL
, &input
[N_TEXELS
/ 2], n_comp
, N_TEXELS
/ 2);
1121 /* Scan the channel with max variance for lo & hi
1122 * and use those as the two representative colors.
1124 minVal
= 2000; /* big enough */
1125 maxVal
= -1; /* small enough */
1126 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1127 GLint t
= input
[k
][maxVarL
];
1137 minVal
= 2000; /* big enough */
1138 maxVal
= -1; /* small enough */
1139 for (; k
< N_TEXELS
; k
++) {
1140 GLint t
= input
[k
][maxVarR
];
1152 /* left microtile */
1154 for (i
= 0; i
< n_comp
; i
++) {
1155 vec
[0][i
] = input
[minColL
][i
];
1156 vec
[1][i
] = input
[maxColL
][i
];
1158 if (minColL
!= maxColL
) {
1159 /* compute interpolation vector */
1160 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1164 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1166 /* interpolate color */
1167 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1173 /* funky encoding for LSB of green */
1174 if ((GLint
)((lolo
>> 1) & 1) != (((vec
[1][GCOMP
] ^ vec
[0][GCOMP
]) >> 2) & 1)) {
1175 for (i
= 0; i
< n_comp
; i
++) {
1176 vec
[1][i
] = input
[minColL
][i
];
1177 vec
[0][i
] = input
[maxColL
][i
];
1185 /* right microtile */
1187 for (i
= 0; i
< n_comp
; i
++) {
1188 vec
[2][i
] = input
[minColR
][i
];
1189 vec
[3][i
] = input
[maxColR
][i
];
1191 if (minColR
!= maxColR
) {
1192 /* compute interpolation vector */
1193 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1197 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1199 /* interpolate color */
1200 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1206 /* funky encoding for LSB of green */
1207 if ((GLint
)((lohi
>> 1) & 1) != (((vec
[3][GCOMP
] ^ vec
[2][GCOMP
]) >> 2) & 1)) {
1208 for (i
= 0; i
< n_comp
; i
++) {
1209 vec
[3][i
] = input
[minColR
][i
];
1210 vec
[2][i
] = input
[maxColR
][i
];
1218 FX64_MOV32(hi
, 8 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1219 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1220 for (i
= 0; i
< n_comp
; i
++) {
1223 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1226 ((Fx64
*)cc
)[1] = hi
;
1231 fxt1_quantize (GLuint
*cc
, const GLubyte
*lines
[], GLint comps
)
1234 GLubyte reord
[N_TEXELS
][MAX_COMP
];
1236 GLubyte input
[N_TEXELS
][MAX_COMP
];
1240 /* make the whole block opaque */
1241 _mesa_memset(input
, -1, sizeof(input
));
1244 /* 8 texels each line */
1245 for (l
= 0; l
< 4; l
++) {
1246 for (k
= 0; k
< 4; k
++) {
1247 for (i
= 0; i
< comps
; i
++) {
1248 input
[k
+ l
* 4][i
] = *lines
[l
]++;
1251 for (; k
< 8; k
++) {
1252 for (i
= 0; i
< comps
; i
++) {
1253 input
[k
+ l
* 4 + 12][i
] = *lines
[l
]++;
1259 * 00, 01, 02, 03, 08, 09, 0a, 0b
1260 * 10, 11, 12, 13, 18, 19, 1a, 1b
1261 * 04, 05, 06, 07, 0c, 0d, 0e, 0f
1262 * 14, 15, 16, 17, 1c, 1d, 1e, 1f
1266 * stupidity flows forth from this
1271 /* skip all transparent black texels */
1273 for (k
= 0; k
< N_TEXELS
; k
++) {
1274 /* test all components against 0 */
1275 if (!ISTBLACK(input
[k
])) {
1276 /* texel is not transparent black */
1277 COPY_4UBV(reord
[l
], input
[k
]);
1278 if (reord
[l
][ACOMP
] < (255 - ALPHA_TS
)) {
1279 /* non-opaque texel */
1289 fxt1_quantize_ALPHA0(cc
, input
, reord
, l
);
1290 } else if (l
== 0) {
1291 cc
[0] = cc
[1] = cc
[2] = -1;
1293 } else if (l
< N_TEXELS
) {
1294 fxt1_quantize_HI(cc
, input
, reord
, l
);
1296 fxt1_quantize_CHROMA(cc
, input
);
1298 (void)fxt1_quantize_ALPHA1
;
1299 (void)fxt1_quantize_MIXED1
;
1300 (void)fxt1_quantize_MIXED0
;
1303 fxt1_quantize_ALPHA1(cc
, input
);
1304 } else if (l
== 0) {
1305 cc
[0] = cc
[1] = cc
[2] = ~0u;
1307 } else if (l
< N_TEXELS
) {
1308 fxt1_quantize_MIXED1(cc
, input
);
1310 fxt1_quantize_MIXED0(cc
, input
);
1312 (void)fxt1_quantize_ALPHA0
;
1313 (void)fxt1_quantize_HI
;
1314 (void)fxt1_quantize_CHROMA
;
1320 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
1321 const void *source
, GLint srcRowStride
,
1322 void *dest
, GLint destRowStride
)
1325 const GLubyte
*data
;
1326 GLuint
*encoded
= (GLuint
*)dest
;
1327 void *newSource
= NULL
;
1329 assert(comps
== 3 || comps
== 4);
1331 /* Replicate image if width is not M8 or height is not M4 */
1332 if ((width
& 7) | (height
& 3)) {
1333 GLint newWidth
= (width
+ 7) & ~7;
1334 GLint newHeight
= (height
+ 3) & ~3;
1335 newSource
= _mesa_malloc(comps
* newWidth
* newHeight
* sizeof(GLchan
));
1337 GET_CURRENT_CONTEXT(ctx
);
1338 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1341 _mesa_upscale_teximage2d(width
, height
, newWidth
, newHeight
,
1342 comps
, (const GLchan
*) source
,
1343 srcRowStride
, (GLchan
*) newSource
);
1347 srcRowStride
= comps
* newWidth
;
1350 /* convert from 16/32-bit channels to GLubyte if needed */
1351 if (CHAN_TYPE
!= GL_UNSIGNED_BYTE
) {
1352 const GLuint n
= width
* height
* comps
;
1353 const GLchan
*src
= (const GLchan
*) source
;
1354 GLubyte
*dest
= (GLubyte
*) _mesa_malloc(n
* sizeof(GLubyte
));
1357 GET_CURRENT_CONTEXT(ctx
);
1358 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1361 for (i
= 0; i
< n
; i
++) {
1362 dest
[i
] = CHAN_TO_UBYTE(src
[i
]);
1364 if (newSource
!= NULL
) {
1365 _mesa_free(newSource
);
1367 newSource
= dest
; /* we'll free this buffer before returning */
1368 source
= dest
; /* the new, GLubyte incoming image */
1371 data
= (const GLubyte
*) source
;
1372 destRowStride
= (destRowStride
- width
* 2) / 4;
1373 for (y
= 0; y
< height
; y
+= 4) {
1374 GLuint offs
= 0 + (y
+ 0) * srcRowStride
;
1375 for (x
= 0; x
< width
; x
+= 8) {
1376 const GLubyte
*lines
[4];
1377 lines
[0] = &data
[offs
];
1378 lines
[1] = lines
[0] + srcRowStride
;
1379 lines
[2] = lines
[1] + srcRowStride
;
1380 lines
[3] = lines
[2] + srcRowStride
;
1382 fxt1_quantize(encoded
, lines
, comps
);
1383 /* 128 bits per 8x4 block */
1386 encoded
+= destRowStride
;
1390 if (newSource
!= NULL
) {
1391 _mesa_free(newSource
);
1396 /***************************************************************************\
1399 * The decoder is based on GL_3DFX_texture_compression_FXT1
1400 * specification and serves as a concept for the encoder.
1401 \***************************************************************************/
1404 /* lookup table for scaling 5 bit colors up to 8 bits */
1405 static const GLubyte _rgb_scale_5
[] = {
1406 0, 8, 16, 25, 33, 41, 49, 58,
1407 66, 74, 82, 90, 99, 107, 115, 123,
1408 132, 140, 148, 156, 165, 173, 181, 189,
1409 197, 206, 214, 222, 230, 239, 247, 255
1412 /* lookup table for scaling 6 bit colors up to 8 bits */
1413 static const GLubyte _rgb_scale_6
[] = {
1414 0, 4, 8, 12, 16, 20, 24, 28,
1415 32, 36, 40, 45, 49, 53, 57, 61,
1416 65, 69, 73, 77, 81, 85, 89, 93,
1417 97, 101, 105, 109, 113, 117, 121, 125,
1418 130, 134, 138, 142, 146, 150, 154, 158,
1419 162, 166, 170, 174, 178, 182, 186, 190,
1420 194, 198, 202, 206, 210, 215, 219, 223,
1421 227, 231, 235, 239, 243, 247, 251, 255
1425 #define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
1426 #define UP5(c) _rgb_scale_5[(c) & 31]
1427 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
1428 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
1432 fxt1_decode_1HI (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1437 cc
= (const GLuint
*)(code
+ t
/ 8);
1438 t
= (cc
[0] >> (t
& 7)) & 7;
1441 rgba
[RCOMP
] = rgba
[GCOMP
] = rgba
[BCOMP
] = rgba
[ACOMP
] = 0;
1444 cc
= (const GLuint
*)(code
+ 12);
1446 b
= UP5(CC_SEL(cc
, 0));
1447 g
= UP5(CC_SEL(cc
, 5));
1448 r
= UP5(CC_SEL(cc
, 10));
1449 } else if (t
== 6) {
1450 b
= UP5(CC_SEL(cc
, 15));
1451 g
= UP5(CC_SEL(cc
, 20));
1452 r
= UP5(CC_SEL(cc
, 25));
1454 b
= LERP(6, t
, UP5(CC_SEL(cc
, 0)), UP5(CC_SEL(cc
, 15)));
1455 g
= LERP(6, t
, UP5(CC_SEL(cc
, 5)), UP5(CC_SEL(cc
, 20)));
1456 r
= LERP(6, t
, UP5(CC_SEL(cc
, 10)), UP5(CC_SEL(cc
, 25)));
1458 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1459 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1460 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1461 rgba
[ACOMP
] = CHAN_MAX
;
1467 fxt1_decode_1CHROMA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1472 cc
= (const GLuint
*)code
;
1477 t
= (cc
[0] >> (t
* 2)) & 3;
1480 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1481 kk
= cc
[0] >> (t
& 7);
1482 rgba
[BCOMP
] = UBYTE_TO_CHAN( UP5(kk
) );
1483 rgba
[GCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 5) );
1484 rgba
[RCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 10) );
1485 rgba
[ACOMP
] = CHAN_MAX
;
1490 fxt1_decode_1MIXED (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1496 cc
= (const GLuint
*)code
;
1499 t
= (cc
[1] >> (t
* 2)) & 3;
1501 col
[0][BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1502 col
[0][GCOMP
] = CC_SEL(cc
, 99);
1503 col
[0][RCOMP
] = CC_SEL(cc
, 104);
1505 col
[1][BCOMP
] = CC_SEL(cc
, 109);
1506 col
[1][GCOMP
] = CC_SEL(cc
, 114);
1507 col
[1][RCOMP
] = CC_SEL(cc
, 119);
1508 glsb
= CC_SEL(cc
, 126);
1509 selb
= CC_SEL(cc
, 33);
1511 t
= (cc
[0] >> (t
* 2)) & 3;
1513 col
[0][BCOMP
] = CC_SEL(cc
, 64);
1514 col
[0][GCOMP
] = CC_SEL(cc
, 69);
1515 col
[0][RCOMP
] = CC_SEL(cc
, 74);
1517 col
[1][BCOMP
] = CC_SEL(cc
, 79);
1518 col
[1][GCOMP
] = CC_SEL(cc
, 84);
1519 col
[1][RCOMP
] = CC_SEL(cc
, 89);
1520 glsb
= CC_SEL(cc
, 125);
1521 selb
= CC_SEL(cc
, 1);
1524 if (CC_SEL(cc
, 124) & 1) {
1529 rgba
[RCOMP
] = rgba
[BCOMP
] = rgba
[GCOMP
] = rgba
[ACOMP
] = 0;
1533 b
= UP5(col
[0][BCOMP
]);
1534 g
= UP5(col
[0][GCOMP
]);
1535 r
= UP5(col
[0][RCOMP
]);
1536 } else if (t
== 2) {
1537 b
= UP5(col
[1][BCOMP
]);
1538 g
= UP6(col
[1][GCOMP
], glsb
);
1539 r
= UP5(col
[1][RCOMP
]);
1541 b
= (UP5(col
[0][BCOMP
]) + UP5(col
[1][BCOMP
])) / 2;
1542 g
= (UP5(col
[0][GCOMP
]) + UP6(col
[1][GCOMP
], glsb
)) / 2;
1543 r
= (UP5(col
[0][RCOMP
]) + UP5(col
[1][RCOMP
])) / 2;
1545 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1546 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1547 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1548 rgba
[ACOMP
] = CHAN_MAX
;
1554 b
= UP5(col
[0][BCOMP
]);
1555 g
= UP6(col
[0][GCOMP
], glsb
^ selb
);
1556 r
= UP5(col
[0][RCOMP
]);
1557 } else if (t
== 3) {
1558 b
= UP5(col
[1][BCOMP
]);
1559 g
= UP6(col
[1][GCOMP
], glsb
);
1560 r
= UP5(col
[1][RCOMP
]);
1562 b
= LERP(3, t
, UP5(col
[0][BCOMP
]), UP5(col
[1][BCOMP
]));
1563 g
= LERP(3, t
, UP6(col
[0][GCOMP
], glsb
^ selb
),
1564 UP6(col
[1][GCOMP
], glsb
));
1565 r
= LERP(3, t
, UP5(col
[0][RCOMP
]), UP5(col
[1][RCOMP
]));
1567 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1568 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1569 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1570 rgba
[ACOMP
] = CHAN_MAX
;
1576 fxt1_decode_1ALPHA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1581 cc
= (const GLuint
*)code
;
1582 if (CC_SEL(cc
, 124) & 1) {
1588 t
= (cc
[1] >> (t
* 2)) & 3;
1590 col0
[BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1591 col0
[GCOMP
] = CC_SEL(cc
, 99);
1592 col0
[RCOMP
] = CC_SEL(cc
, 104);
1593 col0
[ACOMP
] = CC_SEL(cc
, 119);
1595 t
= (cc
[0] >> (t
* 2)) & 3;
1597 col0
[BCOMP
] = CC_SEL(cc
, 64);
1598 col0
[GCOMP
] = CC_SEL(cc
, 69);
1599 col0
[RCOMP
] = CC_SEL(cc
, 74);
1600 col0
[ACOMP
] = CC_SEL(cc
, 109);
1604 b
= UP5(col0
[BCOMP
]);
1605 g
= UP5(col0
[GCOMP
]);
1606 r
= UP5(col0
[RCOMP
]);
1607 a
= UP5(col0
[ACOMP
]);
1608 } else if (t
== 3) {
1609 b
= UP5(CC_SEL(cc
, 79));
1610 g
= UP5(CC_SEL(cc
, 84));
1611 r
= UP5(CC_SEL(cc
, 89));
1612 a
= UP5(CC_SEL(cc
, 114));
1614 b
= LERP(3, t
, UP5(col0
[BCOMP
]), UP5(CC_SEL(cc
, 79)));
1615 g
= LERP(3, t
, UP5(col0
[GCOMP
]), UP5(CC_SEL(cc
, 84)));
1616 r
= LERP(3, t
, UP5(col0
[RCOMP
]), UP5(CC_SEL(cc
, 89)));
1617 a
= LERP(3, t
, UP5(col0
[ACOMP
]), UP5(CC_SEL(cc
, 114)));
1626 t
= (cc
[0] >> (t
* 2)) & 3;
1633 cc
= (const GLuint
*)code
;
1634 a
= UP5(cc
[3] >> (t
* 5 + 13));
1636 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1637 kk
= cc
[0] >> (t
& 7);
1643 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1644 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1645 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1646 rgba
[ACOMP
] = UBYTE_TO_CHAN(a
);
1651 fxt1_decode_1 (const void *texture
, GLint stride
, /* in pixels */
1652 GLint i
, GLint j
, GLchan
*rgba
)
1654 static void (*decode_1
[]) (const GLubyte
*, GLint
, GLchan
*) = {
1655 fxt1_decode_1HI
, /* cc-high = "00?" */
1656 fxt1_decode_1HI
, /* cc-high = "00?" */
1657 fxt1_decode_1CHROMA
, /* cc-chroma = "010" */
1658 fxt1_decode_1ALPHA
, /* alpha = "011" */
1659 fxt1_decode_1MIXED
, /* mixed = "1??" */
1660 fxt1_decode_1MIXED
, /* mixed = "1??" */
1661 fxt1_decode_1MIXED
, /* mixed = "1??" */
1662 fxt1_decode_1MIXED
/* mixed = "1??" */
1665 const GLubyte
*code
= (const GLubyte
*)texture
+
1666 ((j
/ 4) * (stride
/ 8) + (i
/ 8)) * 16;
1667 GLint mode
= CC_SEL(code
, 125);
1675 decode_1
[mode
](code
, t
, rgba
);