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 unsigned_fetch_texel_rgtc(unsigned srcRowStride
, const GLubyte
*pixdata
,
55 unsigned i
, unsigned j
, GLubyte
*value
, unsigned comps
);
57 static void signed_fetch_texel_rgtc(unsigned srcRowStride
, const GLbyte
*pixdata
,
58 unsigned i
, unsigned j
, GLbyte
*value
, unsigned comps
);
60 static void extractsrc_u( GLubyte srcpixels
[4][4], const GLchan
*srcaddr
,
61 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
64 const GLchan
*curaddr
;
65 for (j
= 0; j
< numypixels
; j
++) {
66 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
67 for (i
= 0; i
< numxpixels
; i
++) {
68 srcpixels
[j
][i
] = *curaddr
/ (CHAN_MAX
/ 255);
74 static void extractsrc_s( GLbyte srcpixels
[4][4], const GLfloat
*srcaddr
,
75 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
78 const GLfloat
*curaddr
;
79 for (j
= 0; j
< numypixels
; j
++) {
80 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
81 for (i
= 0; i
< numxpixels
; i
++) {
82 srcpixels
[j
][i
] = FLOAT_TO_BYTE_TEX(*curaddr
);
90 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS
)
93 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
94 const GLchan
*tempImage
= NULL
;
96 int numxpixels
, numypixels
;
97 const GLchan
*srcaddr
;
98 GLubyte srcpixels
[4][4];
101 ASSERT(dstFormat
== MESA_FORMAT_RED_RGTC1
);
102 ASSERT(dstXoffset
% 4 == 0);
103 ASSERT(dstYoffset
% 4 == 0);
104 ASSERT(dstZoffset
% 4 == 0);
106 (void) dstImageOffsets
;
109 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
111 _mesa_get_format_base_format(dstFormat
),
112 srcWidth
, srcHeight
, srcDepth
,
113 srcFormat
, srcType
, srcAddr
,
116 return GL_FALSE
; /* out of memory */
118 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
120 texWidth
, (GLubyte
*) dstAddr
);
123 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
124 for (j
= 0; j
< srcHeight
; j
+=4) {
125 if (srcHeight
> j
+ 3) numypixels
= 4;
126 else numypixels
= srcHeight
- j
;
127 srcaddr
= tempImage
+ j
* srcWidth
;
128 for (i
= 0; i
< srcWidth
; i
+= 4) {
129 if (srcWidth
> i
+ 3) numxpixels
= 4;
130 else numxpixels
= srcWidth
- i
;
131 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
132 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
133 srcaddr
+= numxpixels
;
136 blkaddr
+= dstRowDiff
;
139 free((void *) tempImage
);
145 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS
)
148 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
149 const GLfloat
*tempImage
= NULL
;
151 int numxpixels
, numypixels
;
152 const GLfloat
*srcaddr
;
153 GLbyte srcpixels
[4][4];
156 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RED_RGTC1
);
157 ASSERT(dstXoffset
% 4 == 0);
158 ASSERT(dstYoffset
% 4 == 0);
159 ASSERT(dstZoffset
% 4 == 0);
161 (void) dstImageOffsets
;
163 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
165 _mesa_get_format_base_format(dstFormat
),
166 srcWidth
, srcHeight
, srcDepth
,
167 srcFormat
, srcType
, srcAddr
,
170 return GL_FALSE
; /* out of memory */
172 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
174 texWidth
, (GLubyte
*) dstAddr
);
177 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
178 for (j
= 0; j
< srcHeight
; j
+=4) {
179 if (srcHeight
> j
+ 3) numypixels
= 4;
180 else numypixels
= srcHeight
- j
;
181 srcaddr
= tempImage
+ j
* srcWidth
;
182 for (i
= 0; i
< srcWidth
; i
+= 4) {
183 if (srcWidth
> i
+ 3) numxpixels
= 4;
184 else numxpixels
= srcWidth
- i
;
185 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
186 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
187 srcaddr
+= numxpixels
;
190 blkaddr
+= dstRowDiff
;
193 free((void *) tempImage
);
199 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS
)
202 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
203 const GLchan
*tempImage
= NULL
;
205 int numxpixels
, numypixels
;
206 const GLchan
*srcaddr
;
207 GLubyte srcpixels
[4][4];
211 ASSERT(dstFormat
== MESA_FORMAT_RG_RGTC2
);
212 ASSERT(dstXoffset
% 4 == 0);
213 ASSERT(dstYoffset
% 4 == 0);
214 ASSERT(dstZoffset
% 4 == 0);
216 (void) dstImageOffsets
;
218 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
220 _mesa_get_format_base_format(dstFormat
),
221 srcWidth
, srcHeight
, srcDepth
,
222 srcFormat
, srcType
, srcAddr
,
225 return GL_FALSE
; /* out of memory */
227 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
229 texWidth
, (GLubyte
*) dstAddr
);
232 dstRowDiff
= dstRowStride
>= (srcWidth
* 8) ? dstRowStride
- (((srcWidth
+ 7) & ~7) * 8) : 0;
233 for (j
= 0; j
< srcHeight
; j
+=4) {
234 if (srcHeight
> j
+ 3) numypixels
= 4;
235 else numypixels
= srcHeight
- j
;
236 srcaddr
= tempImage
+ j
* srcWidth
* 2;
237 for (i
= 0; i
< srcWidth
; i
+= 4) {
238 if (srcWidth
> i
+ 3) numxpixels
= 4;
239 else numxpixels
= srcWidth
- i
;
240 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
241 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
244 extractsrc_u(srcpixels
, (GLchan
*)srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
245 unsigned_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
249 srcaddr
+= numxpixels
* 2;
251 blkaddr
+= dstRowDiff
;
254 free((void *) tempImage
);
260 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS
)
263 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
264 const GLfloat
*tempImage
= NULL
;
266 int numxpixels
, numypixels
;
267 const GLfloat
*srcaddr
;
268 GLbyte srcpixels
[4][4];
272 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RG_RGTC2
);
273 ASSERT(dstXoffset
% 4 == 0);
274 ASSERT(dstYoffset
% 4 == 0);
275 ASSERT(dstZoffset
% 4 == 0);
277 (void) dstImageOffsets
;
279 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
281 _mesa_get_format_base_format(dstFormat
),
282 srcWidth
, srcHeight
, srcDepth
,
283 srcFormat
, srcType
, srcAddr
,
286 return GL_FALSE
; /* out of memory */
288 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
290 texWidth
, (GLubyte
*) dstAddr
);
293 dstRowDiff
= dstRowStride
>= (srcWidth
* 8) ? dstRowStride
- (((srcWidth
+ 7) & ~7) * 8) : 0;
294 for (j
= 0; j
< srcHeight
; j
+= 4) {
295 if (srcHeight
> j
+ 3) numypixels
= 4;
296 else numypixels
= srcHeight
- j
;
297 srcaddr
= tempImage
+ j
* srcWidth
* 2;
298 for (i
= 0; i
< srcWidth
; i
+= 4) {
299 if (srcWidth
> i
+ 3) numxpixels
= 4;
300 else numxpixels
= srcWidth
- i
;
302 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
303 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
306 extractsrc_s(srcpixels
, srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
307 signed_encode_rgtc_chan(blkaddr
, srcpixels
, numxpixels
, numypixels
);
310 srcaddr
+= numxpixels
* 2;
313 blkaddr
+= dstRowDiff
;
316 free((void *) tempImage
);
322 _mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image
*texImage
,
323 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
326 unsigned_fetch_texel_rgtc(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
),
328 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
335 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image
*texImage
,
336 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
339 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
341 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
348 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image
*texImage
,
349 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
352 unsigned_fetch_texel_rgtc(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
),
354 unsigned_fetch_texel_rgtc(texImage
->RowStride
, (GLubyte
*)(texImage
->Data
) + 8,
356 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
357 texel
[GCOMP
] = UBYTE_TO_FLOAT(green
);
363 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image
*texImage
,
364 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
367 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
369 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
) + 8,
371 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
372 texel
[GCOMP
] = BYTE_TO_FLOAT_TEX(green
);
377 #define TAG(x) unsigned_##x
383 #include "texcompress_rgtc_tmp.h"
390 #define TAG(x) signed_##x
392 #define T_MIN (GLbyte)-128
393 #define T_MAX (GLbyte)127
395 #include "texcompress_rgtc_tmp.h"