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 * Called via TexFormat->StoreImage to store an RGB_FXT1 texture.
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_texformat_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 dstFormat
->BaseFormat
,
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,
109 dstFormat
->MesaFormat
,
110 texWidth
, (GLubyte
*) dstAddr
);
112 fxt1_encode(srcWidth
, srcHeight
, 3, pixels
, srcRowStride
,
116 _mesa_free((void*) tempImage
);
123 * Called via TexFormat->StoreImage to store an RGBA_FXT1 texture.
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_texformat_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 dstFormat
->BaseFormat
,
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,
166 dstFormat
->MesaFormat
,
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 const struct gl_texture_format _mesa_texformat_rgb_fxt1
= {
230 MESA_FORMAT_RGB_FXT1
, /* MesaFormat */
231 GL_RGB
, /* BaseFormat */
232 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
233 4, /*approx*/ /* RedBits */
234 4, /*approx*/ /* GreenBits */
235 4, /*approx*/ /* BlueBits */
237 0, /* LuminanceBits */
238 0, /* IntensityBits */
243 _mesa_texstore_rgb_fxt1
, /* StoreTexImageFunc */
244 NULL
, /*impossible*/ /* FetchTexel1D */
245 _mesa_fetch_texel_2d_rgb_fxt1
, /* FetchTexel2D */
246 NULL
, /*impossible*/ /* FetchTexel3D */
247 NULL
, /*impossible*/ /* FetchTexel1Df */
248 _mesa_fetch_texel_2d_f_rgb_fxt1
, /* FetchTexel2Df */
249 NULL
, /*impossible*/ /* FetchTexel3Df */
250 NULL
/* StoreTexel */
253 const struct gl_texture_format _mesa_texformat_rgba_fxt1
= {
254 MESA_FORMAT_RGBA_FXT1
, /* MesaFormat */
255 GL_RGBA
, /* BaseFormat */
256 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
257 4, /*approx*/ /* RedBits */
258 4, /*approx*/ /* GreenBits */
259 4, /*approx*/ /* BlueBits */
260 1, /*approx*/ /* AlphaBits */
261 0, /* LuminanceBits */
262 0, /* IntensityBits */
267 _mesa_texstore_rgba_fxt1
, /* StoreTexImageFunc */
268 NULL
, /*impossible*/ /* FetchTexel1D */
269 _mesa_fetch_texel_2d_rgba_fxt1
, /* FetchTexel2D */
270 NULL
, /*impossible*/ /* FetchTexel3D */
271 NULL
, /*impossible*/ /* FetchTexel1Df */
272 _mesa_fetch_texel_2d_f_rgba_fxt1
, /* FetchTexel2Df */
273 NULL
, /*impossible*/ /* FetchTexel3Df */
274 NULL
/* StoreTexel */
278 /***************************************************************************\
281 * The encoder was built by reversing the decoder,
282 * and is vaguely based on Texus2 by 3dfx. Note that this code
283 * is merely a proof of concept, since it is highly UNoptimized;
284 * moreover, it is sub-optimal due to initial conditions passed
285 * to Lloyd's algorithm (the interpolation modes are even worse).
286 \***************************************************************************/
289 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
290 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
291 #define N_TEXELS 32 /* number of texels in a block (always 32) */
292 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
293 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
294 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
295 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
296 #define ISTBLACK(v) (*((GLuint *)(v)) == 0)
300 * Define a 64-bit unsigned integer type and macros
304 #define FX64_NATIVE 1
306 typedef uint64_t Fx64
;
308 #define FX64_MOV32(a, b) a = b
309 #define FX64_OR32(a, b) a |= b
310 #define FX64_SHL(a, c) a <<= c
314 #define FX64_NATIVE 0
320 #define FX64_MOV32(a, b) a.lo = b
321 #define FX64_OR32(a, b) a.lo |= b
323 #define FX64_SHL(a, c) \
326 a.hi = a.lo << ((c) - 32); \
329 a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
337 #define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
338 #define SAFECDOT 1 /* for paranoids */
340 #define MAKEIVEC(NV, NC, IV, B, V0, V1) \
342 /* compute interpolation vector */ \
346 for (i = 0; i < NC; i++) { \
347 IV[i] = (V1[i] - V0[i]) * F(i); \
348 d2 += IV[i] * IV[i]; \
350 rd2 = (GLfloat)NV / d2; \
352 for (i = 0; i < NC; i++) { \
354 B -= IV[i] * V0[i]; \
357 B = B * rd2 + 0.5f; \
360 #define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
362 GLfloat dot = 0.0F; \
363 for (i = 0; i < NC; i++) { \
364 dot += V[i] * IV[i]; \
366 TEXEL = (GLint)(dot + B); \
370 } else if (TEXEL > NV) { \
378 fxt1_bestcol (GLfloat vec
[][MAX_COMP
], GLint nv
,
379 GLubyte input
[MAX_COMP
], GLint nc
)
381 GLint i
, j
, best
= -1;
382 GLfloat err
= 1e9
; /* big enough */
384 for (j
= 0; j
< nv
; j
++) {
386 for (i
= 0; i
< nc
; i
++) {
387 e
+= (vec
[j
][i
] - input
[i
]) * (vec
[j
][i
] - input
[i
]);
400 fxt1_worst (GLfloat vec
[MAX_COMP
],
401 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
403 GLint i
, k
, worst
= -1;
404 GLfloat err
= -1.0F
; /* small enough */
406 for (k
= 0; k
< n
; k
++) {
408 for (i
= 0; i
< nc
; i
++) {
409 e
+= (vec
[i
] - input
[k
][i
]) * (vec
[i
] - input
[k
][i
]);
422 fxt1_variance (GLdouble variance
[MAX_COMP
],
423 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
425 GLint i
, k
, best
= 0;
427 GLdouble var
, maxvar
= -1; /* small enough */
428 GLdouble teenth
= 1.0 / n
;
430 for (i
= 0; i
< nc
; i
++) {
432 for (k
= 0; k
< n
; k
++) {
433 GLint t
= input
[k
][i
];
437 var
= sx2
* teenth
- sx
* sx
* teenth
* teenth
;
452 fxt1_choose (GLfloat vec
[][MAX_COMP
], GLint nv
,
453 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
456 /* Choose colors from a grid.
460 for (j
= 0; j
< nv
; j
++) {
461 GLint m
= j
* (n
- 1) / (nv
- 1);
462 for (i
= 0; i
< nc
; i
++) {
463 vec
[j
][i
] = input
[m
][i
];
467 /* Our solution here is to find the darkest and brightest colors in
468 * the 8x4 tile and use those as the two representative colors.
469 * There are probably better algorithms to use (histogram-based).
472 GLint minSum
= 2000; /* big enough */
473 GLint maxSum
= -1; /* small enough */
474 GLint minCol
= 0; /* phoudoin: silent compiler! */
475 GLint maxCol
= 0; /* phoudoin: silent compiler! */
485 _mesa_memset(hist
, 0, sizeof(hist
));
487 for (k
= 0; k
< n
; k
++) {
491 for (i
= 0; i
< nc
; i
++) {
496 for (l
= 0; l
< n
; l
++) {
505 } else if (hist
[l
].key
== key
) {
521 for (j
= 0; j
< lenh
; j
++) {
522 for (i
= 0; i
< nc
; i
++) {
523 vec
[j
][i
] = (GLfloat
)input
[hist
[j
].idx
][i
];
526 for (; j
< nv
; j
++) {
527 for (i
= 0; i
< nc
; i
++) {
528 vec
[j
][i
] = vec
[0][i
];
534 for (j
= 0; j
< nv
; j
++) {
535 for (i
= 0; i
< nc
; i
++) {
536 vec
[j
][i
] = ((nv
- 1 - j
) * input
[minCol
][i
] + j
* input
[maxCol
][i
] + (nv
- 1) / 2) / (GLfloat
)(nv
- 1);
546 fxt1_lloyd (GLfloat vec
[][MAX_COMP
], GLint nv
,
547 GLubyte input
[N_TEXELS
][MAX_COMP
], GLint nc
, GLint n
)
549 /* Use the generalized lloyd's algorithm for VQ:
550 * find 4 color vectors.
552 * for each sample color
553 * sort to nearest vector.
555 * replace each vector with the centroid of it's matching colors.
557 * repeat until RMS doesn't improve.
559 * if a color vector has no samples, or becomes the same as another
560 * vector, replace it with the color which is farthest from a sample.
562 * vec[][MAX_COMP] initial vectors and resulting colors
563 * nv number of resulting colors required
564 * input[N_TEXELS][MAX_COMP] input texels
565 * nc number of components in input / vec
566 * n number of input samples
569 GLint sum
[MAX_VECT
][MAX_COMP
]; /* used to accumulate closest texels */
570 GLint cnt
[MAX_VECT
]; /* how many times a certain vector was chosen */
571 GLfloat error
, lasterror
= 1e9
;
576 for (rep
= 0; rep
< LL_N_REP
; rep
++) {
577 /* reset sums & counters */
578 for (j
= 0; j
< nv
; j
++) {
579 for (i
= 0; i
< nc
; i
++) {
586 /* scan whole block */
587 for (k
= 0; k
< n
; k
++) {
590 GLfloat err
= 1e9
; /* big enough */
591 /* determine best vector */
592 for (j
= 0; j
< nv
; j
++) {
593 GLfloat e
= (vec
[j
][0] - input
[k
][0]) * (vec
[j
][0] - input
[k
][0]) +
594 (vec
[j
][1] - input
[k
][1]) * (vec
[j
][1] - input
[k
][1]) +
595 (vec
[j
][2] - input
[k
][2]) * (vec
[j
][2] - input
[k
][2]);
597 e
+= (vec
[j
][3] - input
[k
][3]) * (vec
[j
][3] - input
[k
][3]);
605 GLint best
= fxt1_bestcol(vec
, nv
, input
[k
], nc
, &err
);
607 /* add in closest color */
608 for (i
= 0; i
< nc
; i
++) {
609 sum
[best
][i
] += input
[k
][i
];
611 /* mark this vector as used */
613 /* accumulate error */
618 if ((error
< LL_RMS_E
) ||
619 ((error
< lasterror
) && ((lasterror
- error
) < LL_RMS_D
))) {
620 return !0; /* good match */
624 /* move each vector to the barycenter of its closest colors */
625 for (j
= 0; j
< nv
; j
++) {
627 GLfloat div
= 1.0F
/ cnt
[j
];
628 for (i
= 0; i
< nc
; i
++) {
629 vec
[j
][i
] = div
* sum
[j
][i
];
632 /* this vec has no samples or is identical with a previous vec */
633 GLint worst
= fxt1_worst(vec
[j
], input
, nc
, n
);
634 for (i
= 0; i
< nc
; i
++) {
635 vec
[j
][i
] = input
[worst
][i
];
641 return 0; /* could not converge fast enough */
646 fxt1_quantize_CHROMA (GLuint
*cc
,
647 GLubyte input
[N_TEXELS
][MAX_COMP
])
649 const GLint n_vect
= 4; /* 4 base vectors to find */
650 const GLint n_comp
= 3; /* 3 components: R, G, B */
651 GLfloat vec
[MAX_VECT
][MAX_COMP
];
653 Fx64 hi
; /* high quadword */
654 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
656 if (fxt1_choose(vec
, n_vect
, input
, n_comp
, N_TEXELS
) != 0) {
657 fxt1_lloyd(vec
, n_vect
, input
, n_comp
, N_TEXELS
);
660 FX64_MOV32(hi
, 4); /* cc-chroma = "010" + unused bit */
661 for (j
= n_vect
- 1; j
>= 0; j
--) {
662 for (i
= 0; i
< n_comp
; i
++) {
665 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
668 ((Fx64
*)cc
)[1] = hi
;
671 /* right microtile */
672 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
674 lohi
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
677 for (; k
>= 0; k
--) {
679 lolo
|= fxt1_bestcol(vec
, n_vect
, input
[k
], n_comp
);
687 fxt1_quantize_ALPHA0 (GLuint
*cc
,
688 GLubyte input
[N_TEXELS
][MAX_COMP
],
689 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
691 const GLint n_vect
= 3; /* 3 base vectors to find */
692 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
693 GLfloat vec
[MAX_VECT
][MAX_COMP
];
695 Fx64 hi
; /* high quadword */
696 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
698 /* the last vector indicates zero */
699 for (i
= 0; i
< n_comp
; i
++) {
703 /* the first n texels in reord are guaranteed to be non-zero */
704 if (fxt1_choose(vec
, n_vect
, reord
, n_comp
, n
) != 0) {
705 fxt1_lloyd(vec
, n_vect
, reord
, n_comp
, n
);
708 FX64_MOV32(hi
, 6); /* alpha = "011" + lerp = 0 */
709 for (j
= n_vect
- 1; j
>= 0; j
--) {
712 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
714 for (j
= n_vect
- 1; j
>= 0; j
--) {
715 for (i
= 0; i
< n_comp
- 1; i
++) {
718 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
721 ((Fx64
*)cc
)[1] = hi
;
724 /* right microtile */
725 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/2; k
--) {
727 lohi
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
730 for (; k
>= 0; k
--) {
732 lolo
|= fxt1_bestcol(vec
, n_vect
+ 1, input
[k
], n_comp
);
740 fxt1_quantize_ALPHA1 (GLuint
*cc
,
741 GLubyte input
[N_TEXELS
][MAX_COMP
])
743 const GLint n_vect
= 3; /* highest vector number in each microtile */
744 const GLint n_comp
= 4; /* 4 components: R, G, B, A */
745 GLfloat vec
[1 + 1 + 1][MAX_COMP
]; /* 1.5 extrema for each sub-block */
746 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
748 Fx64 hi
; /* high quadword */
749 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
753 GLint minColL
= 0, maxColL
= 0;
754 GLint minColR
= 0, maxColR
= 0;
755 GLint sumL
= 0, sumR
= 0;
757 /* Our solution here is to find the darkest and brightest colors in
758 * the 4x4 tile and use those as the two representative colors.
759 * There are probably better algorithms to use (histogram-based).
762 while ((minColL
== maxColL
) && nn_comp
) {
763 minSum
= 2000; /* big enough */
764 maxSum
= -1; /* small enough */
765 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
767 for (i
= 0; i
< nn_comp
; i
++) {
785 while ((minColR
== maxColR
) && nn_comp
) {
786 minSum
= 2000; /* big enough */
787 maxSum
= -1; /* small enough */
788 for (k
= N_TEXELS
/ 2; k
< N_TEXELS
; k
++) {
790 for (i
= 0; i
< nn_comp
; i
++) {
807 /* choose the common vector (yuck!) */
810 GLint v1
= 0, v2
= 0;
811 GLfloat err
= 1e9
; /* big enough */
812 GLfloat tv
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
813 for (i
= 0; i
< n_comp
; i
++) {
814 tv
[0][i
] = input
[minColL
][i
];
815 tv
[1][i
] = input
[maxColL
][i
];
816 tv
[2][i
] = input
[minColR
][i
];
817 tv
[3][i
] = input
[maxColR
][i
];
819 for (j1
= 0; j1
< 2; j1
++) {
820 for (j2
= 2; j2
< 4; j2
++) {
822 for (i
= 0; i
< n_comp
; i
++) {
823 e
+= (tv
[j1
][i
] - tv
[j2
][i
]) * (tv
[j1
][i
] - tv
[j2
][i
]);
832 for (i
= 0; i
< n_comp
; i
++) {
833 vec
[0][i
] = tv
[1 - v1
][i
];
834 vec
[1][i
] = (tv
[v1
][i
] * sumL
+ tv
[v2
][i
] * sumR
) / (sumL
+ sumR
);
835 vec
[2][i
] = tv
[5 - v2
][i
];
841 if (minColL
!= maxColL
) {
842 /* compute interpolation vector */
843 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
847 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
849 /* interpolate color */
850 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
859 /* right microtile */
861 if (minColR
!= maxColR
) {
862 /* compute interpolation vector */
863 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[1]);
867 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
869 /* interpolate color */
870 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
879 FX64_MOV32(hi
, 7); /* alpha = "011" + lerp = 1 */
880 for (j
= n_vect
- 1; j
>= 0; j
--) {
883 FX64_OR32(hi
, (GLuint
)(vec
[j
][ACOMP
] / 8.0F
));
885 for (j
= n_vect
- 1; j
>= 0; j
--) {
886 for (i
= 0; i
< n_comp
- 1; i
++) {
889 FX64_OR32(hi
, (GLuint
)(vec
[j
][i
] / 8.0F
));
892 ((Fx64
*)cc
)[1] = hi
;
897 fxt1_quantize_HI (GLuint
*cc
,
898 GLubyte input
[N_TEXELS
][MAX_COMP
],
899 GLubyte reord
[N_TEXELS
][MAX_COMP
], GLint n
)
901 const GLint n_vect
= 6; /* highest vector number */
902 const GLint n_comp
= 3; /* 3 components: R, G, B */
903 GLfloat b
= 0.0F
; /* phoudoin: silent compiler! */
904 GLfloat iv
[MAX_COMP
]; /* interpolation vector */
906 GLuint hihi
; /* high quadword: hi dword */
908 GLint minSum
= 2000; /* big enough */
909 GLint maxSum
= -1; /* small enough */
910 GLint minCol
= 0; /* phoudoin: silent compiler! */
911 GLint maxCol
= 0; /* phoudoin: silent compiler! */
913 /* Our solution here is to find the darkest and brightest colors in
914 * the 8x4 tile and use those as the two representative colors.
915 * There are probably better algorithms to use (histogram-based).
917 for (k
= 0; k
< n
; k
++) {
919 for (i
= 0; i
< n_comp
; i
++) {
932 hihi
= 0; /* cc-hi = "00" */
933 for (i
= 0; i
< n_comp
; i
++) {
936 hihi
|= reord
[maxCol
][i
] >> 3;
938 for (i
= 0; i
< n_comp
; i
++) {
941 hihi
|= reord
[minCol
][i
] >> 3;
944 cc
[0] = cc
[1] = cc
[2] = 0;
946 /* compute interpolation vector */
947 if (minCol
!= maxCol
) {
948 MAKEIVEC(n_vect
, n_comp
, iv
, b
, reord
[minCol
], reord
[maxCol
]);
952 for (k
= N_TEXELS
- 1; k
>= 0; k
--) {
954 GLuint
*kk
= (GLuint
*)((char *)cc
+ t
/ 8);
955 GLint texel
= n_vect
+ 1; /* transparent black */
957 if (!ISTBLACK(input
[k
])) {
958 if (minCol
!= maxCol
) {
959 /* interpolate color */
960 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
962 kk
[0] |= texel
<< (t
& 7);
966 kk
[0] |= texel
<< (t
& 7);
973 fxt1_quantize_MIXED1 (GLuint
*cc
,
974 GLubyte input
[N_TEXELS
][MAX_COMP
])
976 const GLint n_vect
= 2; /* highest vector number in each microtile */
977 const GLint n_comp
= 3; /* 3 components: R, G, B */
978 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
979 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
981 Fx64 hi
; /* high quadword */
982 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
986 GLint minColL
= 0, maxColL
= -1;
987 GLint minColR
= 0, maxColR
= -1;
989 /* Our solution here is to find the darkest and brightest colors in
990 * the 4x4 tile and use those as the two representative colors.
991 * There are probably better algorithms to use (histogram-based).
993 minSum
= 2000; /* big enough */
994 maxSum
= -1; /* small enough */
995 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
996 if (!ISTBLACK(input
[k
])) {
998 for (i
= 0; i
< n_comp
; i
++) {
1011 minSum
= 2000; /* big enough */
1012 maxSum
= -1; /* small enough */
1013 for (; k
< N_TEXELS
; k
++) {
1014 if (!ISTBLACK(input
[k
])) {
1016 for (i
= 0; i
< n_comp
; i
++) {
1030 /* left microtile */
1031 if (maxColL
== -1) {
1032 /* all transparent black */
1034 for (i
= 0; i
< n_comp
; i
++) {
1040 for (i
= 0; i
< n_comp
; i
++) {
1041 vec
[0][i
] = input
[minColL
][i
];
1042 vec
[1][i
] = input
[maxColL
][i
];
1044 if (minColL
!= maxColL
) {
1045 /* compute interpolation vector */
1046 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1050 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1051 GLint texel
= n_vect
+ 1; /* transparent black */
1052 if (!ISTBLACK(input
[k
])) {
1053 /* interpolate color */
1054 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1064 /* right microtile */
1065 if (maxColR
== -1) {
1066 /* all transparent black */
1068 for (i
= 0; i
< n_comp
; i
++) {
1074 for (i
= 0; i
< n_comp
; i
++) {
1075 vec
[2][i
] = input
[minColR
][i
];
1076 vec
[3][i
] = input
[maxColR
][i
];
1078 if (minColR
!= maxColR
) {
1079 /* compute interpolation vector */
1080 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1084 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1085 GLint texel
= n_vect
+ 1; /* transparent black */
1086 if (!ISTBLACK(input
[k
])) {
1087 /* interpolate color */
1088 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1098 FX64_MOV32(hi
, 9 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1099 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1100 for (i
= 0; i
< n_comp
; i
++) {
1103 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1106 ((Fx64
*)cc
)[1] = hi
;
1111 fxt1_quantize_MIXED0 (GLuint
*cc
,
1112 GLubyte input
[N_TEXELS
][MAX_COMP
])
1114 const GLint n_vect
= 3; /* highest vector number in each microtile */
1115 const GLint n_comp
= 3; /* 3 components: R, G, B */
1116 GLubyte vec
[2 * 2][MAX_COMP
]; /* 2 extrema for each sub-block */
1117 GLfloat b
, iv
[MAX_COMP
]; /* interpolation vector */
1119 Fx64 hi
; /* high quadword */
1120 GLuint lohi
, lolo
; /* low quadword: hi dword, lo dword */
1122 GLint minColL
= 0, maxColL
= 0;
1123 GLint minColR
= 0, maxColR
= 0;
1128 /* Our solution here is to find the darkest and brightest colors in
1129 * the 4x4 tile and use those as the two representative colors.
1130 * There are probably better algorithms to use (histogram-based).
1132 minSum
= 2000; /* big enough */
1133 maxSum
= -1; /* small enough */
1134 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1136 for (i
= 0; i
< n_comp
; i
++) {
1148 minSum
= 2000; /* big enough */
1149 maxSum
= -1; /* small enough */
1150 for (; k
< N_TEXELS
; k
++) {
1152 for (i
= 0; i
< n_comp
; i
++) {
1167 GLint maxVarL
= fxt1_variance(NULL
, input
, n_comp
, N_TEXELS
/ 2);
1168 GLint maxVarR
= fxt1_variance(NULL
, &input
[N_TEXELS
/ 2], n_comp
, N_TEXELS
/ 2);
1170 /* Scan the channel with max variance for lo & hi
1171 * and use those as the two representative colors.
1173 minVal
= 2000; /* big enough */
1174 maxVal
= -1; /* small enough */
1175 for (k
= 0; k
< N_TEXELS
/ 2; k
++) {
1176 GLint t
= input
[k
][maxVarL
];
1186 minVal
= 2000; /* big enough */
1187 maxVal
= -1; /* small enough */
1188 for (; k
< N_TEXELS
; k
++) {
1189 GLint t
= input
[k
][maxVarR
];
1201 /* left microtile */
1203 for (i
= 0; i
< n_comp
; i
++) {
1204 vec
[0][i
] = input
[minColL
][i
];
1205 vec
[1][i
] = input
[maxColL
][i
];
1207 if (minColL
!= maxColL
) {
1208 /* compute interpolation vector */
1209 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[0], vec
[1]);
1213 for (k
= N_TEXELS
/ 2 - 1; k
>= 0; k
--) {
1215 /* interpolate color */
1216 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1222 /* funky encoding for LSB of green */
1223 if ((GLint
)((lolo
>> 1) & 1) != (((vec
[1][GCOMP
] ^ vec
[0][GCOMP
]) >> 2) & 1)) {
1224 for (i
= 0; i
< n_comp
; i
++) {
1225 vec
[1][i
] = input
[minColL
][i
];
1226 vec
[0][i
] = input
[maxColL
][i
];
1234 /* right microtile */
1236 for (i
= 0; i
< n_comp
; i
++) {
1237 vec
[2][i
] = input
[minColR
][i
];
1238 vec
[3][i
] = input
[maxColR
][i
];
1240 if (minColR
!= maxColR
) {
1241 /* compute interpolation vector */
1242 MAKEIVEC(n_vect
, n_comp
, iv
, b
, vec
[2], vec
[3]);
1246 for (k
= N_TEXELS
- 1; k
>= N_TEXELS
/ 2; k
--) {
1248 /* interpolate color */
1249 CALCCDOT(texel
, n_vect
, n_comp
, iv
, b
, input
[k
]);
1255 /* funky encoding for LSB of green */
1256 if ((GLint
)((lohi
>> 1) & 1) != (((vec
[3][GCOMP
] ^ vec
[2][GCOMP
]) >> 2) & 1)) {
1257 for (i
= 0; i
< n_comp
; i
++) {
1258 vec
[3][i
] = input
[minColR
][i
];
1259 vec
[2][i
] = input
[maxColR
][i
];
1267 FX64_MOV32(hi
, 8 | (vec
[3][GCOMP
] & 4) | ((vec
[1][GCOMP
] >> 1) & 2)); /* chroma = "1" */
1268 for (j
= 2 * 2 - 1; j
>= 0; j
--) {
1269 for (i
= 0; i
< n_comp
; i
++) {
1272 FX64_OR32(hi
, vec
[j
][i
] >> 3);
1275 ((Fx64
*)cc
)[1] = hi
;
1280 fxt1_quantize (GLuint
*cc
, const GLubyte
*lines
[], GLint comps
)
1283 GLubyte reord
[N_TEXELS
][MAX_COMP
];
1285 GLubyte input
[N_TEXELS
][MAX_COMP
];
1289 /* make the whole block opaque */
1290 _mesa_memset(input
, -1, sizeof(input
));
1293 /* 8 texels each line */
1294 for (l
= 0; l
< 4; l
++) {
1295 for (k
= 0; k
< 4; k
++) {
1296 for (i
= 0; i
< comps
; i
++) {
1297 input
[k
+ l
* 4][i
] = *lines
[l
]++;
1300 for (; k
< 8; k
++) {
1301 for (i
= 0; i
< comps
; i
++) {
1302 input
[k
+ l
* 4 + 12][i
] = *lines
[l
]++;
1308 * 00, 01, 02, 03, 08, 09, 0a, 0b
1309 * 10, 11, 12, 13, 18, 19, 1a, 1b
1310 * 04, 05, 06, 07, 0c, 0d, 0e, 0f
1311 * 14, 15, 16, 17, 1c, 1d, 1e, 1f
1315 * stupidity flows forth from this
1320 /* skip all transparent black texels */
1322 for (k
= 0; k
< N_TEXELS
; k
++) {
1323 /* test all components against 0 */
1324 if (!ISTBLACK(input
[k
])) {
1325 /* texel is not transparent black */
1326 COPY_4UBV(reord
[l
], input
[k
]);
1327 if (reord
[l
][ACOMP
] < (255 - ALPHA_TS
)) {
1328 /* non-opaque texel */
1338 fxt1_quantize_ALPHA0(cc
, input
, reord
, l
);
1339 } else if (l
== 0) {
1340 cc
[0] = cc
[1] = cc
[2] = -1;
1342 } else if (l
< N_TEXELS
) {
1343 fxt1_quantize_HI(cc
, input
, reord
, l
);
1345 fxt1_quantize_CHROMA(cc
, input
);
1347 (void)fxt1_quantize_ALPHA1
;
1348 (void)fxt1_quantize_MIXED1
;
1349 (void)fxt1_quantize_MIXED0
;
1352 fxt1_quantize_ALPHA1(cc
, input
);
1353 } else if (l
== 0) {
1354 cc
[0] = cc
[1] = cc
[2] = ~0u;
1356 } else if (l
< N_TEXELS
) {
1357 fxt1_quantize_MIXED1(cc
, input
);
1359 fxt1_quantize_MIXED0(cc
, input
);
1361 (void)fxt1_quantize_ALPHA0
;
1362 (void)fxt1_quantize_HI
;
1363 (void)fxt1_quantize_CHROMA
;
1369 fxt1_encode (GLuint width
, GLuint height
, GLint comps
,
1370 const void *source
, GLint srcRowStride
,
1371 void *dest
, GLint destRowStride
)
1374 const GLubyte
*data
;
1375 GLuint
*encoded
= (GLuint
*)dest
;
1376 void *newSource
= NULL
;
1378 assert(comps
== 3 || comps
== 4);
1380 /* Replicate image if width is not M8 or height is not M4 */
1381 if ((width
& 7) | (height
& 3)) {
1382 GLint newWidth
= (width
+ 7) & ~7;
1383 GLint newHeight
= (height
+ 3) & ~3;
1384 newSource
= _mesa_malloc(comps
* newWidth
* newHeight
* sizeof(GLchan
));
1386 GET_CURRENT_CONTEXT(ctx
);
1387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1390 _mesa_upscale_teximage2d(width
, height
, newWidth
, newHeight
,
1391 comps
, (const GLchan
*) source
,
1392 srcRowStride
, (GLchan
*) newSource
);
1396 srcRowStride
= comps
* newWidth
;
1399 /* convert from 16/32-bit channels to GLubyte if needed */
1400 if (CHAN_TYPE
!= GL_UNSIGNED_BYTE
) {
1401 const GLuint n
= width
* height
* comps
;
1402 const GLchan
*src
= (const GLchan
*) source
;
1403 GLubyte
*dest
= (GLubyte
*) _mesa_malloc(n
* sizeof(GLubyte
));
1406 GET_CURRENT_CONTEXT(ctx
);
1407 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture compression");
1410 for (i
= 0; i
< n
; i
++) {
1411 dest
[i
] = CHAN_TO_UBYTE(src
[i
]);
1413 if (newSource
!= NULL
) {
1414 _mesa_free(newSource
);
1416 newSource
= dest
; /* we'll free this buffer before returning */
1417 source
= dest
; /* the new, GLubyte incoming image */
1420 data
= (const GLubyte
*) source
;
1421 destRowStride
= (destRowStride
- width
* 2) / 4;
1422 for (y
= 0; y
< height
; y
+= 4) {
1423 GLuint offs
= 0 + (y
+ 0) * srcRowStride
;
1424 for (x
= 0; x
< width
; x
+= 8) {
1425 const GLubyte
*lines
[4];
1426 lines
[0] = &data
[offs
];
1427 lines
[1] = lines
[0] + srcRowStride
;
1428 lines
[2] = lines
[1] + srcRowStride
;
1429 lines
[3] = lines
[2] + srcRowStride
;
1431 fxt1_quantize(encoded
, lines
, comps
);
1432 /* 128 bits per 8x4 block */
1435 encoded
+= destRowStride
;
1439 if (newSource
!= NULL
) {
1440 _mesa_free(newSource
);
1445 /***************************************************************************\
1448 * The decoder is based on GL_3DFX_texture_compression_FXT1
1449 * specification and serves as a concept for the encoder.
1450 \***************************************************************************/
1453 /* lookup table for scaling 5 bit colors up to 8 bits */
1454 static const GLubyte _rgb_scale_5
[] = {
1455 0, 8, 16, 25, 33, 41, 49, 58,
1456 66, 74, 82, 90, 99, 107, 115, 123,
1457 132, 140, 148, 156, 165, 173, 181, 189,
1458 197, 206, 214, 222, 230, 239, 247, 255
1461 /* lookup table for scaling 6 bit colors up to 8 bits */
1462 static const GLubyte _rgb_scale_6
[] = {
1463 0, 4, 8, 12, 16, 20, 24, 28,
1464 32, 36, 40, 45, 49, 53, 57, 61,
1465 65, 69, 73, 77, 81, 85, 89, 93,
1466 97, 101, 105, 109, 113, 117, 121, 125,
1467 130, 134, 138, 142, 146, 150, 154, 158,
1468 162, 166, 170, 174, 178, 182, 186, 190,
1469 194, 198, 202, 206, 210, 215, 219, 223,
1470 227, 231, 235, 239, 243, 247, 251, 255
1474 #define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
1475 #define UP5(c) _rgb_scale_5[(c) & 31]
1476 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
1477 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
1481 fxt1_decode_1HI (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1486 cc
= (const GLuint
*)(code
+ t
/ 8);
1487 t
= (cc
[0] >> (t
& 7)) & 7;
1490 rgba
[RCOMP
] = rgba
[GCOMP
] = rgba
[BCOMP
] = rgba
[ACOMP
] = 0;
1493 cc
= (const GLuint
*)(code
+ 12);
1495 b
= UP5(CC_SEL(cc
, 0));
1496 g
= UP5(CC_SEL(cc
, 5));
1497 r
= UP5(CC_SEL(cc
, 10));
1498 } else if (t
== 6) {
1499 b
= UP5(CC_SEL(cc
, 15));
1500 g
= UP5(CC_SEL(cc
, 20));
1501 r
= UP5(CC_SEL(cc
, 25));
1503 b
= LERP(6, t
, UP5(CC_SEL(cc
, 0)), UP5(CC_SEL(cc
, 15)));
1504 g
= LERP(6, t
, UP5(CC_SEL(cc
, 5)), UP5(CC_SEL(cc
, 20)));
1505 r
= LERP(6, t
, UP5(CC_SEL(cc
, 10)), UP5(CC_SEL(cc
, 25)));
1507 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1508 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1509 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1510 rgba
[ACOMP
] = CHAN_MAX
;
1516 fxt1_decode_1CHROMA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1521 cc
= (const GLuint
*)code
;
1526 t
= (cc
[0] >> (t
* 2)) & 3;
1529 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1530 kk
= cc
[0] >> (t
& 7);
1531 rgba
[BCOMP
] = UBYTE_TO_CHAN( UP5(kk
) );
1532 rgba
[GCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 5) );
1533 rgba
[RCOMP
] = UBYTE_TO_CHAN( UP5(kk
>> 10) );
1534 rgba
[ACOMP
] = CHAN_MAX
;
1539 fxt1_decode_1MIXED (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1545 cc
= (const GLuint
*)code
;
1548 t
= (cc
[1] >> (t
* 2)) & 3;
1550 col
[0][BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1551 col
[0][GCOMP
] = CC_SEL(cc
, 99);
1552 col
[0][RCOMP
] = CC_SEL(cc
, 104);
1554 col
[1][BCOMP
] = CC_SEL(cc
, 109);
1555 col
[1][GCOMP
] = CC_SEL(cc
, 114);
1556 col
[1][RCOMP
] = CC_SEL(cc
, 119);
1557 glsb
= CC_SEL(cc
, 126);
1558 selb
= CC_SEL(cc
, 33);
1560 t
= (cc
[0] >> (t
* 2)) & 3;
1562 col
[0][BCOMP
] = CC_SEL(cc
, 64);
1563 col
[0][GCOMP
] = CC_SEL(cc
, 69);
1564 col
[0][RCOMP
] = CC_SEL(cc
, 74);
1566 col
[1][BCOMP
] = CC_SEL(cc
, 79);
1567 col
[1][GCOMP
] = CC_SEL(cc
, 84);
1568 col
[1][RCOMP
] = CC_SEL(cc
, 89);
1569 glsb
= CC_SEL(cc
, 125);
1570 selb
= CC_SEL(cc
, 1);
1573 if (CC_SEL(cc
, 124) & 1) {
1578 rgba
[RCOMP
] = rgba
[BCOMP
] = rgba
[GCOMP
] = rgba
[ACOMP
] = 0;
1582 b
= UP5(col
[0][BCOMP
]);
1583 g
= UP5(col
[0][GCOMP
]);
1584 r
= UP5(col
[0][RCOMP
]);
1585 } else if (t
== 2) {
1586 b
= UP5(col
[1][BCOMP
]);
1587 g
= UP6(col
[1][GCOMP
], glsb
);
1588 r
= UP5(col
[1][RCOMP
]);
1590 b
= (UP5(col
[0][BCOMP
]) + UP5(col
[1][BCOMP
])) / 2;
1591 g
= (UP5(col
[0][GCOMP
]) + UP6(col
[1][GCOMP
], glsb
)) / 2;
1592 r
= (UP5(col
[0][RCOMP
]) + UP5(col
[1][RCOMP
])) / 2;
1594 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1595 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1596 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1597 rgba
[ACOMP
] = CHAN_MAX
;
1603 b
= UP5(col
[0][BCOMP
]);
1604 g
= UP6(col
[0][GCOMP
], glsb
^ selb
);
1605 r
= UP5(col
[0][RCOMP
]);
1606 } else if (t
== 3) {
1607 b
= UP5(col
[1][BCOMP
]);
1608 g
= UP6(col
[1][GCOMP
], glsb
);
1609 r
= UP5(col
[1][RCOMP
]);
1611 b
= LERP(3, t
, UP5(col
[0][BCOMP
]), UP5(col
[1][BCOMP
]));
1612 g
= LERP(3, t
, UP6(col
[0][GCOMP
], glsb
^ selb
),
1613 UP6(col
[1][GCOMP
], glsb
));
1614 r
= LERP(3, t
, UP5(col
[0][RCOMP
]), UP5(col
[1][RCOMP
]));
1616 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1617 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1618 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1619 rgba
[ACOMP
] = CHAN_MAX
;
1625 fxt1_decode_1ALPHA (const GLubyte
*code
, GLint t
, GLchan
*rgba
)
1630 cc
= (const GLuint
*)code
;
1631 if (CC_SEL(cc
, 124) & 1) {
1637 t
= (cc
[1] >> (t
* 2)) & 3;
1639 col0
[BCOMP
] = (*(const GLuint
*)(code
+ 11)) >> 6;
1640 col0
[GCOMP
] = CC_SEL(cc
, 99);
1641 col0
[RCOMP
] = CC_SEL(cc
, 104);
1642 col0
[ACOMP
] = CC_SEL(cc
, 119);
1644 t
= (cc
[0] >> (t
* 2)) & 3;
1646 col0
[BCOMP
] = CC_SEL(cc
, 64);
1647 col0
[GCOMP
] = CC_SEL(cc
, 69);
1648 col0
[RCOMP
] = CC_SEL(cc
, 74);
1649 col0
[ACOMP
] = CC_SEL(cc
, 109);
1653 b
= UP5(col0
[BCOMP
]);
1654 g
= UP5(col0
[GCOMP
]);
1655 r
= UP5(col0
[RCOMP
]);
1656 a
= UP5(col0
[ACOMP
]);
1657 } else if (t
== 3) {
1658 b
= UP5(CC_SEL(cc
, 79));
1659 g
= UP5(CC_SEL(cc
, 84));
1660 r
= UP5(CC_SEL(cc
, 89));
1661 a
= UP5(CC_SEL(cc
, 114));
1663 b
= LERP(3, t
, UP5(col0
[BCOMP
]), UP5(CC_SEL(cc
, 79)));
1664 g
= LERP(3, t
, UP5(col0
[GCOMP
]), UP5(CC_SEL(cc
, 84)));
1665 r
= LERP(3, t
, UP5(col0
[RCOMP
]), UP5(CC_SEL(cc
, 89)));
1666 a
= LERP(3, t
, UP5(col0
[ACOMP
]), UP5(CC_SEL(cc
, 114)));
1675 t
= (cc
[0] >> (t
* 2)) & 3;
1682 cc
= (const GLuint
*)code
;
1683 a
= UP5(cc
[3] >> (t
* 5 + 13));
1685 cc
= (const GLuint
*)(code
+ 8 + t
/ 8);
1686 kk
= cc
[0] >> (t
& 7);
1692 rgba
[RCOMP
] = UBYTE_TO_CHAN(r
);
1693 rgba
[GCOMP
] = UBYTE_TO_CHAN(g
);
1694 rgba
[BCOMP
] = UBYTE_TO_CHAN(b
);
1695 rgba
[ACOMP
] = UBYTE_TO_CHAN(a
);
1700 fxt1_decode_1 (const void *texture
, GLint stride
, /* in pixels */
1701 GLint i
, GLint j
, GLchan
*rgba
)
1703 static void (*decode_1
[]) (const GLubyte
*, GLint
, GLchan
*) = {
1704 fxt1_decode_1HI
, /* cc-high = "00?" */
1705 fxt1_decode_1HI
, /* cc-high = "00?" */
1706 fxt1_decode_1CHROMA
, /* cc-chroma = "010" */
1707 fxt1_decode_1ALPHA
, /* alpha = "011" */
1708 fxt1_decode_1MIXED
, /* mixed = "1??" */
1709 fxt1_decode_1MIXED
, /* mixed = "1??" */
1710 fxt1_decode_1MIXED
, /* mixed = "1??" */
1711 fxt1_decode_1MIXED
/* mixed = "1??" */
1714 const GLubyte
*code
= (const GLubyte
*)texture
+
1715 ((j
/ 4) * (stride
/ 8) + (i
/ 8)) * 16;
1716 GLint mode
= CC_SEL(code
, 125);
1724 decode_1
[mode
](code
, t
, rgba
);