• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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