26dca2d760b5dbbb08566c719158fd1194606721
[mesa.git] / src / mesa / main / texcompress_rgtc.c
1 /*
2 * Copyright (C) 2011 Red Hat Inc.
3 *
4 * block compression parts are:
5 * Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
6 *
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:
13 *
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
16 * Software.
17 *
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.
25 *
26 * Author:
27 * Dave Airlie
28 */
29
30 /**
31 * \file texcompress_rgtc.c
32 * GL_EXT_texture_compression_rgtc support.
33 */
34
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "colormac.h"
39 #include "image.h"
40 #include "macros.h"
41 #include "mfeatures.h"
42 #include "mipmap.h"
43 #include "texcompress.h"
44 #include "texcompress_rgtc.h"
45 #include "texstore.h"
46
47 #define RGTC_DEBUG 0
48
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);
53
54 static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata,
55 unsigned i, unsigned j, GLubyte *value, unsigned comps);
56
57 static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata,
58 unsigned i, unsigned j, GLbyte *value, unsigned comps);
59
60 static void extractsrc_u( GLubyte srcpixels[4][4], const GLchan *srcaddr,
61 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
62 {
63 GLubyte i, j;
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);
69 curaddr += comps;
70 }
71 }
72 }
73
74 static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr,
75 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
76 {
77 GLubyte i, j;
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);
83 curaddr += comps;
84 }
85 }
86 }
87
88
89 GLboolean
90 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
91 {
92 GLubyte *dst;
93 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
94 const GLchan *tempImage = NULL;
95 int i, j;
96 int numxpixels, numypixels;
97 const GLchan *srcaddr;
98 GLubyte srcpixels[4][4];
99 GLubyte *blkaddr;
100 GLint dstRowDiff;
101 ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1);
102 ASSERT(dstXoffset % 4 == 0);
103 ASSERT(dstYoffset % 4 == 0);
104 ASSERT(dstZoffset % 4 == 0);
105 (void) dstZoffset;
106 (void) dstImageOffsets;
107
108
109 tempImage = _mesa_make_temp_chan_image(ctx, dims,
110 baseInternalFormat,
111 _mesa_get_format_base_format(dstFormat),
112 srcWidth, srcHeight, srcDepth,
113 srcFormat, srcType, srcAddr,
114 srcPacking);
115 if (!tempImage)
116 return GL_FALSE; /* out of memory */
117
118 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
119 dstFormat,
120 texWidth, (GLubyte *) dstAddr);
121
122 blkaddr = dst;
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;
134 blkaddr += 8;
135 }
136 blkaddr += dstRowDiff;
137 }
138 if (tempImage)
139 free((void *) tempImage);
140
141 return GL_TRUE;
142 }
143
144 GLboolean
145 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
146 {
147 GLbyte *dst;
148 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
149 const GLfloat *tempImage = NULL;
150 int i, j;
151 int numxpixels, numypixels;
152 const GLfloat *srcaddr;
153 GLbyte srcpixels[4][4];
154 GLbyte *blkaddr;
155 GLint dstRowDiff;
156 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1);
157 ASSERT(dstXoffset % 4 == 0);
158 ASSERT(dstYoffset % 4 == 0);
159 ASSERT(dstZoffset % 4 == 0);
160 (void) dstZoffset;
161 (void) dstImageOffsets;
162
163 tempImage = _mesa_make_temp_float_image(ctx, dims,
164 baseInternalFormat,
165 _mesa_get_format_base_format(dstFormat),
166 srcWidth, srcHeight, srcDepth,
167 srcFormat, srcType, srcAddr,
168 srcPacking, 0x0);
169 if (!tempImage)
170 return GL_FALSE; /* out of memory */
171
172 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
173 dstFormat,
174 texWidth, (GLubyte *) dstAddr);
175
176 blkaddr = dst;
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;
188 blkaddr += 8;
189 }
190 blkaddr += dstRowDiff;
191 }
192 if (tempImage)
193 free((void *) tempImage);
194
195 return GL_TRUE;
196 }
197
198 GLboolean
199 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
200 {
201 GLubyte *dst;
202 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
203 const GLchan *tempImage = NULL;
204 int i, j;
205 int numxpixels, numypixels;
206 const GLchan *srcaddr;
207 GLubyte srcpixels[4][4];
208 GLubyte *blkaddr;
209 GLint dstRowDiff;
210
211 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2);
212 ASSERT(dstXoffset % 4 == 0);
213 ASSERT(dstYoffset % 4 == 0);
214 ASSERT(dstZoffset % 4 == 0);
215 (void) dstZoffset;
216 (void) dstImageOffsets;
217
218 tempImage = _mesa_make_temp_chan_image(ctx, dims,
219 baseInternalFormat,
220 _mesa_get_format_base_format(dstFormat),
221 srcWidth, srcHeight, srcDepth,
222 srcFormat, srcType, srcAddr,
223 srcPacking);
224 if (!tempImage)
225 return GL_FALSE; /* out of memory */
226
227 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
228 dstFormat,
229 texWidth, (GLubyte *) dstAddr);
230
231 blkaddr = dst;
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);
242
243 blkaddr += 8;
244 extractsrc_u(srcpixels, (GLchan *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
245 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
246
247 blkaddr += 8;
248
249 srcaddr += numxpixels * 2;
250 }
251 blkaddr += dstRowDiff;
252 }
253 if (tempImage)
254 free((void *) tempImage);
255
256 return GL_TRUE;
257 }
258
259 GLboolean
260 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
261 {
262 GLbyte *dst;
263 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
264 const GLfloat *tempImage = NULL;
265 int i, j;
266 int numxpixels, numypixels;
267 const GLfloat *srcaddr;
268 GLbyte srcpixels[4][4];
269 GLbyte *blkaddr;
270 GLint dstRowDiff;
271
272 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2);
273 ASSERT(dstXoffset % 4 == 0);
274 ASSERT(dstYoffset % 4 == 0);
275 ASSERT(dstZoffset % 4 == 0);
276 (void) dstZoffset;
277 (void) dstImageOffsets;
278
279 tempImage = _mesa_make_temp_float_image(ctx, dims,
280 baseInternalFormat,
281 _mesa_get_format_base_format(dstFormat),
282 srcWidth, srcHeight, srcDepth,
283 srcFormat, srcType, srcAddr,
284 srcPacking, 0x0);
285 if (!tempImage)
286 return GL_FALSE; /* out of memory */
287
288 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
289 dstFormat,
290 texWidth, (GLubyte *) dstAddr);
291
292 blkaddr = dst;
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;
301
302 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
303 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
304 blkaddr += 8;
305
306 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
307 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
308 blkaddr += 8;
309
310 srcaddr += numxpixels * 2;
311
312 }
313 blkaddr += dstRowDiff;
314 }
315 if (tempImage)
316 free((void *) tempImage);
317
318 return GL_TRUE;
319 }
320
321 void
322 _mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image *texImage,
323 GLint i, GLint j, GLint k, GLfloat *texel)
324 {
325 GLubyte red;
326 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
327 i, j, &red, 1);
328 texel[RCOMP] = UBYTE_TO_FLOAT(red);
329 texel[GCOMP] = 0.0;
330 texel[BCOMP] = 0.0;
331 texel[ACOMP] = 1.0;
332 }
333
334 void
335 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image *texImage,
336 GLint i, GLint j, GLint k, GLfloat *texel)
337 {
338 GLbyte red;
339 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
340 i, j, &red, 1);
341 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
342 texel[GCOMP] = 0.0;
343 texel[BCOMP] = 0.0;
344 texel[ACOMP] = 1.0;
345 }
346
347 void
348 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image *texImage,
349 GLint i, GLint j, GLint k, GLfloat *texel)
350 {
351 GLubyte red, green;
352 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
353 i, j, &red, 2);
354 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
355 i, j, &green, 2);
356 texel[RCOMP] = UBYTE_TO_FLOAT(red);
357 texel[GCOMP] = UBYTE_TO_FLOAT(green);
358 texel[BCOMP] = 0.0;
359 texel[ACOMP] = 1.0;
360 }
361
362 void
363 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
364 GLint i, GLint j, GLint k, GLfloat *texel)
365 {
366 GLbyte red, green;
367 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
368 i, j, &red, 2);
369 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
370 i, j, &green, 2);
371 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
372 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
373 texel[BCOMP] = 0.0;
374 texel[ACOMP] = 1.0;
375 }
376
377 #define TAG(x) unsigned_##x
378
379 #define TYPE GLubyte
380 #define T_MIN 0
381 #define T_MAX 0xff
382
383 #include "texcompress_rgtc_tmp.h"
384
385 #undef TAG
386 #undef TYPE
387 #undef T_MIN
388 #undef T_MAX
389
390 #define TAG(x) signed_##x
391 #define TYPE GLbyte
392 #define T_MIN (GLbyte)-128
393 #define T_MAX (GLbyte)127
394
395 #include "texcompress_rgtc_tmp.h"
396
397 #undef TAG
398 #undef TYPE
399 #undef T_MIN
400 #undef T_MAX