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