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"
50 static void unsigned_encode_rgtc_ubyte(GLubyte
*blkaddr
, GLubyte srccolors
[4][4],
51 GLint numxpixels
, GLint numypixels
);
52 static void signed_encode_rgtc_ubyte(GLbyte
*blkaddr
, GLbyte srccolors
[4][4],
53 GLint numxpixels
, GLint numypixels
);
55 static void unsigned_fetch_texel_rgtc(unsigned srcRowStride
, const GLubyte
*pixdata
,
56 unsigned i
, unsigned j
, GLubyte
*value
, unsigned comps
);
58 static void signed_fetch_texel_rgtc(unsigned srcRowStride
, const GLbyte
*pixdata
,
59 unsigned i
, unsigned j
, GLbyte
*value
, unsigned comps
);
61 static void extractsrc_u( GLubyte srcpixels
[4][4], const GLubyte
*srcaddr
,
62 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
65 const GLubyte
*curaddr
;
66 for (j
= 0; j
< numypixels
; j
++) {
67 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
68 for (i
= 0; i
< numxpixels
; i
++) {
69 srcpixels
[j
][i
] = *curaddr
;
75 static void extractsrc_s( GLbyte srcpixels
[4][4], const GLfloat
*srcaddr
,
76 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
79 const GLfloat
*curaddr
;
80 for (j
= 0; j
< numypixels
; j
++) {
81 curaddr
= srcaddr
+ j
* srcRowStride
* comps
;
82 for (i
= 0; i
< numxpixels
; i
++) {
83 srcpixels
[j
][i
] = FLOAT_TO_BYTE_TEX(*curaddr
);
91 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS
)
94 const GLubyte
*tempImage
= NULL
;
96 int numxpixels
, numypixels
;
97 const GLubyte
*srcaddr
;
98 GLubyte srcpixels
[4][4];
101 ASSERT(dstFormat
== MESA_FORMAT_RED_RGTC1
||
102 dstFormat
== MESA_FORMAT_L_LATC1
);
104 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
106 _mesa_get_format_base_format(dstFormat
),
107 srcWidth
, srcHeight
, srcDepth
,
108 srcFormat
, srcType
, srcAddr
,
111 return GL_FALSE
; /* out of memory */
116 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
117 for (j
= 0; j
< srcHeight
; j
+=4) {
118 if (srcHeight
> j
+ 3) numypixels
= 4;
119 else numypixels
= srcHeight
- j
;
120 srcaddr
= tempImage
+ j
* srcWidth
;
121 for (i
= 0; i
< srcWidth
; i
+= 4) {
122 if (srcWidth
> i
+ 3) numxpixels
= 4;
123 else numxpixels
= srcWidth
- i
;
124 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
125 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
126 srcaddr
+= numxpixels
;
129 blkaddr
+= dstRowDiff
;
132 free((void *) tempImage
);
138 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS
)
141 const GLfloat
*tempImage
= NULL
;
143 int numxpixels
, numypixels
;
144 const GLfloat
*srcaddr
;
145 GLbyte srcpixels
[4][4];
148 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RED_RGTC1
||
149 dstFormat
== MESA_FORMAT_SIGNED_L_LATC1
);
151 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
153 _mesa_get_format_base_format(dstFormat
),
154 srcWidth
, srcHeight
, srcDepth
,
155 srcFormat
, srcType
, srcAddr
,
158 return GL_FALSE
; /* out of memory */
160 dst
= (GLbyte
*) dstSlices
[0];
163 dstRowDiff
= dstRowStride
>= (srcWidth
* 2) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 2) : 0;
164 for (j
= 0; j
< srcHeight
; j
+=4) {
165 if (srcHeight
> j
+ 3) numypixels
= 4;
166 else numypixels
= srcHeight
- j
;
167 srcaddr
= tempImage
+ j
* srcWidth
;
168 for (i
= 0; i
< srcWidth
; i
+= 4) {
169 if (srcWidth
> i
+ 3) numxpixels
= 4;
170 else numxpixels
= srcWidth
- i
;
171 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 1);
172 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
173 srcaddr
+= numxpixels
;
176 blkaddr
+= dstRowDiff
;
179 free((void *) tempImage
);
185 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS
)
188 const GLubyte
*tempImage
= NULL
;
190 int numxpixels
, numypixels
;
191 const GLubyte
*srcaddr
;
192 GLubyte srcpixels
[4][4];
196 ASSERT(dstFormat
== MESA_FORMAT_RG_RGTC2
||
197 dstFormat
== MESA_FORMAT_LA_LATC2
);
199 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
201 _mesa_get_format_base_format(dstFormat
),
202 srcWidth
, srcHeight
, srcDepth
,
203 srcFormat
, srcType
, srcAddr
,
206 return GL_FALSE
; /* out of memory */
211 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
212 for (j
= 0; j
< srcHeight
; j
+=4) {
213 if (srcHeight
> j
+ 3) numypixels
= 4;
214 else numypixels
= srcHeight
- j
;
215 srcaddr
= tempImage
+ j
* srcWidth
* 2;
216 for (i
= 0; i
< srcWidth
; i
+= 4) {
217 if (srcWidth
> i
+ 3) numxpixels
= 4;
218 else numxpixels
= srcWidth
- i
;
219 extractsrc_u(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
220 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
223 extractsrc_u(srcpixels
, (GLubyte
*)srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
224 unsigned_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
228 srcaddr
+= numxpixels
* 2;
230 blkaddr
+= dstRowDiff
;
233 free((void *) tempImage
);
239 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS
)
242 const GLfloat
*tempImage
= NULL
;
244 int numxpixels
, numypixels
;
245 const GLfloat
*srcaddr
;
246 GLbyte srcpixels
[4][4];
250 ASSERT(dstFormat
== MESA_FORMAT_SIGNED_RG_RGTC2
||
251 dstFormat
== MESA_FORMAT_SIGNED_LA_LATC2
);
253 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
255 _mesa_get_format_base_format(dstFormat
),
256 srcWidth
, srcHeight
, srcDepth
,
257 srcFormat
, srcType
, srcAddr
,
260 return GL_FALSE
; /* out of memory */
262 dst
= (GLbyte
*) dstSlices
[0];
265 dstRowDiff
= dstRowStride
>= (srcWidth
* 4) ? dstRowStride
- (((srcWidth
+ 3) & ~3) * 4) : 0;
266 for (j
= 0; j
< srcHeight
; j
+= 4) {
267 if (srcHeight
> j
+ 3) numypixels
= 4;
268 else numypixels
= srcHeight
- j
;
269 srcaddr
= tempImage
+ j
* srcWidth
* 2;
270 for (i
= 0; i
< srcWidth
; i
+= 4) {
271 if (srcWidth
> i
+ 3) numxpixels
= 4;
272 else numxpixels
= srcWidth
- i
;
274 extractsrc_s(srcpixels
, srcaddr
, srcWidth
, numxpixels
, numypixels
, 2);
275 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
278 extractsrc_s(srcpixels
, srcaddr
+ 1, srcWidth
, numxpixels
, numypixels
, 2);
279 signed_encode_rgtc_ubyte(blkaddr
, srcpixels
, numxpixels
, numypixels
);
282 srcaddr
+= numxpixels
* 2;
285 blkaddr
+= dstRowDiff
;
288 free((void *) tempImage
);
294 #define TAG(x) unsigned_##x
300 #include "texcompress_rgtc_tmp.h"
307 #define TAG(x) signed_##x
309 #define T_MIN (GLbyte)-128
310 #define T_MAX (GLbyte)127
312 #include "texcompress_rgtc_tmp.h"
322 fetch_red_rgtc1(const GLubyte
*map
, const GLuint imageOffsets
[],
323 GLint rowStride
, GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
326 GLuint sliceOffset
= k
? imageOffsets
[k
] / 2 : 0;
327 unsigned_fetch_texel_rgtc(rowStride
, map
+ sliceOffset
, i
, j
, &red
, 1);
328 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
335 fetch_l_latc1(const GLubyte
*map
, const GLuint imageOffsets
[],
336 GLint rowStride
, GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
339 GLuint sliceOffset
= k
? imageOffsets
[k
] / 2 : 0;
340 unsigned_fetch_texel_rgtc(rowStride
, map
+ sliceOffset
, i
, j
, &red
, 1);
343 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
348 fetch_signed_red_rgtc1(const GLubyte
*map
, const GLuint imageOffsets
[],
349 GLint rowStride
, GLint i
, GLint j
, GLint k
,
353 GLuint sliceOffset
= k
? imageOffsets
[k
] / 2 : 0;
354 signed_fetch_texel_rgtc(rowStride
, (const GLbyte
*) map
+ sliceOffset
,
356 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
363 fetch_signed_l_latc1(const GLubyte
*map
, const GLuint imageOffsets
[],
364 GLint rowStride
, GLint i
, GLint j
, GLint k
,
368 GLuint sliceOffset
= k
? imageOffsets
[k
] / 2 : 0;
369 unsigned_fetch_texel_rgtc(rowStride
, map
+ sliceOffset
, i
, j
, &red
, 1);
372 texel
[BCOMP
] = BYTE_TO_FLOAT(red
);
377 fetch_rg_rgtc2(const GLubyte
*map
, const GLuint imageOffsets
[],
378 GLint rowStride
, GLint i
, GLint j
, GLint k
,
382 GLuint sliceOffset
= k
? imageOffsets
[k
] : 0;
383 unsigned_fetch_texel_rgtc(rowStride
,
386 unsigned_fetch_texel_rgtc(rowStride
,
387 map
+ sliceOffset
+ 8,
389 texel
[RCOMP
] = UBYTE_TO_FLOAT(red
);
390 texel
[GCOMP
] = UBYTE_TO_FLOAT(green
);
396 fetch_la_latc2(const GLubyte
*map
, const GLuint imageOffsets
[],
397 GLint rowStride
, GLint i
, GLint j
, GLint k
,
401 GLuint sliceOffset
= k
? imageOffsets
[k
] : 0;
402 unsigned_fetch_texel_rgtc(rowStride
,
405 unsigned_fetch_texel_rgtc(rowStride
,
406 map
+ sliceOffset
+ 8,
410 texel
[BCOMP
] = UBYTE_TO_FLOAT(red
);
411 texel
[ACOMP
] = UBYTE_TO_FLOAT(green
);
416 fetch_signed_rg_rgtc2(const GLubyte
*map
, const GLuint imageOffsets
[],
417 GLint rowStride
, GLint i
, GLint j
, GLint k
,
421 GLuint sliceOffset
= k
? imageOffsets
[k
] : 0;
422 signed_fetch_texel_rgtc(rowStride
,
423 (GLbyte
*) map
+ sliceOffset
,
425 signed_fetch_texel_rgtc(rowStride
,
426 (GLbyte
*) map
+ sliceOffset
+ 8,
428 texel
[RCOMP
] = BYTE_TO_FLOAT_TEX(red
);
429 texel
[GCOMP
] = BYTE_TO_FLOAT_TEX(green
);
436 fetch_signed_la_latc2(const GLubyte
*map
, const GLuint imageOffsets
[],
437 GLint rowStride
, GLint i
, GLint j
, GLint k
,
441 GLuint sliceOffset
= k
? imageOffsets
[k
] : 0;
442 signed_fetch_texel_rgtc(rowStride
,
443 (GLbyte
*) map
+ sliceOffset
,
445 signed_fetch_texel_rgtc(rowStride
,
446 (GLbyte
*) map
+ sliceOffset
+ 8,
450 texel
[BCOMP
] = BYTE_TO_FLOAT_TEX(red
);
451 texel
[ACOMP
] = BYTE_TO_FLOAT_TEX(green
);
455 compressed_fetch_func
456 _mesa_get_compressed_rgtc_func(gl_format format
)
459 case MESA_FORMAT_RED_RGTC1
:
460 return fetch_red_rgtc1
;
461 case MESA_FORMAT_L_LATC1
:
462 return fetch_l_latc1
;
463 case MESA_FORMAT_SIGNED_RED_RGTC1
:
464 return fetch_signed_red_rgtc1
;
465 case MESA_FORMAT_SIGNED_L_LATC1
:
466 return fetch_signed_l_latc1
;
467 case MESA_FORMAT_RG_RGTC2
:
468 return fetch_rg_rgtc2
;
469 case MESA_FORMAT_LA_LATC2
:
470 return fetch_la_latc2
;
471 case MESA_FORMAT_SIGNED_RG_RGTC2
:
472 return fetch_signed_rg_rgtc2
;
473 case MESA_FORMAT_SIGNED_LA_LATC2
:
474 return fetch_signed_la_latc2
;