Merge remote branch 'origin/master' into pipe-video
[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 dstFormat == MESA_FORMAT_L_LATC1);
103 ASSERT(dstXoffset % 4 == 0);
104 ASSERT(dstYoffset % 4 == 0);
105 ASSERT(dstZoffset % 4 == 0);
106 (void) dstZoffset;
107 (void) dstImageOffsets;
108
109
110 tempImage = _mesa_make_temp_chan_image(ctx, dims,
111 baseInternalFormat,
112 _mesa_get_format_base_format(dstFormat),
113 srcWidth, srcHeight, srcDepth,
114 srcFormat, srcType, srcAddr,
115 srcPacking);
116 if (!tempImage)
117 return GL_FALSE; /* out of memory */
118
119 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
120 dstFormat,
121 texWidth, (GLubyte *) dstAddr);
122
123 blkaddr = dst;
124 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
125 for (j = 0; j < srcHeight; j+=4) {
126 if (srcHeight > j + 3) numypixels = 4;
127 else numypixels = srcHeight - j;
128 srcaddr = tempImage + j * srcWidth;
129 for (i = 0; i < srcWidth; i += 4) {
130 if (srcWidth > i + 3) numxpixels = 4;
131 else numxpixels = srcWidth - i;
132 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
133 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
134 srcaddr += numxpixels;
135 blkaddr += 8;
136 }
137 blkaddr += dstRowDiff;
138 }
139 if (tempImage)
140 free((void *) tempImage);
141
142 return GL_TRUE;
143 }
144
145 GLboolean
146 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
147 {
148 GLbyte *dst;
149 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
150 const GLfloat *tempImage = NULL;
151 int i, j;
152 int numxpixels, numypixels;
153 const GLfloat *srcaddr;
154 GLbyte srcpixels[4][4];
155 GLbyte *blkaddr;
156 GLint dstRowDiff;
157 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
158 dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
159 ASSERT(dstXoffset % 4 == 0);
160 ASSERT(dstYoffset % 4 == 0);
161 ASSERT(dstZoffset % 4 == 0);
162 (void) dstZoffset;
163 (void) dstImageOffsets;
164
165 tempImage = _mesa_make_temp_float_image(ctx, dims,
166 baseInternalFormat,
167 _mesa_get_format_base_format(dstFormat),
168 srcWidth, srcHeight, srcDepth,
169 srcFormat, srcType, srcAddr,
170 srcPacking, 0x0);
171 if (!tempImage)
172 return GL_FALSE; /* out of memory */
173
174 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
175 dstFormat,
176 texWidth, (GLubyte *) dstAddr);
177
178 blkaddr = dst;
179 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 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_chan(blkaddr, srcpixels, numxpixels, numypixels);
189 srcaddr += numxpixels;
190 blkaddr += 8;
191 }
192 blkaddr += dstRowDiff;
193 }
194 if (tempImage)
195 free((void *) tempImage);
196
197 return GL_TRUE;
198 }
199
200 GLboolean
201 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
202 {
203 GLubyte *dst;
204 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
205 const GLchan *tempImage = NULL;
206 int i, j;
207 int numxpixels, numypixels;
208 const GLchan *srcaddr;
209 GLubyte srcpixels[4][4];
210 GLubyte *blkaddr;
211 GLint dstRowDiff;
212
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);
218 (void) dstZoffset;
219 (void) dstImageOffsets;
220
221 tempImage = _mesa_make_temp_chan_image(ctx, dims,
222 baseInternalFormat,
223 _mesa_get_format_base_format(dstFormat),
224 srcWidth, srcHeight, srcDepth,
225 srcFormat, srcType, srcAddr,
226 srcPacking);
227 if (!tempImage)
228 return GL_FALSE; /* out of memory */
229
230 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
231 dstFormat,
232 texWidth, (GLubyte *) dstAddr);
233
234 blkaddr = dst;
235 dstRowDiff = dstRowStride >= (srcWidth * 8) ? dstRowStride - (((srcWidth + 7) & ~7) * 8) : 0;
236 for (j = 0; j < srcHeight; j+=4) {
237 if (srcHeight > j + 3) numypixels = 4;
238 else numypixels = srcHeight - j;
239 srcaddr = tempImage + j * srcWidth * 2;
240 for (i = 0; i < srcWidth; i += 4) {
241 if (srcWidth > i + 3) numxpixels = 4;
242 else numxpixels = srcWidth - i;
243 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
244 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
245
246 blkaddr += 8;
247 extractsrc_u(srcpixels, (GLchan *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
248 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
249
250 blkaddr += 8;
251
252 srcaddr += numxpixels * 2;
253 }
254 blkaddr += dstRowDiff;
255 }
256 if (tempImage)
257 free((void *) tempImage);
258
259 return GL_TRUE;
260 }
261
262 GLboolean
263 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
264 {
265 GLbyte *dst;
266 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
267 const GLfloat *tempImage = NULL;
268 int i, j;
269 int numxpixels, numypixels;
270 const GLfloat *srcaddr;
271 GLbyte srcpixels[4][4];
272 GLbyte *blkaddr;
273 GLint dstRowDiff;
274
275 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
276 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
277 ASSERT(dstXoffset % 4 == 0);
278 ASSERT(dstYoffset % 4 == 0);
279 ASSERT(dstZoffset % 4 == 0);
280 (void) dstZoffset;
281 (void) dstImageOffsets;
282
283 tempImage = _mesa_make_temp_float_image(ctx, dims,
284 baseInternalFormat,
285 _mesa_get_format_base_format(dstFormat),
286 srcWidth, srcHeight, srcDepth,
287 srcFormat, srcType, srcAddr,
288 srcPacking, 0x0);
289 if (!tempImage)
290 return GL_FALSE; /* out of memory */
291
292 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
293 dstFormat,
294 texWidth, (GLubyte *) dstAddr);
295
296 blkaddr = dst;
297 dstRowDiff = dstRowStride >= (srcWidth * 8) ? dstRowStride - (((srcWidth + 7) & ~7) * 8) : 0;
298 for (j = 0; j < srcHeight; j += 4) {
299 if (srcHeight > j + 3) numypixels = 4;
300 else numypixels = srcHeight - j;
301 srcaddr = tempImage + j * srcWidth * 2;
302 for (i = 0; i < srcWidth; i += 4) {
303 if (srcWidth > i + 3) numxpixels = 4;
304 else numxpixels = srcWidth - i;
305
306 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
307 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
308 blkaddr += 8;
309
310 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
311 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
312 blkaddr += 8;
313
314 srcaddr += numxpixels * 2;
315
316 }
317 blkaddr += dstRowDiff;
318 }
319 if (tempImage)
320 free((void *) tempImage);
321
322 return GL_TRUE;
323 }
324
325 void
326 _mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image *texImage,
327 GLint i, GLint j, GLint k, GLfloat *texel)
328 {
329 GLubyte red;
330 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
331 i, j, &red, 1);
332 texel[RCOMP] = UBYTE_TO_FLOAT(red);
333 texel[GCOMP] = 0.0;
334 texel[BCOMP] = 0.0;
335 texel[ACOMP] = 1.0;
336 }
337
338 void
339 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image *texImage,
340 GLint i, GLint j, GLint k, GLfloat *texel)
341 {
342 GLbyte red;
343 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
344 i, j, &red, 1);
345 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
346 texel[GCOMP] = 0.0;
347 texel[BCOMP] = 0.0;
348 texel[ACOMP] = 1.0;
349 }
350
351 void
352 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image *texImage,
353 GLint i, GLint j, GLint k, GLfloat *texel)
354 {
355 GLubyte red, green;
356 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
357 i, j, &red, 2);
358 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
359 i, j, &green, 2);
360 texel[RCOMP] = UBYTE_TO_FLOAT(red);
361 texel[GCOMP] = UBYTE_TO_FLOAT(green);
362 texel[BCOMP] = 0.0;
363 texel[ACOMP] = 1.0;
364 }
365
366 void
367 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
368 GLint i, GLint j, GLint k, GLfloat *texel)
369 {
370 GLbyte red, green;
371 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
372 i, j, &red, 2);
373 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
374 i, j, &green, 2);
375 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
376 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
377 texel[BCOMP] = 0.0;
378 texel[ACOMP] = 1.0;
379 }
380
381 void
382 _mesa_fetch_texel_2d_f_l_latc1(const struct gl_texture_image *texImage,
383 GLint i, GLint j, GLint k, GLfloat *texel)
384 {
385 GLubyte red;
386 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
387 i, j, &red, 1);
388 texel[RCOMP] =
389 texel[GCOMP] =
390 texel[BCOMP] = UBYTE_TO_FLOAT(red);
391 texel[ACOMP] = 1.0;
392 }
393
394 void
395 _mesa_fetch_texel_2d_f_signed_l_latc1(const struct gl_texture_image *texImage,
396 GLint i, GLint j, GLint k, GLfloat *texel)
397 {
398 GLbyte red;
399 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
400 i, j, &red, 1);
401 texel[RCOMP] =
402 texel[GCOMP] =
403 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
404 texel[ACOMP] = 1.0;
405 }
406
407 void
408 _mesa_fetch_texel_2d_f_la_latc2(const struct gl_texture_image *texImage,
409 GLint i, GLint j, GLint k, GLfloat *texel)
410 {
411 GLubyte red, green;
412 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
413 i, j, &red, 2);
414 unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
415 i, j, &green, 2);
416 texel[RCOMP] =
417 texel[GCOMP] =
418 texel[BCOMP] = UBYTE_TO_FLOAT(red);
419 texel[ACOMP] = UBYTE_TO_FLOAT(green);
420 }
421
422 void
423 _mesa_fetch_texel_2d_f_signed_la_latc2(const struct gl_texture_image *texImage,
424 GLint i, GLint j, GLint k, GLfloat *texel)
425 {
426 GLbyte red, green;
427 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
428 i, j, &red, 2);
429 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
430 i, j, &green, 2);
431 texel[RCOMP] =
432 texel[GCOMP] =
433 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
434 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
435 }
436
437 #define TAG(x) unsigned_##x
438
439 #define TYPE GLubyte
440 #define T_MIN 0
441 #define T_MAX 0xff
442
443 #include "texcompress_rgtc_tmp.h"
444
445 #undef TAG
446 #undef TYPE
447 #undef T_MIN
448 #undef T_MAX
449
450 #define TAG(x) signed_##x
451 #define TYPE GLbyte
452 #define T_MIN (GLbyte)-128
453 #define T_MAX (GLbyte)127
454
455 #include "texcompress_rgtc_tmp.h"
456
457 #undef TAG
458 #undef TYPE
459 #undef T_MIN
460 #undef T_MAX