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
extractsrc_u(GLubyte srcpixels[4][4],const GLubyte * srcaddr,GLint srcRowStride,GLint numxpixels,GLint numypixels,GLint comps)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
extractsrc_s(GLbyte srcpixels[4][4],const GLfloat * srcaddr,GLint srcRowStride,GLint numxpixels,GLint numypixels,GLint comps)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
_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)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
_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)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
_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)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_little_endian() ? MESA_FORMAT_R8G8_UNORM
200 : MESA_FORMAT_G8R8_UNORM;
201 else
202 tempFormat = _mesa_little_endian() ? MESA_FORMAT_L8A8_UNORM
203 : MESA_FORMAT_A8L8_UNORM;
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