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