mesa: fix signed/unsignd mix-up in fetch_signed_l_latc1()
[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
48 #define RGTC_DEBUG 0
49
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);
54
55 static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata,
56 unsigned i, unsigned j, GLubyte *value, unsigned comps);
57
58 static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata,
59 unsigned i, unsigned j, GLbyte *value, unsigned comps);
60
61 static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr,
62 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
63 {
64 GLubyte i, j;
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;
70 curaddr += comps;
71 }
72 }
73 }
74
75 static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr,
76 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
77 {
78 GLubyte i, j;
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);
84 curaddr += comps;
85 }
86 }
87 }
88
89
90 GLboolean
91 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
92 {
93 GLubyte *dst;
94 const GLubyte *tempImage = NULL;
95 int i, j;
96 int numxpixels, numypixels;
97 const GLubyte *srcaddr;
98 GLubyte srcpixels[4][4];
99 GLubyte *blkaddr;
100 GLint dstRowDiff;
101 ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
102 dstFormat == MESA_FORMAT_L_LATC1);
103
104 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
105 baseInternalFormat,
106 _mesa_get_format_base_format(dstFormat),
107 srcWidth, srcHeight, srcDepth,
108 srcFormat, srcType, srcAddr,
109 srcPacking);
110 if (!tempImage)
111 return GL_FALSE; /* out of memory */
112
113 dst = dstSlices[0];
114
115 blkaddr = dst;
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;
127 blkaddr += 8;
128 }
129 blkaddr += dstRowDiff;
130 }
131
132 free((void *) tempImage);
133
134 return GL_TRUE;
135 }
136
137 GLboolean
138 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
139 {
140 GLbyte *dst;
141 const GLfloat *tempImage = NULL;
142 int i, j;
143 int numxpixels, numypixels;
144 const GLfloat *srcaddr;
145 GLbyte srcpixels[4][4];
146 GLbyte *blkaddr;
147 GLint dstRowDiff;
148 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
149 dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
150
151 tempImage = _mesa_make_temp_float_image(ctx, dims,
152 baseInternalFormat,
153 _mesa_get_format_base_format(dstFormat),
154 srcWidth, srcHeight, srcDepth,
155 srcFormat, srcType, srcAddr,
156 srcPacking, 0x0);
157 if (!tempImage)
158 return GL_FALSE; /* out of memory */
159
160 dst = (GLbyte *) dstSlices[0];
161
162 blkaddr = dst;
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;
174 blkaddr += 8;
175 }
176 blkaddr += dstRowDiff;
177 }
178
179 free((void *) tempImage);
180
181 return GL_TRUE;
182 }
183
184 GLboolean
185 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
186 {
187 GLubyte *dst;
188 const GLubyte *tempImage = NULL;
189 int i, j;
190 int numxpixels, numypixels;
191 const GLubyte *srcaddr;
192 GLubyte srcpixels[4][4];
193 GLubyte *blkaddr;
194 GLint dstRowDiff;
195
196 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 ||
197 dstFormat == MESA_FORMAT_LA_LATC2);
198
199 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
200 baseInternalFormat,
201 _mesa_get_format_base_format(dstFormat),
202 srcWidth, srcHeight, srcDepth,
203 srcFormat, srcType, srcAddr,
204 srcPacking);
205 if (!tempImage)
206 return GL_FALSE; /* out of memory */
207
208 dst = dstSlices[0];
209
210 blkaddr = dst;
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);
221
222 blkaddr += 8;
223 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
224 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
225
226 blkaddr += 8;
227
228 srcaddr += numxpixels * 2;
229 }
230 blkaddr += dstRowDiff;
231 }
232
233 free((void *) tempImage);
234
235 return GL_TRUE;
236 }
237
238 GLboolean
239 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
240 {
241 GLbyte *dst;
242 const GLfloat *tempImage = NULL;
243 int i, j;
244 int numxpixels, numypixels;
245 const GLfloat *srcaddr;
246 GLbyte srcpixels[4][4];
247 GLbyte *blkaddr;
248 GLint dstRowDiff;
249
250 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
251 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
252
253 tempImage = _mesa_make_temp_float_image(ctx, dims,
254 baseInternalFormat,
255 _mesa_get_format_base_format(dstFormat),
256 srcWidth, srcHeight, srcDepth,
257 srcFormat, srcType, srcAddr,
258 srcPacking, 0x0);
259 if (!tempImage)
260 return GL_FALSE; /* out of memory */
261
262 dst = (GLbyte *) dstSlices[0];
263
264 blkaddr = dst;
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;
273
274 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
275 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
276 blkaddr += 8;
277
278 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
279 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
280 blkaddr += 8;
281
282 srcaddr += numxpixels * 2;
283
284 }
285 blkaddr += dstRowDiff;
286 }
287
288 free((void *) tempImage);
289
290 return GL_TRUE;
291 }
292
293
294 #define TAG(x) unsigned_##x
295
296 #define TYPE GLubyte
297 #define T_MIN 0
298 #define T_MAX 0xff
299
300 #include "texcompress_rgtc_tmp.h"
301
302 #undef TAG
303 #undef TYPE
304 #undef T_MIN
305 #undef T_MAX
306
307 #define TAG(x) signed_##x
308 #define TYPE GLbyte
309 #define T_MIN (GLbyte)-128
310 #define T_MAX (GLbyte)127
311
312 #include "texcompress_rgtc_tmp.h"
313
314 #undef TAG
315 #undef TYPE
316 #undef T_MIN
317 #undef T_MAX
318
319
320
321 static void
322 fetch_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[],
323 GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel)
324 {
325 GLubyte red;
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);
329 texel[GCOMP] = 0.0;
330 texel[BCOMP] = 0.0;
331 texel[ACOMP] = 1.0;
332 }
333
334 static void
335 fetch_l_latc1(const GLubyte *map, const GLuint imageOffsets[],
336 GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel)
337 {
338 GLubyte red;
339 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0;
340 unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1);
341 texel[RCOMP] =
342 texel[GCOMP] =
343 texel[BCOMP] = UBYTE_TO_FLOAT(red);
344 texel[ACOMP] = 1.0;
345 }
346
347 static void
348 fetch_signed_red_rgtc1(const GLubyte *map, const GLuint imageOffsets[],
349 GLint rowStride, GLint i, GLint j, GLint k,
350 GLfloat *texel)
351 {
352 GLbyte red;
353 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0;
354 signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map + sliceOffset,
355 i, j, &red, 1);
356 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
357 texel[GCOMP] = 0.0;
358 texel[BCOMP] = 0.0;
359 texel[ACOMP] = 1.0;
360 }
361
362 static void
363 fetch_signed_l_latc1(const GLubyte *map, const GLuint imageOffsets[],
364 GLint rowStride, GLint i, GLint j, GLint k,
365 GLfloat *texel)
366 {
367 GLbyte red;
368 GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0;
369 signed_fetch_texel_rgtc(rowStride, (GLbyte *) map + sliceOffset,
370 i, j, &red, 1);
371 texel[RCOMP] =
372 texel[GCOMP] =
373 texel[BCOMP] = BYTE_TO_FLOAT(red);
374 texel[ACOMP] = 1.0;
375 }
376
377 static void
378 fetch_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[],
379 GLint rowStride, GLint i, GLint j, GLint k,
380 GLfloat *texel)
381 {
382 GLubyte red, green;
383 GLuint sliceOffset = k ? imageOffsets[k] : 0;
384 unsigned_fetch_texel_rgtc(rowStride,
385 map + sliceOffset,
386 i, j, &red, 2);
387 unsigned_fetch_texel_rgtc(rowStride,
388 map + sliceOffset + 8,
389 i, j, &green, 2);
390 texel[RCOMP] = UBYTE_TO_FLOAT(red);
391 texel[GCOMP] = UBYTE_TO_FLOAT(green);
392 texel[BCOMP] = 0.0;
393 texel[ACOMP] = 1.0;
394 }
395
396 static void
397 fetch_la_latc2(const GLubyte *map, const GLuint imageOffsets[],
398 GLint rowStride, GLint i, GLint j, GLint k,
399 GLfloat *texel)
400 {
401 GLubyte red, green;
402 GLuint sliceOffset = k ? imageOffsets[k] : 0;
403 unsigned_fetch_texel_rgtc(rowStride,
404 map + sliceOffset,
405 i, j, &red, 2);
406 unsigned_fetch_texel_rgtc(rowStride,
407 map + sliceOffset + 8,
408 i, j, &green, 2);
409 texel[RCOMP] =
410 texel[GCOMP] =
411 texel[BCOMP] = UBYTE_TO_FLOAT(red);
412 texel[ACOMP] = UBYTE_TO_FLOAT(green);
413 }
414
415
416 static void
417 fetch_signed_rg_rgtc2(const GLubyte *map, const GLuint imageOffsets[],
418 GLint rowStride, GLint i, GLint j, GLint k,
419 GLfloat *texel)
420 {
421 GLbyte red, green;
422 GLuint sliceOffset = k ? imageOffsets[k] : 0;
423 signed_fetch_texel_rgtc(rowStride,
424 (GLbyte *) map + sliceOffset,
425 i, j, &red, 2);
426 signed_fetch_texel_rgtc(rowStride,
427 (GLbyte *) map + sliceOffset + 8,
428 i, j, &green, 2);
429 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
430 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
431 texel[BCOMP] = 0.0;
432 texel[ACOMP] = 1.0;
433 }
434
435
436 static void
437 fetch_signed_la_latc2(const GLubyte *map, const GLuint imageOffsets[],
438 GLint rowStride, GLint i, GLint j, GLint k,
439 GLfloat *texel)
440 {
441 GLbyte red, green;
442 GLuint sliceOffset = k ? imageOffsets[k] : 0;
443 signed_fetch_texel_rgtc(rowStride,
444 (GLbyte *) map + sliceOffset,
445 i, j, &red, 2);
446 signed_fetch_texel_rgtc(rowStride,
447 (GLbyte *) map + sliceOffset + 8,
448 i, j, &green, 2);
449 texel[RCOMP] =
450 texel[GCOMP] =
451 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
452 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
453 }
454
455
456 compressed_fetch_func
457 _mesa_get_compressed_rgtc_func(gl_format format)
458 {
459 switch (format) {
460 case MESA_FORMAT_RED_RGTC1:
461 return fetch_red_rgtc1;
462 case MESA_FORMAT_L_LATC1:
463 return fetch_l_latc1;
464 case MESA_FORMAT_SIGNED_RED_RGTC1:
465 return fetch_signed_red_rgtc1;
466 case MESA_FORMAT_SIGNED_L_LATC1:
467 return fetch_signed_l_latc1;
468 case MESA_FORMAT_RG_RGTC2:
469 return fetch_rg_rgtc2;
470 case MESA_FORMAT_LA_LATC2:
471 return fetch_la_latc2;
472 case MESA_FORMAT_SIGNED_RG_RGTC2:
473 return fetch_signed_rg_rgtc2;
474 case MESA_FORMAT_SIGNED_LA_LATC2:
475 return fetch_signed_la_latc2;
476 default:
477 return NULL;
478 }
479 }