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 "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 
     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 
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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