2 * Copyright (C) 2011 Red Hat Inc.
4 * block compression parts are:
5 * Copyright (C) 2004 Roland Scheidegger 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 (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
31 * \file texcompress_rgtc.c
32 * GL_EXT_texture_compression_rgtc support.
41 #include "mfeatures.h"
43 #include "texcompress.h"
44 #include "texcompress_rgtc.h"
49 static void unsigned_encode_rgtc_chan(GLubyte
*blkaddr
, GLubyte srccolors
[4][4],
50 GLint numxpixels
, GLint numypixels
);
51 static void signed_encode_rgtc_chan(GLbyte
*blkaddr
, GLbyte srccolors
[4][4],
52 GLint numxpixels
, GLint numypixels
);
54 static void extractsrc_u( GLubyte srcpixels
[4][4], const GLchan
*srcaddr
,
55 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
58 const GLchan
*curaddr
;
59 for (j
= 0; j
< numypixels
; j
++) {
60 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
61 for (i
= 0; i
< numxpixels
; i
++) {
62 srcpixels
[j
][i
] = *curaddr
/ (CHAN_MAX
/ 255);
68 static void extractsrc_s( GLbyte srcpixels
[4][4], const GLfloat
*srcaddr
,
69 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
72 const GLfloat
*curaddr
;
73 for (j
= 0; j
< numypixels
; j
++) {
74 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
75 for (i
= 0; i
< numxpixels
; i
++) {
76 srcpixels
[j
][i
] = FLOAT_TO_BYTE_TEX(*curaddr
);
84 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS
)
87 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
88 const GLchan
*tempImage
= NULL
;
90 int numxpixels
, numypixels
;
91 const GLchan
*srcaddr
;
92 GLubyte srcpixels
[4][4];
95 ASSERT(dstFormat
== MESA_FORMAT_RED_RGTC1
);
96 ASSERT(dstXoffset
% 4 == 0);
97 ASSERT(dstYoffset
% 4 == 0);
98 ASSERT(dstZoffset
% 4 == 0);
100 (void) dstImageOffsets
;
103 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
105 _mesa_get_format_base_format(dstFormat
),
106 srcWidth
, srcHeight
, srcDepth
,
107 srcFormat
, srcType
, srcAddr
,
110 return GL_FALSE
; /* out of memory */
112 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
114 texWidth
, (GLubyte
*) dstAddr
);
117 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
118 for (j
= 0; j
< srcHeight
; j
+=4) {
119 if (srcHeight
> j
+ 3) numypixels
= 4;
120 else numypixels
= srcHeight
- j
;
121 srcaddr
= tempImage
+ j
* srcWidth
;
122 for (i
= 0; i
< srcWidth
; i
+= 4) {
123 if (srcWidth
> i
+ 3) numxpixels
= 4;
124 else numxpixels
= srcWidth
- i
;
125 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
126 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
127 srcaddr
+= numxpixels
;
130 blkaddr
+= dstRowDiff
;
133 free((void *) tempImage
);
139 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS
)
142 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
143 const GLfloat
*tempImage
= NULL
;
145 int numxpixels
, numypixels
;
146 const GLfloat
*srcaddr
;
147 GLbyte srcpixels
[4][4];
150 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RED_RGTC1
);
151 ASSERT(dstXoffset
% 4 == 0);
152 ASSERT(dstYoffset
% 4 == 0);
153 ASSERT(dstZoffset
% 4 == 0);
155 (void) dstImageOffsets
;
157 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
159 _mesa_get_format_base_format(dstFormat
),
160 srcWidth
, srcHeight
, srcDepth
,
161 srcFormat
, srcType
, srcAddr
,
164 return GL_FALSE
; /* out of memory */
166 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
168 texWidth
, (GLubyte
*) dstAddr
);
171 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
172 for (j
= 0; j
< srcHeight
; j
+=4) {
173 if (srcHeight
> j
+ 3) numypixels
= 4;
174 else numypixels
= srcHeight
- j
;
175 srcaddr
= tempImage
+ j
* srcWidth
;
176 for (i
= 0; i
< srcWidth
; i
+= 4) {
177 if (srcWidth
> i
+ 3) numxpixels
= 4;
178 else numxpixels
= srcWidth
- i
;
179 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
180 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
181 srcaddr
+= numxpixels
;
184 blkaddr
+= dstRowDiff
;
187 free((void *) tempImage
);
193 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS
)
196 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
197 const GLchan
*tempImage
= NULL
;
199 int numxpixels
, numypixels
;
200 const GLchan
*srcaddr
;
201 GLubyte srcpixels
[4][4];
205 ASSERT(dstFormat
== MESA_FORMAT_RG_RGTC2
);
206 ASSERT(dstXoffset
% 4 == 0);
207 ASSERT(dstYoffset
% 4 == 0);
208 ASSERT(dstZoffset
% 4 == 0);
210 (void) dstImageOffsets
;
212 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
214 _mesa_get_format_base_format(dstFormat
),
215 srcWidth
, srcHeight
, srcDepth
,
216 srcFormat
, srcType
, srcAddr
,
219 return GL_FALSE
; /* out of memory */
221 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
223 texWidth
, (GLubyte
*) dstAddr
);
226 dstRowDiff
= dstRowStride
>= (srcWidth
* 8) ? dstRowStride
- (((srcWidth
+ 7) & ~7) * 8) : 0;
227 for (j
= 0; j
< srcHeight
; j
+=4) {
228 if (srcHeight
> j
+ 3) numypixels
= 4;
229 else numypixels
= srcHeight
- j
;
230 srcaddr
= tempImage
+ j
* srcWidth
* 2;
231 for (i
= 0; i
< srcWidth
; i
+= 4) {
232 if (srcWidth
> i
+ 3) numxpixels
= 4;
233 else numxpixels
= srcWidth
- i
;
234 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
235 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
238 extractsrc_u(srcpixels
, (GLchan
*)srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
239 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
243 srcaddr
+= numxpixels
* 2;
245 blkaddr
+= dstRowDiff
;
248 free((void *) tempImage
);
254 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS
)
257 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
258 const GLfloat
*tempImage
= NULL
;
260 int numxpixels
, numypixels
;
261 const GLfloat
*srcaddr
;
262 GLbyte srcpixels
[4][4];
266 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RG_RGTC2
);
267 ASSERT(dstXoffset
% 4 == 0);
268 ASSERT(dstYoffset
% 4 == 0);
269 ASSERT(dstZoffset
% 4 == 0);
271 (void) dstImageOffsets
;
273 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
275 _mesa_get_format_base_format(dstFormat
),
276 srcWidth
, srcHeight
, srcDepth
,
277 srcFormat
, srcType
, srcAddr
,
280 return GL_FALSE
; /* out of memory */
282 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
284 texWidth
, (GLubyte
*) dstAddr
);
287 dstRowDiff
= dstRowStride
>= (srcWidth
* 8) ? dstRowStride
- (((srcWidth
+ 7) & ~7) * 8) : 0;
288 for (j
= 0; j
< srcHeight
; j
+= 4) {
289 if (srcHeight
> j
+ 3) numypixels
= 4;
290 else numypixels
= srcHeight
- j
;
291 srcaddr
= tempImage
+ j
* srcWidth
* 2;
292 for (i
= 0; i
< srcWidth
; i
+= 4) {
293 if (srcWidth
> i
+ 3) numxpixels
= 4;
294 else numxpixels
= srcWidth
- i
;
296 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
297 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
300 extractsrc_s(srcpixels
, srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
301 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
304 srcaddr
+= numxpixels
* 2;
307 blkaddr
+= dstRowDiff
;
310 free((void *) tempImage
);
315 static void _fetch_texel_rgtc_u(GLint srcRowStride
, const GLubyte
*pixdata
,
316 GLint i
, GLint j
, GLchan
*value
, int comps
)
319 const GLubyte
*blksrc
= (pixdata
+ ((srcRowStride
+ 3) / 4 * (j
/ 4) + (i
/ 4)) * 8 * comps
);
320 const GLubyte alpha0
= blksrc
[0];
321 const GLubyte alpha1
= blksrc
[1];
322 const GLubyte bit_pos
= ((j
&3) * 4 + (i
&3)) * 3;
323 const GLubyte acodelow
= blksrc
[2 + bit_pos
/ 8];
324 const GLubyte acodehigh
= blksrc
[3 + bit_pos
/ 8];
325 const GLubyte code
= (acodelow
>> (bit_pos
& 0x7) |
326 (acodehigh
<< (8 - (bit_pos
& 0x7)))) & 0x7;
329 decode
= UBYTE_TO_CHAN( alpha0
);
331 decode
= UBYTE_TO_CHAN( alpha1
);
332 else if (alpha0
> alpha1
)
333 decode
= UBYTE_TO_CHAN( ((alpha0
* (8 - code
) + (alpha1
* (code
- 1))) / 7) );
335 decode
= UBYTE_TO_CHAN( ((alpha0
* (6 - code
) + (alpha1
* (code
- 1))) / 5) );
345 static void _fetch_texel_rgtc_s(GLint srcRowStride
, const GLbyte
*pixdata
,
346 GLint i
, GLint j
, GLbyte
*value
, int comps
)
349 const GLbyte
*blksrc
= (pixdata
+ ((srcRowStride
+ 3) / 4 * (j
/ 4) + (i
/ 4)) * 8 * comps
);
350 const GLbyte alpha0
= blksrc
[0];
351 const GLbyte alpha1
= blksrc
[1];
352 const GLbyte bit_pos
= ((j
&3) * 4 + (i
&3)) * 3;
353 const GLbyte acodelow
= blksrc
[2 + bit_pos
/ 8];
354 const GLbyte acodehigh
= blksrc
[3 + bit_pos
/ 8];
355 const GLbyte code
= (acodelow
>> (bit_pos
& 0x7) |
356 (acodehigh
<< (8 - (bit_pos
& 0x7)))) & 0x7;
362 else if (alpha0
> alpha1
)
363 decode
= ((alpha0
* (8 - code
) + (alpha1
* (code
- 1))) / 7);
365 decode
= ((alpha0
* (6 - code
) + (alpha1
* (code
- 1))) / 5);
375 _mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image
*texImage
,
376 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
379 _fetch_texel_rgtc_u(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
),
381 texel
[RCOMP
] = CHAN_TO_FLOAT(red
);
388 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image
*texImage
,
389 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
392 _fetch_texel_rgtc_s(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
394 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
401 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image
*texImage
,
402 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
405 _fetch_texel_rgtc_u(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
),
407 _fetch_texel_rgtc_u(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
) + 8,
409 texel
[RCOMP
] = CHAN_TO_FLOAT(red
);
410 texel
[GCOMP
] = CHAN_TO_FLOAT(green
);
416 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image
*texImage
,
417 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
420 _fetch_texel_rgtc_s(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
422 _fetch_texel_rgtc_s(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
) + 8,
424 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
425 texel
[GCOMP
] = BYTE_TO_FLOAT_TEX(green
);
430 #define TAG(x) unsigned_##x
436 #include "texcompress_rgtc_tmp.h"
443 #define TAG(x) signed_##x
445 #define T_MIN (GLbyte)-127
446 #define T_MAX (GLbyte)127
448 #include "texcompress_rgtc_tmp.h"