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