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  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     20  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  **************************************************************************/
     24 
     25 #include "u_dl.h"
     26 #include "u_math.h"
     27 #include "u_format.h"
     28 #include "u_format_s3tc.h"
     29 
     30 
     31 #if defined(_WIN32) || defined(WIN32)
     32 #define DXTN_LIBNAME "dxtn.dll"
     33 #elif defined(__APPLE__)
     34 #define DXTN_LIBNAME "libtxc_dxtn.dylib"
     35 #else
     36 #define DXTN_LIBNAME "libtxc_dxtn.so"
     37 #endif
     38 
     39 
     40 static void
     41 util_format_dxt1_rgb_fetch_stub(int src_stride,
     42                                 const uint8_t *src,
     43                                 int col, int row,
     44                                 uint8_t *dst)
     45 {
     46    assert(0);
     47 }
     48 
     49 
     50 static void
     51 util_format_dxt1_rgba_fetch_stub(int src_stride,
     52                                  const uint8_t *src,
     53                                  int col, int row,
     54                                  uint8_t *dst )
     55 {
     56    assert(0);
     57 }
     58 
     59 
     60 static void
     61 util_format_dxt3_rgba_fetch_stub(int src_stride,
     62                                  const uint8_t *src,
     63                                  int col, int row,
     64                                  uint8_t *dst )
     65 {
     66    assert(0);
     67 }
     68 
     69 
     70 static void
     71 util_format_dxt5_rgba_fetch_stub(int src_stride,
     72                                  const uint8_t *src,
     73                                  int col, int row,
     74                                  uint8_t *dst )
     75 {
     76    assert(0);
     77 }
     78 
     79 
     80 static void
     81 util_format_dxtn_pack_stub(int src_comps,
     82                            int width, int height,
     83                            const uint8_t *src,
     84                            enum util_format_dxtn dst_format,
     85                            uint8_t *dst,
     86                            int dst_stride)
     87 {
     88    assert(0);
     89 }
     90 
     91 
     92 boolean util_format_s3tc_enabled = FALSE;
     93 
     94 util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = util_format_dxt1_rgb_fetch_stub;
     95 util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = util_format_dxt1_rgba_fetch_stub;
     96 util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = util_format_dxt3_rgba_fetch_stub;
     97 util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = util_format_dxt5_rgba_fetch_stub;
     98 
     99 util_format_dxtn_pack_t util_format_dxtn_pack = util_format_dxtn_pack_stub;
    100 
    101 
    102 void
    103 util_format_s3tc_init(void)
    104 {
    105    static boolean first_time = TRUE;
    106    struct util_dl_library *library = NULL;
    107    util_dl_proc fetch_2d_texel_rgb_dxt1;
    108    util_dl_proc fetch_2d_texel_rgba_dxt1;
    109    util_dl_proc fetch_2d_texel_rgba_dxt3;
    110    util_dl_proc fetch_2d_texel_rgba_dxt5;
    111    util_dl_proc tx_compress_dxtn;
    112 
    113    if (!first_time)
    114       return;
    115    first_time = FALSE;
    116 
    117    if (util_format_s3tc_enabled)
    118       return;
    119 
    120    library = util_dl_open(DXTN_LIBNAME);
    121    if (!library) {
    122       if (getenv("force_s3tc_enable") &&
    123           !strcmp(getenv("force_s3tc_enable"), "true")) {
    124          debug_printf("couldn't open " DXTN_LIBNAME ", enabling DXTn due to "
    125             "force_s3tc_enable=true environment variable\n");
    126          util_format_s3tc_enabled = TRUE;
    127       } else {
    128          debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
    129             "compression/decompression unavailable\n");
    130       }
    131       return;
    132    }
    133 
    134    fetch_2d_texel_rgb_dxt1 =
    135          util_dl_get_proc_address(library, "fetch_2d_texel_rgb_dxt1");
    136    fetch_2d_texel_rgba_dxt1 =
    137          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt1");
    138    fetch_2d_texel_rgba_dxt3 =
    139          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt3");
    140    fetch_2d_texel_rgba_dxt5 =
    141          util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt5");
    142    tx_compress_dxtn =
    143          util_dl_get_proc_address(library, "tx_compress_dxtn");
    144 
    145    if (!util_format_dxt1_rgb_fetch ||
    146        !util_format_dxt1_rgba_fetch ||
    147        !util_format_dxt3_rgba_fetch ||
    148        !util_format_dxt5_rgba_fetch ||
    149        !util_format_dxtn_pack) {
    150       debug_printf("couldn't reference all symbols in " DXTN_LIBNAME
    151                    ", software DXTn compression/decompression "
    152                    "unavailable\n");
    153       util_dl_close(library);
    154       return;
    155    }
    156 
    157    util_format_dxt1_rgb_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgb_dxt1;
    158    util_format_dxt1_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt1;
    159    util_format_dxt3_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt3;
    160    util_format_dxt5_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt5;
    161    util_format_dxtn_pack = (util_format_dxtn_pack_t)tx_compress_dxtn;
    162    util_format_s3tc_enabled = TRUE;
    163 }
    164 
    165 
    166 /*
    167  * Pixel fetch.
    168  */
    169 
    170 void
    171 util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    172 {
    173    util_format_dxt1_rgb_fetch(0, src, i, j, dst);
    174 }
    175 
    176 void
    177 util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    178 {
    179    util_format_dxt1_rgba_fetch(0, src, i, j, dst);
    180 }
    181 
    182 void
    183 util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    184 {
    185    util_format_dxt3_rgba_fetch(0, src, i, j, dst);
    186 }
    187 
    188 void
    189 util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    190 {
    191    util_format_dxt5_rgba_fetch(0, src, i, j, dst);
    192 }
    193 
    194 void
    195 util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    196 {
    197    uint8_t tmp[4];
    198    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
    199    dst[0] = ubyte_to_float(tmp[0]);
    200    dst[1] = ubyte_to_float(tmp[1]);
    201    dst[2] = ubyte_to_float(tmp[2]);
    202    dst[3] = 1.0;
    203 }
    204 
    205 void
    206 util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    207 {
    208    uint8_t tmp[4];
    209    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
    210    dst[0] = ubyte_to_float(tmp[0]);
    211    dst[1] = ubyte_to_float(tmp[1]);
    212    dst[2] = ubyte_to_float(tmp[2]);
    213    dst[3] = ubyte_to_float(tmp[3]);
    214 }
    215 
    216 void
    217 util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    218 {
    219    uint8_t tmp[4];
    220    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
    221    dst[0] = ubyte_to_float(tmp[0]);
    222    dst[1] = ubyte_to_float(tmp[1]);
    223    dst[2] = ubyte_to_float(tmp[2]);
    224    dst[3] = ubyte_to_float(tmp[3]);
    225 }
    226 
    227 void
    228 util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    229 {
    230    uint8_t tmp[4];
    231    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
    232    dst[0] = ubyte_to_float(tmp[0]);
    233    dst[1] = ubyte_to_float(tmp[1]);
    234    dst[2] = ubyte_to_float(tmp[2]);
    235    dst[3] = ubyte_to_float(tmp[3]);
    236 }
    237 
    238 
    239 /*
    240  * Block decompression.
    241  */
    242 
    243 static INLINE void
    244 util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    245                                         const uint8_t *src_row, unsigned src_stride,
    246                                         unsigned width, unsigned height,
    247                                         util_format_dxtn_fetch_t fetch,
    248                                         unsigned block_size)
    249 {
    250    const unsigned bw = 4, bh = 4, comps = 4;
    251    unsigned x, y, i, j;
    252    for(y = 0; y < height; y += bh) {
    253       const uint8_t *src = src_row;
    254       for(x = 0; x < width; x += bw) {
    255          for(j = 0; j < bh; ++j) {
    256             for(i = 0; i < bw; ++i) {
    257                uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
    258                fetch(0, src, i, j, dst);
    259             }
    260          }
    261          src += block_size;
    262       }
    263       src_row += src_stride;
    264    }
    265 }
    266 
    267 void
    268 util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    269                                         const uint8_t *src_row, unsigned src_stride,
    270                                         unsigned width, unsigned height)
    271 {
    272    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    273                                            src_row, src_stride,
    274                                            width, height,
    275                                            util_format_dxt1_rgb_fetch, 8);
    276 }
    277 
    278 void
    279 util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    280                                          const uint8_t *src_row, unsigned src_stride,
    281                                          unsigned width, unsigned height)
    282 {
    283    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    284                                            src_row, src_stride,
    285                                            width, height,
    286                                            util_format_dxt1_rgba_fetch, 8);
    287 }
    288 
    289 void
    290 util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    291                                          const uint8_t *src_row, unsigned src_stride,
    292                                          unsigned width, unsigned height)
    293 {
    294    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    295                                            src_row, src_stride,
    296                                            width, height,
    297                                            util_format_dxt3_rgba_fetch, 16);
    298 }
    299 
    300 void
    301 util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    302                                          const uint8_t *src_row, unsigned src_stride,
    303                                          unsigned width, unsigned height)
    304 {
    305    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
    306                                            src_row, src_stride,
    307                                            width, height,
    308                                            util_format_dxt5_rgba_fetch, 16);
    309 }
    310 
    311 static INLINE void
    312 util_format_dxtn_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    313                                        const uint8_t *src_row, unsigned src_stride,
    314                                        unsigned width, unsigned height,
    315                                        util_format_dxtn_fetch_t fetch,
    316                                        unsigned block_size)
    317 {
    318    unsigned x, y, i, j;
    319    for(y = 0; y < height; y += 4) {
    320       const uint8_t *src = src_row;
    321       for(x = 0; x < width; x += 4) {
    322          for(j = 0; j < 4; ++j) {
    323             for(i = 0; i < 4; ++i) {
    324                float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
    325                uint8_t tmp[4];
    326                fetch(0, src, i, j, tmp);
    327                dst[0] = ubyte_to_float(tmp[0]);
    328                dst[1] = ubyte_to_float(tmp[1]);
    329                dst[2] = ubyte_to_float(tmp[2]);
    330                dst[3] = ubyte_to_float(tmp[3]);
    331             }
    332          }
    333          src += block_size;
    334       }
    335       src_row += src_stride;
    336    }
    337 }
    338 
    339 void
    340 util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    341                                        const uint8_t *src_row, unsigned src_stride,
    342                                        unsigned width, unsigned height)
    343 {
    344    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    345                                           src_row, src_stride,
    346                                           width, height,
    347                                           util_format_dxt1_rgb_fetch, 8);
    348 }
    349 
    350 void
    351 util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    352                                         const uint8_t *src_row, unsigned src_stride,
    353                                         unsigned width, unsigned height)
    354 {
    355    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    356                                           src_row, src_stride,
    357                                           width, height,
    358                                           util_format_dxt1_rgba_fetch, 8);
    359 }
    360 
    361 void
    362 util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    363                                         const uint8_t *src_row, unsigned src_stride,
    364                                         unsigned width, unsigned height)
    365 {
    366    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    367                                           src_row, src_stride,
    368                                           width, height,
    369                                           util_format_dxt3_rgba_fetch, 16);
    370 }
    371 
    372 void
    373 util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
    374                                         const uint8_t *src_row, unsigned src_stride,
    375                                         unsigned width, unsigned height)
    376 {
    377    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
    378                                           src_row, src_stride,
    379                                           width, height,
    380                                           util_format_dxt5_rgba_fetch, 16);
    381 }
    382 
    383 
    384 /*
    385  * Block compression.
    386  */
    387 
    388 void
    389 util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    390                                       const uint8_t *src, unsigned src_stride,
    391                                       unsigned width, unsigned height)
    392 {
    393    const unsigned bw = 4, bh = 4, bytes_per_block = 8;
    394    unsigned x, y, i, j, k;
    395    for(y = 0; y < height; y += bh) {
    396       uint8_t *dst = dst_row;
    397       for(x = 0; x < width; x += bw) {
    398          uint8_t tmp[4][4][3];  /* [bh][bw][comps] */
    399          for(j = 0; j < bh; ++j) {
    400             for(i = 0; i < bw; ++i) {
    401                for(k = 0; k < 3; ++k) {
    402                   tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*4 + k];
    403                }
    404             }
    405          }
    406          util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0);
    407          dst += bytes_per_block;
    408       }
    409       dst_row += dst_stride / sizeof(*dst_row);
    410    }
    411 }
    412 
    413 void
    414 util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    415                                        const uint8_t *src, unsigned src_stride,
    416                                        unsigned width, unsigned height)
    417 {
    418    const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 8;
    419    unsigned x, y, i, j, k;
    420    for(y = 0; y < height; y += bh) {
    421       uint8_t *dst = dst_row;
    422       for(x = 0; x < width; x += bw) {
    423          uint8_t tmp[4][4][4];  /* [bh][bw][comps] */
    424          for(j = 0; j < bh; ++j) {
    425             for(i = 0; i < bw; ++i) {
    426                for(k = 0; k < comps; ++k) {
    427                   tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
    428                }
    429             }
    430          }
    431          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0);
    432          dst += bytes_per_block;
    433       }
    434       dst_row += dst_stride / sizeof(*dst_row);
    435    }
    436 }
    437 
    438 void
    439 util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
    440                                        const uint8_t *src, unsigned src_stride,
    441                                        unsigned width, unsigned height)
    442 {
    443    const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16;
    444    unsigned x, y, i, j, k;
    445    for(y = 0; y < height; y += bh) {
    446       uint8_t *dst = dst_row;
    447       for(x = 0; x < width; x += bw) {
    448          uint8_t tmp[4][4][4];  /* [bh][bw][comps] */
    449          for(j = 0; j < bh; ++j) {
    450             for(i = 0; i < bw; ++i) {
    451                for(k = 0; k < comps; ++k) {
    452                   tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
    453                }
    454             }
    455          }
    456          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0);
    457          dst += bytes_per_block;
    458       }
    459       dst_row += dst_stride / sizeof(*dst_row);
    460    }
    461 }
    462 
    463 void
    464 util_format_dxt5_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    const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16;
    469    unsigned x, y, i, j, k;
    470 
    471    for(y = 0; y < height; y += bh) {
    472       uint8_t *dst = dst_row;
    473       for(x = 0; x < width; x += bw) {
    474          uint8_t tmp[4][4][4];  /* [bh][bw][comps] */
    475          for(j = 0; j < bh; ++j) {
    476             for(i = 0; i < bw; ++i) {
    477                for(k = 0; k < comps; ++k) {
    478                   tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
    479                }
    480             }
    481          }
    482          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0);
    483          dst += bytes_per_block;
    484       }
    485       dst_row += dst_stride / sizeof(*dst_row);
    486    }
    487 }
    488 
    489 void
    490 util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    491                                      const float *src, unsigned src_stride,
    492                                      unsigned width, unsigned height)
    493 {
    494    unsigned x, y, i, j, k;
    495    for(y = 0; y < height; y += 4) {
    496       uint8_t *dst = dst_row;
    497       for(x = 0; x < width; x += 4) {
    498          uint8_t tmp[4][4][3];
    499          for(j = 0; j < 4; ++j) {
    500             for(i = 0; i < 4; ++i) {
    501                for(k = 0; k < 3; ++k) {
    502                   tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
    503                }
    504             }
    505          }
    506          util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0);
    507          dst += 8;
    508       }
    509       dst_row += 4*dst_stride/sizeof(*dst_row);
    510    }
    511 }
    512 
    513 void
    514 util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    515                                       const float *src, unsigned src_stride,
    516                                       unsigned width, unsigned height)
    517 {
    518    unsigned x, y, i, j, k;
    519    for(y = 0; y < height; y += 4) {
    520       uint8_t *dst = dst_row;
    521       for(x = 0; x < width; x += 4) {
    522          uint8_t tmp[4][4][4];
    523          for(j = 0; j < 4; ++j) {
    524             for(i = 0; i < 4; ++i) {
    525                for(k = 0; k < 4; ++k) {
    526                   tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
    527                }
    528             }
    529          }
    530          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0);
    531          dst += 8;
    532       }
    533       dst_row += 4*dst_stride/sizeof(*dst_row);
    534    }
    535 }
    536 
    537 void
    538 util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    539                                       const float *src, unsigned src_stride,
    540                                       unsigned width, unsigned height)
    541 {
    542    unsigned x, y, i, j, k;
    543    for(y = 0; y < height; y += 4) {
    544       uint8_t *dst = dst_row;
    545       for(x = 0; x < width; x += 4) {
    546          uint8_t tmp[4][4][4];
    547          for(j = 0; j < 4; ++j) {
    548             for(i = 0; i < 4; ++i) {
    549                for(k = 0; k < 4; ++k) {
    550                   tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
    551                }
    552             }
    553          }
    554          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0);
    555          dst += 16;
    556       }
    557       dst_row += 4*dst_stride/sizeof(*dst_row);
    558    }
    559 }
    560 
    561 void
    562 util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
    563                                       const float *src, unsigned src_stride,
    564                                       unsigned width, unsigned height)
    565 {
    566    unsigned x, y, i, j, k;
    567    for(y = 0; y < height; y += 4) {
    568       uint8_t *dst = dst_row;
    569       for(x = 0; x < width; x += 4) {
    570          uint8_t tmp[4][4][4];
    571          for(j = 0; j < 4; ++j) {
    572             for(i = 0; i < 4; ++i) {
    573                for(k = 0; k < 4; ++k) {
    574                   tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
    575                }
    576             }
    577          }
    578          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0);
    579          dst += 16;
    580       }
    581       dst_row += 4*dst_stride/sizeof(*dst_row);
    582    }
    583 }
    584 
    585 
    586 /*
    587  * SRGB variants.
    588  *
    589  * FIXME: shunts to RGB for now
    590  */
    591 
    592 void
    593 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)
    594 {
    595    util_format_dxt1_rgb_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    596 }
    597 
    598 void
    599 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)
    600 {
    601    util_format_dxt1_rgb_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    602 }
    603 
    604 void
    605 util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    606 {
    607    util_format_dxt1_rgb_fetch_rgba_8unorm(dst, src, i, j);
    608 }
    609 
    610 void
    611 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)
    612 {
    613    util_format_dxt1_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    614 }
    615 
    616 void
    617 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)
    618 {
    619    util_format_dxt1_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    620 }
    621 
    622 void
    623 util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    624 {
    625    util_format_dxt1_rgba_fetch_rgba_8unorm(dst, src, i, j);
    626 }
    627 
    628 void
    629 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)
    630 {
    631    util_format_dxt3_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    632 }
    633 
    634 void
    635 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)
    636 {
    637    util_format_dxt3_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    638 }
    639 
    640 void
    641 util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    642 {
    643    util_format_dxt3_rgba_fetch_rgba_8unorm(dst, src, i, j);
    644 }
    645 
    646 void
    647 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)
    648 {
    649    util_format_dxt5_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    650 }
    651 
    652 void
    653 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)
    654 {
    655    util_format_dxt5_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
    656 }
    657 
    658 void
    659 util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
    660 {
    661    util_format_dxt5_rgba_fetch_rgba_8unorm(dst, src, i, j);
    662 }
    663 
    664 void
    665 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)
    666 {
    667    util_format_dxt1_rgb_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    668 }
    669 
    670 void
    671 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)
    672 {
    673    util_format_dxt1_rgb_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    674 }
    675 
    676 void
    677 util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    678 {
    679    util_format_dxt1_rgb_fetch_rgba_float(dst, src, i, j);
    680 }
    681 
    682 void
    683 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)
    684 {
    685    util_format_dxt1_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    686 }
    687 
    688 void
    689 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)
    690 {
    691    util_format_dxt1_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    692 }
    693 
    694 void
    695 util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    696 {
    697    util_format_dxt1_rgba_fetch_rgba_float(dst, src, i, j);
    698 }
    699 
    700 void
    701 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)
    702 {
    703    util_format_dxt3_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    704 }
    705 
    706 void
    707 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)
    708 {
    709    util_format_dxt3_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    710 }
    711 
    712 void
    713 util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    714 {
    715    util_format_dxt3_rgba_fetch_rgba_float(dst, src, i, j);
    716 }
    717 
    718 void
    719 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)
    720 {
    721    util_format_dxt5_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    722 }
    723 
    724 void
    725 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)
    726 {
    727    util_format_dxt5_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
    728 }
    729 
    730 void
    731 util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
    732 {
    733    util_format_dxt5_rgba_fetch_rgba_float(dst, src, i, j);
    734 }
    735 
    736