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_ubyte(GLubyte
*blkaddr
, GLubyte srccolors
[4][4],
52 GLint numxpixels
, GLint numypixels
);
53 static void signed_encode_rgtc_ubyte(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 GLubyte
*srcaddr
,
63 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
66 const GLubyte
*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
;
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 GLubyte
*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);
111 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
113 _mesa_get_format_base_format(dstFormat
),
114 srcWidth
, srcHeight
, srcDepth
,
115 srcFormat
, srcType
, srcAddr
,
118 return GL_FALSE
; /* out of memory */
120 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
122 texWidth
, dstSlices
[0]);
125 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
126 for (j
= 0; j
< srcHeight
; j
+=4) {
127 if (srcHeight
> j
+ 3) numypixels
= 4;
128 else numypixels
= srcHeight
- j
;
129 srcaddr
= tempImage
+ j
* srcWidth
;
130 for (i
= 0; i
< srcWidth
; i
+= 4) {
131 if (srcWidth
> i
+ 3) numxpixels
= 4;
132 else numxpixels
= srcWidth
- i
;
133 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
134 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
135 srcaddr
+= numxpixels
;
138 blkaddr
+= dstRowDiff
;
141 free((void *) tempImage
);
147 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS
)
150 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
151 const GLfloat
*tempImage
= NULL
;
153 int numxpixels
, numypixels
;
154 const GLfloat
*srcaddr
;
155 GLbyte srcpixels
[4][4];
158 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RED_RGTC1
||
159 dstFormat
== MESA_FORMAT_SIGNED_L_LATC1
);
160 ASSERT(dstXoffset
% 4 == 0);
161 ASSERT(dstYoffset
% 4 == 0);
162 ASSERT(dstZoffset
% 4 == 0);
165 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
167 _mesa_get_format_base_format(dstFormat
),
168 srcWidth
, srcHeight
, srcDepth
,
169 srcFormat
, srcType
, srcAddr
,
172 return GL_FALSE
; /* out of memory */
174 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
176 texWidth
, dstSlices
[0]);
179 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
180 for (j
= 0; j
< srcHeight
; j
+=4) {
181 if (srcHeight
> j
+ 3) numypixels
= 4;
182 else numypixels
= srcHeight
- j
;
183 srcaddr
= tempImage
+ j
* srcWidth
;
184 for (i
= 0; i
< srcWidth
; i
+= 4) {
185 if (srcWidth
> i
+ 3) numxpixels
= 4;
186 else numxpixels
= srcWidth
- i
;
187 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
188 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
189 srcaddr
+= numxpixels
;
192 blkaddr
+= dstRowDiff
;
195 free((void *) tempImage
);
201 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS
)
204 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
205 const GLubyte
*tempImage
= NULL
;
207 int numxpixels
, numypixels
;
208 const GLubyte
*srcaddr
;
209 GLubyte srcpixels
[4][4];
213 ASSERT(dstFormat
== MESA_FORMAT_RG_RGTC2
||
214 dstFormat
== MESA_FORMAT_LA_LATC2
);
215 ASSERT(dstXoffset
% 4 == 0);
216 ASSERT(dstYoffset
% 4 == 0);
217 ASSERT(dstZoffset
% 4 == 0);
220 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
222 _mesa_get_format_base_format(dstFormat
),
223 srcWidth
, srcHeight
, srcDepth
,
224 srcFormat
, srcType
, srcAddr
,
227 return GL_FALSE
; /* out of memory */
229 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
231 texWidth
, dstSlices
[0]);
234 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
235 for (j
= 0; j
< srcHeight
; j
+=4) {
236 if (srcHeight
> j
+ 3) numypixels
= 4;
237 else numypixels
= srcHeight
- j
;
238 srcaddr
= tempImage
+ j
* srcWidth
* 2;
239 for (i
= 0; i
< srcWidth
; i
+= 4) {
240 if (srcWidth
> i
+ 3) numxpixels
= 4;
241 else numxpixels
= srcWidth
- i
;
242 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
243 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
246 extractsrc_u(srcpixels
, (GLubyte
*)srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
247 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
251 srcaddr
+= numxpixels
* 2;
253 blkaddr
+= dstRowDiff
;
256 free((void *) tempImage
);
262 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS
)
265 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
266 const GLfloat
*tempImage
= NULL
;
268 int numxpixels
, numypixels
;
269 const GLfloat
*srcaddr
;
270 GLbyte srcpixels
[4][4];
274 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RG_RGTC2
||
275 dstFormat
== MESA_FORMAT_SIGNED_LA_LATC2
);
276 ASSERT(dstXoffset
% 4 == 0);
277 ASSERT(dstYoffset
% 4 == 0);
278 ASSERT(dstZoffset
% 4 == 0);
281 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
283 _mesa_get_format_base_format(dstFormat
),
284 srcWidth
, srcHeight
, srcDepth
,
285 srcFormat
, srcType
, srcAddr
,
288 return GL_FALSE
; /* out of memory */
290 dst
= (GLbyte
*)_mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
292 texWidth
, dstSlices
[0]);
295 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
296 for (j
= 0; j
< srcHeight
; j
+= 4) {
297 if (srcHeight
> j
+ 3) numypixels
= 4;
298 else numypixels
= srcHeight
- j
;
299 srcaddr
= tempImage
+ j
* srcWidth
* 2;
300 for (i
= 0; i
< srcWidth
; i
+= 4) {
301 if (srcWidth
> i
+ 3) numxpixels
= 4;
302 else numxpixels
= srcWidth
- i
;
304 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
305 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
308 extractsrc_s(srcpixels
, srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
309 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
312 srcaddr
+= numxpixels
* 2;
315 blkaddr
+= dstRowDiff
;
318 free((void *) tempImage
);
324 _mesa_fetch_texel_2d_f_red_rgtc1(const struct swrast_texture_image
*texImage
,
325 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
328 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
,
330 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
337 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct swrast_texture_image
*texImage
,
338 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
341 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
343 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
350 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct swrast_texture_image
*texImage
,
351 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
354 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
,
356 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
+ 8,
358 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
359 texel
[GCOMP
] = UBYTE_TO_FLOAT(green
);
365 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct swrast_texture_image
*texImage
,
366 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
369 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
371 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
) + 8,
373 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
374 texel
[GCOMP
] = BYTE_TO_FLOAT_TEX(green
);
380 _mesa_fetch_texel_2d_f_l_latc1(const struct swrast_texture_image
*texImage
,
381 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
384 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
,
388 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
393 _mesa_fetch_texel_2d_f_signed_l_latc1(const struct swrast_texture_image
*texImage
,
394 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
397 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
401 texel
[BCOMP
] = BYTE_TO_FLOAT_TEX(red
);
406 _mesa_fetch_texel_2d_f_la_latc2(const struct swrast_texture_image
*texImage
,
407 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
410 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
,
412 unsigned_fetch_texel_rgtc(texImage
->RowStride
, texImage
->Data
+ 8,
416 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
417 texel
[ACOMP
] = UBYTE_TO_FLOAT(green
);
421 _mesa_fetch_texel_2d_f_signed_la_latc2(const struct swrast_texture_image
*texImage
,
422 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
425 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
),
427 signed_fetch_texel_rgtc(texImage
->RowStride
, (GLbyte
*)(texImage
->Data
) + 8,
431 texel
[BCOMP
] = BYTE_TO_FLOAT_TEX(red
);
432 texel
[ACOMP
] = BYTE_TO_FLOAT_TEX(green
);
435 #define TAG(x) unsigned_##x
441 #include "texcompress_rgtc_tmp.h"
448 #define TAG(x) signed_##x
450 #define T_MIN (GLbyte)-128
451 #define T_MAX (GLbyte)127
453 #include "texcompress_rgtc_tmp.h"