Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      4  * Copyright (c) 2008 VMware, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  **************************************************************************/
     25 
     26 #include "u_dl.h"
     27 #include "u_math.h"
     28 #include "u_format.h"
     29 #include "u_format_s3tc.h"
     30 #include "util/format_srgb.h"
     31 
     32 
     33 #if defined(_WIN32) || defined(WIN32)
     34 #define DXTN_LIBNAME "dxtn.dll"
     35 #elif defined(__CYGWIN__)
     36 #define DXTN_LIBNAME "cygtxc_dxtn.dll"
     37 #elif defined(__APPLE__)
     38 #define DXTN_LIBNAME "libtxc_dxtn.dylib"
     39 #else
     40 #define DXTN_LIBNAME "libtxc_dxtn.so"
     41 #endif
     42 
     43 
     44 static void
     45 util_format_dxt1_rgb_fetch_stub(int src_stride,
     46                                 const uint8_t *src,
     47                                 int col, int row,
     48                                 uint8_t *dst)
     49 {
     50    assert(0);
     51 }
     52 
     53 
     54 static void
     55 util_format_dxt1_rgba_fetch_stub(int src_stride,
     56                                  const uint8_t *src,
     57                                  int col, int row,
     58                                  uint8_t *dst )
     59 {
     60    assert(0);
     61 }
     62 
     63 
     64 static void
     65 util_format_dxt3_rgba_fetch_stub(int src_stride,
     66                                  const uint8_t *src,
     67                                  int col, int row,
     68                                  uint8_t *dst )
     69 {
     70    assert(0);
     71 }
     72 
     73 
     74 static void
     75 util_format_dxt5_rgba_fetch_stub(int src_stride,
     76                                  const uint8_t *src,
     77                                  int col, int row,
     78                                  uint8_t *dst )
     79 {
     80    assert(0);
     81 }
     82 
     83 
     84 static void
     85 util_format_dxtn_pack_stub(int src_comps,
     86                            int width, int height,
     87                            const uint8_t *src,
     88                            enum util_format_dxtn dst_format,
     89                            uint8_t *dst,
     90                            int dst_stride)
     91 {
     92    assert(0);
     93 }
     94 
     95 
     96 boolean util_format_s3tc_enabled = FALSE;
     97 
     98 util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = util_format_dxt1_rgb_fetch_stub;
     99 util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = util_format_dxt1_rgba_fetch_stub;
    100 util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = util_format_dxt3_rgba_fetch_stub;
    101 util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = util_format_dxt5_rgba_fetch_stub;
    102 
    103 util_format_dxtn_pack_t util_format_dxtn_pack = util_format_dxtn_pack_stub;
    104 
    105 
    106 void
    107 util_format_s3tc_init(void)
    108 {
    109    static boolean first_time = TRUE;
    110    struct util_dl_library *library = NULL;
    111    util_dl_proc fetch_2d_texel_rgb_dxt1;
    112    util_dl_proc fetch_2d_texel_rgba_dxt1;
    113    util_dl_proc fetch_2d_texel_rgba_dxt3;
    114    util_dl_proc fetch_2d_texel_rgba_dxt5;
    115    util_dl_proc tx_compress_dxtn;
    116 
    117    if (!first_time)
    118       return;
    119    first_time = FALSE;
    120 
    121    if (util_format_s3tc_enabled)
    122       return;
    123 
    124    library = util_dl_open(DXTN_LIBNAME);
    125    if (!library) {
    126       debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
    127                    "compression/decompression unavailable\n");
    128       return;
    129    }
    130 
    131    fetch_2d_texel_rgb_dxt1 =
    132          util_dl_get_proc_address(library, "fetch_2d_texel_rgb_dxt1");
    133    fetch_2d_texel_rgba_dxt1 =
    134          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt1");
    135    fetch_2d_texel_rgba_dxt3 =
    136          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt3");
    137    fetch_2d_texel_rgba_dxt5 =
    138          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt5");
    139    tx_compress_dxtn =
    140          util_dl_get_proc_address(library, "tx_compress_dxtn");
    141 
    142    if (!util_format_dxt1_rgb_fetch ||
    143        !util_format_dxt1_rgba_fetch ||
    144        !util_format_dxt3_rgba_fetch ||
    145        !util_format_dxt5_rgba_fetch ||
    146        !util_format_dxtn_pack) {
    147       debug_printf("couldn't reference all symbols in " DXTN_LIBNAME
    148                    ", software DXTn compression/decompression "
    149                    "unavailable\n");
    150       util_dl_close(library);
    151       return;
    152    }
    153 
    154    util_format_dxt1_rgb_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgb_dxt1;
    155    util_format_dxt1_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt1;
    156    util_format_dxt3_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt3;
    157    util_format_dxt5_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt5;
    158    util_format_dxtn_pack = (util_format_dxtn_pack_t)tx_compress_dxtn;
    159    util_format_s3tc_enabled = TRUE;
    160 }
    161 
    162 
    163 /*
    164  * Pixel fetch.
    165  */
    166 
    167 void
    168 util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    169 {
    170    util_format_dxt1_rgb_fetch(0, src, i, j, dst);
    171 }
    172 
    173 void
    174 util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    175 {
    176    util_format_dxt1_rgba_fetch(0, src, i, j, dst);
    177 }
    178 
    179 void
    180 util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    181 {
    182    util_format_dxt3_rgba_fetch(0, src, i, j, dst);
    183 }
    184 
    185 void
    186 util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    187 {
    188    util_format_dxt5_rgba_fetch(0, src, i, j, dst);
    189 }
    190 
    191 void
    192 util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    193 {
    194    uint8_t tmp[4];
    195    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
    196    dst[0] = ubyte_to_float(tmp[0]);
    197    dst[1] = ubyte_to_float(tmp[1]);
    198    dst[2] = ubyte_to_float(tmp[2]);
    199    dst[3] = 1.0;
    200 }
    201 
    202 void
    203 util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    204 {
    205    uint8_t tmp[4];
    206    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
    207    dst[0] = ubyte_to_float(tmp[0]);
    208    dst[1] = ubyte_to_float(tmp[1]);
    209    dst[2] = ubyte_to_float(tmp[2]);
    210    dst[3] = ubyte_to_float(tmp[3]);
    211 }
    212 
    213 void
    214 util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    215 {
    216    uint8_t tmp[4];
    217    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
    218    dst[0] = ubyte_to_float(tmp[0]);
    219    dst[1] = ubyte_to_float(tmp[1]);
    220    dst[2] = ubyte_to_float(tmp[2]);
    221    dst[3] = ubyte_to_float(tmp[3]);
    222 }
    223 
    224 void
    225 util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    226 {
    227    uint8_t tmp[4];
    228    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
    229    dst[0] = ubyte_to_float(tmp[0]);
    230    dst[1] = ubyte_to_float(tmp[1]);
    231    dst[2] = ubyte_to_float(tmp[2]);
    232    dst[3] = ubyte_to_float(tmp[3]);
    233 }
    234 
    235 
    236 /*
    237  * Block decompression.
    238  */
    239 
    240 static inline void
    241 util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    242                                         const uint8_t *src_row, unsigned src_stride,
    243                                         unsigned width, unsigned height,
    244                                         util_format_dxtn_fetch_t fetch,
    245                                         unsigned block_size, boolean srgb)
    246 {
    247    const unsigned bw = 4, bh = 4, comps = 4;
    248    unsigned x, y, i, j;
    249    for(y = 0; y < height; y += bh) {
    250       const uint8_t *src = src_row;
    251       for(x = 0; x < width; x += bw) {
    252          for(j = 0; j < bh; ++j) {
    253             for(i = 0; i < bw; ++i) {
    254                uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
    255                fetch(0, src, i, j, dst);
    256                if (srgb) {
    257                   dst[0] = util_format_srgb_to_linear_8unorm(dst[0]);
    258                   dst[1] = util_format_srgb_to_linear_8unorm(dst[1]);
    259                   dst[2] = util_format_srgb_to_linear_8unorm(dst[2]);
    260                }
    261             }
    262          }
    263          src += block_size;
    264       }
    265       src_row += src_stride;
    266    }
    267 }
    268 
    269 void
    270 util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    271                                         const uint8_t *src_row, unsigned src_stride,
    272                                         unsigned width, unsigned height)
    273 {
    274    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    275                                            src_row, src_stride,
    276                                            width, height,
    277                                            util_format_dxt1_rgb_fetch,
    278                                            8, FALSE);
    279 }
    280 
    281 void
    282 util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    283                                          const uint8_t *src_row, unsigned src_stride,
    284                                          unsigned width, unsigned height)
    285 {
    286    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    287                                            src_row, src_stride,
    288                                            width, height,
    289                                            util_format_dxt1_rgba_fetch,
    290                                            8, FALSE);
    291 }
    292 
    293 void
    294 util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    295                                          const uint8_t *src_row, unsigned src_stride,
    296                                          unsigned width, unsigned height)
    297 {
    298    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    299                                            src_row, src_stride,
    300                                            width, height,
    301                                            util_format_dxt3_rgba_fetch,
    302                                            16, FALSE);
    303 }
    304 
    305 void
    306 util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    307                                          const uint8_t *src_row, unsigned src_stride,
    308                                          unsigned width, unsigned height)
    309 {
    310    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    311                                            src_row, src_stride,
    312                                            width, height,
    313                                            util_format_dxt5_rgba_fetch,
    314                                            16, FALSE);
    315 }
    316 
    317 static inline void
    318 util_format_dxtn_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    319                                        const uint8_t *src_row, unsigned src_stride,
    320                                        unsigned width, unsigned height,
    321                                        util_format_dxtn_fetch_t fetch,
    322                                        unsigned block_size, boolean srgb)
    323 {
    324    unsigned x, y, i, j;
    325    for(y = 0; y < height; y += 4) {
    326       const uint8_t *src = src_row;
    327       for(x = 0; x < width; x += 4) {
    328          for(j = 0; j < 4; ++j) {
    329             for(i = 0; i < 4; ++i) {
    330                float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
    331                uint8_t tmp[4];
    332                fetch(0, src, i, j, tmp);
    333                if (srgb) {
    334                   dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
    335                   dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
    336                   dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
    337                }
    338                else {
    339                   dst[0] = ubyte_to_float(tmp[0]);
    340                   dst[1] = ubyte_to_float(tmp[1]);
    341                   dst[2] = ubyte_to_float(tmp[2]);
    342                }
    343                dst[3] = ubyte_to_float(tmp[3]);
    344             }
    345          }
    346          src += block_size;
    347       }
    348       src_row += src_stride;
    349    }
    350 }
    351 
    352 void
    353 util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    354                                        const uint8_t *src_row, unsigned src_stride,
    355                                        unsigned width, unsigned height)
    356 {
    357    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    358                                           src_row, src_stride,
    359                                           width, height,
    360                                           util_format_dxt1_rgb_fetch,
    361                                           8, FALSE);
    362 }
    363 
    364 void
    365 util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    366                                         const uint8_t *src_row, unsigned src_stride,
    367                                         unsigned width, unsigned height)
    368 {
    369    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    370                                           src_row, src_stride,
    371                                           width, height,
    372                                           util_format_dxt1_rgba_fetch,
    373                                           8, FALSE);
    374 }
    375 
    376 void
    377 util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    378                                         const uint8_t *src_row, unsigned src_stride,
    379                                         unsigned width, unsigned height)
    380 {
    381    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    382                                           src_row, src_stride,
    383                                           width, height,
    384                                           util_format_dxt3_rgba_fetch,
    385                                           16, FALSE);
    386 }
    387 
    388 void
    389 util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    390                                         const uint8_t *src_row, unsigned src_stride,
    391                                         unsigned width, unsigned height)
    392 {
    393    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    394                                           src_row, src_stride,
    395                                           width, height,
    396                                           util_format_dxt5_rgba_fetch,
    397                                           16, FALSE);
    398 }
    399 
    400 
    401 /*
    402  * Block compression.
    403  */
    404 
    405 static inline void
    406 util_format_dxtn_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    407                                   const uint8_t *src, unsigned src_stride,
    408                                   unsigned width, unsigned height,
    409                                   enum util_format_dxtn format,
    410                                   unsigned block_size, boolean srgb)
    411 {
    412    const unsigned bw = 4, bh = 4, comps = 4;
    413    unsigned x, y, i, j, k;
    414    for(y = 0; y < height; y += bh) {
    415       uint8_t *dst = dst_row;
    416       for(x = 0; x < width; x += bw) {
    417          uint8_t tmp[4][4][4];  /* [bh][bw][comps] */
    418          for(j = 0; j < bh; ++j) {
    419             for(i = 0; i < bw; ++i) {
    420                uint8_t src_tmp;
    421                for(k = 0; k < 3; ++k) {
    422                   src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + k];
    423                   if (srgb) {
    424                      tmp[j][i][k] = util_format_linear_to_srgb_8unorm(src_tmp);
    425                   }
    426                   else {
    427                      tmp[j][i][k] = src_tmp;
    428                   }
    429                }
    430                /* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */
    431                tmp[j][i][3] = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + 3];
    432             }
    433          }
    434          /* even for dxt1_rgb have 4 src comps */
    435          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0);
    436          dst += block_size;
    437       }
    438       dst_row += dst_stride / sizeof(*dst_row);
    439    }
    440 
    441 }
    442 
    443 void
    444 util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    445                                       const uint8_t *src, unsigned src_stride,
    446                                       unsigned width, unsigned height)
    447 {
    448    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
    449                                      width, height, UTIL_FORMAT_DXT1_RGB,
    450                                      8, FALSE);
    451 }
    452 
    453 void
    454 util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    455                                        const uint8_t *src, unsigned src_stride,
    456                                        unsigned width, unsigned height)
    457 {
    458    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
    459                                      width, height, UTIL_FORMAT_DXT1_RGBA,
    460                                      8, FALSE);
    461 }
    462 
    463 void
    464 util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    465                                        const uint8_t *src, unsigned src_stride,
    466                                        unsigned width, unsigned height)
    467 {
    468    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
    469                                      width, height, UTIL_FORMAT_DXT3_RGBA,
    470                                      16, FALSE);
    471 }
    472 
    473 void
    474 util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    475                                        const uint8_t *src, unsigned src_stride,
    476                                        unsigned width, unsigned height)
    477 {
    478    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
    479                                      width, height, UTIL_FORMAT_DXT5_RGBA,
    480                                      16, FALSE);
    481 }
    482 
    483 static inline void
    484 util_format_dxtn_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    485                                  const float *src, unsigned src_stride,
    486                                  unsigned width, unsigned height,
    487                                  enum util_format_dxtn format,
    488                                  unsigned block_size, boolean srgb)
    489 {
    490    unsigned x, y, i, j, k;
    491    for(y = 0; y < height; y += 4) {
    492       uint8_t *dst = dst_row;
    493       for(x = 0; x < width; x += 4) {
    494          uint8_t tmp[4][4][4];
    495          for(j = 0; j < 4; ++j) {
    496             for(i = 0; i < 4; ++i) {
    497                float src_tmp;
    498                for(k = 0; k < 3; ++k) {
    499                   src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k];
    500                   if (srgb) {
    501                      tmp[j][i][k] = util_format_linear_float_to_srgb_8unorm(src_tmp);
    502                   }
    503                   else {
    504                      tmp[j][i][k] = float_to_ubyte(src_tmp);
    505                   }
    506                }
    507                /* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */
    508                src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + 3];
    509                tmp[j][i][3] = float_to_ubyte(src_tmp);
    510             }
    511          }
    512          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0);
    513          dst += block_size;
    514       }
    515       dst_row += 4*dst_stride/sizeof(*dst_row);
    516    }
    517 }
    518 
    519 void
    520 util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    521                                      const float *src, unsigned src_stride,
    522                                      unsigned width, unsigned height)
    523 {
    524    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
    525                                     width, height, UTIL_FORMAT_DXT1_RGB,
    526                                     8, FALSE);
    527 }
    528 
    529 void
    530 util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    531                                       const float *src, unsigned src_stride,
    532                                       unsigned width, unsigned height)
    533 {
    534    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
    535                                     width, height, UTIL_FORMAT_DXT1_RGBA,
    536                                     8, FALSE);
    537 }
    538 
    539 void
    540 util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    541                                       const float *src, unsigned src_stride,
    542                                       unsigned width, unsigned height)
    543 {
    544    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
    545                                     width, height, UTIL_FORMAT_DXT3_RGBA,
    546                                     16, FALSE);
    547 }
    548 
    549 void
    550 util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    551                                       const float *src, unsigned src_stride,
    552                                       unsigned width, unsigned height)
    553 {
    554    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
    555                                     width, height, UTIL_FORMAT_DXT5_RGBA,
    556                                     16, FALSE);
    557 }
    558 
    559 
    560 /*
    561  * SRGB variants.
    562  */
    563 
    564 void
    565 util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    566 {
    567    uint8_t tmp[4];
    568    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
    569    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
    570    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
    571    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
    572    dst[3] = 255;
    573 }
    574 
    575 void
    576 util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    577 {
    578    uint8_t tmp[4];
    579    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
    580    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
    581    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
    582    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
    583    dst[3] = tmp[3];
    584 }
    585 
    586 void
    587 util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    588 {
    589    uint8_t tmp[4];
    590    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
    591    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
    592    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
    593    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
    594    dst[3] = tmp[3];
    595 }
    596 
    597 void
    598 util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    599 {
    600    uint8_t tmp[4];
    601    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
    602    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
    603    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
    604    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
    605    dst[3] = tmp[3];
    606 }
    607 
    608 void
    609 util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    610 {
    611    uint8_t tmp[4];
    612    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
    613    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
    614    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
    615    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
    616    dst[3] = 1.0f;
    617 }
    618 
    619 void
    620 util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    621 {
    622    uint8_t tmp[4];
    623    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
    624    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
    625    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
    626    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
    627    dst[3] = ubyte_to_float(tmp[3]);
    628 }
    629 
    630 void
    631 util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    632 {
    633    uint8_t tmp[4];
    634    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
    635    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
    636    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
    637    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
    638    dst[3] = ubyte_to_float(tmp[3]);
    639 }
    640 
    641 void
    642 util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    643 {
    644    uint8_t tmp[4];
    645    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
    646    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
    647    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
    648    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
    649    dst[3] = ubyte_to_float(tmp[3]);
    650 }
    651 
    652 void
    653 util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    654 {
    655    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    656                                            src_row, src_stride,
    657                                            width, height,
    658                                            util_format_dxt1_rgb_fetch,
    659                                            8, TRUE);
    660 }
    661 
    662 void
    663 util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    664 {
    665    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    666                                            src_row, src_stride,
    667                                            width, height,
    668                                            util_format_dxt1_rgba_fetch,
    669                                            8, TRUE);
    670 }
    671 
    672 void
    673 util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    674 {
    675    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    676                                            src_row, src_stride,
    677                                            width, height,
    678                                            util_format_dxt3_rgba_fetch,
    679                                            16, TRUE);
    680 }
    681 
    682 void
    683 util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    684 {
    685    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    686                                            src_row, src_stride,
    687                                            width, height,
    688                                            util_format_dxt5_rgba_fetch,
    689                                            16, TRUE);
    690 }
    691 
    692 void
    693 util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    694 {
    695    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    696                                           src_row, src_stride,
    697                                           width, height,
    698                                           util_format_dxt1_rgb_fetch,
    699                                           8, TRUE);
    700 }
    701 
    702 void
    703 util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    704 {
    705    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    706                                           src_row, src_stride,
    707                                           width, height,
    708                                           util_format_dxt1_rgba_fetch,
    709                                           8, TRUE);
    710 }
    711 
    712 void
    713 util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    714 {
    715    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    716                                           src_row, src_stride,
    717                                           width, height,
    718                                           util_format_dxt3_rgba_fetch,
    719                                           16, TRUE);
    720 }
    721 
    722 void
    723 util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    724 {
    725    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    726                                           src_row, src_stride,
    727                                           width, height,
    728                                           util_format_dxt5_rgba_fetch,
    729                                           16, TRUE);
    730 }
    731 
    732 void
    733 util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    734 {
    735    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
    736                                      width, height, UTIL_FORMAT_DXT1_RGB,
    737                                      8, TRUE);
    738 }
    739 
    740 void
    741 util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    742 {
    743    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
    744                                      width, height, UTIL_FORMAT_DXT1_RGBA,
    745                                      8, TRUE);
    746 }
    747 
    748 void
    749 util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    750 {
    751    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
    752                                      width, height, UTIL_FORMAT_DXT3_RGBA,
    753                                      16, TRUE);
    754 }
    755 
    756 void
    757 util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
    758 {
    759    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
    760                                      width, height, UTIL_FORMAT_DXT5_RGBA,
    761                                      16, TRUE);
    762 }
    763 
    764 void
    765 util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
    766 {
    767    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
    768                                     width, height, UTIL_FORMAT_DXT1_RGB,
    769                                     8, TRUE);
    770 }
    771 
    772 void
    773 util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
    774 {
    775    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
    776                                     width, height, UTIL_FORMAT_DXT1_RGBA,
    777                                     8, TRUE);
    778 }
    779 
    780 void
    781 util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
    782 {
    783    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
    784                                     width, height, UTIL_FORMAT_DXT3_RGBA,
    785                                     16, TRUE);
    786 }
    787 
    788 void
    789 util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
    790 {
    791    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
    792                                     width, height, UTIL_FORMAT_DXT5_RGBA,
    793                                     16, TRUE);
    794 }
    795 
    796