Home | History | Annotate | Download | only in main
      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 
     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 
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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