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