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"
46 #include "swrast/s_context.h"
51 static void unsigned_encode_rgtc_chan(GLubyte
*blkaddr
, GLubyte srccolors
[4][4],
52 GLint numxpixels
, GLint numypixels
);
53 static void signed_encode_rgtc_chan(GLbyte
*blkaddr
, GLbyte srccolors
[4][4],
54 GLint numxpixels
, GLint numypixels
);
56 static void unsigned_fetch_texel_rgtc(unsigned srcRowStride
, const GLubyte
*pixdata
,
57 unsigned i
, unsigned j
, GLubyte
*value
, unsigned comps
);
59 static void signed_fetch_texel_rgtc(unsigned srcRowStride
, const GLbyte
*pixdata
,
60 unsigned i
, unsigned j
, GLbyte
*value
, unsigned comps
);
62 static void extractsrc_u( GLubyte srcpixels
[4][4], const GLchan
*srcaddr
,
63 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
66 const GLchan
*curaddr
;
67 for (j
= 0; j
< numypixels
; j
++) {
68 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
69 for (i
= 0; i
< numxpixels
; i
++) {
70 srcpixels
[j
][i
] = *curaddr
/ (CHAN_MAX
/ 255);
76 static void extractsrc_s( GLbyte srcpixels
[4][4], const GLfloat
*srcaddr
,
77 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
80 const GLfloat
*curaddr
;
81 for (j
= 0; j
< numypixels
; j
++) {
82 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
83 for (i
= 0; i
< numxpixels
; i
++) {
84 srcpixels
[j
][i
] = FLOAT_TO_BYTE_TEX(*curaddr
);
92 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS
)
95 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
96 const GLubyte
*tempImage
= NULL
;
98 int numxpixels
, numypixels
;
99 const GLchan
*srcaddr
;
100 GLubyte srcpixels
[4][4];
103 ASSERT(dstFormat
== MESA_FORMAT_RED_RGTC1
||
104 dstFormat
== MESA_FORMAT_L_LATC1
);
105 ASSERT(dstXoffset
% 4 == 0);
106 ASSERT(dstYoffset
% 4 == 0);
107 ASSERT(dstZoffset
% 4 == 0);
109 (void) dstImageOffsets
;
112 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
114 _mesa_get_format_base_format(dstFormat
),
115 srcWidth
, srcHeight
, srcDepth
,
116 srcFormat
, srcType
, srcAddr
,
119 return GL_FALSE
; /* out of memory */
121 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
123 texWidth
, (GLubyte
*) dstAddr
);
126 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
127 for (j
= 0; j
< srcHeight
; j
+=4) {
128 if (srcHeight
> j
+ 3) numypixels
= 4;
129 else numypixels
= srcHeight
- j
;
130 srcaddr
= tempImage
+ j
* srcWidth
;
131 for (i
= 0; i
< srcWidth
; i
+= 4) {
132 if (srcWidth
> i
+ 3) numxpixels
= 4;
133 else numxpixels
= srcWidth
- i
;
134 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
135 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
136 srcaddr
+= numxpixels
;
139 blkaddr
+= dstRowDiff
;
142 free((void *) tempImage
);
148 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS
)
151 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
152 const GLfloat
*tempImage
= NULL
;
154 int numxpixels
, numypixels
;
155 const GLfloat
*srcaddr
;
156 GLbyte srcpixels
[4][4];
159 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RED_RGTC1
||
160 dstFormat
== MESA_FORMAT_SIGNED_L_LATC1
);
161 ASSERT(dstXoffset
% 4 == 0);
162 ASSERT(dstYoffset
% 4 == 0);
163 ASSERT(dstZoffset
% 4 == 0);
165 (void) dstImageOffsets
;
167 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
169 _mesa_get_format_base_format(dstFormat
),
170 srcWidth
, srcHeight
, srcDepth
,
171 srcFormat
, srcType
, srcAddr
,
174 return GL_FALSE
; /* out of memory */
176 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
178 texWidth
, (GLubyte
*) dstAddr
);
181 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
182 for (j
= 0; j
< srcHeight
; j
+=4) {
183 if (srcHeight
> j
+ 3) numypixels
= 4;
184 else numypixels
= srcHeight
- j
;
185 srcaddr
= tempImage
+ j
* srcWidth
;
186 for (i
= 0; i
< srcWidth
; i
+= 4) {
187 if (srcWidth
> i
+ 3) numxpixels
= 4;
188 else numxpixels
= srcWidth
- i
;
189 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
190 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
191 srcaddr
+= numxpixels
;
194 blkaddr
+= dstRowDiff
;
197 free((void *) tempImage
);
203 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS
)
206 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
207 const GLubyte
*tempImage
= NULL
;
209 int numxpixels
, numypixels
;
210 const GLchan
*srcaddr
;
211 GLubyte srcpixels
[4][4];
215 ASSERT(dstFormat
== MESA_FORMAT_RG_RGTC2
||
216 dstFormat
== MESA_FORMAT_LA_LATC2
);
217 ASSERT(dstXoffset
% 4 == 0);
218 ASSERT(dstYoffset
% 4 == 0);
219 ASSERT(dstZoffset
% 4 == 0);
221 (void) dstImageOffsets
;
223 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
225 _mesa_get_format_base_format(dstFormat
),
226 srcWidth
, srcHeight
, srcDepth
,
227 srcFormat
, srcType
, srcAddr
,
230 return GL_FALSE
; /* out of memory */
232 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
234 texWidth
, (GLubyte
*) dstAddr
);
237 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
238 for (j
= 0; j
< srcHeight
; j
+=4) {
239 if (srcHeight
> j
+ 3) numypixels
= 4;
240 else numypixels
= srcHeight
- j
;
241 srcaddr
= tempImage
+ j
* srcWidth
* 2;
242 for (i
= 0; i
< srcWidth
; i
+= 4) {
243 if (srcWidth
> i
+ 3) numxpixels
= 4;
244 else numxpixels
= srcWidth
- i
;
245 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
246 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
249 extractsrc_u(srcpixels
, (GLchan
*)srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
250 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
254 srcaddr
+= numxpixels
* 2;
256 blkaddr
+= dstRowDiff
;
259 free((void *) tempImage
);
265 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS
)
268 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
269 const GLfloat
*tempImage
= NULL
;
271 int numxpixels
, numypixels
;
272 const GLfloat
*srcaddr
;
273 GLbyte srcpixels
[4][4];
277 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RG_RGTC2
||
278 dstFormat
== MESA_FORMAT_SIGNED_LA_LATC2
);
279 ASSERT(dstXoffset
% 4 == 0);
280 ASSERT(dstYoffset
% 4 == 0);
281 ASSERT(dstZoffset
% 4 == 0);
283 (void) dstImageOffsets
;
285 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
287 _mesa_get_format_base_format(dstFormat
),
288 srcWidth
, srcHeight
, srcDepth
,
289 srcFormat
, srcType
, srcAddr
,
292 return GL_FALSE
; /* out of memory */
294 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
296 texWidth
, (GLubyte
*) dstAddr
);
299 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
300 for (j
= 0; j
< srcHeight
; j
+= 4) {
301 if (srcHeight
> j
+ 3) numypixels
= 4;
302 else numypixels
= srcHeight
- j
;
303 srcaddr
= tempImage
+ j
* srcWidth
* 2;
304 for (i
= 0; i
< srcWidth
; i
+= 4) {
305 if (srcWidth
> i
+ 3) numxpixels
= 4;
306 else numxpixels
= srcWidth
- i
;
308 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
309 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
312 extractsrc_s(srcpixels
, srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
313 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
316 srcaddr
+= numxpixels
* 2;
319 blkaddr
+= dstRowDiff
;
322 free((void *) tempImage
);
328 _mesa_fetch_texel_2d_f_red_rgtc1(const struct swrast_texture_image
*texImage
,
329 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
332 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
),
334 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
341 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct swrast_texture_image
*texImage
,
342 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
345 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
),
347 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
354 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct swrast_texture_image
*texImage
,
355 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
358 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
),
360 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
) + 8,
362 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
363 texel
[GCOMP
] = UBYTE_TO_FLOAT(green
);
369 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct swrast_texture_image
*texImage
,
370 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
373 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
),
375 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
) + 8,
377 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
378 texel
[GCOMP
] = BYTE_TO_FLOAT_TEX(green
);
384 _mesa_fetch_texel_2d_f_l_latc1(const struct swrast_texture_image
*texImage
,
385 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
388 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
),
392 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
397 _mesa_fetch_texel_2d_f_signed_l_latc1(const struct swrast_texture_image
*texImage
,
398 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
401 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
),
405 texel
[BCOMP
] = BYTE_TO_FLOAT_TEX(red
);
410 _mesa_fetch_texel_2d_f_la_latc2(const struct swrast_texture_image
*texImage
,
411 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
414 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
),
416 unsigned_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLubyte
*)(texImage
->Base
.Data
) + 8,
420 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
421 texel
[ACOMP
] = UBYTE_TO_FLOAT(green
);
425 _mesa_fetch_texel_2d_f_signed_la_latc2(const struct swrast_texture_image
*texImage
,
426 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
429 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
),
431 signed_fetch_texel_rgtc(texImage
->Base
.RowStride
, (GLbyte
*)(texImage
->Base
.Data
) + 8,
435 texel
[BCOMP
] = BYTE_TO_FLOAT_TEX(red
);
436 texel
[ACOMP
] = BYTE_TO_FLOAT_TEX(green
);
439 #define TAG(x) unsigned_##x
445 #include "texcompress_rgtc_tmp.h"
452 #define TAG(x) signed_##x
454 #define T_MIN (GLbyte)-128
455 #define T_MAX (GLbyte)127
457 #include "texcompress_rgtc_tmp.h"