• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
util_format_dxt1_rgb_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt1_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt3_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
util_format_dxt5_rgba_fetch_stub(int src_stride,const uint8_t * src,int col,int row,uint8_t * dst)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
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)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
util_format_s3tc_init(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
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgb_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_rgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
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,boolean srgb)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
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)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
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)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
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)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
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)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
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,boolean srgb)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
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)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
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)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
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)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
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)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
util_format_dxtn_pack_rgba_8unorm(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src,unsigned src_stride,unsigned width,unsigned height,enum util_format_dxtn format,unsigned block_size,boolean srgb)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
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)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
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)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
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)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
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)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
util_format_dxtn_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height,enum util_format_dxtn format,unsigned block_size,boolean srgb)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
util_format_dxt1_rgb_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt3_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt5_rgba_pack_rgba_float(uint8_t * dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)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
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_srgb_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt1_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt3_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
util_format_dxt5_srgba_fetch_rgba_float(float * dst,const uint8_t * src,unsigned i,unsigned j)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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
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)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