mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
841 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68c88f692e | ||
|
|
df19b37d6d | ||
|
|
1b5c352566 | ||
|
|
bed6a9e4d4 | ||
|
|
d602ad1d3e | ||
|
|
51c31347df | ||
|
|
00876e7076 | ||
|
|
47eb499893 | ||
|
|
b8680c3139 | ||
|
|
9b4e3b8f74 | ||
|
|
3e858167bc | ||
|
|
44d66555cc | ||
|
|
c5438ceca3 | ||
|
|
3e1927ae44 | ||
|
|
b688117002 | ||
|
|
e62e6fb6c3 | ||
|
|
262e94e5d7 | ||
|
|
11a4b4e7ff | ||
|
|
a98cfcf28c | ||
|
|
d02f30ee62 | ||
|
|
c0bf01a646 | ||
|
|
babb985e9e | ||
|
|
e379c8317d | ||
|
|
5098277474 | ||
|
|
4a94cb6cbd | ||
|
|
e245454b91 | ||
|
|
b003eadd2d | ||
|
|
a5984d8213 | ||
|
|
4dbd95b0bb | ||
|
|
68803229da | ||
|
|
b661a2a149 | ||
|
|
63cd355d7a | ||
|
|
0f5ff68679 | ||
|
|
bd74921926 | ||
|
|
78f83514f4 | ||
|
|
2c36259b88 | ||
|
|
32a0bed6af | ||
|
|
d415f8364c | ||
|
|
7c768b6833 | ||
|
|
773f6968a4 | ||
|
|
1021199512 | ||
|
|
08ef9e2bd9 | ||
|
|
6ba3f96f27 | ||
|
|
7d5b7bc3ce | ||
|
|
0d43d30346 | ||
|
|
da824b4e9e | ||
|
|
ed08b5f34e | ||
|
|
0ce312c1c3 | ||
|
|
07bc2fa452 | ||
|
|
bfd2775074 | ||
|
|
94ccafd745 | ||
|
|
5c6049c4ae | ||
|
|
090464c42d | ||
|
|
89a00db3d6 | ||
|
|
fc415dff93 | ||
|
|
f648a9a438 | ||
|
|
cac6669423 | ||
|
|
7db487a49b | ||
|
|
c96607fe37 | ||
|
|
ba0dae5f57 | ||
|
|
5fe5148e86 | ||
|
|
5445cb516a | ||
|
|
84a29ffcca | ||
|
|
e56075976f | ||
|
|
0f709735c0 | ||
|
|
ad3f0fd6cd | ||
|
|
fbfdacd589 | ||
|
|
aedc51e151 | ||
|
|
fe95a697f4 | ||
|
|
f99cf28429 | ||
|
|
bea1eb0cf9 | ||
|
|
3cf21e0ab6 | ||
|
|
521b32c253 | ||
|
|
190b525ca6 | ||
|
|
baa00e4d38 | ||
|
|
51bc6c1465 | ||
|
|
ea8492082a | ||
|
|
9d1fd23d78 | ||
|
|
9ff575377d | ||
|
|
47250293cd | ||
|
|
f9b346521d | ||
|
|
b5a4c71eff | ||
|
|
2604256424 | ||
|
|
906ac6a8ea | ||
|
|
3db21e0579 | ||
|
|
abd03884de | ||
|
|
a159256b07 | ||
|
|
d9a2618b7a | ||
|
|
dca0291cfb | ||
|
|
b261873471 | ||
|
|
bfd01c913a | ||
|
|
818b3fe779 | ||
|
|
66a28e4488 | ||
|
|
28e2ecf920 | ||
|
|
d3dbf53fa7 | ||
|
|
8fb2940f25 | ||
|
|
55498762f9 | ||
|
|
50baaf39d6 | ||
|
|
4743ccac8c | ||
|
|
0dc3fc6228 | ||
|
|
a7a4583c84 | ||
|
|
6b52937262 | ||
|
|
df9caf6fb8 | ||
|
|
be5f8d2e60 | ||
|
|
b0e01ca518 | ||
|
|
4e85272393 | ||
|
|
bffed9a839 | ||
|
|
7ed0c0d031 | ||
|
|
ae6e4c98f6 | ||
|
|
38cfa9912d | ||
|
|
b02318e2b6 | ||
|
|
db45263221 | ||
|
|
3fd9625f1c | ||
|
|
2978b6050d | ||
|
|
274acddcf1 | ||
|
|
8dffc85707 | ||
|
|
f799631a70 | ||
|
|
d744f0dfeb | ||
|
|
bdb8de6d3b | ||
|
|
e751f367ca | ||
|
|
13f2d87ba8 | ||
|
|
3cac2cf7c2 | ||
|
|
a67409bfc6 | ||
|
|
6a556c9968 | ||
|
|
4d93285ca2 | ||
|
|
98c35a308d | ||
|
|
7da97e6d80 | ||
|
|
edf686752a | ||
|
|
b7e17646a3 | ||
|
|
3f437e7496 | ||
|
|
7ab6c62dee | ||
|
|
2a7bf35f20 | ||
|
|
08552a83cc | ||
|
|
ee417ee4c5 | ||
|
|
869837f5f0 | ||
|
|
7ab6bac39a | ||
|
|
e388294004 | ||
|
|
bba5ef67ff | ||
|
|
83dc2de6ca | ||
|
|
f47fbda0e6 | ||
|
|
d34d2af849 | ||
|
|
db92af8ca4 | ||
|
|
47897fc2be | ||
|
|
b451602f69 | ||
|
|
96ac35a4bd | ||
|
|
ddd33a0701 | ||
|
|
d5e4a1c896 | ||
|
|
9674fd773c | ||
|
|
01e916b132 | ||
|
|
1867791653 | ||
|
|
bc11ff0571 | ||
|
|
e550cf9b63 | ||
|
|
bafd87694c | ||
|
|
caf6298ad1 | ||
|
|
7f0d287512 | ||
|
|
2177de2238 | ||
|
|
32973c746e | ||
|
|
3bf94330ef | ||
|
|
34ae3b1eb0 | ||
|
|
b9288d4845 | ||
|
|
a13cb32eb1 | ||
|
|
9d72ad785d | ||
|
|
0afde446c4 | ||
|
|
49111a6fbe | ||
|
|
251140fd52 | ||
|
|
f57c7d216c | ||
|
|
36157402c8 | ||
|
|
51ee8f4015 | ||
|
|
fb85bb9076 | ||
|
|
0a391e2407 | ||
|
|
52f03c900f | ||
|
|
74be344ce6 | ||
|
|
14574ef4eb | ||
|
|
fe565afff0 | ||
|
|
5fcd0f94c2 | ||
|
|
e22609ea29 | ||
|
|
1d068ffde9 | ||
|
|
fe133b3c0c | ||
|
|
eb42ce3343 | ||
|
|
c50c24e3c9 | ||
|
|
ab85d759b0 | ||
|
|
2ef2adf517 | ||
|
|
c13e23ab68 | ||
|
|
ec57e9c178 | ||
|
|
b5a2fe3223 | ||
|
|
88d378d293 | ||
|
|
c79e6ecc2c | ||
|
|
a46ee17537 | ||
|
|
b6dbffa251 | ||
|
|
4af1f7846d | ||
|
|
f5e706f753 | ||
|
|
2dcf602666 | ||
|
|
42be070727 | ||
|
|
98ded09177 | ||
|
|
24cb93d7c5 | ||
|
|
535ebdbc8c | ||
|
|
42a6076967 | ||
|
|
fb27549bed | ||
|
|
6720c9ef83 | ||
|
|
b7c135586e | ||
|
|
f47b55ce42 | ||
|
|
a635796b12 | ||
|
|
fbbd11bc18 | ||
|
|
4134dd015d | ||
|
|
b0dedcc590 | ||
|
|
f5ce81d72c | ||
|
|
9810d2923c | ||
|
|
92ede270ce | ||
|
|
427096dc29 | ||
|
|
a7f948c00f | ||
|
|
4afa5b8409 | ||
|
|
7f285b2164 | ||
|
|
9dac7825d7 | ||
|
|
305d0e81d6 | ||
|
|
56f3d6ea09 | ||
|
|
edc04fb8e3 | ||
|
|
a72f78fd79 | ||
|
|
aadd0fd65e | ||
|
|
e2bc80a96f | ||
|
|
704e531c1f | ||
|
|
203981182d | ||
|
|
14b67e3ac3 | ||
|
|
f83e11892b | ||
|
|
a8c549baee | ||
|
|
13142dd31d | ||
|
|
ed5c364603 | ||
|
|
0ccf7d2e10 | ||
|
|
ebb0dc7cc5 | ||
|
|
52ebebc739 | ||
|
|
c8141261f2 | ||
|
|
9c7750b85d | ||
|
|
bf10b55aa1 | ||
|
|
43d9ea99b0 | ||
|
|
37f28e95b6 | ||
|
|
1870193615 | ||
|
|
189374d19c | ||
|
|
ac04695edd | ||
|
|
93bf9db0b4 | ||
|
|
9219a1a38b | ||
|
|
1a28d6f0d1 | ||
|
|
aca1b4478e | ||
|
|
9a794f7aaa | ||
|
|
6e65558d42 | ||
|
|
74936f49e0 | ||
|
|
9864cd97de | ||
|
|
6d7deb57a0 | ||
|
|
21876ff590 | ||
|
|
c543c05968 | ||
|
|
a5537da4df | ||
|
|
edaddeecc4 | ||
|
|
6b30a199da | ||
|
|
23c637e3e5 | ||
|
|
313b0fe3b5 | ||
|
|
90818c3627 | ||
|
|
89877aba58 | ||
|
|
80cb381b35 | ||
|
|
73a4d258a9 | ||
|
|
26fcbc712e | ||
|
|
7e4bc6ba22 | ||
|
|
a975a472b8 | ||
|
|
29a1304218 | ||
|
|
af5279cf56 | ||
|
|
4a59a80f1d | ||
|
|
501088b859 | ||
|
|
aa0bd38134 | ||
|
|
35d3bf2f2d | ||
|
|
09d0ff2577 | ||
|
|
567b0173ec | ||
|
|
20411aa8d6 | ||
|
|
be94aa97db | ||
|
|
f65c1dd5bc | ||
|
|
a92297ceec | ||
|
|
a8ea4e55ef | ||
|
|
3195befab1 | ||
|
|
2cdc65c06b | ||
|
|
0529715640 | ||
|
|
2534cb2c9d | ||
|
|
49f4c36b0e | ||
|
|
4b08672f99 | ||
|
|
73f7cb1fa7 | ||
|
|
8f64d118c8 | ||
|
|
e31625d2bd | ||
|
|
7907ead7fc | ||
|
|
276193d876 | ||
|
|
9c61053fe0 | ||
|
|
8779bf44d8 | ||
|
|
5ea4c55a6a | ||
|
|
4662d0e5dc | ||
|
|
cc5f594384 | ||
|
|
d9ff9d7aa1 | ||
|
|
08b9037781 | ||
|
|
59125c9b12 | ||
|
|
e5ba376985 | ||
|
|
165595008e | ||
|
|
8dc905e827 | ||
|
|
7cc8e5887f | ||
|
|
3599438e57 | ||
|
|
88515d58ab | ||
|
|
338e1a71a9 | ||
|
|
d9fc763f82 | ||
|
|
7eeb6c7aca | ||
|
|
a045c917e7 | ||
|
|
a052a43b84 | ||
|
|
94d87a35be | ||
|
|
0c8c798051 | ||
|
|
c9ddab444a | ||
|
|
1222270e44 | ||
|
|
86b5de8785 | ||
|
|
e97f03ed8b | ||
|
|
0a76c5a64d | ||
|
|
01a1b017e8 | ||
|
|
ddefb8a393 | ||
|
|
62a5cd98da | ||
|
|
8ad9d7d047 | ||
|
|
10ed797881 | ||
|
|
23918e25c2 | ||
|
|
de022ab68d | ||
|
|
5561884126 | ||
|
|
406d7468dd | ||
|
|
41124994fa | ||
|
|
c4e048eedf | ||
|
|
eff9b4167c | ||
|
|
47931a0689 | ||
|
|
34ca40fa2a | ||
|
|
821f732ff9 | ||
|
|
54c8ef7ee6 | ||
|
|
dc9e531cb1 | ||
|
|
2bd151e6f2 | ||
|
|
ae084643c4 | ||
|
|
bd1b91b862 | ||
|
|
f221c85e17 | ||
|
|
e2fe93e403 | ||
|
|
f98e23f061 | ||
|
|
18f6518d41 | ||
|
|
74598b3055 | ||
|
|
6159cd4114 | ||
|
|
3c70d7f575 | ||
|
|
bd70f1ca4a | ||
|
|
0e67507d3a | ||
|
|
beab573758 | ||
|
|
e46890fd76 | ||
|
|
3888638f8c | ||
|
|
44778c374f | ||
|
|
207d4df5e7 | ||
|
|
d454a7dafc | ||
|
|
53b4ddc4cb | ||
|
|
23c8780bff | ||
|
|
958ab4048c | ||
|
|
657d20d36e | ||
|
|
fde045241f | ||
|
|
b3be566426 | ||
|
|
1eebb550a8 | ||
|
|
fbe5f88417 | ||
|
|
d9609b9f51 | ||
|
|
815d7b2967 | ||
|
|
98ce7c81c8 | ||
|
|
e4d8f3d901 | ||
|
|
ca5dfdd25c | ||
|
|
11634c6567 | ||
|
|
f6a313f1a5 | ||
|
|
1a46898cde | ||
|
|
63ee30cbb3 | ||
|
|
20241f301b | ||
|
|
61c653c49c | ||
|
|
a7f4f992e1 | ||
|
|
daa9953d40 | ||
|
|
4771198c30 | ||
|
|
d8f3717119 | ||
|
|
33ab6fd09b | ||
|
|
1391e1339e | ||
|
|
2f2614737a | ||
|
|
85a62427f9 | ||
|
|
8fd91cb7df | ||
|
|
c5820a4f54 | ||
|
|
572eae596c | ||
|
|
6f3c189129 | ||
|
|
7a0017bd40 | ||
|
|
74f840f66b | ||
|
|
4a7c194157 | ||
|
|
116eb6dc5b | ||
|
|
0bab3c74ea | ||
|
|
6328de43e3 | ||
|
|
5becdc9ab5 | ||
|
|
26b6394b67 | ||
|
|
1b6086ab62 | ||
|
|
87a4536a2e | ||
|
|
d20b897ac8 | ||
|
|
6f26b064b9 | ||
|
|
3a2c78d17c | ||
|
|
19d375b4bd | ||
|
|
8162461618 | ||
|
|
0cadc3189c | ||
|
|
e971a9ebf5 | ||
|
|
19f85713ce | ||
|
|
4c41de6013 | ||
|
|
96f9cde1bc | ||
|
|
3feef0824c | ||
|
|
5f2ab55c93 | ||
|
|
0f75bfe17d | ||
|
|
7faa132622 | ||
|
|
b69e6da105 | ||
|
|
11edb128e9 | ||
|
|
fc4407aaef | ||
|
|
2a418e3282 | ||
|
|
59415542ff | ||
|
|
00416e26bb | ||
|
|
e936398e17 | ||
|
|
e3b45c3efd | ||
|
|
7ad759007a | ||
|
|
2fab554360 | ||
|
|
e98b6e6cb3 | ||
|
|
aa5147a52b | ||
|
|
83ebbe95c5 | ||
|
|
2ad71d046b | ||
|
|
099e1f900d | ||
|
|
0c6537e917 | ||
|
|
8937fb3d11 | ||
|
|
028085f8f9 | ||
|
|
b33932f47b | ||
|
|
d122939183 | ||
|
|
b09eb4e42d | ||
|
|
e75ddb878a | ||
|
|
6e3dca5a1a | ||
|
|
b069f51e6f | ||
|
|
bb1e6d06e4 | ||
|
|
f747abcc3b | ||
|
|
77738f72b4 | ||
|
|
61f11d12ff | ||
|
|
7e00b2c9a9 | ||
|
|
7dd4ab947b | ||
|
|
be213695a0 | ||
|
|
cde548a2f9 | ||
|
|
e76481f454 | ||
|
|
1a8d1d443e | ||
|
|
a14c8eb7d5 | ||
|
|
97ea52a6c1 | ||
|
|
0617182dfc | ||
|
|
bd99d76416 | ||
|
|
fdbe9305a9 | ||
|
|
fd772e42da | ||
|
|
df56797b38 | ||
|
|
28e72110bb | ||
|
|
e451c5f70c | ||
|
|
20b8fef950 | ||
|
|
47449a424d | ||
|
|
e8ab761be4 | ||
|
|
6463fc541b | ||
|
|
08b3194b96 | ||
|
|
62fa768e60 | ||
|
|
cafe7a9dc2 | ||
|
|
7ffc671c3a | ||
|
|
eaeea83547 | ||
|
|
76b758dbd2 | ||
|
|
ab19b109ce | ||
|
|
73c3216ca6 | ||
|
|
ee56c5b13c | ||
|
|
46768c8624 | ||
|
|
24340caa35 | ||
|
|
6dc92b00a6 | ||
|
|
43a81a3cb1 | ||
|
|
0df388cd96 | ||
|
|
c342f9cac5 | ||
|
|
21042934e3 | ||
|
|
888e024d0c | ||
|
|
fe9794ba53 | ||
|
|
e546acec1e | ||
|
|
272ad1d37f | ||
|
|
a87e661745 | ||
|
|
f750eb56ab | ||
|
|
118b604a66 | ||
|
|
cfd9343230 | ||
|
|
8bcc2c94b9 | ||
|
|
377930d004 | ||
|
|
a9526b7cc1 | ||
|
|
ff01a6359b | ||
|
|
6c3ea29157 | ||
|
|
36be1a8f7d | ||
|
|
691c3764ac | ||
|
|
aa0292ada1 | ||
|
|
e4429527e3 | ||
|
|
f06285e3a4 | ||
|
|
6d47cefefd | ||
|
|
fe71fc6a30 | ||
|
|
0e649bc70b | ||
|
|
e0915d8372 | ||
|
|
3f4d9cda85 | ||
|
|
4e25988961 | ||
|
|
b1502c754a | ||
|
|
303cef78ed | ||
|
|
a72f282156 | ||
|
|
32e77a2bd3 | ||
|
|
a53fdfae82 | ||
|
|
806ab5ad01 | ||
|
|
f5ddc0d7c6 | ||
|
|
a6eb5d32d8 | ||
|
|
b03c982706 | ||
|
|
7835ebd14f | ||
|
|
fd67049cf9 | ||
|
|
c2f05371e4 | ||
|
|
5c9c071086 | ||
|
|
f7677105ed | ||
|
|
9e2a73c7a7 | ||
|
|
c9f5f03d02 | ||
|
|
c313736334 | ||
|
|
1eb9a60b4a | ||
|
|
e50fe50daf | ||
|
|
643c83c2a0 | ||
|
|
44733d7655 | ||
|
|
fcdd43fc78 | ||
|
|
78643623c3 | ||
|
|
b27846ce39 | ||
|
|
b87b8eb7bb | ||
|
|
709dfdd3f2 | ||
|
|
faef28d5c4 | ||
|
|
309dd4f847 | ||
|
|
506897fab2 | ||
|
|
4e0aff053c | ||
|
|
2ba6fbbcc2 | ||
|
|
e987eac545 | ||
|
|
6b9781fee6 | ||
|
|
181ceb38cc | ||
|
|
595ce0ea19 | ||
|
|
b624330155 | ||
|
|
380c316869 | ||
|
|
31dacc2d21 | ||
|
|
b557a82009 | ||
|
|
e4af1c4244 | ||
|
|
7c26ac5578 | ||
|
|
2948d50b0d | ||
|
|
48fefddcb2 | ||
|
|
f4d8af2f0d | ||
|
|
afa3108623 | ||
|
|
6fcfddf19a | ||
|
|
6d2f442cbd | ||
|
|
e8260e7191 | ||
|
|
48a4367a2c | ||
|
|
edd3540f34 | ||
|
|
111c32c5ed | ||
|
|
af22ca3ae0 | ||
|
|
5e2caa326c | ||
|
|
50f9f60341 | ||
|
|
65f61b143a | ||
|
|
10f4892b7e | ||
|
|
f71d518f75 | ||
|
|
c5b11fe484 | ||
|
|
068fd04f15 | ||
|
|
a461750b55 | ||
|
|
291df6a0e4 | ||
|
|
8afeb4ea61 | ||
|
|
b30f246900 | ||
|
|
7fd042b197 | ||
|
|
b6b3e364f2 | ||
|
|
70e5f18971 | ||
|
|
1fb35593d5 | ||
|
|
b1b9c32644 | ||
|
|
8eeed7d42c | ||
|
|
584493d945 | ||
|
|
da8e551e77 | ||
|
|
a717930d5a | ||
|
|
abc000f614 | ||
|
|
cd51f1def3 | ||
|
|
f5573cf0ab | ||
|
|
1d036a4897 | ||
|
|
f9eced6244 | ||
|
|
90a7253c66 | ||
|
|
31e065f83a | ||
|
|
571f443339 | ||
|
|
4a4157919c | ||
|
|
e73aa0e81b | ||
|
|
2343246315 | ||
|
|
e5f41ce175 | ||
|
|
8184f2eaa9 | ||
|
|
e0bb465945 | ||
|
|
55749a63eb | ||
|
|
aa1b8db3ea | ||
|
|
023713fd67 | ||
|
|
35093c3e37 | ||
|
|
4e5dac3e25 | ||
|
|
c52e84ac41 | ||
|
|
7f8488771d | ||
|
|
57ff271f4b | ||
|
|
43703755f8 | ||
|
|
17b6cc00ab | ||
|
|
a03563b366 | ||
|
|
ff9da17498 | ||
|
|
722bc94270 | ||
|
|
d51a5db5b1 | ||
|
|
04541ae2ab | ||
|
|
c58a67815b | ||
|
|
085f964cd9 | ||
|
|
a8b6e448eb | ||
|
|
78ab8381d9 | ||
|
|
49a5d82086 | ||
|
|
4ed129ccac | ||
|
|
ed09dca17e | ||
|
|
e64fbb2f0e | ||
|
|
e37f8a6521 | ||
|
|
b54bcc0e20 | ||
|
|
db37d51bb1 | ||
|
|
197b9fc560 | ||
|
|
fd30b00205 | ||
|
|
f182379d24 | ||
|
|
32ba08980d | ||
|
|
1e1f08abb9 | ||
|
|
cbe20c0eed | ||
|
|
ec288ffa62 | ||
|
|
7e18c02c7e | ||
|
|
4a505cc239 | ||
|
|
35c81106c6 | ||
|
|
1094222d3f | ||
|
|
065d0db4c9 | ||
|
|
bc51537080 | ||
|
|
b7dfcb282b | ||
|
|
78a9411766 | ||
|
|
4724f67596 | ||
|
|
e0851bb86f | ||
|
|
08e68d9563 | ||
|
|
0b6dccae51 | ||
|
|
60adfd5046 | ||
|
|
3e782d355d | ||
|
|
22a7324b69 | ||
|
|
f3b4c50909 | ||
|
|
a45f27e6e9 | ||
|
|
2f84bf0cca | ||
|
|
3e2c3e5075 | ||
|
|
154259d0a6 | ||
|
|
7d2d05ff59 | ||
|
|
f7c587c9a8 | ||
|
|
9162b30b18 | ||
|
|
14cfe37c8b | ||
|
|
a27a0ab49d | ||
|
|
0742fe07ec | ||
|
|
65a92470d3 | ||
|
|
10dc1a2da2 | ||
|
|
aad2128c32 | ||
|
|
2640678cac | ||
|
|
8b90e2d53d | ||
|
|
f87175dc7f | ||
|
|
b30444c0d0 | ||
|
|
c1da0caf15 | ||
|
|
c4a8fc5b71 | ||
|
|
8eb46b5a4c | ||
|
|
8be16d1039 | ||
|
|
76e6208d1b | ||
|
|
bc09080ba5 | ||
|
|
a6eb257a3a | ||
|
|
e62450d255 | ||
|
|
1aa922f700 | ||
|
|
4c9d2f99b1 | ||
|
|
f6e899b570 | ||
|
|
695c39fba2 | ||
|
|
e5616cff98 | ||
|
|
76d5994c1e | ||
|
|
cbb40832a1 | ||
|
|
e4bdcde1ca | ||
|
|
863e119ff4 | ||
|
|
2ccf6dc872 | ||
|
|
24ebf1b4f1 | ||
|
|
ed2832434c | ||
|
|
5e160fca8f | ||
|
|
a0ef82e221 | ||
|
|
3e7ac3d66c | ||
|
|
730e6fa737 | ||
|
|
cdfcd9fddd | ||
|
|
b6930c10b9 | ||
|
|
852734580d | ||
|
|
d1dc6a9c1d | ||
|
|
4fa6d3ed3f | ||
|
|
92e190ad6c | ||
|
|
da4fcffef4 | ||
|
|
1a5731dd8e | ||
|
|
e764c5cd4e | ||
|
|
e23b247947 | ||
|
|
3d7792436f | ||
|
|
d8187fbea4 | ||
|
|
02259ad0a5 | ||
|
|
220a68df9a | ||
|
|
2ced24f69e | ||
|
|
ec91d0dc74 | ||
|
|
46874f4673 | ||
|
|
9eac47dc6c | ||
|
|
9e3fd5c2e0 | ||
|
|
ae4be6e2b1 | ||
|
|
434df49a7d | ||
|
|
c939c0fcd5 | ||
|
|
952c39f324 | ||
|
|
0fea7e2a70 | ||
|
|
c1baab68d0 | ||
|
|
ccef18f7a9 | ||
|
|
8cb056bde3 | ||
|
|
6ecaaee9e0 | ||
|
|
c5f916bda0 | ||
|
|
52a9a4649c | ||
|
|
d2219b4dbd | ||
|
|
155f603245 | ||
|
|
cb7630a6ab | ||
|
|
284fba1ce3 | ||
|
|
aa4bd6c88c | ||
|
|
623993930b | ||
|
|
dbf2c854c6 | ||
|
|
25351bc05c | ||
|
|
27cc5f499c | ||
|
|
b7c2f39a17 | ||
|
|
3541c1ccf8 | ||
|
|
7a05738d11 | ||
|
|
686220ae0c | ||
|
|
cf380d36b9 | ||
|
|
50bc0193ac | ||
|
|
2162a72831 | ||
|
|
313666f85b | ||
|
|
e9d79263b4 | ||
|
|
4ede6d65fd | ||
|
|
14d2eee371 | ||
|
|
717f370be0 | ||
|
|
d05e4b9727 | ||
|
|
697c53b4d8 | ||
|
|
d9b58ec3ce | ||
|
|
6c8b37d7ca | ||
|
|
39f43e766d | ||
|
|
5379a13944 | ||
|
|
cd0c1607ef | ||
|
|
26a4f71385 | ||
|
|
06b3e6ad71 | ||
|
|
79d22a8d77 | ||
|
|
9914212600 | ||
|
|
765f55e67b | ||
|
|
2d922cc035 | ||
|
|
42e0625ab3 | ||
|
|
c72e894fc7 | ||
|
|
5bc2342d47 | ||
|
|
ea2b0b5e59 | ||
|
|
d70cc0221a | ||
|
|
b12587b44e | ||
|
|
c4708bdc35 | ||
|
|
1fa2c0bf50 | ||
|
|
b4c70d357a | ||
|
|
f18262ee96 | ||
|
|
c1f1761482 | ||
|
|
067c3eea16 | ||
|
|
6957cc7001 | ||
|
|
7dea23eea8 | ||
|
|
319ec1f774 | ||
|
|
2079532e83 | ||
|
|
de1d646fe9 | ||
|
|
4bc3ab6285 | ||
|
|
1adc9cbb49 | ||
|
|
7cdf5eefc9 | ||
|
|
c7ee72647d | ||
|
|
5434af348e | ||
|
|
169cea0f01 | ||
|
|
a8f3ec8184 | ||
|
|
7796b2a12b | ||
|
|
d9cffd58ba | ||
|
|
e566386240 | ||
|
|
45af1e172f | ||
|
|
768b2e52a6 | ||
|
|
7abd2009b0 | ||
|
|
46f075e891 | ||
|
|
832c381ac4 | ||
|
|
e021282264 | ||
|
|
2a60d385c6 | ||
|
|
4d37e35675 | ||
|
|
df3868a280 | ||
|
|
0799bb8cf1 | ||
|
|
69048dede4 | ||
|
|
76df6d1f43 | ||
|
|
2d03b21f2b | ||
|
|
62cbd44933 | ||
|
|
44c8f6d8b0 | ||
|
|
f3fc1dd59c | ||
|
|
708931e48b | ||
|
|
81800d2883 | ||
|
|
d0411d7ddf | ||
|
|
70e232cab3 | ||
|
|
f90396bda4 | ||
|
|
ae8808b86e | ||
|
|
8d5b827432 | ||
|
|
cb672697e7 | ||
|
|
0bae9fc29b | ||
|
|
49c8b68700 | ||
|
|
1e2fcd17e0 | ||
|
|
468b9d2655 | ||
|
|
a3305ff791 | ||
|
|
814b0d5873 | ||
|
|
863f3e82ac | ||
|
|
529c756458 | ||
|
|
67b98dbdaa | ||
|
|
a16981cbe5 | ||
|
|
777bf338fa | ||
|
|
3ba8d9ebff | ||
|
|
db5384e19c | ||
|
|
fd3984287b | ||
|
|
31dbea4e0b | ||
|
|
0992e784f1 | ||
|
|
c59cc1fbb7 | ||
|
|
903edc79f7 | ||
|
|
4c94c69f02 | ||
|
|
4c57c214bd | ||
|
|
1cbeea3016 | ||
|
|
0d18738192 | ||
|
|
1e7c7db29b | ||
|
|
7c098a2665 | ||
|
|
3ab539be1e | ||
|
|
b46d5e4efc | ||
|
|
db06e11a7c | ||
|
|
757ed33e4f | ||
|
|
8eb5dfce85 | ||
|
|
f34db72a97 | ||
|
|
3dfdc8ee6f | ||
|
|
5a846296ca | ||
|
|
0bea015dcd | ||
|
|
fe0b401edd | ||
|
|
69f8e82c3f | ||
|
|
79d3d43a85 | ||
|
|
e8a7f596bc | ||
|
|
a096c00b68 | ||
|
|
e284ef8906 | ||
|
|
154a8750dc | ||
|
|
0de4ca4a19 | ||
|
|
23c9c9f72e | ||
|
|
96ff10c692 | ||
|
|
30bc7ea132 | ||
|
|
d9ea1591b0 | ||
|
|
0cc1bb5ad8 | ||
|
|
509bbd7605 | ||
|
|
4632afe1ab | ||
|
|
6680698ba6 | ||
|
|
2b06b12ca2 | ||
|
|
9b53916e06 | ||
|
|
f3ce1dd7a3 | ||
|
|
91b0426d68 | ||
|
|
63a5b95939 | ||
|
|
480a3fe171 | ||
|
|
b160eac49f | ||
|
|
37ba82b8b7 | ||
|
|
2d604145f1 | ||
|
|
d60a6df313 | ||
|
|
236d9e3028 | ||
|
|
175327e711 | ||
|
|
6342f99504 | ||
|
|
6164ae9f60 |
@@ -86,5 +86,5 @@ SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: ForContinuationAndIndentation
|
||||
UseTab: AlignWithSpaces
|
||||
...
|
||||
|
||||
54
.github/CONTRIBUTING.md
vendored
54
.github/CONTRIBUTING.md
vendored
@@ -1,54 +0,0 @@
|
||||
# So you want to contribute to PCSX2? Great
|
||||
|
||||
As a first step, please review these links as they'll help you understand how the development of PCSX2 works.
|
||||
|
||||
* [Just Starting Out](#just-starting-out)
|
||||
* [Issue Reporting](#issue-reporting)
|
||||
* [Pull Request Guidelines](#pull-request-guidelines)
|
||||
* [General Documentation And Coding Strategies](#general-documentation-and-coding-strategies)
|
||||
* [Tasks](#tasks)
|
||||
|
||||
## Just Starting Out
|
||||
|
||||
* If you're unfamilar with git, check out this [brief introduction to Git](https://github.com/PCSX2/pcsx2/wiki/07-Git-survival-guide)
|
||||
* [How to build PCSX2 for Windows](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
|
||||
* [How to build PCSX2 for Linux](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
|
||||
|
||||
## Issue Reporting
|
||||
|
||||
* [How to write a useful issue](https://github.com/PCSX2/pcsx2/wiki/How-to-create-useful-and-valid-issues)
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
The following is a list of *general* style recommendations that will make reviewing and merging easier:
|
||||
|
||||
* Commit Messages
|
||||
* Please try to prefix your commit message, indicating what area of the project was modified.
|
||||
* For example `gs: message...`.
|
||||
* Looking at the project's commit history will help with keeping prefixes consistent overtime, *there is no strictly enforced list*.
|
||||
|
||||
* Try to keep messages brief and informative
|
||||
|
||||
* Remove unnecessary commits and squash commits together when appropriate.
|
||||
* If you are not familiar with rebasing with git, check out the following resources:
|
||||
* CLI - https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
|
||||
* GUI (SourceTree) - https://www.atlassian.com/blog/sourcetree/interactive-rebase-sourcetree
|
||||
|
||||
* Code Styling and Formatting
|
||||
* [Consult the style guide](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
* Run `clang-format` using the configuration file in the root of the repository
|
||||
* Visual Studio Setup - https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/
|
||||
* IMPORTANT - if you are running `clang-format` on unrelated changes (ie. formatting an entire file), please do so in a separate commit.
|
||||
* If you cannot scope your `clang-format` to just your changes and do not want to format unrelated code. Try your best to stick with the existing formatting already established in the file in question.
|
||||
|
||||
## General Documentation And Coding Strategies
|
||||
|
||||
* [Commenting Etiquette](https://github.com/PCSX2/pcsx2/wiki/06-Commenting-Etiquette)
|
||||
|
||||
* [Coding style](https://github.com/PCSX2/pcsx2/wiki/Code-Formatting-Guidelines)
|
||||
* [More comprehensive style-guide (Currently in Draft)](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
## Tasks
|
||||
|
||||
* [Issues](https://github.com/PCSX2/pcsx2/issues)
|
||||
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1,3 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [PCSX2]
|
||||
liberapay: PCSX2
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/app_bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/app_bug_report.yaml
vendored
@@ -70,6 +70,8 @@ body:
|
||||
- Windows 11
|
||||
- Windows 10 (64bit)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 26 (Tahoe)
|
||||
- macOS 15 (Sequoia)
|
||||
- macOS 14 (Sonoma)
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
10
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -66,6 +66,10 @@ body:
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid.
|
||||
|
||||
Please read our troubleshooting pages and our issue reporting guide.
|
||||
- [Troubleshooting page](https://pcsx2.net/docs/category/troubleshooting).
|
||||
- [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify).
|
||||
|
||||
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
|
||||
- type: input
|
||||
id: rev
|
||||
@@ -83,6 +87,8 @@ body:
|
||||
- Windows 11
|
||||
- Windows 10 (64bit)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 26 (Tahoe)
|
||||
- macOS 15 (Sequoia)
|
||||
- macOS 14 (Sonoma)
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
@@ -100,14 +106,14 @@ body:
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: "Example: i5-7600"
|
||||
placeholder: "Example: Intel i5 12400F"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: "Example: GTX 1070"
|
||||
placeholder: "Example: Nvidia RTX 4060"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,3 +6,6 @@
|
||||
|
||||
### Suggested Testing Steps
|
||||
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
|
||||
|
||||
### Did you use AI to help find, test, or implement this issue or feature?
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->
|
||||
|
||||
11
.github/labeler.yml
vendored
11
.github/labeler.yml
vendored
@@ -22,6 +22,10 @@
|
||||
- '3rdparty/**/*'
|
||||
- '**/3rdpartyDeps.props'
|
||||
- '.gitmodules'
|
||||
'requires-win-deps-build':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '.github/workflows/scripts/windows/*'
|
||||
'Documentation':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@@ -36,6 +40,13 @@
|
||||
- 'pcsx2-qt/**/*'
|
||||
- '3rdparty/Qt/*'
|
||||
- '3rdparty/Qt/**/*'
|
||||
'OSD / ImGui':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/ImGui/*'
|
||||
- 'pcsx2/ImGui/**/*'
|
||||
- '3rdparty/imgui/*'
|
||||
- '3rdparty/imgui/**/*'
|
||||
'GameDB':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
57
.github/workflows/cron_publish_flatpak.yml
vendored
57
.github/workflows/cron_publish_flatpak.yml
vendored
@@ -6,36 +6,45 @@ on:
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Check if release is needed"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 180
|
||||
outputs:
|
||||
PCSX2_RELEASE: ${{ steps.getinfo.outputs.PCSX2_RELEASE }}
|
||||
FLATHUB_RELEASE: ${{ steps.getinfo.outputs.FLATHUB_RELEASE }}
|
||||
steps:
|
||||
- name: Get latest tag and Flathub release
|
||||
id: getinfo
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
PCSX2_RELEASE=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/PCSX2/pcsx2/releases | jq -r '.[0].tag_name')
|
||||
FLATHUB_RELEASE=$(curl -L -s https://flathub.org/api/v2/appstream/net.pcsx2.PCSX2 | jq -r '.releases | max_by(.version) | .version')
|
||||
echo "Latest PCSX2 release is: '${PCSX2_RELEASE}'"
|
||||
echo "Latest Flathub release is: '${FLATHUB_RELEASE}'"
|
||||
PCSX2_RELEASE=$(echo $PCSX2_RELEASE | sed 's/[^0-9]*//g')
|
||||
FLATHUB_RELEASE=$(echo $FLATHUB_RELEASE | sed 's/[^0-9]*//g')
|
||||
echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# check is disabled as the flathub api does not give us beta repository information
|
||||
# Alternatively we can "flatpak remote-info or parse the appstream directly for the beta repo"
|
||||
# Maybe in the future if we don't want to publish the same version twice if we get no commits
|
||||
# for 24 hours.
|
||||
|
||||
# check:
|
||||
# if: github.repository == 'PCSX2/pcsx2'
|
||||
# name: "Check if release is needed"
|
||||
# runs-on: ubuntu-latest
|
||||
# timeout-minutes: 180
|
||||
# outputs:
|
||||
# PCSX2_RELEASE: ${{ steps.getinfo.outputs.PCSX2_RELEASE }}
|
||||
# FLATHUB_RELEASE: ${{ steps.getinfo.outputs.FLATHUB_RELEASE }}
|
||||
# steps:
|
||||
# - name: Get latest tag and Flathub release
|
||||
# id: getinfo
|
||||
# env:
|
||||
# GH_TOKEN: ${{ github.token }}
|
||||
# run: |
|
||||
# PCSX2_RELEASE=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/PCSX2/pcsx2/releases | jq -r '.[0].tag_name')
|
||||
# FLATHUB_RELEASE=$(curl -L -s https://flathub.org/api/v2/appstream/net.pcsx2.PCSX2 | jq -r '.releases | max_by(.version) | .version')
|
||||
# echo "Latest PCSX2 release is: '${PCSX2_RELEASE}'"
|
||||
# echo "Latest Flathub release is: '${FLATHUB_RELEASE}'"
|
||||
# PCSX2_RELEASE=$(echo $PCSX2_RELEASE | sed 's/[^0-9]*//g')
|
||||
# FLATHUB_RELEASE=$(echo $FLATHUB_RELEASE | sed 's/[^0-9]*//g')
|
||||
# echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
# echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: check
|
||||
# needs: check
|
||||
# outputs are automatically compared as strings. This doesn't work in our favour
|
||||
# Use fromJson() to convert them to proper integers...
|
||||
# see: https://github.com/github/docs/pull/25870
|
||||
# and: https://github.com/orgs/community/discussions/57480
|
||||
#if: fromJson(needs.check.outputs.FLATHUB_RELEASE) < fromJson(needs.check.outputs.PCSX2_RELEASE)
|
||||
|
||||
# if: fromJson(needs.check.outputs.FLATHUB_RELEASE) < fromJson(needs.check.outputs.PCSX2_RELEASE)
|
||||
# As the check step is disabled, perform repository check here
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Build and publish Flatpak"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
name: "Update Base Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
|
||||
2
.github/workflows/lint_gamedb.yml
vendored
2
.github/workflows/lint_gamedb.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
|
||||
27
.github/workflows/linux_build_flatpak.yml
vendored
27
.github/workflows/linux_build_flatpak.yml
vendored
@@ -45,28 +45,25 @@ jobs:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.7
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.9
|
||||
options: --privileged
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
# 10 here, since the odds of having 10 untagged commits in a row should be slim to none
|
||||
# This is required for the tagging logic in generate-metainfo.sh
|
||||
fetch-depth: 10
|
||||
fetch-tags: true
|
||||
|
||||
# Work around container ownership issue
|
||||
- name: Set Safe Directory
|
||||
shell: bash
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
# Hackity hack. When running the workflow on a schedule, we don't have the tag,
|
||||
# it doesn't fetch tags, therefore we don't get a version. So grab them manually.
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
@@ -96,7 +93,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (beta)
|
||||
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -112,7 +109,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (stable)
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -125,14 +122,14 @@ jobs:
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
|
||||
#- name: Validate build
|
||||
# run: |
|
||||
# flatpak-builder-lint repo repo
|
||||
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
@@ -141,7 +138,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
@@ -156,7 +153,7 @@ jobs:
|
||||
mv "./${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
9
.github/workflows/linux_build_qt.yml
vendored
9
.github/workflows/linux_build_qt.yml
vendored
@@ -55,11 +55,11 @@ jobs:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 500M
|
||||
CCACHE_MAXSIZE: 100M
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -140,9 +140,12 @@ jobs:
|
||||
-DCMAKE_CXX_COMPILER=clang++-17 \
|
||||
-DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DENABLE_SETCAP=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE \
|
||||
-DUSE_LINKED_FFMPEG=ON \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
$ADDITIONAL_CMAKE_ARGS
|
||||
|
||||
- name: Build PCSX2
|
||||
@@ -171,7 +174,7 @@ jobs:
|
||||
|
||||
- name: Upload artifact
|
||||
if: inputs.buildAppImage == true
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
17
.github/workflows/macos_build.yml
vendored
17
.github/workflows/macos_build.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-14
|
||||
default: macos-26
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
@@ -42,13 +42,13 @@ jobs:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 500M
|
||||
CCACHE_MAXSIZE: 100M
|
||||
# Only way to use a secret in an if statement
|
||||
SIGN_KEY: ${{ secrets.APPLE_SIGN_P12_B64 }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
@@ -62,8 +62,11 @@ jobs:
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Use Xcode 15.2
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.2.app
|
||||
- name: Use Xcode 26.0.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
|
||||
|
||||
- name: Install Metal Toolchain
|
||||
run: xcodebuild -downloadComponent MetalToolchain
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
@@ -91,7 +94,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh', '.github/workflows/scripts/common/*.patch') }}
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/*', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
@@ -194,7 +197,7 @@ jobs:
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS.tar.xz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: "*.tar.xz"
|
||||
|
||||
12
.github/workflows/release_cut_new.yml
vendored
12
.github/workflows/release_cut_new.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
outputs:
|
||||
new_tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -163,12 +163,12 @@ jobs:
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v6
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/src/core/indicators/ClassicDropIndicatorOverlay.h b/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
index 2dfb9718a..9b01f002e 100644
|
||||
--- a/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
+++ b/src/core/indicators/ClassicDropIndicatorOverlay.h
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
-#include "core/DropIndicatorOverlay.h"
|
||||
+#include <kddockwidgets/core/DropIndicatorOverlay.h>
|
||||
|
||||
namespace KDDockWidgets {
|
||||
|
||||
60
.github/workflows/scripts/common/qtapng-cmake.patch
vendored
Normal file
60
.github/workflows/scripts/common/qtapng-cmake.patch
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index bace076..bfb1c66 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -21,6 +21,10 @@ endif ()
|
||||
|
||||
find_package(Qt${APNG_QT_VERSION} REQUIRED COMPONENTS Core Gui)
|
||||
|
||||
+set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||
+find_package(PNG 1.6.40 REQUIRED)
|
||||
+find_package(ZLIB REQUIRED)
|
||||
+
|
||||
add_subdirectory(src)
|
||||
|
||||
if(APNG_TESTS)
|
||||
diff --git a/cmake/FindZLib.cmake b/cmake/FindZLib.cmake
|
||||
deleted file mode 100644
|
||||
index f8e9220..0000000
|
||||
--- a/cmake/FindZLib.cmake
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
-add_library(ZLIB::ZLIB ALIAS zlibstatic) # use our zlib
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index 697df95..0e89371 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -1,2 +1 @@
|
||||
-add_subdirectory(3rdparty EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(plugins)
|
||||
diff --git a/src/plugins/imageformats/apng/CMakeLists.txt b/src/plugins/imageformats/apng/CMakeLists.txt
|
||||
index e1b3fd9..72164fb 100644
|
||||
--- a/src/plugins/imageformats/apng/CMakeLists.txt
|
||||
+++ b/src/plugins/imageformats/apng/CMakeLists.txt
|
||||
@@ -14,13 +14,10 @@ target_sources(ApngImagePlugin PRIVATE ${APNG_SOURCES})
|
||||
target_link_libraries(ApngImagePlugin PRIVATE
|
||||
Qt${APNG_QT_VERSION}::Core
|
||||
Qt${APNG_QT_VERSION}::Gui
|
||||
- png_static
|
||||
- zlibstatic
|
||||
+ PNG::PNG
|
||||
+ ZLIB::ZLIB
|
||||
)
|
||||
|
||||
-get_target_property(_png_include png_static INCLUDE_DIRECTORIES)
|
||||
-target_include_directories(ApngImagePlugin PRIVATE ${_png_include})
|
||||
-
|
||||
target_compile_definitions(ApngImagePlugin PRIVATE
|
||||
QT_DEPRECATED_WARNINGS
|
||||
QT_ASCII_CAST_WARNINGS
|
||||
@@ -31,3 +28,10 @@ set_target_properties(ApngImagePlugin PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins/imageformats"
|
||||
LIBRARY_OUTPUT_NAME qapng
|
||||
)
|
||||
+
|
||||
+install(TARGETS ApngImagePlugin DESTINATION "plugins/imageformats")
|
||||
+
|
||||
+if(WIN32 AND MSVC)
|
||||
+ set_target_properties(ApngImagePlugin PROPERTIES DEBUG_POSTFIX d)
|
||||
+ install(FILES $<TARGET_PDB_FILE:ApngImagePlugin> DESTINATION "plugins/imageformats" OPTIONAL)
|
||||
+endif()
|
||||
@@ -9,6 +9,5 @@ set -e
|
||||
"$SCRIPTDIR/../../../../tools/retry.sh" sudo apt-get -y install qt6-l10n-tools python3
|
||||
|
||||
"$SCRIPTDIR/../../../../tools/generate_fullscreen_ui_translation_strings.py"
|
||||
"$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_glyph_ranges.py"
|
||||
"$SCRIPTDIR/../../../../tools/generate_update_fa_glyph_ranges.py"
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_base_translation.sh"
|
||||
|
||||
94
.github/workflows/scripts/linux/appimage-qt.sh
vendored
94
.github/workflows/scripts/linux/appimage-qt.sh
vendored
@@ -41,24 +41,13 @@ BINARY=pcsx2-qt
|
||||
APPDIRNAME=PCSX2.AppDir
|
||||
STRIP=strip
|
||||
|
||||
# Need both libharfbuzz.so and libharfbuzz.so.0 for bundled libs
|
||||
|
||||
declare -a MANUAL_LIBS=(
|
||||
"libshaderc_shared.so.1"
|
||||
)
|
||||
|
||||
declare -a MANUAL_QT_LIBS=(
|
||||
"libQt6WaylandEglClientHwIntegration.so.6"
|
||||
)
|
||||
|
||||
declare -a MANUAL_QT_PLUGINS=(
|
||||
"wayland-decoration-client"
|
||||
"wayland-graphics-integration-client"
|
||||
"wayland-shell-integration"
|
||||
)
|
||||
|
||||
declare -a REMOVE_LIBS=(
|
||||
'libwayland-client.so*'
|
||||
'libwayland-cursor.so*'
|
||||
'libwayland-egl.so*'
|
||||
"libharfbuzz.so.0"
|
||||
"libharfbuzz.so"
|
||||
"libfreetype.so.6"
|
||||
)
|
||||
|
||||
set -e
|
||||
@@ -66,7 +55,6 @@ set -e
|
||||
LINUXDEPLOY=./linuxdeploy-x86_64.AppImage
|
||||
LINUXDEPLOY_PLUGIN_QT=./linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
APPIMAGETOOL=./appimagetool-x86_64.AppImage
|
||||
PATCHELF=patchelf
|
||||
|
||||
if [ ! -f "$LINUXDEPLOY" ]; then
|
||||
"$PCSX2DIR/tools/retry.sh" wget -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
@@ -79,29 +67,36 @@ if [ ! -f "$LINUXDEPLOY_PLUGIN_QT" ]; then
|
||||
fi
|
||||
|
||||
if [ ! -f "$APPIMAGETOOL" ]; then
|
||||
"$PCSX2DIR/tools/retry.sh" wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
"$PCSX2DIR/tools/retry.sh" wget -O "$APPIMAGETOOL" https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x "$APPIMAGETOOL"
|
||||
fi
|
||||
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
rm -fr "$OUTDIR"
|
||||
|
||||
# Our deps build dosn't create libharfbuzz.so.0, so we have to symlink it here
|
||||
hbpath=$(find "$DEPSDIR" -name "libharfbuzz.so")
|
||||
if [ ! -f "$hbpath" ]; then
|
||||
echo "Missing harfbuzz. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$hbpath.0" ]; then
|
||||
echo "Symlinking libharfbuzz.so.0"
|
||||
ln -s "$hbpath" "$hbpath.0"
|
||||
fi
|
||||
|
||||
echo "Locating extra libraries..."
|
||||
EXTRA_LIBS_ARGS=""
|
||||
EXTRA_LIBS_ARGS=()
|
||||
for lib in "${MANUAL_LIBS[@]}"; do
|
||||
srcpath=$(find "$DEPSDIR" -name "$lib")
|
||||
if [ ! -f "$srcpath" ]; then
|
||||
echo "Missinge extra library $lib. Exiting."
|
||||
echo "Missing extra library $lib. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found $lib at $srcpath."
|
||||
|
||||
if [ "$EXTRA_LIBS_ARGS" == "" ]; then
|
||||
EXTRA_LIBS_ARGS="--library=$srcpath"
|
||||
else
|
||||
EXTRA_LIBS_ARGS="$EXTRA_LIBS_ARGS,$srcpath"
|
||||
fi
|
||||
EXTRA_LIBS_ARGS+=( "--library=$srcpath" )
|
||||
done
|
||||
|
||||
# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
|
||||
@@ -125,55 +120,20 @@ cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" "net.pcsx2.PCSX2
|
||||
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "PCSX2.png"
|
||||
|
||||
echo "Running linuxdeploy to create AppDir..."
|
||||
EXTRA_QT_PLUGINS="core;gui;svg;waylandclient;widgets;xcbqpa" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
|
||||
# The wayland platform plugin requires the plugins deployed for the waylandcompositor module
|
||||
# Interestingly, specifying the module doesn't copy the module, only the required plugins for it
|
||||
# https://github.com/linuxdeploy/linuxdeploy-plugin-qt/issues/160#issuecomment-2655543893
|
||||
EXTRA_QT_MODULES="core;gui;svg;waylandclient;waylandcompositor;widgets;xcbqpa" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland.so" \
|
||||
DEPLOY_PLATFORM_THEMES="1" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" $EXTRA_LIBS_ARGS \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" ${EXTRA_LIBS_ARGS[@]} \
|
||||
--desktop-file="net.pcsx2.PCSX2.desktop" --icon-file="PCSX2.png"
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
||||
|
||||
# LinuxDeploy's Qt plugin doesn't include Wayland support. So manually copy in the additional Wayland libraries.
|
||||
echo "Copying Qt Wayland libraries..."
|
||||
for lib in "${MANUAL_QT_LIBS[@]}"; do
|
||||
srcpath="$DEPSDIR/lib/$lib"
|
||||
dstpath="$OUTDIR/usr/lib/$lib"
|
||||
echo " $srcpath -> $dstpath"
|
||||
cp "$srcpath" "$dstpath"
|
||||
$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
|
||||
done
|
||||
|
||||
# .. and plugins.
|
||||
echo "Copying Qt Wayland plugins..."
|
||||
for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
|
||||
srcpath="$DEPSDIR/plugins/$GROUP"
|
||||
dstpath="$OUTDIR/usr/plugins/$GROUP"
|
||||
echo " $srcpath -> $dstpath"
|
||||
mkdir -p "$dstpath"
|
||||
|
||||
for srcsopath in $(find "$DEPSDIR/plugins/$GROUP" -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
soname=$(basename "$srcsopath")
|
||||
dstsopath="$dstpath/$soname"
|
||||
echo " $srcsopath -> $dstsopath"
|
||||
cp "$srcsopath" "$dstsopath"
|
||||
$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
|
||||
done
|
||||
done
|
||||
|
||||
# Why do we have to manually remove these libs? Because the linuxdeploy Qt plugin
|
||||
# copies them, not the "main" linuxdeploy binary, and plugins don't inherit the
|
||||
# include list...
|
||||
for lib in "${REMOVE_LIBS[@]}"; do
|
||||
for libpath in $(find "$OUTDIR/usr/lib" -name "$lib"); do
|
||||
echo " Removing problematic library ${libpath}."
|
||||
rm -f "$libpath"
|
||||
done
|
||||
done
|
||||
|
||||
# Restore unstripped deps (for cache).
|
||||
rm -fr "$DEPSDIR"
|
||||
mv "$DEPSDIR.bak" "$DEPSDIR"
|
||||
|
||||
@@ -14,55 +14,65 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.45
|
||||
LIBWEBP=1.5.0
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
SDL=SDL3-3.2.10
|
||||
QT=6.9.0
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.26
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=0.0.13
|
||||
PLUTOSVG=0.0.6
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
SHADERC=2025.3
|
||||
SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz
|
||||
2047c6242a57bf97cf40079fa9f91752c137cd9ae84760faa9a2e5e8a440606f qtimageformats-everywhere-src-$QT.tar.xz
|
||||
ec359d930c95935ea48af58b100c2f5d0d275968ec8ca1e0e76629b7159215fc qtsvg-everywhere-src-$QT.tar.xz
|
||||
fa645589cc3f939022401a926825972a44277dead8ec8607d9f2662e6529c9a4 qttools-everywhere-src-$QT.tar.xz
|
||||
1d5581ef5fc7c7bc556f2403017983683993bbebfcdf977ef8f180f604668c3f qttranslations-everywhere-src-$QT.tar.xz
|
||||
503416fcb04db503bd130e6a49c45e3e546f091e83406f774a0c703130c91805 qtwayland-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
|
||||
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
603f2b0a259b24bd0fb14f880d7761b1d248118a42a6870cdbe8fdda4173761f qtwayland-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download" \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
@@ -71,6 +81,7 @@ curl -L \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz" \
|
||||
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
@@ -93,7 +104,9 @@ cd ..
|
||||
echo "Building libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
|
||||
cd "libpng-$LIBPNG"
|
||||
patch -p1 < "../libpng-$LIBPNG-apng.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
@@ -103,14 +116,16 @@ echo "Building libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build -G Ninja
|
||||
# On non debian or debian based Linux systems, libjpeg-turbo will set CMAKE_INSTALL_DEFAULT_LIBDIR "lib64" (or libx32)
|
||||
# That will prevent CMake from finding the deps libjpeg later on. if we set CMAKE_INSTALL_DEFAULT_LIBDIR, libjpeg-turbo will leave it as is, so set it to "lib"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -DCMAKE_INSTALL_DEFAULT_LIBDIR="lib" -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
tar xf "$LZ4.tar.gz"
|
||||
tar xf "lz4-$LZ4.tar.gz"
|
||||
cd "lz4-$LZ4"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DLZ4_BUILD_CLI=OFF -DLZ4_BUILD_LEGACY_LZ4C=OFF -B build-dir -G Ninja build/cmake
|
||||
cmake --build build-dir --parallel
|
||||
@@ -137,6 +152,33 @@ cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType without HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building SDL..."
|
||||
rm -fr "$SDL"
|
||||
tar xf "$SDL.tar.gz"
|
||||
@@ -217,11 +259,20 @@ cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt APNG..."
|
||||
rm -fr "QtApng-$QTAPNG"
|
||||
tar xf "QtApng-$QTAPNG.tar.gz"
|
||||
cd "QtApng-$QTAPNG"
|
||||
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
@@ -240,7 +291,7 @@ echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=OFF -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
196
.github/workflows/scripts/linux/build-dependencies-runner.sh
vendored
Executable file
196
.github/workflows/scripts/linux/build-dependencies-runner.sh
vendored
Executable file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Syntax: $0 <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPTDIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
INSTALLDIR="$1"
|
||||
if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.22
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.3
|
||||
SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download" \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz" \
|
||||
-o "plutovg-$PLUTOVG.tar.gz" "https://github.com/sammycage/plutovg/archive/v$PLUTOVG.tar.gz" \
|
||||
-o "plutosvg-$PLUTOSVG.tar.gz" "https://github.com/sammycage/plutosvg/archive/v$PLUTOSVG.tar.gz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
unzip "$LIBBACKTRACE.zip"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR"
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Building libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
|
||||
cd "libpng-$LIBPNG"
|
||||
patch -p1 < "../libpng-$LIBPNG-apng.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
tar xf "lz4-$LZ4.tar.gz"
|
||||
cd "lz4-$LZ4"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DLZ4_BUILD_CLI=OFF -DLZ4_BUILD_LEGACY_LZ4C=OFF -B build-dir -G Ninja build/cmake
|
||||
cmake --build build-dir --parallel
|
||||
ninja -C build-dir install
|
||||
cd ..
|
||||
|
||||
echo "Building Zstandard..."
|
||||
rm -fr "zstd-$ZSTD"
|
||||
tar xf "zstd-$ZSTD.tar.gz"
|
||||
cd "zstd-$ZSTD"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType without HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building WebP..."
|
||||
rm -fr "libwebp-$LIBWEBP"
|
||||
tar xf "libwebp-$LIBWEBP.tar.gz"
|
||||
cd "libwebp-$LIBWEBP"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -B build -G Ninja \
|
||||
-DWEBP_BUILD_ANIM_UTILS=OFF -DWEBP_BUILD_CWEBP=OFF -DWEBP_BUILD_DWEBP=OFF -DWEBP_BUILD_GIF2WEBP=OFF -DWEBP_BUILD_IMG2WEBP=OFF \
|
||||
-DWEBP_BUILD_VWEBP=OFF -DWEBP_BUILD_WEBPINFO=OFF -DWEBP_BUILD_WEBPMUX=OFF -DWEBP_BUILD_EXTRAS=OFF -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building SDL..."
|
||||
rm -fr "$SDL"
|
||||
tar xf "$SDL.tar.gz"
|
||||
cd "$SDL"
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoVG..."
|
||||
rm -fr "plutovg-$PLUTOVG"
|
||||
tar xf "plutovg-$PLUTOVG.tar.gz"
|
||||
cd "plutovg-$PLUTOVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building shaderc..."
|
||||
rm -fr "shaderc-$SHADERC"
|
||||
tar xf "shaderc-$SHADERC.tar.gz"
|
||||
cd "shaderc-$SHADERC"
|
||||
cd third_party
|
||||
tar xf "../../shaderc-glslang-$SHADERC_GLSLANG.tar.gz"
|
||||
mv "glslang-$SHADERC_GLSLANG" "glslang"
|
||||
tar xf "../../shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz"
|
||||
mv "SPIRV-Headers-$SHADERC_SPIRVHEADERS" "spirv-headers"
|
||||
tar xf "../../shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz"
|
||||
mv "SPIRV-Tools-$SHADERC_SPIRVTOOLS" "spirv-tools"
|
||||
cd ..
|
||||
patch -p1 < "$SCRIPTDIR/../common/shaderc-changes.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DSHADERC_SKIP_TESTS=ON -DSHADERC_SKIP_EXAMPLES=ON -DSHADERC_SKIP_COPYRIGHT_CHECK=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -r deps-build
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.10.tar.gz",
|
||||
"sha256": "f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.26.tar.gz",
|
||||
"sha256": "dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -15,24 +15,24 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/google/shaderc.git",
|
||||
"commit": "47a9387ef5b3600d30d84c71ec77a59dc7db46fa"
|
||||
"commit": "8c2e602ce440b7739c95ff3d69cecb1adf6becda"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/142052fa30f9eca191aa9dcf65359fcaed09eeec.tar.gz",
|
||||
"sha256": "aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/efd24d75bcbc55620e759f6bf42c45a32abac5f8.tar.gz",
|
||||
"sha256": "9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47",
|
||||
"dest": "third_party/glslang"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/5e3ad389ee56fca27c9705d093ae5387ce404df4.tar.gz",
|
||||
"sha256": "5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/2a611a970fdbc41ac2e3e328802aed9985352dca.tar.gz",
|
||||
"sha256": "c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a",
|
||||
"dest": "third_party/spirv-headers"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/dd4b663e13c07fea4fbb3f70c1c91c86731099f7.tar.gz",
|
||||
"sha256": "03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/33e02568181e3312f49a3cf33df470bf96ef293a.tar.gz",
|
||||
"sha256": "44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff",
|
||||
"dest": "third_party/spirv-tools"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -14,13 +14,9 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/KDAB/KDDockWidgets.git",
|
||||
"tag": "v2.2.3",
|
||||
"commit": "28d16d0431d7cdc9f36cb619d22621146fdfab44",
|
||||
"tag": "v2.3.0",
|
||||
"commit": "c38711026e17e34916dd82c6fcbdcc0d2342f541",
|
||||
"disable-submodules": true
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "../../../common/kddockwidgets-dodgy-include.patch"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"type": "git",
|
||||
"url": "https://github.com/sammycage/plutovg.git",
|
||||
"tag": "v0.0.13",
|
||||
"sha256": "5e4712cf873b0c7829a4a6157763e2ad3ac49164"
|
||||
"tag": "v1.3.1",
|
||||
"commit": "57f82ac9ffc98fb47833f1661583b347b2a08dd3"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"type": "git",
|
||||
"url": "https://github.com/sammycage/plutosvg.git",
|
||||
"tag": "v0.0.6",
|
||||
"sha256": "c5388fa96feca1f1376a3d0485d5e35159452707"
|
||||
"tag": "v0.0.7",
|
||||
"commit": "31f7d2675416cd777c8e86220b035364873b2a8b"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
46
.github/workflows/scripts/linux/flatpak/modules/26-libpng.json
vendored
Normal file
46
.github/workflows/scripts/linux/flatpak/modules/26-libpng.json
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "libpng",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"-DPNG_TESTS=OFF",
|
||||
"-DPNG_STATIC=OFF",
|
||||
"-DPNG_SHARED=ON",
|
||||
"-DPNG_TOOLS=OFF"
|
||||
],
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.50/libpng-1.6.50.tar.xz",
|
||||
"sha256": "4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.50-apng.patch.gz",
|
||||
"dest-filename": "libpng-1.6.50-apng.patch.gz",
|
||||
"sha256": "687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"commands":
|
||||
[
|
||||
"gunzip -f libpng-1.6.50-apng.patch.gz",
|
||||
"patch -p1 < \"libpng-1.6.50-apng.patch\""
|
||||
]
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin",
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la",
|
||||
"/lib/cmake",
|
||||
"/lib/libpng",
|
||||
"/lib/pkgconfig",
|
||||
"/share/man"
|
||||
]
|
||||
}
|
||||
|
||||
29
.github/workflows/scripts/linux/flatpak/modules/27-qtapng.json
vendored
Normal file
29
.github/workflows/scripts/linux/flatpak/modules/27-qtapng.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "qtapng",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\""
|
||||
],
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jurplel/QtApng.git",
|
||||
"tag": "1.3.0",
|
||||
"commit": "bd15516b281204e90ecd5b80b00d1274b062f5fc"
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "../../../common/qtapng-cmake.patch"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/plugins"
|
||||
],
|
||||
"post-install": [
|
||||
"mv ${FLATPAK_DEST}/plugins/* ${FLATPAK_DEST}/bin/"
|
||||
]
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"app-id": "net.pcsx2.PCSX2",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.8",
|
||||
"runtime-version": "6.10",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm18"
|
||||
"org.freedesktop.Sdk.Extension.llvm20"
|
||||
],
|
||||
"add-extensions": {
|
||||
"org.freedesktop.Platform.ffmpeg-full": {
|
||||
"directory": "lib/ffmpeg",
|
||||
"version": "24.08",
|
||||
"version": "25.08",
|
||||
"add-ld-path": ".",
|
||||
"autodownload": true
|
||||
}
|
||||
@@ -32,6 +32,8 @@
|
||||
"modules/23-kddockwidgets.json",
|
||||
"modules/24-plutovg.json",
|
||||
"modules/25-plutosvg.json",
|
||||
"modules/26-libpng.json",
|
||||
"modules/27-qtapng.json",
|
||||
{
|
||||
"name": "pcsx2",
|
||||
"buildsystem": "cmake-ninja",
|
||||
@@ -45,10 +47,11 @@
|
||||
"cxxflags": "",
|
||||
"cxxflags-override": true,
|
||||
"config-opts": [
|
||||
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\"",
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm18/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm18/bin/clang++",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm20/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm20/bin/clang++",
|
||||
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_MODULE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
|
||||
@@ -12,12 +12,24 @@ GIT_DATE=$(git log -1 --pretty=%cd --date=iso8601)
|
||||
GIT_VERSION=$(git tag --points-at HEAD)
|
||||
GIT_HASH=$(git rev-parse HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
# In the odd event that we run this script before the release gets tagged.
|
||||
GIT_VERSION=$(git describe --tags)
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
if [[ -z "${GIT_VERSION}" ]]; then
|
||||
if git branch -r --contains HEAD | grep -q 'origin/master'; then
|
||||
# Our master doesn't have a tagged commit
|
||||
# This happens when the commit is "ci skip"
|
||||
# abbrev so we have just the latest tag
|
||||
# ie v2.3.420 (Yes, that's the current master at the time of writing)
|
||||
GIT_VERSION=$(git describe --tags --abbrev=0)
|
||||
else
|
||||
# We are probably building a PR
|
||||
# Keep the short SHA in the version
|
||||
# ie v2.3.420-1-g10dc1a2da
|
||||
GIT_VERSION=$(git describe --tags)
|
||||
fi
|
||||
|
||||
if [[ -z "${GIT_VERSION}" ]]; then
|
||||
# Fallback to raw commit hash
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "GIT_DATE: ${GIT_DATE}"
|
||||
|
||||
@@ -11,7 +11,7 @@ merge_binaries() {
|
||||
"
|
||||
pushd "$X86DIR"
|
||||
for X86BIN in $(find . -type f \( -name '*.dylib' -o -name '*.a' -o -perm +111 \)); do
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O " >/dev/null; then
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O.*x86_64" >/dev/null; then
|
||||
ARMBIN="${ARMDIR}/${X86BIN}"
|
||||
echo "Merge $ARMBIN to $X86BIN..."
|
||||
lipo -create "$X86BIN" "$ARMBIN" -o "$X86BIN"
|
||||
@@ -38,25 +38,26 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
SDL=SDL3-3.2.10
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
SDL=SDL3-3.2.26
|
||||
ZSTD=1.5.7
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
LIBPNG=1.6.45
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=0.0.13
|
||||
PLUTOSVG=0.0.6
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
SHADERC=2025.3
|
||||
SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -77,28 +78,30 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
|
||||
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -C - -L \
|
||||
@@ -106,17 +109,19 @@ curl -C - -L \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
@@ -187,7 +192,7 @@ cd ..
|
||||
|
||||
echo "Installing LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
tar xf "$LZ4.tar.gz"
|
||||
tar xf "lz4-$LZ4.tar.gz"
|
||||
cd "lz4-$LZ4"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DBUILD_SHARED_LIBS=ON -DLZ4_BUILD_CLI=OFF -DLZ4_BUILD_LEGACY_LZ4C=OFF -B build-dir build/cmake
|
||||
make -C build-dir "-j$NPROCS"
|
||||
@@ -200,7 +205,9 @@ cd ..
|
||||
echo "Installing libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
|
||||
cd "libpng-$LIBPNG"
|
||||
patch -p1 < "../libpng-$LIBPNG-apng.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -DPNG_ARM_NEON=on -B build-arm64
|
||||
@@ -213,8 +220,11 @@ echo "Installing libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build
|
||||
make -C build "-j$NPROCS"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
make -C build-arm64 "-j$NPROCS"
|
||||
merge_binaries $(realpath build) $(realpath build-arm64)
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -275,6 +285,10 @@ echo "Installing Qt Base..."
|
||||
rm -fr "qtbase-everywhere-src-$QT"
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
|
||||
# Patch Qt to support macOS 11
|
||||
patch -p1 < "$SCRIPTDIR/qt-macos11compat.patch"
|
||||
|
||||
# since we don't have a direct reference to QtSvg, it doesn't deployed directly from the main binary
|
||||
# (only indirectly from iconengines), and the libqsvg.dylib imageformat plugin does not get deployed.
|
||||
# We could run macdeployqt twice, but that's even more janky than patching it.
|
||||
@@ -310,7 +324,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -321,7 +335,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -332,7 +346,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -361,26 +375,35 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
echo "Building Qt APNG..."
|
||||
rm -fr "QtApng-$QTAPNG"
|
||||
tar xf "QtApng-$QTAPNG.tar.gz"
|
||||
cd "QtApng-$QTAPNG"
|
||||
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoVG..."
|
||||
rm -fr "plutovg-$PLUTOVG"
|
||||
tar xf "plutovg-$PLUTOVG.tar.gz"
|
||||
cd "plutovg-$PLUTOVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -389,7 +412,7 @@ echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -20,25 +20,26 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
SDL=SDL3-3.2.10
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
SDL=SDL3-3.2.26
|
||||
ZSTD=1.5.7
|
||||
LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
LIBPNG=1.6.45
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBWEBP=1.5.0
|
||||
FFMPEG=6.0
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=0.0.13
|
||||
PLUTOSVG=0.0.6
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2024.1
|
||||
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
SHADERC=2025.3
|
||||
SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -53,32 +54,35 @@ CMAKE_COMMON=(
|
||||
-DCMAKE_PREFIX_PATH="$INSTALLDIR"
|
||||
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
|
||||
-DCMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
-DCMAKE_APPLE_SILICON_PROCESSOR="x86_64"
|
||||
-DCMAKE_INSTALL_NAME_DIR='$<INSTALL_PREFIX>/lib'
|
||||
)
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f87be7b4dec66db4098e9c167b2aa34e2ca10aeb5443bdde95ae03185ed513e0 $SDL.tar.gz
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
0728800155f3ed0a0c87e03addbd30ecbe374f7b080678bbca1506051d50dec3 $LZ4.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
eb3b5f0c16313d34f208d90c2fa1e588a23283eed63b101edd5422be6165d528 shaderc-$SHADERC.tar.gz
|
||||
aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
|
||||
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
@@ -86,8 +90,9 @@ curl -L \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/archive/$LZ4.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
@@ -97,6 +102,7 @@ curl -L \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-o "QtApng-$QTAPNG.tar.gz" "https://github.com/jurplel/QtApng/archive/refs/tags/$QTAPNG.tar.gz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
@@ -146,7 +152,7 @@ cd ..
|
||||
|
||||
echo "Installing LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
tar xf "$LZ4.tar.gz"
|
||||
tar xf "lz4-$LZ4.tar.gz"
|
||||
cd "lz4-$LZ4"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DLZ4_BUILD_CLI=OFF -DLZ4_BUILD_LEGACY_LZ4C=OFF -B build-dir build/cmake
|
||||
make -C build-dir "-j$NPROCS"
|
||||
@@ -156,7 +162,9 @@ cd ..
|
||||
echo "Installing libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
|
||||
cd "libpng-$LIBPNG"
|
||||
patch -p1 < "../libpng-$LIBPNG-apng.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
@@ -226,26 +234,18 @@ rm -fr "qtbase-everywhere-src-$QT"
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
|
||||
# Patch Qt to support macOS 11
|
||||
patch -p1 < "$SCRIPTDIR/qt-macos11compat.patch"
|
||||
|
||||
# Patch Qt to fix a bug with message boxes on Tahoe
|
||||
patch -p1 < "$SCRIPTDIR/clickbutton.patch"
|
||||
|
||||
# since we don't have a direct reference to QtSvg, it doesn't deployed directly from the main binary
|
||||
# (only indirectly from iconengines), and the libqsvg.dylib imageformat plugin does not get deployed.
|
||||
# We could run macdeployqt twice, but that's even more janky than patching it.
|
||||
|
||||
# https://github.com/qt/qtbase/commit/7b018629c3c3ab23665bf1da00c43c1546042035
|
||||
# The QProcess default wait time of 30s may be too short in e.g. CI environments where processes may be blocked
|
||||
# for a longer time waiting for CPU or IO.
|
||||
|
||||
patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
||||
--- shared.cpp
|
||||
+++ shared.cpp
|
||||
@@ -152,7 +152,7 @@
|
||||
LogDebug() << " inspecting" << binaryPath;
|
||||
QProcess otool;
|
||||
otool.start("otool", QStringList() << "-L" << binaryPath);
|
||||
- otool.waitForFinished();
|
||||
+ otool.waitForFinished(-1);
|
||||
|
||||
if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) {
|
||||
LogError() << otool.readAllStandardError();
|
||||
@@ -1122,14 +1122,8 @@
|
||||
addPlugins(QStringLiteral("networkinformation"));
|
||||
}
|
||||
@@ -264,7 +264,7 @@ patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
||||
|
||||
// Platforminputcontext plugins if QtGui is in use
|
||||
EOF
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DCMAKE_BUILD_TYPE=MinSizeRel -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -275,7 +275,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -286,7 +286,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -297,7 +297,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -326,16 +326,25 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
echo "Building Qt APNG..."
|
||||
rm -fr "QtApng-$QTAPNG"
|
||||
tar xf "QtApng-$QTAPNG.tar.gz"
|
||||
cd "QtApng-$QTAPNG"
|
||||
patch -p1 < "$SCRIPTDIR/../common/qtapng-cmake.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
patch -p1 < "$SCRIPTDIR/../common/kddockwidgets-dodgy-include.patch"
|
||||
cmake "${CMAKE_COMMON[@]}" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
|
||||
16
.github/workflows/scripts/macos/clickbutton.patch
vendored
Normal file
16
.github/workflows/scripts/macos/clickbutton.patch
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
--- a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
|
||||
+++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
|
||||
@@ -88,6 +88,11 @@ bool QCocoaMessageDialog::show(Qt::WindowModality windowModality)
|
||||
qCWarning(lcQpaDialogs, "Cannot run window modal dialog without parent window");
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ // Tahoe has issues with window-modal alert buttons not responding to mouse
|
||||
+ if (windowModality == Qt::WindowModal
|
||||
+ && QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe)
|
||||
+ return false;
|
||||
|
||||
// And without options we don't know what to show
|
||||
if (!options())
|
||||
|
||||
# Source https://codereview.qt-project.org/c/qt/qtbase/+/689796
|
||||
78
.github/workflows/scripts/macos/qt-macos11compat.patch
vendored
Normal file
78
.github/workflows/scripts/macos/qt-macos11compat.patch
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
diff --git a/.cmake.conf b/.cmake.conf
|
||||
index 9a21ff42a74..d6707ba7dff 100644
|
||||
--- a/.cmake.conf
|
||||
+++ b/.cmake.conf
|
||||
@@ -51,7 +51,7 @@ set(QT_MAX_NEW_POLICY_CMAKE_VERSION_QT_APPLE "3.21")
|
||||
set(QT_SUPPORTED_MIN_MACOS_SDK_VERSION "14")
|
||||
set(QT_SUPPORTED_MAX_MACOS_SDK_VERSION "26")
|
||||
set(QT_SUPPORTED_MIN_MACOS_XCODE_VERSION "15")
|
||||
-set(QT_SUPPORTED_MIN_MACOS_VERSION "13")
|
||||
+set(QT_SUPPORTED_MIN_MACOS_VERSION "11")
|
||||
set(QT_SUPPORTED_MAX_MACOS_VERSION_TESTED "26")
|
||||
|
||||
set(QT_SUPPORTED_MIN_IOS_SDK_VERSION "17")
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index d3a14fc67eb..1553b956fe3 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -12,6 +12,10 @@ cmake_minimum_required(VERSION 3.16)
|
||||
# Get the repo version and CMake policy details
|
||||
include(.cmake.conf)
|
||||
|
||||
+if(APPLE)
|
||||
+ add_compile_options(-Werror=unguarded-availability-new)
|
||||
+endif()
|
||||
+
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtBaseHelpers.cmake)
|
||||
|
||||
qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}")
|
||||
diff --git a/src/corelib/global/qsysinfo.cpp b/src/corelib/global/qsysinfo.cpp
|
||||
index ae762c0cc6d..9171a5736b4 100644
|
||||
--- a/src/corelib/global/qsysinfo.cpp
|
||||
+++ b/src/corelib/global/qsysinfo.cpp
|
||||
@@ -1027,7 +1027,7 @@ QByteArray QSysInfo::machineUniqueId()
|
||||
{
|
||||
#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
|
||||
char uuid[UuidStringLen + 1];
|
||||
- io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
+ io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
|
||||
CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
|
||||
return QByteArray(uuid);
|
||||
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
|
||||
index 9f27dbe694e..c023a48cad3 100644
|
||||
--- a/src/corelib/kernel/qcore_mac.mm
|
||||
+++ b/src/corelib/kernel/qcore_mac.mm
|
||||
@@ -372,7 +372,7 @@ bool qt_apple_runningWithLiquidGlass()
|
||||
return config;
|
||||
#endif
|
||||
|
||||
- QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMainPortDefault, "IODeviceTree:/options");
|
||||
+ QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
|
||||
if (!nvram) {
|
||||
qWarning("Failed to locate NVRAM entry in IO registry");
|
||||
return {};
|
||||
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
index 6b33d94d58c..867389e4c93 100644
|
||||
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
@@ -323,6 +323,8 @@ a normal (not maximized or full screen) top-level window.
|
||||
m_view.safeAreaInsets.bottom
|
||||
};
|
||||
|
||||
+ if (@available(macOS 12, *)) {
|
||||
+
|
||||
// The screen's safe area insets represent the distances from the screen's
|
||||
// edges at which content isn't obscured. The view's safe area margins do
|
||||
// not include the screen's insets automatically, so we need to manually
|
||||
@@ -355,6 +357,10 @@ a normal (not maximized or full screen) top-level window.
|
||||
};
|
||||
|
||||
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();
|
||||
+
|
||||
+ } else {
|
||||
+ return viewSafeAreaMargins.toMargins();
|
||||
+ }
|
||||
}
|
||||
|
||||
void QCocoaWindow::updateSafeAreaMarginsIfNeeded()
|
||||
@@ -66,7 +66,7 @@ const embed = new MessageEmbed()
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
@@ -42,49 +42,53 @@ echo INSTALLDIR=%INSTALLDIR%
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
set SDL=SDL3-3.2.10
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set WEBP=1.5.0
|
||||
set FREETYPE=2.14.1
|
||||
set HARFBUZZ=12.0.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set LIBPNGLONG=1.6.50
|
||||
set SDL=SDL3-3.2.26
|
||||
set QT=6.10.0
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
set PLUTOVG=0.0.13
|
||||
set PLUTOSVG=0.0.6
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.1
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2024.1
|
||||
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
set SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
set SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
set SHADERC=2025.3
|
||||
set SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
set SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1645.zip a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/%LZ4%.zip" 0c33119688d6b180c7e760b0acd70059222389cfd581632623784bee27e51a31 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 01d9ab20fc071b076be91df5396b464b4ef159e93b2b2addda1cc36750fc1f29 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 5f8a94a161bd2e71a82f478dc19f4ec77ac95a50709f5a68d5951001ed6bb856 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 5885ce1a114615cc5fa69e459f069d3fe2bcb1320fd9cc162821f3920ef44735 || goto error
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 0f3e036294974736982d8ec00f0bed763cd9f75ab9eacf8effe413af5d78ef06 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 739356eef1192fff9d641c320a8f5ef4a10506b8927def4b9ceb764c7e947369 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" d3b5379edcace266273d789249b6d68ae9495ec1b0b562ba6d039034cd315d8e || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" ac2fe34a9f1c1451b6785474e9b1b64eb59edef6553be3d630240f16a730456d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c12f8bfb617e4a03da104be36f6966ba7f64bee331f0095da1a649a1149796d2 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c6d0f0a512304ad87b20f5ff604442dd8d55769d659576ecfe5462fcd7bb9b7d || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" e6cc1ebf62cf37d81f3b86990086108518037bb383e75da327f297cc4fc1ae36 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" e313baaa7c934503ef601c909661a84e5b795dfa12f0354721cac7a9c27be47e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 24826a70d0b168a66eb16ec9d7eeeba0d4ca9d4babc1199889d374918008426e || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 615184f756d91ce416f2cf883bb67fd4262651417c2e40c4d681c8641a48263e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" fa59a54334feaba5702b9c25724c3f4746123865769b36dd5a28d9ef5e9d39ab || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" bf385994c20293485b378c27dfdbd77a31b949deabccd9218a977f173eda9f6f || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 77d2425458bca62c16b1ed49ed02de4c4114a113781bd94c1961b273bdca00fb || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" ebd389bf79c17d79d999b3e9756359945020bbef799537aa96d8900464c373c5 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 6b954cb358a43915a54b6ca7a27db11b15c4f6e9ec547ab4cad71857354692bc || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 00c4fa1a26de21c7c8db6947e06094a338e7d4edf972bc70d30afea9315373f2 || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
@@ -92,7 +96,7 @@ if %DEBUG%==1 (
|
||||
echo Building release libraries...
|
||||
)
|
||||
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_SHARED_LINKER_FLAGS_MINSIZEREL="/DEBUG"
|
||||
set ARM64TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE="%SCRIPTDIR%\cmake-toolchain-windows-arm64.cmake"
|
||||
|
||||
echo Building Zlib...
|
||||
@@ -107,7 +111,10 @@ cd .. || goto error
|
||||
echo Building libpng...
|
||||
rmdir /S /Q "lpng%LIBPNG%"
|
||||
%SEVENZIP% x "lpng%LIBPNG%.zip" || goto error
|
||||
rem apng not in released libpng yet
|
||||
%SEVENZIP% x "lpng%LIBPNG%-apng.patch.gz" -aoa || goto error
|
||||
cd "lpng%LIBPNG%" || goto error
|
||||
%PATCH% -p1 < "../libpng-%LIBPNGLONG%-apng.patch" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -190,7 +197,7 @@ cd .. || goto error
|
||||
if %DEBUG%==1 (
|
||||
set QTBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=MinSizeRel -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt base...
|
||||
@@ -246,12 +253,36 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set QTAPNGBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTAPNGBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt APNG...
|
||||
rmdir /S /Q "QtApng-%QTAPNG%"
|
||||
%SEVENZIP% x "QtApng-%QTAPNG%.zip" || goto error
|
||||
cd "QtApng-%QTAPNG%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\qtapng-cmake.patch" || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
@@ -40,49 +40,53 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
|
||||
set SDL=SDL3-3.2.10
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set WEBP=1.5.0
|
||||
set FREETYPE=2.14.1
|
||||
set HARFBUZZ=12.0.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.26
|
||||
set LIBPNGLONG=1.6.50
|
||||
set QT=6.10.0
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
set PLUTOVG=0.0.13
|
||||
set PLUTOSVG=0.0.6
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.1
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2024.1
|
||||
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
|
||||
set SHADERC_SPIRVHEADERS=5e3ad389ee56fca27c9705d093ae5387ce404df4
|
||||
set SHADERC_SPIRVTOOLS=dd4b663e13c07fea4fbb3f70c1c91c86731099f7
|
||||
set SHADERC=2025.3
|
||||
set SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
set SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
set SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1645.zip a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/%LZ4%.zip" 0c33119688d6b180c7e760b0acd70059222389cfd581632623784bee27e51a31 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 01d9ab20fc071b076be91df5396b464b4ef159e93b2b2addda1cc36750fc1f29 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 5f8a94a161bd2e71a82f478dc19f4ec77ac95a50709f5a68d5951001ed6bb856 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 5885ce1a114615cc5fa69e459f069d3fe2bcb1320fd9cc162821f3920ef44735 || goto error
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 0f3e036294974736982d8ec00f0bed763cd9f75ab9eacf8effe413af5d78ef06 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 739356eef1192fff9d641c320a8f5ef4a10506b8927def4b9ceb764c7e947369 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" d3b5379edcace266273d789249b6d68ae9495ec1b0b562ba6d039034cd315d8e || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" ac2fe34a9f1c1451b6785474e9b1b64eb59edef6553be3d630240f16a730456d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c12f8bfb617e4a03da104be36f6966ba7f64bee331f0095da1a649a1149796d2 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c6d0f0a512304ad87b20f5ff604442dd8d55769d659576ecfe5462fcd7bb9b7d || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" e6cc1ebf62cf37d81f3b86990086108518037bb383e75da327f297cc4fc1ae36 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" e313baaa7c934503ef601c909661a84e5b795dfa12f0354721cac7a9c27be47e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 24826a70d0b168a66eb16ec9d7eeeba0d4ca9d4babc1199889d374918008426e || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 615184f756d91ce416f2cf883bb67fd4262651417c2e40c4d681c8641a48263e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" fa59a54334feaba5702b9c25724c3f4746123865769b36dd5a28d9ef5e9d39ab || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" bf385994c20293485b378c27dfdbd77a31b949deabccd9218a977f173eda9f6f || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 77d2425458bca62c16b1ed49ed02de4c4114a113781bd94c1961b273bdca00fb || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" ebd389bf79c17d79d999b3e9756359945020bbef799537aa96d8900464c373c5 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 6b954cb358a43915a54b6ca7a27db11b15c4f6e9ec547ab4cad71857354692bc || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 00c4fa1a26de21c7c8db6947e06094a338e7d4edf972bc70d30afea9315373f2 || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
@@ -90,7 +94,7 @@ if %DEBUG%==1 (
|
||||
echo Building release libraries...
|
||||
)
|
||||
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_SHARED_LINKER_FLAGS_MINSIZEREL="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_MINSIZEREL="/DEBUG"
|
||||
|
||||
echo Building Zlib...
|
||||
rmdir /S /Q "zlib-%ZLIB%"
|
||||
@@ -104,7 +108,10 @@ cd .. || goto error
|
||||
echo Building libpng...
|
||||
rmdir /S /Q "lpng%LIBPNG%"
|
||||
%SEVENZIP% x "lpng%LIBPNG%.zip" || goto error
|
||||
rem apng not in released libpng yet
|
||||
%SEVENZIP% x "lpng%LIBPNG%-apng.patch.gz" -aoa || goto error
|
||||
cd "lpng%LIBPNG%" || goto error
|
||||
%PATCH% -p1 < "../libpng-%LIBPNGLONG%-apng.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -187,7 +194,7 @@ cd .. || goto error
|
||||
if %DEBUG%==1 (
|
||||
set QTBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=MinSizeRel -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt base...
|
||||
@@ -198,9 +205,6 @@ cd "qtbase-everywhere-src-%QT%" || goto error
|
||||
rem Disable the PCRE2 JIT, it doesn't properly verify AVX2 support.
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-disable-pcre2-jit.patch" || goto error
|
||||
|
||||
rem Hackfix settings icon stretching
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-fix-icon-stretch.patch" || goto error
|
||||
|
||||
cmake -B build -DFEATURE_sql=OFF -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% -DINPUT_gui=yes -DINPUT_widgets=yes -DINPUT_ssl=yes -DINPUT_openssl=no -DINPUT_schannel=yes -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON %QTBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -229,7 +233,7 @@ ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
echo Building Qt Tools...
|
||||
rmdir /S /Q "qtimageformats-everywhere-src-%QT%"
|
||||
rmdir /S /Q "qttools-everywhere-src-%QT%"
|
||||
%SEVENZIP% x "qttools-everywhere-src-%QT%.zip" || goto error
|
||||
cd "qttools-everywhere-src-%QT%" || goto error
|
||||
mkdir build || goto error
|
||||
@@ -250,12 +254,36 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set QTAPNGBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTAPNGBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt APNG...
|
||||
rmdir /S /Q "QtApng-%QTAPNG%"
|
||||
%SEVENZIP% x "QtApng-%QTAPNG%.zip" || goto error
|
||||
cd "QtApng-%QTAPNG%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\qtapng-cmake.patch" || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt6.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistent naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
index 208420d7e8..26ef6f31ef 100644
|
||||
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
|
||||
@@ -4232,8 +4232,6 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
|
||||
|
||||
case SE_ItemViewItemDecoration:
|
||||
rect = QWindowsStyle::subElementRect(element, option, widget);
|
||||
- if (qstyleoption_cast<const QStyleOptionViewItem *>(option))
|
||||
- rect.adjust(-2, 0, 2, 0);
|
||||
break;
|
||||
|
||||
case SE_ItemViewItemFocusRect:
|
||||
4
.github/workflows/triage_pr.yml
vendored
4
.github/workflows/triage_pr.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
pr-message: |-
|
||||
## Thank you for submitting a contribution to PCSX2
|
||||
|
||||
As this is your first pull request, [please be aware of the contributing guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md).
|
||||
As this is your first pull request, [please be aware of the contributing guidelines](https://pcsx2.net/docs/contributing/).
|
||||
|
||||
Additionally, as per recent changes in GitHub Actions, your pull request will need to be approved by a maintainer before GitHub Actions can run against it. [You can find more information about this change here.](https://github.blog/2021-04-22-github-actions-update-helping-maintainers-combat-bad-actors/)
|
||||
|
||||
|
||||
2
.github/workflows/windows_build_matrix.yml
vendored
2
.github/workflows/windows_build_matrix.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
|
||||
|
||||
8
.github/workflows/windows_build_qt.yml
vendored
8
.github/workflows/windows_build_qt.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Configure MSBuild Clang Version
|
||||
if: inputs.configuration != 'CMake'
|
||||
@@ -154,7 +154,7 @@ jobs:
|
||||
cmake --build build --config Release --target unittests
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: |
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
!./bin/**/*.lib
|
||||
|
||||
- name: Install the Breakpad Symbol Generator
|
||||
uses: baptiste0928/cargo-install@91c5da15570085bcde6f4d7aed98cb82d6769fd3
|
||||
uses: baptiste0928/cargo-install@b687c656bda5733207e629b50a22bf68974a0305
|
||||
with:
|
||||
crate: dump_syms
|
||||
|
||||
@@ -186,7 +186,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}-symbols
|
||||
path: |
|
||||
|
||||
17
.github/workflows/windows_deps_dispatch.yml
vendored
Normal file
17
.github/workflows/windows_deps_dispatch.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: 🖥️ 📦 Dispatch Windows Deps Build
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
trigger:
|
||||
if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'requires-win-deps-build')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dispatch to windows-dependencies repo
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.DEPS_REPO_DISPATCH_ACCESS_TOKEN }}
|
||||
repository: pcsx2/pcsx2-windows-dependencies
|
||||
event-type: deps-update
|
||||
4
3rdparty/cpuinfo/README.md
vendored
4
3rdparty/cpuinfo/README.md
vendored
@@ -9,7 +9,7 @@ cpuinfo is a library to detect essential for performance optimization informatio
|
||||
## Features
|
||||
|
||||
- **Cross-platform** availability:
|
||||
- Linux, Windows, macOS, Android, and iOS operating systems
|
||||
- Linux, Windows, macOS, Android, iOS and FreeBSD operating systems
|
||||
- x86, x86-64, ARM, and ARM64 architectures
|
||||
- Modern **C/C++ interface**
|
||||
- Thread-safe
|
||||
@@ -258,6 +258,8 @@ LDFLAGS+= $(pkg-config --libs libcpuinfo)
|
||||
- [x] x86
|
||||
- [x] x86-64
|
||||
- [x] arm64
|
||||
- [x] FreeBSD
|
||||
- [x] x86-64
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
34
3rdparty/cpuinfo/include/cpuinfo.h
vendored
34
3rdparty/cpuinfo/include/cpuinfo.h
vendored
@@ -353,6 +353,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_palm_cove = 0x0010020B,
|
||||
/** Intel Sunny Cove microarchitecture (10 nm, Ice Lake). */
|
||||
cpuinfo_uarch_sunny_cove = 0x0010020C,
|
||||
/** Intel Willow Cove microarchitecture (10 nm, Tiger Lake). */
|
||||
cpuinfo_uarch_willow_cove = 0x0010020D,
|
||||
|
||||
/** Pentium 4 with Willamette, Northwood, or Foster cores. */
|
||||
cpuinfo_uarch_willamette = 0x00100300,
|
||||
@@ -371,6 +373,10 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_goldmont = 0x00100404,
|
||||
/** Intel Goldmont Plus microarchitecture (Gemini Lake). */
|
||||
cpuinfo_uarch_goldmont_plus = 0x00100405,
|
||||
/** Intel Gracemont microarchitecture (Twin Lake). */
|
||||
cpuinfo_uarch_gracemont = 0x00100406,
|
||||
/** Intel Crestmont microarchitecture (Sierra Forest). */
|
||||
cpuinfo_uarch_crestmont = 0x00100407,
|
||||
|
||||
/** Intel Knights Ferry HPC boards. */
|
||||
cpuinfo_uarch_knights_ferry = 0x00100500,
|
||||
@@ -382,6 +388,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_knights_hill = 0x00100503,
|
||||
/** Intel Knights Mill Xeon Phi. */
|
||||
cpuinfo_uarch_knights_mill = 0x00100504,
|
||||
/** Intel Darkmont microarchitecture (e-core used in Clearwater Forest). */
|
||||
cpuinfo_uarch_darkmont = 0x00100505,
|
||||
|
||||
/** Intel/Marvell XScale series. */
|
||||
cpuinfo_uarch_xscale = 0x00100600,
|
||||
@@ -581,6 +589,22 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_avalanche = 0x0070010D,
|
||||
/** Apple A15 / M2 processor (little cores). */
|
||||
cpuinfo_uarch_blizzard = 0x0070010E,
|
||||
/** Apple A16 processor (big cores). */
|
||||
cpuinfo_uarch_everest = 0x00700200,
|
||||
/** Apple A16 processor (little cores). */
|
||||
cpuinfo_uarch_sawtooth = 0x00700201,
|
||||
/** Apple A17 processor (big cores). */
|
||||
cpuinfo_uarch_coll_everest = 0x00700202,
|
||||
/** Apple A17 processor (little cores). */
|
||||
cpuinfo_uarch_coll_sawtooth = 0x00700203,
|
||||
/** Apple A18 processor (big cores). */
|
||||
cpuinfo_uarch_tupai_everest = 0x00700204,
|
||||
/** Apple A18 processor (little cores). */
|
||||
cpuinfo_uarch_tupai_sawtooth = 0x00700205,
|
||||
/** Apple A18 pro processor (big cores). */
|
||||
cpuinfo_uarch_tahiti_everest = 0x00700206,
|
||||
/** Apple A18 pro processor (little cores). */
|
||||
cpuinfo_uarch_tahiti_sawtooth = 0x00700207,
|
||||
|
||||
/** Cavium ThunderX. */
|
||||
cpuinfo_uarch_thunderx = 0x00800100,
|
||||
@@ -1700,6 +1724,7 @@ struct cpuinfo_arm_isa {
|
||||
bool sme_b16b16;
|
||||
bool sme_f16f16;
|
||||
uint32_t svelen;
|
||||
uint32_t smelen;
|
||||
#endif
|
||||
bool rdm;
|
||||
bool fp16arith;
|
||||
@@ -2081,6 +2106,15 @@ static inline uint32_t cpuinfo_get_max_arm_sve_length(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to get the max SME vector length on ARM CPU's which support SME.
|
||||
static inline uint32_t cpuinfo_get_max_arm_sme_length(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.smelen * 8; // bytes * 8 = bit length(vector length)
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_arm_sme(void) {
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
return cpuinfo_isa.sme;
|
||||
|
||||
2
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
2
3rdparty/cpuinfo/src/arm/linux/aarch32-isa.c
vendored
@@ -149,6 +149,8 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc T310");
|
||||
} else if (chipset->series == cpuinfo_arm_chipset_series_unisoc_ums && chipset->model == 312) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: cause occasional SIGILL on Unisoc UMS312");
|
||||
} else if (chipset->vendor == cpuinfo_arm_chipset_vendor_unknown) {
|
||||
cpuinfo_log_warning("VDOT instructions disabled: unknown chipset");
|
||||
} else {
|
||||
switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
|
||||
case UINT32_C(0x4100D0B0): /* Cortex-A76 */
|
||||
|
||||
17
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
17
3rdparty/cpuinfo/src/arm/linux/aarch64-isa.c
vendored
@@ -191,4 +191,21 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
|
||||
// Mask out the SVE vector length bits
|
||||
isa->svelen = ret & PR_SVE_VL_LEN_MASK;
|
||||
}
|
||||
|
||||
#ifndef PR_SME_GET_VL
|
||||
#define PR_SME_GET_VL 64
|
||||
#endif
|
||||
|
||||
#ifndef PR_SME_VL_LEN_MASK
|
||||
#define PR_SME_VL_LEN_MASK 0xffff
|
||||
#endif
|
||||
|
||||
ret = prctl(PR_SME_GET_VL);
|
||||
if (ret < 0) {
|
||||
cpuinfo_log_warning("No SME support on this machine");
|
||||
isa->smelen = 0; // Assume no SME support if the call fails
|
||||
} else {
|
||||
// Mask out the SME vector length bits
|
||||
isa->smelen = ret & PR_SME_VL_LEN_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
56
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
56
3rdparty/cpuinfo/src/arm/mach/init.c
vendored
@@ -27,6 +27,45 @@
|
||||
#ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD
|
||||
#define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D
|
||||
#endif
|
||||
// Following are copied over from ncnn/src/cpu.cpp
|
||||
// A16
|
||||
#ifndef CPUFAMILY_ARM_EVEREST_SAWTOOTH
|
||||
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
|
||||
#endif
|
||||
// A17
|
||||
#ifndef CPUFAMILY_ARM_COLL
|
||||
#define CPUFAMILY_ARM_COLL 0x2876f5b5
|
||||
#endif
|
||||
// A18
|
||||
#ifndef CPUFAMILY_ARM_TUPAI
|
||||
#define CPUFAMILY_ARM_TUPAI 0x204526d0
|
||||
#endif
|
||||
// A18 Pro
|
||||
#ifndef CPUFAMILY_ARM_TAHITI
|
||||
#define CPUFAMILY_ARM_TAHITI 0x75d4acb9
|
||||
#endif
|
||||
// For M3/M4 we need to populate more information about
|
||||
// efficiency and perf cores.
|
||||
// M3
|
||||
#ifndef CPUFAMILY_ARM_IBIZA
|
||||
#define CPUFAMILY_ARM_IBIZA 0xfa33415e
|
||||
#endif
|
||||
// M3 Pro
|
||||
#ifndef CPUFAMILY_ARM_LOBOS
|
||||
#define CPUFAMILY_ARM_LOBOS 0x5f4dea93
|
||||
#endif
|
||||
// M3 Max
|
||||
#ifndef CPUFAMILY_ARM_PALMA
|
||||
#define CPUFAMILY_ARM_PALMA 0x72015832
|
||||
#endif
|
||||
// M4
|
||||
#ifndef CPUFAMILY_ARM_DONAN
|
||||
#define CPUFAMILY_ARM_DONAN 0x6f5129ac
|
||||
#endif
|
||||
// M4 Pro / M4 Max
|
||||
#ifndef CPUFAMILY_ARM_BRAVA
|
||||
#define CPUFAMILY_ARM_BRAVA 0x17d5b93a
|
||||
#endif
|
||||
|
||||
struct cpuinfo_arm_isa cpuinfo_isa = {
|
||||
.aes = true,
|
||||
@@ -93,6 +132,23 @@ static enum cpuinfo_uarch decode_uarch(uint32_t cpu_family, uint32_t core_index,
|
||||
case CPUFAMILY_ARM_AVALANCHE_BLIZZARD:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_everest : cpuinfo_uarch_sawtooth;
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
case CPUFAMILY_ARM_COLL:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_coll_everest : cpuinfo_uarch_coll_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TUPAI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tupai_everest : cpuinfo_uarch_tupai_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TAHITI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tahiti_everest
|
||||
: cpuinfo_uarch_tahiti_sawtooth;
|
||||
|
||||
default:
|
||||
/* Use hw.cpusubtype for detection */
|
||||
break;
|
||||
|
||||
2
3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c
vendored
2
3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c
vendored
@@ -112,7 +112,7 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
*
|
||||
* for more details.
|
||||
*/
|
||||
int ret = syscall(NR_riscv_hwprobe, pairs, pairs_count, cpu_set_size, (unsigned long*)cpu_set, 0 /* flags */);
|
||||
int ret = syscall(NR_riscv_hwprobe, pairs, pairs_count, cpu_set_size, cpu_set, 0 /* flags */);
|
||||
#else
|
||||
int ret = __riscv_hwprobe(pairs, pairs_count, cpu_set_size, (unsigned long*)cpu_set, 0 /* flags */);
|
||||
#endif
|
||||
|
||||
9
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
9
3rdparty/cpuinfo/src/x86/linux/cpuinfo.c
vendored
@@ -80,11 +80,7 @@ struct proc_cpuinfo_parser_state {
|
||||
* Decode a single line of /proc/cpuinfo information.
|
||||
* Lines have format <words-with-spaces>[ ]*:[ ]<space-separated words>
|
||||
*/
|
||||
static bool parse_line(
|
||||
const char* line_start,
|
||||
const char* line_end,
|
||||
void* context,
|
||||
uint64_t line_number) {
|
||||
static bool parse_line(const char* line_start, const char* line_end, void* context, uint64_t line_number) {
|
||||
struct proc_cpuinfo_parser_state* restrict state = context;
|
||||
/* Empty line. Skip. */
|
||||
if (line_start == line_end) {
|
||||
@@ -215,6 +211,5 @@ bool cpuinfo_x86_linux_parse_proc_cpuinfo(
|
||||
.max_processors_count = max_processors_count,
|
||||
.processors = processors,
|
||||
};
|
||||
return cpuinfo_linux_parse_multiline_file(
|
||||
"/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
|
||||
return cpuinfo_linux_parse_multiline_file("/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
|
||||
}
|
||||
|
||||
9
3rdparty/cpuinfo/src/x86/uarch.c
vendored
9
3rdparty/cpuinfo/src/x86/uarch.c
vendored
@@ -168,6 +168,9 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
case 0x7E: // Ice Lake-U
|
||||
return cpuinfo_uarch_sunny_cove;
|
||||
|
||||
case 0x8C: // Tiger U
|
||||
case 0x8D: // Tiger H
|
||||
return cpuinfo_uarch_willow_cove;
|
||||
/* Low-power cores */
|
||||
case 0x1C: // Diamondville,
|
||||
// Silverthorne,
|
||||
@@ -185,6 +188,10 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
case 0x5A: // Moorefield
|
||||
case 0x5D: // SoFIA
|
||||
return cpuinfo_uarch_silvermont;
|
||||
case 0xBE: // Twin Lake
|
||||
return cpuinfo_uarch_gracemont;
|
||||
case 0xAF: // Sierra Forest
|
||||
return cpuinfo_uarch_crestmont;
|
||||
case 0x4C: // Braswell, Cherry
|
||||
// Trail
|
||||
case 0x75: // Spreadtrum
|
||||
@@ -201,6 +208,8 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
return cpuinfo_uarch_knights_landing;
|
||||
case 0x85:
|
||||
return cpuinfo_uarch_knights_mill;
|
||||
case 0xDD: // Clearwater Forest
|
||||
return cpuinfo_uarch_darkmont;
|
||||
}
|
||||
break;
|
||||
case 0x0F:
|
||||
|
||||
116
3rdparty/cubeb/README.md
vendored
116
3rdparty/cubeb/README.md
vendored
@@ -1,7 +1,117 @@
|
||||
# libcubeb - Cross-platform Audio I/O Library
|
||||
|
||||
[](https://github.com/mozilla/cubeb/actions/workflows/build.yml)
|
||||
|
||||
See INSTALL.md for build instructions.
|
||||
`libcubeb` is a cross-platform C library for high and low-latency audio input/output. It provides a simple, consistent API for audio playback and recording across multiple platforms and audio backends. It is written in C, C++ and Rust, with a C ABI and [Rust](https://github.com/mozilla/cubeb-rs) bindings. While originally written for use in the Firefox Web browser, a number of other software projects have adopted it.
|
||||
|
||||
See [Backend Support](https://github.com/mozilla/cubeb/wiki/Backend-Support) in the wiki for the support level of each backend.
|
||||
## Features
|
||||
|
||||
Licensed under an ISC-style license. See LICENSE for details.
|
||||
- **Cross-platform support**: Windows, macOS, Linux, Android, and other platforms
|
||||
- **Versatile**: Optimized for low-latency real-time audio applications, or power efficient higher latency playback
|
||||
- **A/V sync**: Latency compensated audio clock reporting for easy audio/video synchronization
|
||||
- **Full-duplex support**: Simultaneous audio input and output, reclocked
|
||||
- **Device enumeration**: Query available audio devices
|
||||
- **Audio processing for speech**: Can use VoiceProcessing IO on recent macOS
|
||||
|
||||
## Supported Backends & status
|
||||
|
||||
| *Backend* | *Support Level* | *Platform version* | *Notes* |
|
||||
|-------------------|-----------------|--------------------|--------------------------------------------------|
|
||||
| PulseAudio (Rust) | Tier-1 | | Main Linux desktop backend |
|
||||
| AudioUnit (Rust) | Tier-1 | | Main macOS backend |
|
||||
| WASAPI | Tier-1 | Windows >= 7 | Main Windows backend |
|
||||
| AAudio | Tier-1 | Android >= 8 | Main Android backend for most devices |
|
||||
| OpenSL | Tier-1 | Android >= 2.3 | Android backend for older devices |
|
||||
| OSS | Tier-2 | | |
|
||||
| sndio | Tier-2 | | |
|
||||
| Sun | Tier-2 | | |
|
||||
| WinMM | Tier-3 | Windows XP | Was Tier-1, Firefox minimum Windows version 7. |
|
||||
| AudioTrack | Tier-3 | Android < 2.3 | Was Tier-1, Firefox minimum Android version 4.1. |
|
||||
| ALSA | Tier-3 | | |
|
||||
| JACK | Tier-3 | | |
|
||||
| KAI | Tier-3 | | |
|
||||
| PulseAudio (C) | Tier-4 | | Was Tier-1, superseded by Rust |
|
||||
| AudioUnit (C++) | Tier-4 | | Was Tier-1, superseded by Rust |
|
||||
|
||||
Tier-1: Actively maintained. Should have CI coverage. Critical for Firefox.
|
||||
|
||||
Tier-2: Actively maintained by contributors. CI coverage appreciated.
|
||||
|
||||
Tier-3: Maintainers/patches accepted. Status unclear.
|
||||
|
||||
Tier-4: Deprecated, obsolete. Scheduled to be removed.
|
||||
|
||||
Note that the support level is not a judgement of the relative merits
|
||||
of a backend, only the current state of support, which is informed
|
||||
by Firefox's needs, the responsiveness of a backend's
|
||||
maintainer, and the level of contributions to that backend.
|
||||
|
||||
## Building
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- CMake 3.15 or later
|
||||
- Non-ancient MSVC, clang or gcc, for compiling both C and C++
|
||||
- Platform-specific audio libraries (automatically detected)
|
||||
- Optional but recommended: Rust compiler to compile and link more recent backends for macOS and PulseAudio
|
||||
|
||||
### Quick build
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mozilla/cubeb.git
|
||||
cd cubeb
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
### Better build with Rust backends
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/mozilla/cubeb.git
|
||||
cd cubeb
|
||||
cmake -B build -DBUILD_RUST_LIBS=ON
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
### Platform-Specific Notes
|
||||
|
||||
**Windows**: Supports Visual Studio 2015+ and MinGW-w64. Use `-G "Visual Studio 16 2019"` or `-G "MinGW Makefiles"`.
|
||||
|
||||
**macOS**: Requires Xcode command line tools. Audio frameworks are automatically linked.
|
||||
|
||||
**Linux**: Development packages for desired backends:
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install libpulse-dev libasound2-dev libjack-dev
|
||||
|
||||
# Fedora/RHEL
|
||||
sudo dnf install pulseaudio-libs-devel alsa-lib-devel jack-audio-connection-kit-devel
|
||||
```
|
||||
|
||||
**Android**: Use with Android NDK. AAudio requires API level 26+.
|
||||
|
||||
## Testing
|
||||
|
||||
Run the test suite:
|
||||
```bash
|
||||
cd build
|
||||
ctest
|
||||
```
|
||||
|
||||
Use the interactive test tool:
|
||||
```bash
|
||||
./cubeb-test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under an ISC-style license. See [LICENSE](LICENSE) for details.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please see the [contribution guidelines](CONTRIBUTING.md) and check the [issue tracker](https://github.com/mozilla/cubeb/issues).
|
||||
|
||||
## Links
|
||||
|
||||
- [GitHub Repository](https://github.com/mozilla/cubeb)
|
||||
- [API Documentation](https://mozilla.github.io/cubeb/)
|
||||
|
||||
97
3rdparty/cubeb/include/cubeb/cubeb.h
vendored
97
3rdparty/cubeb/include/cubeb/cubeb.h
vendored
@@ -49,6 +49,7 @@ extern "C" {
|
||||
output_params.channels = 2;
|
||||
output_params.layout = CUBEB_LAYOUT_UNDEFINED;
|
||||
output_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
output_params.input_params = CUBEB_INPUT_PROCESSING_PARAM_NONE;
|
||||
|
||||
rv = cubeb_get_min_latency(app_ctx, &output_params, &latency_frames);
|
||||
if (rv != CUBEB_OK) {
|
||||
@@ -62,6 +63,7 @@ extern "C" {
|
||||
input_params.channels = 1;
|
||||
input_params.layout = CUBEB_LAYOUT_UNDEFINED;
|
||||
input_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
input_params.input_params = CUBEB_INPUT_PROCESSING_PARAM_NONE;
|
||||
|
||||
cubeb_stream * stm;
|
||||
rv = cubeb_stream_init(app_ctx, &stm, "Example Stream 1",
|
||||
@@ -193,39 +195,39 @@ typedef uint32_t cubeb_channel_layout;
|
||||
// Some common layout definitions.
|
||||
enum {
|
||||
CUBEB_LAYOUT_UNDEFINED = 0, // Indicate the speaker's layout is undefined.
|
||||
CUBEB_LAYOUT_MONO = (uint32_t)CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_MONO_LFE = (uint32_t)CUBEB_LAYOUT_MONO | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_STEREO = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT,
|
||||
CUBEB_LAYOUT_STEREO_LFE = (uint32_t)CUBEB_LAYOUT_STEREO | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_MONO = CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_MONO_LFE = CUBEB_LAYOUT_MONO | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_STEREO = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT,
|
||||
CUBEB_LAYOUT_STEREO_LFE = CUBEB_LAYOUT_STEREO | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F =
|
||||
(uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT | (uint32_t)CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_3F_LFE = (uint32_t)CUBEB_LAYOUT_3F | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_3F_LFE = CUBEB_LAYOUT_3F | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_2F1 =
|
||||
(uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT | (uint32_t)CHANNEL_BACK_CENTER,
|
||||
CUBEB_LAYOUT_2F1_LFE = (uint32_t)CUBEB_LAYOUT_2F1 | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F1 = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_FRONT_CENTER | (uint32_t)CHANNEL_BACK_CENTER,
|
||||
CUBEB_LAYOUT_3F1_LFE = (uint32_t)CUBEB_LAYOUT_3F1 | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_2F2 = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_SIDE_LEFT | (uint32_t)CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_2F2_LFE = (uint32_t)CUBEB_LAYOUT_2F2 | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_QUAD = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_BACK_LEFT | (uint32_t)CHANNEL_BACK_RIGHT,
|
||||
CUBEB_LAYOUT_QUAD_LFE = (uint32_t)CUBEB_LAYOUT_QUAD | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F2 = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_FRONT_CENTER | (uint32_t)CHANNEL_SIDE_LEFT |
|
||||
(uint32_t)CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_3F2_LFE = (uint32_t)CUBEB_LAYOUT_3F2 | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F2_BACK = (uint32_t)CUBEB_LAYOUT_QUAD | (uint32_t)CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_3F2_LFE_BACK = (uint32_t)CUBEB_LAYOUT_3F2_BACK | (uint32_t)CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F3R_LFE = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_FRONT_CENTER | (uint32_t)CHANNEL_LOW_FREQUENCY |
|
||||
(uint32_t)CHANNEL_BACK_CENTER | (uint32_t)CHANNEL_SIDE_LEFT |
|
||||
(uint32_t)CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_3F4_LFE = (uint32_t)CHANNEL_FRONT_LEFT | (uint32_t)CHANNEL_FRONT_RIGHT |
|
||||
(uint32_t)CHANNEL_FRONT_CENTER | (uint32_t)CHANNEL_LOW_FREQUENCY |
|
||||
(uint32_t)CHANNEL_BACK_LEFT | (uint32_t)CHANNEL_BACK_RIGHT |
|
||||
(uint32_t)CHANNEL_SIDE_LEFT | (uint32_t)CHANNEL_SIDE_RIGHT,
|
||||
CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_CENTER,
|
||||
CUBEB_LAYOUT_2F1_LFE = CUBEB_LAYOUT_2F1 | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER,
|
||||
CUBEB_LAYOUT_3F1_LFE = CUBEB_LAYOUT_3F1 | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_2F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_2F2_LFE = CUBEB_LAYOUT_2F2 | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_QUAD = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT,
|
||||
CUBEB_LAYOUT_QUAD_LFE = CUBEB_LAYOUT_QUAD | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_FRONT_CENTER | CHANNEL_SIDE_LEFT |
|
||||
CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_3F2_LFE = CUBEB_LAYOUT_3F2 | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F2_BACK = CUBEB_LAYOUT_QUAD | CHANNEL_FRONT_CENTER,
|
||||
CUBEB_LAYOUT_3F2_LFE_BACK = CUBEB_LAYOUT_3F2_BACK | CHANNEL_LOW_FREQUENCY,
|
||||
CUBEB_LAYOUT_3F3R_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
|
||||
CHANNEL_BACK_CENTER | CHANNEL_SIDE_LEFT |
|
||||
CHANNEL_SIDE_RIGHT,
|
||||
CUBEB_LAYOUT_3F4_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
|
||||
CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
|
||||
CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT |
|
||||
CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT,
|
||||
};
|
||||
|
||||
/** Miscellaneous stream preferences. */
|
||||
@@ -279,7 +281,10 @@ typedef struct {
|
||||
cubeb_channel_layout
|
||||
layout; /**< Requested channel layout. This must be consistent with the
|
||||
provided channels. CUBEB_LAYOUT_UNDEFINED if unknown */
|
||||
cubeb_stream_prefs prefs; /**< Requested preferences. */
|
||||
cubeb_stream_prefs prefs; /**< Requested preferences. */
|
||||
cubeb_input_processing_params input_params; /**< Requested input processing
|
||||
params. Ignored for output streams. At present, only supported on the
|
||||
WASAPI backend; others should use cubeb_set_input_processing_params. */
|
||||
} cubeb_stream_params;
|
||||
|
||||
/** Audio device description */
|
||||
@@ -414,6 +419,13 @@ typedef struct {
|
||||
size_t count; /**< Device count in collection. */
|
||||
} cubeb_device_collection;
|
||||
|
||||
/** Array of compiled backends returned by `cubeb_get_backend_names`. */
|
||||
typedef struct {
|
||||
const char * const *
|
||||
names; /**< Array of strings representing backend names. */
|
||||
size_t count; /**< Length of the array. */
|
||||
} cubeb_backend_names;
|
||||
|
||||
/** User supplied data callback.
|
||||
- Calling other cubeb functions from this callback is unsafe.
|
||||
- The code in the callback should be non-blocking.
|
||||
@@ -454,6 +466,8 @@ typedef void (*cubeb_device_changed_callback)(void * user_ptr);
|
||||
|
||||
/**
|
||||
* User supplied callback called when the underlying device collection changed.
|
||||
* This callback will be called when devices are added or removed from the
|
||||
* system, or when the default device changes for the specified device type.
|
||||
* @param context A pointer to the cubeb context.
|
||||
* @param user_ptr The pointer passed to
|
||||
* cubeb_register_device_collection_changed. */
|
||||
@@ -485,17 +499,18 @@ CUBEB_EXPORT int
|
||||
cubeb_init(cubeb ** context, char const * context_name,
|
||||
char const * backend_name);
|
||||
|
||||
/** Returns a list of backend names which can be supplid to cubeb_init().
|
||||
Array is null-terminated. */
|
||||
CUBEB_EXPORT const char**
|
||||
cubeb_get_backend_names();
|
||||
|
||||
/** Get a read-only string identifying this context's current backend.
|
||||
@param context A pointer to the cubeb context.
|
||||
@retval Read-only string identifying current backend. */
|
||||
CUBEB_EXPORT char const *
|
||||
cubeb_get_backend_id(cubeb * context);
|
||||
|
||||
/** Get a read-only array of strings identifying available backends.
|
||||
These can be passed as `backend_name` parameter to `cubeb_init`.
|
||||
@retval Struct containing the array with backend names. */
|
||||
CUBEB_EXPORT cubeb_backend_names
|
||||
cubeb_get_backend_names();
|
||||
|
||||
/** Get the maximum possible number of channels.
|
||||
@param context A pointer to the cubeb context.
|
||||
@param max_channels The maximum number of channels.
|
||||
@@ -674,7 +689,7 @@ cubeb_stream_get_current_device(cubeb_stream * stm,
|
||||
application is accessing audio input. When all inputs are muted they can
|
||||
prove to the user that the application is not actively capturing any input.
|
||||
@param stream the stream for which to set input mute state
|
||||
@param muted whether the input should mute or not
|
||||
@param mute whether the input should mute or not
|
||||
@retval CUBEB_OK
|
||||
@retval CUBEB_ERROR_INVALID_PARAMETER if this stream does not have an input
|
||||
device
|
||||
@@ -745,14 +760,16 @@ cubeb_device_collection_destroy(cubeb * context,
|
||||
cubeb_device_collection * collection);
|
||||
|
||||
/** Registers a callback which is called when the system detects
|
||||
a new device or a device is removed.
|
||||
a new device or a device is removed, or when the default device
|
||||
changes for the specified device type.
|
||||
@param context
|
||||
@param devtype device type to include. Different callbacks and user pointers
|
||||
can be registered for each devtype. The hybrid devtype
|
||||
`CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT` is also valid
|
||||
and will register the provided callback and user pointer in both
|
||||
sides.
|
||||
@param callback a function called whenever the system device list changes.
|
||||
@param callback a function called whenever the system device list changes,
|
||||
including when default devices change.
|
||||
Passing NULL allow to unregister a function. You have to unregister
|
||||
first before you register a new callback.
|
||||
@param user_ptr pointer to user specified data which will be present in
|
||||
|
||||
125
3rdparty/cubeb/src/cubeb.c
vendored
125
3rdparty/cubeb/src/cubeb.c
vendored
@@ -31,6 +31,10 @@ struct cubeb_stream {
|
||||
int
|
||||
pulse_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_PULSE_RUST)
|
||||
int
|
||||
pulse_rust_init(cubeb ** contet, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_JACK)
|
||||
int
|
||||
jack_init(cubeb ** context, char const * context_name);
|
||||
@@ -43,6 +47,10 @@ alsa_init(cubeb ** context, char const * context_name);
|
||||
int
|
||||
audiounit_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_AUDIOUNIT_RUST)
|
||||
int
|
||||
audiounit_rust_init(cubeb ** contet, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_WINMM)
|
||||
int
|
||||
winmm_init(cubeb ** context, char const * context_name);
|
||||
@@ -55,10 +63,30 @@ wasapi_init(cubeb ** context, char const * context_name);
|
||||
int
|
||||
sndio_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_SUN)
|
||||
int
|
||||
sun_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_OPENSL)
|
||||
int
|
||||
opensl_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_OSS)
|
||||
int
|
||||
oss_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_AAUDIO)
|
||||
int
|
||||
aaudio_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
int
|
||||
audiotrack_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
#if defined(USE_KAI)
|
||||
int
|
||||
kai_init(cubeb ** context, char const * context_name);
|
||||
#endif
|
||||
|
||||
static int
|
||||
validate_stream_params(cubeb_stream_params * input_stream_params,
|
||||
@@ -123,6 +151,10 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
if (!strcmp(backend_name, "pulse")) {
|
||||
#if defined(USE_PULSE)
|
||||
init_oneshot = pulse_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "pulse-rust")) {
|
||||
#if defined(USE_PULSE_RUST)
|
||||
init_oneshot = pulse_rust_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "jack")) {
|
||||
#if defined(USE_JACK)
|
||||
@@ -135,6 +167,10 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
} else if (!strcmp(backend_name, "audiounit")) {
|
||||
#if defined(USE_AUDIOUNIT)
|
||||
init_oneshot = audiounit_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "audiounit-rust")) {
|
||||
#if defined(USE_AUDIOUNIT_RUST)
|
||||
init_oneshot = audiounit_rust_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "wasapi")) {
|
||||
#if defined(USE_WASAPI)
|
||||
@@ -147,10 +183,30 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
} else if (!strcmp(backend_name, "sndio")) {
|
||||
#if defined(USE_SNDIO)
|
||||
init_oneshot = sndio_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "sun")) {
|
||||
#if defined(USE_SUN)
|
||||
init_oneshot = sun_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "opensl")) {
|
||||
#if defined(USE_OPENSL)
|
||||
init_oneshot = opensl_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "oss")) {
|
||||
#if defined(USE_OSS)
|
||||
init_oneshot = oss_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "aaudio")) {
|
||||
#if defined(USE_AAUDIO)
|
||||
init_oneshot = aaudio_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "audiotrack")) {
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
init_oneshot = audiotrack_init;
|
||||
#endif
|
||||
} else if (!strcmp(backend_name, "kai")) {
|
||||
#if defined(USE_KAI)
|
||||
init_oneshot = kai_init;
|
||||
#endif
|
||||
} else {
|
||||
/* Already set */
|
||||
@@ -163,6 +219,9 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
* to override all other choices
|
||||
*/
|
||||
init_oneshot,
|
||||
#if defined(USE_PULSE_RUST)
|
||||
pulse_rust_init,
|
||||
#endif
|
||||
#if defined(USE_PULSE)
|
||||
pulse_init,
|
||||
#endif
|
||||
@@ -178,6 +237,9 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
#if defined(USE_OSS)
|
||||
oss_init,
|
||||
#endif
|
||||
#if defined(USE_AUDIOUNIT_RUST)
|
||||
audiounit_rust_init,
|
||||
#endif
|
||||
#if defined(USE_AUDIOUNIT)
|
||||
audiounit_init,
|
||||
#endif
|
||||
@@ -189,6 +251,18 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
#endif
|
||||
#if defined(USE_SUN)
|
||||
sun_init,
|
||||
#endif
|
||||
#if defined(USE_AAUDIO)
|
||||
aaudio_init,
|
||||
#endif
|
||||
#if defined(USE_OPENSL)
|
||||
opensl_init,
|
||||
#endif
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
audiotrack_init,
|
||||
#endif
|
||||
#if defined(USE_KAI)
|
||||
kai_init,
|
||||
#endif
|
||||
};
|
||||
int i;
|
||||
@@ -214,13 +288,26 @@ cubeb_init(cubeb ** context, char const * context_name,
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
const char**
|
||||
char const *
|
||||
cubeb_get_backend_id(cubeb * context)
|
||||
{
|
||||
if (!context) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return context->ops->get_backend_id(context);
|
||||
}
|
||||
|
||||
cubeb_backend_names
|
||||
cubeb_get_backend_names()
|
||||
{
|
||||
static const char* backend_names[] = {
|
||||
static const char * const backend_names[] = {
|
||||
#if defined(USE_PULSE)
|
||||
"pulse",
|
||||
#endif
|
||||
#if defined(USE_PULSE_RUST)
|
||||
"pulse-rust",
|
||||
#endif
|
||||
#if defined(USE_JACK)
|
||||
"jack",
|
||||
#endif
|
||||
@@ -230,6 +317,9 @@ cubeb_get_backend_names()
|
||||
#if defined(USE_AUDIOUNIT)
|
||||
"audiounit",
|
||||
#endif
|
||||
#if defined(USE_AUDIOUNIT_RUST)
|
||||
"audiounit-rust",
|
||||
#endif
|
||||
#if defined(USE_WASAPI)
|
||||
"wasapi",
|
||||
#endif
|
||||
@@ -239,23 +329,30 @@ cubeb_get_backend_names()
|
||||
#if defined(USE_SNDIO)
|
||||
"sndio",
|
||||
#endif
|
||||
#if defined(USE_SUN)
|
||||
"sun",
|
||||
#endif
|
||||
#if defined(USE_OPENSL)
|
||||
"opensl",
|
||||
#endif
|
||||
#if defined(USE_OSS)
|
||||
"oss",
|
||||
#endif
|
||||
NULL,
|
||||
#if defined(USE_AAUDIO)
|
||||
"aaudio",
|
||||
#endif
|
||||
#if defined(USE_AUDIOTRACK)
|
||||
"audiotrack",
|
||||
#endif
|
||||
#if defined(USE_KAI)
|
||||
"kai",
|
||||
#endif
|
||||
};
|
||||
|
||||
return backend_names;
|
||||
}
|
||||
|
||||
char const *
|
||||
cubeb_get_backend_id(cubeb * context)
|
||||
{
|
||||
if (!context) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return context->ops->get_backend_id(context);
|
||||
return (cubeb_backend_names){
|
||||
.names = backend_names,
|
||||
.count = NELEMS(backend_names),
|
||||
};
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
17
3rdparty/cubeb/src/cubeb_audiounit.cpp
vendored
17
3rdparty/cubeb/src/cubeb_audiounit.cpp
vendored
@@ -213,12 +213,19 @@ struct cubeb_stream {
|
||||
cubeb_device_changed_callback device_changed_callback = nullptr;
|
||||
owned_critical_section device_changed_callback_lock;
|
||||
/* Stream creation parameters */
|
||||
cubeb_stream_params input_stream_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
cubeb_stream_params input_stream_params = {CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
cubeb_stream_params output_stream_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
cubeb_stream_params output_stream_params = {
|
||||
CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
device_info input_device;
|
||||
device_info output_device;
|
||||
/* Format descriptions */
|
||||
|
||||
161
3rdparty/cubeb/src/cubeb_log.cpp
vendored
161
3rdparty/cubeb/src/cubeb_log.cpp
vendored
@@ -16,8 +16,8 @@
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static std::atomic<cubeb_log_level> g_cubeb_log_level;
|
||||
static std::atomic<cubeb_log_callback> g_cubeb_log_callback;
|
||||
std::atomic<cubeb_log_level> g_cubeb_log_level;
|
||||
std::atomic<cubeb_log_callback> g_cubeb_log_callback;
|
||||
|
||||
/** The maximum size of a log message, after having been formatted. */
|
||||
const size_t CUBEB_LOG_MESSAGE_MAX_SIZE = 256;
|
||||
@@ -32,6 +32,133 @@ cubeb_noop_log_callback(char const * /* fmt */, ...)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This wraps an inline buffer, that represents a log message, that must be
|
||||
* null-terminated.
|
||||
* This class should not use system calls or other potentially blocking code.
|
||||
*/
|
||||
class cubeb_log_message {
|
||||
public:
|
||||
cubeb_log_message() { *storage = '\0'; }
|
||||
cubeb_log_message(char const str[CUBEB_LOG_MESSAGE_MAX_SIZE])
|
||||
{
|
||||
size_t length = strlen(str);
|
||||
/* paranoia against malformed message */
|
||||
assert(length < CUBEB_LOG_MESSAGE_MAX_SIZE);
|
||||
if (length > CUBEB_LOG_MESSAGE_MAX_SIZE - 1) {
|
||||
return;
|
||||
}
|
||||
PodCopy(storage, str, length);
|
||||
storage[length] = '\0';
|
||||
}
|
||||
char const * get() { return storage; }
|
||||
|
||||
private:
|
||||
char storage[CUBEB_LOG_MESSAGE_MAX_SIZE]{};
|
||||
};
|
||||
|
||||
/** Lock-free asynchronous logger, made so that logging from a
|
||||
* real-time audio callback does not block the audio thread. */
|
||||
class cubeb_async_logger {
|
||||
public:
|
||||
/* This is thread-safe since C++11 */
|
||||
static cubeb_async_logger & get()
|
||||
{
|
||||
static cubeb_async_logger instance;
|
||||
return instance;
|
||||
}
|
||||
void push(char const str[CUBEB_LOG_MESSAGE_MAX_SIZE])
|
||||
{
|
||||
cubeb_log_message msg(str);
|
||||
auto * owned_queue = msg_queue.load();
|
||||
// Check if the queue is being deallocated. If not, grab ownership. If yes,
|
||||
// return, the message won't be logged.
|
||||
if (!owned_queue ||
|
||||
!msg_queue.compare_exchange_strong(owned_queue, nullptr)) {
|
||||
return;
|
||||
}
|
||||
owned_queue->enqueue(msg);
|
||||
// Return ownership.
|
||||
msg_queue.store(owned_queue);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
assert(logging_thread.get_id() == std::thread::id());
|
||||
logging_thread = std::thread([this]() {
|
||||
CUBEB_REGISTER_THREAD("cubeb_log");
|
||||
while (!shutdown_thread) {
|
||||
cubeb_log_message msg;
|
||||
while (msg_queue_consumer.load()->dequeue(&msg, 1)) {
|
||||
cubeb_log_internal_no_format(msg.get());
|
||||
}
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(CUBEB_LOG_BATCH_PRINT_INTERVAL_MS));
|
||||
}
|
||||
CUBEB_UNREGISTER_THREAD();
|
||||
});
|
||||
}
|
||||
// Tell the underlying queue the producer thread has changed, so it does not
|
||||
// assert in debug. This should be called with the thread stopped.
|
||||
void reset_producer_thread()
|
||||
{
|
||||
if (msg_queue) {
|
||||
msg_queue.load()->reset_thread_ids();
|
||||
}
|
||||
}
|
||||
void start()
|
||||
{
|
||||
auto * queue =
|
||||
new lock_free_queue<cubeb_log_message>(CUBEB_LOG_MESSAGE_QUEUE_DEPTH);
|
||||
msg_queue.store(queue);
|
||||
msg_queue_consumer.store(queue);
|
||||
shutdown_thread = false;
|
||||
run();
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
assert(((g_cubeb_log_callback == cubeb_noop_log_callback) ||
|
||||
!g_cubeb_log_callback) &&
|
||||
"Only call stop after logging has been disabled.");
|
||||
shutdown_thread = true;
|
||||
if (logging_thread.get_id() != std::thread::id()) {
|
||||
logging_thread.join();
|
||||
logging_thread = std::thread();
|
||||
auto * owned_queue = msg_queue.load();
|
||||
// Check if the queue is being used. If not, grab ownership. If yes,
|
||||
// try again shortly. At this point, the logging thread has been joined,
|
||||
// so nothing is going to dequeue.
|
||||
// If there is a valid pointer here, then the real-time audio thread that
|
||||
// logs won't attempt to write into the queue, and instead drop the
|
||||
// message.
|
||||
while (!msg_queue.compare_exchange_weak(owned_queue, nullptr)) {
|
||||
}
|
||||
delete owned_queue;
|
||||
msg_queue_consumer.store(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cubeb_async_logger() {}
|
||||
~cubeb_async_logger()
|
||||
{
|
||||
assert(logging_thread.get_id() == std::thread::id() &&
|
||||
(g_cubeb_log_callback == cubeb_noop_log_callback ||
|
||||
!g_cubeb_log_callback));
|
||||
if (msg_queue.load()) {
|
||||
delete msg_queue.load();
|
||||
}
|
||||
}
|
||||
/** This is quite a big data structure, but is only instantiated if the
|
||||
* asynchronous logger is used. The two pointers point to the same object, but
|
||||
* the first one can be temporarily null when a message is being enqueued. */
|
||||
std::atomic<lock_free_queue<cubeb_log_message> *> msg_queue = {nullptr};
|
||||
|
||||
std::atomic<lock_free_queue<cubeb_log_message> *> msg_queue_consumer = {
|
||||
nullptr};
|
||||
std::atomic<bool> shutdown_thread = {false};
|
||||
std::thread logging_thread;
|
||||
};
|
||||
|
||||
void
|
||||
cubeb_log_internal(char const * file, uint32_t line, char const * fmt, ...)
|
||||
{
|
||||
@@ -49,6 +176,29 @@ cubeb_log_internal_no_format(const char * msg)
|
||||
g_cubeb_log_callback.load()(msg);
|
||||
}
|
||||
|
||||
void
|
||||
cubeb_async_log(char const * fmt, ...)
|
||||
{
|
||||
// This is going to copy a 256 bytes array around, which is fine.
|
||||
// We don't want to allocate memory here, because this is made to
|
||||
// be called from a real-time callback.
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char msg[CUBEB_LOG_MESSAGE_MAX_SIZE];
|
||||
vsnprintf(msg, CUBEB_LOG_MESSAGE_MAX_SIZE, fmt, args);
|
||||
cubeb_async_logger::get().push(msg);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
cubeb_async_log_reset_threads(void)
|
||||
{
|
||||
if (!g_cubeb_log_callback) {
|
||||
return;
|
||||
}
|
||||
cubeb_async_logger::get().reset_producer_thread();
|
||||
}
|
||||
|
||||
void
|
||||
cubeb_log_set(cubeb_log_level log_level, cubeb_log_callback log_callback)
|
||||
{
|
||||
@@ -57,8 +207,15 @@ cubeb_log_set(cubeb_log_level log_level, cubeb_log_callback log_callback)
|
||||
// nullptr, to prevent a TOCTOU race between checking the pointer
|
||||
if (log_callback && log_level != CUBEB_LOG_DISABLED) {
|
||||
g_cubeb_log_callback = log_callback;
|
||||
if (log_level == CUBEB_LOG_VERBOSE) {
|
||||
cubeb_async_logger::get().start();
|
||||
}
|
||||
} else if (!log_callback || CUBEB_LOG_DISABLED) {
|
||||
g_cubeb_log_callback = cubeb_noop_log_callback;
|
||||
// This returns once the thread has joined.
|
||||
// This is safe even if CUBEB_LOG_VERBOSE was not set; the thread will
|
||||
// simply not be joinable.
|
||||
cubeb_async_logger::get().stop();
|
||||
} else {
|
||||
assert(false && "Incorrect parameters passed to cubeb_log_set");
|
||||
}
|
||||
|
||||
18
3rdparty/cubeb/src/cubeb_log.h
vendored
18
3rdparty/cubeb/src/cubeb_log.h
vendored
@@ -39,7 +39,12 @@ cubeb_log_get_callback(void);
|
||||
void
|
||||
cubeb_log_internal_no_format(const char * msg);
|
||||
void
|
||||
cubeb_log_internal(const char * filename, uint32_t line, const char * fmt, ...);
|
||||
cubeb_log_internal(const char * filename, uint32_t line, const char * fmt, ...)
|
||||
PRINTF_FORMAT(3, 4);
|
||||
void
|
||||
cubeb_async_log(const char * fmt, ...) PRINTF_FORMAT(1, 2);
|
||||
void
|
||||
cubeb_async_log_reset_threads(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -55,9 +60,16 @@ cubeb_log_internal(const char * filename, uint32_t line, const char * fmt, ...);
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ALOG_INTERNAL(level, fmt, ...) \
|
||||
do { \
|
||||
if (cubeb_log_get_level() >= level && cubeb_log_get_callback()) { \
|
||||
cubeb_async_log(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Asynchronous logging macros to log in real-time callbacks. */
|
||||
/* Should not be used on android due to the use of global/static variables. */
|
||||
#define ALOGV(msg, ...) LOG_INTERNAL(CUBEB_LOG_VERBOSE, msg, ##__VA_ARGS__)
|
||||
#define ALOG(msg, ...) LOG_INTERNAL(CUBEB_LOG_NORMAL, msg, ##__VA_ARGS__)
|
||||
#define ALOGV(msg, ...) ALOG_INTERNAL(CUBEB_LOG_VERBOSE, msg, ##__VA_ARGS__)
|
||||
#define ALOG(msg, ...) ALOG_INTERNAL(CUBEB_LOG_NORMAL, msg, ##__VA_ARGS__)
|
||||
|
||||
#endif // CUBEB_LOG
|
||||
|
||||
6
3rdparty/cubeb/src/cubeb_resampler.cpp
vendored
6
3rdparty/cubeb/src/cubeb_resampler.cpp
vendored
@@ -371,3 +371,9 @@ cubeb_resampler_latency(cubeb_resampler * resampler)
|
||||
{
|
||||
return resampler->latency();
|
||||
}
|
||||
|
||||
cubeb_resampler_stats
|
||||
cubeb_resampler_stats_get(cubeb_resampler * resampler)
|
||||
{
|
||||
return resampler->stats();
|
||||
}
|
||||
|
||||
14
3rdparty/cubeb/src/cubeb_resampler.h
vendored
14
3rdparty/cubeb/src/cubeb_resampler.h
vendored
@@ -84,6 +84,20 @@ cubeb_resampler_destroy(cubeb_resampler * resampler);
|
||||
long
|
||||
cubeb_resampler_latency(cubeb_resampler * resampler);
|
||||
|
||||
/**
|
||||
* Test-only introspection API to ensure that there is no buffering
|
||||
* buildup when resampling.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t input_input_buffer_size;
|
||||
size_t input_output_buffer_size;
|
||||
size_t output_input_buffer_size;
|
||||
size_t output_output_buffer_size;
|
||||
} cubeb_resampler_stats;
|
||||
|
||||
cubeb_resampler_stats
|
||||
cubeb_resampler_stats_get(cubeb_resampler * resampler);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
92
3rdparty/cubeb/src/cubeb_resampler_internal.h
vendored
92
3rdparty/cubeb/src/cubeb_resampler_internal.h
vendored
@@ -56,6 +56,7 @@ struct cubeb_resampler {
|
||||
virtual long fill(void * input_buffer, long * input_frames_count,
|
||||
void * output_buffer, long frames_needed) = 0;
|
||||
virtual long latency() = 0;
|
||||
virtual cubeb_resampler_stats stats() = 0;
|
||||
virtual ~cubeb_resampler() {}
|
||||
};
|
||||
|
||||
@@ -86,6 +87,16 @@ public:
|
||||
|
||||
virtual long latency() { return 0; }
|
||||
|
||||
virtual cubeb_resampler_stats stats()
|
||||
{
|
||||
cubeb_resampler_stats stats;
|
||||
stats.input_input_buffer_size = internal_input_buffer.length();
|
||||
stats.input_output_buffer_size = 0;
|
||||
stats.output_input_buffer_size = 0;
|
||||
stats.output_output_buffer_size = 0;
|
||||
return stats;
|
||||
}
|
||||
|
||||
void drop_audio_if_needed()
|
||||
{
|
||||
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
|
||||
@@ -122,6 +133,20 @@ public:
|
||||
virtual long fill(void * input_buffer, long * input_frames_count,
|
||||
void * output_buffer, long output_frames_needed);
|
||||
|
||||
virtual cubeb_resampler_stats stats()
|
||||
{
|
||||
cubeb_resampler_stats stats = {};
|
||||
if (input_processor) {
|
||||
stats.input_input_buffer_size = input_processor->input_buffer_size();
|
||||
stats.input_output_buffer_size = input_processor->output_buffer_size();
|
||||
}
|
||||
if (output_processor) {
|
||||
stats.output_input_buffer_size = output_processor->input_buffer_size();
|
||||
stats.output_output_buffer_size = output_processor->output_buffer_size();
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
virtual long latency()
|
||||
{
|
||||
if (input_processor && output_processor) {
|
||||
@@ -280,29 +305,28 @@ public:
|
||||
}
|
||||
|
||||
/** Returns the number of frames to pass in the input of the resampler to have
|
||||
* exactly `output_frame_count` resampled frames. This can return a number
|
||||
* slightly bigger than what is strictly necessary, but it guaranteed that the
|
||||
* number of output frames will be exactly equal. */
|
||||
* at least `output_frame_count` resampled frames. */
|
||||
uint32_t input_needed_for_output(int32_t output_frame_count) const
|
||||
{
|
||||
assert(output_frame_count >= 0); // Check overflow
|
||||
int32_t unresampled_frames_left =
|
||||
samples_to_frames(resampling_in_buffer.length());
|
||||
int32_t resampled_frames_left =
|
||||
samples_to_frames(resampling_out_buffer.length());
|
||||
float input_frames_needed =
|
||||
(output_frame_count - unresampled_frames_left) * resampling_ratio -
|
||||
resampled_frames_left;
|
||||
if (input_frames_needed < 0) {
|
||||
return 0;
|
||||
}
|
||||
return (uint32_t)ceilf(input_frames_needed);
|
||||
float input_frames_needed_frac =
|
||||
static_cast<float>(output_frame_count) * resampling_ratio;
|
||||
// speex_resample()` can be irregular in its consumption of input samples.
|
||||
// Provide one more frame than the number that would be required with
|
||||
// regular consumption, to make the speex resampler behave more regularly,
|
||||
// and so predictably.
|
||||
auto input_frame_needed =
|
||||
1 + static_cast<int32_t>(ceilf(input_frames_needed_frac));
|
||||
input_frame_needed -= std::min(unresampled_frames_left, input_frame_needed);
|
||||
return input_frame_needed;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the input buffer, that contains empty space for at
|
||||
* least `frame_count` elements. This is useful so that consumer can directly
|
||||
* write into the input buffer of the resampler. The pointer returned is
|
||||
* adjusted so that leftover data are not overwritten.
|
||||
* least `frame_count` elements. This is useful so that consumer can
|
||||
* directly write into the input buffer of the resampler. The pointer
|
||||
* returned is adjusted so that leftover data are not overwritten.
|
||||
*/
|
||||
T * input_buffer(size_t frame_count)
|
||||
{
|
||||
@@ -312,8 +336,8 @@ public:
|
||||
return resampling_in_buffer.data() + leftover_samples;
|
||||
}
|
||||
|
||||
/** This method works with `input_buffer`, and allows to inform the processor
|
||||
how much frames have been written in the provided buffer. */
|
||||
/** This method works with `input_buffer`, and allows to inform the
|
||||
processor how much frames have been written in the provided buffer. */
|
||||
void written(size_t written_frames)
|
||||
{
|
||||
resampling_in_buffer.set_length(leftover_samples +
|
||||
@@ -331,6 +355,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
size_t input_buffer_size() const { return resampling_in_buffer.length(); }
|
||||
size_t output_buffer_size() const { return resampling_out_buffer.length(); }
|
||||
|
||||
private:
|
||||
/** Wrapper for the speex resampling functions to have a typed
|
||||
* interface. */
|
||||
@@ -359,6 +386,7 @@ private:
|
||||
output_frame_count);
|
||||
assert(rv == RESAMPLER_ERR_SUCCESS);
|
||||
}
|
||||
|
||||
/** The state for the speex resampler used internaly. */
|
||||
SpeexResamplerState * speex_resampler;
|
||||
/** Source rate / target rate. */
|
||||
@@ -371,8 +399,8 @@ private:
|
||||
auto_array<T> resampling_out_buffer;
|
||||
/** Additional latency inserted into the pipeline for synchronisation. */
|
||||
uint32_t additional_latency;
|
||||
/** When `input_buffer` is called, this allows tracking the number of samples
|
||||
that were in the buffer. */
|
||||
/** When `input_buffer` is called, this allows tracking the number of
|
||||
samples that were in the buffer. */
|
||||
uint32_t leftover_samples;
|
||||
};
|
||||
|
||||
@@ -417,8 +445,8 @@ public:
|
||||
return delay_output_buffer.data();
|
||||
}
|
||||
/** Get a pointer to the first writable location in the input buffer>
|
||||
* @parameter frames_needed the number of frames the user needs to write into
|
||||
* the buffer.
|
||||
* @parameter frames_needed the number of frames the user needs to write
|
||||
* into the buffer.
|
||||
* @returns a pointer to a location in the input buffer where #frames_needed
|
||||
* can be writen. */
|
||||
T * input_buffer(uint32_t frames_needed)
|
||||
@@ -428,8 +456,8 @@ public:
|
||||
frames_to_samples(frames_needed));
|
||||
return delay_input_buffer.data() + leftover_samples;
|
||||
}
|
||||
/** This method works with `input_buffer`, and allows to inform the processor
|
||||
how much frames have been written in the provided buffer. */
|
||||
/** This method works with `input_buffer`, and allows to inform the
|
||||
processor how much frames have been written in the provided buffer. */
|
||||
void written(size_t frames_written)
|
||||
{
|
||||
delay_input_buffer.set_length(leftover_samples +
|
||||
@@ -450,8 +478,8 @@ public:
|
||||
|
||||
return to_pop;
|
||||
}
|
||||
/** Returns the number of frames one needs to input into the delay line to get
|
||||
* #frames_needed frames back.
|
||||
/** Returns the number of frames one needs to input into the delay line to
|
||||
* get #frames_needed frames back.
|
||||
* @parameter frames_needed the number of frames one want to write into the
|
||||
* delay_line
|
||||
* @returns the number of frames one will get. */
|
||||
@@ -469,19 +497,23 @@ public:
|
||||
|
||||
void drop_audio_if_needed()
|
||||
{
|
||||
size_t available = samples_to_frames(delay_input_buffer.length());
|
||||
uint32_t available = samples_to_frames(delay_input_buffer.length());
|
||||
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
|
||||
if (available > to_keep) {
|
||||
ALOGV("Dropping %u frames", available - to_keep);
|
||||
|
||||
delay_input_buffer.pop(nullptr, frames_to_samples(available - to_keep));
|
||||
}
|
||||
}
|
||||
|
||||
size_t input_buffer_size() const { return delay_input_buffer.length(); }
|
||||
size_t output_buffer_size() const { return delay_output_buffer.length(); }
|
||||
|
||||
private:
|
||||
/** The length, in frames, of this delay line */
|
||||
uint32_t length;
|
||||
/** When `input_buffer` is called, this allows tracking the number of samples
|
||||
that where in the buffer. */
|
||||
/** When `input_buffer` is called, this allows tracking the number of
|
||||
samples that where in the buffer. */
|
||||
uint32_t leftover_samples;
|
||||
/** The input buffer, where the delay is applied. */
|
||||
auto_array<T> delay_input_buffer;
|
||||
@@ -511,8 +543,8 @@ cubeb_resampler_create_internal(cubeb_stream * stream,
|
||||
"need at least one valid parameter pointer.");
|
||||
|
||||
/* All the streams we have have a sample rate that matches the target
|
||||
sample rate, use a no-op resampler, that simply forwards the buffers to the
|
||||
callback. */
|
||||
sample rate, use a no-op resampler, that simply forwards the buffers to
|
||||
the callback. */
|
||||
if (((input_params && input_params->rate == target_rate) &&
|
||||
(output_params && output_params->rate == target_rate)) ||
|
||||
(input_params && !output_params && (input_params->rate == target_rate)) ||
|
||||
|
||||
490
3rdparty/cubeb/src/cubeb_wasapi.cpp
vendored
490
3rdparty/cubeb/src/cubeb_wasapi.cpp
vendored
@@ -4,8 +4,12 @@
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0603
|
||||
#endif // !_WIN32_WINNT
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif // !NOMINMAX
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -37,31 +41,6 @@
|
||||
#include "cubeb_tracing.h"
|
||||
#include "cubeb_utils.h"
|
||||
|
||||
// Some people have reported glitches with IAudioClient3 capture streams:
|
||||
// http://blog.nirbheek.in/2018/03/low-latency-audio-on-windows-with.html
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1590902
|
||||
#define ALLOW_AUDIO_CLIENT_3_FOR_INPUT 0
|
||||
// IAudioClient3::GetSharedModeEnginePeriod() seem to return min latencies
|
||||
// bigger than IAudioClient::GetDevicePeriod(), which is confusing (10ms vs
|
||||
// 3ms), though the default latency is usually the same and we should use the
|
||||
// IAudioClient3 function anyway, as it's more correct
|
||||
#define USE_AUDIO_CLIENT_3_MIN_PERIOD 1
|
||||
// If this is true, we allow IAudioClient3 the creation of sessions with a
|
||||
// latency above the default one (usually 10ms).
|
||||
// Whether we should default this to true or false depend on many things:
|
||||
// -Does creating a shared IAudioClient3 session (not locked to a format)
|
||||
// actually forces all the IAudioClient(1) sessions to have the same latency?
|
||||
// I could find no proof of that.
|
||||
// -Does creating a shared IAudioClient3 session with a latency >= the default
|
||||
// one actually improve the latency (as in how late the audio is) at all?
|
||||
// -Maybe we could expose this as cubeb stream pref
|
||||
// (e.g. take priority over other apps)?
|
||||
#define ALLOW_AUDIO_CLIENT_3_LATENCY_OVER_DEFAULT 1
|
||||
// If this is true and the user specified a target latency >= the IAudioClient3
|
||||
// max one, then we reject it and fall back to IAudioClient(1). There wouldn't
|
||||
// be much point in having a low latency if that's not what the user wants.
|
||||
#define REJECT_AUDIO_CLIENT_3_LATENCY_OVER_MAX 0
|
||||
|
||||
// Windows 10 exposes the IAudioClient3 interface to create low-latency streams.
|
||||
// Copy the interface definition from audioclient.h here to make the code
|
||||
// simpler and so that we can still access IAudioClient3 via COM if cubeb was
|
||||
@@ -229,11 +208,6 @@ struct auto_stream_ref {
|
||||
cubeb_stream * stm;
|
||||
};
|
||||
|
||||
using set_mm_thread_characteristics_function =
|
||||
decltype(&AvSetMmThreadCharacteristicsW);
|
||||
using revert_mm_thread_characteristics_function =
|
||||
decltype(&AvRevertMmThreadCharacteristics);
|
||||
|
||||
extern cubeb_ops const wasapi_ops;
|
||||
|
||||
static com_heap_ptr<wchar_t>
|
||||
@@ -304,8 +278,8 @@ wasapi_enumerate_devices_internal(cubeb * context, cubeb_device_type type,
|
||||
static int
|
||||
wasapi_device_collection_destroy(cubeb * ctx,
|
||||
cubeb_device_collection * collection);
|
||||
static char const *
|
||||
wstr_to_utf8(wchar_t const * str);
|
||||
static std::unique_ptr<char const[]>
|
||||
wstr_to_utf8(LPCWSTR str);
|
||||
static std::unique_ptr<wchar_t const[]>
|
||||
utf8_to_wstr(char const * str);
|
||||
|
||||
@@ -314,6 +288,15 @@ utf8_to_wstr(char const * str);
|
||||
class wasapi_collection_notification_client;
|
||||
class monitor_device_notifications;
|
||||
|
||||
typedef enum {
|
||||
/* Clear options */
|
||||
CUBEB_AUDIO_CLIENT2_NONE,
|
||||
/* Use AUDCLNT_STREAMOPTIONS_RAW */
|
||||
CUBEB_AUDIO_CLIENT2_RAW,
|
||||
/* Use CUBEB_STREAM_PREF_COMMUNICATIONS */
|
||||
CUBEB_AUDIO_CLIENT2_VOICE
|
||||
} AudioClient2Option;
|
||||
|
||||
struct cubeb {
|
||||
cubeb_ops const * ops = &wasapi_ops;
|
||||
owned_critical_section lock;
|
||||
@@ -331,13 +314,6 @@ struct cubeb {
|
||||
nullptr;
|
||||
void * output_collection_changed_user_ptr = nullptr;
|
||||
UINT64 performance_counter_frequency;
|
||||
/* Library dynamically opened to increase the render thread priority, and
|
||||
the two function pointers we need. */
|
||||
HMODULE mmcss_module = nullptr;
|
||||
set_mm_thread_characteristics_function set_mm_thread_characteristics =
|
||||
nullptr;
|
||||
revert_mm_thread_characteristics_function revert_mm_thread_characteristics =
|
||||
nullptr;
|
||||
};
|
||||
|
||||
class wasapi_endpoint_notification_client;
|
||||
@@ -360,20 +336,33 @@ struct cubeb_stream {
|
||||
/* Mixer pameters. We need to convert the input stream to this
|
||||
samplerate/channel layout, as WASAPI does not resample nor upmix
|
||||
itself. */
|
||||
cubeb_stream_params input_mix_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
cubeb_stream_params input_mix_params = {CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
cubeb_stream_params output_mix_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
cubeb_stream_params output_mix_params = {CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
/* Stream parameters. This is what the client requested,
|
||||
* and what will be presented in the callback. */
|
||||
cubeb_stream_params input_stream_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
cubeb_stream_params input_stream_params = {CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
cubeb_stream_params output_stream_params = {CUBEB_SAMPLE_FLOAT32NE, 0, 0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE};
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
cubeb_stream_params output_stream_params = {
|
||||
CUBEB_SAMPLE_FLOAT32NE,
|
||||
0,
|
||||
0,
|
||||
CUBEB_LAYOUT_UNDEFINED,
|
||||
CUBEB_STREAM_PREF_NONE,
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NONE};
|
||||
/* A MMDevice role for this stream: either communication or console here. */
|
||||
ERole role;
|
||||
/* True if this stream will transport voice-data. */
|
||||
@@ -662,6 +651,10 @@ public:
|
||||
LPCWSTR device_id)
|
||||
{
|
||||
LOG("collection: Audio device default changed, id = %S.", device_id);
|
||||
|
||||
/* Default device changes count as device collection changes */
|
||||
monitor_notifications.notify(flow);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -772,7 +765,7 @@ public:
|
||||
LPCWSTR device_id)
|
||||
{
|
||||
LOG("endpoint: Audio device default changed flow=%d role=%d "
|
||||
"new_device_id=%ws.",
|
||||
"new_device_id=%S.",
|
||||
flow, role, device_id);
|
||||
|
||||
/* we only support a single stream type for now. */
|
||||
@@ -783,11 +776,13 @@ public:
|
||||
DWORD last_change_ms = timeGetTime() - last_device_change;
|
||||
bool same_device = default_device_id && device_id &&
|
||||
wcscmp(default_device_id.get(), device_id) == 0;
|
||||
LOG("endpoint: Audio device default changed last_change=%u same_device=%d",
|
||||
LOG("endpoint: Audio device default changed last_change=%lu same_device=%d",
|
||||
last_change_ms, same_device);
|
||||
if (last_change_ms > DEVICE_CHANGE_DEBOUNCE_MS || !same_device) {
|
||||
if (device_id) {
|
||||
default_device_id.reset(_wcsdup(device_id));
|
||||
wchar_t * new_device_id = new wchar_t[wcslen(device_id) + 1];
|
||||
wcscpy(new_device_id, device_id);
|
||||
default_device_id.reset(new_device_id);
|
||||
} else {
|
||||
default_device_id.reset();
|
||||
}
|
||||
@@ -863,16 +858,12 @@ intern_device_id(cubeb * ctx, wchar_t const * id)
|
||||
|
||||
auto_lock lock(ctx->lock);
|
||||
|
||||
char const * tmp = wstr_to_utf8(id);
|
||||
std::unique_ptr<char const[]> tmp = wstr_to_utf8(id);
|
||||
if (!tmp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char const * interned = cubeb_strings_intern(ctx->device_ids, tmp);
|
||||
|
||||
free((void *)tmp);
|
||||
|
||||
return interned;
|
||||
return cubeb_strings_intern(ctx->device_ids, tmp.get());
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -977,7 +968,7 @@ refill(cubeb_stream * stm, void * input_buffer, long input_frames_count,
|
||||
cubeb_resampler_fill(stm->resampler.get(), input_buffer,
|
||||
&input_frames_count, dest, output_frames_needed);
|
||||
if (out_frames < 0) {
|
||||
ALOGV("Callback refill error: %d", out_frames);
|
||||
ALOGV("Callback refill error: %ld", out_frames);
|
||||
wasapi_state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
|
||||
return out_frames;
|
||||
}
|
||||
@@ -1263,8 +1254,8 @@ refill_callback_duplex(cubeb_stream * stm)
|
||||
XASSERT(has_input(stm) && has_output(stm));
|
||||
|
||||
if (stm->input_stream_params.prefs & CUBEB_STREAM_PREF_LOOPBACK) {
|
||||
HRESULT rv = get_input_buffer(stm);
|
||||
if (FAILED(rv)) {
|
||||
rv = get_input_buffer(stm);
|
||||
if (!rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1274,7 +1265,6 @@ refill_callback_duplex(cubeb_stream * stm)
|
||||
|
||||
rv = get_output_buffer(stm, output_buffer, output_frames);
|
||||
if (!rv) {
|
||||
hr = stm->render_client->ReleaseBuffer(output_frames, 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1291,9 +1281,11 @@ refill_callback_duplex(cubeb_stream * stm)
|
||||
|
||||
stm->total_output_frames += output_frames;
|
||||
|
||||
ALOGV("in: %zu, out: %zu, missing: %ld, ratio: %f", stm->total_input_frames,
|
||||
stm->total_output_frames,
|
||||
static_cast<long>(stm->total_output_frames) - stm->total_input_frames,
|
||||
ALOGV("in: %llu, out: %llu, missing: %ld, ratio: %f",
|
||||
(unsigned long long)stm->total_input_frames,
|
||||
(unsigned long long)stm->total_output_frames,
|
||||
static_cast<long long>(stm->total_output_frames) -
|
||||
static_cast<long long>(stm->total_input_frames),
|
||||
static_cast<float>(stm->total_output_frames) / stm->total_input_frames);
|
||||
|
||||
long got;
|
||||
@@ -1438,8 +1430,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
|
||||
/* We could consider using "Pro Audio" here for WebAudio and
|
||||
maybe WebRTC. */
|
||||
mmcss_handle =
|
||||
stm->context->set_mm_thread_characteristics(L"Audio", &mmcss_task_index);
|
||||
mmcss_handle = AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index);
|
||||
if (!mmcss_handle) {
|
||||
/* This is not fatal, but we might glitch under heavy load. */
|
||||
LOG("Unable to use mmcss to bump the render thread priority: %lx",
|
||||
@@ -1519,8 +1510,8 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
is_playing = stm->refill_callback(stm);
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 3: { /* input available */
|
||||
HRESULT rv = get_input_buffer(stm);
|
||||
if (FAILED(rv)) {
|
||||
bool rv = get_input_buffer(stm);
|
||||
if (!rv) {
|
||||
is_playing = false;
|
||||
continue;
|
||||
}
|
||||
@@ -1532,8 +1523,11 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG("case %lu not handled in render loop.", waitResult);
|
||||
XASSERT(false);
|
||||
LOG("render_loop: waitResult=%lu (lastError=%lu) unhandled, exiting",
|
||||
waitResult, GetLastError());
|
||||
is_playing = false;
|
||||
hr = E_FAIL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1547,7 +1541,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
}
|
||||
|
||||
if (mmcss_handle) {
|
||||
stm->context->revert_mm_thread_characteristics(mmcss_handle);
|
||||
AvRevertMmThreadCharacteristics(mmcss_handle);
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
@@ -1560,18 +1554,6 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
void
|
||||
wasapi_destroy(cubeb * context);
|
||||
|
||||
HANDLE WINAPI
|
||||
set_mm_thread_characteristics_noop(LPCWSTR, LPDWORD mmcss_task_index)
|
||||
{
|
||||
return (HANDLE)1;
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
revert_mm_thread_characteristics_noop(HANDLE mmcss_handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
register_notification_client(cubeb_stream * stm)
|
||||
{
|
||||
@@ -1807,31 +1789,6 @@ wasapi_init(cubeb ** context, char const * context_name)
|
||||
ctx->performance_counter_frequency = 0;
|
||||
}
|
||||
|
||||
ctx->mmcss_module = LoadLibraryW(L"Avrt.dll");
|
||||
|
||||
bool success = false;
|
||||
if (ctx->mmcss_module) {
|
||||
ctx->set_mm_thread_characteristics =
|
||||
reinterpret_cast<set_mm_thread_characteristics_function>(
|
||||
GetProcAddress(ctx->mmcss_module, "AvSetMmThreadCharacteristicsW"));
|
||||
ctx->revert_mm_thread_characteristics =
|
||||
reinterpret_cast<revert_mm_thread_characteristics_function>(
|
||||
GetProcAddress(ctx->mmcss_module,
|
||||
"AvRevertMmThreadCharacteristics"));
|
||||
success = ctx->set_mm_thread_characteristics &&
|
||||
ctx->revert_mm_thread_characteristics;
|
||||
}
|
||||
if (!success) {
|
||||
// This is not a fatal error, but we might end up glitching when
|
||||
// the system is under high load.
|
||||
LOG("Could not load avrt.dll or fetch AvSetMmThreadCharacteristicsW "
|
||||
"AvRevertMmThreadCharacteristics: %lx",
|
||||
GetLastError());
|
||||
ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop;
|
||||
ctx->revert_mm_thread_characteristics =
|
||||
&revert_mm_thread_characteristics_noop;
|
||||
}
|
||||
|
||||
*context = ctx;
|
||||
|
||||
return CUBEB_OK;
|
||||
@@ -1839,7 +1796,6 @@ wasapi_init(cubeb ** context, char const * context_name)
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum ShutdownPhase { OnStop, OnDestroy };
|
||||
|
||||
bool
|
||||
stop_and_join_render_thread(cubeb_stream * stm)
|
||||
@@ -1855,16 +1811,7 @@ stop_and_join_render_thread(cubeb_stream * stm)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Wait five seconds for the rendering thread to return. It's supposed to
|
||||
* check its event loop very often, five seconds is rather conservative.
|
||||
* Note: 5*1s loop to work around timer sleep issues on pre-Windows 8. */
|
||||
DWORD r;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
r = WaitForSingleObject(stm->thread, 1000);
|
||||
if (r == WAIT_OBJECT_0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DWORD r = WaitForSingleObject(stm->thread, INFINITE);
|
||||
if (r != WAIT_OBJECT_0) {
|
||||
LOG("stop_and_join_render_thread: WaitForSingleObject on thread failed: "
|
||||
"%lx, %lx",
|
||||
@@ -1888,10 +1835,6 @@ wasapi_destroy(cubeb * context)
|
||||
}
|
||||
}
|
||||
|
||||
if (context->mmcss_module) {
|
||||
FreeLibrary(context->mmcss_module);
|
||||
}
|
||||
|
||||
delete context;
|
||||
}
|
||||
|
||||
@@ -1949,44 +1892,6 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params,
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
#if USE_AUDIO_CLIENT_3_MIN_PERIOD
|
||||
// This is unreliable as we can't know the actual mixer format cubeb will
|
||||
// ask for later on (nor we can branch on ALLOW_AUDIO_CLIENT_3_FOR_INPUT),
|
||||
// and the min latency can change based on that.
|
||||
com_ptr<IAudioClient3> client3;
|
||||
hr = device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, NULL,
|
||||
client3.receive_vpp());
|
||||
if (SUCCEEDED(hr)) {
|
||||
WAVEFORMATEX * mix_format = nullptr;
|
||||
hr = client3->GetMixFormat(&mix_format);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
uint32_t default_period = 0, fundamental_period = 0, min_period = 0,
|
||||
max_period = 0;
|
||||
hr = client3->GetSharedModeEnginePeriod(mix_format, &default_period,
|
||||
&fundamental_period, &min_period,
|
||||
&max_period);
|
||||
|
||||
auto sample_rate = mix_format->nSamplesPerSec;
|
||||
CoTaskMemFree(mix_format);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Print values in the same format as IAudioDevice::GetDevicePeriod()
|
||||
REFERENCE_TIME min_period_rt(frames_to_hns(sample_rate, min_period));
|
||||
REFERENCE_TIME default_period_rt(
|
||||
frames_to_hns(sample_rate, default_period));
|
||||
LOG("default device period: %I64d, minimum device period: %I64d",
|
||||
default_period_rt, min_period_rt);
|
||||
|
||||
*latency_frames = hns_to_frames(params.rate, min_period_rt);
|
||||
|
||||
LOG("Minimum latency in frames: %u", *latency_frames);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
com_ptr<IAudioClient> client;
|
||||
hr = device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
|
||||
client.receive_vpp());
|
||||
@@ -2006,8 +1911,18 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params,
|
||||
LOG("default device period: %I64d, minimum device period: %I64d",
|
||||
default_period, minimum_period);
|
||||
|
||||
// The minimum_period is only relevant in exclusive streams.
|
||||
/* If we're on Windows 10, we can use IAudioClient3 to get minimal latency.
|
||||
Otherwise, according to the docs, the best latency we can achieve is by
|
||||
synchronizing the stream and the engine.
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/dd370871%28v=vs.85%29.aspx
|
||||
*/
|
||||
|
||||
// #ifdef _WIN32_WINNT_WIN10
|
||||
#if 0
|
||||
*latency_frames = hns_to_frames(params.rate, minimum_period);
|
||||
#else
|
||||
*latency_frames = hns_to_frames(params.rate, default_period);
|
||||
#endif
|
||||
|
||||
LOG("Minimum latency in frames: %u", *latency_frames);
|
||||
|
||||
@@ -2044,6 +1959,21 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
wasapi_get_supported_input_processing_params(
|
||||
cubeb * ctx, cubeb_input_processing_params * params)
|
||||
{
|
||||
// This is not entirely accurate -- windows doesn't document precisely what
|
||||
// AudioCategory_Communications does -- but assume that we can set all or none
|
||||
// of them.
|
||||
*params = static_cast<cubeb_input_processing_params>(
|
||||
CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_VOICE_ISOLATION);
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
waveformatex_update_derived_properties(WAVEFORMATEX * format)
|
||||
{
|
||||
@@ -2097,10 +2027,7 @@ handle_channel_layout(cubeb_stream * stm, EDataFlow direction,
|
||||
if (hr == S_FALSE) {
|
||||
/* Channel layout not supported, but WASAPI gives us a suggestion. Use it,
|
||||
and handle the eventual upmix/downmix ourselves. Ignore the subformat of
|
||||
the suggestion, since it seems to always be IEEE_FLOAT.
|
||||
This fallback doesn't update the bit depth, so if a device
|
||||
only supported bit depths cubeb doesn't support, so IAudioClient3
|
||||
streams might fail */
|
||||
the suggestion, since it seems to always be IEEE_FLOAT. */
|
||||
LOG("Using WASAPI suggested format: channels: %d", closest->nChannels);
|
||||
XASSERT(closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE);
|
||||
WAVEFORMATEXTENSIBLE * closest_pcm =
|
||||
@@ -2122,7 +2049,8 @@ handle_channel_layout(cubeb_stream * stm, EDataFlow direction,
|
||||
}
|
||||
|
||||
static int
|
||||
initialize_iaudioclient2(com_ptr<IAudioClient> & audio_client)
|
||||
initialize_iaudioclient2(com_ptr<IAudioClient> & audio_client,
|
||||
AudioClient2Option option)
|
||||
{
|
||||
com_ptr<IAudioClient2> audio_client2;
|
||||
audio_client->QueryInterface<IAudioClient2>(audio_client2.receive());
|
||||
@@ -2131,10 +2059,14 @@ initialize_iaudioclient2(com_ptr<IAudioClient> & audio_client)
|
||||
"AUDCLNT_STREAMOPTIONS_RAW.");
|
||||
return CUBEB_OK;
|
||||
}
|
||||
AudioClientProperties properties = {0};
|
||||
AudioClientProperties properties = {};
|
||||
properties.cbSize = sizeof(AudioClientProperties);
|
||||
#ifndef __MINGW32__
|
||||
properties.Options |= AUDCLNT_STREAMOPTIONS_RAW;
|
||||
if (option == CUBEB_AUDIO_CLIENT2_RAW) {
|
||||
properties.Options |= AUDCLNT_STREAMOPTIONS_RAW;
|
||||
} else if (option == CUBEB_AUDIO_CLIENT2_VOICE) {
|
||||
properties.eCategory = AudioCategory_Communications;
|
||||
}
|
||||
#endif
|
||||
HRESULT hr = audio_client2->SetClientProperties(&properties);
|
||||
if (FAILED(hr)) {
|
||||
@@ -2144,12 +2076,12 @@ initialize_iaudioclient2(com_ptr<IAudioClient> & audio_client)
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool
|
||||
initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
|
||||
cubeb_stream * stm,
|
||||
const com_heap_ptr<WAVEFORMATEX> & mix_format,
|
||||
DWORD flags, EDataFlow direction,
|
||||
REFERENCE_TIME latency_hns)
|
||||
DWORD flags, EDataFlow direction)
|
||||
{
|
||||
com_ptr<IAudioClient3> audio_client3;
|
||||
audio_client->QueryInterface<IAudioClient3>(audio_client3.receive());
|
||||
@@ -2165,22 +2097,24 @@ initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some people have reported glitches with capture streams:
|
||||
// http://blog.nirbheek.in/2018/03/low-latency-audio-on-windows-with.html
|
||||
if (direction == eCapture) {
|
||||
LOG("Audio stream is capture, not using IAudioClient3");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Possibly initialize a shared-mode stream using IAudioClient3. Initializing
|
||||
// a stream this way lets you request lower latencies, but also locks the
|
||||
// global WASAPI engine at that latency.
|
||||
// - If we request a shared-mode stream, streams created with IAudioClient
|
||||
// might have their latency adjusted to match. When the shared-mode stream
|
||||
// is closed, they'll go back to normal.
|
||||
// - If there's already a shared-mode stream running, if it created with the
|
||||
// AUDCLNT_STREAMOPTIONS_MATCH_FORMAT option, the audio engine would be
|
||||
// locked to that format, so we have to match it (a custom one would fail).
|
||||
// - We don't lock the WASAPI engine to a format, as it's antisocial towards
|
||||
// other apps, especially if we locked to a latency >= than its default.
|
||||
// - If the user requested latency is >= the default one, we might still
|
||||
// accept it (without locking the format) depending on
|
||||
// ALLOW_AUDIO_CLIENT_3_LATENCY_OVER_DEFAULT, as we might want to prioritize
|
||||
// to lower our latency over other apps
|
||||
// (there might still be latency advantages compared to IAudioDevice(1)).
|
||||
// will
|
||||
// have their latency adjusted to match. When the shared-mode stream is
|
||||
// closed, they'll go back to normal.
|
||||
// - If there's already a shared-mode stream running, then we cannot request
|
||||
// the engine change to a different latency - we have to match it.
|
||||
// - It's antisocial to lock the WASAPI engine at its default latency. If we
|
||||
// would do this, then stop and use IAudioClient instead.
|
||||
|
||||
HRESULT hr;
|
||||
uint32_t default_period = 0, fundamental_period = 0, min_period = 0,
|
||||
@@ -2192,59 +2126,28 @@ initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
|
||||
LOG("Could not get shared mode engine period: error: %lx", hr);
|
||||
return false;
|
||||
}
|
||||
uint32_t requested_latency =
|
||||
hns_to_frames(mix_format->nSamplesPerSec, latency_hns);
|
||||
#if !ALLOW_AUDIO_CLIENT_3_LATENCY_OVER_DEFAULT
|
||||
uint32_t requested_latency = stm->latency;
|
||||
if (requested_latency >= default_period) {
|
||||
LOG("Requested latency %i equal or greater than default latency %i,"
|
||||
" not using IAudioClient3",
|
||||
LOG("Requested latency %i greater than default latency %i, not using "
|
||||
"IAudioClient3",
|
||||
requested_latency, default_period);
|
||||
return false;
|
||||
}
|
||||
#elif REJECT_AUDIO_CLIENT_3_LATENCY_OVER_MAX
|
||||
if (requested_latency > max_period) {
|
||||
// Fallback to IAudioClient(1) as it's more accepting of large latencies
|
||||
LOG("Requested latency %i greater than max latency %i,"
|
||||
" not using IAudioClient3",
|
||||
requested_latency, max_period);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
LOG("Got shared mode engine period: default=%i fundamental=%i min=%i max=%i",
|
||||
default_period, fundamental_period, min_period, max_period);
|
||||
// Snap requested latency to a valid value
|
||||
uint32_t old_requested_latency = requested_latency;
|
||||
// The period is required to be a multiple of the fundamental period
|
||||
// (and >= min and <= max, which should still be true)
|
||||
requested_latency -= requested_latency % fundamental_period;
|
||||
if (requested_latency < min_period) {
|
||||
requested_latency = min_period;
|
||||
}
|
||||
// Likely unnecessary, but won't hurt
|
||||
if (requested_latency > max_period) {
|
||||
requested_latency = max_period;
|
||||
}
|
||||
requested_latency -= (requested_latency - min_period) % fundamental_period;
|
||||
if (requested_latency != old_requested_latency) {
|
||||
LOG("Requested latency %i was adjusted to %i", old_requested_latency,
|
||||
requested_latency);
|
||||
}
|
||||
|
||||
DWORD new_flags = flags;
|
||||
// Always add these flags to IAudioClient3, they might help
|
||||
// if the stream doesn't have the same format as the audio engine.
|
||||
new_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
|
||||
new_flags |= AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||
|
||||
hr = audio_client3->InitializeSharedAudioStream(new_flags, requested_latency,
|
||||
hr = audio_client3->InitializeSharedAudioStream(flags, requested_latency,
|
||||
mix_format.get(), NULL);
|
||||
// This error should be returned first even if
|
||||
// the period was locked (AUDCLNT_E_ENGINE_PERIODICITY_LOCKED)
|
||||
if (hr == AUDCLNT_E_INVALID_STREAM_FLAG) {
|
||||
LOG("Got AUDCLNT_E_INVALID_STREAM_FLAG, removing some flags");
|
||||
hr = audio_client3->InitializeSharedAudioStream(flags, requested_latency,
|
||||
mix_format.get(), NULL);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
return true;
|
||||
} else if (hr == AUDCLNT_E_ENGINE_PERIODICITY_LOCKED) {
|
||||
@@ -2256,37 +2159,22 @@ initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
|
||||
}
|
||||
|
||||
uint32_t current_period = 0;
|
||||
WAVEFORMATEX * current_format_ptr = nullptr;
|
||||
WAVEFORMATEX * current_format = nullptr;
|
||||
// We have to pass a valid WAVEFORMATEX** and not nullptr, otherwise
|
||||
// GetCurrentSharedModeEnginePeriod will return E_POINTER
|
||||
hr = audio_client3->GetCurrentSharedModeEnginePeriod(¤t_format_ptr,
|
||||
hr = audio_client3->GetCurrentSharedModeEnginePeriod(¤t_format,
|
||||
¤t_period);
|
||||
CoTaskMemFree(current_format);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not get current shared mode engine period: error: %lx", hr);
|
||||
return false;
|
||||
}
|
||||
com_heap_ptr<WAVEFORMATEX> current_format(current_format_ptr);
|
||||
if (current_format->nSamplesPerSec != mix_format->nSamplesPerSec) {
|
||||
// Unless some other external app locked the shared mode engine period
|
||||
// within our audio initialization, this is unlikely to happen, though we
|
||||
// can't respect the user selected latency, so we fallback on IAudioClient
|
||||
LOG("IAudioClient3::GetCurrentSharedModeEnginePeriod() returned a "
|
||||
"different mixer format (nSamplesPerSec) from "
|
||||
"IAudioClient::GetMixFormat(); not using IAudioClient3");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if REJECT_AUDIO_CLIENT_3_LATENCY_OVER_MAX
|
||||
// Reject IAudioClient3 if we can't respect the user target latency.
|
||||
// We don't need to check against default_latency anymore,
|
||||
// as the current_period is already the best one we could get.
|
||||
if (old_requested_latency > current_period) {
|
||||
LOG("Requested latency %i greater than currently locked shared mode "
|
||||
"latency %i, not using IAudioClient3",
|
||||
old_requested_latency, current_period);
|
||||
if (current_period >= default_period) {
|
||||
LOG("Current shared mode engine period %i too high, not using IAudioClient",
|
||||
current_period);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
hr = audio_client3->InitializeSharedAudioStream(flags, current_period,
|
||||
mix_format.get(), NULL);
|
||||
@@ -2299,6 +2187,7 @@ initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
|
||||
LOG("Could not initialize shared stream with IAudioClient3: error: %lx", hr);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DIRECTION_NAME (direction == eCapture ? "capture" : "render")
|
||||
|
||||
@@ -2322,12 +2211,6 @@ setup_wasapi_stream_one_side(cubeb_stream * stm,
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
#if ALLOW_AUDIO_CLIENT_3_FOR_INPUT
|
||||
constexpr bool allow_audio_client_3 = true;
|
||||
#else
|
||||
const bool allow_audio_client_3 = direction == eRender;
|
||||
#endif
|
||||
|
||||
stm->stream_reset_lock.assert_current_thread_owns();
|
||||
// If user doesn't specify a particular device, we can choose another one when
|
||||
// the given devid is unavailable.
|
||||
@@ -2364,14 +2247,17 @@ setup_wasapi_stream_one_side(cubeb_stream * stm,
|
||||
|
||||
/* Get a client. We will get all other interfaces we need from
|
||||
* this pointer. */
|
||||
if (allow_audio_client_3) {
|
||||
hr = device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, NULL,
|
||||
audio_client.receive_vpp());
|
||||
}
|
||||
if (!allow_audio_client_3 || hr == E_NOINTERFACE) {
|
||||
hr = device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
|
||||
audio_client.receive_vpp());
|
||||
#if 0 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1590902
|
||||
hr = device->Activate(__uuidof(IAudioClient3),
|
||||
CLSCTX_INPROC_SERVER,
|
||||
NULL, audio_client.receive_vpp());
|
||||
if (hr == E_NOINTERFACE) {
|
||||
#endif
|
||||
hr = device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
|
||||
audio_client.receive_vpp());
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not activate the device to get an audio"
|
||||
@@ -2494,21 +2380,41 @@ setup_wasapi_stream_one_side(cubeb_stream * stm,
|
||||
}
|
||||
|
||||
if (stream_params->prefs & CUBEB_STREAM_PREF_RAW) {
|
||||
if (initialize_iaudioclient2(audio_client) != CUBEB_OK) {
|
||||
if (initialize_iaudioclient2(audio_client, CUBEB_AUDIO_CLIENT2_RAW) !=
|
||||
CUBEB_OK) {
|
||||
LOG("Can't initialize an IAudioClient2, error: %lx", GetLastError());
|
||||
// This is not fatal.
|
||||
}
|
||||
} else if (direction == eCapture &&
|
||||
(stream_params->prefs & CUBEB_STREAM_PREF_VOICE) &&
|
||||
stream_params->input_params != CUBEB_INPUT_PROCESSING_PARAM_NONE) {
|
||||
if (stream_params->input_params ==
|
||||
(CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL |
|
||||
CUBEB_INPUT_PROCESSING_PARAM_VOICE_ISOLATION)) {
|
||||
if (initialize_iaudioclient2(audio_client, CUBEB_AUDIO_CLIENT2_VOICE) !=
|
||||
CUBEB_OK) {
|
||||
LOG("Can't initialize an IAudioClient2, error: %lx", GetLastError());
|
||||
// This is not fatal.
|
||||
}
|
||||
} else {
|
||||
LOG("Invalid combination of input processing params %#x",
|
||||
stream_params->input_params);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (allow_audio_client_3 &&
|
||||
initialize_iaudioclient3(audio_client, stm, mix_format, flags, direction,
|
||||
latency_hns)) {
|
||||
#if 0 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1590902
|
||||
if (initialize_iaudioclient3(audio_client, stm, mix_format, flags, direction)) {
|
||||
LOG("Initialized with IAudioClient3");
|
||||
} else {
|
||||
hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, latency_hns,
|
||||
0, mix_format.get(), NULL);
|
||||
#endif
|
||||
hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, latency_hns, 0,
|
||||
mix_format.get(), NULL);
|
||||
#if 0
|
||||
}
|
||||
|
||||
#endif
|
||||
if (FAILED(hr)) {
|
||||
LOG("Unable to initialize audio client for %s: %lx.", DIRECTION_NAME, hr);
|
||||
return CUBEB_ERROR;
|
||||
@@ -2970,6 +2876,7 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||
}
|
||||
}
|
||||
|
||||
cubeb_async_log_reset_threads();
|
||||
stm->thread =
|
||||
(HANDLE)_beginthreadex(NULL, 512 * 1024, wasapi_stream_render_loop, stm,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
|
||||
@@ -3031,7 +2938,7 @@ wasapi_stream_add_ref(cubeb_stream * stm)
|
||||
{
|
||||
XASSERT(stm);
|
||||
LONG result = InterlockedIncrement(&stm->ref_count);
|
||||
LOGV("Stream ref count incremented = %i (%p)", result, stm);
|
||||
LOGV("Stream ref count incremented = %ld (%p)", result, stm);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3041,7 +2948,7 @@ wasapi_stream_release(cubeb_stream * stm)
|
||||
XASSERT(stm);
|
||||
|
||||
LONG result = InterlockedDecrement(&stm->ref_count);
|
||||
LOGV("Stream ref count decremented = %i (%p)", result, stm);
|
||||
LOGV("Stream ref count decremented = %ld (%p)", result, stm);
|
||||
if (result == 0) {
|
||||
LOG("Stream ref count hit zero, destroying (%p)", stm);
|
||||
|
||||
@@ -3303,7 +3210,7 @@ wasapi_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static char const *
|
||||
static std::unique_ptr<char const[]>
|
||||
wstr_to_utf8(LPCWSTR str)
|
||||
{
|
||||
int size = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, NULL, NULL);
|
||||
@@ -3311,8 +3218,8 @@ wstr_to_utf8(LPCWSTR str)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char * ret = static_cast<char *>(malloc(size));
|
||||
::WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
|
||||
std::unique_ptr<char[]> ret(new char[size]);
|
||||
::WideCharToMultiByte(CP_UTF8, 0, str, -1, ret.get(), size, NULL, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3440,7 +3347,7 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
prop_variant namevar;
|
||||
hr = propstore->GetValue(PKEY_Device_FriendlyName, &namevar);
|
||||
if (SUCCEEDED(hr) && namevar.vt == VT_LPWSTR) {
|
||||
ret.friendly_name = wstr_to_utf8(namevar.pwszVal);
|
||||
ret.friendly_name = wstr_to_utf8(namevar.pwszVal).release();
|
||||
}
|
||||
if (!ret.friendly_name) {
|
||||
// This is not fatal, but a valid string is expected in all cases.
|
||||
@@ -3461,7 +3368,7 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
prop_variant instancevar;
|
||||
hr = ps->GetValue(PKEY_Device_InstanceId, &instancevar);
|
||||
if (SUCCEEDED(hr) && instancevar.vt == VT_LPWSTR) {
|
||||
ret.group_id = wstr_to_utf8(instancevar.pwszVal);
|
||||
ret.group_id = wstr_to_utf8(instancevar.pwszVal).release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3477,7 +3384,8 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
ret.preferred =
|
||||
(cubeb_device_pref)(ret.preferred | CUBEB_DEVICE_PREF_MULTIMEDIA |
|
||||
CUBEB_DEVICE_PREF_NOTIFICATION);
|
||||
} else if (defaults->is_default(flow, eCommunications, device_id.get())) {
|
||||
}
|
||||
if (defaults->is_default(flow, eCommunications, device_id.get())) {
|
||||
ret.preferred =
|
||||
(cubeb_device_pref)(ret.preferred | CUBEB_DEVICE_PREF_VOICE);
|
||||
}
|
||||
@@ -3504,7 +3412,6 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
CUBEB_DEVICE_FMT_S16NE);
|
||||
ret.default_format = CUBEB_DEVICE_FMT_F32NE;
|
||||
prop_variant fmtvar;
|
||||
WAVEFORMATEX * wfx = NULL;
|
||||
hr = propstore->GetValue(PKEY_AudioEngine_DeviceFormat, &fmtvar);
|
||||
if (SUCCEEDED(hr) && fmtvar.vt == VT_BLOB) {
|
||||
if (fmtvar.blob.cbSize == sizeof(PCMWAVEFORMAT)) {
|
||||
@@ -3514,7 +3421,8 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
ret.max_rate = ret.min_rate = ret.default_rate = pcm->wf.nSamplesPerSec;
|
||||
ret.max_channels = pcm->wf.nChannels;
|
||||
} else if (fmtvar.blob.cbSize >= sizeof(WAVEFORMATEX)) {
|
||||
wfx = reinterpret_cast<WAVEFORMATEX *>(fmtvar.blob.pBlobData);
|
||||
WAVEFORMATEX * wfx =
|
||||
reinterpret_cast<WAVEFORMATEX *>(fmtvar.blob.pBlobData);
|
||||
|
||||
if (fmtvar.blob.cbSize >= sizeof(WAVEFORMATEX) + wfx->cbSize ||
|
||||
wfx->wFormatTag == WAVE_FORMAT_PCM) {
|
||||
@@ -3524,30 +3432,9 @@ wasapi_create_device(cubeb * ctx, cubeb_device_info & ret,
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_AUDIO_CLIENT_3_MIN_PERIOD
|
||||
// Here we assume an IAudioClient3 stream will successfully
|
||||
// be initialized later (it might fail)
|
||||
#if ALLOW_AUDIO_CLIENT_3_FOR_INPUT
|
||||
constexpr bool allow_audio_client_3 = true;
|
||||
#else
|
||||
const bool allow_audio_client_3 = flow == eRender;
|
||||
#endif
|
||||
com_ptr<IAudioClient3> client3;
|
||||
uint32_t def, fun, min, max;
|
||||
if (allow_audio_client_3 && wfx &&
|
||||
SUCCEEDED(dev->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER,
|
||||
NULL, client3.receive_vpp())) &&
|
||||
SUCCEEDED(
|
||||
client3->GetSharedModeEnginePeriod(wfx, &def, &fun, &min, &max))) {
|
||||
ret.latency_lo = min;
|
||||
// This latency might actually be used as "default" and not "max" later on,
|
||||
// so we return the default (we never really want to use the max anyway)
|
||||
ret.latency_hi = def;
|
||||
} else
|
||||
#endif
|
||||
if (SUCCEEDED(dev->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
|
||||
NULL, client.receive_vpp())) &&
|
||||
SUCCEEDED(client->GetDevicePeriod(&def_period, &min_period))) {
|
||||
if (SUCCEEDED(dev->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
|
||||
NULL, client.receive_vpp())) &&
|
||||
SUCCEEDED(client->GetDevicePeriod(&def_period, &min_period))) {
|
||||
ret.latency_lo = hns_to_frames(ret.default_rate, min_period);
|
||||
ret.latency_hi = hns_to_frames(ret.default_rate, def_period);
|
||||
} else {
|
||||
@@ -3638,7 +3525,7 @@ wasapi_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
{
|
||||
return wasapi_enumerate_devices_internal(
|
||||
context, type, out,
|
||||
DEVICE_STATE_ACTIVE /*| DEVICE_STATE_DISABLED | DEVICE_STATE_UNPLUGGED*/);
|
||||
DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_UNPLUGGED);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -3656,6 +3543,14 @@ wasapi_device_collection_destroy(cubeb * /*ctx*/,
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
wasapi_set_input_processing_params(cubeb_stream * stream,
|
||||
cubeb_input_processing_params params)
|
||||
{
|
||||
LOG("Cannot set voice processing params after init. Use cubeb_stream_init.");
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int
|
||||
wasapi_register_device_collection_changed(
|
||||
cubeb * context, cubeb_device_type devtype,
|
||||
@@ -3736,7 +3631,8 @@ cubeb_ops const wasapi_ops = {
|
||||
/*.get_max_channel_count =*/wasapi_get_max_channel_count,
|
||||
/*.get_min_latency =*/wasapi_get_min_latency,
|
||||
/*.get_preferred_sample_rate =*/wasapi_get_preferred_sample_rate,
|
||||
/*.get_supported_input_processing_params =*/NULL,
|
||||
/*.get_supported_input_processing_params =*/
|
||||
wasapi_get_supported_input_processing_params,
|
||||
/*.enumerate_devices =*/wasapi_enumerate_devices,
|
||||
/*.device_collection_destroy =*/wasapi_device_collection_destroy,
|
||||
/*.destroy =*/wasapi_destroy,
|
||||
@@ -3751,7 +3647,7 @@ cubeb_ops const wasapi_ops = {
|
||||
/*.stream_set_name =*/NULL,
|
||||
/*.stream_get_current_device =*/NULL,
|
||||
/*.stream_set_input_mute =*/NULL,
|
||||
/*.stream_set_input_processing_params =*/NULL,
|
||||
/*.stream_set_input_processing_params =*/wasapi_set_input_processing_params,
|
||||
/*.stream_device_destroy =*/NULL,
|
||||
/*.stream_register_device_changed_callback =*/NULL,
|
||||
/*.register_device_collection_changed =*/
|
||||
|
||||
19
3rdparty/cubeb/subprojects/speex/arch.h
vendored
19
3rdparty/cubeb/subprojects/speex/arch.h
vendored
@@ -41,10 +41,10 @@
|
||||
#ifdef FLOATING_POINT
|
||||
#error You cannot compile as floating point and fixed point at the same time
|
||||
#endif
|
||||
#ifdef _USE_SSE
|
||||
#ifdef USE_SSE
|
||||
#error SSE is only for floating-point
|
||||
#endif
|
||||
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
|
||||
#if defined(ARM4_ASM) + defined(ARM5E_ASM) + defined(BFIN_ASM) > 1
|
||||
#error Make up your mind. What CPU do you have?
|
||||
#endif
|
||||
#ifdef VORBIS_PSYCHO
|
||||
@@ -56,10 +56,10 @@
|
||||
#ifndef FLOATING_POINT
|
||||
#error You now need to define either FIXED_POINT or FLOATING_POINT
|
||||
#endif
|
||||
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
|
||||
#if defined(ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
|
||||
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
|
||||
#endif
|
||||
#ifdef FIXED_POINT_DEBUG
|
||||
#ifdef FIXED_DEBUG
|
||||
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
|
||||
#endif
|
||||
|
||||
@@ -117,9 +117,9 @@ typedef spx_word32_t spx_sig_t;
|
||||
|
||||
#ifdef ARM5E_ASM
|
||||
#include "fixed_arm5e.h"
|
||||
#elif defined (ARM4_ASM)
|
||||
#elif defined(ARM4_ASM)
|
||||
#include "fixed_arm4.h"
|
||||
#elif defined (BFIN_ASM)
|
||||
#elif defined(BFIN_ASM)
|
||||
#include "fixed_bfin.h"
|
||||
#endif
|
||||
|
||||
@@ -177,16 +177,13 @@ typedef float spx_word32_t;
|
||||
#define ADD32(a,b) ((a)+(b))
|
||||
#define SUB32(a,b) ((a)-(b))
|
||||
#define MULT16_16_16(a,b) ((a)*(b))
|
||||
#define MULT16_32_32(a,b) ((a)*(b))
|
||||
#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b))
|
||||
#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
|
||||
|
||||
#define MULT16_32_Q11(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q13(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q14(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_32_P15(a,b) ((a)*(b))
|
||||
|
||||
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
|
||||
@@ -210,7 +207,7 @@ typedef float spx_word32_t;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
#if defined(CONFIG_TI_C54X) || defined(CONFIG_TI_C55X)
|
||||
|
||||
/* 2 on TI C5x DSP */
|
||||
#define BYTES_PER_CHAR 2
|
||||
|
||||
16
3rdparty/cubeb/subprojects/speex/fixed_generic.h
vendored
16
3rdparty/cubeb/subprojects/speex/fixed_generic.h
vendored
@@ -69,22 +69,18 @@
|
||||
|
||||
|
||||
/* result fits in 16 bits */
|
||||
#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b))))
|
||||
#define MULT16_16_16(a,b) (((spx_word16_t)(a))*((spx_word16_t)(b)))
|
||||
/* result fits in 32 bits */
|
||||
#define MULT16_32_32(a,b) (((spx_word16_t)(a))*((spx_word32_t)(b)))
|
||||
|
||||
/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */
|
||||
#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b)))
|
||||
|
||||
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
|
||||
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
|
||||
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
|
||||
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
|
||||
|
||||
#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
|
||||
#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
|
||||
|
||||
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
|
||||
#define MULT16_32_P15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MULT16_32_Q15(a,b) ADD32(MULT16_32_32(a,SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MAC16_32_Q15(c,a,b) ADD32(c,MULT16_32_Q15(a,b))
|
||||
|
||||
|
||||
#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11)))
|
||||
|
||||
90
3rdparty/cubeb/subprojects/speex/resample.c
vendored
90
3rdparty/cubeb/subprojects/speex/resample.c
vendored
@@ -46,7 +46,7 @@
|
||||
Smith, Julius O. Digital Audio Resampling Home Page
|
||||
Center for Computer Research in Music and Acoustics (CCRMA),
|
||||
Stanford University, 2007.
|
||||
Web published at http://ccrma.stanford.edu/~jos/resample/.
|
||||
Web published at https://ccrma.stanford.edu/~jos/resample/.
|
||||
|
||||
There is one main difference, though. This resampler uses cubic
|
||||
interpolation instead of linear interpolation in the above paper. This
|
||||
@@ -63,9 +63,12 @@
|
||||
|
||||
#ifdef OUTSIDE_SPEEX
|
||||
#include <stdlib.h>
|
||||
static void *speex_alloc (int size) {return calloc(size,1);}
|
||||
static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
|
||||
static void speex_free (void *ptr) {free(ptr);}
|
||||
static void *speex_alloc(int size) {return calloc(size,1);}
|
||||
static void *speex_realloc(void *ptr, int size) {return realloc(ptr, size);}
|
||||
static void speex_free(void *ptr) {free(ptr);}
|
||||
#ifndef EXPORT
|
||||
#define EXPORT
|
||||
#endif
|
||||
#include "speex_resampler.h"
|
||||
#include "arch.h"
|
||||
#else /* OUTSIDE_SPEEX */
|
||||
@@ -75,7 +78,6 @@ static void speex_free (void *ptr) {free(ptr);}
|
||||
#include "os_support.h"
|
||||
#endif /* OUTSIDE_SPEEX */
|
||||
|
||||
#include "stack_alloc.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
@@ -91,18 +93,18 @@ static void speex_free (void *ptr) {free(ptr);}
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX 4294967296U
|
||||
#define UINT32_MAX 4294967295U
|
||||
#endif
|
||||
|
||||
#ifdef _USE_SSE
|
||||
#ifdef USE_SSE
|
||||
#include "resample_sse.h"
|
||||
#endif
|
||||
|
||||
#ifdef _USE_NEON
|
||||
#ifdef USE_NEON
|
||||
#include "resample_neon.h"
|
||||
#endif
|
||||
|
||||
/* Numer of elements to allocate on the stack */
|
||||
/* Number of elements to allocate on the stack */
|
||||
#ifdef VAR_ARRAYS
|
||||
#define FIXED_STACK_ALLOC 8192
|
||||
#else
|
||||
@@ -194,16 +196,14 @@ struct FuncDef {
|
||||
int oversample;
|
||||
};
|
||||
|
||||
static const struct FuncDef _KAISER12 = {kaiser12_table, 64};
|
||||
#define KAISER12 (&_KAISER12)
|
||||
/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
|
||||
#define KAISER12 (&_KAISER12)*/
|
||||
static const struct FuncDef _KAISER10 = {kaiser10_table, 32};
|
||||
#define KAISER10 (&_KAISER10)
|
||||
static const struct FuncDef _KAISER8 = {kaiser8_table, 32};
|
||||
#define KAISER8 (&_KAISER8)
|
||||
static const struct FuncDef _KAISER6 = {kaiser6_table, 32};
|
||||
#define KAISER6 (&_KAISER6)
|
||||
static const struct FuncDef kaiser12_funcdef = {kaiser12_table, 64};
|
||||
#define KAISER12 (&kaiser12_funcdef)
|
||||
static const struct FuncDef kaiser10_funcdef = {kaiser10_table, 32};
|
||||
#define KAISER10 (&kaiser10_funcdef)
|
||||
static const struct FuncDef kaiser8_funcdef = {kaiser8_table, 32};
|
||||
#define KAISER8 (&kaiser8_funcdef)
|
||||
static const struct FuncDef kaiser6_funcdef = {kaiser6_table, 32};
|
||||
#define KAISER6 (&kaiser6_funcdef)
|
||||
|
||||
struct QualityMapping {
|
||||
int base_length;
|
||||
@@ -473,7 +473,7 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
|
||||
}
|
||||
|
||||
cubic_coef(frac, interp);
|
||||
sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1));
|
||||
sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
|
||||
sum = SATURATE32PSHR(sum, 15, 32767);
|
||||
#else
|
||||
cubic_coef(frac, interp);
|
||||
@@ -572,6 +572,7 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
|
||||
const int frac_advance = st->frac_advance;
|
||||
const spx_uint32_t den_rate = st->den_rate;
|
||||
|
||||
(void)in;
|
||||
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
|
||||
{
|
||||
out[out_stride * out_sample++] = 0;
|
||||
@@ -589,16 +590,15 @@ static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_in
|
||||
return out_sample;
|
||||
}
|
||||
|
||||
static int _muldiv(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t mul, spx_uint32_t div)
|
||||
static int multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den)
|
||||
{
|
||||
speex_assert(result);
|
||||
spx_uint32_t major = value / div;
|
||||
spx_uint32_t remainder = value % div;
|
||||
spx_uint32_t major = value / den;
|
||||
spx_uint32_t remain = value % den;
|
||||
/* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */
|
||||
if (remainder > UINT32_MAX / mul || major > UINT32_MAX / mul
|
||||
|| major * mul > UINT32_MAX - remainder * mul / div)
|
||||
if (remain > UINT32_MAX / num || major > UINT32_MAX / num
|
||||
|| major * num > UINT32_MAX - remain * num / den)
|
||||
return RESAMPLER_ERR_OVERFLOW;
|
||||
*result = remainder * mul / div + major * mul;
|
||||
*result = remain * num / den + major * num;
|
||||
return RESAMPLER_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -619,7 +619,7 @@ static int update_filter(SpeexResamplerState *st)
|
||||
{
|
||||
/* down-sampling */
|
||||
st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
|
||||
if (_muldiv(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS)
|
||||
if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS)
|
||||
goto fail;
|
||||
/* Round up to make sure we have a multiple of 8 for SSE */
|
||||
st->filt_len = ((st->filt_len-1)&(~0x7))+8;
|
||||
@@ -638,12 +638,12 @@ static int update_filter(SpeexResamplerState *st)
|
||||
st->cutoff = quality_map[st->quality].upsample_bandwidth;
|
||||
}
|
||||
|
||||
/* Choose the resampling type that requires the least amount of memory */
|
||||
#ifdef RESAMPLE_FULL_SINC_TABLE
|
||||
use_direct = 1;
|
||||
if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)
|
||||
goto fail;
|
||||
#else
|
||||
/* Choose the resampling type that requires the least amount of memory */
|
||||
use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
|
||||
&& INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
|
||||
#endif
|
||||
@@ -733,16 +733,18 @@ static int update_filter(SpeexResamplerState *st)
|
||||
{
|
||||
spx_uint32_t j;
|
||||
spx_uint32_t olen = old_length;
|
||||
spx_uint32_t start = i*st->mem_alloc_size;
|
||||
spx_uint32_t magic_samples = st->magic_samples[i];
|
||||
/*if (st->magic_samples[i])*/
|
||||
{
|
||||
/* Try and remove the magic samples as if nothing had happened */
|
||||
|
||||
/* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
|
||||
olen = old_length + 2*st->magic_samples[i];
|
||||
for (j=old_length-1+st->magic_samples[i];j--;)
|
||||
st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
|
||||
for (j=0;j<st->magic_samples[i];j++)
|
||||
st->mem[i*st->mem_alloc_size+j] = 0;
|
||||
olen = old_length + 2*magic_samples;
|
||||
for (j=old_length-1+magic_samples;j--;)
|
||||
st->mem[start+j+magic_samples] = st->mem[i*old_alloc_size+j];
|
||||
for (j=0;j<magic_samples;j++)
|
||||
st->mem[start+j] = 0;
|
||||
st->magic_samples[i] = 0;
|
||||
}
|
||||
if (st->filt_len > olen)
|
||||
@@ -750,17 +752,18 @@ static int update_filter(SpeexResamplerState *st)
|
||||
/* If the new filter length is still bigger than the "augmented" length */
|
||||
/* Copy data going backward */
|
||||
for (j=0;j<olen-1;j++)
|
||||
st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)];
|
||||
st->mem[start+(st->filt_len-2-j)] = st->mem[start+(olen-2-j)];
|
||||
/* Then put zeros for lack of anything better */
|
||||
for (;j<st->filt_len-1;j++)
|
||||
st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0;
|
||||
st->mem[start+(st->filt_len-2-j)] = 0;
|
||||
/* Adjust last_sample */
|
||||
st->last_sample[i] += (st->filt_len - olen)/2;
|
||||
} else {
|
||||
/* Put back some of the magic! */
|
||||
st->magic_samples[i] = (olen - st->filt_len)/2;
|
||||
for (j=0;j<st->filt_len-1+st->magic_samples[i];j++)
|
||||
st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
|
||||
magic_samples = (olen - st->filt_len)/2;
|
||||
for (j=0;j<st->filt_len-1+magic_samples;j++)
|
||||
st->mem[start+j] = st->mem[start+j+magic_samples];
|
||||
st->magic_samples[i] = magic_samples;
|
||||
}
|
||||
}
|
||||
} else if (st->filt_len < old_length)
|
||||
@@ -977,8 +980,7 @@ EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t cha
|
||||
const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);
|
||||
#ifdef VAR_ARRAYS
|
||||
const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC;
|
||||
VARDECL(spx_word16_t *ystack);
|
||||
ALLOC(ystack, ylen, spx_word16_t);
|
||||
spx_word16_t ystack[ylen];
|
||||
#else
|
||||
const unsigned int ylen = FIXED_STACK_ALLOC;
|
||||
spx_word16_t ystack[FIXED_STACK_ALLOC];
|
||||
@@ -1093,7 +1095,7 @@ EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_r
|
||||
*out_rate = st->out_rate;
|
||||
}
|
||||
|
||||
static inline spx_uint32_t _gcd(spx_uint32_t a, spx_uint32_t b)
|
||||
static inline spx_uint32_t compute_gcd(spx_uint32_t a, spx_uint32_t b)
|
||||
{
|
||||
while (b != 0)
|
||||
{
|
||||
@@ -1123,7 +1125,7 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r
|
||||
st->num_rate = ratio_num;
|
||||
st->den_rate = ratio_den;
|
||||
|
||||
fact = _gcd (st->num_rate, st->den_rate);
|
||||
fact = compute_gcd(st->num_rate, st->den_rate);
|
||||
|
||||
st->num_rate /= fact;
|
||||
st->den_rate /= fact;
|
||||
@@ -1132,7 +1134,7 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r
|
||||
{
|
||||
for (i=0;i<st->nb_channels;i++)
|
||||
{
|
||||
if (_muldiv(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS)
|
||||
if (multiply_frac(&st->samp_frac_num[i],st->samp_frac_num[i],st->den_rate,old_den) != RESAMPLER_ERR_SUCCESS)
|
||||
return RESAMPLER_ERR_OVERFLOW;
|
||||
/* Safety net */
|
||||
if (st->samp_frac_num[i] >= st->den_rate)
|
||||
|
||||
168
3rdparty/cubeb/subprojects/speex/resample_neon.h
vendored
168
3rdparty/cubeb/subprojects/speex/resample_neon.h
vendored
@@ -36,14 +36,26 @@
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#ifdef __thumb2__
|
||||
#if defined(__aarch64__)
|
||||
static inline int32_t saturate_32bit_to_16bit(int32_t a) {
|
||||
int32_t ret;
|
||||
asm ("fmov s0, %w[a]\n"
|
||||
"sqxtn h0, s0\n"
|
||||
"sxtl v0.4s, v0.4h\n"
|
||||
"fmov %w[ret], s0\n"
|
||||
: [ret] "=r" (ret)
|
||||
: [a] "r" (a)
|
||||
: "v0" );
|
||||
return ret;
|
||||
}
|
||||
#elif defined(__thumb2__)
|
||||
static inline int32_t saturate_32bit_to_16bit(int32_t a) {
|
||||
int32_t ret;
|
||||
asm ("ssat %[ret], #16, %[a]"
|
||||
: [ret] "=&r" (ret)
|
||||
: [ret] "=r" (ret)
|
||||
: [a] "r" (a)
|
||||
: );
|
||||
return ret;
|
||||
@@ -54,7 +66,7 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
|
||||
asm ("vmov.s32 d0[0], %[a]\n"
|
||||
"vqmovn.s32 d0, q0\n"
|
||||
"vmov.s16 %[ret], d0[0]\n"
|
||||
: [ret] "=&r" (ret)
|
||||
: [ret] "=r" (ret)
|
||||
: [a] "r" (a)
|
||||
: "q0");
|
||||
return ret;
|
||||
@@ -64,7 +76,63 @@ static inline int32_t saturate_32bit_to_16bit(int32_t a) {
|
||||
#define WORD2INT(x) (saturate_32bit_to_16bit(x))
|
||||
|
||||
#define OVERRIDE_INNER_PRODUCT_SINGLE
|
||||
/* Only works when len % 4 == 0 */
|
||||
/* Only works when len % 4 == 0 and len >= 4 */
|
||||
#if defined(__aarch64__)
|
||||
static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
|
||||
{
|
||||
int32_t ret;
|
||||
uint32_t remainder = len % 16;
|
||||
len = len - remainder;
|
||||
|
||||
asm volatile (" cmp %w[len], #0\n"
|
||||
" b.ne 1f\n"
|
||||
" ld1 {v16.4h}, [%[b]], #8\n"
|
||||
" ld1 {v20.4h}, [%[a]], #8\n"
|
||||
" subs %w[remainder], %w[remainder], #4\n"
|
||||
" smull v0.4s, v16.4h, v20.4h\n"
|
||||
" b.ne 4f\n"
|
||||
" b 5f\n"
|
||||
"1:"
|
||||
" ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
|
||||
" ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
|
||||
" subs %w[len], %w[len], #16\n"
|
||||
" smull v0.4s, v16.4h, v20.4h\n"
|
||||
" smlal v0.4s, v17.4h, v21.4h\n"
|
||||
" smlal v0.4s, v18.4h, v22.4h\n"
|
||||
" smlal v0.4s, v19.4h, v23.4h\n"
|
||||
" b.eq 3f\n"
|
||||
"2:"
|
||||
" ld1 {v16.4h, v17.4h, v18.4h, v19.4h}, [%[b]], #32\n"
|
||||
" ld1 {v20.4h, v21.4h, v22.4h, v23.4h}, [%[a]], #32\n"
|
||||
" subs %w[len], %w[len], #16\n"
|
||||
" smlal v0.4s, v16.4h, v20.4h\n"
|
||||
" smlal v0.4s, v17.4h, v21.4h\n"
|
||||
" smlal v0.4s, v18.4h, v22.4h\n"
|
||||
" smlal v0.4s, v19.4h, v23.4h\n"
|
||||
" b.ne 2b\n"
|
||||
"3:"
|
||||
" cmp %w[remainder], #0\n"
|
||||
" b.eq 5f\n"
|
||||
"4:"
|
||||
" ld1 {v18.4h}, [%[b]], #8\n"
|
||||
" ld1 {v22.4h}, [%[a]], #8\n"
|
||||
" subs %w[remainder], %w[remainder], #4\n"
|
||||
" smlal v0.4s, v18.4h, v22.4h\n"
|
||||
" b.ne 4b\n"
|
||||
"5:"
|
||||
" saddlv d0, v0.4s\n"
|
||||
" sqxtn s0, d0\n"
|
||||
" sqrshrn h0, s0, #15\n"
|
||||
" sxtl v0.4s, v0.4h\n"
|
||||
" fmov %w[ret], s0\n"
|
||||
: [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
[len] "+r" (len), [remainder] "+r" (remainder)
|
||||
:
|
||||
: "cc", "v0",
|
||||
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len)
|
||||
{
|
||||
int32_t ret;
|
||||
@@ -112,33 +180,104 @@ static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, u
|
||||
" vqmovn.s64 d0, q0\n"
|
||||
" vqrshrn.s32 d0, q0, #15\n"
|
||||
" vmov.s16 %[ret], d0[0]\n"
|
||||
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
: [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
[len] "+r" (len), [remainder] "+r" (remainder)
|
||||
:
|
||||
: "cc", "q0",
|
||||
"d16", "d17", "d18", "d19",
|
||||
"d20", "d21", "d22", "d23");
|
||||
"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23");
|
||||
|
||||
return ret;
|
||||
}
|
||||
#elif defined(FLOATING_POINT)
|
||||
#endif // !defined(__aarch64__)
|
||||
|
||||
#elif defined(FLOATING_POINT)
|
||||
#if defined(__aarch64__)
|
||||
static inline int32_t saturate_float_to_16bit(float a) {
|
||||
int32_t ret;
|
||||
asm ("fcvtas s1, %s[a]\n"
|
||||
"sqxtn h1, s1\n"
|
||||
"sxtl v1.4s, v1.4h\n"
|
||||
"fmov %w[ret], s1\n"
|
||||
: [ret] "=r" (ret)
|
||||
: [a] "w" (a)
|
||||
: "v1");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int32_t saturate_float_to_16bit(float a) {
|
||||
int32_t ret;
|
||||
asm ("vmov.f32 d0[0], %[a]\n"
|
||||
"vcvt.s32.f32 d0, d0, #15\n"
|
||||
"vqrshrn.s32 d0, q0, #15\n"
|
||||
"vmov.s16 %[ret], d0[0]\n"
|
||||
: [ret] "=&r" (ret)
|
||||
: [ret] "=r" (ret)
|
||||
: [a] "r" (a)
|
||||
: "q0");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef WORD2INT
|
||||
#define WORD2INT(x) (saturate_float_to_16bit(x))
|
||||
|
||||
#define OVERRIDE_INNER_PRODUCT_SINGLE
|
||||
/* Only works when len % 4 == 0 */
|
||||
/* Only works when len % 4 == 0 and len >= 4 */
|
||||
#if defined(__aarch64__)
|
||||
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
|
||||
{
|
||||
float ret;
|
||||
uint32_t remainder = len % 16;
|
||||
len = len - remainder;
|
||||
|
||||
asm volatile (" cmp %w[len], #0\n"
|
||||
" b.ne 1f\n"
|
||||
" ld1 {v16.4s}, [%[b]], #16\n"
|
||||
" ld1 {v20.4s}, [%[a]], #16\n"
|
||||
" subs %w[remainder], %w[remainder], #4\n"
|
||||
" fmul v1.4s, v16.4s, v20.4s\n"
|
||||
" b.ne 4f\n"
|
||||
" b 5f\n"
|
||||
"1:"
|
||||
" ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
|
||||
" ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
|
||||
" subs %w[len], %w[len], #16\n"
|
||||
" fmul v1.4s, v16.4s, v20.4s\n"
|
||||
" fmul v2.4s, v17.4s, v21.4s\n"
|
||||
" fmul v3.4s, v18.4s, v22.4s\n"
|
||||
" fmul v4.4s, v19.4s, v23.4s\n"
|
||||
" b.eq 3f\n"
|
||||
"2:"
|
||||
" ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [%[b]], #64\n"
|
||||
" ld1 {v20.4s, v21.4s, v22.4s, v23.4s}, [%[a]], #64\n"
|
||||
" subs %w[len], %w[len], #16\n"
|
||||
" fmla v1.4s, v16.4s, v20.4s\n"
|
||||
" fmla v2.4s, v17.4s, v21.4s\n"
|
||||
" fmla v3.4s, v18.4s, v22.4s\n"
|
||||
" fmla v4.4s, v19.4s, v23.4s\n"
|
||||
" b.ne 2b\n"
|
||||
"3:"
|
||||
" fadd v16.4s, v1.4s, v2.4s\n"
|
||||
" fadd v17.4s, v3.4s, v4.4s\n"
|
||||
" cmp %w[remainder], #0\n"
|
||||
" fadd v1.4s, v16.4s, v17.4s\n"
|
||||
" b.eq 5f\n"
|
||||
"4:"
|
||||
" ld1 {v18.4s}, [%[b]], #16\n"
|
||||
" ld1 {v22.4s}, [%[a]], #16\n"
|
||||
" subs %w[remainder], %w[remainder], #4\n"
|
||||
" fmla v1.4s, v18.4s, v22.4s\n"
|
||||
" b.ne 4b\n"
|
||||
"5:"
|
||||
" faddp v1.4s, v1.4s, v1.4s\n"
|
||||
" faddp %[ret].4s, v1.4s, v1.4s\n"
|
||||
: [ret] "=w" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
[len] "+r" (len), [remainder] "+r" (remainder)
|
||||
:
|
||||
: "cc", "v1", "v2", "v3", "v4",
|
||||
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
|
||||
{
|
||||
float ret;
|
||||
@@ -191,11 +330,12 @@ static inline float inner_product_single(const float *a, const float *b, unsigne
|
||||
" vadd.f32 d0, d0, d1\n"
|
||||
" vpadd.f32 d0, d0, d0\n"
|
||||
" vmov.f32 %[ret], d0[0]\n"
|
||||
: [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
: [ret] "=r" (ret), [a] "+r" (a), [b] "+r" (b),
|
||||
[len] "+l" (len), [remainder] "+l" (remainder)
|
||||
:
|
||||
: "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8",
|
||||
"q9", "q10", "q11");
|
||||
: "cc", "q0", "q1", "q2", "q3",
|
||||
"q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11");
|
||||
return ret;
|
||||
}
|
||||
#endif // defined(__aarch64__)
|
||||
#endif
|
||||
|
||||
@@ -71,7 +71,7 @@ static inline float interpolate_product_single(const float *a, const float *b, u
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _USE_SSE2
|
||||
#ifdef USE_SSE2
|
||||
#include <emmintrin.h>
|
||||
#define OVERRIDE_INNER_PRODUCT_DOUBLE
|
||||
|
||||
|
||||
31
3rdparty/d3d12memalloc/CHANGELOG.md
vendored
31
3rdparty/d3d12memalloc/CHANGELOG.md
vendored
@@ -1,3 +1,34 @@
|
||||
# 3.0.1 (2025-05-08)
|
||||
|
||||
- Fixed macros `D3D12MA_RECOMMENDED_ALLOCATOR_FLAGS`, `D3D12MA_RECOMMENDED_POOL_FLAGS` (#73).
|
||||
|
||||
# 3.0.0 (2025-05-05)
|
||||
|
||||
It has been a long time since the previous official release, so hopefully everyone has been using the latest code from "master" branch, which is always maintained in a good state, not the old version. For completeness, here is the list of changes since v2.0.1. The major version number has changed, so there are some compatibility-breaking changes, but the basic API stays the same and is mostly backward-compatible.
|
||||
|
||||
- Added helper structs: `CALLOCATION_DESC`, `CPOOL_DESC`, `CVIRTUAL_BLOCK_DESC`, `CVIRTUAL_ALLOCATION_DESC`.
|
||||
- Added macros: `D3D12MA_RECOMMENDED_ALLOCATOR_FLAGS`, `D3D12MA_RECOMMENDED_HEAP_FLAGS`, `D3D12MA_RECOMMENDED_POOL_FLAGS`.
|
||||
- Added functions: `Allocator::CreateResource3`, `CreateAliasingResource2`.
|
||||
- They support parameters: `D3D12_BARRIER_LAYOUT InitialLayout`, `const DXGI_FORMAT* pCastableFormats`.
|
||||
- They require recent DirectX 12 Agility SDK. To use them, `ID3D12Device10` must be available.
|
||||
To use non-empty list of castable formats, `ID3D12Device12` must be available.
|
||||
- Added support for GPU Upload Heaps (`D3D12_HEAP_TYPE_GPU_UPLOAD`).
|
||||
- Requires recent DirectX 12 Agility SDK. Support on the user's machine is available only when supported by the motherboard, GPU, drivers, and enabled as "Resizable BAR" in UEFI settings. It can be queried using new `Allocator::IsGPUUploadHeapSupported` function.
|
||||
- `TotalStatistics::HeapType` array was extended from 4 to 5 elements.
|
||||
- Added missing function `Allocator::CreateAliasingResource1`.
|
||||
- Added `POOL_DESC::ResidencyPriority` member.
|
||||
- Removed `Allocation::WasZeroInitialized` function. It wasn't fully implemented anyway.
|
||||
- Added `POOL_FLAG_ALWAYS_COMMITTED`.
|
||||
- Added a heuristic that prefers creating small buffers as committed to save memory.
|
||||
- It is enabled by default. It can be disabled by new flag `ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED`.
|
||||
- Macro `D3D12MA_OPTIONS16_SUPPORTED` is no longer exposed in the header or Cmake script.
|
||||
It is defined automatically based on the Agility SDK version.
|
||||
- Added macro `D3D12MA_DEBUG_LOG`, which can be used to log unfreed allocations.
|
||||
- Many improvements in the documentation, including new chapters: "Frequently asked questions", "Optimal resource allocation".
|
||||
- Countless fixes and improvements, including performance optimizations, compatibility with various compilers, tests.
|
||||
- Major changes in the Cmake script.
|
||||
- Fixes in "GpuMemDumpVis.py" script.
|
||||
|
||||
# 2.0.1 (2022-04-05)
|
||||
|
||||
A maintenance release with some bug fixes and improvements. There are no changes in the library API.
|
||||
|
||||
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
2
3rdparty/d3d12memalloc/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Copyright (c) 2019-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
9
3rdparty/d3d12memalloc/README.md
vendored
9
3rdparty/d3d12memalloc/README.md
vendored
@@ -10,10 +10,6 @@ Easy to integrate memory allocation library for Direct3D 12.
|
||||
|
||||
**Product page:** [D3D12 Memory Allocator on GPUOpen](https://gpuopen.com/gaming-product/d3d12-memory-allocator/)
|
||||
|
||||
**Build status:**
|
||||
|
||||
Windows: [](https://ci.appveyor.com/project/adam-sawicki-amd/d3d12memoryallocator)
|
||||
|
||||
[](http://isitmaintained.com/project/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator "Average time to resolve an issue")
|
||||
|
||||
# Problem
|
||||
@@ -91,7 +87,7 @@ With this one function call:
|
||||
|
||||
# Binaries
|
||||
|
||||
The release comes with precompiled binary executable for "D3D12Sample" application which contains test suite. It is compiled using Visual Studio 2019, so it requires appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If its launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), "x64" version.
|
||||
The release comes with precompiled binary executable for "D3D12Sample" application which contains test suite. It is compiled using Visual Studio 2022, so it requires appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If its launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170), "X64" version.
|
||||
|
||||
# Copyright notice
|
||||
|
||||
@@ -113,7 +109,8 @@ For more information see [NOTICES.txt](NOTICES.txt).
|
||||
|
||||
- **[Qt Project](https://github.com/qt)**
|
||||
- **[Ghost of Tsushima: Director's Cut PC](https://www.youtube.com/watch?v=cPKBDbCYctc&t=698s)** - Information avaliable in 11:38 of credits
|
||||
- **[Godot Engine](https://github.com/godotengine/godot/)** - multi-platform 2D and 3D game engine. License: MIT.
|
||||
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
|
||||
- **[Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
- **[Wicked Engine](https://github.com/turanszkij/WickedEngine)** - 3D engine with modern graphics
|
||||
|
||||
[Some other projects on GitHub](https://github.com/search?q=D3D12MemAlloc.h&type=Code) and some game development studios that use DX12 in their games.
|
||||
|
||||
1062
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
1062
3rdparty/d3d12memalloc/include/D3D12MemAlloc.h
vendored
File diff suppressed because it is too large
Load Diff
467
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
467
3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp
vendored
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2019-2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
// Copyright (c) 2019-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,6 +33,13 @@
|
||||
#include <shared_mutex>
|
||||
#endif
|
||||
|
||||
// Includes needed for MinGW - see #71.
|
||||
#ifndef _MSC_VER
|
||||
#include <guiddef.h>
|
||||
// guiddef.h must be included first.
|
||||
#include <dxguids.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -42,6 +49,14 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef _D3D12MA_CONFIGURATION
|
||||
|
||||
#if !defined(D3D12MA_CPP20)
|
||||
#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
|
||||
#define D3D12MA_CPP20 1
|
||||
#else
|
||||
#define D3D12MA_CPP20 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if !defined(WINVER) || WINVER < 0x0600
|
||||
#error Required at least WinAPI version supporting: client = Windows Vista, server = Windows Server 2008.
|
||||
@@ -64,6 +79,10 @@
|
||||
#define D3D12MA_ASSERT(cond) assert(cond)
|
||||
#endif
|
||||
|
||||
#if D3D12MA_CPP20
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
// Assert that will be called very often, like inside data structures e.g. operator[].
|
||||
// Making it non-empty can make program slow.
|
||||
#ifndef D3D12MA_HEAVY_ASSERT
|
||||
@@ -107,6 +126,14 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
|
||||
#define D3D12MA_DEFAULT_BLOCK_SIZE (64ull * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_OPTIONS16_SUPPORTED
|
||||
#if D3D12_SDK_VERSION >= 610
|
||||
#define D3D12MA_OPTIONS16_SUPPORTED 1
|
||||
#else
|
||||
#define D3D12MA_OPTIONS16_SUPPORTED 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_DEBUG_LOG
|
||||
#define D3D12MA_DEBUG_LOG(format, ...)
|
||||
/*
|
||||
@@ -128,10 +155,6 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
|
||||
|
||||
#define D3D12MA_IID_PPV_ARGS(ppType) __uuidof(**(ppType)), reinterpret_cast<void**>(ppType)
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
#define D3D12MA_CREATE_NOT_ZEROED_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
namespace D3D12MA
|
||||
{
|
||||
static constexpr UINT HEAP_TYPE_COUNT = 5;
|
||||
@@ -292,6 +315,10 @@ static UINT8 BitScanLSB(UINT64 mask)
|
||||
if (_BitScanForward64(&pos, mask))
|
||||
return static_cast<UINT8>(pos);
|
||||
return UINT8_MAX;
|
||||
#elif D3D12MA_CPP20
|
||||
if (mask != 0)
|
||||
return static_cast<uint8_t>(std::countr_zero(mask));
|
||||
return UINT8_MAX;
|
||||
#elif defined __GNUC__ || defined __clang__
|
||||
return static_cast<UINT8>(__builtin_ffsll(mask)) - 1U;
|
||||
#else
|
||||
@@ -314,6 +341,10 @@ static UINT8 BitScanLSB(UINT32 mask)
|
||||
if (_BitScanForward(&pos, mask))
|
||||
return static_cast<UINT8>(pos);
|
||||
return UINT8_MAX;
|
||||
#elif D3D12MA_CPP20
|
||||
if (mask != 0)
|
||||
return static_cast<uint8_t>(std::countr_zero(mask));
|
||||
return UINT8_MAX;
|
||||
#elif defined __GNUC__ || defined __clang__
|
||||
return static_cast<UINT8>(__builtin_ffs(mask)) - 1U;
|
||||
#else
|
||||
@@ -336,6 +367,9 @@ static UINT8 BitScanMSB(UINT64 mask)
|
||||
unsigned long pos;
|
||||
if (_BitScanReverse64(&pos, mask))
|
||||
return static_cast<UINT8>(pos);
|
||||
#elif D3D12MA_CPP20
|
||||
if (mask != 0)
|
||||
return 63 - static_cast<uint8_t>(std::countl_zero(mask));
|
||||
#elif defined __GNUC__ || defined __clang__
|
||||
if (mask)
|
||||
return 63 - static_cast<UINT8>(__builtin_clzll(mask));
|
||||
@@ -358,6 +392,9 @@ static UINT8 BitScanMSB(UINT32 mask)
|
||||
unsigned long pos;
|
||||
if (_BitScanReverse(&pos, mask))
|
||||
return static_cast<UINT8>(pos);
|
||||
#elif D3D12MA_CPP20
|
||||
if (mask != 0)
|
||||
return 31 - static_cast<uint8_t>(std::countl_zero(mask));
|
||||
#elif defined __GNUC__ || defined __clang__
|
||||
if (mask)
|
||||
return 31 - static_cast<UINT8>(__builtin_clz(mask));
|
||||
@@ -2791,7 +2828,7 @@ class AllocationObjectAllocator
|
||||
D3D12MA_CLASS_NO_COPY(AllocationObjectAllocator);
|
||||
public:
|
||||
AllocationObjectAllocator(const ALLOCATION_CALLBACKS& allocationCallbacks, bool useMutex)
|
||||
: m_Allocator(allocationCallbacks, 1024), m_UseMutex(useMutex) {}
|
||||
: m_UseMutex(useMutex), m_Allocator(allocationCallbacks, 1024) {}
|
||||
|
||||
template<typename... Types>
|
||||
Allocation* Allocate(Types... args);
|
||||
@@ -2982,7 +3019,7 @@ void BlockMetadata::DebugLogAllocation(UINT64 offset, UINT64 size, void* private
|
||||
LPCWSTR name = allocation->GetName();
|
||||
|
||||
D3D12MA_DEBUG_LOG(L"UNFREED ALLOCATION; Offset: %llu; Size: %llu; PrivateData: %p; Name: %s",
|
||||
offset, size, privateData, name ? name : L"D3D12MA_Empty");
|
||||
offset, size, privateData, name ? name : L"");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5369,8 +5406,8 @@ struct CREATE_RESOURCE_PARAMS
|
||||
{
|
||||
CREATE_RESOURCE_PARAMS() = delete;
|
||||
CREATE_RESOURCE_PARAMS(
|
||||
const D3D12_RESOURCE_DESC* pResourceDesc,
|
||||
D3D12_RESOURCE_STATES InitialResourceState,
|
||||
const D3D12_RESOURCE_DESC* pResourceDesc,
|
||||
D3D12_RESOURCE_STATES InitialResourceState,
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue)
|
||||
: Variant(VARIANT_WITH_STATE)
|
||||
, pResourceDesc(pResourceDesc)
|
||||
@@ -5380,8 +5417,8 @@ struct CREATE_RESOURCE_PARAMS
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
CREATE_RESOURCE_PARAMS(
|
||||
const D3D12_RESOURCE_DESC1* pResourceDesc,
|
||||
D3D12_RESOURCE_STATES InitialResourceState,
|
||||
const D3D12_RESOURCE_DESC1* pResourceDesc,
|
||||
D3D12_RESOURCE_STATES InitialResourceState,
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue)
|
||||
: Variant(VARIANT_WITH_STATE_AND_DESC1)
|
||||
, pResourceDesc1(pResourceDesc)
|
||||
@@ -5396,7 +5433,7 @@ struct CREATE_RESOURCE_PARAMS
|
||||
D3D12_BARRIER_LAYOUT InitialLayout,
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue,
|
||||
UINT32 NumCastableFormats,
|
||||
DXGI_FORMAT* pCastableFormats)
|
||||
const DXGI_FORMAT* pCastableFormats)
|
||||
: Variant(VARIANT_WITH_LAYOUT)
|
||||
, pResourceDesc1(pResourceDesc)
|
||||
, InitialLayout(InitialLayout)
|
||||
@@ -5466,7 +5503,7 @@ struct CREATE_RESOURCE_PARAMS
|
||||
D3D12MA_ASSERT(Variant >= VARIANT_WITH_LAYOUT);
|
||||
return NumCastableFormats;
|
||||
}
|
||||
DXGI_FORMAT* GetCastableFormats() const
|
||||
const DXGI_FORMAT* GetCastableFormats() const
|
||||
{
|
||||
D3D12MA_ASSERT(Variant >= VARIANT_WITH_LAYOUT);
|
||||
return pCastableFormats;
|
||||
@@ -5491,7 +5528,7 @@ private:
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue;
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
UINT32 NumCastableFormats;
|
||||
DXGI_FORMAT* pCastableFormats;
|
||||
const DXGI_FORMAT* pCastableFormats;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -5541,6 +5578,7 @@ public:
|
||||
UINT64 size,
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
bool committedAllowed,
|
||||
size_t allocationCount,
|
||||
Allocation** pAllocations);
|
||||
|
||||
@@ -5551,6 +5589,7 @@ public:
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
const CREATE_RESOURCE_PARAMS& createParams,
|
||||
bool committedAllowed,
|
||||
Allocation** ppAllocation,
|
||||
REFIID riidResource,
|
||||
void** ppvResource);
|
||||
@@ -5601,6 +5640,7 @@ private:
|
||||
UINT64 size,
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
bool committedAllowed,
|
||||
Allocation** pAllocation);
|
||||
|
||||
HRESULT AllocateFromBlock(
|
||||
@@ -5706,29 +5746,31 @@ HRESULT CurrentBudgetData::UpdateBudget(IDXGIAdapter3* adapter3, bool useMutex)
|
||||
DXGI_QUERY_VIDEO_MEMORY_INFO infoLocal = {};
|
||||
DXGI_QUERY_VIDEO_MEMORY_INFO infoNonLocal = {};
|
||||
const HRESULT hrLocal = adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &infoLocal);
|
||||
if (FAILED(hrLocal))
|
||||
{
|
||||
return hrLocal;
|
||||
}
|
||||
const HRESULT hrNonLocal = adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &infoNonLocal);
|
||||
if (FAILED(hrNonLocal))
|
||||
{
|
||||
return hrNonLocal;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hrLocal) || SUCCEEDED(hrNonLocal))
|
||||
{
|
||||
MutexLockWrite lockWrite(m_BudgetMutex, useMutex);
|
||||
|
||||
if (SUCCEEDED(hrLocal))
|
||||
{
|
||||
m_D3D12Usage[0] = infoLocal.CurrentUsage;
|
||||
m_D3D12Budget[0] = infoLocal.Budget;
|
||||
}
|
||||
if (SUCCEEDED(hrNonLocal))
|
||||
{
|
||||
m_D3D12Usage[1] = infoNonLocal.CurrentUsage;
|
||||
m_D3D12Budget[1] = infoNonLocal.Budget;
|
||||
}
|
||||
m_D3D12Usage[0] = infoLocal.CurrentUsage;
|
||||
m_D3D12Budget[0] = infoLocal.Budget;
|
||||
|
||||
m_D3D12Usage[1] = infoNonLocal.CurrentUsage;
|
||||
m_D3D12Budget[1] = infoNonLocal.Budget;
|
||||
|
||||
m_BlockBytesAtD3D12Fetch[0] = m_BlockBytes[0];
|
||||
m_BlockBytesAtD3D12Fetch[1] = m_BlockBytes[1];
|
||||
m_OperationsSinceBudgetFetch = 0;
|
||||
}
|
||||
|
||||
return FAILED(hrLocal) ? hrLocal : hrNonLocal;
|
||||
return S_OK;
|
||||
}
|
||||
#endif // #if D3D12MA_DXGI_1_4
|
||||
|
||||
@@ -5847,6 +5889,7 @@ public:
|
||||
|
||||
AllocatorPimpl* GetAllocator() const { return m_Allocator; }
|
||||
const POOL_DESC& GetDesc() const { return m_Desc; }
|
||||
bool AlwaysCommitted() const { return (m_Desc.Flags & POOL_FLAG_ALWAYS_COMMITTED) != 0; }
|
||||
bool SupportsCommittedAllocations() const { return m_Desc.BlockSize == 0; }
|
||||
LPCWSTR GetName() const { return m_Name; }
|
||||
|
||||
@@ -5903,6 +5946,12 @@ public:
|
||||
#endif
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
ID3D12Device8* GetDevice8() const { return m_Device8; }
|
||||
#endif
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
ID3D12Device10* GetDevice10() const { return m_Device10; }
|
||||
#endif
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
ID3D12Device12* GetDevice12() const { return m_Device12; }
|
||||
#endif
|
||||
// Shortcut for "Allocation Callbacks", because this function is called so often.
|
||||
const ALLOCATION_CALLBACKS& GetAllocs() const { return m_AllocationCallbacks; }
|
||||
@@ -6011,6 +6060,9 @@ private:
|
||||
#endif
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
ID3D12Device10* m_Device10 = NULL; // AddRef, optional
|
||||
#endif
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
ID3D12Device12* m_Device12 = NULL; // AddRef, optional
|
||||
#endif
|
||||
IDXGIAdapter* m_Adapter; // AddRef
|
||||
#if D3D12MA_DXGI_1_4
|
||||
@@ -6071,12 +6123,26 @@ private:
|
||||
HRESULT UpdateD3D12Budget();
|
||||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfoNative(const D3D12_RESOURCE_DESC& resourceDesc) const;
|
||||
HRESULT GetResourceAllocationInfoMiddle(D3D12_RESOURCE_DESC& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const;
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfoNative(const D3D12_RESOURCE_DESC1& resourceDesc) const;
|
||||
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo2Native(const D3D12_RESOURCE_DESC1& resourceDesc) const;
|
||||
HRESULT GetResourceAllocationInfoMiddle(D3D12_RESOURCE_DESC1& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const;
|
||||
#endif
|
||||
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo3Native(const D3D12_RESOURCE_DESC1& resourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats) const;
|
||||
#endif
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc) const;
|
||||
HRESULT GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const;
|
||||
|
||||
bool NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size);
|
||||
|
||||
@@ -6148,6 +6214,10 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
m_Device->QueryInterface(D3D12MA_IID_PPV_ARGS(&m_Device10));
|
||||
#endif
|
||||
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
m_Device->QueryInterface(D3D12MA_IID_PPV_ARGS(&m_Device12));
|
||||
#endif
|
||||
|
||||
HRESULT hr = m_Adapter->GetDesc(&m_AdapterDesc);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -6163,9 +6233,6 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
m_D3D12Options.ResourceHeapTier = (D3D12MA_FORCE_RESOURCE_HEAP_TIER);
|
||||
#endif
|
||||
|
||||
// You must define this macro to like `#define D3D12MA_OPTIONS16_SUPPORTED 1` to enable GPU Upload Heaps!
|
||||
// Unfortunately there is no way to programmatically check if the included <d3d12.h> defines D3D12_FEATURE_DATA_D3D12_OPTIONS16 or not.
|
||||
// Main interfaces have respective macros like __ID3D12Device4_INTERFACE_DEFINED__, but structures like this do not.
|
||||
#if D3D12MA_OPTIONS16_SUPPORTED
|
||||
{
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16 = {};
|
||||
@@ -6175,7 +6242,7 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
m_GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // #if D3D12MA_OPTIONS16_SUPPORTED
|
||||
|
||||
hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &m_D3D12Architecture, sizeof(m_D3D12Architecture));
|
||||
if (FAILED(hr))
|
||||
@@ -6223,6 +6290,9 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
|
||||
AllocatorPimpl::~AllocatorPimpl()
|
||||
{
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
SAFE_RELEASE(m_Device12);
|
||||
#endif
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
SAFE_RELEASE(m_Device10);
|
||||
#endif
|
||||
@@ -6319,12 +6389,15 @@ HRESULT AllocatorPimpl::CreatePlacedResourceWrap(
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
// Microsoft defined pCastableFormats parameter as pointer to non-const and only fixed it in later Agility SDK,
|
||||
// thus we need const_cast.
|
||||
return m_Device10->CreatePlacedResource2(pHeap, HeapOffset,
|
||||
createParams.GetResourceDesc1(), createParams.GetInitialLayout(),
|
||||
createParams.GetOptimizedClearValue(), createParams.GetNumCastableFormats(),
|
||||
createParams.GetCastableFormats(), riidResource, ppvResource);
|
||||
} else
|
||||
const_cast<DXGI_FORMAT*>(createParams.GetCastableFormats()), riidResource, ppvResource);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
@@ -6335,21 +6408,19 @@ HRESULT AllocatorPimpl::CreatePlacedResourceWrap(
|
||||
return m_Device8->CreatePlacedResource1(pHeap, HeapOffset,
|
||||
createParams.GetResourceDesc1(), createParams.GetInitialResourceState(),
|
||||
createParams.GetOptimizedClearValue(), riidResource, ppvResource);
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
|
||||
if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE)
|
||||
{
|
||||
return m_Device->CreatePlacedResource(pHeap, HeapOffset,
|
||||
createParams.GetResourceDesc(), createParams.GetInitialResourceState(),
|
||||
createParams.GetOptimizedClearValue(), riidResource, ppvResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12MA_ASSERT(0);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
D3D12MA_ASSERT(0);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT AllocatorPimpl::CreateResource(
|
||||
const ALLOCATION_DESC* pAllocDesc,
|
||||
@@ -6366,6 +6437,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
*ppvResource = NULL;
|
||||
}
|
||||
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
CREATE_RESOURCE_PARAMS finalCreateParams = createParams;
|
||||
D3D12_RESOURCE_DESC finalResourceDesc;
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
@@ -6376,45 +6448,49 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
if (!m_Device8)
|
||||
if (m_Device8 != NULL)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
}
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc1);
|
||||
}
|
||||
#endif
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_LAYOUT)
|
||||
{
|
||||
if (!m_Device10)
|
||||
if (m_Device10 != NULL)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
}
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc1);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
D3D12MA_ASSERT(0);
|
||||
return E_INVALIDARG;
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
D3D12MA_ASSERT(IsPow2(resAllocInfo.Alignment));
|
||||
// We've seen UINT64_MAX returned when the call to GetResourceAllocationInfo was invalid.
|
||||
D3D12MA_ASSERT(resAllocInfo.SizeInBytes != UINT64_MAX);
|
||||
D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);
|
||||
|
||||
BlockVector* blockVector = NULL;
|
||||
CommittedAllocationParameters committedAllocationParams = {};
|
||||
bool preferCommitted = false;
|
||||
|
||||
HRESULT hr;
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
if (createParams.Variant >= CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
@@ -6445,7 +6521,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
if (blockVector != NULL)
|
||||
{
|
||||
hr = blockVector->CreateResource(resAllocInfo.SizeInBytes, resAllocInfo.Alignment,
|
||||
*pAllocDesc, finalCreateParams,
|
||||
*pAllocDesc, finalCreateParams, committedAllocationParams.IsValid(),
|
||||
ppAllocation, riidResource, ppvResource);
|
||||
if (SUCCEEDED(hr))
|
||||
return hr;
|
||||
@@ -6488,7 +6564,7 @@ HRESULT AllocatorPimpl::AllocateMemory(
|
||||
if (blockVector != NULL)
|
||||
{
|
||||
hr = blockVector->Allocate(pAllocInfo->SizeInBytes, pAllocInfo->Alignment,
|
||||
*pAllocDesc, 1, (Allocation**)ppAllocation);
|
||||
*pAllocDesc, committedAllocationParams.IsValid(), 1, (Allocation**)ppAllocation);
|
||||
if (SUCCEEDED(hr))
|
||||
return hr;
|
||||
}
|
||||
@@ -6510,6 +6586,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
*ppvResource = NULL;
|
||||
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
CREATE_RESOURCE_PARAMS finalCreateParams = createParams;
|
||||
D3D12_RESOURCE_DESC finalResourceDesc;
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
@@ -6520,37 +6597,40 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
if (!m_Device8)
|
||||
if (m_Device8 != NULL)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
}
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc1);
|
||||
}
|
||||
#endif
|
||||
#ifdef __ID3D12Device10_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_LAYOUT)
|
||||
{
|
||||
if (!m_Device10)
|
||||
if (m_Device10 != NULL)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
}
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
resAllocInfo = GetResourceAllocationInfo(finalResourceDesc1);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
D3D12MA_ASSERT(0);
|
||||
return E_INVALIDARG;
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
D3D12MA_ASSERT(IsPow2(resAllocInfo.Alignment));
|
||||
D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);
|
||||
|
||||
@@ -6773,42 +6853,41 @@ void AllocatorPimpl::GetBudget(Budget* outLocalBudget, Budget* outNonLocalBudget
|
||||
outLocalBudget ? &outLocalBudget->BudgetBytes : NULL,
|
||||
outNonLocalBudget ? &outNonLocalBudget->UsageBytes : NULL,
|
||||
outNonLocalBudget ? &outNonLocalBudget->BudgetBytes : NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (SUCCEEDED(UpdateD3D12Budget()))
|
||||
{
|
||||
UpdateD3D12Budget();
|
||||
GetBudget(outLocalBudget, outNonLocalBudget); // Recursion
|
||||
GetBudget(outLocalBudget, outNonLocalBudget); // Recursion.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
// Fallback path - manual calculation, not real budget.
|
||||
if (outLocalBudget)
|
||||
{
|
||||
if (outLocalBudget)
|
||||
{
|
||||
outLocalBudget->UsageBytes = outLocalBudget->Stats.BlockBytes;
|
||||
outLocalBudget->BudgetBytes = GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL_COPY) * 8 / 10; // 80% heuristics.
|
||||
}
|
||||
if (outNonLocalBudget)
|
||||
{
|
||||
outNonLocalBudget->UsageBytes = outNonLocalBudget->Stats.BlockBytes;
|
||||
outNonLocalBudget->BudgetBytes = GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL_COPY) * 8 / 10; // 80% heuristics.
|
||||
}
|
||||
outLocalBudget->UsageBytes = outLocalBudget->Stats.BlockBytes;
|
||||
outLocalBudget->BudgetBytes = GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL_COPY) * 8 / 10; // 80% heuristics.
|
||||
}
|
||||
if (outNonLocalBudget)
|
||||
{
|
||||
outNonLocalBudget->UsageBytes = outNonLocalBudget->Stats.BlockBytes;
|
||||
outNonLocalBudget->BudgetBytes = GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL_COPY) * 8 / 10; // 80% heuristics.
|
||||
}
|
||||
}
|
||||
|
||||
void AllocatorPimpl::GetBudgetForHeapType(Budget& outBudget, D3D12_HEAP_TYPE heapType)
|
||||
{
|
||||
switch (heapType)
|
||||
const bool isLocal = StandardHeapTypeToMemorySegmentGroup(heapType) ==
|
||||
DXGI_MEMORY_SEGMENT_GROUP_LOCAL_COPY;
|
||||
if (isLocal)
|
||||
{
|
||||
case D3D12_HEAP_TYPE_DEFAULT:
|
||||
case D3D12_HEAP_TYPE_GPU_UPLOAD_COPY:
|
||||
GetBudget(&outBudget, NULL);
|
||||
break;
|
||||
case D3D12_HEAP_TYPE_UPLOAD:
|
||||
case D3D12_HEAP_TYPE_READBACK:
|
||||
}
|
||||
else
|
||||
{
|
||||
GetBudget(NULL, &outBudget);
|
||||
break;
|
||||
default: D3D12MA_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7248,12 +7327,15 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
// Microsoft defined pCastableFormats parameter as pointer to non-const and only fixed it in later Agility SDK,
|
||||
// thus we need const_cast.
|
||||
hr = m_Device10->CreateCommittedResource3(
|
||||
&committedAllocParams.m_HeapProperties,
|
||||
committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS,
|
||||
createParams.GetResourceDesc1(), createParams.GetInitialLayout(),
|
||||
createParams.GetOptimizedClearValue(), committedAllocParams.m_ProtectedSession,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(),
|
||||
createParams.GetNumCastableFormats(), const_cast<DXGI_FORMAT*>(createParams.GetCastableFormats()),
|
||||
D3D12MA_IID_PPV_ARGS(&res));
|
||||
} else
|
||||
#endif
|
||||
@@ -7396,8 +7478,8 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
outCommittedAllocationParams = CommittedAllocationParameters();
|
||||
outPreferCommitted = false;
|
||||
|
||||
D3D12MA_ASSERT((allocDesc.HeapType != D3D12_HEAP_TYPE_GPU_UPLOAD_COPY || IsGPUUploadHeapSupported()) &&
|
||||
"Trying to allocate from D3D12_HEAP_TYPE_GPU_UPLOAD while GPUUploadHeapSupported == FALSE or D3D12MA_OPTIONS16_SUPPORTED macro was not defined when compiling D3D12MA library.");
|
||||
if (allocDesc.HeapType == D3D12_HEAP_TYPE_GPU_UPLOAD_COPY && !IsGPUUploadHeapSupported())
|
||||
return E_NOTIMPL;
|
||||
|
||||
bool msaaAlwaysCommitted;
|
||||
if (allocDesc.CustomPool != NULL)
|
||||
@@ -7405,7 +7487,8 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
PoolPimpl* const pool = allocDesc.CustomPool->m_Pimpl;
|
||||
|
||||
msaaAlwaysCommitted = pool->GetBlockVector()->DeniesMsaaTextures();
|
||||
outBlockVector = pool->GetBlockVector();
|
||||
if(!pool->AlwaysCommitted())
|
||||
outBlockVector = pool->GetBlockVector();
|
||||
|
||||
const auto& desc = pool->GetDesc();
|
||||
outCommittedAllocationParams.m_ProtectedSession = desc.pProtectedSession;
|
||||
@@ -7444,12 +7527,6 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
outPreferCommitted = true;
|
||||
}
|
||||
}
|
||||
|
||||
const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS;
|
||||
if (outBlockVector != NULL && extraHeapFlags != 0)
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((allocDesc.Flags & ALLOCATION_FLAG_COMMITTED) != 0 ||
|
||||
@@ -7479,12 +7556,7 @@ UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, Reso
|
||||
D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS;
|
||||
|
||||
#if D3D12MA_CREATE_NOT_ZEROED_AVAILABLE
|
||||
// If allocator was created with ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED, also ignore
|
||||
// D3D12_HEAP_FLAG_CREATE_NOT_ZEROED.
|
||||
if(m_DefaultPoolsNotZeroed)
|
||||
{
|
||||
extraHeapFlags &= ~D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
||||
}
|
||||
extraHeapFlags &= ~D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
||||
#endif
|
||||
|
||||
if (extraHeapFlags != 0)
|
||||
@@ -7603,7 +7675,7 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
||||
}
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(const D3D12_RESOURCE_DESC1& resourceDesc) const
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo2Native(const D3D12_RESOURCE_DESC1& resourceDesc) const
|
||||
{
|
||||
D3D12MA_ASSERT(m_Device8 != NULL);
|
||||
D3D12_RESOURCE_ALLOCATION_INFO1 info1Unused;
|
||||
@@ -7619,8 +7691,71 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
||||
}
|
||||
#endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo3Native(const D3D12_RESOURCE_DESC1& resourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats) const
|
||||
{
|
||||
D3D12MA_ASSERT(m_Device12 != NULL);
|
||||
D3D12_RESOURCE_ALLOCATION_INFO1 info1Unused;
|
||||
|
||||
// This is how new D3D12 headers define GetResourceAllocationInfo function -
|
||||
// different signature depending on these macros.
|
||||
#if defined(_MSC_VER) || !defined(_WIN32)
|
||||
return m_Device12->GetResourceAllocationInfo3(0, 1, &resourceDesc,
|
||||
&NumCastableFormats, &pCastableFormats, &info1Unused);
|
||||
#else
|
||||
D3D12_RESOURCE_ALLOCATION_INFO retVal;
|
||||
return *m_Device12->GetResourceAllocationInfo3(&retVal, 0, 1, &resourceDesc,
|
||||
&NumCastableFormats, &pCastableFormats, &info1Unused);
|
||||
#endif
|
||||
}
|
||||
#endif // #ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
|
||||
HRESULT AllocatorPimpl::GetResourceAllocationInfoMiddle(
|
||||
D3D12_RESOURCE_DESC& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const
|
||||
{
|
||||
if (NumCastableFormats > 0)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
outAllocInfo = GetResourceAllocationInfoNative(inOutResourceDesc);
|
||||
return outAllocInfo.SizeInBytes != UINT64_MAX ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
HRESULT AllocatorPimpl::GetResourceAllocationInfoMiddle(
|
||||
D3D12_RESOURCE_DESC1& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const
|
||||
{
|
||||
if (NumCastableFormats > 0)
|
||||
{
|
||||
#ifdef __ID3D12Device12_INTERFACE_DEFINED__
|
||||
if (m_Device12 != NULL)
|
||||
{
|
||||
outAllocInfo = GetResourceAllocationInfo3Native(inOutResourceDesc, NumCastableFormats, pCastableFormats);
|
||||
return outAllocInfo.SizeInBytes != UINT64_MAX ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
#else
|
||||
return E_NOTIMPL;
|
||||
#endif
|
||||
}
|
||||
|
||||
outAllocInfo = GetResourceAllocationInfo2Native(inOutResourceDesc);
|
||||
return outAllocInfo.SizeInBytes != UINT64_MAX ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
|
||||
#endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc) const
|
||||
HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const
|
||||
{
|
||||
#ifdef __ID3D12Device1_INTERFACE_DEFINED__
|
||||
/* Optional optimization: Microsoft documentation says:
|
||||
@@ -7634,12 +7769,15 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_R
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
return {
|
||||
outAllocInfo = {
|
||||
AlignUp<UINT64>(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes
|
||||
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT }; // Alignment
|
||||
return S_OK;
|
||||
}
|
||||
#endif // #ifdef __ID3D12Device1_INTERFACE_DEFINED__
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
#if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D &&
|
||||
@@ -7657,17 +7795,19 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_R
|
||||
D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT :
|
||||
D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
inOutResourceDesc.Alignment = smallAlignmentToTry;
|
||||
const D3D12_RESOURCE_ALLOCATION_INFO smallAllocInfo = GetResourceAllocationInfoNative(inOutResourceDesc);
|
||||
hr = GetResourceAllocationInfoMiddle(
|
||||
inOutResourceDesc, NumCastableFormats, pCastableFormats, outAllocInfo);
|
||||
// Check if alignment requested has been granted.
|
||||
if (smallAllocInfo.Alignment == smallAlignmentToTry)
|
||||
if (SUCCEEDED(hr) && outAllocInfo.Alignment == smallAlignmentToTry)
|
||||
{
|
||||
return smallAllocInfo;
|
||||
return S_OK;
|
||||
}
|
||||
inOutResourceDesc.Alignment = 0; // Restore original
|
||||
}
|
||||
#endif // #if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
|
||||
|
||||
return GetResourceAllocationInfoNative(inOutResourceDesc);
|
||||
return GetResourceAllocationInfoMiddle(
|
||||
inOutResourceDesc, NumCastableFormats, pCastableFormats, outAllocInfo);
|
||||
}
|
||||
|
||||
bool AllocatorPimpl::NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size)
|
||||
@@ -7988,6 +8128,7 @@ HRESULT BlockVector::Allocate(
|
||||
UINT64 size,
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
bool committedAllowed,
|
||||
size_t allocationCount,
|
||||
Allocation** pAllocations)
|
||||
{
|
||||
@@ -8002,6 +8143,7 @@ HRESULT BlockVector::Allocate(
|
||||
size,
|
||||
alignment,
|
||||
allocDesc,
|
||||
committedAllowed,
|
||||
pAllocations + allocIndex);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -8090,40 +8232,43 @@ HRESULT BlockVector::CreateResource(
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
const CREATE_RESOURCE_PARAMS& createParams,
|
||||
bool committedAllowed,
|
||||
Allocation** ppAllocation,
|
||||
REFIID riidResource,
|
||||
void** ppvResource)
|
||||
{
|
||||
HRESULT hr = Allocate(size, alignment, allocDesc, 1, ppAllocation);
|
||||
HRESULT hr = Allocate(size, alignment, allocDesc, committedAllowed, 1, ppAllocation);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
ID3D12Resource* res = NULL;
|
||||
hr = m_hAllocator->CreatePlacedResourceWrap(
|
||||
(*ppAllocation)->m_Placed.block->GetHeap(),
|
||||
(*ppAllocation)->GetOffset(),
|
||||
createParams,
|
||||
D3D12MA_IID_PPV_ARGS(&res));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ID3D12Resource* res = NULL;
|
||||
hr = m_hAllocator->CreatePlacedResourceWrap(
|
||||
(*ppAllocation)->m_Placed.block->GetHeap(),
|
||||
(*ppAllocation)->GetOffset(),
|
||||
createParams,
|
||||
D3D12MA_IID_PPV_ARGS(&res));
|
||||
if (ppvResource != NULL)
|
||||
{
|
||||
hr = res->QueryInterface(riidResource, ppvResource);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (ppvResource != NULL)
|
||||
{
|
||||
hr = res->QueryInterface(riidResource, ppvResource);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(*ppAllocation)->SetResourcePointer(res, createParams.GetBaseResourceDesc());
|
||||
}
|
||||
else
|
||||
{
|
||||
res->Release();
|
||||
SAFE_RELEASE(*ppAllocation);
|
||||
}
|
||||
(*ppAllocation)->SetResourcePointer(res, createParams.GetBaseResourceDesc());
|
||||
}
|
||||
else
|
||||
{
|
||||
res->Release();
|
||||
SAFE_RELEASE(*ppAllocation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SAFE_RELEASE(*ppAllocation);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -8241,6 +8386,7 @@ HRESULT BlockVector::AllocatePage(
|
||||
UINT64 size,
|
||||
UINT64 alignment,
|
||||
const ALLOCATION_DESC& allocDesc,
|
||||
bool committedAllowed,
|
||||
Allocation** pAllocation)
|
||||
{
|
||||
// Early reject: requested allocation size is larger that maximum block size for this block vector.
|
||||
@@ -8257,13 +8403,19 @@ HRESULT BlockVector::AllocatePage(
|
||||
freeMemory = (budget.UsageBytes < budget.BudgetBytes) ? (budget.BudgetBytes - budget.UsageBytes) : 0;
|
||||
}
|
||||
|
||||
const bool canCreateNewBlock =
|
||||
const bool canExceedFreeMemory = !committedAllowed;
|
||||
|
||||
bool canCreateNewBlock =
|
||||
((allocDesc.Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) == 0) &&
|
||||
(m_Blocks.size() < m_MaxBlockCount) &&
|
||||
// Even if we don't have to stay within budget with this allocation, when the
|
||||
// budget would be exceeded, we don't want to allocate new blocks, but always
|
||||
// create resources as committed.
|
||||
freeMemory >= size;
|
||||
(m_Blocks.size() < m_MaxBlockCount);
|
||||
|
||||
// Even if we don't have to stay within budget with this allocation, when the
|
||||
// budget would be exceeded, we don't want to allocate new blocks, but always
|
||||
// create resources as committed.
|
||||
if (freeMemory < size && !canExceedFreeMemory)
|
||||
{
|
||||
canCreateNewBlock = false;
|
||||
}
|
||||
|
||||
// 1. Search existing allocations
|
||||
{
|
||||
@@ -8313,26 +8465,29 @@ HRESULT BlockVector::AllocatePage(
|
||||
}
|
||||
}
|
||||
|
||||
size_t newBlockIndex = 0;
|
||||
HRESULT hr = newBlockSize <= freeMemory ?
|
||||
CreateBlock(newBlockSize, &newBlockIndex) : E_OUTOFMEMORY;
|
||||
size_t newBlockIndex = SIZE_MAX;
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
if (newBlockSize <= freeMemory || canExceedFreeMemory)
|
||||
{
|
||||
hr = CreateBlock(newBlockSize, &newBlockIndex);
|
||||
}
|
||||
// Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
|
||||
if (!m_ExplicitBlockSize)
|
||||
{
|
||||
while (FAILED(hr) && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
|
||||
{
|
||||
const UINT64 smallerNewBlockSize = newBlockSize / 2;
|
||||
if (smallerNewBlockSize >= size)
|
||||
{
|
||||
newBlockSize = smallerNewBlockSize;
|
||||
++newBlockSizeShift;
|
||||
hr = newBlockSize <= freeMemory ?
|
||||
CreateBlock(newBlockSize, &newBlockIndex) : E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
if (smallerNewBlockSize < size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
newBlockSize = smallerNewBlockSize;
|
||||
++newBlockSizeShift;
|
||||
if (newBlockSize <= freeMemory || canExceedFreeMemory)
|
||||
{
|
||||
hr = CreateBlock(newBlockSize, &newBlockIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9509,6 +9664,8 @@ HRESULT Pool::BeginDefragmentation(const DEFRAGMENTATION_DESC* pDesc, Defragment
|
||||
// Check for support
|
||||
if (m_Pimpl->GetBlockVector()->GetAlgorithm() & POOL_FLAG_ALGORITHM_LINEAR)
|
||||
return E_NOINTERFACE;
|
||||
if(m_Pimpl->AlwaysCommitted())
|
||||
return E_NOINTERFACE;
|
||||
|
||||
AllocatorPimpl* allocator = m_Pimpl->GetAllocator();
|
||||
*ppContext = D3D12MA_NEW(allocator->GetAllocs(), DefragmentationContext)(allocator, *pDesc, m_Pimpl->GetBlockVector());
|
||||
@@ -9612,7 +9769,7 @@ HRESULT Allocator::CreateResource3(
|
||||
D3D12_BARRIER_LAYOUT InitialLayout,
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue,
|
||||
UINT32 NumCastableFormats,
|
||||
DXGI_FORMAT* pCastableFormats,
|
||||
const DXGI_FORMAT* pCastableFormats,
|
||||
Allocation** ppAllocation,
|
||||
REFIID riidResource,
|
||||
void** ppvResource)
|
||||
@@ -9702,7 +9859,7 @@ HRESULT Allocator::CreateAliasingResource2(
|
||||
D3D12_BARRIER_LAYOUT InitialLayout,
|
||||
const D3D12_CLEAR_VALUE* pOptimizedClearValue,
|
||||
UINT32 NumCastableFormats,
|
||||
DXGI_FORMAT* pCastableFormats,
|
||||
const DXGI_FORMAT* pCastableFormats,
|
||||
REFIID riidResource,
|
||||
void** ppvResource)
|
||||
{
|
||||
@@ -9732,6 +9889,12 @@ HRESULT Allocator::CreatePool(
|
||||
D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::CreatePool.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if ((pPoolDesc->Flags & POOL_FLAG_ALWAYS_COMMITTED) != 0 &&
|
||||
(pPoolDesc->BlockSize != 0 || pPoolDesc->MinBlockCount > 0))
|
||||
{
|
||||
D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::CreatePool while POOL_FLAG_ALWAYS_COMMITTED is specified.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (!m_Pimpl->HeapFlagsFulfillResourceHeapTier(pPoolDesc->HeapFlags))
|
||||
{
|
||||
D3D12MA_ASSERT(0 && "Invalid pPoolDesc->HeapFlags passed to Allocator::CreatePool. Did you forget to handle ResourceHeapTier=1?");
|
||||
|
||||
1
3rdparty/fast_float/CONTRIBUTORS
vendored
1
3rdparty/fast_float/CONTRIBUTORS
vendored
@@ -8,3 +8,4 @@ Lénárd Szolnoki
|
||||
Jan Pharago
|
||||
Maya Warrier
|
||||
Taha Khokhar
|
||||
Anders Dalvander
|
||||
|
||||
489
3rdparty/fast_float/README.md
vendored
489
3rdparty/fast_float/README.md
vendored
@@ -1,160 +1,233 @@
|
||||
|
||||
## fast_float number parsing library: 4x faster than strtod
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:fast_float)
|
||||
|
||||
[](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml)
|
||||
|
||||
The fast_float library provides fast header-only implementations for the C++ from_chars
|
||||
functions for `float` and `double` types as well as integer types. These functions convert ASCII strings representing decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including
|
||||
round to even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries.
|
||||
The fast_float library provides fast header-only implementations for the C++
|
||||
from_chars functions for `float` and `double` types as well as integer types.
|
||||
These functions convert ASCII strings representing decimal values (e.g.,
|
||||
`1.3e10`) into binary types. We provide exact rounding (including round to
|
||||
even). In our experience, these `fast_float` functions many times faster than
|
||||
comparable number-parsing functions from existing C++ standard libraries.
|
||||
|
||||
Specifically, `fast_float` provides the following two functions to parse floating-point numbers with a C++17-like syntax (the library itself only requires C++11):
|
||||
Specifically, `fast_float` provides the following two functions to parse
|
||||
floating-point numbers with a C++17-like syntax (the library itself only
|
||||
requires C++11):
|
||||
|
||||
```C++
|
||||
from_chars_result from_chars(const char* first, const char* last, float& value, ...);
|
||||
from_chars_result from_chars(const char* first, const char* last, double& value, ...);
|
||||
from_chars_result from_chars(char const *first, char const *last, float &value, ...);
|
||||
from_chars_result from_chars(char const *first, char const *last, double &value, ...);
|
||||
```
|
||||
|
||||
You can also parse integer types:
|
||||
|
||||
|
||||
|
||||
```C++
|
||||
from_chars_result from_chars(char const *first, char const *last, int &value, ...);
|
||||
from_chars_result from_chars(char const *first, char const *last, unsigned &value, ...);
|
||||
```
|
||||
|
||||
The return type (`from_chars_result`) is defined as the struct:
|
||||
|
||||
```C++
|
||||
struct from_chars_result {
|
||||
const char* ptr;
|
||||
std::errc ec;
|
||||
char const *ptr;
|
||||
std::errc ec;
|
||||
};
|
||||
```
|
||||
|
||||
It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
|
||||
a locale-independent format equivalent to the C++17 from_chars function.
|
||||
The resulting floating-point value is the closest floating-point values (using either float or double),
|
||||
using the "round to even" convention for values that would otherwise fall right in-between two values.
|
||||
That is, we provide exact parsing according to the IEEE standard.
|
||||
It parses the character sequence `[first, last)` for a number. It parses
|
||||
floating-point numbers expecting a locale-independent format equivalent to the
|
||||
C++17 from_chars function. The resulting floating-point value is the closest
|
||||
floating-point values (using either `float` or `double`), using the "round to
|
||||
even" convention for values that would otherwise fall right in-between two
|
||||
values. That is, we provide exact parsing according to the IEEE standard.
|
||||
|
||||
Given a successful parse, the pointer (`ptr`) in the returned value is set to
|
||||
point right after the parsed number, and the `value` referenced is set to the
|
||||
parsed value. In case of error, the returned `ec` contains a representative
|
||||
error, otherwise the default (`std::errc()`) value is stored.
|
||||
|
||||
Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the
|
||||
parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned
|
||||
`ec` contains a representative error, otherwise the default (`std::errc()`) value is stored.
|
||||
|
||||
The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`).
|
||||
The implementation does not throw and does not allocate memory (e.g., with `new`
|
||||
or `malloc`).
|
||||
|
||||
It will parse infinity and nan values.
|
||||
|
||||
Example:
|
||||
|
||||
``` C++
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "3.1416 xyz ";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
std::string input = "3.1416 xyz ";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
You can parse delimited numbers:
|
||||
|
||||
```C++
|
||||
const std::string input = "234532.3426362,7869234.9823,324562.645";
|
||||
std::string input = "234532.3426362,7869234.9823,324562.645";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) {
|
||||
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) {
|
||||
// check error
|
||||
}
|
||||
// we have result == 234532.3426362.
|
||||
if(answer.ptr[0] != ',') {
|
||||
if (answer.ptr[0] != ',') {
|
||||
// unexpected delimiter
|
||||
}
|
||||
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) {
|
||||
answer = fast_float::from_chars(answer.ptr + 1, input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) {
|
||||
// check error
|
||||
}
|
||||
// we have result == 7869234.9823.
|
||||
if(answer.ptr[0] != ',') {
|
||||
if (answer.ptr[0] != ',') {
|
||||
// unexpected delimiter
|
||||
}
|
||||
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) {
|
||||
answer = fast_float::from_chars(answer.ptr + 1, input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) {
|
||||
// check error
|
||||
}
|
||||
// we have result == 324562.645.
|
||||
```
|
||||
|
||||
Like the C++17 standard, the `fast_float::from_chars` functions take an optional
|
||||
last argument of the type `fast_float::chars_format`. It is a bitset value: we
|
||||
check whether `fmt & fast_float::chars_format::fixed` and `fmt &
|
||||
fast_float::chars_format::scientific` are set to determine whether we allow the
|
||||
fixed point and scientific notation respectively. The default is
|
||||
`fast_float::chars_format::general` which allows both `fixed` and `scientific`.
|
||||
|
||||
The library seeks to follow the C++17 (see
|
||||
[28.2.3.(6.1)](https://eel.is/c++draft/charconv.from.chars#6.1)) specification.
|
||||
|
||||
Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
|
||||
the type `fast_float::chars_format`. It is a bitset value: we check whether
|
||||
`fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
|
||||
to determine whether we allow the fixed point and scientific notation respectively.
|
||||
The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
|
||||
|
||||
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
|
||||
* The `from_chars` function does not skip leading white-space characters.
|
||||
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden.
|
||||
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
|
||||
* The `from_chars` function does not skip leading white-space characters (unless
|
||||
`fast_float::chars_format::skip_white_space` is set).
|
||||
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is
|
||||
forbidden (unless `fast_float::chars_format::allow_leading_plus` is set).
|
||||
* It is generally impossible to represent a decimal value exactly as binary
|
||||
floating-point number (`float` and `double` types). We seek the nearest value.
|
||||
We round to an even mantissa when we are in-between two binary floating-point
|
||||
numbers.
|
||||
|
||||
Furthermore, we have the following restrictions:
|
||||
* We only support `float` and `double` types at this time.
|
||||
|
||||
* We support `float` and `double`, but not `long double`. We also support
|
||||
fixed-width floating-point types such as `std::float64_t`, `std::float32_t`,
|
||||
`std::float16_t`, and `std::bfloat16_t`.
|
||||
* We only support the decimal format: we do not support hexadecimal strings.
|
||||
* For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value and the returned `ec` is set to `std::errc::result_out_of_range`.
|
||||
* For values that are either very large or very small (e.g., `1e9999`), we
|
||||
represent it using the infinity or negative infinity value and the returned
|
||||
`ec` is set to `std::errc::result_out_of_range`.
|
||||
|
||||
We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems.
|
||||
|
||||
We assume that the rounding mode is set to nearest (`std::fegetround() == FE_TONEAREST`).
|
||||
We support Visual Studio, macOS, Linux, freeBSD. We support big and little
|
||||
endian. We support 32-bit and 64-bit systems.
|
||||
|
||||
We assume that the rounding mode is set to nearest (`std::fegetround() ==
|
||||
FE_TONEAREST`).
|
||||
|
||||
## Integer types
|
||||
|
||||
You can also parse integer types using different bases (e.g., 2, 10, 16). The following code will
|
||||
print the number 22250738585072012 three times:
|
||||
|
||||
You can also parse integer types using different bases (e.g., 2, 10, 16). The
|
||||
following code will print the number 22250738585072012 three times:
|
||||
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
uint64_t i;
|
||||
const char str[] = "22250738585072012";
|
||||
auto answer = fast_float::from_chars(str, str + strlen(str), i);
|
||||
std::string str = "22250738585072012";
|
||||
auto answer = fast_float::from_chars(str.data(), str.data() + str.size(), i);
|
||||
if (answer.ec != std::errc()) {
|
||||
std::cerr << "parsing failure\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << "parsed the number "<< i << std::endl;
|
||||
std::cout << "parsed the number " << i << std::endl;
|
||||
|
||||
const char binstr[] = "1001111000011001110110111001001010110100111000110001100";
|
||||
std::string binstr = "1001111000011001110110111001001010110100111000110001100";
|
||||
|
||||
answer = fast_float::from_chars(binstr, binstr + strlen(binstr), i, 2);
|
||||
answer = fast_float::from_chars(binstr.data(), binstr.data() + binstr.size(), i, 2);
|
||||
if (answer.ec != std::errc()) {
|
||||
std::cerr << "parsing failure\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << "parsed the number "<< i << std::endl;
|
||||
std::cout << "parsed the number " << i << std::endl;
|
||||
|
||||
std::string hexstr = "4f0cedc95a718c";
|
||||
|
||||
const char hexstr[] = "4f0cedc95a718c";
|
||||
|
||||
answer = fast_float::from_chars(hexstr, hexstr + strlen(hexstr), i, 16);
|
||||
answer = fast_float::from_chars(hexstr.data(), hexstr.data() + hexstr.size(), i, 16);
|
||||
if (answer.ec != std::errc()) {
|
||||
std::cerr << "parsing failure\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << "parsed the number "<< i << std::endl;
|
||||
std::cout << "parsed the number " << i << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
## Behavior of result_out_of_range
|
||||
|
||||
When parsing floating-point values, the numbers can sometimes be too small
|
||||
(e.g., `1e-1000`) or too large (e.g., `1e1000`). The C language established the
|
||||
precedent that these small values are out of range. In such cases, it is
|
||||
customary to parse small values to zero and large values to infinity. That is
|
||||
the behaviour of the C language (e.g., `stdtod`). That is the behaviour followed
|
||||
by the fast_float library.
|
||||
|
||||
Specifically, we follow Jonathan Wakely's interpretation of the standard:
|
||||
|
||||
> In any case, the resulting value is one of at most two floating-point values
|
||||
> closest to the value of the string matching the pattern.
|
||||
|
||||
It is also the approach taken by the [Microsoft C++
|
||||
library](https://github.com/microsoft/STL/blob/62205ab155d093e71dd9588a78f02c5396c3c14b/tests/std/tests/P0067R5_charconv/test.cpp#L943-L946).
|
||||
|
||||
Hence, we have the following examples:
|
||||
|
||||
```cpp
|
||||
double result = -1;
|
||||
std::string str = "3e-1000";
|
||||
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
|
||||
// r.ec == std::errc::result_out_of_range
|
||||
// r.ptr == str.data() + 7
|
||||
// result == 0
|
||||
```
|
||||
|
||||
```cpp
|
||||
double result = -1;
|
||||
std::string str = "3e1000";
|
||||
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
|
||||
// r.ec == std::errc::result_out_of_range
|
||||
// r.ptr == str.data() + 6
|
||||
// result == std::numeric_limits<double>::infinity()
|
||||
```
|
||||
|
||||
Users who wish for the value to be left unmodified given
|
||||
`std::errc::result_out_of_range` may do so by adding two lines of code:
|
||||
|
||||
```cpp
|
||||
double old_result = result; // make copy
|
||||
auto r = fast_float::from_chars(start, end, result);
|
||||
if (r.ec == std::errc::result_out_of_range) { result = old_result; }
|
||||
```
|
||||
|
||||
## C++20: compile-time evaluation (constexpr)
|
||||
|
||||
In C++20, you may use `fast_float::from_chars` to parse strings
|
||||
at compile-time, as in the following example:
|
||||
In C++20, you may use `fast_float::from_chars` to parse strings at compile-time,
|
||||
as in the following example:
|
||||
|
||||
```C++
|
||||
// consteval forces compile-time evaluation of the function in C++20.
|
||||
consteval double parse(std::string_view input) {
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) { return -1.0; }
|
||||
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) { return -1.0; }
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -167,108 +240,107 @@ constexpr double constexptest() {
|
||||
|
||||
## C++23: Fixed width floating-point types
|
||||
|
||||
The library also supports fixed-width floating-point types such as `std::float32_t` and `std::float64_t`. E.g., you can write:
|
||||
The library also supports fixed-width floating-point types such as
|
||||
`std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`.
|
||||
E.g., you can write:
|
||||
|
||||
```C++
|
||||
std::float32_t result;
|
||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||
``````
|
||||
|
||||
```
|
||||
|
||||
## Non-ASCII Inputs
|
||||
|
||||
We also support UTF-16 and UTF-32 inputs, as well as ASCII/UTF-8, as in the following example:
|
||||
We also support UTF-16 and UTF-32 inputs, as well as ASCII/UTF-8, as in the
|
||||
following example:
|
||||
|
||||
``` C++
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::u16string input = u"3.1416 xyz ";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
std::u16string input = u"3.1416 xyz ";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
|
||||
if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced options: using commas as decimal separator, JSON and Fortran
|
||||
|
||||
## Advanced options: using commas as decimal separator, JSON and Fortran
|
||||
|
||||
The C++ standard stipulate that `from_chars` has to be locale-independent. In
|
||||
particular, the decimal separator has to be the period (`.`). However,
|
||||
some users still want to use the `fast_float` library with in a locale-dependent
|
||||
manner. Using a separate function called `from_chars_advanced`, we allow the users
|
||||
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
|
||||
the comma). You may use it as follows.
|
||||
particular, the decimal separator has to be the period (`.`). However, some
|
||||
users still want to use the `fast_float` library with in a locale-dependent
|
||||
manner. Using a separate function called `from_chars_advanced`, we allow the
|
||||
users to pass a `parse_options` instance which contains a custom decimal
|
||||
separator (e.g., the comma). You may use it as follows.
|
||||
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "3,1416 xyz ";
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::general, ','};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
std::string input = "3,1416 xyz ";
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::general, ','};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
|
||||
if ((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
You can also parse Fortran-like inputs:
|
||||
### You can also parse Fortran-like inputs
|
||||
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "1d+4";
|
||||
double result;
|
||||
fast_float::parse_options options{ fast_float::chars_format::fortran };
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
std::string input = "1d+4";
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::fortran};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
|
||||
if ((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
You may also enforce the JSON format ([RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259#section-6)):
|
||||
|
||||
### You may also enforce the JSON format ([RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259#section-6))
|
||||
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "+.1"; // not valid
|
||||
double result;
|
||||
fast_float::parse_options options{ fast_float::chars_format::json };
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
|
||||
return EXIT_SUCCESS;
|
||||
std::string input = "+.1"; // not valid
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::json};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
|
||||
if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
By default the JSON format does not allow `inf`:
|
||||
|
||||
```C++
|
||||
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "inf"; // not valid in JSON
|
||||
double result;
|
||||
fast_float::parse_options options{ fast_float::chars_format::json };
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if(answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
|
||||
std::string input = "inf"; // not valid in JSON
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::json};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
|
||||
if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
You can allow it with a non-standard `json_or_infnan` variant:
|
||||
|
||||
```C++
|
||||
@@ -276,55 +348,77 @@ You can allow it with a non-standard `json_or_infnan` variant:
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan
|
||||
double result;
|
||||
fast_float::parse_options options{ fast_float::chars_format::json_or_infnan };
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if(answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; }
|
||||
return EXIT_SUCCESS;
|
||||
std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::json_or_infnan};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
|
||||
if (answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; }
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
``````
|
||||
```
|
||||
|
||||
## Relation With Other Work
|
||||
## Users and Related Work
|
||||
|
||||
The fast_float library is part of:
|
||||
|
||||
- GCC (as of version 12): the `from_chars` function in GCC relies on fast_float.
|
||||
- [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's web browser)
|
||||
* GCC (as of version 12): the `from_chars` function in GCC relies on fast_float,
|
||||
* [Chromium](https://github.com/Chromium/Chromium), the engine behind Google
|
||||
Chrome, Microsoft Edge, and Opera,
|
||||
* [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's
|
||||
web browser),
|
||||
* [DuckDB](https://duckdb.org),
|
||||
* [Redis](https://github.com/redis/redis) and [Valkey](https://github.com/valkey-io/valkey),
|
||||
* [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied
|
||||
the number parsing speed by two or three times,
|
||||
* [Google Jsonnet](https://github.com/google/jsonnet),
|
||||
* [ClickHouse](https://github.com/ClickHouse/ClickHouse).
|
||||
|
||||
The fastfloat algorithm is part of the [LLVM standard
|
||||
libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
|
||||
There is a [derived implementation part of
|
||||
AdaCore](https://github.com/AdaCore/VSS).
|
||||
|
||||
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
|
||||
|
||||
There is a [derived implementation part of AdaCore](https://github.com/AdaCore/VSS).
|
||||
|
||||
|
||||
The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).
|
||||
The fast_float library provides a performance similar to that of the
|
||||
[fast_double_parser](https://github.com/lemire/fast_double_parser) library but
|
||||
using an updated algorithm reworked from the ground up, and while offering an
|
||||
API more in line with the expectations of C++ programmers. The
|
||||
fast_double_parser library is part of the [Microsoft LightGBM machine-learning
|
||||
framework](https://github.com/microsoft/LightGBM).
|
||||
|
||||
## References
|
||||
|
||||
- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021.
|
||||
- Noble Mushtak, Daniel Lemire, [Fast Number Parsing Without Fallback](https://arxiv.org/abs/2212.06644), Software: Practice and Experience 53 (7), 2023.
|
||||
* Daniel Lemire, [Number Parsing at a Gigabyte per
|
||||
Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience
|
||||
51 (8), 2021.
|
||||
* Noble Mushtak, Daniel Lemire, [Fast Number Parsing Without
|
||||
Fallback](https://arxiv.org/abs/2212.06644), Software: Practice and Experience
|
||||
53 (7), 2023.
|
||||
|
||||
## Other programming languages
|
||||
|
||||
- [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called `rcppfastfloat`.
|
||||
- [There is a Rust port of the fast_float library](https://github.com/aldanor/fast-float-rust/) called `fast-float-rust`.
|
||||
- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`. It used for important systems such as [Jackson](https://github.com/FasterXML/jackson-core).
|
||||
- [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`.
|
||||
|
||||
|
||||
## Users
|
||||
|
||||
The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet). It is part of GCC (as of GCC 12). It is part of WebKit (Safari).
|
||||
|
||||
* [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called
|
||||
`rcppfastfloat`.
|
||||
* [There is a Rust port of the fast_float
|
||||
library](https://github.com/aldanor/fast-float-rust/) called
|
||||
`fast-float-rust`.
|
||||
* [There is a Java port of the fast_float
|
||||
library](https://github.com/wrandelshofer/FastDoubleParser) called
|
||||
`FastDoubleParser`. It used for important systems such as
|
||||
[Jackson](https://github.com/FasterXML/jackson-core).
|
||||
* [There is a C# port of the fast_float
|
||||
library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`.
|
||||
|
||||
## How fast is it?
|
||||
|
||||
It can parse random floating-point numbers at a speed of 1 GB/s on some systems. We find that it is often twice as fast as the best available competitor, and many times faster than many standard-library implementations.
|
||||
It can parse random floating-point numbers at a speed of 1 GB/s on some systems.
|
||||
We find that it is often twice as fast as the best available competitor, and
|
||||
many times faster than many standard-library implementations.
|
||||
|
||||
<img src="http://lemire.me/blog/wp-content/uploads/2020/11/fastfloat_speed.png" width="400">
|
||||
<img src="https://lemire.me/blog/wp-content/uploads/2020/11/fastfloat_speed.png"
|
||||
width="400" alt="fast_float is many times faster than many standard-library
|
||||
implementations">
|
||||
|
||||
```
|
||||
```bash
|
||||
$ ./build/benchmarks/benchmark
|
||||
# parsing random integers in the range [0,1)
|
||||
volume = 2.09808 MB
|
||||
@@ -335,75 +429,122 @@ abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfl
|
||||
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
|
||||
```
|
||||
|
||||
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
|
||||
|
||||
See the [Benchmarking](#benchmarking) section for instructions on how to run our benchmarks.
|
||||
|
||||
## Video
|
||||
|
||||
[](http://www.youtube.com/watch?v=AVXgvlMeIm4)<br />
|
||||
[](https://www.youtube.com/watch?v=AVXgvlMeIm4)
|
||||
|
||||
## Using as a CMake dependency
|
||||
|
||||
This library is header-only by design. The CMake file provides the `fast_float` target
|
||||
which is merely a pointer to the `include` directory.
|
||||
This library is header-only by design. The CMake file provides the `fast_float`
|
||||
target which is merely a pointer to the `include` directory.
|
||||
|
||||
If you drop the `fast_float` repository in your CMake project, you should be able to use
|
||||
it in this manner:
|
||||
If you drop the `fast_float` repository in your CMake project, you should be
|
||||
able to use it in this manner:
|
||||
|
||||
```cmake
|
||||
add_subdirectory(fast_float)
|
||||
target_link_libraries(myprogram PUBLIC fast_float)
|
||||
```
|
||||
|
||||
Or you may want to retrieve the dependency automatically if you have a sufficiently recent version of CMake (3.11 or better at least):
|
||||
Or you may want to retrieve the dependency automatically if you have a
|
||||
sufficiently recent version of CMake (3.11 or better at least):
|
||||
|
||||
```cmake
|
||||
FetchContent_Declare(
|
||||
fast_float
|
||||
GIT_REPOSITORY https://github.com/lemire/fast_float.git
|
||||
GIT_TAG tags/v1.1.2
|
||||
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
|
||||
GIT_TAG tags/v8.0.2
|
||||
GIT_SHALLOW TRUE)
|
||||
|
||||
FetchContent_MakeAvailable(fast_float)
|
||||
target_link_libraries(myprogram PUBLIC fast_float)
|
||||
|
||||
```
|
||||
|
||||
You should change the `GIT_TAG` line so that you recover the version you wish to use.
|
||||
You should change the `GIT_TAG` line so that you recover the version you wish to
|
||||
use.
|
||||
|
||||
You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so:
|
||||
|
||||
```cmake
|
||||
CPMAddPackage(
|
||||
NAME fast_float
|
||||
GITHUB_REPOSITORY "fastfloat/fast_float"
|
||||
GIT_TAG v8.0.2)
|
||||
```
|
||||
|
||||
## Using as single header
|
||||
|
||||
The script `script/amalgamate.py` may be used to generate a single header
|
||||
version of the library if so desired.
|
||||
Just run the script from the root directory of this repository.
|
||||
You can customize the license type and output file if desired as described in
|
||||
the command line help.
|
||||
version of the library if so desired. Just run the script from the root
|
||||
directory of this repository. You can customize the license type and output file
|
||||
if desired as described in the command line help.
|
||||
|
||||
You may directly download automatically generated single-header files:
|
||||
|
||||
https://github.com/fastfloat/fast_float/releases/download/v6.1.1/fast_float.h
|
||||
<https://github.com/fastfloat/fast_float/releases/download/v8.0.2/fast_float.h>
|
||||
|
||||
## RFC 7159
|
||||
## Benchmarking
|
||||
|
||||
If you need support for RFC 7159 (JSON standard), you may want to consider using the [fast_double_parser](https://github.com/lemire/fast_double_parser/) library instead.
|
||||
The project has its own benchmarks with realistic data inputs. Under Linux or macOS,
|
||||
you can use it as follows if your system supports C++17:
|
||||
|
||||
```
|
||||
cmake -B build -D FASTFLOAT_BENCHMARKS=ON
|
||||
cmake --build build
|
||||
./build/benchmarks/realbenchmark
|
||||
```
|
||||
|
||||
Importantly, by default, the benchmark is built in Release mode.
|
||||
|
||||
The instructions are similar under Windows.
|
||||
|
||||
Under Linux and macOS, it is recommended to run the benchmarks in a privileged manner to get access
|
||||
to hardware performance counters. You may be able to do so with the `sudo` command
|
||||
in some cases:
|
||||
|
||||
```
|
||||
sudo ./build/benchmarks/realbenchmark
|
||||
```
|
||||
|
||||
If you have a text file containing one number per line (`myfile.txt`), you can run a benchmark over it like so:
|
||||
```
|
||||
cmake -B build -D FASTFLOAT_BENCHMARKS=ON
|
||||
cmake --build build
|
||||
./build/benchmarks/realbenchmark myfile.txt
|
||||
```
|
||||
|
||||
|
||||
## Packages
|
||||
|
||||
* The fast_float library is part of the [Conan package
|
||||
manager](https://conan.io/center/recipes/fast_float).
|
||||
* It is part of the [brew package
|
||||
manager](https://formulae.brew.sh/formula/fast_float).
|
||||
* Some Linux distribution like Fedora include fast_float (e.g., as
|
||||
`fast_float-devel`).
|
||||
|
||||
## Credit
|
||||
|
||||
Though this work is inspired by many different people, this work benefited especially from exchanges with
|
||||
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
|
||||
invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits.
|
||||
Though this work is inspired by many different people, this work benefited
|
||||
especially from exchanges with Michael Eisel, who motivated the original
|
||||
research with his key insights, and with Nigel Tao who provided invaluable
|
||||
feedback. Rémy Oudompheng first implemented a fast path we use in the case of
|
||||
long digits.
|
||||
|
||||
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
|
||||
under the Apache 2.0 license.
|
||||
The library includes code adapted from Google Wuffs (written by Nigel Tao) which
|
||||
was originally published under the Apache 2.0 license.
|
||||
|
||||
## License
|
||||
|
||||
<sup>
|
||||
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
|
||||
2.0</a> or <a href="LICENSE-MIT">MIT license</a> or <a href="LICENSE-BOOST">BOOST license</a> .
|
||||
2.0</a> or <a href="LICENSE-MIT">MIT license</a> or <a
|
||||
href="LICENSE-BOOST">BOOST license</a>.
|
||||
</sup>
|
||||
|
||||
<br>
|
||||
<br/>
|
||||
|
||||
<sub>
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
namespace fast_float {
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline constexpr bool has_simd_opt() {
|
||||
template <typename UC> fastfloat_really_inline constexpr bool has_simd_opt() {
|
||||
#ifdef FASTFLOAT_HAS_SIMD
|
||||
return std::is_same<UC, char16_t>::value;
|
||||
#else
|
||||
@@ -37,24 +36,20 @@ fastfloat_really_inline constexpr bool is_integer(UC c) noexcept {
|
||||
}
|
||||
|
||||
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
||||
return (val & 0xFF00000000000000) >> 56
|
||||
| (val & 0x00FF000000000000) >> 40
|
||||
| (val & 0x0000FF0000000000) >> 24
|
||||
| (val & 0x000000FF00000000) >> 8
|
||||
| (val & 0x00000000FF000000) << 8
|
||||
| (val & 0x0000000000FF0000) << 24
|
||||
| (val & 0x000000000000FF00) << 40
|
||||
| (val & 0x00000000000000FF) << 56;
|
||||
return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 |
|
||||
(val & 0x0000FF0000000000) >> 24 | (val & 0x000000FF00000000) >> 8 |
|
||||
(val & 0x00000000FF000000) << 8 | (val & 0x0000000000FF0000) << 24 |
|
||||
(val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56;
|
||||
}
|
||||
|
||||
// Read 8 UC into a u64. Truncates UC if not char.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t read8_to_u64(const UC *chars) {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
read8_to_u64(UC const *chars) {
|
||||
if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) {
|
||||
uint64_t val = 0;
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
val |= uint64_t(uint8_t(*chars)) << (i*8);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
val |= uint64_t(uint8_t(*chars)) << (i * 8);
|
||||
++chars;
|
||||
}
|
||||
return val;
|
||||
@@ -70,44 +65,41 @@ uint64_t read8_to_u64(const UC *chars) {
|
||||
|
||||
#ifdef FASTFLOAT_SSE2
|
||||
|
||||
fastfloat_really_inline
|
||||
uint64_t simd_read8_to_u64(const __m128i data) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
const __m128i packed = _mm_packus_epi16(data, data);
|
||||
fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
__m128i const packed = _mm_packus_epi16(data, data);
|
||||
#ifdef FASTFLOAT_64BIT
|
||||
return uint64_t(_mm_cvtsi128_si64(packed));
|
||||
#else
|
||||
uint64_t value;
|
||||
// Visual Studio + older versions of GCC don't support _mm_storeu_si64
|
||||
_mm_storel_epi64(reinterpret_cast<__m128i*>(&value), packed);
|
||||
_mm_storel_epi64(reinterpret_cast<__m128i *>(&value), packed);
|
||||
return value;
|
||||
#endif
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
}
|
||||
|
||||
fastfloat_really_inline
|
||||
uint64_t simd_read8_to_u64(const char16_t* chars) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
return simd_read8_to_u64(_mm_loadu_si128(reinterpret_cast<const __m128i*>(chars)));
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
return simd_read8_to_u64(
|
||||
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars)));
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
}
|
||||
|
||||
#elif defined(FASTFLOAT_NEON)
|
||||
|
||||
|
||||
fastfloat_really_inline
|
||||
uint64_t simd_read8_to_u64(const uint16x8_t data) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
fastfloat_really_inline uint64_t simd_read8_to_u64(uint16x8_t const data) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
uint8x8_t utf8_packed = vmovn_u16(data);
|
||||
return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0);
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
}
|
||||
|
||||
fastfloat_really_inline
|
||||
uint64_t simd_read8_to_u64(const char16_t* chars) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
return simd_read8_to_u64(vld1q_u16(reinterpret_cast<const uint16_t*>(chars)));
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
return simd_read8_to_u64(
|
||||
vld1q_u16(reinterpret_cast<uint16_t const *>(chars)));
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
}
|
||||
|
||||
#endif // FASTFLOAT_SSE2
|
||||
@@ -119,101 +111,84 @@ template <typename UC>
|
||||
template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0>
|
||||
#endif
|
||||
// dummy for compile
|
||||
uint64_t simd_read8_to_u64(UC const*) {
|
||||
uint64_t simd_read8_to_u64(UC const *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void write_u64(uint8_t *chars, uint64_t val) {
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
*chars = uint8_t(val);
|
||||
val >>= 8;
|
||||
++chars;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if FASTFLOAT_IS_BIG_ENDIAN == 1
|
||||
// Need to read as-if the number was in little-endian order.
|
||||
val = byteswap(val);
|
||||
#endif
|
||||
::memcpy(chars, &val, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
// credit @aqrit
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
uint32_t parse_eight_digits_unrolled(uint64_t val) {
|
||||
const uint64_t mask = 0x000000FF000000FF;
|
||||
const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
|
||||
const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
|
||||
parse_eight_digits_unrolled(uint64_t val) {
|
||||
uint64_t const mask = 0x000000FF000000FF;
|
||||
uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
|
||||
uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
|
||||
val -= 0x3030303030303030;
|
||||
val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
|
||||
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
||||
return uint32_t(val);
|
||||
}
|
||||
|
||||
|
||||
// Call this if chars are definitely 8 digits.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint32_t parse_eight_digits_unrolled(UC const * chars) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t
|
||||
parse_eight_digits_unrolled(UC const *chars) noexcept {
|
||||
if (cpp20_and_in_constexpr() || !has_simd_opt<UC>()) {
|
||||
return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay
|
||||
}
|
||||
return parse_eight_digits_unrolled(simd_read8_to_u64(chars));
|
||||
}
|
||||
|
||||
|
||||
// credit @aqrit
|
||||
fastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val) noexcept {
|
||||
fastfloat_really_inline constexpr bool
|
||||
is_made_of_eight_digits_fast(uint64_t val) noexcept {
|
||||
return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) &
|
||||
0x8080808080808080));
|
||||
0x8080808080808080));
|
||||
}
|
||||
|
||||
|
||||
#ifdef FASTFLOAT_HAS_SIMD
|
||||
|
||||
// Call this if chars might not be 8 digits.
|
||||
// Using this style (instead of is_made_of_eight_digits_fast() then parse_eight_digits_unrolled())
|
||||
// ensures we don't load SIMD registers twice.
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
bool simd_parse_if_eight_digits_unrolled(const char16_t* chars, uint64_t& i) noexcept {
|
||||
// Using this style (instead of is_made_of_eight_digits_fast() then
|
||||
// parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice.
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||
simd_parse_if_eight_digits_unrolled(char16_t const *chars,
|
||||
uint64_t &i) noexcept {
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef FASTFLOAT_SSE2
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
const __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i*>(chars));
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
__m128i const data =
|
||||
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars));
|
||||
|
||||
// (x - '0') <= 9
|
||||
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
||||
const __m128i t0 = _mm_add_epi16(data, _mm_set1_epi16(32720));
|
||||
const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759));
|
||||
__m128i const t0 = _mm_add_epi16(data, _mm_set1_epi16(32720));
|
||||
__m128i const t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759));
|
||||
|
||||
if (_mm_movemask_epi8(t1) == 0) {
|
||||
i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
} else
|
||||
return false;
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
#elif defined(FASTFLOAT_NEON)
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
const uint16x8_t data = vld1q_u16(reinterpret_cast<const uint16_t*>(chars));
|
||||
|
||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||
uint16x8_t const data = vld1q_u16(reinterpret_cast<uint16_t const *>(chars));
|
||||
|
||||
// (x - '0') <= 9
|
||||
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
||||
const uint16x8_t t0 = vsubq_u16(data, vmovq_n_u16('0'));
|
||||
const uint16x8_t mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1));
|
||||
uint16x8_t const t0 = vsubq_u16(data, vmovq_n_u16('0'));
|
||||
uint16x8_t const mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1));
|
||||
|
||||
if (vminvq_u16(mask) == 0xFFFF) {
|
||||
i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
} else
|
||||
return false;
|
||||
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||
#else
|
||||
(void)chars; (void)i;
|
||||
(void)chars;
|
||||
(void)i;
|
||||
return false;
|
||||
#endif // FASTFLOAT_SSE2
|
||||
}
|
||||
@@ -227,79 +202,119 @@ template <typename UC>
|
||||
template <typename UC, FASTFLOAT_ENABLE_IF(!has_simd_opt<UC>()) = 0>
|
||||
#endif
|
||||
// dummy for compile
|
||||
bool simd_parse_if_eight_digits_unrolled(UC const*, uint64_t&) {
|
||||
bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template <typename UC, FASTFLOAT_ENABLE_IF(!std::is_same<UC, char>::value) = 0>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void loop_parse_if_eight_digits(const UC*& p, const UC* const pend, uint64_t& i) {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
loop_parse_if_eight_digits(UC const *&p, UC const *const pend, uint64_t &i) {
|
||||
if (!has_simd_opt<UC>()) {
|
||||
return;
|
||||
}
|
||||
while ((std::distance(p, pend) >= 8) && simd_parse_if_eight_digits_unrolled(p, i)) { // in rare cases, this will overflow, but that's ok
|
||||
while ((std::distance(p, pend) >= 8) &&
|
||||
simd_parse_if_eight_digits_unrolled(
|
||||
p, i)) { // in rare cases, this will overflow, but that's ok
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void loop_parse_if_eight_digits(const char*& p, const char* const pend, uint64_t& i) {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
loop_parse_if_eight_digits(char const *&p, char const *const pend,
|
||||
uint64_t &i) {
|
||||
// optimizes better than parse_if_eight_digits_unrolled() for UC = char.
|
||||
while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(read8_to_u64(p))) {
|
||||
i = i * 100000000 + parse_eight_digits_unrolled(read8_to_u64(p)); // in rare cases, this will overflow, but that's ok
|
||||
while ((std::distance(p, pend) >= 8) &&
|
||||
is_made_of_eight_digits_fast(read8_to_u64(p))) {
|
||||
i = i * 100000000 +
|
||||
parse_eight_digits_unrolled(read8_to_u64(
|
||||
p)); // in rare cases, this will overflow, but that's ok
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UC>
|
||||
struct parsed_number_string_t {
|
||||
enum class parse_error {
|
||||
no_error,
|
||||
// [JSON-only] The minus sign must be followed by an integer.
|
||||
missing_integer_after_sign,
|
||||
// A sign must be followed by an integer or dot.
|
||||
missing_integer_or_dot_after_sign,
|
||||
// [JSON-only] The integer part must not have leading zeros.
|
||||
leading_zeros_in_integer_part,
|
||||
// [JSON-only] The integer part must have at least one digit.
|
||||
no_digits_in_integer_part,
|
||||
// [JSON-only] If there is a decimal point, there must be digits in the
|
||||
// fractional part.
|
||||
no_digits_in_fractional_part,
|
||||
// The mantissa must have at least one digit.
|
||||
no_digits_in_mantissa,
|
||||
// Scientific notation requires an exponential part.
|
||||
missing_exponential_part,
|
||||
};
|
||||
|
||||
template <typename UC> struct parsed_number_string_t {
|
||||
int64_t exponent{0};
|
||||
uint64_t mantissa{0};
|
||||
UC const * lastmatch{nullptr};
|
||||
UC const *lastmatch{nullptr};
|
||||
bool negative{false};
|
||||
bool valid{false};
|
||||
bool too_many_digits{false};
|
||||
// contains the range of the significant digits
|
||||
span<const UC> integer{}; // non-nullable
|
||||
span<const UC> fraction{}; // nullable
|
||||
span<UC const> integer{}; // non-nullable
|
||||
span<UC const> fraction{}; // nullable
|
||||
parse_error error{parse_error::no_error};
|
||||
};
|
||||
|
||||
using byte_span = span<const char>;
|
||||
using byte_span = span<char const>;
|
||||
using parsed_number_string = parsed_number_string_t<char>;
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t<UC>
|
||||
report_parse_error(UC const *p, parse_error error) {
|
||||
parsed_number_string_t<UC> answer;
|
||||
answer.valid = false;
|
||||
answer.lastmatch = p;
|
||||
answer.error = error;
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Assuming that you use no more than 19 digits, this will
|
||||
// parse an ASCII string.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, parse_options_t<UC> options) noexcept {
|
||||
chars_format const fmt = options.format;
|
||||
template <bool basic_json_fmt, typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t<UC>
|
||||
parse_number_string(UC const *p, UC const *pend,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
chars_format const fmt = detail::adjust_for_feature_macros(options.format);
|
||||
UC const decimal_point = options.decimal_point;
|
||||
|
||||
parsed_number_string_t<UC> answer;
|
||||
answer.valid = false;
|
||||
answer.too_many_digits = false;
|
||||
// assume p < pend, so dereference without checks;
|
||||
answer.negative = (*p == UC('-'));
|
||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||
if ((*p == UC('-')) || (!(fmt & FASTFLOAT_JSONFMT) && *p == UC('+'))) {
|
||||
#else
|
||||
if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
#endif
|
||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
if ((*p == UC('-')) || (uint64_t(fmt & chars_format::allow_leading_plus) &&
|
||||
!basic_json_fmt && *p == UC('+'))) {
|
||||
++p;
|
||||
if (p == pend) {
|
||||
return answer;
|
||||
return report_parse_error<UC>(
|
||||
p, parse_error::missing_integer_or_dot_after_sign);
|
||||
}
|
||||
if (fmt & FASTFLOAT_JSONFMT) {
|
||||
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
||||
if (!is_integer(*p)) { // a sign must be followed by an integer
|
||||
return answer;
|
||||
}
|
||||
} else {
|
||||
if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot
|
||||
return answer;
|
||||
return report_parse_error<UC>(p,
|
||||
parse_error::missing_integer_after_sign);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!is_integer(*p) &&
|
||||
(*p !=
|
||||
decimal_point)) { // a sign must be followed by an integer or the dot
|
||||
return report_parse_error<UC>(
|
||||
p, parse_error::missing_integer_or_dot_after_sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
UC const * const start_digits = p;
|
||||
UC const *const start_digits = p;
|
||||
|
||||
uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
|
||||
|
||||
@@ -307,24 +322,29 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
// a multiplication by 10 is cheaper than an arbitrary integer
|
||||
// multiplication
|
||||
i = 10 * i +
|
||||
uint64_t(*p - UC('0')); // might overflow, we will handle the overflow later
|
||||
uint64_t(*p -
|
||||
UC('0')); // might overflow, we will handle the overflow later
|
||||
++p;
|
||||
}
|
||||
UC const * const end_of_integer_part = p;
|
||||
UC const *const end_of_integer_part = p;
|
||||
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
||||
answer.integer = span<const UC>(start_digits, size_t(digit_count));
|
||||
if (fmt & FASTFLOAT_JSONFMT) {
|
||||
answer.integer = span<UC const>(start_digits, size_t(digit_count));
|
||||
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
||||
// at least 1 digit in integer part, without leading zeros
|
||||
if (digit_count == 0 || (start_digits[0] == UC('0') && digit_count > 1)) {
|
||||
return answer;
|
||||
if (digit_count == 0) {
|
||||
return report_parse_error<UC>(p, parse_error::no_digits_in_integer_part);
|
||||
}
|
||||
if ((start_digits[0] == UC('0') && digit_count > 1)) {
|
||||
return report_parse_error<UC>(start_digits,
|
||||
parse_error::leading_zeros_in_integer_part);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t exponent = 0;
|
||||
const bool has_decimal_point = (p != pend) && (*p == decimal_point);
|
||||
bool const has_decimal_point = (p != pend) && (*p == decimal_point);
|
||||
if (has_decimal_point) {
|
||||
++p;
|
||||
UC const * before = p;
|
||||
UC const *before = p;
|
||||
// can occur at most twice without overflowing, but let it occur more, since
|
||||
// for integers with many digits, digit parsing is the primary bottleneck.
|
||||
loop_parse_if_eight_digits(p, pend, i);
|
||||
@@ -335,41 +355,45 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
|
||||
}
|
||||
exponent = before - p;
|
||||
answer.fraction = span<const UC>(before, size_t(p - before));
|
||||
answer.fraction = span<UC const>(before, size_t(p - before));
|
||||
digit_count -= exponent;
|
||||
}
|
||||
if (fmt & FASTFLOAT_JSONFMT) {
|
||||
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
||||
// at least 1 digit in fractional part
|
||||
if (has_decimal_point && exponent == 0) {
|
||||
return answer;
|
||||
return report_parse_error<UC>(p,
|
||||
parse_error::no_digits_in_fractional_part);
|
||||
}
|
||||
}
|
||||
else if (digit_count == 0) { // we must have encountered at least one integer!
|
||||
return answer;
|
||||
}
|
||||
int64_t exp_number = 0; // explicit exponential part
|
||||
if ( ((fmt & chars_format::scientific) &&
|
||||
(p != pend) &&
|
||||
((UC('e') == *p) || (UC('E') == *p)))
|
||||
||
|
||||
((fmt & FASTFLOAT_FORTRANFMT) &&
|
||||
(p != pend) &&
|
||||
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || (UC('D') == *p)))) {
|
||||
UC const * location_of_e = p;
|
||||
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || (UC('D') == *p)) {
|
||||
else if (digit_count == 0) { // we must have encountered at least one integer!
|
||||
return report_parse_error<UC>(p, parse_error::no_digits_in_mantissa);
|
||||
}
|
||||
int64_t exp_number = 0; // explicit exponential part
|
||||
if ((uint64_t(fmt & chars_format::scientific) && (p != pend) &&
|
||||
((UC('e') == *p) || (UC('E') == *p))) ||
|
||||
(uint64_t(fmt & detail::basic_fortran_fmt) && (p != pend) &&
|
||||
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) ||
|
||||
(UC('D') == *p)))) {
|
||||
UC const *location_of_e = p;
|
||||
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) ||
|
||||
(UC('D') == *p)) {
|
||||
++p;
|
||||
}
|
||||
bool neg_exp = false;
|
||||
if ((p != pend) && (UC('-') == *p)) {
|
||||
neg_exp = true;
|
||||
++p;
|
||||
} else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
||||
} else if ((p != pend) &&
|
||||
(UC('+') ==
|
||||
*p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
||||
++p;
|
||||
}
|
||||
if ((p == pend) || !is_integer(*p)) {
|
||||
if(!(fmt & chars_format::fixed)) {
|
||||
// We are in error.
|
||||
return answer;
|
||||
if (!uint64_t(fmt & chars_format::fixed)) {
|
||||
// The exponential part is invalid for scientific notation, so it must
|
||||
// be a trailing token for fixed notation. However, fixed notation is
|
||||
// disabled, so report a scientific notation error.
|
||||
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
||||
}
|
||||
// Otherwise, we will be ignoring the 'e'.
|
||||
p = location_of_e;
|
||||
@@ -381,12 +405,17 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
}
|
||||
++p;
|
||||
}
|
||||
if(neg_exp) { exp_number = - exp_number; }
|
||||
if (neg_exp) {
|
||||
exp_number = -exp_number;
|
||||
}
|
||||
exponent += exp_number;
|
||||
}
|
||||
} else {
|
||||
// If it scientific and not fixed, we have to bail out.
|
||||
if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; }
|
||||
if (uint64_t(fmt & chars_format::scientific) &&
|
||||
!uint64_t(fmt & chars_format::fixed)) {
|
||||
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
||||
}
|
||||
}
|
||||
answer.lastmatch = p;
|
||||
answer.valid = true;
|
||||
@@ -401,9 +430,11 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
// We have to handle the case where we have 0.0000somenumber.
|
||||
// We need to be mindful of the case where we only have zeroes...
|
||||
// E.g., 0.000000000...000.
|
||||
UC const * start = start_digits;
|
||||
UC const *start = start_digits;
|
||||
while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {
|
||||
if(*start == UC('0')) { digit_count --; }
|
||||
if (*start == UC('0')) {
|
||||
digit_count--;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
@@ -414,18 +445,17 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
// pre-tokenized spans from above.
|
||||
i = 0;
|
||||
p = answer.integer.ptr;
|
||||
UC const* int_end = p + answer.integer.len();
|
||||
const uint64_t minimal_nineteen_digit_integer{ 1000000000000000000 };
|
||||
UC const *int_end = p + answer.integer.len();
|
||||
uint64_t const minimal_nineteen_digit_integer{1000000000000000000};
|
||||
while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
|
||||
i = i * 10 + uint64_t(*p - UC('0'));
|
||||
++p;
|
||||
}
|
||||
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
|
||||
exponent = end_of_integer_part - p + exp_number;
|
||||
}
|
||||
else { // We have a value with a fractional component.
|
||||
} else { // We have a value with a fractional component.
|
||||
p = answer.fraction.ptr;
|
||||
UC const* frac_end = p + answer.fraction.len();
|
||||
UC const *frac_end = p + answer.fraction.len();
|
||||
while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
|
||||
i = i * 10 + uint64_t(*p - UC('0'));
|
||||
++p;
|
||||
@@ -441,35 +471,43 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
||||
}
|
||||
|
||||
template <typename T, typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value, int base) {
|
||||
from_chars_result_t<UC> answer;
|
||||
|
||||
UC const* const first = p;
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
parse_options_t<UC> options) {
|
||||
chars_format const fmt = detail::adjust_for_feature_macros(options.format);
|
||||
int const base = options.base;
|
||||
|
||||
bool negative = (*p == UC('-'));
|
||||
from_chars_result_t<UC> answer;
|
||||
|
||||
UC const *const first = p;
|
||||
|
||||
bool const negative = (*p == UC('-'));
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
if (!std::is_signed<T>::value && negative) {
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||
if ((*p == UC('-')) || (*p == UC('+'))) {
|
||||
#else
|
||||
if (*p == UC('-')) {
|
||||
#endif
|
||||
if ((*p == UC('-')) ||
|
||||
(uint64_t(fmt & chars_format::allow_leading_plus) && (*p == UC('+')))) {
|
||||
++p;
|
||||
}
|
||||
|
||||
UC const* const start_num = p;
|
||||
UC const *const start_num = p;
|
||||
|
||||
while (p!= pend && *p == UC('0')) {
|
||||
++p;
|
||||
while (p != pend && *p == UC('0')) {
|
||||
++p;
|
||||
}
|
||||
|
||||
const bool has_leading_zeros = p > start_num;
|
||||
bool const has_leading_zeros = p > start_num;
|
||||
|
||||
UC const* const start_digits = p;
|
||||
UC const *const start_digits = p;
|
||||
|
||||
uint64_t i = 0;
|
||||
if (base == 10) {
|
||||
@@ -481,9 +519,9 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
||||
break;
|
||||
}
|
||||
i = uint64_t(base) * i + digit; // might overflow, check this later
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
|
||||
size_t digit_count = size_t(p - start_digits);
|
||||
|
||||
if (digit_count == 0) {
|
||||
@@ -491,12 +529,11 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
||||
value = 0;
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
}
|
||||
return answer;
|
||||
return answer;
|
||||
}
|
||||
|
||||
answer.ptr = p;
|
||||
@@ -507,7 +544,8 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
return answer;
|
||||
}
|
||||
// this check can be eliminated for all other types, but they will all require a max_digits(base) equivalent
|
||||
// this check can be eliminated for all other types, but they will all require
|
||||
// a max_digits(base) equivalent
|
||||
if (digit_count == max_digits && i < min_safe_u64(base)) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
return answer;
|
||||
@@ -524,18 +562,22 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
||||
if (negative) {
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4146)
|
||||
#pragma warning(disable : 4146)
|
||||
#endif
|
||||
// this weird workaround is required because:
|
||||
// - converting unsigned to signed when its value is greater than signed max is UB pre-C++23.
|
||||
// - converting unsigned to signed when its value is greater than signed max
|
||||
// is UB pre-C++23.
|
||||
// - reinterpret_casting (~i + 1) would work, but it is not constexpr
|
||||
// this is always optimized into a neg instruction (note: T is an integer type)
|
||||
value = T(-std::numeric_limits<T>::max() - T(i - uint64_t(std::numeric_limits<T>::max())));
|
||||
// this is always optimized into a neg instruction (note: T is an integer
|
||||
// type)
|
||||
value = T(-std::numeric_limits<T>::max() -
|
||||
T(i - uint64_t(std::numeric_limits<T>::max())));
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
} else {
|
||||
value = T(i);
|
||||
}
|
||||
else { value = T(i); }
|
||||
|
||||
answer.ec = std::errc();
|
||||
return answer;
|
||||
|
||||
223
3rdparty/fast_float/include/fast_float/bigint.h
vendored
223
3rdparty/fast_float/include/fast_float/bigint.h
vendored
@@ -37,15 +37,14 @@ constexpr size_t bigint_limbs = bigint_bits / limb_bits;
|
||||
|
||||
// vector-like type that is allocated on the stack. the entire
|
||||
// buffer is pre-allocated, and only the length changes.
|
||||
template <uint16_t size>
|
||||
struct stackvec {
|
||||
template <uint16_t size> struct stackvec {
|
||||
limb data[size];
|
||||
// we never need more than 150 limbs
|
||||
uint16_t length{0};
|
||||
|
||||
stackvec() = default;
|
||||
stackvec(const stackvec &) = delete;
|
||||
stackvec &operator=(const stackvec &) = delete;
|
||||
stackvec(stackvec const &) = delete;
|
||||
stackvec &operator=(stackvec const &) = delete;
|
||||
stackvec(stackvec &&) = delete;
|
||||
stackvec &operator=(stackvec &&other) = delete;
|
||||
|
||||
@@ -54,16 +53,18 @@ struct stackvec {
|
||||
FASTFLOAT_ASSERT(try_extend(s));
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR14 limb& operator[](size_t index) noexcept {
|
||||
FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept {
|
||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||
return data[index];
|
||||
}
|
||||
FASTFLOAT_CONSTEXPR14 const limb& operator[](size_t index) const noexcept {
|
||||
|
||||
FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept {
|
||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
// index from the end of the container
|
||||
FASTFLOAT_CONSTEXPR14 const limb& rindex(size_t index) const noexcept {
|
||||
FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept {
|
||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||
size_t rindex = length - index - 1;
|
||||
return data[rindex];
|
||||
@@ -73,20 +74,19 @@ struct stackvec {
|
||||
FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
|
||||
length = uint16_t(len);
|
||||
}
|
||||
constexpr size_t len() const noexcept {
|
||||
return length;
|
||||
}
|
||||
constexpr bool is_empty() const noexcept {
|
||||
return length == 0;
|
||||
}
|
||||
constexpr size_t capacity() const noexcept {
|
||||
return size;
|
||||
}
|
||||
|
||||
constexpr size_t len() const noexcept { return length; }
|
||||
|
||||
constexpr bool is_empty() const noexcept { return length == 0; }
|
||||
|
||||
constexpr size_t capacity() const noexcept { return size; }
|
||||
|
||||
// append item to vector, without bounds checking
|
||||
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
|
||||
data[length] = value;
|
||||
length++;
|
||||
}
|
||||
|
||||
// append item to vector, returning if item was added
|
||||
FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
|
||||
if (len() < capacity()) {
|
||||
@@ -96,12 +96,14 @@ struct stackvec {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// add items to the vector, from a span, without bounds checking
|
||||
FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
|
||||
limb* ptr = data + length;
|
||||
limb *ptr = data + length;
|
||||
std::copy_n(s.ptr, s.len(), ptr);
|
||||
set_len(len() + s.len());
|
||||
}
|
||||
|
||||
// try to add items to the vector, returning if items were added
|
||||
FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {
|
||||
if (len() + s.len() <= capacity()) {
|
||||
@@ -111,6 +113,7 @@ struct stackvec {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// resize the vector, without bounds checking
|
||||
// if the new size is longer than the vector, assign value to each
|
||||
// appended item.
|
||||
@@ -118,14 +121,15 @@ struct stackvec {
|
||||
void resize_unchecked(size_t new_len, limb value) noexcept {
|
||||
if (new_len > len()) {
|
||||
size_t count = new_len - len();
|
||||
limb* first = data + len();
|
||||
limb* last = first + count;
|
||||
limb *first = data + len();
|
||||
limb *last = first + count;
|
||||
::std::fill(first, last, value);
|
||||
set_len(new_len);
|
||||
} else {
|
||||
set_len(new_len);
|
||||
}
|
||||
}
|
||||
|
||||
// try to resize the vector, returning if the vector was resized.
|
||||
FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {
|
||||
if (new_len > capacity()) {
|
||||
@@ -135,6 +139,7 @@ struct stackvec {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// check if any limbs are non-zero after the given index.
|
||||
// this needs to be done in reverse order, since the index
|
||||
// is relative to the most significant limbs.
|
||||
@@ -147,6 +152,7 @@ struct stackvec {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize the big integer, so most-significant zero limbs are removed.
|
||||
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
|
||||
while (len() > 0 && rindex(0) == 0) {
|
||||
@@ -155,21 +161,21 @@ struct stackvec {
|
||||
}
|
||||
};
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
uint64_t empty_hi64(bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t
|
||||
empty_hi64(bool &truncated) noexcept {
|
||||
truncated = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t uint64_hi64(uint64_t r0, bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
uint64_hi64(uint64_t r0, bool &truncated) noexcept {
|
||||
truncated = false;
|
||||
int shl = leading_zeroes(r0);
|
||||
return r0 << shl;
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
uint64_hi64(uint64_t r0, uint64_t r1, bool &truncated) noexcept {
|
||||
int shl = leading_zeroes(r0);
|
||||
if (shl == 0) {
|
||||
truncated = r1 != 0;
|
||||
@@ -181,20 +187,20 @@ uint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t uint32_hi64(uint32_t r0, bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
uint32_hi64(uint32_t r0, bool &truncated) noexcept {
|
||||
return uint64_hi64(r0, truncated);
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t uint32_hi64(uint32_t r0, uint32_t r1, bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
uint32_hi64(uint32_t r0, uint32_t r1, bool &truncated) noexcept {
|
||||
uint64_t x0 = r0;
|
||||
uint64_t x1 = r1;
|
||||
return uint64_hi64((x0 << 32) | x1, truncated);
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
uint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool &truncated) noexcept {
|
||||
uint64_t x0 = r0;
|
||||
uint64_t x1 = r1;
|
||||
uint64_t x2 = r2;
|
||||
@@ -205,17 +211,17 @@ uint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noe
|
||||
// we want an efficient operation. for msvc, where
|
||||
// we don't have built-in intrinsics, this is still
|
||||
// pretty fast.
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
limb scalar_add(limb x, limb y, bool& overflow) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb
|
||||
scalar_add(limb x, limb y, bool &overflow) noexcept {
|
||||
limb z;
|
||||
// gcc and clang
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_add_overflow)
|
||||
if (!cpp20_and_in_constexpr()) {
|
||||
overflow = __builtin_add_overflow(x, y, &z);
|
||||
return z;
|
||||
}
|
||||
#endif
|
||||
#if __has_builtin(__builtin_add_overflow)
|
||||
if (!cpp20_and_in_constexpr()) {
|
||||
overflow = __builtin_add_overflow(x, y, &z);
|
||||
return z;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// generic, this still optimizes correctly on MSVC.
|
||||
@@ -225,24 +231,24 @@ limb scalar_add(limb x, limb y, bool& overflow) noexcept {
|
||||
}
|
||||
|
||||
// multiply two small integers, getting both the high and low bits.
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
limb scalar_mul(limb x, limb y, limb& carry) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb
|
||||
scalar_mul(limb x, limb y, limb &carry) noexcept {
|
||||
#ifdef FASTFLOAT_64BIT_LIMB
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
// GCC and clang both define it as an extension.
|
||||
__uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry);
|
||||
carry = limb(z >> limb_bits);
|
||||
return limb(z);
|
||||
#else
|
||||
#else
|
||||
// fallback, no native 128-bit integer multiplication with carry.
|
||||
// on msvc, this optimizes identically, somehow.
|
||||
value128 z = full_multiplication(x, y);
|
||||
bool overflow;
|
||||
z.low = scalar_add(z.low, carry, overflow);
|
||||
z.high += uint64_t(overflow); // cannot overflow
|
||||
z.high += uint64_t(overflow); // cannot overflow
|
||||
carry = z.high;
|
||||
return z.low;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry);
|
||||
carry = limb(z >> limb_bits);
|
||||
@@ -253,8 +259,8 @@ limb scalar_mul(limb x, limb y, limb& carry) noexcept {
|
||||
// add scalar value to bigint starting from offset.
|
||||
// used in grade school multiplication
|
||||
template <uint16_t size>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
bool small_add_from(stackvec<size>& vec, limb y, size_t start) noexcept {
|
||||
inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
||||
size_t start) noexcept {
|
||||
size_t index = start;
|
||||
limb carry = y;
|
||||
bool overflow;
|
||||
@@ -271,15 +277,15 @@ bool small_add_from(stackvec<size>& vec, limb y, size_t start) noexcept {
|
||||
|
||||
// add scalar value to bigint.
|
||||
template <uint16_t size>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
bool small_add(stackvec<size>& vec, limb y) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||
small_add(stackvec<size> &vec, limb y) noexcept {
|
||||
return small_add_from(vec, y, 0);
|
||||
}
|
||||
|
||||
// multiply bigint by scalar value.
|
||||
template <uint16_t size>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
bool small_mul(stackvec<size>& vec, limb y) noexcept {
|
||||
inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec<size> &vec,
|
||||
limb y) noexcept {
|
||||
limb carry = 0;
|
||||
for (size_t index = 0; index < vec.len(); index++) {
|
||||
vec[index] = scalar_mul(vec[index], y, carry);
|
||||
@@ -293,12 +299,12 @@ bool small_mul(stackvec<size>& vec, limb y) noexcept {
|
||||
// add bigint to bigint starting from index.
|
||||
// used in grade school multiplication
|
||||
template <uint16_t size>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
bool large_add_from(stackvec<size>& x, limb_span y, size_t start) noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
||||
size_t start) noexcept {
|
||||
// the effective x buffer is from `xstart..x.len()`, so exit early
|
||||
// if we can't get that current range.
|
||||
if (x.len() < start || y.len() > x.len() - start) {
|
||||
FASTFLOAT_TRY(x.try_resize(y.len() + start, 0));
|
||||
FASTFLOAT_TRY(x.try_resize(y.len() + start, 0));
|
||||
}
|
||||
|
||||
bool carry = false;
|
||||
@@ -324,15 +330,14 @@ bool large_add_from(stackvec<size>& x, limb_span y, size_t start) noexcept {
|
||||
|
||||
// add bigint to bigint.
|
||||
template <uint16_t size>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
bool large_add_from(stackvec<size>& x, limb_span y) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||
large_add_from(stackvec<size> &x, limb_span y) noexcept {
|
||||
return large_add_from(x, y, 0);
|
||||
}
|
||||
|
||||
// grade-school multiplication algorithm
|
||||
template <uint16_t size>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
bool long_mul(stackvec<size>& x, limb_span y) noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
|
||||
limb_span xs = limb_span(x.data, x.len());
|
||||
stackvec<size> z(xs);
|
||||
limb_span zs = limb_span(z.data, z.len());
|
||||
@@ -360,8 +365,7 @@ bool long_mul(stackvec<size>& x, limb_span y) noexcept {
|
||||
|
||||
// grade-school multiplication algorithm
|
||||
template <uint16_t size>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
bool large_mul(stackvec<size>& x, limb_span y) noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec<size> &x, limb_span y) noexcept {
|
||||
if (y.len() == 1) {
|
||||
FASTFLOAT_TRY(small_mul(x, y[0]));
|
||||
} else {
|
||||
@@ -370,36 +374,58 @@ bool large_mul(stackvec<size>& x, limb_span y) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename = void>
|
||||
struct pow5_tables {
|
||||
template <typename = void> struct pow5_tables {
|
||||
static constexpr uint32_t large_step = 135;
|
||||
static constexpr uint64_t small_power_of_5[] = {
|
||||
1UL, 5UL, 25UL, 125UL, 625UL, 3125UL, 15625UL, 78125UL, 390625UL,
|
||||
1953125UL, 9765625UL, 48828125UL, 244140625UL, 1220703125UL,
|
||||
6103515625UL, 30517578125UL, 152587890625UL, 762939453125UL,
|
||||
3814697265625UL, 19073486328125UL, 95367431640625UL, 476837158203125UL,
|
||||
2384185791015625UL, 11920928955078125UL, 59604644775390625UL,
|
||||
298023223876953125UL, 1490116119384765625UL, 7450580596923828125UL,
|
||||
1UL,
|
||||
5UL,
|
||||
25UL,
|
||||
125UL,
|
||||
625UL,
|
||||
3125UL,
|
||||
15625UL,
|
||||
78125UL,
|
||||
390625UL,
|
||||
1953125UL,
|
||||
9765625UL,
|
||||
48828125UL,
|
||||
244140625UL,
|
||||
1220703125UL,
|
||||
6103515625UL,
|
||||
30517578125UL,
|
||||
152587890625UL,
|
||||
762939453125UL,
|
||||
3814697265625UL,
|
||||
19073486328125UL,
|
||||
95367431640625UL,
|
||||
476837158203125UL,
|
||||
2384185791015625UL,
|
||||
11920928955078125UL,
|
||||
59604644775390625UL,
|
||||
298023223876953125UL,
|
||||
1490116119384765625UL,
|
||||
7450580596923828125UL,
|
||||
};
|
||||
#ifdef FASTFLOAT_64BIT_LIMB
|
||||
constexpr static limb large_power_of_5[] = {
|
||||
1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL,
|
||||
10482974169319127550UL, 198276706040285095UL};
|
||||
1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL,
|
||||
10482974169319127550UL, 198276706040285095UL};
|
||||
#else
|
||||
constexpr static limb large_power_of_5[] = {
|
||||
4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U,
|
||||
1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U};
|
||||
4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U,
|
||||
1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U};
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr uint32_t pow5_tables<T>::large_step;
|
||||
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
||||
|
||||
template <typename T>
|
||||
constexpr uint64_t pow5_tables<T>::small_power_of_5[];
|
||||
template <typename T> constexpr uint32_t pow5_tables<T>::large_step;
|
||||
|
||||
template <typename T>
|
||||
constexpr limb pow5_tables<T>::large_power_of_5[];
|
||||
template <typename T> constexpr uint64_t pow5_tables<T>::small_power_of_5[];
|
||||
|
||||
template <typename T> constexpr limb pow5_tables<T>::large_power_of_5[];
|
||||
|
||||
#endif
|
||||
|
||||
// big integer type. implements a small subset of big integer
|
||||
// arithmetic, using simple algorithms since asymptotically
|
||||
@@ -409,13 +435,14 @@ struct bigint : pow5_tables<> {
|
||||
// storage of the limbs, in little-endian order.
|
||||
stackvec<bigint_limbs> vec;
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 bigint(): vec() {}
|
||||
bigint(const bigint &) = delete;
|
||||
bigint &operator=(const bigint &) = delete;
|
||||
FASTFLOAT_CONSTEXPR20 bigint() : vec() {}
|
||||
|
||||
bigint(bigint const &) = delete;
|
||||
bigint &operator=(bigint const &) = delete;
|
||||
bigint(bigint &&) = delete;
|
||||
bigint &operator=(bigint &&other) = delete;
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 bigint(uint64_t value): vec() {
|
||||
FASTFLOAT_CONSTEXPR20 bigint(uint64_t value) : vec() {
|
||||
#ifdef FASTFLOAT_64BIT_LIMB
|
||||
vec.push_unchecked(value);
|
||||
#else
|
||||
@@ -427,7 +454,7 @@ struct bigint : pow5_tables<> {
|
||||
|
||||
// get the high 64 bits from the vector, and if bits were truncated.
|
||||
// this is to get the significant digits for the float.
|
||||
FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool& truncated) const noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool &truncated) const noexcept {
|
||||
#ifdef FASTFLOAT_64BIT_LIMB
|
||||
if (vec.len() == 0) {
|
||||
return empty_hi64(truncated);
|
||||
@@ -446,7 +473,8 @@ struct bigint : pow5_tables<> {
|
||||
} else if (vec.len() == 2) {
|
||||
return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated);
|
||||
} else {
|
||||
uint64_t result = uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated);
|
||||
uint64_t result =
|
||||
uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated);
|
||||
truncated |= vec.nonzero(3);
|
||||
return result;
|
||||
}
|
||||
@@ -459,7 +487,7 @@ struct bigint : pow5_tables<> {
|
||||
// positive, this is larger, otherwise they are equal.
|
||||
// the limbs are stored in little-endian order, so we
|
||||
// must compare the limbs in ever order.
|
||||
FASTFLOAT_CONSTEXPR20 int compare(const bigint& other) const noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 int compare(bigint const &other) const noexcept {
|
||||
if (vec.len() > other.vec.len()) {
|
||||
return 1;
|
||||
} else if (vec.len() < other.vec.len()) {
|
||||
@@ -512,12 +540,12 @@ struct bigint : pow5_tables<> {
|
||||
return false;
|
||||
} else if (!vec.is_empty()) {
|
||||
// move limbs
|
||||
limb* dst = vec.data + n;
|
||||
const limb* src = vec.data;
|
||||
limb *dst = vec.data + n;
|
||||
limb const *src = vec.data;
|
||||
std::copy_backward(src, src + vec.len(), dst + vec.len());
|
||||
// fill in empty limbs
|
||||
limb* first = vec.data;
|
||||
limb* last = first + n;
|
||||
limb *first = vec.data;
|
||||
limb *last = first + n;
|
||||
::std::fill(first, last, 0);
|
||||
vec.set_len(n + vec.len());
|
||||
return true;
|
||||
@@ -560,18 +588,12 @@ struct bigint : pow5_tables<> {
|
||||
return int(limb_bits * vec.len()) - lz;
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept {
|
||||
return small_mul(vec, y);
|
||||
}
|
||||
FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); }
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept {
|
||||
return small_add(vec, y);
|
||||
}
|
||||
FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept { return small_add(vec, y); }
|
||||
|
||||
// multiply as if by 2 raised to a power.
|
||||
FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept {
|
||||
return shl(exp);
|
||||
}
|
||||
FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept { return shl(exp); }
|
||||
|
||||
// multiply as if by 5 raised to a power.
|
||||
FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept {
|
||||
@@ -597,9 +619,8 @@ struct bigint : pow5_tables<> {
|
||||
// Work around clang bug https://godbolt.org/z/zedh7rrhc
|
||||
// This is similar to https://github.com/llvm/llvm-project/issues/47746,
|
||||
// except the workaround described there don't work here
|
||||
FASTFLOAT_TRY(
|
||||
small_mul(vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))
|
||||
);
|
||||
FASTFLOAT_TRY(small_mul(
|
||||
vec, limb(((void)small_power_of_5[0], small_power_of_5[exp]))));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
// Testing for https://wg21.link/N3652, adopted in C++14
|
||||
#if __cpp_constexpr >= 201304
|
||||
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
|
||||
#define FASTFLOAT_CONSTEXPR14 constexpr
|
||||
#else
|
||||
#define FASTFLOAT_CONSTEXPR14
|
||||
@@ -20,16 +20,23 @@
|
||||
#define FASTFLOAT_HAS_BIT_CAST 0
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
|
||||
#if defined(__cpp_lib_is_constant_evaluated) && \
|
||||
__cpp_lib_is_constant_evaluated >= 201811L
|
||||
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1
|
||||
#else
|
||||
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
|
||||
#define FASTFLOAT_IF_CONSTEXPR17(x) if constexpr (x)
|
||||
#else
|
||||
#define FASTFLOAT_IF_CONSTEXPR17(x) if (x)
|
||||
#endif
|
||||
|
||||
// Testing for relevant C++20 constexpr library features
|
||||
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED \
|
||||
&& FASTFLOAT_HAS_BIT_CAST \
|
||||
&& __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/
|
||||
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \
|
||||
defined(__cpp_lib_constexpr_algorithms) && \
|
||||
__cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/
|
||||
#define FASTFLOAT_CONSTEXPR20 constexpr
|
||||
#define FASTFLOAT_IS_CONSTEXPR 1
|
||||
#else
|
||||
@@ -37,4 +44,10 @@
|
||||
#define FASTFLOAT_IS_CONSTEXPR 0
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 0
|
||||
#else
|
||||
#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 1
|
||||
#endif
|
||||
|
||||
#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H
|
||||
|
||||
@@ -12,27 +12,34 @@
|
||||
|
||||
namespace fast_float {
|
||||
|
||||
// This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating
|
||||
// the result, with the "high" part corresponding to the most significant bits and the
|
||||
// low part corresponding to the least significant bits.
|
||||
// This will compute or rather approximate w * 5**q and return a pair of 64-bit
|
||||
// words approximating the result, with the "high" part corresponding to the
|
||||
// most significant bits and the low part corresponding to the least significant
|
||||
// bits.
|
||||
//
|
||||
template <int bit_precision>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
value128 compute_product_approximation(int64_t q, uint64_t w) {
|
||||
const int index = 2 * int(q - powers::smallest_power_of_five);
|
||||
// For small values of q, e.g., q in [0,27], the answer is always exact because
|
||||
// The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]);
|
||||
// gives the exact answer.
|
||||
value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]);
|
||||
static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]");
|
||||
constexpr uint64_t precision_mask = (bit_precision < 64) ?
|
||||
(uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
|
||||
: uint64_t(0xFFFFFFFFFFFFFFFF);
|
||||
if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower)
|
||||
// regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed.
|
||||
value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]);
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128
|
||||
compute_product_approximation(int64_t q, uint64_t w) {
|
||||
int const index = 2 * int(q - powers::smallest_power_of_five);
|
||||
// For small values of q, e.g., q in [0,27], the answer is always exact
|
||||
// because The line value128 firstproduct = full_multiplication(w,
|
||||
// power_of_five_128[index]); gives the exact answer.
|
||||
value128 firstproduct =
|
||||
full_multiplication(w, powers::power_of_five_128[index]);
|
||||
static_assert((bit_precision >= 0) && (bit_precision <= 64),
|
||||
" precision should be in (0,64]");
|
||||
constexpr uint64_t precision_mask =
|
||||
(bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
|
||||
: uint64_t(0xFFFFFFFFFFFFFFFF);
|
||||
if ((firstproduct.high & precision_mask) ==
|
||||
precision_mask) { // could further guard with (lower + w < lower)
|
||||
// regarding the second product, we only need secondproduct.high, but our
|
||||
// expectation is that the compiler will optimize this extra work away if
|
||||
// needed.
|
||||
value128 secondproduct =
|
||||
full_multiplication(w, powers::power_of_five_128[index + 1]);
|
||||
firstproduct.low += secondproduct.high;
|
||||
if(secondproduct.high > firstproduct.low) {
|
||||
if (secondproduct.high > firstproduct.low) {
|
||||
firstproduct.high++;
|
||||
}
|
||||
}
|
||||
@@ -55,43 +62,45 @@ namespace detail {
|
||||
* where
|
||||
* p = log(5**-q)/log(2) = -q * log(5)/log(2)
|
||||
*/
|
||||
constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept {
|
||||
return (((152170 + 65536) * q) >> 16) + 63;
|
||||
}
|
||||
constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept {
|
||||
return (((152170 + 65536) * q) >> 16) + 63;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// create an adjusted mantissa, biased by the invalid power2
|
||||
// for significant digits already multiplied by 10 ** q.
|
||||
template <typename binary>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa
|
||||
compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
|
||||
int hilz = int(w >> 63) ^ 1;
|
||||
adjusted_mantissa answer;
|
||||
answer.mantissa = w << hilz;
|
||||
int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent();
|
||||
answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias);
|
||||
answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 +
|
||||
invalid_am_bias);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// w * 10 ** q, without rounding the representation up.
|
||||
// the power2 in the exponent will be adjusted by invalid_am_bias.
|
||||
template <typename binary>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa compute_error(int64_t q, uint64_t w) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
compute_error(int64_t q, uint64_t w) noexcept {
|
||||
int lz = leading_zeroes(w);
|
||||
w <<= lz;
|
||||
value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
|
||||
value128 product =
|
||||
compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
|
||||
return compute_error_scaled<binary>(q, product.high, lz);
|
||||
}
|
||||
|
||||
// w * 10 ** q
|
||||
// The returned value should be a valid ieee64 number that simply need to be packed.
|
||||
// However, in some very rare cases, the computation will fail. In such cases, we
|
||||
// return an adjusted_mantissa with a negative power of 2: the caller should recompute
|
||||
// in such cases.
|
||||
// Computers w * 10 ** q.
|
||||
// The returned value should be a valid number that simply needs to be
|
||||
// packed. However, in some very rare cases, the computation will fail. In such
|
||||
// cases, we return an adjusted_mantissa with a negative power of 2: the caller
|
||||
// should recompute in such cases.
|
||||
template <typename binary>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
compute_float(int64_t q, uint64_t w) noexcept {
|
||||
adjusted_mantissa answer;
|
||||
if ((w == 0) || (q < binary::smallest_power_of_ten())) {
|
||||
answer.power2 = 0;
|
||||
@@ -105,7 +114,8 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
answer.mantissa = 0;
|
||||
return answer;
|
||||
}
|
||||
// At this point in time q is in [powers::smallest_power_of_five, powers::largest_power_of_five].
|
||||
// At this point in time q is in [powers::smallest_power_of_five,
|
||||
// powers::largest_power_of_five].
|
||||
|
||||
// We want the most significant bit of i to be 1. Shift if needed.
|
||||
int lz = leading_zeroes(w);
|
||||
@@ -114,26 +124,32 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// The required precision is binary::mantissa_explicit_bits() + 3 because
|
||||
// 1. We need the implicit bit
|
||||
// 2. We need an extra bit for rounding purposes
|
||||
// 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift)
|
||||
// 3. We might lose a bit due to the "upperbit" routine (result too small,
|
||||
// requiring a shift)
|
||||
|
||||
value128 product = compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
|
||||
value128 product =
|
||||
compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
|
||||
// The computed 'product' is always sufficient.
|
||||
// Mathematical proof:
|
||||
// Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to appear)
|
||||
// See script/mushtak_lemire.py
|
||||
// Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to
|
||||
// appear) See script/mushtak_lemire.py
|
||||
|
||||
// The "compute_product_approximation" function can be slightly slower than a branchless approach:
|
||||
// value128 product = compute_product(q, w);
|
||||
// but in practice, we can win big with the compute_product_approximation if its additional branch
|
||||
// is easily predicted. Which is best is data specific.
|
||||
// The "compute_product_approximation" function can be slightly slower than a
|
||||
// branchless approach: value128 product = compute_product(q, w); but in
|
||||
// practice, we can win big with the compute_product_approximation if its
|
||||
// additional branch is easily predicted. Which is best is data specific.
|
||||
int upperbit = int(product.high >> 63);
|
||||
int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;
|
||||
|
||||
answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
|
||||
answer.mantissa = product.high >> shift;
|
||||
|
||||
answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent());
|
||||
answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz -
|
||||
binary::minimum_exponent());
|
||||
if (answer.power2 <= 0) { // we have a subnormal?
|
||||
// Here have that answer.power2 <= 0 so -answer.power2 >= 0
|
||||
if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
|
||||
if (-answer.power2 + 1 >=
|
||||
64) { // if we have more than 64 bits below the minimum exponent, you
|
||||
// have a zero for sure.
|
||||
answer.power2 = 0;
|
||||
answer.mantissa = 0;
|
||||
// result should be zero
|
||||
@@ -142,7 +158,8 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// next line is safe because -answer.power2 + 1 < 64
|
||||
answer.mantissa >>= -answer.power2 + 1;
|
||||
// Thankfully, we can't have both "round-to-even" and subnormals because
|
||||
// "round-to-even" only occurs for powers close to 0.
|
||||
// "round-to-even" only occurs for powers close to 0 in the 32-bit and
|
||||
// and 64-bit case (with no more than 19 digits).
|
||||
answer.mantissa += (answer.mantissa & 1); // round up
|
||||
answer.mantissa >>= 1;
|
||||
// There is a weird scenario where we don't have a subnormal but just.
|
||||
@@ -152,20 +169,26 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer
|
||||
// subnormal, but we can only know this after rounding.
|
||||
// So we only declare a subnormal if we are smaller than the threshold.
|
||||
answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1;
|
||||
answer.power2 =
|
||||
(answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits()))
|
||||
? 0
|
||||
: 1;
|
||||
return answer;
|
||||
}
|
||||
|
||||
// usually, we round *up*, but if we fall right in between and and we have an
|
||||
// even basis, we need to round down
|
||||
// We are only concerned with the cases where 5**q fits in single 64-bit word.
|
||||
if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) &&
|
||||
((answer.mantissa & 3) == 1) ) { // we may fall between two floats!
|
||||
if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) &&
|
||||
(q <= binary::max_exponent_round_to_even()) &&
|
||||
((answer.mantissa & 3) == 1)) { // we may fall between two floats!
|
||||
// To be in-between two floats we need that in doing
|
||||
// answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3);
|
||||
// ... we dropped out only zeroes. But if this happened, then we can go back!!!
|
||||
if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) {
|
||||
answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up
|
||||
// answer.mantissa = product.high >> (upperbit + 64 -
|
||||
// binary::mantissa_explicit_bits() - 3);
|
||||
// ... we dropped out only zeroes. But if this happened, then we can go
|
||||
// back!!!
|
||||
if ((answer.mantissa << shift) == product.high) {
|
||||
answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,19 +13,34 @@
|
||||
namespace fast_float {
|
||||
|
||||
// 1e0 to 1e19
|
||||
constexpr static uint64_t powers_of_ten_uint64[] = {
|
||||
1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL,
|
||||
1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL,
|
||||
100000000000000UL, 1000000000000000UL, 10000000000000000UL, 100000000000000000UL,
|
||||
1000000000000000000UL, 10000000000000000000UL};
|
||||
constexpr static uint64_t powers_of_ten_uint64[] = {1UL,
|
||||
10UL,
|
||||
100UL,
|
||||
1000UL,
|
||||
10000UL,
|
||||
100000UL,
|
||||
1000000UL,
|
||||
10000000UL,
|
||||
100000000UL,
|
||||
1000000000UL,
|
||||
10000000000UL,
|
||||
100000000000UL,
|
||||
1000000000000UL,
|
||||
10000000000000UL,
|
||||
100000000000000UL,
|
||||
1000000000000000UL,
|
||||
10000000000000000UL,
|
||||
100000000000000000UL,
|
||||
1000000000000000000UL,
|
||||
10000000000000000000UL};
|
||||
|
||||
// calculate the exponent, in scientific notation, of the number.
|
||||
// this algorithm is not even close to optimized, but it has no practical
|
||||
// effect on performance: in order to have a faster algorithm, we'd need
|
||||
// to slow down performance for faster algorithms, and this is still fast.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
int32_t scientific_exponent(parsed_number_string_t<UC> & num) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t
|
||||
scientific_exponent(parsed_number_string_t<UC> &num) noexcept {
|
||||
uint64_t mantissa = num.mantissa;
|
||||
int32_t exponent = int32_t(num.exponent);
|
||||
while (mantissa >= 10000) {
|
||||
@@ -45,15 +60,16 @@ int32_t scientific_exponent(parsed_number_string_t<UC> & num) noexcept {
|
||||
|
||||
// this converts a native floating-point number to an extended-precision float.
|
||||
template <typename T>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa to_extended(T value) noexcept {
|
||||
using equiv_uint = typename binary_format<T>::equiv_uint;
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
to_extended(T value) noexcept {
|
||||
using equiv_uint = equiv_uint_t<T>;
|
||||
constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
|
||||
constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
|
||||
constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
|
||||
|
||||
adjusted_mantissa am;
|
||||
int32_t bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();
|
||||
int32_t bias = binary_format<T>::mantissa_explicit_bits() -
|
||||
binary_format<T>::minimum_exponent();
|
||||
equiv_uint bits;
|
||||
#if FASTFLOAT_HAS_BIT_CAST
|
||||
bits = std::bit_cast<equiv_uint>(value);
|
||||
@@ -66,7 +82,8 @@ adjusted_mantissa to_extended(T value) noexcept {
|
||||
am.mantissa = bits & mantissa_mask;
|
||||
} else {
|
||||
// normal
|
||||
am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits());
|
||||
am.power2 = int32_t((bits & exponent_mask) >>
|
||||
binary_format<T>::mantissa_explicit_bits());
|
||||
am.power2 -= bias;
|
||||
am.mantissa = (bits & mantissa_mask) | hidden_bit_mask;
|
||||
}
|
||||
@@ -78,8 +95,8 @@ adjusted_mantissa to_extended(T value) noexcept {
|
||||
// we are given a native float that represents b, so we need to adjust it
|
||||
// halfway between b and b+u.
|
||||
template <typename T>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa to_extended_halfway(T value) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
to_extended_halfway(T value) noexcept {
|
||||
adjusted_mantissa am = to_extended(value);
|
||||
am.mantissa <<= 1;
|
||||
am.mantissa += 1;
|
||||
@@ -89,15 +106,18 @@ adjusted_mantissa to_extended_halfway(T value) noexcept {
|
||||
|
||||
// round an extended-precision float to the nearest machine float.
|
||||
template <typename T, typename callback>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
void round(adjusted_mantissa& am, callback cb) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am,
|
||||
callback cb) noexcept {
|
||||
int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
|
||||
if (-am.power2 >= mantissa_shift) {
|
||||
// have a denormal float
|
||||
int32_t shift = -am.power2 + 1;
|
||||
cb(am, std::min<int32_t>(shift, 64));
|
||||
// check for round-up: if rounding-nearest carried us to the hidden bit.
|
||||
am.power2 = (am.mantissa < (uint64_t(1) << binary_format<T>::mantissa_explicit_bits())) ? 0 : 1;
|
||||
am.power2 = (am.mantissa <
|
||||
(uint64_t(1) << binary_format<T>::mantissa_explicit_bits()))
|
||||
? 0
|
||||
: 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +125,8 @@ void round(adjusted_mantissa& am, callback cb) noexcept {
|
||||
cb(am, mantissa_shift);
|
||||
|
||||
// check for carry
|
||||
if (am.mantissa >= (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
|
||||
if (am.mantissa >=
|
||||
(uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
|
||||
am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
|
||||
am.power2++;
|
||||
}
|
||||
@@ -119,16 +140,11 @@ void round(adjusted_mantissa& am, callback cb) noexcept {
|
||||
}
|
||||
|
||||
template <typename callback>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept {
|
||||
const uint64_t mask
|
||||
= (shift == 64)
|
||||
? UINT64_MAX
|
||||
: (uint64_t(1) << shift) - 1;
|
||||
const uint64_t halfway
|
||||
= (shift == 0)
|
||||
? 0
|
||||
: uint64_t(1) << (shift - 1);
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
||||
round_nearest_tie_even(adjusted_mantissa &am, int32_t shift,
|
||||
callback cb) noexcept {
|
||||
uint64_t const mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1;
|
||||
uint64_t const halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1);
|
||||
uint64_t truncated_bits = am.mantissa & mask;
|
||||
bool is_above = truncated_bits > halfway;
|
||||
bool is_halfway = truncated_bits == halfway;
|
||||
@@ -145,8 +161,8 @@ void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) n
|
||||
am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
||||
round_down(adjusted_mantissa &am, int32_t shift) noexcept {
|
||||
if (shift == 64) {
|
||||
am.mantissa = 0;
|
||||
} else {
|
||||
@@ -154,11 +170,13 @@ void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
|
||||
}
|
||||
am.power2 += shift;
|
||||
}
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void skip_zeros(UC const * & first, UC const * last) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
skip_zeros(UC const *&first, UC const *last) noexcept {
|
||||
uint64_t val;
|
||||
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
|
||||
while (!cpp20_and_in_constexpr() &&
|
||||
std::distance(first, last) >= int_cmp_len<UC>()) {
|
||||
::memcpy(&val, first, sizeof(uint64_t));
|
||||
if (val != int_cmp_zeros<UC>()) {
|
||||
break;
|
||||
@@ -176,11 +194,12 @@ void skip_zeros(UC const * & first, UC const * last) noexcept {
|
||||
// determine if any non-zero digits were truncated.
|
||||
// all characters must be valid digits.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
bool is_truncated(UC const * first, UC const * last) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||
is_truncated(UC const *first, UC const *last) noexcept {
|
||||
// do 8-bit optimizations, can just compare to 8 literal 0s.
|
||||
uint64_t val;
|
||||
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= int_cmp_len<UC>()) {
|
||||
while (!cpp20_and_in_constexpr() &&
|
||||
std::distance(first, last) >= int_cmp_len<UC>()) {
|
||||
::memcpy(&val, first, sizeof(uint64_t));
|
||||
if (val != int_cmp_zeros<UC>()) {
|
||||
return true;
|
||||
@@ -195,16 +214,17 @@ bool is_truncated(UC const * first, UC const * last) noexcept {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
bool is_truncated(span<const UC> s) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||
is_truncated(span<UC const> s) noexcept {
|
||||
return is_truncated(s.ptr, s.ptr + s.len());
|
||||
}
|
||||
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void parse_eight_digits(const UC*& p, limb& value, size_t& counter, size_t& count) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
parse_eight_digits(UC const *&p, limb &value, size_t &counter,
|
||||
size_t &count) noexcept {
|
||||
value = value * 100000000 + parse_eight_digits_unrolled(p);
|
||||
p += 8;
|
||||
counter += 8;
|
||||
@@ -212,22 +232,23 @@ void parse_eight_digits(const UC*& p, limb& value, size_t& counter, size_t& coun
|
||||
}
|
||||
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||
void parse_one_digit(UC const *& p, limb& value, size_t& counter, size_t& count) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
||||
parse_one_digit(UC const *&p, limb &value, size_t &counter,
|
||||
size_t &count) noexcept {
|
||||
value = value * 10 + limb(*p - UC('0'));
|
||||
p++;
|
||||
counter++;
|
||||
count++;
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void add_native(bigint& big, limb power, limb value) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
add_native(bigint &big, limb power, limb value) noexcept {
|
||||
big.mul(power);
|
||||
big.add(value);
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||
void round_up_bigint(bigint& big, size_t& count) noexcept {
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||
round_up_bigint(bigint &big, size_t &count) noexcept {
|
||||
// need to round-up the digits, but need to avoid rounding
|
||||
// ....9999 to ...10000, which could cause a false halfway point.
|
||||
add_native(big, 10, 1);
|
||||
@@ -236,8 +257,9 @@ void round_up_bigint(bigint& big, size_t& count) noexcept {
|
||||
|
||||
// parse the significant digits into a big integer
|
||||
template <typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_digits, size_t& digits) noexcept {
|
||||
inline FASTFLOAT_CONSTEXPR20 void
|
||||
parse_mantissa(bigint &result, parsed_number_string_t<UC> &num,
|
||||
size_t max_digits, size_t &digits) noexcept {
|
||||
// try to minimize the number of big integer and scalar multiplication.
|
||||
// therefore, try to parse 8 digits at a time, and multiply by the largest
|
||||
// scalar value (9 or 19 digits) for each step.
|
||||
@@ -251,12 +273,13 @@ void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_
|
||||
#endif
|
||||
|
||||
// process all integer digits.
|
||||
UC const * p = num.integer.ptr;
|
||||
UC const * pend = p + num.integer.len();
|
||||
UC const *p = num.integer.ptr;
|
||||
UC const *pend = p + num.integer.len();
|
||||
skip_zeros(p, pend);
|
||||
// process all digits, in increments of step per loop
|
||||
while (p != pend) {
|
||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
|
||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) &&
|
||||
(max_digits - digits >= 8)) {
|
||||
parse_eight_digits(p, value, counter, digits);
|
||||
}
|
||||
while (counter < step && p != pend && digits < max_digits) {
|
||||
@@ -289,7 +312,8 @@ void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_
|
||||
}
|
||||
// process all digits, in increments of step per loop
|
||||
while (p != pend) {
|
||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
|
||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) &&
|
||||
(max_digits - digits >= 8)) {
|
||||
parse_eight_digits(p, value, counter, digits);
|
||||
}
|
||||
while (counter < step && p != pend && digits < max_digits) {
|
||||
@@ -317,19 +341,23 @@ void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept {
|
||||
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept {
|
||||
FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent)));
|
||||
adjusted_mantissa answer;
|
||||
bool truncated;
|
||||
answer.mantissa = bigmant.hi64(truncated);
|
||||
int bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent();
|
||||
int bias = binary_format<T>::mantissa_explicit_bits() -
|
||||
binary_format<T>::minimum_exponent();
|
||||
answer.power2 = bigmant.bit_length() - 64 + bias;
|
||||
|
||||
round<T>(answer, [truncated](adjusted_mantissa& a, int32_t shift) {
|
||||
round_nearest_tie_even(a, shift, [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
|
||||
return is_above || (is_halfway && truncated) || (is_odd && is_halfway);
|
||||
});
|
||||
round<T>(answer, [truncated](adjusted_mantissa &a, int32_t shift) {
|
||||
round_nearest_tie_even(
|
||||
a, shift,
|
||||
[truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
|
||||
return is_above || (is_halfway && truncated) ||
|
||||
(is_odd && is_halfway);
|
||||
});
|
||||
});
|
||||
|
||||
return answer;
|
||||
@@ -341,15 +369,17 @@ adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcep
|
||||
// we then need to scale by `2^(f- e)`, and then the two significant digits
|
||||
// are of the same magnitude.
|
||||
template <typename T>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int32_t exponent) noexcept {
|
||||
bigint& real_digits = bigmant;
|
||||
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp(
|
||||
bigint &bigmant, adjusted_mantissa am, int32_t exponent) noexcept {
|
||||
bigint &real_digits = bigmant;
|
||||
int32_t real_exp = exponent;
|
||||
|
||||
// get the value of `b`, rounded down, and get a bigint representation of b+h
|
||||
adjusted_mantissa am_b = am;
|
||||
// gcc7 buf: use a lambda to remove the noexcept qualifier bug with -Wnoexcept-type.
|
||||
round<T>(am_b, [](adjusted_mantissa&a, int32_t shift) { round_down(a, shift); });
|
||||
// gcc7 buf: use a lambda to remove the noexcept qualifier bug with
|
||||
// -Wnoexcept-type.
|
||||
round<T>(am_b,
|
||||
[](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); });
|
||||
T b;
|
||||
to_float(false, am_b, b);
|
||||
adjusted_mantissa theor = to_extended_halfway(b);
|
||||
@@ -371,18 +401,19 @@ adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int
|
||||
// compare digits, and use it to director rounding
|
||||
int ord = real_digits.compare(theor_digits);
|
||||
adjusted_mantissa answer = am;
|
||||
round<T>(answer, [ord](adjusted_mantissa& a, int32_t shift) {
|
||||
round_nearest_tie_even(a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
|
||||
(void)_; // not needed, since we've done our comparison
|
||||
(void)__; // not needed, since we've done our comparison
|
||||
if (ord > 0) {
|
||||
return true;
|
||||
} else if (ord < 0) {
|
||||
return false;
|
||||
} else {
|
||||
return is_odd;
|
||||
}
|
||||
});
|
||||
round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
|
||||
round_nearest_tie_even(
|
||||
a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
|
||||
(void)_; // not needed, since we've done our comparison
|
||||
(void)__; // not needed, since we've done our comparison
|
||||
if (ord > 0) {
|
||||
return true;
|
||||
} else if (ord < 0) {
|
||||
return false;
|
||||
} else {
|
||||
return is_odd;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return answer;
|
||||
@@ -402,8 +433,8 @@ adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int
|
||||
// the actual digits. we then compare the big integer representations
|
||||
// of both, and use that to direct rounding.
|
||||
template <typename T, typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR20
|
||||
adjusted_mantissa digit_comp(parsed_number_string_t<UC>& num, adjusted_mantissa am) noexcept {
|
||||
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
digit_comp(parsed_number_string_t<UC> &num, adjusted_mantissa am) noexcept {
|
||||
// remove the invalid exponent bias
|
||||
am.power2 -= invalid_am_bias;
|
||||
|
||||
|
||||
@@ -6,43 +6,54 @@
|
||||
|
||||
namespace fast_float {
|
||||
/**
|
||||
* This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
|
||||
* a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale.
|
||||
* The resulting floating-point value is the closest floating-point values (using either float or double),
|
||||
* using the "round to even" convention for values that would otherwise fall right in-between two values.
|
||||
* That is, we provide exact parsing according to the IEEE standard.
|
||||
* This function parses the character sequence [first,last) for a number. It
|
||||
* parses floating-point numbers expecting a locale-indepent format equivalent
|
||||
* to what is used by std::strtod in the default ("C") locale. The resulting
|
||||
* floating-point value is the closest floating-point values (using either float
|
||||
* or double), using the "round to even" convention for values that would
|
||||
* otherwise fall right in-between two values. That is, we provide exact parsing
|
||||
* according to the IEEE standard.
|
||||
*
|
||||
* Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the
|
||||
* parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned
|
||||
* `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored.
|
||||
* Given a successful parse, the pointer (`ptr`) in the returned value is set to
|
||||
* point right after the parsed number, and the `value` referenced is set to the
|
||||
* parsed value. In case of error, the returned `ec` contains a representative
|
||||
* error, otherwise the default (`std::errc()`) value is stored.
|
||||
*
|
||||
* The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`).
|
||||
* The implementation does not throw and does not allocate memory (e.g., with
|
||||
* `new` or `malloc`).
|
||||
*
|
||||
* Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
|
||||
* the type `fast_float::chars_format`. It is a bitset value: we check whether
|
||||
* `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
|
||||
* to determine whether we allow the fixed point and scientific notation respectively.
|
||||
* The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
|
||||
* Like the C++17 standard, the `fast_float::from_chars` functions take an
|
||||
* optional last argument of the type `fast_float::chars_format`. It is a bitset
|
||||
* value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt &
|
||||
* fast_float::chars_format::scientific` are set to determine whether we allow
|
||||
* the fixed point and scientific notation respectively. The default is
|
||||
* `fast_float::chars_format::general` which allows both `fixed` and
|
||||
* `scientific`.
|
||||
*/
|
||||
template<typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>())>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
|
||||
T &value, chars_format fmt = chars_format::general) noexcept;
|
||||
template <typename T, typename UC = char,
|
||||
typename = FASTFLOAT_ENABLE_IF(is_supported_float_type<T>::value)>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars(UC const *first, UC const *last, T &value,
|
||||
chars_format fmt = chars_format::general) noexcept;
|
||||
|
||||
/**
|
||||
* Like from_chars, but accepts an `options` argument to govern number parsing.
|
||||
* Both for floating-point types and integer types.
|
||||
*/
|
||||
template<typename T, typename UC = char>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
||||
T &value, parse_options_t<UC> options) noexcept;
|
||||
template <typename T, typename UC = char>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept;
|
||||
|
||||
/**
|
||||
* from_chars for integer types.
|
||||
*/
|
||||
template <typename T, typename UC = char, typename = FASTFLOAT_ENABLE_IF(!is_supported_float_type<T>())>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars(UC const * first, UC const * last, T& value, int base = 10) noexcept;
|
||||
* from_chars for integer types.
|
||||
*/
|
||||
template <typename T, typename UC = char,
|
||||
typename = FASTFLOAT_ENABLE_IF(is_supported_integer_type<T>::value)>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept;
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
#include "parse_number.h"
|
||||
#endif // FASTFLOAT_FAST_FLOAT_H
|
||||
|
||||
1326
3rdparty/fast_float/include/fast_float/fast_table.h
vendored
1326
3rdparty/fast_float/include/fast_float/fast_table.h
vendored
File diff suppressed because it is too large
Load Diff
1147
3rdparty/fast_float/include/fast_float/float_common.h
vendored
1147
3rdparty/fast_float/include/fast_float/float_common.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,8 @@
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <system_error>
|
||||
namespace fast_float {
|
||||
|
||||
namespace fast_float {
|
||||
|
||||
namespace detail {
|
||||
/**
|
||||
@@ -20,45 +20,49 @@ namespace detail {
|
||||
* strings a null-free and fixed.
|
||||
**/
|
||||
template <typename T, typename UC>
|
||||
from_chars_result_t<UC> FASTFLOAT_CONSTEXPR14
|
||||
parse_infnan(UC const * first, UC const * last, T &value) noexcept {
|
||||
from_chars_result_t<UC>
|
||||
FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first, UC const *last,
|
||||
T &value, chars_format fmt) noexcept {
|
||||
from_chars_result_t<UC> answer{};
|
||||
answer.ptr = first;
|
||||
answer.ec = std::errc(); // be optimistic
|
||||
bool minusSign = false;
|
||||
if (*first == UC('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
|
||||
minusSign = true;
|
||||
++first;
|
||||
// assume first < last, so dereference without checks;
|
||||
bool const minusSign = (*first == UC('-'));
|
||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||
if ((*first == UC('-')) ||
|
||||
(uint64_t(fmt & chars_format::allow_leading_plus) &&
|
||||
(*first == UC('+')))) {
|
||||
++first;
|
||||
}
|
||||
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||
if (*first == UC('+')) {
|
||||
++first;
|
||||
}
|
||||
#endif
|
||||
if (last - first >= 3) {
|
||||
if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
|
||||
answer.ptr = (first += 3);
|
||||
value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
|
||||
// Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
|
||||
if(first != last && *first == UC('(')) {
|
||||
for(UC const * ptr = first + 1; ptr != last; ++ptr) {
|
||||
value = minusSign ? -std::numeric_limits<T>::quiet_NaN()
|
||||
: std::numeric_limits<T>::quiet_NaN();
|
||||
// Check for possible nan(n-char-seq-opt), C++17 20.19.3.7,
|
||||
// C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
|
||||
if (first != last && *first == UC('(')) {
|
||||
for (UC const *ptr = first + 1; ptr != last; ++ptr) {
|
||||
if (*ptr == UC(')')) {
|
||||
answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
|
||||
break;
|
||||
}
|
||||
else if(!((UC('a') <= *ptr && *ptr <= UC('z')) || (UC('A') <= *ptr && *ptr <= UC('Z')) || (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
|
||||
} else if (!((UC('a') <= *ptr && *ptr <= UC('z')) ||
|
||||
(UC('A') <= *ptr && *ptr <= UC('Z')) ||
|
||||
(UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
|
||||
break; // forbidden char, not nan(n-char-seq-opt)
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
|
||||
if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
|
||||
if ((last - first >= 8) &&
|
||||
fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
|
||||
answer.ptr = first + 8;
|
||||
} else {
|
||||
answer.ptr = first + 3;
|
||||
}
|
||||
value = minusSign ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity();
|
||||
value = minusSign ? -std::numeric_limits<T>::infinity()
|
||||
: std::numeric_limits<T>::infinity();
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
@@ -86,73 +90,71 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept {
|
||||
// However, it is expected to be much faster than the fegetround()
|
||||
// function call.
|
||||
//
|
||||
// The volatile keywoard prevents the compiler from computing the function
|
||||
// The volatile keyword prevents the compiler from computing the function
|
||||
// at compile-time.
|
||||
// There might be other ways to prevent compile-time optimizations (e.g., asm).
|
||||
// The value does not need to be std::numeric_limits<float>::min(), any small
|
||||
// value so that 1 + x should round to 1 would do (after accounting for excess
|
||||
// precision, as in 387 instructions).
|
||||
static volatile float fmin = std::numeric_limits<float>::min();
|
||||
// There might be other ways to prevent compile-time optimizations (e.g.,
|
||||
// asm). The value does not need to be std::numeric_limits<float>::min(), any
|
||||
// small value so that 1 + x should round to 1 would do (after accounting for
|
||||
// excess precision, as in 387 instructions).
|
||||
static float volatile fmin = std::numeric_limits<float>::min();
|
||||
float fmini = fmin; // we copy it so that it gets loaded at most once.
|
||||
//
|
||||
// Explanation:
|
||||
// Only when fegetround() == FE_TONEAREST do we have that
|
||||
// fmin + 1.0f == 1.0f - fmin.
|
||||
//
|
||||
// FE_UPWARD:
|
||||
// fmin + 1.0f > 1
|
||||
// 1.0f - fmin == 1
|
||||
//
|
||||
// FE_DOWNWARD or FE_TOWARDZERO:
|
||||
// fmin + 1.0f == 1
|
||||
// 1.0f - fmin < 1
|
||||
//
|
||||
// Note: This may fail to be accurate if fast-math has been
|
||||
// enabled, as rounding conventions may not apply.
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
# pragma warning(push)
|
||||
// todo: is there a VS warning?
|
||||
// see https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wfloat-equal"
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
//
|
||||
// Explanation:
|
||||
// Only when fegetround() == FE_TONEAREST do we have that
|
||||
// fmin + 1.0f == 1.0f - fmin.
|
||||
//
|
||||
// FE_UPWARD:
|
||||
// fmin + 1.0f > 1
|
||||
// 1.0f - fmin == 1
|
||||
//
|
||||
// FE_DOWNWARD or FE_TOWARDZERO:
|
||||
// fmin + 1.0f == 1
|
||||
// 1.0f - fmin < 1
|
||||
//
|
||||
// Note: This may fail to be accurate if fast-math has been
|
||||
// enabled, as rounding conventions may not apply.
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(push)
|
||||
// todo: is there a VS warning?
|
||||
// see
|
||||
// https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
return (fmini + 1.0f == 1.0f - fmini);
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
# pragma warning(pop)
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
#pragma warning(pop)
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
struct from_chars_caller
|
||||
{
|
||||
template <typename T> struct from_chars_caller {
|
||||
template <typename UC>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
static from_chars_result_t<UC> call(UC const * first, UC const * last,
|
||||
T &value, parse_options_t<UC> options) noexcept {
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_advanced(first, last, value, options);
|
||||
}
|
||||
};
|
||||
|
||||
#if __STDCPP_FLOAT32_T__ == 1
|
||||
template <>
|
||||
struct from_chars_caller<std::float32_t>
|
||||
{
|
||||
#ifdef __STDCPP_FLOAT32_T__
|
||||
template <> struct from_chars_caller<std::float32_t> {
|
||||
template <typename UC>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
static from_chars_result_t<UC> call(UC const * first, UC const * last,
|
||||
std::float32_t &value, parse_options_t<UC> options) noexcept{
|
||||
// if std::float32_t is defined, and we are in C++23 mode; macro set for float32;
|
||||
// set value to float due to equivalence between float and float32_t
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, std::float32_t &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
// if std::float32_t is defined, and we are in C++23 mode; macro set for
|
||||
// float32; set value to float due to equivalence between float and
|
||||
// float32_t
|
||||
float val;
|
||||
auto ret = from_chars_advanced(first, last, val, options);
|
||||
value = val;
|
||||
@@ -161,16 +163,15 @@ struct from_chars_caller<std::float32_t>
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __STDCPP_FLOAT64_T__ == 1
|
||||
template <>
|
||||
struct from_chars_caller<std::float64_t>
|
||||
{
|
||||
#ifdef __STDCPP_FLOAT64_T__
|
||||
template <> struct from_chars_caller<std::float64_t> {
|
||||
template <typename UC>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
static from_chars_result_t<UC> call(UC const * first, UC const * last,
|
||||
std::float64_t &value, parse_options_t<UC> options) noexcept{
|
||||
// if std::float64_t is defined, and we are in C++23 mode; macro set for float64;
|
||||
// set value as double due to equivalence between double and float64_t
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, std::float64_t &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
// if std::float64_t is defined, and we are in C++23 mode; macro set for
|
||||
// float64; set value as double due to equivalence between double and
|
||||
// float64_t
|
||||
double val;
|
||||
auto ret = from_chars_advanced(first, last, val, options);
|
||||
value = val;
|
||||
@@ -179,52 +180,40 @@ struct from_chars_caller<std::float64_t>
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T, typename UC, typename>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
|
||||
T &value, chars_format fmt /*= chars_format::general*/) noexcept {
|
||||
return from_chars_caller<T>::call(first, last, value, parse_options_t<UC>(fmt));
|
||||
template <typename T, typename UC, typename>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars(UC const *first, UC const *last, T &value,
|
||||
chars_format fmt /*= chars_format::general*/) noexcept {
|
||||
return from_chars_caller<T>::call(first, last, value,
|
||||
parse_options_t<UC>(fmt));
|
||||
}
|
||||
|
||||
template<typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
||||
T &value, parse_options_t<UC> options) noexcept {
|
||||
/**
|
||||
* This function overload takes parsed_number_string_t structure that is created
|
||||
* and populated either by from_chars_advanced function taking chars range and
|
||||
* parsing options or other parsing custom function implemented by user.
|
||||
*/
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
|
||||
|
||||
static_assert (is_supported_float_type<T>(), "only some floating-point types are supported");
|
||||
static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
|
||||
static_assert(is_supported_float_type<T>::value,
|
||||
"only some floating-point types are supported");
|
||||
static_assert(is_supported_char_type<UC>::value,
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
}
|
||||
#endif
|
||||
if (first == last) {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);
|
||||
if (!pns.valid) {
|
||||
if (options.format & chars_format::no_infnan) {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
} else {
|
||||
return detail::parse_infnan(first, last, value);
|
||||
}
|
||||
}
|
||||
|
||||
answer.ec = std::errc(); // be optimistic
|
||||
answer.ptr = pns.lastmatch;
|
||||
// The implementation of the Clinger's fast path is convoluted because
|
||||
// we want round-to-nearest in all cases, irrespective of the rounding mode
|
||||
// selected on the thread.
|
||||
// We proceed optimistically, assuming that detail::rounds_to_nearest() returns
|
||||
// true.
|
||||
if (binary_format<T>::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format<T>::max_exponent_fast_path() && !pns.too_many_digits) {
|
||||
// We proceed optimistically, assuming that detail::rounds_to_nearest()
|
||||
// returns true.
|
||||
if (binary_format<T>::min_exponent_fast_path() <= pns.exponent &&
|
||||
pns.exponent <= binary_format<T>::max_exponent_fast_path() &&
|
||||
!pns.too_many_digits) {
|
||||
// Unfortunately, the conventional Clinger's fast path is only possible
|
||||
// when the system rounds to the nearest float.
|
||||
//
|
||||
@@ -232,68 +221,179 @@ from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
||||
// We could check it first (before the previous branch), but
|
||||
// there might be performance advantages at having the check
|
||||
// be last.
|
||||
if(!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
||||
if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
|
||||
// We have that fegetround() == FE_TONEAREST.
|
||||
// Next is Clinger's fast path.
|
||||
if (pns.mantissa <=binary_format<T>::max_mantissa_fast_path()) {
|
||||
if (pns.mantissa <= binary_format<T>::max_mantissa_fast_path()) {
|
||||
value = T(pns.mantissa);
|
||||
if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); }
|
||||
else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }
|
||||
if (pns.negative) { value = -value; }
|
||||
if (pns.exponent < 0) {
|
||||
value = value / binary_format<T>::exact_power_of_ten(-pns.exponent);
|
||||
} else {
|
||||
value = value * binary_format<T>::exact_power_of_ten(pns.exponent);
|
||||
}
|
||||
if (pns.negative) {
|
||||
value = -value;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
} else {
|
||||
// We do not have that fegetround() == FE_TONEAREST.
|
||||
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal
|
||||
if (pns.exponent >= 0 && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
|
||||
// Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
|
||||
// proposal
|
||||
if (pns.exponent >= 0 &&
|
||||
pns.mantissa <=
|
||||
binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
|
||||
#if defined(__clang__) || defined(FASTFLOAT_32BIT)
|
||||
// Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
|
||||
if(pns.mantissa == 0) {
|
||||
if (pns.mantissa == 0) {
|
||||
value = pns.negative ? T(-0.) : T(0.);
|
||||
return answer;
|
||||
}
|
||||
#endif
|
||||
value = T(pns.mantissa) * binary_format<T>::exact_power_of_ten(pns.exponent);
|
||||
if (pns.negative) { value = -value; }
|
||||
value = T(pns.mantissa) *
|
||||
binary_format<T>::exact_power_of_ten(pns.exponent);
|
||||
if (pns.negative) {
|
||||
value = -value;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
||||
if(pns.too_many_digits && am.power2 >= 0) {
|
||||
if(am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
|
||||
adjusted_mantissa am =
|
||||
compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
||||
if (pns.too_many_digits && am.power2 >= 0) {
|
||||
if (am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
|
||||
am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
|
||||
}
|
||||
}
|
||||
// If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),
|
||||
// then we need to go the long way around again. This is very uncommon.
|
||||
if(am.power2 < 0) { am = digit_comp<T>(pns, am); }
|
||||
// If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa)
|
||||
// and we have an invalid power (am.power2 < 0), then we need to go the long
|
||||
// way around again. This is very uncommon.
|
||||
if (am.power2 < 0) {
|
||||
am = digit_comp<T>(pns, am);
|
||||
}
|
||||
to_float(pns.negative, am, value);
|
||||
// Test for over/underflow.
|
||||
if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || am.power2 == binary_format<T>::infinite_power()) {
|
||||
if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) ||
|
||||
am.power2 == binary_format<T>::infinite_power()) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
|
||||
template <typename T, typename UC, typename>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
from_chars_result_t<UC> from_chars(UC const* first, UC const* last, T& value, int base) noexcept {
|
||||
static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
|
||||
static_assert(is_supported_float_type<T>::value,
|
||||
"only some floating-point types are supported");
|
||||
static_assert(is_supported_char_type<UC>::value,
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
chars_format const fmt = detail::adjust_for_feature_macros(options.format);
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
|
||||
while ((first != last) && fast_float::is_space(uint8_t(*first))) {
|
||||
first++;
|
||||
if (uint64_t(fmt & chars_format::skip_white_space)) {
|
||||
while ((first != last) && fast_float::is_space(*first)) {
|
||||
first++;
|
||||
}
|
||||
}
|
||||
if (first == last) {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
parsed_number_string_t<UC> pns =
|
||||
uint64_t(fmt & detail::basic_json_fmt)
|
||||
? parse_number_string<true, UC>(first, last, options)
|
||||
: parse_number_string<false, UC>(first, last, options);
|
||||
if (!pns.valid) {
|
||||
if (uint64_t(fmt & chars_format::no_infnan)) {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
} else {
|
||||
return detail::parse_infnan(first, last, value, fmt);
|
||||
}
|
||||
}
|
||||
|
||||
// call overload that takes parsed_number_string_t directly.
|
||||
return from_chars_advanced(pns, value);
|
||||
}
|
||||
|
||||
template <typename T, typename UC, typename>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
||||
|
||||
static_assert(is_supported_integer_type<T>::value,
|
||||
"only integer types are supported");
|
||||
static_assert(is_supported_char_type<UC>::value,
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
parse_options_t<UC> options;
|
||||
options.base = base;
|
||||
return from_chars_advanced(first, last, value, options);
|
||||
}
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
|
||||
static_assert(is_supported_integer_type<T>::value,
|
||||
"only integer types are supported");
|
||||
static_assert(is_supported_char_type<UC>::value,
|
||||
"only char, wchar_t, char16_t and char32_t are supported");
|
||||
|
||||
chars_format const fmt = detail::adjust_for_feature_macros(options.format);
|
||||
int const base = options.base;
|
||||
|
||||
from_chars_result_t<UC> answer;
|
||||
if (uint64_t(fmt & chars_format::skip_white_space)) {
|
||||
while ((first != last) && fast_float::is_space(*first)) {
|
||||
first++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (first == last || base < 2 || base > 36) {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
return parse_int_string(first, last, value, base);
|
||||
|
||||
return parse_int_string(first, last, value, options);
|
||||
}
|
||||
|
||||
template <size_t TypeIx> struct from_chars_advanced_caller {
|
||||
static_assert(TypeIx > 0, "unsupported type");
|
||||
};
|
||||
|
||||
template <> struct from_chars_advanced_caller<1> {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_float_advanced(first, last, value, options);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct from_chars_advanced_caller<2> {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_int_advanced(first, last, value, options);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_advanced_caller<
|
||||
size_t(is_supported_float_type<T>::value) +
|
||||
2 * size_t(is_supported_integer_type<T>::value)>::call(first, last, value,
|
||||
options);
|
||||
}
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
18
3rdparty/ffmpeg/COPYING.LGPLv2.1
vendored
18
3rdparty/ffmpeg/COPYING.LGPLv2.1
vendored
@@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
@@ -111,7 +111,7 @@ modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -158,7 +158,7 @@ Library.
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
@@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
@@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
@@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
@@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
@@ -456,7 +456,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
|
||||
2235
3rdparty/ffmpeg/Changelog
vendored
Normal file
2235
3rdparty/ffmpeg/Changelog
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
3rdparty/ffmpeg/LICENSE.md
vendored
2
3rdparty/ffmpeg/LICENSE.md
vendored
@@ -12,7 +12,6 @@ configure to activate them. In this case, FFmpeg's license changes to GPL v2+.
|
||||
|
||||
Specifically, the GPL parts of FFmpeg are:
|
||||
|
||||
- libpostproc
|
||||
- optional x86 optimization in the files
|
||||
- `libavcodec/x86/flac_dsp_gpl.asm`
|
||||
- `libavcodec/x86/idct_mmx.c`
|
||||
@@ -45,7 +44,6 @@ Specifically, the GPL parts of FFmpeg are:
|
||||
- `vf_owdenoise.c`
|
||||
- `vf_perspective.c`
|
||||
- `vf_phase.c`
|
||||
- `vf_pp.c`
|
||||
- `vf_pp7.c`
|
||||
- `vf_pullup.c`
|
||||
- `vf_repeatfields.c`
|
||||
|
||||
2
3rdparty/ffmpeg/headers-version.txt
vendored
2
3rdparty/ffmpeg/headers-version.txt
vendored
@@ -1 +1 @@
|
||||
ffmpeg-7.0.2 from https://ffmpeg.org/releases/ffmpeg-7.0.2.tar.xz
|
||||
ffmpeg-8.0 from https://ffmpeg.org/releases/ffmpeg-8.0.tar.xz
|
||||
284
3rdparty/ffmpeg/include/libavcodec/avcodec.h
vendored
284
3rdparty/ffmpeg/include/libavcodec/avcodec.h
vendored
@@ -187,17 +187,6 @@ struct AVCodecParameters;
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if FF_API_BUFFER_MIN_SIZE
|
||||
/**
|
||||
* @ingroup lavc_encoding
|
||||
* minimum encoding buffer size
|
||||
* Used to avoid some checks during header writing.
|
||||
* @deprecated Unused: avcodec_receive_packet() does not work
|
||||
* with preallocated packet buffers.
|
||||
*/
|
||||
#define AV_INPUT_BUFFER_MIN_SIZE 16384
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup lavc_encoding
|
||||
*/
|
||||
@@ -234,18 +223,9 @@ typedef struct RcOverride{
|
||||
* Use qpel MC.
|
||||
*/
|
||||
#define AV_CODEC_FLAG_QPEL (1 << 4)
|
||||
#if FF_API_DROPCHANGED
|
||||
/**
|
||||
* Don't output frames whose parameters differ from first
|
||||
* decoded frame in stream.
|
||||
*
|
||||
* @deprecated callers should implement this functionality in their own code
|
||||
*/
|
||||
#define AV_CODEC_FLAG_DROPCHANGED (1 << 5)
|
||||
#endif
|
||||
/**
|
||||
* Request the encoder to output reconstructed frames, i.e.\ frames that would
|
||||
* be produced by decoding the encoded bistream. These frames may be retrieved
|
||||
* be produced by decoding the encoded bitstream. These frames may be retrieved
|
||||
* by calling avcodec_receive_frame() immediately after a successful call to
|
||||
* avcodec_receive_packet().
|
||||
*
|
||||
@@ -419,6 +399,12 @@ typedef struct RcOverride{
|
||||
*/
|
||||
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3)
|
||||
|
||||
/**
|
||||
* Decoding only.
|
||||
* Do not apply picture enhancement layers, export them instead.
|
||||
*/
|
||||
#define AV_CODEC_EXPORT_DATA_ENHANCEMENTS (1 << 4)
|
||||
|
||||
/**
|
||||
* The decoder will keep a reference to the frame and may reuse it later.
|
||||
*/
|
||||
@@ -509,16 +495,21 @@ typedef struct AVCodecContext {
|
||||
int flags2;
|
||||
|
||||
/**
|
||||
* some codecs need / can use extradata like Huffman tables.
|
||||
* MJPEG: Huffman tables
|
||||
* rv10: additional flags
|
||||
* MPEG-4: global headers (they can be in the bitstream or here)
|
||||
* The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger
|
||||
* than extradata_size to avoid problems if it is read with the bitstream reader.
|
||||
* The bytewise contents of extradata must not depend on the architecture or CPU endianness.
|
||||
* Must be allocated with the av_malloc() family of functions.
|
||||
* - encoding: Set/allocated/freed by libavcodec.
|
||||
* - decoding: Set/allocated/freed by user.
|
||||
* Out-of-band global headers that may be used by some codecs.
|
||||
*
|
||||
* - decoding: Should be set by the caller when available (typically from a
|
||||
* demuxer) before opening the decoder; some decoders require this to be
|
||||
* set and will fail to initialize otherwise.
|
||||
*
|
||||
* The array must be allocated with the av_malloc() family of functions;
|
||||
* allocated size must be at least AV_INPUT_BUFFER_PADDING_SIZE bytes
|
||||
* larger than extradata_size.
|
||||
*
|
||||
* - encoding: May be set by the encoder in avcodec_open2() (possibly
|
||||
* depending on whether the AV_CODEC_FLAG_GLOBAL_HEADER flag is set).
|
||||
*
|
||||
* After being set, the array is owned by the codec and freed in
|
||||
* avcodec_free_context().
|
||||
*/
|
||||
uint8_t *extradata;
|
||||
int extradata_size;
|
||||
@@ -559,23 +550,6 @@ typedef struct AVCodecContext {
|
||||
*/
|
||||
AVRational framerate;
|
||||
|
||||
#if FF_API_TICKS_PER_FRAME
|
||||
/**
|
||||
* For some codecs, the time base is closer to the field rate than the frame rate.
|
||||
* Most notably, H.264 and MPEG-2 specify time_base as half of frame duration
|
||||
* if no telecine is used ...
|
||||
*
|
||||
* Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.
|
||||
*
|
||||
* @deprecated
|
||||
* - decoding: Use AVCodecDescriptor.props & AV_CODEC_PROP_FIELDS
|
||||
* - encoding: Set AVCodecContext.framerate instead
|
||||
*
|
||||
*/
|
||||
attribute_deprecated
|
||||
int ticks_per_frame;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Codec delay.
|
||||
*
|
||||
@@ -1175,6 +1149,10 @@ typedef struct AVCodecContext {
|
||||
* this callback and filled with the extra buffers if there are more
|
||||
* buffers than buf[] can hold. extended_buf will be freed in
|
||||
* av_frame_unref().
|
||||
* Decoders will generally initialize the whole buffer before it is output
|
||||
* but it can in rare error conditions happen that uninitialized data is passed
|
||||
* through. \important The buffers returned by get_buffer* should thus not contain sensitive
|
||||
* data.
|
||||
*
|
||||
* If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call
|
||||
* avcodec_default_get_buffer2() instead of providing buffers allocated by
|
||||
@@ -1538,6 +1516,7 @@ typedef struct AVCodecContext {
|
||||
#define FF_DCT_MMX 3
|
||||
#define FF_DCT_ALTIVEC 5
|
||||
#define FF_DCT_FAAN 6
|
||||
#define FF_DCT_NEON 7
|
||||
|
||||
/**
|
||||
* IDCT algorithm, see FF_IDCT_* below.
|
||||
@@ -1637,165 +1616,29 @@ typedef struct AVCodecContext {
|
||||
* See the AV_PROFILE_* defines in defs.h.
|
||||
*/
|
||||
int profile;
|
||||
#if FF_API_FF_PROFILE_LEVEL
|
||||
/** @deprecated The following defines are deprecated; use AV_PROFILE_*
|
||||
* in defs.h instead. */
|
||||
#define FF_PROFILE_UNKNOWN -99
|
||||
#define FF_PROFILE_RESERVED -100
|
||||
|
||||
#define FF_PROFILE_AAC_MAIN 0
|
||||
#define FF_PROFILE_AAC_LOW 1
|
||||
#define FF_PROFILE_AAC_SSR 2
|
||||
#define FF_PROFILE_AAC_LTP 3
|
||||
#define FF_PROFILE_AAC_HE 4
|
||||
#define FF_PROFILE_AAC_HE_V2 28
|
||||
#define FF_PROFILE_AAC_LD 22
|
||||
#define FF_PROFILE_AAC_ELD 38
|
||||
#define FF_PROFILE_MPEG2_AAC_LOW 128
|
||||
#define FF_PROFILE_MPEG2_AAC_HE 131
|
||||
|
||||
#define FF_PROFILE_DNXHD 0
|
||||
#define FF_PROFILE_DNXHR_LB 1
|
||||
#define FF_PROFILE_DNXHR_SQ 2
|
||||
#define FF_PROFILE_DNXHR_HQ 3
|
||||
#define FF_PROFILE_DNXHR_HQX 4
|
||||
#define FF_PROFILE_DNXHR_444 5
|
||||
|
||||
#define FF_PROFILE_DTS 20
|
||||
#define FF_PROFILE_DTS_ES 30
|
||||
#define FF_PROFILE_DTS_96_24 40
|
||||
#define FF_PROFILE_DTS_HD_HRA 50
|
||||
#define FF_PROFILE_DTS_HD_MA 60
|
||||
#define FF_PROFILE_DTS_EXPRESS 70
|
||||
#define FF_PROFILE_DTS_HD_MA_X 61
|
||||
#define FF_PROFILE_DTS_HD_MA_X_IMAX 62
|
||||
|
||||
|
||||
#define FF_PROFILE_EAC3_DDP_ATMOS 30
|
||||
|
||||
#define FF_PROFILE_TRUEHD_ATMOS 30
|
||||
|
||||
#define FF_PROFILE_MPEG2_422 0
|
||||
#define FF_PROFILE_MPEG2_HIGH 1
|
||||
#define FF_PROFILE_MPEG2_SS 2
|
||||
#define FF_PROFILE_MPEG2_SNR_SCALABLE 3
|
||||
#define FF_PROFILE_MPEG2_MAIN 4
|
||||
#define FF_PROFILE_MPEG2_SIMPLE 5
|
||||
|
||||
#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag
|
||||
#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag
|
||||
|
||||
#define FF_PROFILE_H264_BASELINE 66
|
||||
#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED)
|
||||
#define FF_PROFILE_H264_MAIN 77
|
||||
#define FF_PROFILE_H264_EXTENDED 88
|
||||
#define FF_PROFILE_H264_HIGH 100
|
||||
#define FF_PROFILE_H264_HIGH_10 110
|
||||
#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA)
|
||||
#define FF_PROFILE_H264_MULTIVIEW_HIGH 118
|
||||
#define FF_PROFILE_H264_HIGH_422 122
|
||||
#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA)
|
||||
#define FF_PROFILE_H264_STEREO_HIGH 128
|
||||
#define FF_PROFILE_H264_HIGH_444 144
|
||||
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244
|
||||
#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA)
|
||||
#define FF_PROFILE_H264_CAVLC_444 44
|
||||
|
||||
#define FF_PROFILE_VC1_SIMPLE 0
|
||||
#define FF_PROFILE_VC1_MAIN 1
|
||||
#define FF_PROFILE_VC1_COMPLEX 2
|
||||
#define FF_PROFILE_VC1_ADVANCED 3
|
||||
|
||||
#define FF_PROFILE_MPEG4_SIMPLE 0
|
||||
#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1
|
||||
#define FF_PROFILE_MPEG4_CORE 2
|
||||
#define FF_PROFILE_MPEG4_MAIN 3
|
||||
#define FF_PROFILE_MPEG4_N_BIT 4
|
||||
#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5
|
||||
#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6
|
||||
#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7
|
||||
#define FF_PROFILE_MPEG4_HYBRID 8
|
||||
#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9
|
||||
#define FF_PROFILE_MPEG4_CORE_SCALABLE 10
|
||||
#define FF_PROFILE_MPEG4_ADVANCED_CODING 11
|
||||
#define FF_PROFILE_MPEG4_ADVANCED_CORE 12
|
||||
#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13
|
||||
#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14
|
||||
#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15
|
||||
|
||||
#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1
|
||||
#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2
|
||||
#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768
|
||||
#define FF_PROFILE_JPEG2000_DCINEMA_2K 3
|
||||
#define FF_PROFILE_JPEG2000_DCINEMA_4K 4
|
||||
|
||||
#define FF_PROFILE_VP9_0 0
|
||||
#define FF_PROFILE_VP9_1 1
|
||||
#define FF_PROFILE_VP9_2 2
|
||||
#define FF_PROFILE_VP9_3 3
|
||||
|
||||
#define FF_PROFILE_HEVC_MAIN 1
|
||||
#define FF_PROFILE_HEVC_MAIN_10 2
|
||||
#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3
|
||||
#define FF_PROFILE_HEVC_REXT 4
|
||||
#define FF_PROFILE_HEVC_SCC 9
|
||||
|
||||
#define FF_PROFILE_VVC_MAIN_10 1
|
||||
#define FF_PROFILE_VVC_MAIN_10_444 33
|
||||
|
||||
#define FF_PROFILE_AV1_MAIN 0
|
||||
#define FF_PROFILE_AV1_HIGH 1
|
||||
#define FF_PROFILE_AV1_PROFESSIONAL 2
|
||||
|
||||
#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0
|
||||
#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1
|
||||
#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2
|
||||
#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3
|
||||
#define FF_PROFILE_MJPEG_JPEG_LS 0xf7
|
||||
|
||||
#define FF_PROFILE_SBC_MSBC 1
|
||||
|
||||
#define FF_PROFILE_PRORES_PROXY 0
|
||||
#define FF_PROFILE_PRORES_LT 1
|
||||
#define FF_PROFILE_PRORES_STANDARD 2
|
||||
#define FF_PROFILE_PRORES_HQ 3
|
||||
#define FF_PROFILE_PRORES_4444 4
|
||||
#define FF_PROFILE_PRORES_XQ 5
|
||||
|
||||
#define FF_PROFILE_ARIB_PROFILE_A 0
|
||||
#define FF_PROFILE_ARIB_PROFILE_C 1
|
||||
|
||||
#define FF_PROFILE_KLVA_SYNC 0
|
||||
#define FF_PROFILE_KLVA_ASYNC 1
|
||||
|
||||
#define FF_PROFILE_EVC_BASELINE 0
|
||||
#define FF_PROFILE_EVC_MAIN 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encoding level descriptor.
|
||||
* - encoding: Set by user, corresponds to a specific level defined by the
|
||||
* codec, usually corresponding to the profile level, if not specified it
|
||||
* is set to FF_LEVEL_UNKNOWN.
|
||||
* is set to AV_LEVEL_UNKNOWN.
|
||||
* - decoding: Set by libavcodec.
|
||||
* See AV_LEVEL_* in defs.h.
|
||||
*/
|
||||
int level;
|
||||
#if FF_API_FF_PROFILE_LEVEL
|
||||
/** @deprecated The following define is deprecated; use AV_LEVEL_UNKOWN
|
||||
* in defs.h instead. */
|
||||
#define FF_LEVEL_UNKNOWN -99
|
||||
#endif
|
||||
|
||||
#if FF_API_CODEC_PROPS
|
||||
/**
|
||||
* Properties of the stream that gets decoded
|
||||
* - encoding: unused
|
||||
* - decoding: set by libavcodec
|
||||
*/
|
||||
attribute_deprecated
|
||||
unsigned properties;
|
||||
#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001
|
||||
#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002
|
||||
#define FF_CODEC_PROPERTY_FILM_GRAIN 0x00000004
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Skip loop filtering for selected frames.
|
||||
@@ -1884,8 +1727,13 @@ typedef struct AVCodecContext {
|
||||
* For SUBTITLE_ASS subtitle type, it should contain the whole ASS
|
||||
* [Script Info] and [V4+ Styles] section, plus the [Events] line and
|
||||
* the Format line following. It shouldn't include any Dialogue line.
|
||||
* - encoding: Set/allocated/freed by user (before avcodec_open2())
|
||||
* - decoding: Set/allocated/freed by libavcodec (by avcodec_open2())
|
||||
*
|
||||
* - encoding: May be set by the caller before avcodec_open2() to an array
|
||||
* allocated with the av_malloc() family of functions.
|
||||
* - decoding: May be set by libavcodec in avcodec_open2().
|
||||
*
|
||||
* After being set, the array is owned by the codec and freed in
|
||||
* avcodec_free_context().
|
||||
*/
|
||||
int subtitle_header_size;
|
||||
uint8_t *subtitle_header;
|
||||
@@ -2071,7 +1919,7 @@ typedef struct AVCodecContext {
|
||||
* - encoding: may be set by user before calling avcodec_open2() for
|
||||
* encoder configuration. Afterwards owned and freed by the
|
||||
* encoder.
|
||||
* - decoding: unused
|
||||
* - decoding: may be set by libavcodec in avcodec_open2().
|
||||
*/
|
||||
AVFrameSideData **decoded_side_data;
|
||||
int nb_decoded_side_data;
|
||||
@@ -2369,24 +2217,6 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
|
||||
*/
|
||||
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
|
||||
|
||||
#if FF_API_AVCODEC_CLOSE
|
||||
/**
|
||||
* Close a given AVCodecContext and free all the data associated with it
|
||||
* (but not the AVCodecContext itself).
|
||||
*
|
||||
* Calling this function on an AVCodecContext that hasn't been opened will free
|
||||
* the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL
|
||||
* codec. Subsequent calls will do nothing.
|
||||
*
|
||||
* @deprecated Do not use this function. Use avcodec_free_context() to destroy a
|
||||
* codec context (either open or closed). Opening and closing a codec context
|
||||
* multiple times is not supported anymore -- use multiple codec contexts
|
||||
* instead.
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avcodec_close(AVCodecContext *avctx);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Free all allocated data in the given subtitle struct.
|
||||
*
|
||||
@@ -2690,6 +2520,36 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
|
||||
enum AVPixelFormat hw_pix_fmt,
|
||||
AVBufferRef **out_frames_ref);
|
||||
|
||||
enum AVCodecConfig {
|
||||
AV_CODEC_CONFIG_PIX_FORMAT, ///< AVPixelFormat, terminated by AV_PIX_FMT_NONE
|
||||
AV_CODEC_CONFIG_FRAME_RATE, ///< AVRational, terminated by {0, 0}
|
||||
AV_CODEC_CONFIG_SAMPLE_RATE, ///< int, terminated by 0
|
||||
AV_CODEC_CONFIG_SAMPLE_FORMAT, ///< AVSampleFormat, terminated by AV_SAMPLE_FMT_NONE
|
||||
AV_CODEC_CONFIG_CHANNEL_LAYOUT, ///< AVChannelLayout, terminated by {0}
|
||||
AV_CODEC_CONFIG_COLOR_RANGE, ///< AVColorRange, terminated by AVCOL_RANGE_UNSPECIFIED
|
||||
AV_CODEC_CONFIG_COLOR_SPACE, ///< AVColorSpace, terminated by AVCOL_SPC_UNSPECIFIED
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a list of all supported values for a given configuration type.
|
||||
*
|
||||
* @param avctx An optional context to use. Values such as
|
||||
* `strict_std_compliance` may affect the result. If NULL,
|
||||
* default values are used.
|
||||
* @param codec The codec to query, or NULL to use avctx->codec.
|
||||
* @param config The configuration to query.
|
||||
* @param flags Currently unused; should be set to zero.
|
||||
* @param out_configs On success, set to a list of configurations, terminated
|
||||
* by a config-specific terminator, or NULL if all
|
||||
* possible values are supported.
|
||||
* @param out_num_configs On success, set to the number of elements in
|
||||
*out_configs, excluding the terminator. Optional.
|
||||
*/
|
||||
int avcodec_get_supported_config(const AVCodecContext *avctx,
|
||||
const AVCodec *codec, enum AVCodecConfig config,
|
||||
unsigned flags, const void **out_configs,
|
||||
int *out_num_configs);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -3040,7 +2900,7 @@ int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
|
||||
*
|
||||
* @note for encoders, this function will only do something if the encoder
|
||||
* declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder
|
||||
* will drain any remaining packets, and can then be re-used for a different
|
||||
* will drain any remaining packets, and can then be reused for a different
|
||||
* stream (as opposed to sending a null frame which will leave the encoder
|
||||
* in a permanent EOF state after draining). This can be desirable if the
|
||||
* cost of tearing down and replacing the encoder instance is high.
|
||||
@@ -3075,8 +2935,8 @@ void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size);
|
||||
void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size);
|
||||
|
||||
/**
|
||||
* @return a positive value if s is open (i.e. avcodec_open2() was called on it
|
||||
* with no corresponding avcodec_close()), 0 otherwise.
|
||||
* @return a positive value if s is open (i.e. avcodec_open2() was called on it),
|
||||
* 0 otherwise.
|
||||
*/
|
||||
int avcodec_is_open(AVCodecContext *s);
|
||||
|
||||
|
||||
34
3rdparty/ffmpeg/include/libavcodec/codec.h
vendored
34
3rdparty/ffmpeg/include/libavcodec/codec.h
vendored
@@ -80,21 +80,6 @@
|
||||
*/
|
||||
#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6)
|
||||
|
||||
#if FF_API_SUBFRAMES
|
||||
/**
|
||||
* Codec can output multiple frames per AVPacket
|
||||
* Normally demuxers return one frame at a time, demuxers which do not do
|
||||
* are connected to a parser to split what they return into proper frames.
|
||||
* This flag is reserved to the very rare category of codecs which have a
|
||||
* bitstream that cannot be split into frames without timeconsuming
|
||||
* operations like full decoding. Demuxers carrying such bitstreams thus
|
||||
* may return multiple frames in a packet. This has many disadvantages like
|
||||
* prohibiting stream copy in many cases thus it should only be considered
|
||||
* as a last resort.
|
||||
*/
|
||||
#define AV_CODEC_CAP_SUBFRAMES (1 << 8)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Codec is experimental and is thus avoided in favor of non experimental
|
||||
* encoders
|
||||
@@ -205,10 +190,19 @@ typedef struct AVCodec {
|
||||
*/
|
||||
int capabilities;
|
||||
uint8_t max_lowres; ///< maximum value for lowres supported by the decoder
|
||||
const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
|
||||
const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
|
||||
const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
|
||||
const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
|
||||
|
||||
/**
|
||||
* Deprecated codec capabilities.
|
||||
*/
|
||||
attribute_deprecated
|
||||
const AVRational *supported_framerates; ///< @deprecated use avcodec_get_supported_config()
|
||||
attribute_deprecated
|
||||
const enum AVPixelFormat *pix_fmts; ///< @deprecated use avcodec_get_supported_config()
|
||||
attribute_deprecated
|
||||
const int *supported_samplerates; ///< @deprecated use avcodec_get_supported_config()
|
||||
attribute_deprecated
|
||||
const enum AVSampleFormat *sample_fmts; ///< @deprecated use avcodec_get_supported_config()
|
||||
|
||||
const AVClass *priv_class; ///< AVClass for the private context
|
||||
const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {AV_PROFILE_UNKNOWN}
|
||||
|
||||
@@ -226,7 +220,9 @@ typedef struct AVCodec {
|
||||
|
||||
/**
|
||||
* Array of supported channel layouts, terminated with a zeroed layout.
|
||||
* @deprecated use avcodec_get_supported_config()
|
||||
*/
|
||||
attribute_deprecated
|
||||
const AVChannelLayout *ch_layouts;
|
||||
} AVCodec;
|
||||
|
||||
|
||||
16
3rdparty/ffmpeg/include/libavcodec/codec_id.h
vendored
16
3rdparty/ffmpeg/include/libavcodec/codec_id.h
vendored
@@ -206,7 +206,9 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_BMV_VIDEO,
|
||||
AV_CODEC_ID_VBLE,
|
||||
AV_CODEC_ID_DXTORY,
|
||||
#if FF_API_V408_CODECID
|
||||
AV_CODEC_ID_V410,
|
||||
#endif
|
||||
AV_CODEC_ID_XWD,
|
||||
AV_CODEC_ID_CDXL,
|
||||
AV_CODEC_ID_XBM,
|
||||
@@ -254,8 +256,10 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_012V,
|
||||
AV_CODEC_ID_AVUI,
|
||||
AV_CODEC_ID_TARGA_Y216,
|
||||
#if FF_API_V408_CODECID
|
||||
AV_CODEC_ID_V308,
|
||||
AV_CODEC_ID_V408,
|
||||
#endif
|
||||
AV_CODEC_ID_YUV4,
|
||||
AV_CODEC_ID_AVRN,
|
||||
AV_CODEC_ID_CPIA,
|
||||
@@ -322,6 +326,11 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_RTV1,
|
||||
AV_CODEC_ID_VMIX,
|
||||
AV_CODEC_ID_LEAD,
|
||||
AV_CODEC_ID_DNXUC,
|
||||
AV_CODEC_ID_RV60,
|
||||
AV_CODEC_ID_JPEGXL_ANIM,
|
||||
AV_CODEC_ID_APV,
|
||||
AV_CODEC_ID_PRORES_RAW,
|
||||
|
||||
/* various PCM "codecs" */
|
||||
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
|
||||
@@ -416,6 +425,8 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_ADPCM_IMA_MOFLEX,
|
||||
AV_CODEC_ID_ADPCM_IMA_ACORN,
|
||||
AV_CODEC_ID_ADPCM_XMD,
|
||||
AV_CODEC_ID_ADPCM_IMA_XBOX,
|
||||
AV_CODEC_ID_ADPCM_SANYO,
|
||||
|
||||
/* AMR */
|
||||
AV_CODEC_ID_AMR_NB = 0x12000,
|
||||
@@ -543,6 +554,8 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_AC4,
|
||||
AV_CODEC_ID_OSQ,
|
||||
AV_CODEC_ID_QOA,
|
||||
AV_CODEC_ID_LC3,
|
||||
AV_CODEC_ID_G728,
|
||||
|
||||
/* subtitle codecs */
|
||||
AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs.
|
||||
@@ -572,6 +585,7 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_HDMV_TEXT_SUBTITLE,
|
||||
AV_CODEC_ID_TTML,
|
||||
AV_CODEC_ID_ARIB_CAPTION,
|
||||
AV_CODEC_ID_IVTV_VBI,
|
||||
|
||||
/* other specific kind of codecs (generally used for attachments) */
|
||||
AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs.
|
||||
@@ -588,6 +602,8 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_TIMED_ID3,
|
||||
AV_CODEC_ID_BIN_DATA,
|
||||
AV_CODEC_ID_SMPTE_2038,
|
||||
AV_CODEC_ID_LCEVC,
|
||||
AV_CODEC_ID_SMPTE_436M_ANC,
|
||||
|
||||
|
||||
AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it
|
||||
|
||||
@@ -148,7 +148,7 @@ typedef struct AVCodecParameters {
|
||||
* durations. Should be set to { 0, 1 } when some frames have differing
|
||||
* durations or if the value is not known.
|
||||
*
|
||||
* @note This field correponds to values that are stored in codec-level
|
||||
* @note This field corresponds to values that are stored in codec-level
|
||||
* headers and is typically overridden by container/transport-layer
|
||||
* timestamps, when available. It should thus be used only as a last resort,
|
||||
* when no higher-level timing information is available.
|
||||
|
||||
27
3rdparty/ffmpeg/include/libavcodec/defs.h
vendored
27
3rdparty/ffmpeg/include/libavcodec/defs.h
vendored
@@ -73,6 +73,7 @@
|
||||
#define AV_PROFILE_AAC_HE_V2 28
|
||||
#define AV_PROFILE_AAC_LD 22
|
||||
#define AV_PROFILE_AAC_ELD 38
|
||||
#define AV_PROFILE_AAC_USAC 41
|
||||
#define AV_PROFILE_MPEG2_AAC_LOW 128
|
||||
#define AV_PROFILE_MPEG2_AAC_HE 131
|
||||
|
||||
@@ -159,6 +160,7 @@
|
||||
#define AV_PROFILE_HEVC_MAIN_10 2
|
||||
#define AV_PROFILE_HEVC_MAIN_STILL_PICTURE 3
|
||||
#define AV_PROFILE_HEVC_REXT 4
|
||||
#define AV_PROFILE_HEVC_MULTIVIEW_MAIN 6
|
||||
#define AV_PROFILE_HEVC_SCC 9
|
||||
|
||||
#define AV_PROFILE_VVC_MAIN_10 1
|
||||
@@ -183,6 +185,9 @@
|
||||
#define AV_PROFILE_PRORES_4444 4
|
||||
#define AV_PROFILE_PRORES_XQ 5
|
||||
|
||||
#define AV_PROFILE_PRORES_RAW 0
|
||||
#define AV_PROFILE_PRORES_RAW_HQ 1
|
||||
|
||||
#define AV_PROFILE_ARIB_PROFILE_A 0
|
||||
#define AV_PROFILE_ARIB_PROFILE_C 1
|
||||
|
||||
@@ -192,6 +197,14 @@
|
||||
#define AV_PROFILE_EVC_BASELINE 0
|
||||
#define AV_PROFILE_EVC_MAIN 1
|
||||
|
||||
#define AV_PROFILE_APV_422_10 33
|
||||
#define AV_PROFILE_APV_422_12 44
|
||||
#define AV_PROFILE_APV_444_10 55
|
||||
#define AV_PROFILE_APV_444_12 66
|
||||
#define AV_PROFILE_APV_4444_10 77
|
||||
#define AV_PROFILE_APV_4444_12 88
|
||||
#define AV_PROFILE_APV_400_10 99
|
||||
|
||||
|
||||
#define AV_LEVEL_UNKNOWN -99
|
||||
|
||||
@@ -323,6 +336,20 @@ typedef struct AVProducerReferenceTime {
|
||||
int flags;
|
||||
} AVProducerReferenceTime;
|
||||
|
||||
/**
|
||||
* RTCP SR (Sender Report) information
|
||||
*
|
||||
* The received sender report information for an RTSP
|
||||
* stream, exposed as AV_PKT_DATA_RTCP_SR side data.
|
||||
*/
|
||||
typedef struct AVRTCPSenderReport {
|
||||
uint32_t ssrc; ///< Synchronization source identifier
|
||||
uint64_t ntp_timestamp; ///< NTP time when the report was sent
|
||||
uint32_t rtp_timestamp; ///< RTP time when the report was sent
|
||||
uint32_t sender_nb_packets; ///< Total number of packets sent
|
||||
uint32_t sender_nb_bytes; ///< Total number of bytes sent (excluding headers or padding)
|
||||
} AVRTCPSenderReport;
|
||||
|
||||
/**
|
||||
* Encode extradata length to a buffer. Used by xiph codecs.
|
||||
*
|
||||
|
||||
55
3rdparty/ffmpeg/include/libavcodec/packet.h
vendored
55
3rdparty/ffmpeg/include/libavcodec/packet.h
vendored
@@ -59,10 +59,6 @@ enum AVPacketSideDataType {
|
||||
* An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows:
|
||||
* @code
|
||||
* u32le param_flags
|
||||
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT)
|
||||
* s32le channel_count
|
||||
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT)
|
||||
* u64le channel_layout
|
||||
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE)
|
||||
* s32le sample_rate
|
||||
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS)
|
||||
@@ -146,7 +142,7 @@ enum AVPacketSideDataType {
|
||||
AV_PKT_DATA_CPB_PROPERTIES,
|
||||
|
||||
/**
|
||||
* Recommmends skipping the specified number of samples
|
||||
* Recommends skipping the specified number of samples
|
||||
* @code
|
||||
* u32le number of samples to skip from start of this packet
|
||||
* u32le number of samples to skip from end of this packet
|
||||
@@ -330,6 +326,42 @@ enum AVPacketSideDataType {
|
||||
*/
|
||||
AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
|
||||
|
||||
/**
|
||||
* The number of pixels to discard from the top/bottom/left/right border of the
|
||||
* decoded frame to obtain the sub-rectangle intended for presentation.
|
||||
*
|
||||
* @code
|
||||
* u32le crop_top
|
||||
* u32le crop_bottom
|
||||
* u32le crop_left
|
||||
* u32le crop_right
|
||||
* @endcode
|
||||
*/
|
||||
AV_PKT_DATA_FRAME_CROPPING,
|
||||
|
||||
/**
|
||||
* Raw LCEVC payload data, as a uint8_t array, with NAL emulation
|
||||
* bytes intact.
|
||||
*/
|
||||
AV_PKT_DATA_LCEVC,
|
||||
|
||||
/**
|
||||
* This side data contains information about the reference display width(s)
|
||||
* and reference viewing distance(s) as well as information about the
|
||||
* corresponding reference stereo pair(s), i.e., the pair(s) of views to be
|
||||
* displayed for the viewer's left and right eyes on the reference display
|
||||
* at the reference viewing distance.
|
||||
* The payload is the AV3DReferenceDisplaysInfo struct defined in
|
||||
* libavutil/tdrdi.h.
|
||||
*/
|
||||
AV_PKT_DATA_3D_REFERENCE_DISPLAYS,
|
||||
|
||||
/**
|
||||
* Contains the last received RTCP SR (Sender Report) information
|
||||
* in the form of the AVRTCPSenderReport struct.
|
||||
*/
|
||||
AV_PKT_DATA_RTCP_SR,
|
||||
|
||||
/**
|
||||
* The number of side data types.
|
||||
* This is not part of the public API/ABI in the sense that it may
|
||||
@@ -341,8 +373,6 @@ enum AVPacketSideDataType {
|
||||
AV_PKT_DATA_NB
|
||||
};
|
||||
|
||||
#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED
|
||||
|
||||
/**
|
||||
* This structure stores auxiliary information for decoding, presenting, or
|
||||
* otherwise processing the coded stream. It is typically exported by demuxers
|
||||
@@ -351,11 +381,11 @@ enum AVPacketSideDataType {
|
||||
*
|
||||
* Global side data is handled as follows:
|
||||
* - During demuxing, it may be exported through
|
||||
* @ref AVStream.codecpar.side_data "AVStream's codec parameters", which can
|
||||
* @ref AVCodecParameters.coded_side_data "AVStream's codec parameters", which can
|
||||
* then be passed as input to decoders through the
|
||||
* @ref AVCodecContext.coded_side_data "decoder context's side data", for
|
||||
* initialization.
|
||||
* - For muxing, it can be fed through @ref AVStream.codecpar.side_data
|
||||
* - For muxing, it can be fed through @ref AVCodecParameters.coded_side_data
|
||||
* "AVStream's codec parameters", typically the output of encoders through
|
||||
* the @ref AVCodecContext.coded_side_data "encoder context's side data", for
|
||||
* initialization.
|
||||
@@ -863,6 +893,13 @@ int av_packet_make_writable(AVPacket *pkt);
|
||||
*/
|
||||
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);
|
||||
|
||||
/**
|
||||
* Allocate an AVContainerFifo instance for AVPacket.
|
||||
*
|
||||
* @param flags currently unused
|
||||
*/
|
||||
struct AVContainerFifo *av_container_fifo_alloc_avpacket(unsigned flags);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
33
3rdparty/ffmpeg/include/libavcodec/vdpau.h
vendored
33
3rdparty/ffmpeg/include/libavcodec/vdpau.h
vendored
@@ -93,28 +93,6 @@ typedef struct AVVDPAUContext {
|
||||
AVVDPAU_Render2 render2;
|
||||
} AVVDPAUContext;
|
||||
|
||||
#if FF_API_VDPAU_ALLOC_GET_SET
|
||||
/**
|
||||
* @brief allocation function for AVVDPAUContext
|
||||
*
|
||||
* Allows extending the struct without breaking API/ABI
|
||||
* @deprecated use av_vdpau_bind_context() instead
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVVDPAUContext *av_alloc_vdpaucontext(void);
|
||||
|
||||
/**
|
||||
* @deprecated render2 is public and can be accessed directly
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVVDPAU_Render2 av_vdpau_hwaccel_get_render2(const AVVDPAUContext *);
|
||||
/**
|
||||
* @deprecated render2 is public and can be accessed directly
|
||||
*/
|
||||
attribute_deprecated
|
||||
void av_vdpau_hwaccel_set_render2(AVVDPAUContext *, AVVDPAU_Render2);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Associate a VDPAU device with a codec context for hardware acceleration.
|
||||
* This function is meant to be called from the get_format() codec callback,
|
||||
@@ -155,17 +133,6 @@ int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
|
||||
int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type,
|
||||
uint32_t *width, uint32_t *height);
|
||||
|
||||
#if FF_API_VDPAU_ALLOC_GET_SET
|
||||
/**
|
||||
* Allocate an AVVDPAUContext.
|
||||
*
|
||||
* @return Newly-allocated AVVDPAUContext or NULL on failure.
|
||||
* @deprecated use av_vdpau_bind_context() instead
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVVDPAUContext *av_vdpau_alloc_context(void);
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* AVCODEC_VDPAU_H */
|
||||
|
||||
2
3rdparty/ffmpeg/include/libavcodec/version.h
vendored
2
3rdparty/ffmpeg/include/libavcodec/version.h
vendored
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "version_major.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MINOR 3
|
||||
#define LIBAVCODEC_VERSION_MINOR 11
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Libavcodec version macros.
|
||||
*/
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 61
|
||||
#define LIBAVCODEC_VERSION_MAJOR 62
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
@@ -37,15 +37,19 @@
|
||||
* at once through the bump. This improves the git bisect-ability of the change.
|
||||
*/
|
||||
|
||||
#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_SUBFRAMES (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_TICKS_PER_FRAME (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_DROPCHANGED (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
|
||||
#define FF_API_AVFFT (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_FF_PROFILE_LEVEL (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_AVCODEC_CLOSE (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_BUFFER_MIN_SIZE (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_VDPAU_ALLOC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 62)
|
||||
#define FF_API_V408_CODECID (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
#define FF_API_CODEC_PROPS (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
#define FF_API_EXR_GAMMA (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
|
||||
#define FF_API_NVDEC_OLD_PIX_FMTS (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
|
||||
// reminder to remove the OMX encoder on next major bump
|
||||
#define FF_CODEC_OMX (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
// reminder to remove Sonic Lossy/Lossless encoders on next major bump
|
||||
#define FF_CODEC_SONIC_ENC (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
// reminder to remove Sonic decoder on next-next major bump
|
||||
#define FF_CODEC_SONIC_DEC (LIBAVCODEC_VERSION_MAJOR < 63)
|
||||
|
||||
#endif /* AVCODEC_VERSION_MAJOR_H */
|
||||
|
||||
217
3rdparty/ffmpeg/include/libavformat/avformat.h
vendored
217
3rdparty/ffmpeg/include/libavformat/avformat.h
vendored
@@ -146,8 +146,8 @@
|
||||
* consumed). The calling program can handle such unrecognized options as it
|
||||
* wishes, e.g.
|
||||
* @code
|
||||
* AVDictionaryEntry *e;
|
||||
* if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
|
||||
* const AVDictionaryEntry *e;
|
||||
* if ((e = av_dict_iterate(options, NULL))) {
|
||||
* fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
|
||||
* abort();
|
||||
* }
|
||||
@@ -459,7 +459,7 @@ typedef struct AVProbeData {
|
||||
#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)
|
||||
|
||||
#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension
|
||||
#define AVPROBE_SCORE_MIME 75 ///< score for file mime type
|
||||
#define AVPROBE_SCORE_MIME_BONUS 30 ///< score added for matching mime type
|
||||
#define AVPROBE_SCORE_MAX 100 ///< maximum score
|
||||
|
||||
#define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer
|
||||
@@ -470,8 +470,7 @@ typedef struct AVProbeData {
|
||||
/**
|
||||
* The muxer/demuxer is experimental and should be used with caution.
|
||||
*
|
||||
* - demuxers: will not be selected automatically by probing, must be specified
|
||||
* explicitly.
|
||||
* It will not be selected automatically, and must be specified explicitly.
|
||||
*/
|
||||
#define AVFMT_EXPERIMENTAL 0x0004
|
||||
#define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */
|
||||
@@ -485,9 +484,6 @@ typedef struct AVProbeData {
|
||||
#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */
|
||||
#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */
|
||||
#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */
|
||||
#if FF_API_ALLOW_FLUSH
|
||||
#define AVFMT_ALLOW_FLUSH 0x10000 /**< @deprecated: Just send a NULL packet if you want to flush a muxer. */
|
||||
#endif
|
||||
#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly
|
||||
increasing timestamps, but they must
|
||||
still be monotonic */
|
||||
@@ -713,6 +709,11 @@ typedef struct AVIndexEntry {
|
||||
* The video stream contains still images.
|
||||
*/
|
||||
#define AV_DISPOSITION_STILL_IMAGE (1 << 20)
|
||||
/**
|
||||
* The video stream contains multiple layers, e.g. stereoscopic views (cf. H.264
|
||||
* Annex G/H, or HEVC Annex F).
|
||||
*/
|
||||
#define AV_DISPOSITION_MULTILAYER (1 << 21)
|
||||
|
||||
/**
|
||||
* @return The AV_DISPOSITION_* flag corresponding to disp or a negative error
|
||||
@@ -842,38 +843,6 @@ typedef struct AVStream {
|
||||
*/
|
||||
AVPacket attached_pic;
|
||||
|
||||
#if FF_API_AVSTREAM_SIDE_DATA
|
||||
/**
|
||||
* An array of side data that applies to the whole stream (i.e. the
|
||||
* container does not allow it to change between packets).
|
||||
*
|
||||
* There may be no overlap between the side data in this array and side data
|
||||
* in the packets. I.e. a given side data is either exported by the muxer
|
||||
* (demuxing) / set by the caller (muxing) in this array, then it never
|
||||
* appears in the packets, or the side data is exported / sent through
|
||||
* the packets (always in the first packet where the value becomes known or
|
||||
* changes), then it does not appear in this array.
|
||||
*
|
||||
* - demuxing: Set by libavformat when the stream is created.
|
||||
* - muxing: May be set by the caller before avformat_write_header().
|
||||
*
|
||||
* Freed by libavformat in avformat_free_context().
|
||||
*
|
||||
* @deprecated use AVStream's @ref AVCodecParameters.coded_side_data
|
||||
* "codecpar side data".
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVPacketSideData *side_data;
|
||||
/**
|
||||
* The number of elements in the AVStream.side_data array.
|
||||
*
|
||||
* @deprecated use AVStream's @ref AVCodecParameters.nb_coded_side_data
|
||||
* "codecpar side data".
|
||||
*/
|
||||
attribute_deprecated
|
||||
int nb_side_data;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Flags indicating events happening on the stream, a combination of
|
||||
* AVSTREAM_EVENT_FLAG_*.
|
||||
@@ -957,7 +926,7 @@ typedef struct AVStream {
|
||||
* the sixth @ref AVStreamGroup.streams "stream" in the group is "512,512",
|
||||
* etc.
|
||||
*
|
||||
* The following is an example of a canvas with overlaping tiles:
|
||||
* The following is an example of a canvas with overlapping tiles:
|
||||
*
|
||||
* +-----------+
|
||||
* | %%%%% |
|
||||
@@ -1077,13 +1046,52 @@ typedef struct AVStreamGroupTileGrid {
|
||||
* final image before presentation.
|
||||
*/
|
||||
int height;
|
||||
|
||||
/**
|
||||
* Additional data associated with the grid.
|
||||
*
|
||||
* Should be allocated with av_packet_side_data_new() or
|
||||
* av_packet_side_data_add(), and will be freed by avformat_free_context().
|
||||
*/
|
||||
AVPacketSideData *coded_side_data;
|
||||
|
||||
/**
|
||||
* Amount of entries in @ref coded_side_data.
|
||||
*/
|
||||
int nb_coded_side_data;
|
||||
} AVStreamGroupTileGrid;
|
||||
|
||||
/**
|
||||
* AVStreamGroupLCEVC is meant to define the relation between video streams
|
||||
* and a data stream containing LCEVC enhancement layer NALUs.
|
||||
*
|
||||
* No more than one stream of @ref AVCodecParameters.codec_type "codec_type"
|
||||
* AVMEDIA_TYPE_DATA shall be present, and it must be of
|
||||
* @ref AVCodecParameters.codec_id "codec_id" AV_CODEC_ID_LCEVC.
|
||||
*/
|
||||
typedef struct AVStreamGroupLCEVC {
|
||||
const AVClass *av_class;
|
||||
|
||||
/**
|
||||
* Index of the LCEVC data stream in AVStreamGroup.
|
||||
*/
|
||||
unsigned int lcevc_index;
|
||||
/**
|
||||
* Width of the final stream for presentation.
|
||||
*/
|
||||
int width;
|
||||
/**
|
||||
* Height of the final image for presentation.
|
||||
*/
|
||||
int height;
|
||||
} AVStreamGroupLCEVC;
|
||||
|
||||
enum AVStreamGroupParamsType {
|
||||
AV_STREAM_GROUP_PARAMS_NONE,
|
||||
AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT,
|
||||
AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION,
|
||||
AV_STREAM_GROUP_PARAMS_TILE_GRID,
|
||||
AV_STREAM_GROUP_PARAMS_LCEVC,
|
||||
};
|
||||
|
||||
struct AVIAMFAudioElement;
|
||||
@@ -1125,6 +1133,7 @@ typedef struct AVStreamGroup {
|
||||
struct AVIAMFAudioElement *iamf_audio_element;
|
||||
struct AVIAMFMixPresentation *iamf_mix_presentation;
|
||||
struct AVStreamGroupTileGrid *tile_grid;
|
||||
struct AVStreamGroupLCEVC *lcevc;
|
||||
} params;
|
||||
|
||||
/**
|
||||
@@ -1411,7 +1420,7 @@ typedef struct AVFormatContext {
|
||||
#define AVFMT_FLAG_NONBLOCK 0x0004 ///< Do not block when reading packets from input.
|
||||
#define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS
|
||||
#define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container
|
||||
#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
|
||||
#define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the filling code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
|
||||
#define AVFMT_FLAG_NOBUFFER 0x0040 ///< Do not buffer frames when possible
|
||||
#define AVFMT_FLAG_CUSTOM_IO 0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.
|
||||
#define AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted
|
||||
@@ -1425,9 +1434,6 @@ typedef struct AVFormatContext {
|
||||
#define AVFMT_FLAG_BITEXACT 0x0400
|
||||
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
|
||||
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
|
||||
#if FF_API_LAVF_SHORTEST
|
||||
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
|
||||
#endif
|
||||
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
|
||||
|
||||
/**
|
||||
@@ -1439,7 +1445,7 @@ typedef struct AVFormatContext {
|
||||
*
|
||||
* @note this is \e not used for determining the \ref AVInputFormat
|
||||
* "input format"
|
||||
* @sa format_probesize
|
||||
* @see format_probesize
|
||||
*/
|
||||
int64_t probesize;
|
||||
|
||||
@@ -1664,9 +1670,11 @@ typedef struct AVFormatContext {
|
||||
int use_wallclock_as_timestamps;
|
||||
|
||||
/**
|
||||
* Skip duration calcuation in estimate_timings_from_pts.
|
||||
* Skip duration calculation in estimate_timings_from_pts.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user
|
||||
*
|
||||
* @see duration_probesize
|
||||
*/
|
||||
int skip_estimate_duration_from_pts;
|
||||
|
||||
@@ -1729,7 +1737,7 @@ typedef struct AVFormatContext {
|
||||
*
|
||||
* Demuxing only, set by the caller before avformat_open_input().
|
||||
*
|
||||
* @sa probesize
|
||||
* @see probesize
|
||||
*/
|
||||
int format_probesize;
|
||||
|
||||
@@ -1765,7 +1773,7 @@ typedef struct AVFormatContext {
|
||||
|
||||
/**
|
||||
* IO repositioned flag.
|
||||
* This is set by avformat when the underlaying IO context read pointer
|
||||
* This is set by avformat when the underlying IO context read pointer
|
||||
* is repositioned, for example when doing byte based seeking.
|
||||
* Demuxers can use the flag to detect such changes.
|
||||
*/
|
||||
@@ -1861,40 +1869,23 @@ typedef struct AVFormatContext {
|
||||
/**
|
||||
* A callback for closing the streams opened with AVFormatContext.io_open().
|
||||
*
|
||||
* Using this is preferred over io_close, because this can return an error.
|
||||
* Therefore this callback is used instead of io_close by the generic
|
||||
* libavformat code if io_close is NULL or the default.
|
||||
*
|
||||
* @param s the format context
|
||||
* @param pb IO context to be closed and freed
|
||||
* @return 0 on success, a negative AVERROR code on failure
|
||||
*/
|
||||
int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb);
|
||||
|
||||
/**
|
||||
* Maximum number of bytes read from input in order to determine stream durations
|
||||
* when using estimate_timings_from_pts in avformat_find_stream_info().
|
||||
* Demuxing only, set by the caller before avformat_find_stream_info().
|
||||
* Can be set to 0 to let avformat choose using a heuristic.
|
||||
*
|
||||
* @see skip_estimate_duration_from_pts
|
||||
*/
|
||||
int64_t duration_probesize;
|
||||
} AVFormatContext;
|
||||
|
||||
/**
|
||||
* This function will cause global side data to be injected in the next packet
|
||||
* of each stream as well as after any subsequent seek.
|
||||
*
|
||||
* @note global side data is always available in every AVStream's
|
||||
* @ref AVCodecParameters.coded_side_data "codecpar side data" array, and
|
||||
* in a @ref AVCodecContext.coded_side_data "decoder's side data" array if
|
||||
* initialized with said stream's codecpar.
|
||||
* @see av_packet_side_data_get()
|
||||
*/
|
||||
void av_format_inject_global_side_data(AVFormatContext *s);
|
||||
|
||||
#if FF_API_GET_DUR_ESTIMATE_METHOD
|
||||
/**
|
||||
* Returns the method used to set ctx->duration.
|
||||
*
|
||||
* @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE.
|
||||
* @deprecated duration_estimation_method is public and can be read directly.
|
||||
*/
|
||||
attribute_deprecated
|
||||
enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup lavf_core Core functions
|
||||
* @ingroup libavf
|
||||
@@ -2072,57 +2063,6 @@ AVStream *avformat_new_stream(AVFormatContext *s, const struct AVCodec *c);
|
||||
*/
|
||||
int avformat_stream_group_add_stream(AVStreamGroup *stg, AVStream *st);
|
||||
|
||||
#if FF_API_AVSTREAM_SIDE_DATA
|
||||
/**
|
||||
* Wrap an existing array as stream side data.
|
||||
*
|
||||
* @param st stream
|
||||
* @param type side information type
|
||||
* @param data the side data array. It must be allocated with the av_malloc()
|
||||
* family of functions. The ownership of the data is transferred to
|
||||
* st.
|
||||
* @param size side information size
|
||||
*
|
||||
* @return zero on success, a negative AVERROR code on failure. On failure,
|
||||
* the stream is unchanged and the data remains owned by the caller.
|
||||
* @deprecated use av_packet_side_data_add() with the stream's
|
||||
* @ref AVCodecParameters.coded_side_data "codecpar side data"
|
||||
*/
|
||||
attribute_deprecated
|
||||
int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,
|
||||
uint8_t *data, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate new information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size side information size
|
||||
*
|
||||
* @return pointer to fresh allocated data or NULL otherwise
|
||||
* @deprecated use av_packet_side_data_new() with the stream's
|
||||
* @ref AVCodecParameters.coded_side_data "codecpar side data"
|
||||
*/
|
||||
attribute_deprecated
|
||||
uint8_t *av_stream_new_side_data(AVStream *stream,
|
||||
enum AVPacketSideDataType type, size_t size);
|
||||
/**
|
||||
* Get side information from stream.
|
||||
*
|
||||
* @param stream stream
|
||||
* @param type desired side information type
|
||||
* @param size If supplied, *size will be set to the size of the side data
|
||||
* or to zero if the desired side data is not present.
|
||||
*
|
||||
* @return pointer to data if present or NULL otherwise
|
||||
* @deprecated use av_packet_side_data_get() with the stream's
|
||||
* @ref AVCodecParameters.coded_side_data "codecpar side data"
|
||||
*/
|
||||
attribute_deprecated
|
||||
uint8_t *av_stream_get_side_data(const AVStream *stream,
|
||||
enum AVPacketSideDataType type, size_t *size);
|
||||
#endif
|
||||
|
||||
AVProgram *av_new_program(AVFormatContext *s, int id);
|
||||
|
||||
/**
|
||||
@@ -2231,7 +2171,7 @@ int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
|
||||
* which case an AVFormatContext is allocated by this
|
||||
* function and written into ps.
|
||||
* Note that a user-supplied AVFormatContext will be freed
|
||||
* on failure.
|
||||
* on failure and its pointer set to NULL.
|
||||
* @param url URL of the stream to open.
|
||||
* @param fmt If non-NULL, this parameter forces a specific input format.
|
||||
* Otherwise the format is autodetected.
|
||||
@@ -2240,7 +2180,8 @@ int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
|
||||
* On return this parameter will be destroyed and replaced with
|
||||
* a dict containing options that were not found. May be NULL.
|
||||
*
|
||||
* @return 0 on success, a negative AVERROR on failure.
|
||||
* @return 0 on success; on failure: frees ps, sets its pointer to NULL,
|
||||
* and returns a negative AVERROR.
|
||||
*
|
||||
* @note If you want to use custom IO, preallocate the format context and set its pb field.
|
||||
*/
|
||||
@@ -3030,6 +2971,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
|
||||
|
||||
int avformat_queue_attached_pictures(AVFormatContext *s);
|
||||
|
||||
#if FF_API_INTERNAL_TIMING
|
||||
enum AVTimebaseSource {
|
||||
AVFMT_TBCF_AUTO = -1,
|
||||
AVFMT_TBCF_DECODER,
|
||||
@@ -3040,25 +2982,20 @@ enum AVTimebaseSource {
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer internal timing information from one stream to another.
|
||||
*
|
||||
* This function is useful when doing stream copy.
|
||||
*
|
||||
* @param ofmt target output format for ost
|
||||
* @param ost output stream which needs timings copy and adjustments
|
||||
* @param ist reference input stream to copy timings from
|
||||
* @param copy_tb define from where the stream codec timebase needs to be imported
|
||||
* @deprecated do not call this function
|
||||
*/
|
||||
attribute_deprecated
|
||||
int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
|
||||
AVStream *ost, const AVStream *ist,
|
||||
enum AVTimebaseSource copy_tb);
|
||||
|
||||
/**
|
||||
* Get the internal codec timebase from a stream.
|
||||
*
|
||||
* @param st input stream to extract the timebase from
|
||||
* @deprecated do not call this function
|
||||
*/
|
||||
attribute_deprecated
|
||||
AVRational av_stream_get_codec_timebase(const AVStream *st);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#include "version_major.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MINOR 1
|
||||
#define LIBAVFORMAT_VERSION_MINOR 3
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
|
||||
// Also please add any ticket numbers that you believe might be affected here
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 61
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 62
|
||||
|
||||
/**
|
||||
* FF_API_* defines may be placed below to indicate public API that will be
|
||||
@@ -41,12 +41,11 @@
|
||||
* at once through the bump. This improves the git bisect-ability of the change.
|
||||
*
|
||||
*/
|
||||
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 62)
|
||||
#define FF_API_LAVF_SHORTEST (LIBAVFORMAT_VERSION_MAJOR < 62)
|
||||
#define FF_API_ALLOW_FLUSH (LIBAVFORMAT_VERSION_MAJOR < 62)
|
||||
#define FF_API_AVSTREAM_SIDE_DATA (LIBAVFORMAT_VERSION_MAJOR < 62)
|
||||
#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 63)
|
||||
|
||||
#define FF_API_GET_DUR_ESTIMATE_METHOD (LIBAVFORMAT_VERSION_MAJOR < 62)
|
||||
#define FF_API_INTERNAL_TIMING (LIBAVFORMAT_VERSION_MAJOR < 63)
|
||||
|
||||
#define FF_API_NO_DEFAULT_TLS_VERIFY (LIBAVFORMAT_VERSION_MAJOR < 63)
|
||||
|
||||
#define FF_API_R_FRAME_RATE 1
|
||||
|
||||
|
||||
@@ -159,9 +159,11 @@
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define av_builtin_constant_p __builtin_constant_p
|
||||
# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos)))
|
||||
# define av_scanf_format(fmtpos, attrpos) __attribute__((__format__(__scanf__, fmtpos, attrpos)))
|
||||
#else
|
||||
# define av_builtin_constant_p(x) 0
|
||||
# define av_printf_format(fmtpos, attrpos)
|
||||
# define av_scanf_format(fmtpos, attrpos)
|
||||
#endif
|
||||
|
||||
#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__)
|
||||
|
||||
45
3rdparty/ffmpeg/include/libavutil/avassert.h
vendored
45
3rdparty/ffmpeg/include/libavutil/avassert.h
vendored
@@ -31,6 +31,7 @@
|
||||
#ifdef HAVE_AV_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "attributes.h"
|
||||
#include "log.h"
|
||||
#include "macros.h"
|
||||
|
||||
@@ -75,4 +76,48 @@
|
||||
*/
|
||||
void av_assert0_fpu(void);
|
||||
|
||||
/**
|
||||
* Asserts that are used as compiler optimization hints depending
|
||||
* upon ASSERT_LEVEL and NBDEBUG.
|
||||
*
|
||||
* Undefined behaviour occurs if execution reaches a point marked
|
||||
* with av_unreachable() or if a condition used with av_assume()
|
||||
* is false.
|
||||
*
|
||||
* The condition used with av_assume() should not have side-effects
|
||||
* and should be visible to the compiler.
|
||||
*/
|
||||
#if defined(ASSERT_LEVEL) ? ASSERT_LEVEL > 0 : !defined(HAVE_AV_CONFIG_H) && !defined(NDEBUG)
|
||||
#define av_unreachable(msg) \
|
||||
do { \
|
||||
av_log(NULL, AV_LOG_PANIC, \
|
||||
"Reached supposedly unreachable code at %s:%d: %s\n", \
|
||||
__FILE__, __LINE__, msg); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#define av_assume(cond) av_assert0(cond)
|
||||
#else
|
||||
#if AV_GCC_VERSION_AT_LEAST(4, 5) || AV_HAS_BUILTIN(__builtin_unreachable)
|
||||
#define av_unreachable(msg) __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#define av_unreachable(msg) __assume(0)
|
||||
#elif __STDC_VERSION__ >= 202311L
|
||||
#include <stddef.h>
|
||||
#define av_unreachable(msg) unreachable()
|
||||
#else
|
||||
#define av_unreachable(msg) ((void)0)
|
||||
#endif
|
||||
|
||||
#if AV_HAS_BUILTIN(__builtin_assume)
|
||||
#define av_assume(cond) __builtin_assume(cond)
|
||||
#elif defined(_MSC_VER)
|
||||
#define av_assume(cond) __assume(cond)
|
||||
#else
|
||||
#define av_assume(cond) do { \
|
||||
if (!(cond)) \
|
||||
av_unreachable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* AVUTIL_AVASSERT_H */
|
||||
|
||||
2
3rdparty/ffmpeg/include/libavutil/avstring.h
vendored
2
3rdparty/ffmpeg/include/libavutil/avstring.h
vendored
@@ -419,7 +419,7 @@ int av_match_list(const char *name, const char *list, char separator);
|
||||
* See libc sscanf manual for more information.
|
||||
* Locale-independent sscanf implementation.
|
||||
*/
|
||||
int av_sscanf(const char *string, const char *format, ...);
|
||||
int av_sscanf(const char *string, const char *format, ...) av_scanf_format(2, 3);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user