util: move shared rgtc code to util (v2)
[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 "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;
87 ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_UNORM ||
88 dstFormat == MESA_FORMAT_L_LATC1_UNORM);
89
90 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
91 baseInternalFormat,
92 _mesa_get_format_base_format(dstFormat),
93 srcWidth, srcHeight, srcDepth,
94 srcFormat, srcType, srcAddr,
95 srcPacking);
96 if (!tempImage)
97 return GL_FALSE; /* out of memory */
98
99 dst = dstSlices[0];
100
101 blkaddr = dst;
102 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
103 for (j = 0; j < srcHeight; j+=4) {
104 if (srcHeight > j + 3) numypixels = 4;
105 else numypixels = srcHeight - j;
106 srcaddr = tempImage + j * srcWidth;
107 for (i = 0; i < srcWidth; i += 4) {
108 if (srcWidth > i + 3) numxpixels = 4;
109 else numxpixels = srcWidth - i;
110 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
111 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
112 srcaddr += numxpixels;
113 blkaddr += 8;
114 }
115 blkaddr += dstRowDiff;
116 }
117
118 free((void *) tempImage);
119
120 return GL_TRUE;
121 }
122
123 GLboolean
124 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
125 {
126 GLbyte *dst;
127 const GLfloat *tempImage = NULL;
128 int i, j;
129 int numxpixels, numypixels;
130 const GLfloat *srcaddr;
131 GLbyte srcpixels[4][4];
132 GLbyte *blkaddr;
133 GLint dstRowDiff;
134 ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_SNORM ||
135 dstFormat == MESA_FORMAT_L_LATC1_SNORM);
136
137 tempImage = _mesa_make_temp_float_image(ctx, dims,
138 baseInternalFormat,
139 _mesa_get_format_base_format(dstFormat),
140 srcWidth, srcHeight, srcDepth,
141 srcFormat, srcType, srcAddr,
142 srcPacking, 0x0);
143 if (!tempImage)
144 return GL_FALSE; /* out of memory */
145
146 dst = (GLbyte *) dstSlices[0];
147
148 blkaddr = dst;
149 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
150 for (j = 0; j < srcHeight; j+=4) {
151 if (srcHeight > j + 3) numypixels = 4;
152 else numypixels = srcHeight - j;
153 srcaddr = tempImage + j * srcWidth;
154 for (i = 0; i < srcWidth; i += 4) {
155 if (srcWidth > i + 3) numxpixels = 4;
156 else numxpixels = srcWidth - i;
157 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
158 util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
159 srcaddr += numxpixels;
160 blkaddr += 8;
161 }
162 blkaddr += dstRowDiff;
163 }
164
165 free((void *) tempImage);
166
167 return GL_TRUE;
168 }
169
170 GLboolean
171 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
172 {
173 GLubyte *dst;
174 const GLubyte *tempImage = NULL;
175 int i, j;
176 int numxpixels, numypixels;
177 const GLubyte *srcaddr;
178 GLubyte srcpixels[4][4];
179 GLubyte *blkaddr;
180 GLint dstRowDiff;
181
182 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM ||
183 dstFormat == MESA_FORMAT_LA_LATC2_UNORM);
184
185 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
186 baseInternalFormat,
187 _mesa_get_format_base_format(dstFormat),
188 srcWidth, srcHeight, srcDepth,
189 srcFormat, srcType, srcAddr,
190 srcPacking);
191 if (!tempImage)
192 return GL_FALSE; /* out of memory */
193
194 dst = dstSlices[0];
195
196 blkaddr = dst;
197 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
198 for (j = 0; j < srcHeight; j+=4) {
199 if (srcHeight > j + 3) numypixels = 4;
200 else numypixels = srcHeight - j;
201 srcaddr = tempImage + j * srcWidth * 2;
202 for (i = 0; i < srcWidth; i += 4) {
203 if (srcWidth > i + 3) numxpixels = 4;
204 else numxpixels = srcWidth - i;
205 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
206 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
207
208 blkaddr += 8;
209 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
210 util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
211
212 blkaddr += 8;
213
214 srcaddr += numxpixels * 2;
215 }
216 blkaddr += dstRowDiff;
217 }
218
219 free((void *) tempImage);
220
221 return GL_TRUE;
222 }
223
224 GLboolean
225 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
226 {
227 GLbyte *dst;
228 const GLfloat *tempImage = NULL;
229 int i, j;
230 int numxpixels, numypixels;
231 const GLfloat *srcaddr;
232 GLbyte srcpixels[4][4];
233 GLbyte *blkaddr;
234 GLint dstRowDiff;
235
236 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM ||
237 dstFormat == MESA_FORMAT_LA_LATC2_SNORM);
238
239 tempImage = _mesa_make_temp_float_image(ctx, dims,
240 baseInternalFormat,
241 _mesa_get_format_base_format(dstFormat),
242 srcWidth, srcHeight, srcDepth,
243 srcFormat, srcType, srcAddr,
244 srcPacking, 0x0);
245 if (!tempImage)
246 return GL_FALSE; /* out of memory */
247
248 dst = (GLbyte *) dstSlices[0];
249
250 blkaddr = dst;
251 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
252 for (j = 0; j < srcHeight; j += 4) {
253 if (srcHeight > j + 3) numypixels = 4;
254 else numypixels = srcHeight - j;
255 srcaddr = tempImage + j * srcWidth * 2;
256 for (i = 0; i < srcWidth; i += 4) {
257 if (srcWidth > i + 3) numxpixels = 4;
258 else numxpixels = srcWidth - i;
259
260 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
261 util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
262 blkaddr += 8;
263
264 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
265 util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
266 blkaddr += 8;
267
268 srcaddr += numxpixels * 2;
269
270 }
271 blkaddr += dstRowDiff;
272 }
273
274 free((void *) tempImage);
275
276 return GL_TRUE;
277 }
278
279 static void
280 fetch_red_rgtc1(const GLubyte *map,
281 GLint rowStride, GLint i, GLint j, GLfloat *texel)
282 {
283 GLubyte red;
284 util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
285 texel[RCOMP] = UBYTE_TO_FLOAT(red);
286 texel[GCOMP] = 0.0;
287 texel[BCOMP] = 0.0;
288 texel[ACOMP] = 1.0;
289 }
290
291 static void
292 fetch_l_latc1(const GLubyte *map,
293 GLint rowStride, GLint i, GLint j, GLfloat *texel)
294 {
295 GLubyte red;
296 util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
297 texel[RCOMP] =
298 texel[GCOMP] =
299 texel[BCOMP] = UBYTE_TO_FLOAT(red);
300 texel[ACOMP] = 1.0;
301 }
302
303 static void
304 fetch_signed_red_rgtc1(const GLubyte *map,
305 GLint rowStride, GLint i, GLint j, GLfloat *texel)
306 {
307 GLbyte red;
308 util_format_signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map,
309 i, j, &red, 1);
310 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
311 texel[GCOMP] = 0.0;
312 texel[BCOMP] = 0.0;
313 texel[ACOMP] = 1.0;
314 }
315
316 static void
317 fetch_signed_l_latc1(const GLubyte *map,
318 GLint rowStride, GLint i, GLint j, GLfloat *texel)
319 {
320 GLbyte red;
321 util_format_signed_fetch_texel_rgtc(rowStride, (GLbyte *) map,
322 i, j, &red, 1);
323 texel[RCOMP] =
324 texel[GCOMP] =
325 texel[BCOMP] = BYTE_TO_FLOAT(red);
326 texel[ACOMP] = 1.0;
327 }
328
329 static void
330 fetch_rg_rgtc2(const GLubyte *map,
331 GLint rowStride, GLint i, GLint j, GLfloat *texel)
332 {
333 GLubyte red, green;
334 util_format_unsigned_fetch_texel_rgtc(rowStride,
335 map,
336 i, j, &red, 2);
337 util_format_unsigned_fetch_texel_rgtc(rowStride,
338 map + 8,
339 i, j, &green, 2);
340 texel[RCOMP] = UBYTE_TO_FLOAT(red);
341 texel[GCOMP] = UBYTE_TO_FLOAT(green);
342 texel[BCOMP] = 0.0;
343 texel[ACOMP] = 1.0;
344 }
345
346 static void
347 fetch_la_latc2(const GLubyte *map,
348 GLint rowStride, GLint i, GLint j, GLfloat *texel)
349 {
350 GLubyte red, green;
351 util_format_unsigned_fetch_texel_rgtc(rowStride,
352 map,
353 i, j, &red, 2);
354 util_format_unsigned_fetch_texel_rgtc(rowStride,
355 map + 8,
356 i, j, &green, 2);
357 texel[RCOMP] =
358 texel[GCOMP] =
359 texel[BCOMP] = UBYTE_TO_FLOAT(red);
360 texel[ACOMP] = UBYTE_TO_FLOAT(green);
361 }
362
363
364 static void
365 fetch_signed_rg_rgtc2(const GLubyte *map,
366 GLint rowStride, GLint i, GLint j, GLfloat *texel)
367 {
368 GLbyte red, green;
369 util_format_signed_fetch_texel_rgtc(rowStride,
370 (GLbyte *) map,
371 i, j, &red, 2);
372 util_format_signed_fetch_texel_rgtc(rowStride,
373 (GLbyte *) map + 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
382 static void
383 fetch_signed_la_latc2(const GLubyte *map,
384 GLint rowStride, GLint i, GLint j, GLfloat *texel)
385 {
386 GLbyte red, green;
387 util_format_signed_fetch_texel_rgtc(rowStride,
388 (GLbyte *) map,
389 i, j, &red, 2);
390 util_format_signed_fetch_texel_rgtc(rowStride,
391 (GLbyte *) map + 8,
392 i, j, &green, 2);
393 texel[RCOMP] =
394 texel[GCOMP] =
395 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
396 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
397 }
398
399
400 compressed_fetch_func
401 _mesa_get_compressed_rgtc_func(mesa_format format)
402 {
403 switch (format) {
404 case MESA_FORMAT_R_RGTC1_UNORM:
405 return fetch_red_rgtc1;
406 case MESA_FORMAT_L_LATC1_UNORM:
407 return fetch_l_latc1;
408 case MESA_FORMAT_R_RGTC1_SNORM:
409 return fetch_signed_red_rgtc1;
410 case MESA_FORMAT_L_LATC1_SNORM:
411 return fetch_signed_l_latc1;
412 case MESA_FORMAT_RG_RGTC2_UNORM:
413 return fetch_rg_rgtc2;
414 case MESA_FORMAT_LA_LATC2_UNORM:
415 return fetch_la_latc2;
416 case MESA_FORMAT_RG_RGTC2_SNORM:
417 return fetch_signed_rg_rgtc2;
418 case MESA_FORMAT_LA_LATC2_SNORM:
419 return fetch_signed_la_latc2;
420 default:
421 return NULL;
422 }
423 }