swrast: Replace ImageOffsets with an ImageSlices pointer.
[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 "mipmap.h"
42 #include "texcompress.h"
43 #include "texcompress_rgtc.h"
44 #include "texstore.h"
45
46
47 #define RGTC_DEBUG 0
48
49 static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4],
50 GLint numxpixels, GLint numypixels);
51 static void signed_encode_rgtc_ubyte(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 GLubyte *srcaddr,
61 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
62 {
63 GLubyte i, j;
64 const GLubyte *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;
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 GLubyte *tempImage = NULL;
94 int i, j;
95 int numxpixels, numypixels;
96 const GLubyte *srcaddr;
97 GLubyte srcpixels[4][4];
98 GLubyte *blkaddr;
99 GLint dstRowDiff;
100 ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
101 dstFormat == MESA_FORMAT_L_LATC1);
102
103 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
104 baseInternalFormat,
105 _mesa_get_format_base_format(dstFormat),
106 srcWidth, srcHeight, srcDepth,
107 srcFormat, srcType, srcAddr,
108 srcPacking);
109 if (!tempImage)
110 return GL_FALSE; /* out of memory */
111
112 dst = dstSlices[0];
113
114 blkaddr = dst;
115 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
116 for (j = 0; j < srcHeight; j+=4) {
117 if (srcHeight > j + 3) numypixels = 4;
118 else numypixels = srcHeight - j;
119 srcaddr = tempImage + j * srcWidth;
120 for (i = 0; i < srcWidth; i += 4) {
121 if (srcWidth > i + 3) numxpixels = 4;
122 else numxpixels = srcWidth - i;
123 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
124 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
125 srcaddr += numxpixels;
126 blkaddr += 8;
127 }
128 blkaddr += dstRowDiff;
129 }
130
131 free((void *) tempImage);
132
133 return GL_TRUE;
134 }
135
136 GLboolean
137 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
138 {
139 GLbyte *dst;
140 const GLfloat *tempImage = NULL;
141 int i, j;
142 int numxpixels, numypixels;
143 const GLfloat *srcaddr;
144 GLbyte srcpixels[4][4];
145 GLbyte *blkaddr;
146 GLint dstRowDiff;
147 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
148 dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
149
150 tempImage = _mesa_make_temp_float_image(ctx, dims,
151 baseInternalFormat,
152 _mesa_get_format_base_format(dstFormat),
153 srcWidth, srcHeight, srcDepth,
154 srcFormat, srcType, srcAddr,
155 srcPacking, 0x0);
156 if (!tempImage)
157 return GL_FALSE; /* out of memory */
158
159 dst = (GLbyte *) dstSlices[0];
160
161 blkaddr = dst;
162 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
163 for (j = 0; j < srcHeight; j+=4) {
164 if (srcHeight > j + 3) numypixels = 4;
165 else numypixels = srcHeight - j;
166 srcaddr = tempImage + j * srcWidth;
167 for (i = 0; i < srcWidth; i += 4) {
168 if (srcWidth > i + 3) numxpixels = 4;
169 else numxpixels = srcWidth - i;
170 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
171 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
172 srcaddr += numxpixels;
173 blkaddr += 8;
174 }
175 blkaddr += dstRowDiff;
176 }
177
178 free((void *) tempImage);
179
180 return GL_TRUE;
181 }
182
183 GLboolean
184 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
185 {
186 GLubyte *dst;
187 const GLubyte *tempImage = NULL;
188 int i, j;
189 int numxpixels, numypixels;
190 const GLubyte *srcaddr;
191 GLubyte srcpixels[4][4];
192 GLubyte *blkaddr;
193 GLint dstRowDiff;
194
195 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 ||
196 dstFormat == MESA_FORMAT_LA_LATC2);
197
198 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
199 baseInternalFormat,
200 _mesa_get_format_base_format(dstFormat),
201 srcWidth, srcHeight, srcDepth,
202 srcFormat, srcType, srcAddr,
203 srcPacking);
204 if (!tempImage)
205 return GL_FALSE; /* out of memory */
206
207 dst = dstSlices[0];
208
209 blkaddr = dst;
210 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
211 for (j = 0; j < srcHeight; j+=4) {
212 if (srcHeight > j + 3) numypixels = 4;
213 else numypixels = srcHeight - j;
214 srcaddr = tempImage + j * srcWidth * 2;
215 for (i = 0; i < srcWidth; i += 4) {
216 if (srcWidth > i + 3) numxpixels = 4;
217 else numxpixels = srcWidth - i;
218 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
219 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
220
221 blkaddr += 8;
222 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
223 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
224
225 blkaddr += 8;
226
227 srcaddr += numxpixels * 2;
228 }
229 blkaddr += dstRowDiff;
230 }
231
232 free((void *) tempImage);
233
234 return GL_TRUE;
235 }
236
237 GLboolean
238 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
239 {
240 GLbyte *dst;
241 const GLfloat *tempImage = NULL;
242 int i, j;
243 int numxpixels, numypixels;
244 const GLfloat *srcaddr;
245 GLbyte srcpixels[4][4];
246 GLbyte *blkaddr;
247 GLint dstRowDiff;
248
249 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
250 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
251
252 tempImage = _mesa_make_temp_float_image(ctx, dims,
253 baseInternalFormat,
254 _mesa_get_format_base_format(dstFormat),
255 srcWidth, srcHeight, srcDepth,
256 srcFormat, srcType, srcAddr,
257 srcPacking, 0x0);
258 if (!tempImage)
259 return GL_FALSE; /* out of memory */
260
261 dst = (GLbyte *) dstSlices[0];
262
263 blkaddr = dst;
264 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
265 for (j = 0; j < srcHeight; j += 4) {
266 if (srcHeight > j + 3) numypixels = 4;
267 else numypixels = srcHeight - j;
268 srcaddr = tempImage + j * srcWidth * 2;
269 for (i = 0; i < srcWidth; i += 4) {
270 if (srcWidth > i + 3) numxpixels = 4;
271 else numxpixels = srcWidth - i;
272
273 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
274 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
275 blkaddr += 8;
276
277 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
278 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
279 blkaddr += 8;
280
281 srcaddr += numxpixels * 2;
282
283 }
284 blkaddr += dstRowDiff;
285 }
286
287 free((void *) tempImage);
288
289 return GL_TRUE;
290 }
291
292
293 #define TAG(x) unsigned_##x
294
295 #define TYPE GLubyte
296 #define T_MIN 0
297 #define T_MAX 0xff
298
299 #include "texcompress_rgtc_tmp.h"
300
301 #undef TAG
302 #undef TYPE
303 #undef T_MIN
304 #undef T_MAX
305
306 #define TAG(x) signed_##x
307 #define TYPE GLbyte
308 #define T_MIN (GLbyte)-128
309 #define T_MAX (GLbyte)127
310
311 #include "texcompress_rgtc_tmp.h"
312
313 #undef TAG
314 #undef TYPE
315 #undef T_MIN
316 #undef T_MAX
317
318
319
320 static void
321 fetch_red_rgtc1(const GLubyte *map,
322 GLint rowStride, GLint i, GLint j, GLfloat *texel)
323 {
324 GLubyte red;
325 unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
326 texel[RCOMP] = UBYTE_TO_FLOAT(red);
327 texel[GCOMP] = 0.0;
328 texel[BCOMP] = 0.0;
329 texel[ACOMP] = 1.0;
330 }
331
332 static void
333 fetch_l_latc1(const GLubyte *map,
334 GLint rowStride, GLint i, GLint j, GLfloat *texel)
335 {
336 GLubyte red;
337 unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
338 texel[RCOMP] =
339 texel[GCOMP] =
340 texel[BCOMP] = UBYTE_TO_FLOAT(red);
341 texel[ACOMP] = 1.0;
342 }
343
344 static void
345 fetch_signed_red_rgtc1(const GLubyte *map,
346 GLint rowStride, GLint i, GLint j, GLfloat *texel)
347 {
348 GLbyte red;
349 signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map,
350 i, j, &red, 1);
351 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
352 texel[GCOMP] = 0.0;
353 texel[BCOMP] = 0.0;
354 texel[ACOMP] = 1.0;
355 }
356
357 static void
358 fetch_signed_l_latc1(const GLubyte *map,
359 GLint rowStride, GLint i, GLint j, GLfloat *texel)
360 {
361 GLbyte red;
362 signed_fetch_texel_rgtc(rowStride, (GLbyte *) map,
363 i, j, &red, 1);
364 texel[RCOMP] =
365 texel[GCOMP] =
366 texel[BCOMP] = BYTE_TO_FLOAT(red);
367 texel[ACOMP] = 1.0;
368 }
369
370 static void
371 fetch_rg_rgtc2(const GLubyte *map,
372 GLint rowStride, GLint i, GLint j, GLfloat *texel)
373 {
374 GLubyte red, green;
375 unsigned_fetch_texel_rgtc(rowStride,
376 map,
377 i, j, &red, 2);
378 unsigned_fetch_texel_rgtc(rowStride,
379 map + 8,
380 i, j, &green, 2);
381 texel[RCOMP] = UBYTE_TO_FLOAT(red);
382 texel[GCOMP] = UBYTE_TO_FLOAT(green);
383 texel[BCOMP] = 0.0;
384 texel[ACOMP] = 1.0;
385 }
386
387 static void
388 fetch_la_latc2(const GLubyte *map,
389 GLint rowStride, GLint i, GLint j, GLfloat *texel)
390 {
391 GLubyte red, green;
392 unsigned_fetch_texel_rgtc(rowStride,
393 map,
394 i, j, &red, 2);
395 unsigned_fetch_texel_rgtc(rowStride,
396 map + 8,
397 i, j, &green, 2);
398 texel[RCOMP] =
399 texel[GCOMP] =
400 texel[BCOMP] = UBYTE_TO_FLOAT(red);
401 texel[ACOMP] = UBYTE_TO_FLOAT(green);
402 }
403
404
405 static void
406 fetch_signed_rg_rgtc2(const GLubyte *map,
407 GLint rowStride, GLint i, GLint j, GLfloat *texel)
408 {
409 GLbyte red, green;
410 signed_fetch_texel_rgtc(rowStride,
411 (GLbyte *) map,
412 i, j, &red, 2);
413 signed_fetch_texel_rgtc(rowStride,
414 (GLbyte *) map + 8,
415 i, j, &green, 2);
416 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
417 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
418 texel[BCOMP] = 0.0;
419 texel[ACOMP] = 1.0;
420 }
421
422
423 static void
424 fetch_signed_la_latc2(const GLubyte *map,
425 GLint rowStride, GLint i, GLint j, GLfloat *texel)
426 {
427 GLbyte red, green;
428 signed_fetch_texel_rgtc(rowStride,
429 (GLbyte *) map,
430 i, j, &red, 2);
431 signed_fetch_texel_rgtc(rowStride,
432 (GLbyte *) map + 8,
433 i, j, &green, 2);
434 texel[RCOMP] =
435 texel[GCOMP] =
436 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
437 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
438 }
439
440
441 compressed_fetch_func
442 _mesa_get_compressed_rgtc_func(gl_format format)
443 {
444 switch (format) {
445 case MESA_FORMAT_RED_RGTC1:
446 return fetch_red_rgtc1;
447 case MESA_FORMAT_L_LATC1:
448 return fetch_l_latc1;
449 case MESA_FORMAT_SIGNED_RED_RGTC1:
450 return fetch_signed_red_rgtc1;
451 case MESA_FORMAT_SIGNED_L_LATC1:
452 return fetch_signed_l_latc1;
453 case MESA_FORMAT_RG_RGTC2:
454 return fetch_rg_rgtc2;
455 case MESA_FORMAT_LA_LATC2:
456 return fetch_la_latc2;
457 case MESA_FORMAT_SIGNED_RG_RGTC2:
458 return fetch_signed_rg_rgtc2;
459 case MESA_FORMAT_SIGNED_LA_LATC2:
460 return fetch_signed_la_latc2;
461 default:
462 return NULL;
463 }
464 }