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 "util/format/u_format.h"
27 #include "util/format/u_format_s3tc.h"
28 #include "util/format_srgb.h"
29 #include "util/u_math.h"
30 
31 #include "util/format/texcompress_s3tc_tmp.h"
32 
33 util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgb_dxt1;
34 util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt1;
35 util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt3;
36 util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt5;
37 
38 util_format_dxtn_pack_t util_format_dxtn_pack = (util_format_dxtn_pack_t)tx_compress_dxtn;
39 
40 
41 /*
42  * Pixel fetch.
43  */
44 
45 void
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)46 util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
47 {
48    util_format_dxt1_rgb_fetch(0, src, i, j, dst);
49 }
50 
51 void
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)52 util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
53 {
54    util_format_dxt1_rgba_fetch(0, src, i, j, dst);
55 }
56 
57 void
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)58 util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
59 {
60    util_format_dxt3_rgba_fetch(0, src, i, j, dst);
61 }
62 
63 void
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)64 util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
65 {
66    util_format_dxt5_rgba_fetch(0, src, i, j, dst);
67 }
68 
69 void
util_format_dxt1_rgb_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)70 util_format_dxt1_rgb_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
71 {
72    float *dst = in_dst;
73    uint8_t tmp[4];
74    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
75    dst[0] = ubyte_to_float(tmp[0]);
76    dst[1] = ubyte_to_float(tmp[1]);
77    dst[2] = ubyte_to_float(tmp[2]);
78    dst[3] = 1.0;
79 }
80 
81 void
util_format_dxt1_rgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)82 util_format_dxt1_rgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
83 {
84    float *dst = in_dst;
85    uint8_t tmp[4];
86    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
87    dst[0] = ubyte_to_float(tmp[0]);
88    dst[1] = ubyte_to_float(tmp[1]);
89    dst[2] = ubyte_to_float(tmp[2]);
90    dst[3] = ubyte_to_float(tmp[3]);
91 }
92 
93 void
util_format_dxt3_rgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)94 util_format_dxt3_rgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
95 {
96    float *dst = in_dst;
97    uint8_t tmp[4];
98    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
99    dst[0] = ubyte_to_float(tmp[0]);
100    dst[1] = ubyte_to_float(tmp[1]);
101    dst[2] = ubyte_to_float(tmp[2]);
102    dst[3] = ubyte_to_float(tmp[3]);
103 }
104 
105 void
util_format_dxt5_rgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)106 util_format_dxt5_rgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
107 {
108    float *dst = in_dst;
109    uint8_t tmp[4];
110    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
111    dst[0] = ubyte_to_float(tmp[0]);
112    dst[1] = ubyte_to_float(tmp[1]);
113    dst[2] = ubyte_to_float(tmp[2]);
114    dst[3] = ubyte_to_float(tmp[3]);
115 }
116 
117 
118 /*
119  * Block decompression.
120  */
121 
122 static inline void
util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height,util_format_dxtn_fetch_t fetch,unsigned block_size,bool srgb)123 util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
124                                         const uint8_t *restrict src_row, unsigned src_stride,
125                                         unsigned width, unsigned height,
126                                         util_format_dxtn_fetch_t fetch,
127                                         unsigned block_size, bool srgb)
128 {
129    const unsigned bw = 4, bh = 4, comps = 4;
130    unsigned x, y, i, j;
131    for(y = 0; y < height; y += bh) {
132       const uint8_t *src = src_row;
133       const unsigned h = MIN2(height - y, bh);
134       for(x = 0; x < width; x += bw) {
135          const unsigned w = MIN2(width - x, bw);
136          for(j = 0; j < h; ++j) {
137             for(i = 0; i < w; ++i) {
138                uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
139                fetch(0, src, i, j, dst);
140                if (srgb) {
141                   dst[0] = util_format_srgb_to_linear_8unorm(dst[0]);
142                   dst[1] = util_format_srgb_to_linear_8unorm(dst[1]);
143                   dst[2] = util_format_srgb_to_linear_8unorm(dst[2]);
144                }
145             }
146          }
147          src += block_size;
148       }
149       src_row += src_stride;
150    }
151 }
152 
153 void
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)154 util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
155                                         const uint8_t *restrict src_row, unsigned src_stride,
156                                         unsigned width, unsigned height)
157 {
158    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
159                                            src_row, src_stride,
160                                            width, height,
161                                            util_format_dxt1_rgb_fetch,
162                                            8, false);
163 }
164 
165 void
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)166 util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
167                                          const uint8_t *restrict src_row, unsigned src_stride,
168                                          unsigned width, unsigned height)
169 {
170    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
171                                            src_row, src_stride,
172                                            width, height,
173                                            util_format_dxt1_rgba_fetch,
174                                            8, false);
175 }
176 
177 void
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)178 util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
179                                          const uint8_t *restrict src_row, unsigned src_stride,
180                                          unsigned width, unsigned height)
181 {
182    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
183                                            src_row, src_stride,
184                                            width, height,
185                                            util_format_dxt3_rgba_fetch,
186                                            16, false);
187 }
188 
189 void
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)190 util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
191                                          const uint8_t *restrict src_row, unsigned src_stride,
192                                          unsigned width, unsigned height)
193 {
194    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
195                                            src_row, src_stride,
196                                            width, height,
197                                            util_format_dxt5_rgba_fetch,
198                                            16, false);
199 }
200 
201 static inline void
util_format_dxtn_rgb_unpack_rgba_float(float * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height,util_format_dxtn_fetch_t fetch,unsigned block_size,bool srgb)202 util_format_dxtn_rgb_unpack_rgba_float(float *restrict dst_row, unsigned dst_stride,
203                                        const uint8_t *restrict src_row, unsigned src_stride,
204                                        unsigned width, unsigned height,
205                                        util_format_dxtn_fetch_t fetch,
206                                        unsigned block_size, bool srgb)
207 {
208    unsigned x, y, i, j;
209    for(y = 0; y < height; y += 4) {
210       const uint8_t *src = src_row;
211       for(x = 0; x < width; x += 4) {
212          for(j = 0; j < 4; ++j) {
213             for(i = 0; i < 4; ++i) {
214                float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
215                uint8_t tmp[4];
216                fetch(0, src, i, j, tmp);
217                if (srgb) {
218                   dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
219                   dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
220                   dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
221                }
222                else {
223                   dst[0] = ubyte_to_float(tmp[0]);
224                   dst[1] = ubyte_to_float(tmp[1]);
225                   dst[2] = ubyte_to_float(tmp[2]);
226                }
227                dst[3] = ubyte_to_float(tmp[3]);
228             }
229          }
230          src += block_size;
231       }
232       src_row += src_stride;
233    }
234 }
235 
236 void
util_format_dxt1_rgb_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)237 util_format_dxt1_rgb_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride,
238                                        const uint8_t *restrict src_row, unsigned src_stride,
239                                        unsigned width, unsigned height)
240 {
241    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
242                                           src_row, src_stride,
243                                           width, height,
244                                           util_format_dxt1_rgb_fetch,
245                                           8, false);
246 }
247 
248 void
util_format_dxt1_rgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)249 util_format_dxt1_rgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride,
250                                         const uint8_t *restrict src_row, unsigned src_stride,
251                                         unsigned width, unsigned height)
252 {
253    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
254                                           src_row, src_stride,
255                                           width, height,
256                                           util_format_dxt1_rgba_fetch,
257                                           8, false);
258 }
259 
260 void
util_format_dxt3_rgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)261 util_format_dxt3_rgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride,
262                                         const uint8_t *restrict src_row, unsigned src_stride,
263                                         unsigned width, unsigned height)
264 {
265    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
266                                           src_row, src_stride,
267                                           width, height,
268                                           util_format_dxt3_rgba_fetch,
269                                           16, false);
270 }
271 
272 void
util_format_dxt5_rgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)273 util_format_dxt5_rgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride,
274                                         const uint8_t *restrict src_row, unsigned src_stride,
275                                         unsigned width, unsigned height)
276 {
277    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
278                                           src_row, src_stride,
279                                           width, height,
280                                           util_format_dxt5_rgba_fetch,
281                                           16, false);
282 }
283 
284 
285 /*
286  * Block compression.
287  */
288 
289 static inline void
util_format_dxtn_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src,unsigned src_stride,unsigned width,unsigned height,enum util_format_dxtn format,unsigned block_size,bool srgb)290 util_format_dxtn_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
291                                   const uint8_t *restrict src, unsigned src_stride,
292                                   unsigned width, unsigned height,
293                                   enum util_format_dxtn format,
294                                   unsigned block_size, bool srgb)
295 {
296    const unsigned bw = 4, bh = 4, comps = 4;
297    unsigned x, y, i, j, k;
298    for(y = 0; y < height; y += bh) {
299       uint8_t *dst = dst_row;
300       for(x = 0; x < width; x += bw) {
301          uint8_t tmp[4][4][4];  /* [bh][bw][comps] */
302          for(j = 0; j < bh; ++j) {
303             for(i = 0; i < bw; ++i) {
304                uint8_t src_tmp;
305                for(k = 0; k < 3; ++k) {
306                   src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + k];
307                   if (srgb) {
308                      tmp[j][i][k] = util_format_linear_to_srgb_8unorm(src_tmp);
309                   }
310                   else {
311                      tmp[j][i][k] = src_tmp;
312                   }
313                }
314                /* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */
315                tmp[j][i][3] = src[(y + j)*src_stride/sizeof(*src) + (x+i)*comps + 3];
316             }
317          }
318          /* even for dxt1_rgb have 4 src comps */
319          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0);
320          dst += block_size;
321       }
322       dst_row += dst_stride / sizeof(*dst_row);
323    }
324 
325 }
326 
327 void
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src,unsigned src_stride,unsigned width,unsigned height)328 util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
329                                       const uint8_t *restrict src, unsigned src_stride,
330                                       unsigned width, unsigned height)
331 {
332    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
333                                      width, height, UTIL_FORMAT_DXT1_RGB,
334                                      8, false);
335 }
336 
337 void
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src,unsigned src_stride,unsigned width,unsigned height)338 util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
339                                        const uint8_t *restrict src, unsigned src_stride,
340                                        unsigned width, unsigned height)
341 {
342    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
343                                      width, height, UTIL_FORMAT_DXT1_RGBA,
344                                      8, false);
345 }
346 
347 void
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src,unsigned src_stride,unsigned width,unsigned height)348 util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
349                                        const uint8_t *restrict src, unsigned src_stride,
350                                        unsigned width, unsigned height)
351 {
352    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
353                                      width, height, UTIL_FORMAT_DXT3_RGBA,
354                                      16, false);
355 }
356 
357 void
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src,unsigned src_stride,unsigned width,unsigned height)358 util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
359                                        const uint8_t *restrict src, unsigned src_stride,
360                                        unsigned width, unsigned height)
361 {
362    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src, src_stride,
363                                      width, height, UTIL_FORMAT_DXT5_RGBA,
364                                      16, false);
365 }
366 
367 static inline void
util_format_dxtn_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * restrict src,unsigned src_stride,unsigned width,unsigned height,enum util_format_dxtn format,unsigned block_size,bool srgb)368 util_format_dxtn_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
369                                  const float *restrict src, unsigned src_stride,
370                                  unsigned width, unsigned height,
371                                  enum util_format_dxtn format,
372                                  unsigned block_size, bool srgb)
373 {
374    unsigned x, y, i, j, k;
375    for(y = 0; y < height; y += 4) {
376       uint8_t *dst = dst_row;
377       for(x = 0; x < width; x += 4) {
378          uint8_t tmp[4][4][4];
379          for(j = 0; j < 4; ++j) {
380             for(i = 0; i < 4; ++i) {
381                float src_tmp;
382                for(k = 0; k < 3; ++k) {
383                   src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k];
384                   if (srgb) {
385                      tmp[j][i][k] = util_format_linear_float_to_srgb_8unorm(src_tmp);
386                   }
387                   else {
388                      tmp[j][i][k] = float_to_ubyte(src_tmp);
389                   }
390                }
391                /* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */
392                src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + 3];
393                tmp[j][i][3] = float_to_ubyte(src_tmp);
394             }
395          }
396          util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0);
397          dst += block_size;
398       }
399       dst_row += 4*dst_stride/sizeof(*dst_row);
400    }
401 }
402 
403 void
util_format_dxt1_rgb_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)404 util_format_dxt1_rgb_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
405                                      const float *src, unsigned src_stride,
406                                      unsigned width, unsigned height)
407 {
408    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
409                                     width, height, UTIL_FORMAT_DXT1_RGB,
410                                     8, false);
411 }
412 
413 void
util_format_dxt1_rgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)414 util_format_dxt1_rgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
415                                       const float *src, unsigned src_stride,
416                                       unsigned width, unsigned height)
417 {
418    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
419                                     width, height, UTIL_FORMAT_DXT1_RGBA,
420                                     8, false);
421 }
422 
423 void
util_format_dxt3_rgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)424 util_format_dxt3_rgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
425                                       const float *src, unsigned src_stride,
426                                       unsigned width, unsigned height)
427 {
428    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
429                                     width, height, UTIL_FORMAT_DXT3_RGBA,
430                                     16, false);
431 }
432 
433 void
util_format_dxt5_rgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * src,unsigned src_stride,unsigned width,unsigned height)434 util_format_dxt5_rgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
435                                       const float *src, unsigned src_stride,
436                                       unsigned width, unsigned height)
437 {
438    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src, src_stride,
439                                     width, height, UTIL_FORMAT_DXT5_RGBA,
440                                     16, false);
441 }
442 
443 
444 /*
445  * SRGB variants.
446  */
447 
448 void
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)449 util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
450 {
451    uint8_t tmp[4];
452    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
453    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
454    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
455    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
456    dst[3] = 255;
457 }
458 
459 void
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)460 util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
461 {
462    uint8_t tmp[4];
463    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
464    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
465    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
466    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
467    dst[3] = tmp[3];
468 }
469 
470 void
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)471 util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
472 {
473    uint8_t tmp[4];
474    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
475    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
476    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
477    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
478    dst[3] = tmp[3];
479 }
480 
481 void
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t * restrict dst,const uint8_t * restrict src,unsigned i,unsigned j)482 util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *restrict dst, const uint8_t *restrict src, unsigned i, unsigned j)
483 {
484    uint8_t tmp[4];
485    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
486    dst[0] = util_format_srgb_to_linear_8unorm(tmp[0]);
487    dst[1] = util_format_srgb_to_linear_8unorm(tmp[1]);
488    dst[2] = util_format_srgb_to_linear_8unorm(tmp[2]);
489    dst[3] = tmp[3];
490 }
491 
492 void
util_format_dxt1_srgb_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)493 util_format_dxt1_srgb_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
494 {
495    float *dst = in_dst;
496    uint8_t tmp[4];
497    util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
498    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
499    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
500    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
501    dst[3] = 1.0f;
502 }
503 
504 void
util_format_dxt1_srgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)505 util_format_dxt1_srgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
506 {
507    float *dst = in_dst;
508    uint8_t tmp[4];
509    util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
510    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
511    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
512    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
513    dst[3] = ubyte_to_float(tmp[3]);
514 }
515 
516 void
util_format_dxt3_srgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)517 util_format_dxt3_srgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
518 {
519    float *dst = in_dst;
520    uint8_t tmp[4];
521    util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
522    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
523    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
524    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
525    dst[3] = ubyte_to_float(tmp[3]);
526 }
527 
528 void
util_format_dxt5_srgba_fetch_rgba(void * restrict in_dst,const uint8_t * restrict src,unsigned i,unsigned j)529 util_format_dxt5_srgba_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src, unsigned i, unsigned j)
530 {
531    float *dst = in_dst;
532    uint8_t tmp[4];
533    util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
534    dst[0] = util_format_srgb_8unorm_to_linear_float(tmp[0]);
535    dst[1] = util_format_srgb_8unorm_to_linear_float(tmp[1]);
536    dst[2] = util_format_srgb_8unorm_to_linear_float(tmp[2]);
537    dst[3] = ubyte_to_float(tmp[3]);
538 }
539 
540 void
util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)541 util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
542 {
543    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
544                                            src_row, src_stride,
545                                            width, height,
546                                            util_format_dxt1_rgb_fetch,
547                                            8, true);
548 }
549 
550 void
util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)551 util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
552 {
553    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
554                                            src_row, src_stride,
555                                            width, height,
556                                            util_format_dxt1_rgba_fetch,
557                                            8, true);
558 }
559 
560 void
util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)561 util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
562 {
563    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
564                                            src_row, src_stride,
565                                            width, height,
566                                            util_format_dxt3_rgba_fetch,
567                                            16, true);
568 }
569 
570 void
util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)571 util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
572 {
573    util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
574                                            src_row, src_stride,
575                                            width, height,
576                                            util_format_dxt5_rgba_fetch,
577                                            16, true);
578 }
579 
580 void
util_format_dxt1_srgb_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)581 util_format_dxt1_srgb_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
582 {
583    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
584                                           src_row, src_stride,
585                                           width, height,
586                                           util_format_dxt1_rgb_fetch,
587                                           8, true);
588 }
589 
590 void
util_format_dxt1_srgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)591 util_format_dxt1_srgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
592 {
593    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
594                                           src_row, src_stride,
595                                           width, height,
596                                           util_format_dxt1_rgba_fetch,
597                                           8, true);
598 }
599 
600 void
util_format_dxt3_srgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)601 util_format_dxt3_srgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
602 {
603    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
604                                           src_row, src_stride,
605                                           width, height,
606                                           util_format_dxt3_rgba_fetch,
607                                           16, true);
608 }
609 
610 void
util_format_dxt5_srgba_unpack_rgba_float(void * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)611 util_format_dxt5_srgba_unpack_rgba_float(void *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
612 {
613    util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
614                                           src_row, src_stride,
615                                           width, height,
616                                           util_format_dxt5_rgba_fetch,
617                                           16, true);
618 }
619 
620 void
util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)621 util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
622 {
623    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
624                                      width, height, UTIL_FORMAT_DXT1_RGB,
625                                      8, true);
626 }
627 
628 void
util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)629 util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
630 {
631    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
632                                      width, height, UTIL_FORMAT_DXT1_RGBA,
633                                      8, true);
634 }
635 
636 void
util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)637 util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
638 {
639    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
640                                      width, height, UTIL_FORMAT_DXT3_RGBA,
641                                      16, true);
642 }
643 
644 void
util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t * restrict dst_row,unsigned dst_stride,const uint8_t * restrict src_row,unsigned src_stride,unsigned width,unsigned height)645 util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride, const uint8_t *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
646 {
647    util_format_dxtn_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride,
648                                      width, height, UTIL_FORMAT_DXT5_RGBA,
649                                      16, true);
650 }
651 
652 void
util_format_dxt1_srgb_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * restrict src_row,unsigned src_stride,unsigned width,unsigned height)653 util_format_dxt1_srgb_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride, const float *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
654 {
655    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
656                                     width, height, UTIL_FORMAT_DXT1_RGB,
657                                     8, true);
658 }
659 
660 void
util_format_dxt1_srgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * restrict src_row,unsigned src_stride,unsigned width,unsigned height)661 util_format_dxt1_srgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride, const float *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
662 {
663    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
664                                     width, height, UTIL_FORMAT_DXT1_RGBA,
665                                     8, true);
666 }
667 
668 void
util_format_dxt3_srgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * restrict src_row,unsigned src_stride,unsigned width,unsigned height)669 util_format_dxt3_srgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride, const float *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
670 {
671    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
672                                     width, height, UTIL_FORMAT_DXT3_RGBA,
673                                     16, true);
674 }
675 
676 void
util_format_dxt5_srgba_pack_rgba_float(uint8_t * restrict dst_row,unsigned dst_stride,const float * restrict src_row,unsigned src_stride,unsigned width,unsigned height)677 util_format_dxt5_srgba_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride, const float *restrict src_row, unsigned src_stride, unsigned width, unsigned height)
678 {
679    util_format_dxtn_pack_rgba_float(dst_row, dst_stride, src_row, src_stride,
680                                     width, height, UTIL_FORMAT_DXT5_RGBA,
681                                     16, true);
682 }
683 
684