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 "texformat.h"
45 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
46 const void *source
, GLint srcRowStride
,
47 void *dest
, GLint destRowStride
);
50 fxt1_decode_1 (const void *texture
, GLint stride
,
51 GLint i
, GLint j
, GLchan
*rgba
);
55 * Called during context initialization.
58 _mesa_init_texture_fxt1( GLcontext
*ctx
)
65 * Called via TexFormat->StoreImage to store an RGB_FXT1 texture.
68 texstore_rgb_fxt1(TEXSTORE_PARAMS
)
73 const GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
74 const GLchan
*tempImage
= NULL
;
76 ASSERT(dstFormat
== &_mesa_texformat_rgb_fxt1
);
77 ASSERT(dstXoffset
% 8 == 0);
78 ASSERT(dstYoffset
% 4 == 0);
79 ASSERT(dstZoffset
== 0);
81 (void) dstImageOffsets
;
83 if (srcFormat
!= GL_RGB
||
84 srcType
!= CHAN_TYPE
||
85 ctx
->_ImageTransferState
||
86 srcPacking
->SwapBytes
) {
87 /* convert image to RGB/GLchan */
88 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
90 dstFormat
->BaseFormat
,
91 srcWidth
, srcHeight
, srcDepth
,
92 srcFormat
, srcType
, srcAddr
,
95 return GL_FALSE
; /* out of memory */
96 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
98 srcRowStride
= 3 * srcWidth
;
102 pixels
= (const GLchan
*) srcAddr
;
103 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
104 srcType
) / sizeof(GLchan
);
107 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
108 dstFormat
->MesaFormat
,
109 texWidth
, (GLubyte
*) dstAddr
);
111 fxt1_encode(srcWidth
, srcHeight
, 3, pixels
, srcRowStride
,
115 _mesa_free((void*) tempImage
);
122 * Called via TexFormat->StoreImage to store an RGBA_FXT1 texture.
125 texstore_rgba_fxt1(TEXSTORE_PARAMS
)
127 const GLchan
*pixels
;
130 GLint texWidth
= dstRowStride
* 8 / 16; /* a bit of a hack */
131 const GLchan
*tempImage
= NULL
;
133 ASSERT(dstFormat
== &_mesa_texformat_rgba_fxt1
);
134 ASSERT(dstXoffset
% 8 == 0);
135 ASSERT(dstYoffset
% 4 == 0);
136 ASSERT(dstZoffset
== 0);
138 (void) dstImageOffsets
;
140 if (srcFormat
!= GL_RGBA
||
141 srcType
!= CHAN_TYPE
||
142 ctx
->_ImageTransferState
||
143 srcPacking
->SwapBytes
) {
144 /* convert image to RGBA/GLchan */
145 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
147 dstFormat
->BaseFormat
,
148 srcWidth
, srcHeight
, srcDepth
,
149 srcFormat
, srcType
, srcAddr
,
152 return GL_FALSE
; /* out of memory */
153 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
155 srcRowStride
= 4 * srcWidth
;
159 pixels
= (const GLchan
*) srcAddr
;
160 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
161 srcType
) / sizeof(GLchan
);
164 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
165 dstFormat
->MesaFormat
,
166 texWidth
, (GLubyte
*) dstAddr
);
168 fxt1_encode(srcWidth
, srcHeight
, 4, pixels
, srcRowStride
,
172 _mesa_free((void*) tempImage
);
179 fetch_texel_2d_rgba_fxt1( const struct gl_texture_image
*texImage
,
180 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
183 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, texel
);
188 fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image
*texImage
,
189 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
191 /* just sample as GLchan and convert to float here */
194 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
195 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
196 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
197 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
198 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
203 fetch_texel_2d_rgb_fxt1( const struct gl_texture_image
*texImage
,
204 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
207 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, texel
);
213 fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image
*texImage
,
214 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
216 /* just sample as GLchan and convert to float here */
219 fxt1_decode_1(texImage
->Data
, texImage
->RowStride
, i
, j
, rgba
);
220 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
221 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
222 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
228 const struct gl_texture_format _mesa_texformat_rgb_fxt1
= {
229 MESA_FORMAT_RGB_FXT1
, /* MesaFormat */
230 GL_RGB
, /* BaseFormat */
231 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
232 4, /*approx*/ /* RedBits */
233 4, /*approx*/ /* GreenBits */
234 4, /*approx*/ /* BlueBits */
236 0, /* LuminanceBits */
237 0, /* IntensityBits */
242 texstore_rgb_fxt1
, /* StoreTexImageFunc */
243 NULL
, /*impossible*/ /* FetchTexel1D */
244 fetch_texel_2d_rgb_fxt1
, /* FetchTexel2D */
245 NULL
, /*impossible*/ /* FetchTexel3D */
246 NULL
, /*impossible*/ /* FetchTexel1Df */
247 fetch_texel_2d_f_rgb_fxt1
, /* FetchTexel2Df */
248 NULL
, /*impossible*/ /* FetchTexel3Df */
249 NULL
/* StoreTexel */
252 const struct gl_texture_format _mesa_texformat_rgba_fxt1
= {
253 MESA_FORMAT_RGBA_FXT1
, /* MesaFormat */
254 GL_RGBA
, /* BaseFormat */
255 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
256 4, /*approx*/ /* RedBits */
257 4, /*approx*/ /* GreenBits */
258 4, /*approx*/ /* BlueBits */
259 1, /*approx*/ /* AlphaBits */
260 0, /* LuminanceBits */
261 0, /* IntensityBits */
266 texstore_rgba_fxt1
, /* StoreTexImageFunc */
267 NULL
, /*impossible*/ /* FetchTexel1D */
268 fetch_texel_2d_rgba_fxt1
, /* FetchTexel2D */
269 NULL
, /*impossible*/ /* FetchTexel3D */
270 NULL
, /*impossible*/ /* FetchTexel1Df */
271 fetch_texel_2d_f_rgba_fxt1
, /* FetchTexel2Df */
272 NULL
, /*impossible*/ /* FetchTexel3Df */
273 NULL
/* StoreTexel */
277 /***************************************************************************\
280 * The encoder was built by reversing the decoder,
281 * and is vaguely based on Texus2 by 3dfx. Note that this code
282 * is merely a proof of concept, since it is highly UNoptimized;
283 * moreover, it is sub-optimal due to initial conditions passed
284 * to Lloyd's algorithm (the interpolation modes are even worse).
285 \***************************************************************************/
288 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
289 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
290 #define N_TEXELS 32 /* number of texels in a block (always 32) */
291 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
292 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
293 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
294 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
295 #define ISTBLACK(v) (*((GLuint *)(v)) == 0)
299 * Define a 64-bit unsigned integer type and macros
303 #define FX64_NATIVE 1
305 typedef uint64_t Fx64
;
307 #define FX64_MOV32(a, b) a = b
308 #define FX64_OR32(a, b) a |= b
309 #define FX64_SHL(a, c) a <<= c
313 #define FX64_NATIVE 0
319 #define FX64_MOV32(a, b) a.lo = b
320 #define FX64_OR32(a, b) a.lo |= b
322 #define FX64_SHL(a, c) \
325 a.hi = a.lo << ((c) - 32); \
328 a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
336 #define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
337 #define SAFECDOT 1 /* for paranoids */
339 #define MAKEIVEC(NV, NC, IV, B, V0, V1) \
341 /* compute interpolation vector */ \
345 for (i = 0; i < NC; i++) { \
346 IV[i] = (V1[i] - V0[i]) * F(i); \
347 d2 += IV[i] * IV[i]; \
349 rd2 = (GLfloat)NV / d2; \
351 for (i = 0; i < NC; i++) { \
353 B -= IV[i] * V0[i]; \
356 B = B * rd2 + 0.5f; \
359 #define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
361 GLfloat dot = 0.0F; \
362 for (i = 0; i < NC; i++) { \
363 dot += V[i] * IV[i]; \
365 TEXEL = (GLint)(dot + B); \
369 } else if (TEXEL > NV) { \
377 fxt1_bestcol (GLfloat vec
[][MAX_COMP
], GLint nv
,
378 GLubyte input
[MAX_COMP
], GLint nc
)
380 GLint i
, j
, best
= -1;
381 GLfloat err
= 1e9
; /* big enough */
383 for (j
= 0; j
< nv
; j
++) {
385 for (i
= 0; i
< nc
; i
++) {
386 e
+= (vec
[j
][i
] - input
[i
]) * (vec
[j
][i
] - input
[i
]);
399 fxt1_worst (GLfloat vec
[MAX_COMP
],
400 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
402 GLint i
, k
, worst
= -1;
403 GLfloat err
= -1.0F
; /* small enough */
405 for (k
= 0; k
< n
; k
++) {
407 for (i
= 0; i
< nc
; i
++) {
408 e
+= (vec
[i
] - input
[k
][i
]) * (vec
[i
] - input
[k
][i
]);
421 fxt1_variance (GLdouble variance
[MAX_COMP
],
422 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
424 GLint i
, k
, best
= 0;
426 GLdouble var
, maxvar
= -1; /* small enough */
427 GLdouble teenth
= 1.0 / n
;
429 for (i
= 0; i
< nc
; i
++) {
431 for (k
= 0; k
< n
; k
++) {
432 GLint t
= input
[k
][i
];
436 var
= sx2
* teenth
- sx
* sx
* teenth
* teenth
;
451 fxt1_choose (GLfloat vec
[][MAX_COMP
], GLint nv
,
452 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
455 /* Choose colors from a grid.
459 for (j
= 0; j
< nv
; j
++) {
460 GLint m
= j
* (n
- 1) / (nv
- 1);
461 for (i
= 0; i
< nc
; i
++) {
462 vec
[j
][i
] = input
[m
][i
];
466 /* Our solution here is to find the darkest and brightest colors in
467 * the 8x4 tile and use those as the two representative colors.
468 * There are probably better algorithms to use (histogram-based).
471 GLint minSum
= 2000; /* big enough */
472 GLint maxSum
= -1; /* small enough */
473 GLint minCol
= 0; /* phoudoin: silent compiler! */
474 GLint maxCol
= 0; /* phoudoin: silent compiler! */
484 _mesa_memset(hist
, 0, sizeof(hist
));
486 for (k
= 0; k
< n
; k
++) {
490 for (i
= 0; i
< nc
; i
++) {
495 for (l
= 0; l
< n
; l
++) {
504 } else if (hist
[l
].key
== key
) {
520 for (j
= 0; j
< lenh
; j
++) {
521 for (i
= 0; i
< nc
; i
++) {
522 vec
[j
][i
] = (GLfloat
)input
[hist
[j
].idx
][i
];
525 for (; j
< nv
; j
++) {
526 for (i
= 0; i
< nc
; i
++) {
527 vec
[j
][i
] = vec
[0][i
];
533 for (j
= 0; j
< nv
; j
++) {
534 for (i
= 0; i
< nc
; i
++) {
535 vec
[j
][i
] = ((nv
- 1 - j
) * input
[minCol
][i
] + j
* input
[maxCol
][i
] + (nv
- 1) / 2) / (GLfloat
)(nv
- 1);
545 fxt1_lloyd (GLfloat vec
[][MAX_COMP
], GLint nv
,
546 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
548 /* Use the generalized lloyd's algorithm for VQ:
549 * find 4 color vectors.
551 * for each sample color
552 * sort to nearest vector.
554 * replace each vector with the centroid of it's matching colors.
556 * repeat until RMS doesn't improve.
558 * if a color vector has no samples, or becomes the same as another
559 * vector, replace it with the color which is farthest from a sample.
561 * vec[][MAX_COMP] initial vectors and resulting colors
562 * nv number of resulting colors required
563 * input[N_TEXELS][MAX_COMP] input texels
564 * nc number of components in input / vec
565 * n number of input samples
568 GLint sum
[MAX_VECT
][MAX_COMP
]; /* used to accumulate closest texels */
569 GLint cnt
[MAX_VECT
]; /* how many times a certain vector was chosen */
570 GLfloat error
, lasterror
= 1e9
;
575 for (rep
= 0; rep
< LL_N_REP
; rep
++) {
576 /* reset sums & counters */
577 for (j
= 0; j
< nv
; j
++) {
578 for (i
= 0; i
< nc
; i
++) {
585 /* scan whole block */
586 for (k
= 0; k
< n
; k
++) {
589 GLfloat err
= 1e9
; /* big enough */
590 /* determine best vector */
591 for (j
= 0; j
< nv
; j
++) {
592 GLfloat e
= (vec
[j
][0] - input
[k
][0]) * (vec
[j
][0] - input
[k
][0]) +
593 (vec
[j
][1] - input
[k
][1]) * (vec
[j
][1] - input
[k
][1]) +
594 (vec
[j
][2] - input
[k
][2]) * (vec
[j
][2] - input
[k
][2]);
596 e
+= (vec
[j
][3] - input
[k
][3]) * (vec
[j
][3] - input
[k
][3]);
604 GLint best
= fxt1_bestcol(vec
, nv
, input
[k
], nc
, &err
);
606 /* add in closest color */
607 for (i
= 0; i
< nc
; i
++) {
608 sum
[best
][i
] += input
[k
][i
];
610 /* mark this vector as used */
612 /* accumulate error */
617 if ((error
< LL_RMS_E
) ||
618 ((error
< lasterror
) && ((lasterror
- error
) < LL_RMS_D
))) {
619 return !0; /* good match */
623 /* move each vector to the barycenter of its closest colors */
624 for (j
= 0; j
< nv
; j
++) {
626 GLfloat div
= 1.0F
/ cnt
[j
];
627 for (i
= 0; i
< nc
; i
++) {
628 vec
[j
][i
] = div
* sum
[j
][i
];
631 /* this vec has no samples or is identical with a previous vec */
632 GLint worst
= fxt1_worst(vec
[j
], input
, nc
, n
);
633 for (i
= 0; i
< nc
; i
++) {
634 vec
[j
][i
] = input
[worst
][i
];
640 return 0; /* could not converge fast enough */
645 fxt1_quantize_CHROMA (GLuint
*cc
,
646 GLubyte input
[N_TEXELS
][MAX_COMP
])
648 const GLint n_vect
= 4; /* 4 base vectors to find */
649 const GLint n_comp
= 3; /* 3 components: R, G, B */
650 GLfloat vec
[MAX_VECT
][MAX_COMP
];
652 Fx64 hi
; /* high quadword */
653 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
655 if (fxt1_choose(vec
, n_vect
, input
, n_comp
, N_TEXELS
) != 0) {
656 fxt1_lloyd(vec
, n_vect
, input
, n_comp
, N_TEXELS
);
659 FX64_MOV32(hi
, 4); /* cc-chroma = "010" + unused bit */
660 for (j
= n_vect
- 1; j
>= 0; j
--) {
661 for (i
= 0; i
< n_comp
; i
++) {
664 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
667 ((Fx64
*)cc
)[1] = hi
;
670 /* right microtile */
671 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
673 lohi
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
676 for (; k
>= 0; k
--) {
678 lolo
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
686 fxt1_quantize_ALPHA0 (GLuint
*cc
,
687 GLubyte input
[N_TEXELS
][MAX_COMP
],
688 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
690 const GLint n_vect
= 3; /* 3 base vectors to find */
691 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
692 GLfloat vec
[MAX_VECT
][MAX_COMP
];
694 Fx64 hi
; /* high quadword */
695 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
697 /* the last vector indicates zero */
698 for (i
= 0; i
< n_comp
; i
++) {
702 /* the first n texels in reord are guaranteed to be non-zero */
703 if (fxt1_choose(vec
, n_vect
, reord
, n_comp
, n
) != 0) {
704 fxt1_lloyd(vec
, n_vect
, reord
, n_comp
, n
);
707 FX64_MOV32(hi
, 6); /* alpha = "011" + lerp = 0 */
708 for (j
= n_vect
- 1; j
>= 0; j
--) {
711 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
713 for (j
= n_vect
- 1; j
>= 0; j
--) {
714 for (i
= 0; i
< n_comp
- 1; i
++) {
717 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
720 ((Fx64
*)cc
)[1] = hi
;
723 /* right microtile */
724 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
726 lohi
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
729 for (; k
>= 0; k
--) {
731 lolo
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
739 fxt1_quantize_ALPHA1 (GLuint
*cc
,
740 GLubyte input
[N_TEXELS
][MAX_COMP
])
742 const GLint n_vect
= 3; /* highest vector number in each microtile */
743 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
744 GLfloat vec
[1 + 1 + 1][MAX_COMP
]; /* 1.5 extrema for each sub-block */
745 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
747 Fx64 hi
; /* high quadword */
748 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
752 GLint minColL
= 0, maxColL
= 0;
753 GLint minColR
= 0, maxColR
= 0;
754 GLint sumL
= 0, sumR
= 0;
756 /* Our solution here is to find the darkest and brightest colors in
757 * the 4x4 tile and use those as the two representative colors.
758 * There are probably better algorithms to use (histogram-based).
761 while ((minColL
== maxColL
) && nn_comp
) {
762 minSum
= 2000; /* big enough */
763 maxSum
= -1; /* small enough */
764 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
766 for (i
= 0; i
< nn_comp
; i
++) {
784 while ((minColR
== maxColR
) && nn_comp
) {
785 minSum
= 2000; /* big enough */
786 maxSum
= -1; /* small enough */
787 for (k
= N_TEXELS
/ 2; k
< N_TEXELS
; k
++) {
789 for (i
= 0; i
< nn_comp
; i
++) {
806 /* choose the common vector (yuck!) */
809 GLint v1
= 0, v2
= 0;
810 GLfloat err
= 1e9
; /* big enough */
811 GLfloat tv
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
812 for (i
= 0; i
< n_comp
; i
++) {
813 tv
[0][i
] = input
[minColL
][i
];
814 tv
[1][i
] = input
[maxColL
][i
];
815 tv
[2][i
] = input
[minColR
][i
];
816 tv
[3][i
] = input
[maxColR
][i
];
818 for (j1
= 0; j1
< 2; j1
++) {
819 for (j2
= 2; j2
< 4; j2
++) {
821 for (i
= 0; i
< n_comp
; i
++) {
822 e
+= (tv
[j1
][i
] - tv
[j2
][i
]) * (tv
[j1
][i
] - tv
[j2
][i
]);
831 for (i
= 0; i
< n_comp
; i
++) {
832 vec
[0][i
] = tv
[1 - v1
][i
];
833 vec
[1][i
] = (tv
[v1
][i
] * sumL
+ tv
[v2
][i
] * sumR
) / (sumL
+ sumR
);
834 vec
[2][i
] = tv
[5 - v2
][i
];
840 if (minColL
!= maxColL
) {
841 /* compute interpolation vector */
842 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
846 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
848 /* interpolate color */
849 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
858 /* right microtile */
860 if (minColR
!= maxColR
) {
861 /* compute interpolation vector */
862 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[1]);
866 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
868 /* interpolate color */
869 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
878 FX64_MOV32(hi
, 7); /* alpha = "011" + lerp = 1 */
879 for (j
= n_vect
- 1; j
>= 0; j
--) {
882 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
884 for (j
= n_vect
- 1; j
>= 0; j
--) {
885 for (i
= 0; i
< n_comp
- 1; i
++) {
888 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
891 ((Fx64
*)cc
)[1] = hi
;
896 fxt1_quantize_HI (GLuint
*cc
,
897 GLubyte input
[N_TEXELS
][MAX_COMP
],
898 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
900 const GLint n_vect
= 6; /* highest vector number */
901 const GLint n_comp
= 3; /* 3 components: R, G, B */
902 GLfloat b
= 0.0F
; /* phoudoin: silent compiler! */
903 GLfloat iv
[MAX_COMP
]; /* interpolation vector */
905 GLuint hihi
; /* high quadword: hi dword */
907 GLint minSum
= 2000; /* big enough */
908 GLint maxSum
= -1; /* small enough */
909 GLint minCol
= 0; /* phoudoin: silent compiler! */
910 GLint maxCol
= 0; /* phoudoin: silent compiler! */
912 /* Our solution here is to find the darkest and brightest colors in
913 * the 8x4 tile and use those as the two representative colors.
914 * There are probably better algorithms to use (histogram-based).
916 for (k
= 0; k
< n
; k
++) {
918 for (i
= 0; i
< n_comp
; i
++) {
931 hihi
= 0; /* cc-hi = "00" */
932 for (i
= 0; i
< n_comp
; i
++) {
935 hihi
|= reord
[maxCol
][i
] >> 3;
937 for (i
= 0; i
< n_comp
; i
++) {
940 hihi
|= reord
[minCol
][i
] >> 3;
943 cc
[0] = cc
[1] = cc
[2] = 0;
945 /* compute interpolation vector */
946 if (minCol
!= maxCol
) {
947 MAKEIVEC(n_vect
, n_comp
, iv
, b
, reord
[minCol
], reord
[maxCol
]);
951 for (k
= N_TEXELS
- 1; k
>= 0; k
--) {
953 GLuint
*kk
= (GLuint
*)((char *)cc
+ t
/ 8);
954 GLint texel
= n_vect
+ 1; /* transparent black */
956 if (!ISTBLACK(input
[k
])) {
957 if (minCol
!= maxCol
) {
958 /* interpolate color */
959 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
961 kk
[0] |= texel
<< (t
& 7);
965 kk
[0] |= texel
<< (t
& 7);
972 fxt1_quantize_MIXED1 (GLuint
*cc
,
973 GLubyte input
[N_TEXELS
][MAX_COMP
])
975 const GLint n_vect
= 2; /* highest vector number in each microtile */
976 const GLint n_comp
= 3; /* 3 components: R, G, B */
977 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
978 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
980 Fx64 hi
; /* high quadword */
981 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
985 GLint minColL
= 0, maxColL
= -1;
986 GLint minColR
= 0, maxColR
= -1;
988 /* Our solution here is to find the darkest and brightest colors in
989 * the 4x4 tile and use those as the two representative colors.
990 * There are probably better algorithms to use (histogram-based).
992 minSum
= 2000; /* big enough */
993 maxSum
= -1; /* small enough */
994 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
995 if (!ISTBLACK(input
[k
])) {
997 for (i
= 0; i
< n_comp
; i
++) {
1010 minSum
= 2000; /* big enough */
1011 maxSum
= -1; /* small enough */
1012 for (; k
< N_TEXELS
; k
++) {
1013 if (!ISTBLACK(input
[k
])) {
1015 for (i
= 0; i
< n_comp
; i
++) {
1029 /* left microtile */
1030 if (maxColL
== -1) {
1031 /* all transparent black */
1033 for (i
= 0; i
< n_comp
; i
++) {
1039 for (i
= 0; i
< n_comp
; i
++) {
1040 vec
[0][i
] = input
[minColL
][i
];
1041 vec
[1][i
] = input
[maxColL
][i
];
1043 if (minColL
!= maxColL
) {
1044 /* compute interpolation vector */
1045 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1049 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1050 GLint texel
= n_vect
+ 1; /* transparent black */
1051 if (!ISTBLACK(input
[k
])) {
1052 /* interpolate color */
1053 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1063 /* right microtile */
1064 if (maxColR
== -1) {
1065 /* all transparent black */
1067 for (i
= 0; i
< n_comp
; i
++) {
1073 for (i
= 0; i
< n_comp
; i
++) {
1074 vec
[2][i
] = input
[minColR
][i
];
1075 vec
[3][i
] = input
[maxColR
][i
];
1077 if (minColR
!= maxColR
) {
1078 /* compute interpolation vector */
1079 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1083 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1084 GLint texel
= n_vect
+ 1; /* transparent black */
1085 if (!ISTBLACK(input
[k
])) {
1086 /* interpolate color */
1087 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1097 FX64_MOV32(hi
, 9 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1098 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1099 for (i
= 0; i
< n_comp
; i
++) {
1102 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1105 ((Fx64
*)cc
)[1] = hi
;
1110 fxt1_quantize_MIXED0 (GLuint
*cc
,
1111 GLubyte input
[N_TEXELS
][MAX_COMP
])
1113 const GLint n_vect
= 3; /* highest vector number in each microtile */
1114 const GLint n_comp
= 3; /* 3 components: R, G, B */
1115 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
1116 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
1118 Fx64 hi
; /* high quadword */
1119 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
1121 GLint minColL
= 0, maxColL
= 0;
1122 GLint minColR
= 0, maxColR
= 0;
1127 /* Our solution here is to find the darkest and brightest colors in
1128 * the 4x4 tile and use those as the two representative colors.
1129 * There are probably better algorithms to use (histogram-based).
1131 minSum
= 2000; /* big enough */
1132 maxSum
= -1; /* small enough */
1133 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1135 for (i
= 0; i
< n_comp
; i
++) {
1147 minSum
= 2000; /* big enough */
1148 maxSum
= -1; /* small enough */
1149 for (; k
< N_TEXELS
; k
++) {
1151 for (i
= 0; i
< n_comp
; i
++) {
1166 GLint maxVarL
= fxt1_variance(NULL
, input
, n_comp
, N_TEXELS
/ 2);
1167 GLint maxVarR
= fxt1_variance(NULL
, &input
[N_TEXELS
/ 2], n_comp
, N_TEXELS
/ 2);
1169 /* Scan the channel with max variance for lo & hi
1170 * and use those as the two representative colors.
1172 minVal
= 2000; /* big enough */
1173 maxVal
= -1; /* small enough */
1174 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1175 GLint t
= input
[k
][maxVarL
];
1185 minVal
= 2000; /* big enough */
1186 maxVal
= -1; /* small enough */
1187 for (; k
< N_TEXELS
; k
++) {
1188 GLint t
= input
[k
][maxVarR
];
1200 /* left microtile */
1202 for (i
= 0; i
< n_comp
; i
++) {
1203 vec
[0][i
] = input
[minColL
][i
];
1204 vec
[1][i
] = input
[maxColL
][i
];
1206 if (minColL
!= maxColL
) {
1207 /* compute interpolation vector */
1208 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1212 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1214 /* interpolate color */
1215 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1221 /* funky encoding for LSB of green */
1222 if ((GLint
)((lolo
>> 1) & 1) != (((vec
[1][GCOMP
] ^ vec
[0][GCOMP
]) >> 2) & 1)) {
1223 for (i
= 0; i
< n_comp
; i
++) {
1224 vec
[1][i
] = input
[minColL
][i
];
1225 vec
[0][i
] = input
[maxColL
][i
];
1233 /* right microtile */
1235 for (i
= 0; i
< n_comp
; i
++) {
1236 vec
[2][i
] = input
[minColR
][i
];
1237 vec
[3][i
] = input
[maxColR
][i
];
1239 if (minColR
!= maxColR
) {
1240 /* compute interpolation vector */
1241 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1245 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1247 /* interpolate color */
1248 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1254 /* funky encoding for LSB of green */
1255 if ((GLint
)((lohi
>> 1) & 1) != (((vec
[3][GCOMP
] ^ vec
[2][GCOMP
]) >> 2) & 1)) {
1256 for (i
= 0; i
< n_comp
; i
++) {
1257 vec
[3][i
] = input
[minColR
][i
];
1258 vec
[2][i
] = input
[maxColR
][i
];
1266 FX64_MOV32(hi
, 8 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1267 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1268 for (i
= 0; i
< n_comp
; i
++) {
1271 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1274 ((Fx64
*)cc
)[1] = hi
;
1279 fxt1_quantize (GLuint
*cc
, const GLubyte
*lines
[], GLint comps
)
1282 GLubyte reord
[N_TEXELS
][MAX_COMP
];
1284 GLubyte input
[N_TEXELS
][MAX_COMP
];
1288 /* make the whole block opaque */
1289 _mesa_memset(input
, -1, sizeof(input
));
1292 /* 8 texels each line */
1293 for (l
= 0; l
< 4; l
++) {
1294 for (k
= 0; k
< 4; k
++) {
1295 for (i
= 0; i
< comps
; i
++) {
1296 input
[k
+ l
* 4][i
] = *lines
[l
]++;
1299 for (; k
< 8; k
++) {
1300 for (i
= 0; i
< comps
; i
++) {
1301 input
[k
+ l
* 4 + 12][i
] = *lines
[l
]++;
1307 * 00, 01, 02, 03, 08, 09, 0a, 0b
1308 * 10, 11, 12, 13, 18, 19, 1a, 1b
1309 * 04, 05, 06, 07, 0c, 0d, 0e, 0f
1310 * 14, 15, 16, 17, 1c, 1d, 1e, 1f
1314 * stupidity flows forth from this
1319 /* skip all transparent black texels */
1321 for (k
= 0; k
< N_TEXELS
; k
++) {
1322 /* test all components against 0 */
1323 if (!ISTBLACK(input
[k
])) {
1324 /* texel is not transparent black */
1325 COPY_4UBV(reord
[l
], input
[k
]);
1326 if (reord
[l
][ACOMP
] < (255 - ALPHA_TS
)) {
1327 /* non-opaque texel */
1337 fxt1_quantize_ALPHA0(cc
, input
, reord
, l
);
1338 } else if (l
== 0) {
1339 cc
[0] = cc
[1] = cc
[2] = -1;
1341 } else if (l
< N_TEXELS
) {
1342 fxt1_quantize_HI(cc
, input
, reord
, l
);
1344 fxt1_quantize_CHROMA(cc
, input
);
1346 (void)fxt1_quantize_ALPHA1
;
1347 (void)fxt1_quantize_MIXED1
;
1348 (void)fxt1_quantize_MIXED0
;
1351 fxt1_quantize_ALPHA1(cc
, input
);
1352 } else if (l
== 0) {
1353 cc
[0] = cc
[1] = cc
[2] = ~0u;
1355 } else if (l
< N_TEXELS
) {
1356 fxt1_quantize_MIXED1(cc
, input
);
1358 fxt1_quantize_MIXED0(cc
, input
);
1360 (void)fxt1_quantize_ALPHA0
;
1361 (void)fxt1_quantize_HI
;
1362 (void)fxt1_quantize_CHROMA
;
1368 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
1369 const void *source
, GLint srcRowStride
,
1370 void *dest
, GLint destRowStride
)
1373 const GLubyte
*data
;
1374 GLuint
*encoded
= (GLuint
*)dest
;
1375 void *newSource
= NULL
;
1377 assert(comps
== 3 || comps
== 4);
1379 /* Replicate image if width is not M8 or height is not M4 */
1380 if ((width
& 7) | (height
& 3)) {
1381 GLint newWidth
= (width
+ 7) & ~7;
1382 GLint newHeight
= (height
+ 3) & ~3;
1383 newSource
= _mesa_malloc(comps
* newWidth
* newHeight
* sizeof(GLchan
));
1385 GET_CURRENT_CONTEXT(ctx
);
1386 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1389 _mesa_upscale_teximage2d(width
, height
, newWidth
, newHeight
,
1390 comps
, (const GLchan
*) source
,
1391 srcRowStride
, (GLchan
*) newSource
);
1395 srcRowStride
= comps
* newWidth
;
1398 /* convert from 16/32-bit channels to GLubyte if needed */
1399 if (CHAN_TYPE
!= GL_UNSIGNED_BYTE
) {
1400 const GLuint n
= width
* height
* comps
;
1401 const GLchan
*src
= (const GLchan
*) source
;
1402 GLubyte
*dest
= (GLubyte
*) _mesa_malloc(n
* sizeof(GLubyte
));
1405 GET_CURRENT_CONTEXT(ctx
);
1406 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1409 for (i
= 0; i
< n
; i
++) {
1410 dest
[i
] = CHAN_TO_UBYTE(src
[i
]);
1412 if (newSource
!= NULL
) {
1413 _mesa_free(newSource
);
1415 newSource
= dest
; /* we'll free this buffer before returning */
1416 source
= dest
; /* the new, GLubyte incoming image */
1419 data
= (const GLubyte
*) source
;
1420 destRowStride
= (destRowStride
- width
* 2) / 4;
1421 for (y
= 0; y
< height
; y
+= 4) {
1422 GLuint offs
= 0 + (y
+ 0) * srcRowStride
;
1423 for (x
= 0; x
< width
; x
+= 8) {
1424 const GLubyte
*lines
[4];
1425 lines
[0] = &data
[offs
];
1426 lines
[1] = lines
[0] + srcRowStride
;
1427 lines
[2] = lines
[1] + srcRowStride
;
1428 lines
[3] = lines
[2] + srcRowStride
;
1430 fxt1_quantize(encoded
, lines
, comps
);
1431 /* 128 bits per 8x4 block */
1434 encoded
+= destRowStride
;
1438 if (newSource
!= NULL
) {
1439 _mesa_free(newSource
);
1444 /***************************************************************************\
1447 * The decoder is based on GL_3DFX_texture_compression_FXT1
1448 * specification and serves as a concept for the encoder.
1449 \***************************************************************************/
1452 /* lookup table for scaling 5 bit colors up to 8 bits */
1453 static const GLubyte _rgb_scale_5
[] = {
1454 0, 8, 16, 25, 33, 41, 49, 58,
1455 66, 74, 82, 90, 99, 107, 115, 123,
1456 132, 140, 148, 156, 165, 173, 181, 189,
1457 197, 206, 214, 222, 230, 239, 247, 255
1460 /* lookup table for scaling 6 bit colors up to 8 bits */
1461 static const GLubyte _rgb_scale_6
[] = {
1462 0, 4, 8, 12, 16, 20, 24, 28,
1463 32, 36, 40, 45, 49, 53, 57, 61,
1464 65, 69, 73, 77, 81, 85, 89, 93,
1465 97, 101, 105, 109, 113, 117, 121, 125,
1466 130, 134, 138, 142, 146, 150, 154, 158,
1467 162, 166, 170, 174, 178, 182, 186, 190,
1468 194, 198, 202, 206, 210, 215, 219, 223,
1469 227, 231, 235, 239, 243, 247, 251, 255
1473 #define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
1474 #define UP5(c) _rgb_scale_5[(c) & 31]
1475 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
1476 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
1480 fxt1_decode_1HI (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1485 cc
= (const GLuint
*)(code
+ t
/ 8);
1486 t
= (cc
[0] >> (t
& 7)) & 7;
1489 rgba
[RCOMP
] = rgba
[GCOMP
] = rgba
[BCOMP
] = rgba
[ACOMP
] = 0;
1492 cc
= (const GLuint
*)(code
+ 12);
1494 b
= UP5(CC_SEL(cc
, 0));
1495 g
= UP5(CC_SEL(cc
, 5));
1496 r
= UP5(CC_SEL(cc
, 10));
1497 } else if (t
== 6) {
1498 b
= UP5(CC_SEL(cc
, 15));
1499 g
= UP5(CC_SEL(cc
, 20));
1500 r
= UP5(CC_SEL(cc
, 25));
1502 b
= LERP(6, t
, UP5(CC_SEL(cc
, 0)), UP5(CC_SEL(cc
, 15)));
1503 g
= LERP(6, t
, UP5(CC_SEL(cc
, 5)), UP5(CC_SEL(cc
, 20)));
1504 r
= LERP(6, t
, UP5(CC_SEL(cc
, 10)), UP5(CC_SEL(cc
, 25)));
1506 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1507 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1508 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1509 rgba
[ACOMP
] = CHAN_MAX
;
1515 fxt1_decode_1CHROMA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1520 cc
= (const GLuint
*)code
;
1525 t
= (cc
[0] >> (t
* 2)) & 3;
1528 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1529 kk
= cc
[0] >> (t
& 7);
1530 rgba
[BCOMP
] = UBYTE_TO_CHAN( UP5(kk
) );
1531 rgba
[GCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 5) );
1532 rgba
[RCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 10) );
1533 rgba
[ACOMP
] = CHAN_MAX
;
1538 fxt1_decode_1MIXED (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1544 cc
= (const GLuint
*)code
;
1547 t
= (cc
[1] >> (t
* 2)) & 3;
1549 col
[0][BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1550 col
[0][GCOMP
] = CC_SEL(cc
, 99);
1551 col
[0][RCOMP
] = CC_SEL(cc
, 104);
1553 col
[1][BCOMP
] = CC_SEL(cc
, 109);
1554 col
[1][GCOMP
] = CC_SEL(cc
, 114);
1555 col
[1][RCOMP
] = CC_SEL(cc
, 119);
1556 glsb
= CC_SEL(cc
, 126);
1557 selb
= CC_SEL(cc
, 33);
1559 t
= (cc
[0] >> (t
* 2)) & 3;
1561 col
[0][BCOMP
] = CC_SEL(cc
, 64);
1562 col
[0][GCOMP
] = CC_SEL(cc
, 69);
1563 col
[0][RCOMP
] = CC_SEL(cc
, 74);
1565 col
[1][BCOMP
] = CC_SEL(cc
, 79);
1566 col
[1][GCOMP
] = CC_SEL(cc
, 84);
1567 col
[1][RCOMP
] = CC_SEL(cc
, 89);
1568 glsb
= CC_SEL(cc
, 125);
1569 selb
= CC_SEL(cc
, 1);
1572 if (CC_SEL(cc
, 124) & 1) {
1577 rgba
[RCOMP
] = rgba
[BCOMP
] = rgba
[GCOMP
] = rgba
[ACOMP
] = 0;
1581 b
= UP5(col
[0][BCOMP
]);
1582 g
= UP5(col
[0][GCOMP
]);
1583 r
= UP5(col
[0][RCOMP
]);
1584 } else if (t
== 2) {
1585 b
= UP5(col
[1][BCOMP
]);
1586 g
= UP6(col
[1][GCOMP
], glsb
);
1587 r
= UP5(col
[1][RCOMP
]);
1589 b
= (UP5(col
[0][BCOMP
]) + UP5(col
[1][BCOMP
])) / 2;
1590 g
= (UP5(col
[0][GCOMP
]) + UP6(col
[1][GCOMP
], glsb
)) / 2;
1591 r
= (UP5(col
[0][RCOMP
]) + UP5(col
[1][RCOMP
])) / 2;
1593 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1594 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1595 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1596 rgba
[ACOMP
] = CHAN_MAX
;
1602 b
= UP5(col
[0][BCOMP
]);
1603 g
= UP6(col
[0][GCOMP
], glsb
^ selb
);
1604 r
= UP5(col
[0][RCOMP
]);
1605 } else if (t
== 3) {
1606 b
= UP5(col
[1][BCOMP
]);
1607 g
= UP6(col
[1][GCOMP
], glsb
);
1608 r
= UP5(col
[1][RCOMP
]);
1610 b
= LERP(3, t
, UP5(col
[0][BCOMP
]), UP5(col
[1][BCOMP
]));
1611 g
= LERP(3, t
, UP6(col
[0][GCOMP
], glsb
^ selb
),
1612 UP6(col
[1][GCOMP
], glsb
));
1613 r
= LERP(3, t
, UP5(col
[0][RCOMP
]), UP5(col
[1][RCOMP
]));
1615 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1616 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1617 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1618 rgba
[ACOMP
] = CHAN_MAX
;
1624 fxt1_decode_1ALPHA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1629 cc
= (const GLuint
*)code
;
1630 if (CC_SEL(cc
, 124) & 1) {
1636 t
= (cc
[1] >> (t
* 2)) & 3;
1638 col0
[BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1639 col0
[GCOMP
] = CC_SEL(cc
, 99);
1640 col0
[RCOMP
] = CC_SEL(cc
, 104);
1641 col0
[ACOMP
] = CC_SEL(cc
, 119);
1643 t
= (cc
[0] >> (t
* 2)) & 3;
1645 col0
[BCOMP
] = CC_SEL(cc
, 64);
1646 col0
[GCOMP
] = CC_SEL(cc
, 69);
1647 col0
[RCOMP
] = CC_SEL(cc
, 74);
1648 col0
[ACOMP
] = CC_SEL(cc
, 109);
1652 b
= UP5(col0
[BCOMP
]);
1653 g
= UP5(col0
[GCOMP
]);
1654 r
= UP5(col0
[RCOMP
]);
1655 a
= UP5(col0
[ACOMP
]);
1656 } else if (t
== 3) {
1657 b
= UP5(CC_SEL(cc
, 79));
1658 g
= UP5(CC_SEL(cc
, 84));
1659 r
= UP5(CC_SEL(cc
, 89));
1660 a
= UP5(CC_SEL(cc
, 114));
1662 b
= LERP(3, t
, UP5(col0
[BCOMP
]), UP5(CC_SEL(cc
, 79)));
1663 g
= LERP(3, t
, UP5(col0
[GCOMP
]), UP5(CC_SEL(cc
, 84)));
1664 r
= LERP(3, t
, UP5(col0
[RCOMP
]), UP5(CC_SEL(cc
, 89)));
1665 a
= LERP(3, t
, UP5(col0
[ACOMP
]), UP5(CC_SEL(cc
, 114)));
1674 t
= (cc
[0] >> (t
* 2)) & 3;
1681 cc
= (const GLuint
*)code
;
1682 a
= UP5(cc
[3] >> (t
* 5 + 13));
1684 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1685 kk
= cc
[0] >> (t
& 7);
1691 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1692 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1693 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1694 rgba
[ACOMP
] = UBYTE_TO_CHAN(a
);
1699 fxt1_decode_1 (const void *texture
, GLint stride
, /* in pixels */
1700 GLint i
, GLint j
, GLchan
*rgba
)
1702 static void (*decode_1
[]) (const GLubyte
*, GLint
, GLchan
*) = {
1703 fxt1_decode_1HI
, /* cc-high = "00?" */
1704 fxt1_decode_1HI
, /* cc-high = "00?" */
1705 fxt1_decode_1CHROMA
, /* cc-chroma = "010" */
1706 fxt1_decode_1ALPHA
, /* alpha = "011" */
1707 fxt1_decode_1MIXED
, /* mixed = "1??" */
1708 fxt1_decode_1MIXED
, /* mixed = "1??" */
1709 fxt1_decode_1MIXED
, /* mixed = "1??" */
1710 fxt1_decode_1MIXED
/* mixed = "1??" */
1713 const GLubyte
*code
= (const GLubyte
*)texture
+
1714 ((j
/ 4) * (stride
/ 8) + (i
/ 8)) * 16;
1715 GLint mode
= CC_SEL(code
, 125);
1723 decode_1
[mode
](code
, t
, rgba
);