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
util_format_dxt1_rgb_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt1_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt3_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt5_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxtn_pack_stub(int src_comps,int width,int height,const uint8_t * src,enum util_format_dxtn dst_format,uint8_t * dst,int dst_stride)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
util_format_s3tc_init(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
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgb_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height,util_format_dxtn_fetch_t fetch,unsigned block_size)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
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxtn_rgb_unpack_rgba_float(float * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height,util_format_dxtn_fetch_t fetch,unsigned block_size)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
util_format_dxt1_rgb_unpack_rgba_float(float * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgba_unpack_rgba_float(float * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt3_rgba_unpack_rgba_float(float * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt5_rgba_unpack_rgba_float(float * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgb_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt3_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt5_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
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)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
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)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
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt1_srgb_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt1_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt3_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
util_format_dxt5_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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