Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  * Copyright (c) 2008 VMware, Inc.
      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 shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 
     27 /**
     28  * \file texcompress_s3tc.c
     29  * GL_EXT_texture_compression_s3tc support.
     30  */
     31 
     32 #include "glheader.h"
     33 #include "imports.h"
     34 #include "image.h"
     35 #include "macros.h"
     36 #include "mtypes.h"
     37 #include "texcompress.h"
     38 #include "texcompress_s3tc.h"
     39 #include "texcompress_s3tc_tmp.h"
     40 #include "texstore.h"
     41 #include "format_unpack.h"
     42 #include "util/format_srgb.h"
     43 
     44 
     45 /**
     46  * Store user's image in rgb_dxt1 format.
     47  */
     48 GLboolean
     49 _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
     50 {
     51    const GLubyte *pixels;
     52    GLubyte *dst;
     53    const GLubyte *tempImage = NULL;
     54 
     55    assert(dstFormat == MESA_FORMAT_RGB_DXT1 ||
     56           dstFormat == MESA_FORMAT_SRGB_DXT1);
     57 
     58    if (srcFormat != GL_RGB ||
     59        srcType != GL_UNSIGNED_BYTE ||
     60        ctx->_ImageTransferState ||
     61        ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth ||
     62        srcPacking->SwapBytes) {
     63       /* convert image to RGB/GLubyte */
     64       GLubyte *tempImageSlices[1];
     65       int rgbRowStride = 3 * srcWidth * sizeof(GLubyte);
     66       tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLubyte));
     67       if (!tempImage)
     68          return GL_FALSE; /* out of memory */
     69       tempImageSlices[0] = (GLubyte *) tempImage;
     70       _mesa_texstore(ctx, dims,
     71                      baseInternalFormat,
     72                      MESA_FORMAT_RGB_UNORM8,
     73                      rgbRowStride, tempImageSlices,
     74                      srcWidth, srcHeight, srcDepth,
     75                      srcFormat, srcType, srcAddr,
     76                      srcPacking);
     77       pixels = tempImage;
     78       srcFormat = GL_RGB;
     79    }
     80    else {
     81       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
     82                                      srcFormat, srcType, 0, 0);
     83    }
     84 
     85    dst = dstSlices[0];
     86 
     87    tx_compress_dxtn(3, srcWidth, srcHeight, pixels,
     88                     GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
     89                     dst, dstRowStride);
     90 
     91    free((void *) tempImage);
     92 
     93    return GL_TRUE;
     94 }
     95 
     96 
     97 /**
     98  * Store user's image in rgba_dxt1 format.
     99  */
    100 GLboolean
    101 _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
    102 {
    103    const GLubyte *pixels;
    104    GLubyte *dst;
    105    const GLubyte *tempImage = NULL;
    106 
    107    assert(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
    108           dstFormat == MESA_FORMAT_SRGBA_DXT1);
    109 
    110    if (srcFormat != GL_RGBA ||
    111        srcType != GL_UNSIGNED_BYTE ||
    112        ctx->_ImageTransferState ||
    113        ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth ||
    114        srcPacking->SwapBytes) {
    115       /* convert image to RGBA/GLubyte */
    116       GLubyte *tempImageSlices[1];
    117       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
    118       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
    119       if (!tempImage)
    120          return GL_FALSE; /* out of memory */
    121       tempImageSlices[0] = (GLubyte *) tempImage;
    122       _mesa_texstore(ctx, dims,
    123                      baseInternalFormat,
    124                      _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
    125                                            : MESA_FORMAT_A8B8G8R8_UNORM,
    126                      rgbaRowStride, tempImageSlices,
    127                      srcWidth, srcHeight, srcDepth,
    128                      srcFormat, srcType, srcAddr,
    129                      srcPacking);
    130       pixels = tempImage;
    131       srcFormat = GL_RGBA;
    132    }
    133    else {
    134       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
    135                                      srcFormat, srcType, 0, 0);
    136    }
    137 
    138    dst = dstSlices[0];
    139 
    140    tx_compress_dxtn(4, srcWidth, srcHeight, pixels,
    141                     GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
    142                     dst, dstRowStride);
    143 
    144    free((void*) tempImage);
    145 
    146    return GL_TRUE;
    147 }
    148 
    149 
    150 /**
    151  * Store user's image in rgba_dxt3 format.
    152  */
    153 GLboolean
    154 _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS)
    155 {
    156    const GLubyte *pixels;
    157    GLubyte *dst;
    158    const GLubyte *tempImage = NULL;
    159 
    160    assert(dstFormat == MESA_FORMAT_RGBA_DXT3 ||
    161           dstFormat == MESA_FORMAT_SRGBA_DXT3);
    162 
    163    if (srcFormat != GL_RGBA ||
    164        srcType != GL_UNSIGNED_BYTE ||
    165        ctx->_ImageTransferState ||
    166        ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth ||
    167        srcPacking->SwapBytes) {
    168       /* convert image to RGBA/GLubyte */
    169       GLubyte *tempImageSlices[1];
    170       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
    171       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
    172       if (!tempImage)
    173          return GL_FALSE; /* out of memory */
    174       tempImageSlices[0] = (GLubyte *) tempImage;
    175       _mesa_texstore(ctx, dims,
    176                      baseInternalFormat,
    177                      _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
    178                                            : MESA_FORMAT_A8B8G8R8_UNORM,
    179                      rgbaRowStride, tempImageSlices,
    180                      srcWidth, srcHeight, srcDepth,
    181                      srcFormat, srcType, srcAddr,
    182                      srcPacking);
    183       pixels = tempImage;
    184    }
    185    else {
    186       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
    187                                      srcFormat, srcType, 0, 0);
    188    }
    189 
    190    dst = dstSlices[0];
    191 
    192    tx_compress_dxtn(4, srcWidth, srcHeight, pixels,
    193                     GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
    194                     dst, dstRowStride);
    195 
    196    free((void *) tempImage);
    197 
    198    return GL_TRUE;
    199 }
    200 
    201 
    202 /**
    203  * Store user's image in rgba_dxt5 format.
    204  */
    205 GLboolean
    206 _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)
    207 {
    208    const GLubyte *pixels;
    209    GLubyte *dst;
    210    const GLubyte *tempImage = NULL;
    211 
    212    assert(dstFormat == MESA_FORMAT_RGBA_DXT5 ||
    213           dstFormat == MESA_FORMAT_SRGBA_DXT5);
    214 
    215    if (srcFormat != GL_RGBA ||
    216        srcType != GL_UNSIGNED_BYTE ||
    217        ctx->_ImageTransferState ||
    218        ALIGN(srcPacking->RowLength, srcPacking->Alignment) != srcWidth ||
    219        srcPacking->SwapBytes) {
    220       /* convert image to RGBA/GLubyte */
    221       GLubyte *tempImageSlices[1];
    222       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
    223       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
    224       if (!tempImage)
    225          return GL_FALSE; /* out of memory */
    226       tempImageSlices[0] = (GLubyte *) tempImage;
    227       _mesa_texstore(ctx, dims,
    228                      baseInternalFormat,
    229                      _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
    230                                            : MESA_FORMAT_A8B8G8R8_UNORM,
    231                      rgbaRowStride, tempImageSlices,
    232                      srcWidth, srcHeight, srcDepth,
    233                      srcFormat, srcType, srcAddr,
    234                      srcPacking);
    235       pixels = tempImage;
    236    }
    237    else {
    238       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
    239                                      srcFormat, srcType, 0, 0);
    240    }
    241 
    242    dst = dstSlices[0];
    243 
    244    tx_compress_dxtn(4, srcWidth, srcHeight, pixels,
    245                     GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
    246                     dst, dstRowStride);
    247 
    248    free((void *) tempImage);
    249 
    250    return GL_TRUE;
    251 }
    252 
    253 
    254 static void
    255 fetch_rgb_dxt1(const GLubyte *map,
    256                GLint rowStride, GLint i, GLint j, GLfloat *texel)
    257 {
    258    GLubyte tex[4];
    259    fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex);
    260    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
    261    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
    262    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
    263    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    264 }
    265 
    266 static void
    267 fetch_rgba_dxt1(const GLubyte *map,
    268                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
    269 {
    270    GLubyte tex[4];
    271    fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex);
    272    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
    273    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
    274    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
    275    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    276 }
    277 
    278 static void
    279 fetch_rgba_dxt3(const GLubyte *map,
    280                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
    281 {
    282    GLubyte tex[4];
    283    fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex);
    284    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
    285    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
    286    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
    287    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    288 }
    289 
    290 static void
    291 fetch_rgba_dxt5(const GLubyte *map,
    292                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
    293 {
    294    GLubyte tex[4];
    295    fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex);
    296    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
    297    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
    298    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
    299    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    300 }
    301 
    302 
    303 static void
    304 fetch_srgb_dxt1(const GLubyte *map,
    305                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
    306 {
    307    GLubyte tex[4];
    308    fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex);
    309    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
    310    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
    311    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
    312    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    313 }
    314 
    315 static void
    316 fetch_srgba_dxt1(const GLubyte *map,
    317                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
    318 {
    319    GLubyte tex[4];
    320    fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex);
    321    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
    322    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
    323    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
    324    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    325 }
    326 
    327 static void
    328 fetch_srgba_dxt3(const GLubyte *map,
    329                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
    330 {
    331    GLubyte tex[4];
    332    fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex);
    333    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
    334    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
    335    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
    336    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    337 }
    338 
    339 static void
    340 fetch_srgba_dxt5(const GLubyte *map,
    341                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
    342 {
    343    GLubyte tex[4];
    344    fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex);
    345    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
    346    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
    347    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
    348    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
    349 }
    350 
    351 
    352 
    353 compressed_fetch_func
    354 _mesa_get_dxt_fetch_func(mesa_format format)
    355 {
    356    switch (format) {
    357    case MESA_FORMAT_RGB_DXT1:
    358       return fetch_rgb_dxt1;
    359    case MESA_FORMAT_RGBA_DXT1:
    360       return fetch_rgba_dxt1;
    361    case MESA_FORMAT_RGBA_DXT3:
    362       return fetch_rgba_dxt3;
    363    case MESA_FORMAT_RGBA_DXT5:
    364       return fetch_rgba_dxt5;
    365    case MESA_FORMAT_SRGB_DXT1:
    366       return fetch_srgb_dxt1;
    367    case MESA_FORMAT_SRGBA_DXT1:
    368       return fetch_srgba_dxt1;
    369    case MESA_FORMAT_SRGBA_DXT3:
    370       return fetch_srgba_dxt3;
    371    case MESA_FORMAT_SRGBA_DXT5:
    372       return fetch_srgba_dxt5;
    373    default:
    374       return NULL;
    375    }
    376 }
    377