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