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