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